kernel: update 3.10 to 3.10.2
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 011-bcm2835-cpufreq-driver.patch
1 --- /dev/null
2 +++ b/drivers/cpufreq/bcm2835-cpufreq.c
3 @@ -0,0 +1,239 @@
4 +/*****************************************************************************\r
5 +* Copyright 2011 Broadcom Corporation.  All rights reserved.\r
6 +*\r
7 +* Unless you and Broadcom execute a separate written software license\r
8 +* agreement governing use of this software, this software is licensed to you\r
9 +* under the terms of the GNU General Public License version 2, available at\r
10 +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").\r
11 +*      \r
12 +* Notwithstanding the above, under no circumstances may you combine this\r
13 +* software in any way with any other Broadcom software provided under a\r
14 +* license other than the GPL, without Broadcom's express prior written\r
15 +* consent.\r
16 +*****************************************************************************/\r
17 +\r
18 +/*****************************************************************************\r
19 +* FILENAME: bcm2835-cpufreq.h\r
20 +* DESCRIPTION: This driver dynamically manages the CPU Frequency of the ARM\r
21 +* processor. Messages are sent to Videocore either setting or requesting the\r
22 +* frequency of the ARM in order to match an appropiate frequency to the current\r
23 +* usage of the processor. The policy which selects the frequency to use is\r
24 +* defined in the kernel .config file, but can be changed during runtime.\r
25 +*****************************************************************************/\r
26 +\r
27 +/* ---------- INCLUDES ---------- */\r
28 +#include <linux/kernel.h>\r
29 +#include <linux/init.h>\r
30 +#include <linux/module.h>\r
31 +#include <linux/cpufreq.h>\r
32 +#include <mach/vcio.h>\r
33 +\r
34 +/* ---------- DEFINES ---------- */\r
35 +/*#define CPUFREQ_DEBUG_ENABLE*/               /* enable debugging */\r
36 +#define MODULE_NAME "bcm2835-cpufreq"\r
37 +\r
38 +#define VCMSG_ID_ARM_CLOCK 0x000000003         /* Clock/Voltage ID's */\r
39 +\r
40 +/* debug printk macros */\r
41 +#ifdef CPUFREQ_DEBUG_ENABLE\r
42 +#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)\r
43 +#else\r
44 +#define print_debug(fmt,...)\r
45 +#endif\r
46 +#define print_err(fmt,...) pr_err("%s:%s:%d: "fmt, MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)\r
47 +#define print_info(fmt,...) pr_info("%s: "fmt, MODULE_NAME, ##__VA_ARGS__)\r
48 +\r
49 +/* tag part of the message */\r
50 +struct vc_msg_tag {\r
51 +       uint32_t tag_id;                /* the message id */\r
52 +       uint32_t buffer_size;           /* size of the buffer (which in this case is always 8 bytes) */\r
53 +       uint32_t data_size;             /* amount of data being sent or received */\r
54 +       uint32_t dev_id;                /* the ID of the clock/voltage to get or set */\r
55 +       uint32_t val;                   /* the value (e.g. rate (in Hz)) to set */\r
56 +};\r
57 +\r
58 +/* message structure to be sent to videocore */\r
59 +struct vc_msg {\r
60 +       uint32_t msg_size;              /* simply, sizeof(struct vc_msg) */\r
61 +       uint32_t request_code;          /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */\r
62 +       struct vc_msg_tag tag;          /* the tag structure above to make */\r
63 +       uint32_t end_tag;               /* an end identifier, should be set to NULL */\r
64 +};\r
65 +\r
66 +/* ---------- GLOBALS ---------- */\r
67 +static struct cpufreq_driver bcm2835_cpufreq_driver;   /* the cpufreq driver global */\r
68 +\r
69 +/*\r
70 + ===============================================\r
71 +  clk_rate either gets or sets the clock rates.\r
72 + ===============================================\r
73 +*/\r
74 +static uint32_t bcm2835_cpufreq_set_clock(int cur_rate, int arm_rate)\r
75 +{\r
76 +       int s, actual_rate=0;\r
77 +       struct vc_msg msg;\r
78 +       \r
79 +       /* wipe all previous message data */\r
80 +       memset(&msg, 0, sizeof msg);\r
81 +       \r
82 +       msg.msg_size = sizeof msg;\r
83 +                       \r
84 +       msg.tag.tag_id = VCMSG_SET_CLOCK_RATE;\r
85 +       msg.tag.buffer_size = 8;\r
86 +       msg.tag.data_size = 8;   /* we're sending the clock ID and the new rates which is a total of 2 words */\r
87 +       msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;\r
88 +       msg.tag.val = arm_rate * 1000;\r
89 +                       \r
90 +       /* send the message */\r
91 +       s = bcm_mailbox_property(&msg, sizeof msg);\r
92 +       \r
93 +       /* check if it was all ok and return the rate in KHz */\r
94 +       if (s == 0 && (msg.request_code & 0x80000000))\r
95 +               actual_rate = msg.tag.val/1000;\r
96 +\r
97 +       print_debug("Setting new frequency = %d -> %d (actual %d)\n", cur_rate, arm_rate, actual_rate); \r
98 +       return actual_rate;\r
99 +}\r
100 +\r
101 +static uint32_t bcm2835_cpufreq_get_clock(int tag)\r
102 +{\r
103 +       int s;\r
104 +       int arm_rate = 0;\r
105 +       struct vc_msg msg;\r
106 +       \r
107 +       /* wipe all previous message data */\r
108 +       memset(&msg, 0, sizeof msg);\r
109 +       \r
110 +       msg.msg_size = sizeof msg;\r
111 +       msg.tag.tag_id = tag;\r
112 +       msg.tag.buffer_size = 8;\r
113 +       msg.tag.data_size = 4; /* we're just sending the clock ID which is one word long */\r
114 +       msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;\r
115 +       \r
116 +       /* send the message */\r
117 +       s = bcm_mailbox_property(&msg, sizeof msg);\r
118 +\r
119 +       /* check if it was all ok and return the rate in KHz */\r
120 +       if (s == 0 && (msg.request_code & 0x80000000))\r
121 +               arm_rate = msg.tag.val/1000;\r
122 +\r
123 +       print_debug("%s frequency = %d\n",\r
124 +               tag == VCMSG_GET_CLOCK_RATE ? "Current":\r
125 +               tag == VCMSG_GET_MIN_CLOCK ? "Min":\r
126 +               tag == VCMSG_GET_MAX_CLOCK ? "Max":\r
127 +               "Unexpected", arm_rate);\r
128 +       \r
129 +       return arm_rate;\r
130 +}\r
131 +\r
132 +/*\r
133 + ====================================================\r
134 +  Module Initialisation registers the cpufreq driver\r
135 + ====================================================\r
136 +*/\r
137 +static int __init bcm2835_cpufreq_module_init(void)\r
138 +{      \r
139 +       print_debug("IN\n");\r
140 +       return cpufreq_register_driver(&bcm2835_cpufreq_driver);\r
141 +}\r
142 +\r
143 +/*\r
144 + =============\r
145 +  Module exit\r
146 + =============\r
147 +*/\r
148 +static void __exit bcm2835_cpufreq_module_exit(void)\r
149 +{\r
150 +       print_debug("IN\n");\r
151 +       cpufreq_unregister_driver(&bcm2835_cpufreq_driver);\r
152 +       return;\r
153 +}\r
154 +\r
155 +/*\r
156 + ==============================================================\r
157 +  Initialisation function sets up the CPU policy for first use\r
158 + ==============================================================\r
159 +*/\r
160 +static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy)\r
161 +{\r
162 +       /* measured value of how long it takes to change frequency */   \r
163 +       policy->cpuinfo.transition_latency = 355000; /* ns */\r
164 +\r
165 +       /* now find out what the maximum and minimum frequencies are */\r
166 +       policy->min = policy->cpuinfo.min_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MIN_CLOCK);\r
167 +       policy->max = policy->cpuinfo.max_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MAX_CLOCK);\r
168 +       policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);\r
169 +       \r
170 +       print_info("min=%d max=%d cur=%d\n", policy->min, policy->max, policy->cur);\r
171 +       return 0;\r
172 +}\r
173 +\r
174 +/*\r
175 + =================================================================================\r
176 +  Target function chooses the most appropriate frequency from the table to enable\r
177 + =================================================================================\r
178 +*/\r
179 +\r
180 +static int bcm2835_cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation)\r
181 +{\r
182 +       unsigned int target = target_freq;\r
183 +       unsigned int cur = policy->cur;\r
184 +       print_debug("%s: min=%d max=%d cur=%d target=%d\n",policy->governor->name,policy->min,policy->max,policy->cur,target_freq);\r
185 +       \r
186 +       /* if we are above min and using ondemand, then just use max */\r
187 +       if (strcmp("ondemand", policy->governor->name)==0 && target > policy->min)\r
188 +               target = policy->max;\r
189 +       /* if the frequency is the same, just quit */\r
190 +       if (target == policy->cur)\r
191 +               return 0;\r
192 +\r
193 +       /* otherwise were good to set the clock frequency */\r
194 +       policy->cur = bcm2835_cpufreq_set_clock(policy->cur, target);\r
195 +       \r
196 +       if (!policy->cur)\r
197 +       {\r
198 +               print_err("Error occurred setting a new frequency (%d)!\n", target);\r
199 +               policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);\r
200 +               return -EINVAL;\r
201 +       }\r
202 +       print_debug("Freq %d->%d (min=%d max=%d target=%d request=%d)\n", cur, policy->cur, policy->min, policy->max, target_freq, target);\r
203 +       return 0;\r
204 +}\r
205 +\r
206 +static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu)\r
207 +{\r
208 +       unsigned int actual_rate = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);\r
209 +       print_debug("cpu=%d\n", actual_rate);\r
210 +       return actual_rate;\r
211 +}\r
212 +\r
213 +/*\r
214 + =================================================================================\r
215 +  Verify ensures that when a policy is changed, it is suitable for the CPU to use\r
216 + =================================================================================\r
217 +*/\r
218 +\r
219 +static int bcm2835_cpufreq_driver_verify(struct cpufreq_policy *policy)\r
220 +{\r
221 +       print_info("switching to governor %s\n", policy->governor->name);\r
222 +       return 0;\r
223 +}\r
224 +\r
225 +\r
226 +/* the CPUFreq driver */\r
227 +static struct cpufreq_driver bcm2835_cpufreq_driver = {\r
228 +               .name   = "BCM2835 CPUFreq",\r
229 +               .owner  = THIS_MODULE,\r
230 +               .init   = bcm2835_cpufreq_driver_init,\r
231 +               .verify = bcm2835_cpufreq_driver_verify,\r
232 +               .target = bcm2835_cpufreq_driver_target,\r
233 +               .get    = bcm2835_cpufreq_driver_get\r
234 +};\r
235 +\r
236 +MODULE_AUTHOR("Dorian Peake and Dom Cobley");\r
237 +MODULE_DESCRIPTION("CPU frequency driver for BCM2835 chip");\r
238 +MODULE_LICENSE("GPL");\r
239 +\r
240 +module_init(bcm2835_cpufreq_module_init);\r
241 +module_exit(bcm2835_cpufreq_module_exit);\r
242 +\r
243 --- a/drivers/cpufreq/Kconfig.arm
244 +++ b/drivers/cpufreq/Kconfig.arm
245 @@ -150,3 +150,11 @@ config ARM_SPEAR_CPUFREQ
246         default y
247         help
248           This adds the CPUFreq driver support for SPEAr SOCs.
249 +
250 +config ARM_BCM2835_CPUFREQ
251 +       bool "BCM2835 Driver"
252 +       default y
253 +       help
254 +         This adds the CPUFreq driver for BCM2835
255 +
256 +         If in doubt, say N.
257 --- a/drivers/cpufreq/Makefile
258 +++ b/drivers/cpufreq/Makefile
259 @@ -72,6 +72,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ)      += sa11
260  obj-$(CONFIG_ARM_SA1110_CPUFREQ)       += sa1110-cpufreq.o
261  obj-$(CONFIG_ARM_SPEAR_CPUFREQ)                += spear-cpufreq.o
262  obj-$(CONFIG_ARCH_TEGRA)               += tegra-cpufreq.o
263 +obj-$(CONFIG_ARM_BCM2835_CPUFREQ)      += bcm2835-cpufreq.o
264  
265  ##################################################################################
266  # PowerPC platform drivers