Commit c0fe5f278d2ce459c2aee2c26e26c761c72231a4
Committed by
Afzal Mohammed
1 parent
3b52353d4d
Exists in
master
cpufreq: OMAP: cleanup for multi-SoC support, move into drivers/cpufreq
Move OMAP cpufreq driver from arch/arm/mach-omap2 into drivers/cpufreq, along with a few cleanups: - generalize support for better handling of different SoCs in the OMAP - use OPP layer instead of OMAP clock internals for frequency table init Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> [khilman@ti.com: move to drivers] Signed-off-by: Kevin Hilman <khilman@ti.com> [vaibhav.bedia@ti.com: Pull in for AM33xx] Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Showing 4 changed files with 189 additions and 172 deletions Side-by-side Diff
arch/arm/plat-omap/Makefile
... | ... | @@ -28,7 +28,6 @@ |
28 | 28 | obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o |
29 | 29 | obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o |
30 | 30 | |
31 | -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o | |
32 | 31 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o |
33 | 32 | obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o |
34 | 33 | obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o |
arch/arm/plat-omap/cpu-omap.c
1 | -/* | |
2 | - * linux/arch/arm/plat-omap/cpu-omap.c | |
3 | - * | |
4 | - * CPU frequency scaling for OMAP | |
5 | - * | |
6 | - * Copyright (C) 2005 Nokia Corporation | |
7 | - * Written by Tony Lindgren <tony@atomide.com> | |
8 | - * | |
9 | - * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | |
10 | - * | |
11 | - * This program is free software; you can redistribute it and/or modify | |
12 | - * it under the terms of the GNU General Public License version 2 as | |
13 | - * published by the Free Software Foundation. | |
14 | - */ | |
15 | -#include <linux/types.h> | |
16 | -#include <linux/kernel.h> | |
17 | -#include <linux/sched.h> | |
18 | -#include <linux/cpufreq.h> | |
19 | -#include <linux/delay.h> | |
20 | -#include <linux/init.h> | |
21 | -#include <linux/err.h> | |
22 | -#include <linux/clk.h> | |
23 | -#include <linux/io.h> | |
24 | - | |
25 | -#include <mach/hardware.h> | |
26 | -#include <plat/clock.h> | |
27 | -#include <asm/system.h> | |
28 | - | |
29 | -#define VERY_HI_RATE 900000000 | |
30 | - | |
31 | -static struct cpufreq_frequency_table *freq_table; | |
32 | - | |
33 | -#ifdef CONFIG_ARCH_OMAP1 | |
34 | -#define MPU_CLK "mpu" | |
35 | -#else | |
36 | -#define MPU_CLK "virt_prcm_set" | |
37 | -#endif | |
38 | - | |
39 | -static struct clk *mpu_clk; | |
40 | - | |
41 | -/* TODO: Add support for SDRAM timing changes */ | |
42 | - | |
43 | -static int omap_verify_speed(struct cpufreq_policy *policy) | |
44 | -{ | |
45 | - if (freq_table) | |
46 | - return cpufreq_frequency_table_verify(policy, freq_table); | |
47 | - | |
48 | - if (policy->cpu) | |
49 | - return -EINVAL; | |
50 | - | |
51 | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | |
52 | - policy->cpuinfo.max_freq); | |
53 | - | |
54 | - policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | |
55 | - policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | |
56 | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | |
57 | - policy->cpuinfo.max_freq); | |
58 | - return 0; | |
59 | -} | |
60 | - | |
61 | -static unsigned int omap_getspeed(unsigned int cpu) | |
62 | -{ | |
63 | - unsigned long rate; | |
64 | - | |
65 | - if (cpu) | |
66 | - return 0; | |
67 | - | |
68 | - rate = clk_get_rate(mpu_clk) / 1000; | |
69 | - return rate; | |
70 | -} | |
71 | - | |
72 | -static int omap_target(struct cpufreq_policy *policy, | |
73 | - unsigned int target_freq, | |
74 | - unsigned int relation) | |
75 | -{ | |
76 | - struct cpufreq_freqs freqs; | |
77 | - int ret = 0; | |
78 | - | |
79 | - /* Ensure desired rate is within allowed range. Some govenors | |
80 | - * (ondemand) will just pass target_freq=0 to get the minimum. */ | |
81 | - if (target_freq < policy->min) | |
82 | - target_freq = policy->min; | |
83 | - if (target_freq > policy->max) | |
84 | - target_freq = policy->max; | |
85 | - | |
86 | - freqs.old = omap_getspeed(0); | |
87 | - freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | |
88 | - freqs.cpu = 0; | |
89 | - | |
90 | - if (freqs.old == freqs.new) | |
91 | - return ret; | |
92 | - | |
93 | - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | |
94 | -#ifdef CONFIG_CPU_FREQ_DEBUG | |
95 | - printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", | |
96 | - freqs.old, freqs.new); | |
97 | -#endif | |
98 | - ret = clk_set_rate(mpu_clk, freqs.new * 1000); | |
99 | - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | |
100 | - | |
101 | - return ret; | |
102 | -} | |
103 | - | |
104 | -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | |
105 | -{ | |
106 | - int result = 0; | |
107 | - | |
108 | - mpu_clk = clk_get(NULL, MPU_CLK); | |
109 | - if (IS_ERR(mpu_clk)) | |
110 | - return PTR_ERR(mpu_clk); | |
111 | - | |
112 | - if (policy->cpu != 0) | |
113 | - return -EINVAL; | |
114 | - | |
115 | - policy->cur = policy->min = policy->max = omap_getspeed(0); | |
116 | - | |
117 | - clk_init_cpufreq_table(&freq_table); | |
118 | - if (freq_table) { | |
119 | - result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | |
120 | - if (!result) | |
121 | - cpufreq_frequency_table_get_attr(freq_table, | |
122 | - policy->cpu); | |
123 | - } else { | |
124 | - policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | |
125 | - policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | |
126 | - VERY_HI_RATE) / 1000; | |
127 | - } | |
128 | - | |
129 | - /* FIXME: what's the actual transition time? */ | |
130 | - policy->cpuinfo.transition_latency = 300 * 1000; | |
131 | - | |
132 | - return 0; | |
133 | -} | |
134 | - | |
135 | -static int omap_cpu_exit(struct cpufreq_policy *policy) | |
136 | -{ | |
137 | - clk_exit_cpufreq_table(&freq_table); | |
138 | - clk_put(mpu_clk); | |
139 | - return 0; | |
140 | -} | |
141 | - | |
142 | -static struct freq_attr *omap_cpufreq_attr[] = { | |
143 | - &cpufreq_freq_attr_scaling_available_freqs, | |
144 | - NULL, | |
145 | -}; | |
146 | - | |
147 | -static struct cpufreq_driver omap_driver = { | |
148 | - .flags = CPUFREQ_STICKY, | |
149 | - .verify = omap_verify_speed, | |
150 | - .target = omap_target, | |
151 | - .get = omap_getspeed, | |
152 | - .init = omap_cpu_init, | |
153 | - .exit = omap_cpu_exit, | |
154 | - .name = "omap", | |
155 | - .attr = omap_cpufreq_attr, | |
156 | -}; | |
157 | - | |
158 | -static int __init omap_cpufreq_init(void) | |
159 | -{ | |
160 | - return cpufreq_register_driver(&omap_driver); | |
161 | -} | |
162 | - | |
163 | -arch_initcall(omap_cpufreq_init); | |
164 | - | |
165 | -/* | |
166 | - * if ever we want to remove this, upon cleanup call: | |
167 | - * | |
168 | - * cpufreq_unregister_driver() | |
169 | - * cpufreq_frequency_table_put_attr() | |
170 | - */ |
drivers/cpufreq/Makefile
... | ... | @@ -43,6 +43,7 @@ |
43 | 43 | obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o |
44 | 44 | obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o |
45 | 45 | obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o |
46 | +obj-$(CONFIG_ARCH_OMAP2PLUS) += omap-cpufreq.o | |
46 | 47 | |
47 | 48 | ################################################################################## |
48 | 49 | # PowerPC platform drivers |
drivers/cpufreq/omap-cpufreq.c
1 | +/* | |
2 | + * CPU frequency scaling for OMAP | |
3 | + * | |
4 | + * Copyright (C) 2005 Nokia Corporation | |
5 | + * Written by Tony Lindgren <tony@atomide.com> | |
6 | + * | |
7 | + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | |
8 | + * | |
9 | + * Copyright (C) 2007-2011 Texas Instruments, Inc. | |
10 | + * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar | |
11 | + * | |
12 | + * This program is free software; you can redistribute it and/or modify | |
13 | + * it under the terms of the GNU General Public License version 2 as | |
14 | + * published by the Free Software Foundation. | |
15 | + */ | |
16 | +#include <linux/types.h> | |
17 | +#include <linux/kernel.h> | |
18 | +#include <linux/sched.h> | |
19 | +#include <linux/cpufreq.h> | |
20 | +#include <linux/delay.h> | |
21 | +#include <linux/init.h> | |
22 | +#include <linux/err.h> | |
23 | +#include <linux/clk.h> | |
24 | +#include <linux/io.h> | |
25 | +#include <linux/opp.h> | |
26 | + | |
27 | +#include <asm/system.h> | |
28 | +#include <asm/smp_plat.h> | |
29 | + | |
30 | +#include <plat/clock.h> | |
31 | +#include <plat/omap-pm.h> | |
32 | +#include <plat/common.h> | |
33 | + | |
34 | +#include <mach/hardware.h> | |
35 | + | |
36 | +#define VERY_HI_RATE 900000000 | |
37 | + | |
38 | +static struct cpufreq_frequency_table *freq_table; | |
39 | +static struct clk *mpu_clk; | |
40 | + | |
41 | +static int omap_verify_speed(struct cpufreq_policy *policy) | |
42 | +{ | |
43 | + if (freq_table) | |
44 | + return cpufreq_frequency_table_verify(policy, freq_table); | |
45 | + | |
46 | + if (policy->cpu) | |
47 | + return -EINVAL; | |
48 | + | |
49 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | |
50 | + policy->cpuinfo.max_freq); | |
51 | + | |
52 | + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | |
53 | + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | |
54 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | |
55 | + policy->cpuinfo.max_freq); | |
56 | + return 0; | |
57 | +} | |
58 | + | |
59 | +static unsigned int omap_getspeed(unsigned int cpu) | |
60 | +{ | |
61 | + unsigned long rate; | |
62 | + | |
63 | + if (cpu) | |
64 | + return 0; | |
65 | + | |
66 | + rate = clk_get_rate(mpu_clk) / 1000; | |
67 | + return rate; | |
68 | +} | |
69 | + | |
70 | +static int omap_target(struct cpufreq_policy *policy, | |
71 | + unsigned int target_freq, | |
72 | + unsigned int relation) | |
73 | +{ | |
74 | + int ret = 0; | |
75 | + struct cpufreq_freqs freqs; | |
76 | + | |
77 | + /* Ensure desired rate is within allowed range. Some govenors | |
78 | + * (ondemand) will just pass target_freq=0 to get the minimum. */ | |
79 | + if (target_freq < policy->min) | |
80 | + target_freq = policy->min; | |
81 | + if (target_freq > policy->max) | |
82 | + target_freq = policy->max; | |
83 | + | |
84 | + freqs.old = omap_getspeed(0); | |
85 | + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | |
86 | + freqs.cpu = 0; | |
87 | + | |
88 | + if (freqs.old == freqs.new) | |
89 | + return ret; | |
90 | + | |
91 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | |
92 | + | |
93 | +#ifdef CONFIG_CPU_FREQ_DEBUG | |
94 | + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | |
95 | +#endif | |
96 | + | |
97 | + ret = clk_set_rate(mpu_clk, freqs.new * 1000); | |
98 | + | |
99 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | |
100 | + | |
101 | + return ret; | |
102 | +} | |
103 | + | |
104 | +static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | |
105 | +{ | |
106 | + int result = 0; | |
107 | + struct device *mpu_dev; | |
108 | + | |
109 | + if (cpu_is_omap24xx()) | |
110 | + mpu_clk = clk_get(NULL, "virt_prcm_set"); | |
111 | + else if (cpu_is_omap34xx()) | |
112 | + mpu_clk = clk_get(NULL, "dpll1_ck"); | |
113 | + else if (cpu_is_omap44xx()) | |
114 | + mpu_clk = clk_get(NULL, "dpll_mpu_ck"); | |
115 | + | |
116 | + if (IS_ERR(mpu_clk)) | |
117 | + return PTR_ERR(mpu_clk); | |
118 | + | |
119 | + if (policy->cpu != 0) | |
120 | + return -EINVAL; | |
121 | + | |
122 | + policy->cur = policy->min = policy->max = omap_getspeed(0); | |
123 | + | |
124 | + mpu_dev = omap2_get_mpuss_device(); | |
125 | + if (!mpu_dev) { | |
126 | + pr_warning("%s: unable to get the mpu device\n", __func__); | |
127 | + return -EINVAL; | |
128 | + } | |
129 | + opp_init_cpufreq_table(mpu_dev, &freq_table); | |
130 | + | |
131 | + if (freq_table) { | |
132 | + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | |
133 | + if (!result) | |
134 | + cpufreq_frequency_table_get_attr(freq_table, | |
135 | + policy->cpu); | |
136 | + } else { | |
137 | + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | |
138 | + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | |
139 | + VERY_HI_RATE) / 1000; | |
140 | + } | |
141 | + | |
142 | + policy->min = policy->cpuinfo.min_freq; | |
143 | + policy->max = policy->cpuinfo.max_freq; | |
144 | + policy->cur = omap_getspeed(0); | |
145 | + | |
146 | + /* FIXME: what's the actual transition time? */ | |
147 | + policy->cpuinfo.transition_latency = 300 * 1000; | |
148 | + | |
149 | + return 0; | |
150 | +} | |
151 | + | |
152 | +static int omap_cpu_exit(struct cpufreq_policy *policy) | |
153 | +{ | |
154 | + clk_exit_cpufreq_table(&freq_table); | |
155 | + clk_put(mpu_clk); | |
156 | + return 0; | |
157 | +} | |
158 | + | |
159 | +static struct freq_attr *omap_cpufreq_attr[] = { | |
160 | + &cpufreq_freq_attr_scaling_available_freqs, | |
161 | + NULL, | |
162 | +}; | |
163 | + | |
164 | +static struct cpufreq_driver omap_driver = { | |
165 | + .flags = CPUFREQ_STICKY, | |
166 | + .verify = omap_verify_speed, | |
167 | + .target = omap_target, | |
168 | + .get = omap_getspeed, | |
169 | + .init = omap_cpu_init, | |
170 | + .exit = omap_cpu_exit, | |
171 | + .name = "omap", | |
172 | + .attr = omap_cpufreq_attr, | |
173 | +}; | |
174 | + | |
175 | +static int __init omap_cpufreq_init(void) | |
176 | +{ | |
177 | + return cpufreq_register_driver(&omap_driver); | |
178 | +} | |
179 | + | |
180 | +static void __exit omap_cpufreq_exit(void) | |
181 | +{ | |
182 | + cpufreq_unregister_driver(&omap_driver); | |
183 | +} | |
184 | + | |
185 | +MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs"); | |
186 | +MODULE_LICENSE("GPL"); | |
187 | +module_init(omap_cpufreq_init); | |
188 | +module_exit(omap_cpufreq_exit); |