PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/configs/platform-raspberrypi/patches/linux-3.11.6/0034-Add-cpufreq-driver.patch

https://gitlab.com/MagneFire/ptxdist-raspberry-pi
Patch | 321 lines | 316 code | 5 blank | 0 comment | 0 complexity | fc561a5d4f54a72981afb6a596eee0cb MD5 | raw file
  1. From 3ffea09d730cf832199afc1ac4979bd8ca9ad20c Mon Sep 17 00:00:00 2001
  2. From: popcornmix <popcornmix@gmail.com>
  3. Date: Wed, 3 Jul 2013 00:49:20 +0100
  4. Subject: [PATCH 034/106] Add cpufreq driver
  5. ---
  6. arch/arm/Kconfig | 1 +
  7. arch/arm/configs/bcmrpi_defconfig | 6 +
  8. drivers/cpufreq/Kconfig.arm | 8 ++
  9. drivers/cpufreq/Makefile | 1 +
  10. drivers/cpufreq/bcm2835-cpufreq.c | 238 ++++++++++++++++++++++++++++++++++++++
  11. 5 files changed, 254 insertions(+)
  12. create mode 100755 drivers/cpufreq/bcm2835-cpufreq.c
  13. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
  14. index b06d944..fe64557 100644
  15. --- a/arch/arm/Kconfig
  16. +++ b/arch/arm/Kconfig
  17. @@ -374,6 +374,7 @@ config ARCH_BCM2708
  18. select HAVE_SCHED_CLOCK
  19. select NEED_MACH_MEMORY_H
  20. select CLKDEV_LOOKUP
  21. + select ARCH_HAS_CPUFREQ
  22. select GENERIC_CLOCKEVENTS
  23. select ARM_ERRATA_411920
  24. select MACH_BCM2708
  25. diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig
  26. index ef43466..5b0a171 100644
  27. --- a/arch/arm/configs/bcmrpi_defconfig
  28. +++ b/arch/arm/configs/bcmrpi_defconfig
  29. @@ -39,6 +39,12 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
  30. CONFIG_ZBOOT_ROM_BSS=0x0
  31. CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
  32. CONFIG_KEXEC=y
  33. +CONFIG_CPU_FREQ=y
  34. +CONFIG_CPU_FREQ_STAT=m
  35. +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
  36. +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
  37. +CONFIG_CPU_FREQ_GOV_USERSPACE=y
  38. +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
  39. CONFIG_CPU_IDLE=y
  40. CONFIG_VFP=y
  41. CONFIG_BINFMT_MISC=m
  42. diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
  43. index de4d5d9..86b9a0a 100644
  44. --- a/drivers/cpufreq/Kconfig.arm
  45. +++ b/drivers/cpufreq/Kconfig.arm
  46. @@ -216,6 +216,14 @@ config ARM_SPEAR_CPUFREQ
  47. help
  48. This adds the CPUFreq driver support for SPEAr SOCs.
  49. +config ARM_BCM2835_CPUFREQ
  50. + bool "BCM2835 Driver"
  51. + default y
  52. + help
  53. + This adds the CPUFreq driver for BCM2835
  54. +
  55. + If in doubt, say N.
  56. +
  57. config ARM_TEGRA_CPUFREQ
  58. bool "TEGRA CPUFreq support"
  59. depends on ARCH_TEGRA
  60. diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
  61. index d345b5a..06dd265 100644
  62. --- a/drivers/cpufreq/Makefile
  63. +++ b/drivers/cpufreq/Makefile
  64. @@ -76,6 +76,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
  65. obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
  66. obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
  67. obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
  68. +obj-$(CONFIG_ARM_BCM2835_CPUFREQ) += bcm2835-cpufreq.o
  69. obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o
  70. ##################################################################################
  71. diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c
  72. new file mode 100755
  73. index 0000000..f9b976c
  74. --- /dev/null
  75. +++ b/drivers/cpufreq/bcm2835-cpufreq.c
  76. @@ -0,0 +1,238 @@
  77. +/*****************************************************************************
  78. +* Copyright 2011 Broadcom Corporation. All rights reserved.
  79. +*
  80. +* Unless you and Broadcom execute a separate written software license
  81. +* agreement governing use of this software, this software is licensed to you
  82. +* under the terms of the GNU General Public License version 2, available at
  83. +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
  84. +*
  85. +* Notwithstanding the above, under no circumstances may you combine this
  86. +* software in any way with any other Broadcom software provided under a
  87. +* license other than the GPL, without Broadcom's express prior written
  88. +* consent.
  89. +*****************************************************************************/
  90. +
  91. +/*****************************************************************************
  92. +* FILENAME: bcm2835-cpufreq.h
  93. +* DESCRIPTION: This driver dynamically manages the CPU Frequency of the ARM
  94. +* processor. Messages are sent to Videocore either setting or requesting the
  95. +* frequency of the ARM in order to match an appropiate frequency to the current
  96. +* usage of the processor. The policy which selects the frequency to use is
  97. +* defined in the kernel .config file, but can be changed during runtime.
  98. +*****************************************************************************/
  99. +
  100. +/* ---------- INCLUDES ---------- */
  101. +#include <linux/kernel.h>
  102. +#include <linux/init.h>
  103. +#include <linux/module.h>
  104. +#include <linux/cpufreq.h>
  105. +#include <mach/vcio.h>
  106. +
  107. +/* ---------- DEFINES ---------- */
  108. +/*#define CPUFREQ_DEBUG_ENABLE*/ /* enable debugging */
  109. +#define MODULE_NAME "bcm2835-cpufreq"
  110. +
  111. +#define VCMSG_ID_ARM_CLOCK 0x000000003 /* Clock/Voltage ID's */
  112. +
  113. +/* debug printk macros */
  114. +#ifdef CPUFREQ_DEBUG_ENABLE
  115. +#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
  116. +#else
  117. +#define print_debug(fmt,...)
  118. +#endif
  119. +#define print_err(fmt,...) pr_err("%s:%s:%d: "fmt, MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)
  120. +#define print_info(fmt,...) pr_info("%s: "fmt, MODULE_NAME, ##__VA_ARGS__)
  121. +
  122. +/* tag part of the message */
  123. +struct vc_msg_tag {
  124. + uint32_t tag_id; /* the message id */
  125. + uint32_t buffer_size; /* size of the buffer (which in this case is always 8 bytes) */
  126. + uint32_t data_size; /* amount of data being sent or received */
  127. + uint32_t dev_id; /* the ID of the clock/voltage to get or set */
  128. + uint32_t val; /* the value (e.g. rate (in Hz)) to set */
  129. +};
  130. +
  131. +/* message structure to be sent to videocore */
  132. +struct vc_msg {
  133. + uint32_t msg_size; /* simply, sizeof(struct vc_msg) */
  134. + uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */
  135. + struct vc_msg_tag tag; /* the tag structure above to make */
  136. + uint32_t end_tag; /* an end identifier, should be set to NULL */
  137. +};
  138. +
  139. +/* ---------- GLOBALS ---------- */
  140. +static struct cpufreq_driver bcm2835_cpufreq_driver; /* the cpufreq driver global */
  141. +
  142. +/*
  143. + ===============================================
  144. + clk_rate either gets or sets the clock rates.
  145. + ===============================================
  146. +*/
  147. +static uint32_t bcm2835_cpufreq_set_clock(int cur_rate, int arm_rate)
  148. +{
  149. + int s, actual_rate=0;
  150. + struct vc_msg msg;
  151. +
  152. + /* wipe all previous message data */
  153. + memset(&msg, 0, sizeof msg);
  154. +
  155. + msg.msg_size = sizeof msg;
  156. +
  157. + msg.tag.tag_id = VCMSG_SET_CLOCK_RATE;
  158. + msg.tag.buffer_size = 8;
  159. + msg.tag.data_size = 8; /* we're sending the clock ID and the new rates which is a total of 2 words */
  160. + msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;
  161. + msg.tag.val = arm_rate * 1000;
  162. +
  163. + /* send the message */
  164. + s = bcm_mailbox_property(&msg, sizeof msg);
  165. +
  166. + /* check if it was all ok and return the rate in KHz */
  167. + if (s == 0 && (msg.request_code & 0x80000000))
  168. + actual_rate = msg.tag.val/1000;
  169. +
  170. + print_debug("Setting new frequency = %d -> %d (actual %d)", cur_rate, arm_rate, actual_rate);
  171. + return actual_rate;
  172. +}
  173. +
  174. +static uint32_t bcm2835_cpufreq_get_clock(int tag)
  175. +{
  176. + int s;
  177. + int arm_rate = 0;
  178. + struct vc_msg msg;
  179. +
  180. + /* wipe all previous message data */
  181. + memset(&msg, 0, sizeof msg);
  182. +
  183. + msg.msg_size = sizeof msg;
  184. + msg.tag.tag_id = tag;
  185. + msg.tag.buffer_size = 8;
  186. + msg.tag.data_size = 4; /* we're just sending the clock ID which is one word long */
  187. + msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;
  188. +
  189. + /* send the message */
  190. + s = bcm_mailbox_property(&msg, sizeof msg);
  191. +
  192. + /* check if it was all ok and return the rate in KHz */
  193. + if (s == 0 && (msg.request_code & 0x80000000))
  194. + arm_rate = msg.tag.val/1000;
  195. +
  196. + print_debug("%s frequency = %d",
  197. + tag == VCMSG_GET_CLOCK_RATE ? "Current":
  198. + tag == VCMSG_GET_MIN_CLOCK ? "Min":
  199. + tag == VCMSG_GET_MAX_CLOCK ? "Max":
  200. + "Unexpected", arm_rate);
  201. +
  202. + return arm_rate;
  203. +}
  204. +
  205. +/*
  206. + ====================================================
  207. + Module Initialisation registers the cpufreq driver
  208. + ====================================================
  209. +*/
  210. +static int __init bcm2835_cpufreq_module_init(void)
  211. +{
  212. + print_debug("IN");
  213. + return cpufreq_register_driver(&bcm2835_cpufreq_driver);
  214. +}
  215. +
  216. +/*
  217. + =============
  218. + Module exit
  219. + =============
  220. +*/
  221. +static void __exit bcm2835_cpufreq_module_exit(void)
  222. +{
  223. + print_debug("IN");
  224. + cpufreq_unregister_driver(&bcm2835_cpufreq_driver);
  225. + return;
  226. +}
  227. +
  228. +/*
  229. + ==============================================================
  230. + Initialisation function sets up the CPU policy for first use
  231. + ==============================================================
  232. +*/
  233. +static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy)
  234. +{
  235. + /* measured value of how long it takes to change frequency */
  236. + policy->cpuinfo.transition_latency = 355000; /* ns */
  237. +
  238. + /* now find out what the maximum and minimum frequencies are */
  239. + policy->min = policy->cpuinfo.min_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MIN_CLOCK);
  240. + policy->max = policy->cpuinfo.max_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MAX_CLOCK);
  241. + policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);
  242. +
  243. + print_info("min=%d max=%d cur=%d", policy->min, policy->max, policy->cur);
  244. + return 0;
  245. +}
  246. +
  247. +/*
  248. + =================================================================================
  249. + Target function chooses the most appropriate frequency from the table to enable
  250. + =================================================================================
  251. +*/
  252. +
  253. +static int bcm2835_cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation)
  254. +{
  255. + unsigned int target = target_freq;
  256. + unsigned int cur = policy->cur;
  257. + print_debug("%s: min=%d max=%d cur=%d target=%d",policy->governor->name,policy->min,policy->max,policy->cur,target_freq);
  258. +
  259. + /* if we are above min and using ondemand, then just use max */
  260. + if (strcmp("ondemand", policy->governor->name)==0 && target > policy->min)
  261. + target = policy->max;
  262. + /* if the frequency is the same, just quit */
  263. + if (target == policy->cur)
  264. + return 0;
  265. +
  266. + /* otherwise were good to set the clock frequency */
  267. + policy->cur = bcm2835_cpufreq_set_clock(policy->cur, target);
  268. +
  269. + if (!policy->cur)
  270. + {
  271. + print_err("Error occurred setting a new frequency (%d)!", target);
  272. + policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);
  273. + return -EINVAL;
  274. + }
  275. + print_debug("Freq %d->%d (min=%d max=%d target=%d request=%d)", cur, policy->cur, policy->min, policy->max, target_freq, target);
  276. + return 0;
  277. +}
  278. +
  279. +static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu)
  280. +{
  281. + unsigned int actual_rate = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);
  282. + print_debug("%d", actual_rate);
  283. + return actual_rate;
  284. +}
  285. +
  286. +/*
  287. + =================================================================================
  288. + Verify ensures that when a policy is changed, it is suitable for the CPU to use
  289. + =================================================================================
  290. +*/
  291. +
  292. +static int bcm2835_cpufreq_driver_verify(struct cpufreq_policy *policy)
  293. +{
  294. + print_info("switching to governor %s", policy->governor->name);
  295. + return 0;
  296. +}
  297. +
  298. +
  299. +/* the CPUFreq driver */
  300. +static struct cpufreq_driver bcm2835_cpufreq_driver = {
  301. + .name = "BCM2835 CPUFreq",
  302. + .owner = THIS_MODULE,
  303. + .init = bcm2835_cpufreq_driver_init,
  304. + .verify = bcm2835_cpufreq_driver_verify,
  305. + .target = bcm2835_cpufreq_driver_target,
  306. + .get = bcm2835_cpufreq_driver_get
  307. +};
  308. +
  309. +MODULE_AUTHOR("Dorian Peake and Dom Cobley");
  310. +MODULE_DESCRIPTION("CPU frequency driver for BCM2835 chip");
  311. +MODULE_LICENSE("GPL");
  312. +
  313. +module_init(bcm2835_cpufreq_module_init);
  314. +module_exit(bcm2835_cpufreq_module_exit);
  315. --
  316. 1.8.4.2