69ac50a032d783500e222ef24111f1b0eacdfe8b
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-3.0 / pm-wip / cpufreq / 0007-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch
1 From 0dce78bb4a6d7d65a7c5c34a7d0dd085dccae72f Mon Sep 17 00:00:00 2001
2 From: Santosh Shilimkar <santosh.shilimkar@ti.com>
3 Date: Mon, 14 Mar 2011 17:08:48 +0530
4 Subject: [PATCH 07/19] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers.
6 This patch is an attempt to cleanup the #ifdeferry in the
7 omap CPUfreq drivers.
9 The split betwenn OMAP1 and OMAP2PLUS is logical because
10 - OMAP1 doesn't support opp layer.
11 - OMAP1 build is seperate from omap2plus.
13 Includes minor header/copyright updates reported by Todd Poynor.
15 Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
16 Cc: Kevin Hilman <khilman@ti.com>
17 Cc: Vishwanath BS <vishwanath.bs@ti.com>
18 Cc: Todd Poynor <toddpoynor@google.com>
19 Cc: Nishanth Menon <nm@ti.com>
20 Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
21 ---
22 arch/arm/mach-omap1/Makefile | 3 +
23 arch/arm/mach-omap1/omap1-cpufreq.c | 175 ++++++++++++++++++++++++++
24 arch/arm/mach-omap2/Makefile | 3 +
25 arch/arm/mach-omap2/omap2plus-cpufreq.c | 201 ++++++++++++++++++++++++++++++
26 arch/arm/plat-omap/Makefile | 1 -
27 arch/arm/plat-omap/cpu-omap.c | 204 -------------------------------
28 6 files changed, 382 insertions(+), 205 deletions(-)
29 create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c
30 create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c
31 delete mode 100644 arch/arm/plat-omap/cpu-omap.c
33 diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
34 index 5b114d1..9600410 100644
35 --- a/arch/arm/mach-omap1/Makefile
36 +++ b/arch/arm/mach-omap1/Makefile
37 @@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
39 obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
41 +# CPUFREQ driver
42 +obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o
43 +
44 # Power Management
45 obj-$(CONFIG_PM) += pm.o sleep.o
47 diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c
48 new file mode 100644
49 index 0000000..7c5216e
50 --- /dev/null
51 +++ b/arch/arm/mach-omap1/omap1-cpufreq.c
52 @@ -0,0 +1,175 @@
53 +/*
54 + * OMAP1 cpufreq driver
55 + *
56 + * CPU frequency scaling for OMAP
57 + *
58 + * Copyright (C) 2005 Nokia Corporation
59 + * Written by Tony Lindgren <tony@atomide.com>
60 + *
61 + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
62 + *
63 + * Copyright (C) 2007-2008 Texas Instruments, Inc.
64 + * Rajendra Nayak <rnayak@ti.com>
65 + *
66 + * This program is free software; you can redistribute it and/or modify
67 + * it under the terms of the GNU General Public License version 2 as
68 + * published by the Free Software Foundation.
69 + */
70 +#include <linux/types.h>
71 +#include <linux/kernel.h>
72 +#include <linux/sched.h>
73 +#include <linux/cpufreq.h>
74 +#include <linux/delay.h>
75 +#include <linux/init.h>
76 +#include <linux/err.h>
77 +#include <linux/clk.h>
78 +#include <linux/io.h>
79 +#include <linux/opp.h>
80 +
81 +#include <asm/system.h>
82 +
83 +#include <plat/clock.h>
84 +#include <plat/omap-pm.h>
85 +
86 +#include <mach/hardware.h>
87 +
88 +#define VERY_HI_RATE 900000000
89 +
90 +static struct cpufreq_frequency_table *freq_table;
91 +static struct clk *mpu_clk;
92 +
93 +static int omap_verify_speed(struct cpufreq_policy *policy)
94 +{
95 + if (freq_table)
96 + return cpufreq_frequency_table_verify(policy, freq_table);
97 +
98 + if (policy->cpu)
99 + return -EINVAL;
100 +
101 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
102 + policy->cpuinfo.max_freq);
103 +
104 + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
105 + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
106 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
107 + policy->cpuinfo.max_freq);
108 + return 0;
109 +}
110 +
111 +static unsigned int omap_getspeed(unsigned int cpu)
112 +{
113 + unsigned long rate;
114 +
115 + if (cpu)
116 + return 0;
117 +
118 + rate = clk_get_rate(mpu_clk) / 1000;
119 + return rate;
120 +}
121 +
122 +static int omap_target(struct cpufreq_policy *policy,
123 + unsigned int target_freq,
124 + unsigned int relation)
125 +{
126 + struct cpufreq_freqs freqs;
127 + int ret = 0;
128 +
129 + /* Ensure desired rate is within allowed range. Some govenors
130 + * (ondemand) will just pass target_freq=0 to get the minimum. */
131 + if (target_freq < policy->min)
132 + target_freq = policy->min;
133 + if (target_freq > policy->max)
134 + target_freq = policy->max;
135 +
136 + freqs.old = omap_getspeed(0);
137 + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
138 + freqs.cpu = 0;
139 +
140 + if (freqs.old == freqs.new)
141 + return ret;
142 +
143 + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
144 +
145 +#ifdef CONFIG_CPU_FREQ_DEBUG
146 + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
147 +#endif
148 + ret = clk_set_rate(mpu_clk, freqs.new * 1000);
149 +
150 + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
151 +
152 + return ret;
153 +}
154 +
155 +static int __init omap_cpu_init(struct cpufreq_policy *policy)
156 +{
157 + int result = 0;
158 +
159 + mpu_clk = clk_get(NULL, "mpu");
160 + if (IS_ERR(mpu_clk))
161 + return PTR_ERR(mpu_clk);
162 +
163 + if (policy->cpu != 0)
164 + return -EINVAL;
165 +
166 + policy->cur = policy->min = policy->max = omap_getspeed(0);
167 +
168 + clk_init_cpufreq_table(&freq_table);
169 +
170 + if (freq_table) {
171 + result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
172 + if (!result)
173 + cpufreq_frequency_table_get_attr(freq_table,
174 + policy->cpu);
175 + } else {
176 + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
177 + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
178 + VERY_HI_RATE) / 1000;
179 + }
180 +
181 + policy->min = policy->cpuinfo.min_freq;
182 + policy->max = policy->cpuinfo.max_freq;
183 + policy->cur = omap_getspeed(0);
184 +
185 + /* FIXME: what's the actual transition time? */
186 + policy->cpuinfo.transition_latency = 300 * 1000;
187 +
188 + return 0;
189 +}
190 +
191 +static int omap_cpu_exit(struct cpufreq_policy *policy)
192 +{
193 + clk_exit_cpufreq_table(&freq_table);
194 + clk_put(mpu_clk);
195 + return 0;
196 +}
197 +
198 +static struct freq_attr *omap_cpufreq_attr[] = {
199 + &cpufreq_freq_attr_scaling_available_freqs,
200 + NULL,
201 +};
202 +
203 +static struct cpufreq_driver omap_driver = {
204 + .flags = CPUFREQ_STICKY,
205 + .verify = omap_verify_speed,
206 + .target = omap_target,
207 + .get = omap_getspeed,
208 + .init = omap_cpu_init,
209 + .exit = omap_cpu_exit,
210 + .name = "omap1",
211 + .attr = omap_cpufreq_attr,
212 +};
213 +
214 +static int __init omap_cpufreq_init(void)
215 +{
216 + return cpufreq_register_driver(&omap_driver);
217 +}
218 +
219 +static void __exit omap_cpufreq_exit(void)
220 +{
221 + cpufreq_unregister_driver(&omap_driver);
222 +}
223 +
224 +MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs");
225 +MODULE_LICENSE("GPL");
226 +module_init(omap_cpufreq_init);
227 +module_exit(omap_cpufreq_exit);
228 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
229 index 8e79ca5..7927dd6 100644
230 --- a/arch/arm/mach-omap2/Makefile
231 +++ b/arch/arm/mach-omap2/Makefile
232 @@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o
233 obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o
234 endif
236 +# CPUFREQ driver
237 +obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o
238 +
239 # Power Management
240 ifeq ($(CONFIG_PM),y)
241 obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
242 diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
243 new file mode 100644
244 index 0000000..27f641b
245 --- /dev/null
246 +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
247 @@ -0,0 +1,201 @@
248 +/*
249 + * OMAP2PLUS cpufreq driver
250 + *
251 + * CPU frequency scaling for OMAP
252 + *
253 + * Copyright (C) 2005 Nokia Corporation
254 + * Written by Tony Lindgren <tony@atomide.com>
255 + *
256 + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
257 + *
258 + * Copyright (C) 2007-2011 Texas Instruments, Inc.
259 + * Updated to support OMAP3
260 + * Rajendra Nayak <rnayak@ti.com>
261 + *
262 + * This program is free software; you can redistribute it and/or modify
263 + * it under the terms of the GNU General Public License version 2 as
264 + * published by the Free Software Foundation.
265 + */
266 +#include <linux/types.h>
267 +#include <linux/kernel.h>
268 +#include <linux/sched.h>
269 +#include <linux/cpufreq.h>
270 +#include <linux/delay.h>
271 +#include <linux/init.h>
272 +#include <linux/err.h>
273 +#include <linux/clk.h>
274 +#include <linux/io.h>
275 +#include <linux/opp.h>
276 +
277 +#include <asm/system.h>
278 +#include <asm/smp_plat.h>
279 +
280 +#include <plat/clock.h>
281 +#include <plat/omap-pm.h>
282 +#include <plat/common.h>
283 +
284 +#include <mach/hardware.h>
285 +
286 +#define VERY_HI_RATE 900000000
287 +
288 +static struct cpufreq_frequency_table *freq_table;
289 +static struct clk *mpu_clk;
290 +
291 +static int omap_verify_speed(struct cpufreq_policy *policy)
292 +{
293 + if (freq_table)
294 + return cpufreq_frequency_table_verify(policy, freq_table);
295 +
296 + if (policy->cpu)
297 + return -EINVAL;
298 +
299 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
300 + policy->cpuinfo.max_freq);
301 +
302 + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
303 + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
304 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
305 + policy->cpuinfo.max_freq);
306 + return 0;
307 +}
308 +
309 +static unsigned int omap_getspeed(unsigned int cpu)
310 +{
311 + unsigned long rate;
312 +
313 + if (cpu)
314 + return 0;
315 +
316 + rate = clk_get_rate(mpu_clk) / 1000;
317 + return rate;
318 +}
319 +
320 +static int omap_target(struct cpufreq_policy *policy,
321 + unsigned int target_freq,
322 + unsigned int relation)
323 +{
324 + int ret = 0;
325 + struct cpufreq_freqs freqs;
326 +
327 + /* Ensure desired rate is within allowed range. Some govenors
328 + * (ondemand) will just pass target_freq=0 to get the minimum. */
329 + if (target_freq < policy->min)
330 + target_freq = policy->min;
331 + if (target_freq > policy->max)
332 + target_freq = policy->max;
333 +
334 + freqs.old = omap_getspeed(0);
335 + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
336 + freqs.cpu = 0;
337 +
338 + if (freqs.old == freqs.new)
339 + return ret;
340 +
341 + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
342 +
343 +#ifdef CONFIG_CPU_FREQ_DEBUG
344 + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
345 +#endif
346 +
347 + ret = clk_set_rate(mpu_clk, freqs.new * 1000);
348 +
349 + /*
350 + * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies
351 + * won't get updated when UP machine cpufreq build with
352 + * CONFIG_SMP enabled. Below code is added only to manage that
353 + * scenario
354 + */
355 + if (!is_smp())
356 + loops_per_jiffy =
357 + cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
358 +
359 + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
360 +
361 + return ret;
362 +}
363 +
364 +static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
365 +{
366 + int result = 0;
367 + struct device *mpu_dev;
368 +
369 + if (cpu_is_omap24xx())
370 + mpu_clk = clk_get(NULL, "virt_prcm_set");
371 + else if (cpu_is_omap34xx())
372 + mpu_clk = clk_get(NULL, "dpll1_ck");
373 + else if (cpu_is_omap34xx())
374 + mpu_clk = clk_get(NULL, "dpll_mpu_ck");
375 +
376 + if (IS_ERR(mpu_clk))
377 + return PTR_ERR(mpu_clk);
378 +
379 + if (policy->cpu != 0)
380 + return -EINVAL;
381 +
382 + policy->cur = policy->min = policy->max = omap_getspeed(0);
383 +
384 + mpu_dev = omap2_get_mpuss_device();
385 + if (!mpu_dev) {
386 + pr_warning("%s: unable to get the mpu device\n", __func__);
387 + return -EINVAL;
388 + }
389 + opp_init_cpufreq_table(mpu_dev, &freq_table);
390 +
391 + if (freq_table) {
392 + result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
393 + if (!result)
394 + cpufreq_frequency_table_get_attr(freq_table,
395 + policy->cpu);
396 + } else {
397 + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
398 + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
399 + VERY_HI_RATE) / 1000;
400 + }
401 +
402 + policy->min = policy->cpuinfo.min_freq;
403 + policy->max = policy->cpuinfo.max_freq;
404 + policy->cur = omap_getspeed(0);
405 +
406 + /* FIXME: what's the actual transition time? */
407 + policy->cpuinfo.transition_latency = 300 * 1000;
408 +
409 + return 0;
410 +}
411 +
412 +static int omap_cpu_exit(struct cpufreq_policy *policy)
413 +{
414 + clk_exit_cpufreq_table(&freq_table);
415 + clk_put(mpu_clk);
416 + return 0;
417 +}
418 +
419 +static struct freq_attr *omap_cpufreq_attr[] = {
420 + &cpufreq_freq_attr_scaling_available_freqs,
421 + NULL,
422 +};
423 +
424 +static struct cpufreq_driver omap_driver = {
425 + .flags = CPUFREQ_STICKY,
426 + .verify = omap_verify_speed,
427 + .target = omap_target,
428 + .get = omap_getspeed,
429 + .init = omap_cpu_init,
430 + .exit = omap_cpu_exit,
431 + .name = "omap2plus",
432 + .attr = omap_cpufreq_attr,
433 +};
434 +
435 +static int __init omap_cpufreq_init(void)
436 +{
437 + return cpufreq_register_driver(&omap_driver);
438 +}
439 +
440 +static void __exit omap_cpufreq_exit(void)
441 +{
442 + cpufreq_unregister_driver(&omap_driver);
443 +}
444 +
445 +MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs");
446 +MODULE_LICENSE("GPL");
447 +module_init(omap_cpufreq_init);
448 +module_exit(omap_cpufreq_exit);
449 diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
450 index f0233e6..4ef7493 100644
451 --- a/arch/arm/plat-omap/Makefile
452 +++ b/arch/arm/plat-omap/Makefile
453 @@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
454 obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
455 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
457 -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
458 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
459 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
460 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
461 diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
462 deleted file mode 100644
463 index 9cd2709..0000000
464 --- a/arch/arm/plat-omap/cpu-omap.c
465 +++ /dev/null
466 @@ -1,204 +0,0 @@
467 -/*
468 - * linux/arch/arm/plat-omap/cpu-omap.c
469 - *
470 - * CPU frequency scaling for OMAP
471 - *
472 - * Copyright (C) 2005 Nokia Corporation
473 - * Written by Tony Lindgren <tony@atomide.com>
474 - *
475 - * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
476 - *
477 - * Copyright (C) 2007-2008 Texas Instruments, Inc.
478 - * Updated to support OMAP3
479 - * Rajendra Nayak <rnayak@ti.com>
480 - *
481 - * This program is free software; you can redistribute it and/or modify
482 - * it under the terms of the GNU General Public License version 2 as
483 - * published by the Free Software Foundation.
484 - */
485 -#include <linux/types.h>
486 -#include <linux/kernel.h>
487 -#include <linux/sched.h>
488 -#include <linux/cpufreq.h>
489 -#include <linux/delay.h>
490 -#include <linux/init.h>
491 -#include <linux/err.h>
492 -#include <linux/clk.h>
493 -#include <linux/io.h>
494 -#include <linux/opp.h>
495 -
496 -#include <mach/hardware.h>
497 -#include <plat/clock.h>
498 -#include <asm/system.h>
499 -
500 -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
501 -#include <plat/omap-pm.h>
502 -#include <plat/common.h>
503 -#endif
504 -
505 -#define VERY_HI_RATE 900000000
506 -
507 -static struct cpufreq_frequency_table *freq_table;
508 -
509 -#ifdef CONFIG_ARCH_OMAP1
510 -#define MPU_CLK "mpu"
511 -#elif defined(CONFIG_ARCH_OMAP3)
512 -#define MPU_CLK "arm_fck"
513 -#else
514 -#define MPU_CLK "virt_prcm_set"
515 -#endif
516 -
517 -static struct clk *mpu_clk;
518 -
519 -/* TODO: Add support for SDRAM timing changes */
520 -
521 -static int omap_verify_speed(struct cpufreq_policy *policy)
522 -{
523 - if (freq_table)
524 - return cpufreq_frequency_table_verify(policy, freq_table);
525 -
526 - if (policy->cpu)
527 - return -EINVAL;
528 -
529 - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
530 - policy->cpuinfo.max_freq);
531 -
532 - policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
533 - policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
534 - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
535 - policy->cpuinfo.max_freq);
536 - return 0;
537 -}
538 -
539 -static unsigned int omap_getspeed(unsigned int cpu)
540 -{
541 - unsigned long rate;
542 -
543 - if (cpu)
544 - return 0;
545 -
546 - rate = clk_get_rate(mpu_clk) / 1000;
547 - return rate;
548 -}
549 -
550 -static int omap_target(struct cpufreq_policy *policy,
551 - unsigned int target_freq,
552 - unsigned int relation)
553 -{
554 -#ifdef CONFIG_ARCH_OMAP1
555 - struct cpufreq_freqs freqs;
556 -#endif
557 -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
558 - unsigned long freq;
559 - struct device *mpu_dev = omap2_get_mpuss_device();
560 -#endif
561 - int ret = 0;
562 -
563 - /* Ensure desired rate is within allowed range. Some govenors
564 - * (ondemand) will just pass target_freq=0 to get the minimum. */
565 - if (target_freq < policy->min)
566 - target_freq = policy->min;
567 - if (target_freq > policy->max)
568 - target_freq = policy->max;
569 -
570 -#ifdef CONFIG_ARCH_OMAP1
571 - freqs.old = omap_getspeed(0);
572 - freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
573 - freqs.cpu = 0;
574 -
575 - if (freqs.old == freqs.new)
576 - return ret;
577 - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
578 -#ifdef CONFIG_CPU_FREQ_DEBUG
579 - printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
580 - freqs.old, freqs.new);
581 -#endif
582 - ret = clk_set_rate(mpu_clk, freqs.new * 1000);
583 - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
584 -#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
585 - freq = target_freq * 1000;
586 - if (opp_find_freq_ceil(mpu_dev, &freq))
587 - omap_pm_cpu_set_freq(freq);
588 -#endif
589 - return ret;
590 -}
591 -
592 -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
593 -{
594 - int result = 0;
595 -
596 - mpu_clk = clk_get(NULL, MPU_CLK);
597 - if (IS_ERR(mpu_clk))
598 - return PTR_ERR(mpu_clk);
599 -
600 - if (policy->cpu != 0)
601 - return -EINVAL;
602 -
603 - policy->cur = policy->min = policy->max = omap_getspeed(0);
604 -
605 - if (!cpu_is_omap34xx()) {
606 - clk_init_cpufreq_table(&freq_table);
607 - } else {
608 - struct device *mpu_dev = omap2_get_mpuss_device();
609 -
610 - opp_init_cpufreq_table(mpu_dev, &freq_table);
611 - }
612 -
613 - if (freq_table) {
614 - result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
615 - if (!result)
616 - cpufreq_frequency_table_get_attr(freq_table,
617 - policy->cpu);
618 - } else {
619 - policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
620 - policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
621 - VERY_HI_RATE) / 1000;
622 - }
623 -
624 - policy->min = policy->cpuinfo.min_freq;
625 - policy->max = policy->cpuinfo.max_freq;
626 - policy->cur = omap_getspeed(0);
627 -
628 - /* FIXME: what's the actual transition time? */
629 - policy->cpuinfo.transition_latency = 300 * 1000;
630 -
631 - return 0;
632 -}
633 -
634 -static int omap_cpu_exit(struct cpufreq_policy *policy)
635 -{
636 - clk_exit_cpufreq_table(&freq_table);
637 - clk_put(mpu_clk);
638 - return 0;
639 -}
640 -
641 -static struct freq_attr *omap_cpufreq_attr[] = {
642 - &cpufreq_freq_attr_scaling_available_freqs,
643 - NULL,
644 -};
645 -
646 -static struct cpufreq_driver omap_driver = {
647 - .flags = CPUFREQ_STICKY,
648 - .verify = omap_verify_speed,
649 - .target = omap_target,
650 - .get = omap_getspeed,
651 - .init = omap_cpu_init,
652 - .exit = omap_cpu_exit,
653 - .name = "omap",
654 - .attr = omap_cpufreq_attr,
655 -};
656 -
657 -static int __init omap_cpufreq_init(void)
658 -{
659 - return cpufreq_register_driver(&omap_driver);
660 -}
661 -
662 -late_initcall(omap_cpufreq_init);
663 -
664 -/*
665 - * if ever we want to remove this, upon cleanup call:
666 - *
667 - * cpufreq_unregister_driver()
668 - * cpufreq_frequency_table_put_attr()
669 - */
670 -
671 --
672 1.6.6.1