diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-27 20:10:46 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-27 20:10:46 -0400 |
commit | 885f925eef411f549f17bc64dd054a3269cf66cd (patch) | |
tree | 6bac783d573a51e497ad28c19b5a71defac85f39 /arch | |
parent | e4f5a3adc454745fea35f1c312e14cbeba6e0ea4 (diff) | |
parent | 45c009a9a447655aecbdb06c86126f05d0272171 (diff) |
Merge branch 'pm-cpufreq'
* pm-cpufreq: (57 commits)
cpufreq: MAINTAINERS: Add co-maintainer
cpufreq: pxa2xx: initialize variables
ARM: S5pv210: compiling issue, ARM_S5PV210_CPUFREQ needs CONFIG_CPU_FREQ_TABLE=y
cpufreq: cpu0: Put cpu parent node after using it
cpufreq: ARM big LITTLE: Adapt to latest cpufreq updates
cpufreq: ARM big LITTLE: put DT nodes after using them
cpufreq: Don't call __cpufreq_governor() for drivers without target()
cpufreq: exynos5440: Protect OPP search calls with RCU lock
cpufreq: dbx500: Round to closest available freq
cpufreq: Call __cpufreq_governor() with correct policy->cpus mask
cpufreq / intel_pstate: Optimize intel_pstate_set_policy
cpufreq: OMAP: instantiate omap-cpufreq as a platform_driver
arm: exynos: Enable OPP library support for exynos5440
cpufreq: exynos: Remove error return even if no soc is found
cpufreq: exynos: Add cpufreq driver for exynos5440
cpufreq: AMD "frequency sensitivity feedback" powersave bias for ondemand governor
cpufreq: ondemand: allow custom powersave_bias_target handler to be registered
cpufreq: convert cpufreq_driver to using RCU
cpufreq: powerpc/platforms/cell: move cpufreq driver to drivers/cpufreq
cpufreq: sparc: move cpufreq driver to drivers/cpufreq
...
Conflicts:
MAINTAINERS (with commit a8e39c3 from pm-cpuidle)
drivers/cpufreq/cpufreq_governor.h (with commit beb0ff3)
Diffstat (limited to 'arch')
73 files changed, 70 insertions, 5295 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1cacda426a0e..cdb83225f3ea 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -2160,7 +2160,6 @@ endmenu | |||
2160 | menu "CPU Power Management" | 2160 | menu "CPU Power Management" |
2161 | 2161 | ||
2162 | if ARCH_HAS_CPUFREQ | 2162 | if ARCH_HAS_CPUFREQ |
2163 | |||
2164 | source "drivers/cpufreq/Kconfig" | 2163 | source "drivers/cpufreq/Kconfig" |
2165 | 2164 | ||
2166 | config CPU_FREQ_IMX | 2165 | config CPU_FREQ_IMX |
@@ -2170,30 +2169,6 @@ config CPU_FREQ_IMX | |||
2170 | help | 2169 | help |
2171 | This enables the CPUfreq driver for i.MX CPUs. | 2170 | This enables the CPUfreq driver for i.MX CPUs. |
2172 | 2171 | ||
2173 | config CPU_FREQ_SA1100 | ||
2174 | bool | ||
2175 | |||
2176 | config CPU_FREQ_SA1110 | ||
2177 | bool | ||
2178 | |||
2179 | config CPU_FREQ_INTEGRATOR | ||
2180 | tristate "CPUfreq driver for ARM Integrator CPUs" | ||
2181 | depends on ARCH_INTEGRATOR && CPU_FREQ | ||
2182 | default y | ||
2183 | help | ||
2184 | This enables the CPUfreq driver for ARM Integrator CPUs. | ||
2185 | |||
2186 | For details, take a look at <file:Documentation/cpu-freq>. | ||
2187 | |||
2188 | If in doubt, say Y. | ||
2189 | |||
2190 | config CPU_FREQ_PXA | ||
2191 | bool | ||
2192 | depends on CPU_FREQ && ARCH_PXA && PXA25x | ||
2193 | default y | ||
2194 | select CPU_FREQ_DEFAULT_GOV_USERSPACE | ||
2195 | select CPU_FREQ_TABLE | ||
2196 | |||
2197 | config CPU_FREQ_S3C | 2172 | config CPU_FREQ_S3C |
2198 | bool | 2173 | bool |
2199 | help | 2174 | help |
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index fb5c1aa98a63..dd1ffccc75e9 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile | |||
@@ -37,7 +37,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o | |||
37 | obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o | 37 | obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o |
38 | 38 | ||
39 | # Power Management | 39 | # Power Management |
40 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | ||
41 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | 40 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o |
42 | obj-$(CONFIG_SUSPEND) += pm.o sleep.o | 41 | obj-$(CONFIG_SUSPEND) += pm.o sleep.o |
43 | obj-$(CONFIG_HAVE_CLK) += pm_domain.o | 42 | obj-$(CONFIG_HAVE_CLK) += pm_domain.o |
diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c deleted file mode 100644 index 4729eaab0f40..000000000000 --- a/arch/arm/mach-davinci/cpufreq.c +++ /dev/null | |||
@@ -1,248 +0,0 @@ | |||
1 | /* | ||
2 | * CPU frequency scaling for DaVinci | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
6 | * Based on linux/arch/arm/plat-omap/cpu-omap.c. Original Copyright follows: | ||
7 | * | ||
8 | * Copyright (C) 2005 Nokia Corporation | ||
9 | * Written by Tony Lindgren <tony@atomide.com> | ||
10 | * | ||
11 | * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
12 | * | ||
13 | * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
14 | * Updated to support OMAP3 | ||
15 | * Rajendra Nayak <rnayak@ti.com> | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License version 2 as | ||
19 | * published by the Free Software Foundation. | ||
20 | */ | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/cpufreq.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/clk.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/export.h> | ||
28 | |||
29 | #include <mach/hardware.h> | ||
30 | #include <mach/cpufreq.h> | ||
31 | #include <mach/common.h> | ||
32 | |||
33 | #include "clock.h" | ||
34 | |||
35 | struct davinci_cpufreq { | ||
36 | struct device *dev; | ||
37 | struct clk *armclk; | ||
38 | struct clk *asyncclk; | ||
39 | unsigned long asyncrate; | ||
40 | }; | ||
41 | static struct davinci_cpufreq cpufreq; | ||
42 | |||
43 | static int davinci_verify_speed(struct cpufreq_policy *policy) | ||
44 | { | ||
45 | struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; | ||
46 | struct cpufreq_frequency_table *freq_table = pdata->freq_table; | ||
47 | struct clk *armclk = cpufreq.armclk; | ||
48 | |||
49 | if (freq_table) | ||
50 | return cpufreq_frequency_table_verify(policy, freq_table); | ||
51 | |||
52 | if (policy->cpu) | ||
53 | return -EINVAL; | ||
54 | |||
55 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
56 | policy->cpuinfo.max_freq); | ||
57 | |||
58 | policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000; | ||
59 | policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000; | ||
60 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
61 | policy->cpuinfo.max_freq); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static unsigned int davinci_getspeed(unsigned int cpu) | ||
66 | { | ||
67 | if (cpu) | ||
68 | return 0; | ||
69 | |||
70 | return clk_get_rate(cpufreq.armclk) / 1000; | ||
71 | } | ||
72 | |||
73 | static int davinci_target(struct cpufreq_policy *policy, | ||
74 | unsigned int target_freq, unsigned int relation) | ||
75 | { | ||
76 | int ret = 0; | ||
77 | unsigned int idx; | ||
78 | struct cpufreq_freqs freqs; | ||
79 | struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; | ||
80 | struct clk *armclk = cpufreq.armclk; | ||
81 | |||
82 | /* | ||
83 | * Ensure desired rate is within allowed range. Some govenors | ||
84 | * (ondemand) will just pass target_freq=0 to get the minimum. | ||
85 | */ | ||
86 | if (target_freq < policy->cpuinfo.min_freq) | ||
87 | target_freq = policy->cpuinfo.min_freq; | ||
88 | if (target_freq > policy->cpuinfo.max_freq) | ||
89 | target_freq = policy->cpuinfo.max_freq; | ||
90 | |||
91 | freqs.old = davinci_getspeed(0); | ||
92 | freqs.new = clk_round_rate(armclk, target_freq * 1000) / 1000; | ||
93 | freqs.cpu = 0; | ||
94 | |||
95 | if (freqs.old == freqs.new) | ||
96 | return ret; | ||
97 | |||
98 | dev_dbg(cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new); | ||
99 | |||
100 | ret = cpufreq_frequency_table_target(policy, pdata->freq_table, | ||
101 | freqs.new, relation, &idx); | ||
102 | if (ret) | ||
103 | return -EINVAL; | ||
104 | |||
105 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
106 | |||
107 | /* if moving to higher frequency, up the voltage beforehand */ | ||
108 | if (pdata->set_voltage && freqs.new > freqs.old) { | ||
109 | ret = pdata->set_voltage(idx); | ||
110 | if (ret) | ||
111 | goto out; | ||
112 | } | ||
113 | |||
114 | ret = clk_set_rate(armclk, idx); | ||
115 | if (ret) | ||
116 | goto out; | ||
117 | |||
118 | if (cpufreq.asyncclk) { | ||
119 | ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate); | ||
120 | if (ret) | ||
121 | goto out; | ||
122 | } | ||
123 | |||
124 | /* if moving to lower freq, lower the voltage after lowering freq */ | ||
125 | if (pdata->set_voltage && freqs.new < freqs.old) | ||
126 | pdata->set_voltage(idx); | ||
127 | |||
128 | out: | ||
129 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
130 | |||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static int davinci_cpu_init(struct cpufreq_policy *policy) | ||
135 | { | ||
136 | int result = 0; | ||
137 | struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; | ||
138 | struct cpufreq_frequency_table *freq_table = pdata->freq_table; | ||
139 | |||
140 | if (policy->cpu != 0) | ||
141 | return -EINVAL; | ||
142 | |||
143 | /* Finish platform specific initialization */ | ||
144 | if (pdata->init) { | ||
145 | result = pdata->init(); | ||
146 | if (result) | ||
147 | return result; | ||
148 | } | ||
149 | |||
150 | policy->cur = policy->min = policy->max = davinci_getspeed(0); | ||
151 | |||
152 | if (freq_table) { | ||
153 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
154 | if (!result) | ||
155 | cpufreq_frequency_table_get_attr(freq_table, | ||
156 | policy->cpu); | ||
157 | } else { | ||
158 | policy->cpuinfo.min_freq = policy->min; | ||
159 | policy->cpuinfo.max_freq = policy->max; | ||
160 | } | ||
161 | |||
162 | policy->min = policy->cpuinfo.min_freq; | ||
163 | policy->max = policy->cpuinfo.max_freq; | ||
164 | policy->cur = davinci_getspeed(0); | ||
165 | |||
166 | /* | ||
167 | * Time measurement across the target() function yields ~1500-1800us | ||
168 | * time taken with no drivers on notification list. | ||
169 | * Setting the latency to 2000 us to accommodate addition of drivers | ||
170 | * to pre/post change notification list. | ||
171 | */ | ||
172 | policy->cpuinfo.transition_latency = 2000 * 1000; | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int davinci_cpu_exit(struct cpufreq_policy *policy) | ||
177 | { | ||
178 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static struct freq_attr *davinci_cpufreq_attr[] = { | ||
183 | &cpufreq_freq_attr_scaling_available_freqs, | ||
184 | NULL, | ||
185 | }; | ||
186 | |||
187 | static struct cpufreq_driver davinci_driver = { | ||
188 | .flags = CPUFREQ_STICKY, | ||
189 | .verify = davinci_verify_speed, | ||
190 | .target = davinci_target, | ||
191 | .get = davinci_getspeed, | ||
192 | .init = davinci_cpu_init, | ||
193 | .exit = davinci_cpu_exit, | ||
194 | .name = "davinci", | ||
195 | .attr = davinci_cpufreq_attr, | ||
196 | }; | ||
197 | |||
198 | static int __init davinci_cpufreq_probe(struct platform_device *pdev) | ||
199 | { | ||
200 | struct davinci_cpufreq_config *pdata = pdev->dev.platform_data; | ||
201 | struct clk *asyncclk; | ||
202 | |||
203 | if (!pdata) | ||
204 | return -EINVAL; | ||
205 | if (!pdata->freq_table) | ||
206 | return -EINVAL; | ||
207 | |||
208 | cpufreq.dev = &pdev->dev; | ||
209 | |||
210 | cpufreq.armclk = clk_get(NULL, "arm"); | ||
211 | if (IS_ERR(cpufreq.armclk)) { | ||
212 | dev_err(cpufreq.dev, "Unable to get ARM clock\n"); | ||
213 | return PTR_ERR(cpufreq.armclk); | ||
214 | } | ||
215 | |||
216 | asyncclk = clk_get(cpufreq.dev, "async"); | ||
217 | if (!IS_ERR(asyncclk)) { | ||
218 | cpufreq.asyncclk = asyncclk; | ||
219 | cpufreq.asyncrate = clk_get_rate(asyncclk); | ||
220 | } | ||
221 | |||
222 | return cpufreq_register_driver(&davinci_driver); | ||
223 | } | ||
224 | |||
225 | static int __exit davinci_cpufreq_remove(struct platform_device *pdev) | ||
226 | { | ||
227 | clk_put(cpufreq.armclk); | ||
228 | |||
229 | if (cpufreq.asyncclk) | ||
230 | clk_put(cpufreq.asyncclk); | ||
231 | |||
232 | return cpufreq_unregister_driver(&davinci_driver); | ||
233 | } | ||
234 | |||
235 | static struct platform_driver davinci_cpufreq_driver = { | ||
236 | .driver = { | ||
237 | .name = "cpufreq-davinci", | ||
238 | .owner = THIS_MODULE, | ||
239 | }, | ||
240 | .remove = __exit_p(davinci_cpufreq_remove), | ||
241 | }; | ||
242 | |||
243 | int __init davinci_cpufreq_init(void) | ||
244 | { | ||
245 | return platform_driver_probe(&davinci_cpufreq_driver, | ||
246 | davinci_cpufreq_probe); | ||
247 | } | ||
248 | |||
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 70f94c87479d..d5dde0727339 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig | |||
@@ -72,10 +72,12 @@ config SOC_EXYNOS5440 | |||
72 | bool "SAMSUNG EXYNOS5440" | 72 | bool "SAMSUNG EXYNOS5440" |
73 | default y | 73 | default y |
74 | depends on ARCH_EXYNOS5 | 74 | depends on ARCH_EXYNOS5 |
75 | select ARCH_HAS_OPP | ||
75 | select ARM_ARCH_TIMER | 76 | select ARM_ARCH_TIMER |
76 | select AUTO_ZRELADDR | 77 | select AUTO_ZRELADDR |
77 | select PINCTRL | 78 | select PINCTRL |
78 | select PINCTRL_EXYNOS5440 | 79 | select PINCTRL_EXYNOS5440 |
80 | select PM_OPP | ||
79 | help | 81 | help |
80 | Enable EXYNOS5440 SoC support | 82 | Enable EXYNOS5440 SoC support |
81 | 83 | ||
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c index d8c75c3c925d..387dc4cceca2 100644 --- a/arch/arm/mach-imx/cpufreq.c +++ b/arch/arm/mach-imx/cpufreq.c | |||
@@ -87,13 +87,12 @@ static int mxc_set_target(struct cpufreq_policy *policy, | |||
87 | 87 | ||
88 | freqs.old = clk_get_rate(cpu_clk) / 1000; | 88 | freqs.old = clk_get_rate(cpu_clk) / 1000; |
89 | freqs.new = freq_Hz / 1000; | 89 | freqs.new = freq_Hz / 1000; |
90 | freqs.cpu = 0; | ||
91 | freqs.flags = 0; | 90 | freqs.flags = 0; |
92 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 91 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); |
93 | 92 | ||
94 | ret = set_cpu_freq(freq_Hz); | 93 | ret = set_cpu_freq(freq_Hz); |
95 | 94 | ||
96 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 95 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); |
97 | 96 | ||
98 | return ret; | 97 | return ret; |
99 | } | 98 | } |
@@ -145,14 +144,11 @@ static int mxc_cpufreq_init(struct cpufreq_policy *policy) | |||
145 | imx_freq_table[i].frequency = CPUFREQ_TABLE_END; | 144 | imx_freq_table[i].frequency = CPUFREQ_TABLE_END; |
146 | 145 | ||
147 | policy->cur = clk_get_rate(cpu_clk) / 1000; | 146 | policy->cur = clk_get_rate(cpu_clk) / 1000; |
148 | policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min; | ||
149 | policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max; | ||
150 | 147 | ||
151 | /* Manual states, that PLL stabilizes in two CLK32 periods */ | 148 | /* Manual states, that PLL stabilizes in two CLK32 periods */ |
152 | policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ; | 149 | policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ; |
153 | 150 | ||
154 | ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table); | 151 | ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table); |
155 | |||
156 | if (ret < 0) { | 152 | if (ret < 0) { |
157 | printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n", | 153 | printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n", |
158 | __func__, ret); | 154 | __func__, ret); |
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile index 5521d18bf19a..d14d6b76f4c2 100644 --- a/arch/arm/mach-integrator/Makefile +++ b/arch/arm/mach-integrator/Makefile | |||
@@ -9,5 +9,4 @@ obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o | |||
9 | obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o | 9 | obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o |
10 | 10 | ||
11 | obj-$(CONFIG_PCI) += pci_v3.o pci.o | 11 | obj-$(CONFIG_PCI) += pci_v3.o pci.o |
12 | obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o | ||
13 | obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o | 12 | obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o |
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c deleted file mode 100644 index 590c192cdf4d..000000000000 --- a/arch/arm/mach-integrator/cpu.c +++ /dev/null | |||
@@ -1,224 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-integrator/cpu.c | ||
3 | * | ||
4 | * Copyright (C) 2001-2002 Deep Blue Solutions Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * CPU support functions | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/cpufreq.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <mach/hardware.h> | ||
22 | #include <mach/platform.h> | ||
23 | #include <asm/mach-types.h> | ||
24 | #include <asm/hardware/icst.h> | ||
25 | |||
26 | static struct cpufreq_driver integrator_driver; | ||
27 | |||
28 | #define CM_ID __io_address(INTEGRATOR_HDR_ID) | ||
29 | #define CM_OSC __io_address(INTEGRATOR_HDR_OSC) | ||
30 | #define CM_STAT __io_address(INTEGRATOR_HDR_STAT) | ||
31 | #define CM_LOCK __io_address(INTEGRATOR_HDR_LOCK) | ||
32 | |||
33 | static const struct icst_params lclk_params = { | ||
34 | .ref = 24000000, | ||
35 | .vco_max = ICST525_VCO_MAX_5V, | ||
36 | .vco_min = ICST525_VCO_MIN, | ||
37 | .vd_min = 8, | ||
38 | .vd_max = 132, | ||
39 | .rd_min = 24, | ||
40 | .rd_max = 24, | ||
41 | .s2div = icst525_s2div, | ||
42 | .idx2s = icst525_idx2s, | ||
43 | }; | ||
44 | |||
45 | static const struct icst_params cclk_params = { | ||
46 | .ref = 24000000, | ||
47 | .vco_max = ICST525_VCO_MAX_5V, | ||
48 | .vco_min = ICST525_VCO_MIN, | ||
49 | .vd_min = 12, | ||
50 | .vd_max = 160, | ||
51 | .rd_min = 24, | ||
52 | .rd_max = 24, | ||
53 | .s2div = icst525_s2div, | ||
54 | .idx2s = icst525_idx2s, | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * Validate the speed policy. | ||
59 | */ | ||
60 | static int integrator_verify_policy(struct cpufreq_policy *policy) | ||
61 | { | ||
62 | struct icst_vco vco; | ||
63 | |||
64 | cpufreq_verify_within_limits(policy, | ||
65 | policy->cpuinfo.min_freq, | ||
66 | policy->cpuinfo.max_freq); | ||
67 | |||
68 | vco = icst_hz_to_vco(&cclk_params, policy->max * 1000); | ||
69 | policy->max = icst_hz(&cclk_params, vco) / 1000; | ||
70 | |||
71 | vco = icst_hz_to_vco(&cclk_params, policy->min * 1000); | ||
72 | policy->min = icst_hz(&cclk_params, vco) / 1000; | ||
73 | |||
74 | cpufreq_verify_within_limits(policy, | ||
75 | policy->cpuinfo.min_freq, | ||
76 | policy->cpuinfo.max_freq); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | |||
82 | static int integrator_set_target(struct cpufreq_policy *policy, | ||
83 | unsigned int target_freq, | ||
84 | unsigned int relation) | ||
85 | { | ||
86 | cpumask_t cpus_allowed; | ||
87 | int cpu = policy->cpu; | ||
88 | struct icst_vco vco; | ||
89 | struct cpufreq_freqs freqs; | ||
90 | u_int cm_osc; | ||
91 | |||
92 | /* | ||
93 | * Save this threads cpus_allowed mask. | ||
94 | */ | ||
95 | cpus_allowed = current->cpus_allowed; | ||
96 | |||
97 | /* | ||
98 | * Bind to the specified CPU. When this call returns, | ||
99 | * we should be running on the right CPU. | ||
100 | */ | ||
101 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | ||
102 | BUG_ON(cpu != smp_processor_id()); | ||
103 | |||
104 | /* get current setting */ | ||
105 | cm_osc = __raw_readl(CM_OSC); | ||
106 | |||
107 | if (machine_is_integrator()) { | ||
108 | vco.s = (cm_osc >> 8) & 7; | ||
109 | } else if (machine_is_cintegrator()) { | ||
110 | vco.s = 1; | ||
111 | } | ||
112 | vco.v = cm_osc & 255; | ||
113 | vco.r = 22; | ||
114 | freqs.old = icst_hz(&cclk_params, vco) / 1000; | ||
115 | |||
116 | /* icst_hz_to_vco rounds down -- so we need the next | ||
117 | * larger freq in case of CPUFREQ_RELATION_L. | ||
118 | */ | ||
119 | if (relation == CPUFREQ_RELATION_L) | ||
120 | target_freq += 999; | ||
121 | if (target_freq > policy->max) | ||
122 | target_freq = policy->max; | ||
123 | vco = icst_hz_to_vco(&cclk_params, target_freq * 1000); | ||
124 | freqs.new = icst_hz(&cclk_params, vco) / 1000; | ||
125 | |||
126 | freqs.cpu = policy->cpu; | ||
127 | |||
128 | if (freqs.old == freqs.new) { | ||
129 | set_cpus_allowed(current, cpus_allowed); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
134 | |||
135 | cm_osc = __raw_readl(CM_OSC); | ||
136 | |||
137 | if (machine_is_integrator()) { | ||
138 | cm_osc &= 0xfffff800; | ||
139 | cm_osc |= vco.s << 8; | ||
140 | } else if (machine_is_cintegrator()) { | ||
141 | cm_osc &= 0xffffff00; | ||
142 | } | ||
143 | cm_osc |= vco.v; | ||
144 | |||
145 | __raw_writel(0xa05f, CM_LOCK); | ||
146 | __raw_writel(cm_osc, CM_OSC); | ||
147 | __raw_writel(0, CM_LOCK); | ||
148 | |||
149 | /* | ||
150 | * Restore the CPUs allowed mask. | ||
151 | */ | ||
152 | set_cpus_allowed(current, cpus_allowed); | ||
153 | |||
154 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static unsigned int integrator_get(unsigned int cpu) | ||
160 | { | ||
161 | cpumask_t cpus_allowed; | ||
162 | unsigned int current_freq; | ||
163 | u_int cm_osc; | ||
164 | struct icst_vco vco; | ||
165 | |||
166 | cpus_allowed = current->cpus_allowed; | ||
167 | |||
168 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | ||
169 | BUG_ON(cpu != smp_processor_id()); | ||
170 | |||
171 | /* detect memory etc. */ | ||
172 | cm_osc = __raw_readl(CM_OSC); | ||
173 | |||
174 | if (machine_is_integrator()) { | ||
175 | vco.s = (cm_osc >> 8) & 7; | ||
176 | } else { | ||
177 | vco.s = 1; | ||
178 | } | ||
179 | vco.v = cm_osc & 255; | ||
180 | vco.r = 22; | ||
181 | |||
182 | current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */ | ||
183 | |||
184 | set_cpus_allowed(current, cpus_allowed); | ||
185 | |||
186 | return current_freq; | ||
187 | } | ||
188 | |||
189 | static int integrator_cpufreq_init(struct cpufreq_policy *policy) | ||
190 | { | ||
191 | |||
192 | /* set default policy and cpuinfo */ | ||
193 | policy->cpuinfo.max_freq = 160000; | ||
194 | policy->cpuinfo.min_freq = 12000; | ||
195 | policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */ | ||
196 | policy->cur = policy->min = policy->max = integrator_get(policy->cpu); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static struct cpufreq_driver integrator_driver = { | ||
202 | .verify = integrator_verify_policy, | ||
203 | .target = integrator_set_target, | ||
204 | .get = integrator_get, | ||
205 | .init = integrator_cpufreq_init, | ||
206 | .name = "integrator", | ||
207 | }; | ||
208 | |||
209 | static int __init integrator_cpu_init(void) | ||
210 | { | ||
211 | return cpufreq_register_driver(&integrator_driver); | ||
212 | } | ||
213 | |||
214 | static void __exit integrator_cpu_exit(void) | ||
215 | { | ||
216 | cpufreq_unregister_driver(&integrator_driver); | ||
217 | } | ||
218 | |||
219 | MODULE_AUTHOR ("Russell M. King"); | ||
220 | MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs"); | ||
221 | MODULE_LICENSE ("GPL"); | ||
222 | |||
223 | module_init(integrator_cpu_init); | ||
224 | module_exit(integrator_cpu_exit); | ||
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 673a4c1d1d76..8d15f9ae19ff 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c | |||
@@ -265,6 +265,12 @@ static void __init omap4_init_voltages(void) | |||
265 | omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva"); | 265 | omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva"); |
266 | } | 266 | } |
267 | 267 | ||
268 | static inline void omap_init_cpufreq(void) | ||
269 | { | ||
270 | struct platform_device_info devinfo = { .name = "omap-cpufreq", }; | ||
271 | platform_device_register_full(&devinfo); | ||
272 | } | ||
273 | |||
268 | static int __init omap2_common_pm_init(void) | 274 | static int __init omap2_common_pm_init(void) |
269 | { | 275 | { |
270 | if (!of_have_populated_dt()) | 276 | if (!of_have_populated_dt()) |
@@ -294,6 +300,9 @@ int __init omap2_common_pm_late_init(void) | |||
294 | 300 | ||
295 | /* Smartreflex device init */ | 301 | /* Smartreflex device init */ |
296 | omap_devinit_smartreflex(); | 302 | omap_devinit_smartreflex(); |
303 | |||
304 | /* cpufreq dummy device instantiation */ | ||
305 | omap_init_cpufreq(); | ||
297 | } | 306 | } |
298 | 307 | ||
299 | #ifdef CONFIG_SUSPEND | 308 | #ifdef CONFIG_SUSPEND |
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 12c500558387..648867a8caa8 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile | |||
@@ -7,12 +7,6 @@ obj-y += clock.o devices.o generic.o irq.o \ | |||
7 | time.o reset.o | 7 | time.o reset.o |
8 | obj-$(CONFIG_PM) += pm.o sleep.o standby.o | 8 | obj-$(CONFIG_PM) += pm.o sleep.o standby.o |
9 | 9 | ||
10 | ifeq ($(CONFIG_CPU_FREQ),y) | ||
11 | obj-$(CONFIG_PXA25x) += cpufreq-pxa2xx.o | ||
12 | obj-$(CONFIG_PXA27x) += cpufreq-pxa2xx.o | ||
13 | obj-$(CONFIG_PXA3xx) += cpufreq-pxa3xx.o | ||
14 | endif | ||
15 | |||
16 | # Generic drivers that other drivers may depend upon | 10 | # Generic drivers that other drivers may depend upon |
17 | 11 | ||
18 | # SoC-specific code | 12 | # SoC-specific code |
diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c deleted file mode 100644 index 6a7aeab42f6c..000000000000 --- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c +++ /dev/null | |||
@@ -1,494 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-pxa/cpufreq-pxa2xx.c | ||
3 | * | ||
4 | * Copyright (C) 2002,2003 Intrinsyc Software | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | * History: | ||
21 | * 31-Jul-2002 : Initial version [FB] | ||
22 | * 29-Jan-2003 : added PXA255 support [FB] | ||
23 | * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.) | ||
24 | * | ||
25 | * Note: | ||
26 | * This driver may change the memory bus clock rate, but will not do any | ||
27 | * platform specific access timing changes... for example if you have flash | ||
28 | * memory connected to CS0, you will need to register a platform specific | ||
29 | * notifier which will adjust the memory access strobes to maintain a | ||
30 | * minimum strobe width. | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/sched.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/cpufreq.h> | ||
39 | #include <linux/err.h> | ||
40 | #include <linux/regulator/consumer.h> | ||
41 | #include <linux/io.h> | ||
42 | |||
43 | #include <mach/pxa2xx-regs.h> | ||
44 | #include <mach/smemc.h> | ||
45 | |||
46 | #ifdef DEBUG | ||
47 | static unsigned int freq_debug; | ||
48 | module_param(freq_debug, uint, 0); | ||
49 | MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0"); | ||
50 | #else | ||
51 | #define freq_debug 0 | ||
52 | #endif | ||
53 | |||
54 | static struct regulator *vcc_core; | ||
55 | |||
56 | static unsigned int pxa27x_maxfreq; | ||
57 | module_param(pxa27x_maxfreq, uint, 0); | ||
58 | MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz" | ||
59 | "(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)"); | ||
60 | |||
61 | typedef struct { | ||
62 | unsigned int khz; | ||
63 | unsigned int membus; | ||
64 | unsigned int cccr; | ||
65 | unsigned int div2; | ||
66 | unsigned int cclkcfg; | ||
67 | int vmin; | ||
68 | int vmax; | ||
69 | } pxa_freqs_t; | ||
70 | |||
71 | /* Define the refresh period in mSec for the SDRAM and the number of rows */ | ||
72 | #define SDRAM_TREF 64 /* standard 64ms SDRAM */ | ||
73 | static unsigned int sdram_rows; | ||
74 | |||
75 | #define CCLKCFG_TURBO 0x1 | ||
76 | #define CCLKCFG_FCS 0x2 | ||
77 | #define CCLKCFG_HALFTURBO 0x4 | ||
78 | #define CCLKCFG_FASTBUS 0x8 | ||
79 | #define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) | ||
80 | #define MDREFR_DRI_MASK 0xFFF | ||
81 | |||
82 | #define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3) | ||
83 | #define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3) | ||
84 | |||
85 | /* | ||
86 | * PXA255 definitions | ||
87 | */ | ||
88 | /* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */ | ||
89 | #define CCLKCFG CCLKCFG_TURBO | CCLKCFG_FCS | ||
90 | |||
91 | static pxa_freqs_t pxa255_run_freqs[] = | ||
92 | { | ||
93 | /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ | ||
94 | { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ | ||
95 | {132700, 132700, 0x123, 1, CCLKCFG, -1, -1}, /* 133, 133, 66, 66 */ | ||
96 | {199100, 99500, 0x141, 0, CCLKCFG, -1, -1}, /* 199, 199, 99, 99 */ | ||
97 | {265400, 132700, 0x143, 1, CCLKCFG, -1, -1}, /* 265, 265, 133, 66 */ | ||
98 | {331800, 165900, 0x145, 1, CCLKCFG, -1, -1}, /* 331, 331, 166, 83 */ | ||
99 | {398100, 99500, 0x161, 0, CCLKCFG, -1, -1}, /* 398, 398, 196, 99 */ | ||
100 | }; | ||
101 | |||
102 | /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ | ||
103 | static pxa_freqs_t pxa255_turbo_freqs[] = | ||
104 | { | ||
105 | /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ | ||
106 | { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ | ||
107 | {199100, 99500, 0x221, 0, CCLKCFG, -1, -1}, /* 99, 199, 50, 99 */ | ||
108 | {298500, 99500, 0x321, 0, CCLKCFG, -1, -1}, /* 99, 287, 50, 99 */ | ||
109 | {298600, 99500, 0x1c1, 0, CCLKCFG, -1, -1}, /* 199, 287, 99, 99 */ | ||
110 | {398100, 99500, 0x241, 0, CCLKCFG, -1, -1}, /* 199, 398, 99, 99 */ | ||
111 | }; | ||
112 | |||
113 | #define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs) | ||
114 | #define NUM_PXA25x_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs) | ||
115 | |||
116 | static struct cpufreq_frequency_table | ||
117 | pxa255_run_freq_table[NUM_PXA25x_RUN_FREQS+1]; | ||
118 | static struct cpufreq_frequency_table | ||
119 | pxa255_turbo_freq_table[NUM_PXA25x_TURBO_FREQS+1]; | ||
120 | |||
121 | static unsigned int pxa255_turbo_table; | ||
122 | module_param(pxa255_turbo_table, uint, 0); | ||
123 | MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table, !0 = turbo table)"); | ||
124 | |||
125 | /* | ||
126 | * PXA270 definitions | ||
127 | * | ||
128 | * For the PXA27x: | ||
129 | * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG. | ||
130 | * | ||
131 | * A = 0 => memory controller clock from table 3-7, | ||
132 | * A = 1 => memory controller clock = system bus clock | ||
133 | * Run mode frequency = 13 MHz * L | ||
134 | * Turbo mode frequency = 13 MHz * L * N | ||
135 | * System bus frequency = 13 MHz * L / (B + 1) | ||
136 | * | ||
137 | * In CCCR: | ||
138 | * A = 1 | ||
139 | * L = 16 oscillator to run mode ratio | ||
140 | * 2N = 6 2 * (turbo mode to run mode ratio) | ||
141 | * | ||
142 | * In CCLKCFG: | ||
143 | * B = 1 Fast bus mode | ||
144 | * HT = 0 Half-Turbo mode | ||
145 | * T = 1 Turbo mode | ||
146 | * | ||
147 | * For now, just support some of the combinations in table 3-7 of | ||
148 | * PXA27x Processor Family Developer's Manual to simplify frequency | ||
149 | * change sequences. | ||
150 | */ | ||
151 | #define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L) | ||
152 | #define CCLKCFG2(B, HT, T) \ | ||
153 | (CCLKCFG_FCS | \ | ||
154 | ((B) ? CCLKCFG_FASTBUS : 0) | \ | ||
155 | ((HT) ? CCLKCFG_HALFTURBO : 0) | \ | ||
156 | ((T) ? CCLKCFG_TURBO : 0)) | ||
157 | |||
158 | static pxa_freqs_t pxa27x_freqs[] = { | ||
159 | {104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1), 900000, 1705000 }, | ||
160 | {156000, 104000, PXA27x_CCCR(1, 8, 3), 0, CCLKCFG2(1, 0, 1), 1000000, 1705000 }, | ||
161 | {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 }, | ||
162 | {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 }, | ||
163 | {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 }, | ||
164 | {520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1), 1450000, 1705000 }, | ||
165 | {624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1), 1550000, 1705000 } | ||
166 | }; | ||
167 | |||
168 | #define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs) | ||
169 | static struct cpufreq_frequency_table | ||
170 | pxa27x_freq_table[NUM_PXA27x_FREQS+1]; | ||
171 | |||
172 | extern unsigned get_clk_frequency_khz(int info); | ||
173 | |||
174 | #ifdef CONFIG_REGULATOR | ||
175 | |||
176 | static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq) | ||
177 | { | ||
178 | int ret = 0; | ||
179 | int vmin, vmax; | ||
180 | |||
181 | if (!cpu_is_pxa27x()) | ||
182 | return 0; | ||
183 | |||
184 | vmin = pxa_freq->vmin; | ||
185 | vmax = pxa_freq->vmax; | ||
186 | if ((vmin == -1) || (vmax == -1)) | ||
187 | return 0; | ||
188 | |||
189 | ret = regulator_set_voltage(vcc_core, vmin, vmax); | ||
190 | if (ret) | ||
191 | pr_err("cpufreq: Failed to set vcc_core in [%dmV..%dmV]\n", | ||
192 | vmin, vmax); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static __init void pxa_cpufreq_init_voltages(void) | ||
197 | { | ||
198 | vcc_core = regulator_get(NULL, "vcc_core"); | ||
199 | if (IS_ERR(vcc_core)) { | ||
200 | pr_info("cpufreq: Didn't find vcc_core regulator\n"); | ||
201 | vcc_core = NULL; | ||
202 | } else { | ||
203 | pr_info("cpufreq: Found vcc_core regulator\n"); | ||
204 | } | ||
205 | } | ||
206 | #else | ||
207 | static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq) | ||
208 | { | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static __init void pxa_cpufreq_init_voltages(void) { } | ||
213 | #endif | ||
214 | |||
215 | static void find_freq_tables(struct cpufreq_frequency_table **freq_table, | ||
216 | pxa_freqs_t **pxa_freqs) | ||
217 | { | ||
218 | if (cpu_is_pxa25x()) { | ||
219 | if (!pxa255_turbo_table) { | ||
220 | *pxa_freqs = pxa255_run_freqs; | ||
221 | *freq_table = pxa255_run_freq_table; | ||
222 | } else { | ||
223 | *pxa_freqs = pxa255_turbo_freqs; | ||
224 | *freq_table = pxa255_turbo_freq_table; | ||
225 | } | ||
226 | } | ||
227 | if (cpu_is_pxa27x()) { | ||
228 | *pxa_freqs = pxa27x_freqs; | ||
229 | *freq_table = pxa27x_freq_table; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | static void pxa27x_guess_max_freq(void) | ||
234 | { | ||
235 | if (!pxa27x_maxfreq) { | ||
236 | pxa27x_maxfreq = 416000; | ||
237 | printk(KERN_INFO "PXA CPU 27x max frequency not defined " | ||
238 | "(pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n", | ||
239 | pxa27x_maxfreq); | ||
240 | } else { | ||
241 | pxa27x_maxfreq *= 1000; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | static void init_sdram_rows(void) | ||
246 | { | ||
247 | uint32_t mdcnfg = __raw_readl(MDCNFG); | ||
248 | unsigned int drac2 = 0, drac0 = 0; | ||
249 | |||
250 | if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3)) | ||
251 | drac2 = MDCNFG_DRAC2(mdcnfg); | ||
252 | |||
253 | if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1)) | ||
254 | drac0 = MDCNFG_DRAC0(mdcnfg); | ||
255 | |||
256 | sdram_rows = 1 << (11 + max(drac0, drac2)); | ||
257 | } | ||
258 | |||
259 | static u32 mdrefr_dri(unsigned int freq) | ||
260 | { | ||
261 | u32 interval = freq * SDRAM_TREF / sdram_rows; | ||
262 | |||
263 | return (interval - (cpu_is_pxa27x() ? 31 : 0)) / 32; | ||
264 | } | ||
265 | |||
266 | /* find a valid frequency point */ | ||
267 | static int pxa_verify_policy(struct cpufreq_policy *policy) | ||
268 | { | ||
269 | struct cpufreq_frequency_table *pxa_freqs_table; | ||
270 | pxa_freqs_t *pxa_freqs; | ||
271 | int ret; | ||
272 | |||
273 | find_freq_tables(&pxa_freqs_table, &pxa_freqs); | ||
274 | ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table); | ||
275 | |||
276 | if (freq_debug) | ||
277 | pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n", | ||
278 | policy->min, policy->max); | ||
279 | |||
280 | return ret; | ||
281 | } | ||
282 | |||
283 | static unsigned int pxa_cpufreq_get(unsigned int cpu) | ||
284 | { | ||
285 | return get_clk_frequency_khz(0); | ||
286 | } | ||
287 | |||
288 | static int pxa_set_target(struct cpufreq_policy *policy, | ||
289 | unsigned int target_freq, | ||
290 | unsigned int relation) | ||
291 | { | ||
292 | struct cpufreq_frequency_table *pxa_freqs_table; | ||
293 | pxa_freqs_t *pxa_freq_settings; | ||
294 | struct cpufreq_freqs freqs; | ||
295 | unsigned int idx; | ||
296 | unsigned long flags; | ||
297 | unsigned int new_freq_cpu, new_freq_mem; | ||
298 | unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; | ||
299 | int ret = 0; | ||
300 | |||
301 | /* Get the current policy */ | ||
302 | find_freq_tables(&pxa_freqs_table, &pxa_freq_settings); | ||
303 | |||
304 | /* Lookup the next frequency */ | ||
305 | if (cpufreq_frequency_table_target(policy, pxa_freqs_table, | ||
306 | target_freq, relation, &idx)) { | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | |||
310 | new_freq_cpu = pxa_freq_settings[idx].khz; | ||
311 | new_freq_mem = pxa_freq_settings[idx].membus; | ||
312 | freqs.old = policy->cur; | ||
313 | freqs.new = new_freq_cpu; | ||
314 | freqs.cpu = policy->cpu; | ||
315 | |||
316 | if (freq_debug) | ||
317 | pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", | ||
318 | freqs.new / 1000, (pxa_freq_settings[idx].div2) ? | ||
319 | (new_freq_mem / 2000) : (new_freq_mem / 1000)); | ||
320 | |||
321 | if (vcc_core && freqs.new > freqs.old) | ||
322 | ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); | ||
323 | if (ret) | ||
324 | return ret; | ||
325 | /* | ||
326 | * Tell everyone what we're about to do... | ||
327 | * you should add a notify client with any platform specific | ||
328 | * Vcc changing capability | ||
329 | */ | ||
330 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
331 | |||
332 | /* Calculate the next MDREFR. If we're slowing down the SDRAM clock | ||
333 | * we need to preset the smaller DRI before the change. If we're | ||
334 | * speeding up we need to set the larger DRI value after the change. | ||
335 | */ | ||
336 | preset_mdrefr = postset_mdrefr = __raw_readl(MDREFR); | ||
337 | if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) { | ||
338 | preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK); | ||
339 | preset_mdrefr |= mdrefr_dri(new_freq_mem); | ||
340 | } | ||
341 | postset_mdrefr = | ||
342 | (postset_mdrefr & ~MDREFR_DRI_MASK) | mdrefr_dri(new_freq_mem); | ||
343 | |||
344 | /* If we're dividing the memory clock by two for the SDRAM clock, this | ||
345 | * must be set prior to the change. Clearing the divide must be done | ||
346 | * after the change. | ||
347 | */ | ||
348 | if (pxa_freq_settings[idx].div2) { | ||
349 | preset_mdrefr |= MDREFR_DB2_MASK; | ||
350 | postset_mdrefr |= MDREFR_DB2_MASK; | ||
351 | } else { | ||
352 | postset_mdrefr &= ~MDREFR_DB2_MASK; | ||
353 | } | ||
354 | |||
355 | local_irq_save(flags); | ||
356 | |||
357 | /* Set new the CCCR and prepare CCLKCFG */ | ||
358 | CCCR = pxa_freq_settings[idx].cccr; | ||
359 | cclkcfg = pxa_freq_settings[idx].cclkcfg; | ||
360 | |||
361 | asm volatile(" \n\ | ||
362 | ldr r4, [%1] /* load MDREFR */ \n\ | ||
363 | b 2f \n\ | ||
364 | .align 5 \n\ | ||
365 | 1: \n\ | ||
366 | str %3, [%1] /* preset the MDREFR */ \n\ | ||
367 | mcr p14, 0, %2, c6, c0, 0 /* set CCLKCFG[FCS] */ \n\ | ||
368 | str %4, [%1] /* postset the MDREFR */ \n\ | ||
369 | \n\ | ||
370 | b 3f \n\ | ||
371 | 2: b 1b \n\ | ||
372 | 3: nop \n\ | ||
373 | " | ||
374 | : "=&r" (unused) | ||
375 | : "r" (MDREFR), "r" (cclkcfg), | ||
376 | "r" (preset_mdrefr), "r" (postset_mdrefr) | ||
377 | : "r4", "r5"); | ||
378 | local_irq_restore(flags); | ||
379 | |||
380 | /* | ||
381 | * Tell everyone what we've just done... | ||
382 | * you should add a notify client with any platform specific | ||
383 | * SDRAM refresh timer adjustments | ||
384 | */ | ||
385 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
386 | |||
387 | /* | ||
388 | * Even if voltage setting fails, we don't report it, as the frequency | ||
389 | * change succeeded. The voltage reduction is not a critical failure, | ||
390 | * only power savings will suffer from this. | ||
391 | * | ||
392 | * Note: if the voltage change fails, and a return value is returned, a | ||
393 | * bug is triggered (seems a deadlock). Should anybody find out where, | ||
394 | * the "return 0" should become a "return ret". | ||
395 | */ | ||
396 | if (vcc_core && freqs.new < freqs.old) | ||
397 | ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int pxa_cpufreq_init(struct cpufreq_policy *policy) | ||
403 | { | ||
404 | int i; | ||
405 | unsigned int freq; | ||
406 | struct cpufreq_frequency_table *pxa255_freq_table; | ||
407 | pxa_freqs_t *pxa255_freqs; | ||
408 | |||
409 | /* try to guess pxa27x cpu */ | ||
410 | if (cpu_is_pxa27x()) | ||
411 | pxa27x_guess_max_freq(); | ||
412 | |||
413 | pxa_cpufreq_init_voltages(); | ||
414 | |||
415 | init_sdram_rows(); | ||
416 | |||
417 | /* set default policy and cpuinfo */ | ||
418 | policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ | ||
419 | policy->cur = get_clk_frequency_khz(0); /* current freq */ | ||
420 | policy->min = policy->max = policy->cur; | ||
421 | |||
422 | /* Generate pxa25x the run cpufreq_frequency_table struct */ | ||
423 | for (i = 0; i < NUM_PXA25x_RUN_FREQS; i++) { | ||
424 | pxa255_run_freq_table[i].frequency = pxa255_run_freqs[i].khz; | ||
425 | pxa255_run_freq_table[i].index = i; | ||
426 | } | ||
427 | pxa255_run_freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
428 | |||
429 | /* Generate pxa25x the turbo cpufreq_frequency_table struct */ | ||
430 | for (i = 0; i < NUM_PXA25x_TURBO_FREQS; i++) { | ||
431 | pxa255_turbo_freq_table[i].frequency = | ||
432 | pxa255_turbo_freqs[i].khz; | ||
433 | pxa255_turbo_freq_table[i].index = i; | ||
434 | } | ||
435 | pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
436 | |||
437 | pxa255_turbo_table = !!pxa255_turbo_table; | ||
438 | |||
439 | /* Generate the pxa27x cpufreq_frequency_table struct */ | ||
440 | for (i = 0; i < NUM_PXA27x_FREQS; i++) { | ||
441 | freq = pxa27x_freqs[i].khz; | ||
442 | if (freq > pxa27x_maxfreq) | ||
443 | break; | ||
444 | pxa27x_freq_table[i].frequency = freq; | ||
445 | pxa27x_freq_table[i].index = i; | ||
446 | } | ||
447 | pxa27x_freq_table[i].index = i; | ||
448 | pxa27x_freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
449 | |||
450 | /* | ||
451 | * Set the policy's minimum and maximum frequencies from the tables | ||
452 | * just constructed. This sets cpuinfo.mxx_freq, min and max. | ||
453 | */ | ||
454 | if (cpu_is_pxa25x()) { | ||
455 | find_freq_tables(&pxa255_freq_table, &pxa255_freqs); | ||
456 | pr_info("PXA255 cpufreq using %s frequency table\n", | ||
457 | pxa255_turbo_table ? "turbo" : "run"); | ||
458 | cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table); | ||
459 | } | ||
460 | else if (cpu_is_pxa27x()) | ||
461 | cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table); | ||
462 | |||
463 | printk(KERN_INFO "PXA CPU frequency change support initialized\n"); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static struct cpufreq_driver pxa_cpufreq_driver = { | ||
469 | .verify = pxa_verify_policy, | ||
470 | .target = pxa_set_target, | ||
471 | .init = pxa_cpufreq_init, | ||
472 | .get = pxa_cpufreq_get, | ||
473 | .name = "PXA2xx", | ||
474 | }; | ||
475 | |||
476 | static int __init pxa_cpu_init(void) | ||
477 | { | ||
478 | int ret = -ENODEV; | ||
479 | if (cpu_is_pxa25x() || cpu_is_pxa27x()) | ||
480 | ret = cpufreq_register_driver(&pxa_cpufreq_driver); | ||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | static void __exit pxa_cpu_exit(void) | ||
485 | { | ||
486 | cpufreq_unregister_driver(&pxa_cpufreq_driver); | ||
487 | } | ||
488 | |||
489 | |||
490 | MODULE_AUTHOR("Intrinsyc Software Inc."); | ||
491 | MODULE_DESCRIPTION("CPU frequency changing driver for the PXA architecture"); | ||
492 | MODULE_LICENSE("GPL"); | ||
493 | module_init(pxa_cpu_init); | ||
494 | module_exit(pxa_cpu_exit); | ||
diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c deleted file mode 100644 index b85b4ab7aac6..000000000000 --- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c +++ /dev/null | |||
@@ -1,258 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-pxa/cpufreq-pxa3xx.c | ||
3 | * | ||
4 | * Copyright (C) 2008 Marvell International Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/cpufreq.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
20 | #include <mach/pxa3xx-regs.h> | ||
21 | |||
22 | #include "generic.h" | ||
23 | |||
24 | #define HSS_104M (0) | ||
25 | #define HSS_156M (1) | ||
26 | #define HSS_208M (2) | ||
27 | #define HSS_312M (3) | ||
28 | |||
29 | #define SMCFS_78M (0) | ||
30 | #define SMCFS_104M (2) | ||
31 | #define SMCFS_208M (5) | ||
32 | |||
33 | #define SFLFS_104M (0) | ||
34 | #define SFLFS_156M (1) | ||
35 | #define SFLFS_208M (2) | ||
36 | #define SFLFS_312M (3) | ||
37 | |||
38 | #define XSPCLK_156M (0) | ||
39 | #define XSPCLK_NONE (3) | ||
40 | |||
41 | #define DMCFS_26M (0) | ||
42 | #define DMCFS_260M (3) | ||
43 | |||
44 | struct pxa3xx_freq_info { | ||
45 | unsigned int cpufreq_mhz; | ||
46 | unsigned int core_xl : 5; | ||
47 | unsigned int core_xn : 3; | ||
48 | unsigned int hss : 2; | ||
49 | unsigned int dmcfs : 2; | ||
50 | unsigned int smcfs : 3; | ||
51 | unsigned int sflfs : 2; | ||
52 | unsigned int df_clkdiv : 3; | ||
53 | |||
54 | int vcc_core; /* in mV */ | ||
55 | int vcc_sram; /* in mV */ | ||
56 | }; | ||
57 | |||
58 | #define OP(cpufreq, _xl, _xn, _hss, _dmc, _smc, _sfl, _dfi, vcore, vsram) \ | ||
59 | { \ | ||
60 | .cpufreq_mhz = cpufreq, \ | ||
61 | .core_xl = _xl, \ | ||
62 | .core_xn = _xn, \ | ||
63 | .hss = HSS_##_hss##M, \ | ||
64 | .dmcfs = DMCFS_##_dmc##M, \ | ||
65 | .smcfs = SMCFS_##_smc##M, \ | ||
66 | .sflfs = SFLFS_##_sfl##M, \ | ||
67 | .df_clkdiv = _dfi, \ | ||
68 | .vcc_core = vcore, \ | ||
69 | .vcc_sram = vsram, \ | ||
70 | } | ||
71 | |||
72 | static struct pxa3xx_freq_info pxa300_freqs[] = { | ||
73 | /* CPU XL XN HSS DMEM SMEM SRAM DFI VCC_CORE VCC_SRAM */ | ||
74 | OP(104, 8, 1, 104, 260, 78, 104, 3, 1000, 1100), /* 104MHz */ | ||
75 | OP(208, 16, 1, 104, 260, 104, 156, 2, 1000, 1100), /* 208MHz */ | ||
76 | OP(416, 16, 2, 156, 260, 104, 208, 2, 1100, 1200), /* 416MHz */ | ||
77 | OP(624, 24, 2, 208, 260, 208, 312, 3, 1375, 1400), /* 624MHz */ | ||
78 | }; | ||
79 | |||
80 | static struct pxa3xx_freq_info pxa320_freqs[] = { | ||
81 | /* CPU XL XN HSS DMEM SMEM SRAM DFI VCC_CORE VCC_SRAM */ | ||
82 | OP(104, 8, 1, 104, 260, 78, 104, 3, 1000, 1100), /* 104MHz */ | ||
83 | OP(208, 16, 1, 104, 260, 104, 156, 2, 1000, 1100), /* 208MHz */ | ||
84 | OP(416, 16, 2, 156, 260, 104, 208, 2, 1100, 1200), /* 416MHz */ | ||
85 | OP(624, 24, 2, 208, 260, 208, 312, 3, 1375, 1400), /* 624MHz */ | ||
86 | OP(806, 31, 2, 208, 260, 208, 312, 3, 1400, 1400), /* 806MHz */ | ||
87 | }; | ||
88 | |||
89 | static unsigned int pxa3xx_freqs_num; | ||
90 | static struct pxa3xx_freq_info *pxa3xx_freqs; | ||
91 | static struct cpufreq_frequency_table *pxa3xx_freqs_table; | ||
92 | |||
93 | static int setup_freqs_table(struct cpufreq_policy *policy, | ||
94 | struct pxa3xx_freq_info *freqs, int num) | ||
95 | { | ||
96 | struct cpufreq_frequency_table *table; | ||
97 | int i; | ||
98 | |||
99 | table = kzalloc((num + 1) * sizeof(*table), GFP_KERNEL); | ||
100 | if (table == NULL) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | for (i = 0; i < num; i++) { | ||
104 | table[i].index = i; | ||
105 | table[i].frequency = freqs[i].cpufreq_mhz * 1000; | ||
106 | } | ||
107 | table[num].index = i; | ||
108 | table[num].frequency = CPUFREQ_TABLE_END; | ||
109 | |||
110 | pxa3xx_freqs = freqs; | ||
111 | pxa3xx_freqs_num = num; | ||
112 | pxa3xx_freqs_table = table; | ||
113 | |||
114 | return cpufreq_frequency_table_cpuinfo(policy, table); | ||
115 | } | ||
116 | |||
117 | static void __update_core_freq(struct pxa3xx_freq_info *info) | ||
118 | { | ||
119 | uint32_t mask = ACCR_XN_MASK | ACCR_XL_MASK; | ||
120 | uint32_t accr = ACCR; | ||
121 | uint32_t xclkcfg; | ||
122 | |||
123 | accr &= ~(ACCR_XN_MASK | ACCR_XL_MASK | ACCR_XSPCLK_MASK); | ||
124 | accr |= ACCR_XN(info->core_xn) | ACCR_XL(info->core_xl); | ||
125 | |||
126 | /* No clock until core PLL is re-locked */ | ||
127 | accr |= ACCR_XSPCLK(XSPCLK_NONE); | ||
128 | |||
129 | xclkcfg = (info->core_xn == 2) ? 0x3 : 0x2; /* turbo bit */ | ||
130 | |||
131 | ACCR = accr; | ||
132 | __asm__("mcr p14, 0, %0, c6, c0, 0\n" : : "r"(xclkcfg)); | ||
133 | |||
134 | while ((ACSR & mask) != (accr & mask)) | ||
135 | cpu_relax(); | ||
136 | } | ||
137 | |||
138 | static void __update_bus_freq(struct pxa3xx_freq_info *info) | ||
139 | { | ||
140 | uint32_t mask; | ||
141 | uint32_t accr = ACCR; | ||
142 | |||
143 | mask = ACCR_SMCFS_MASK | ACCR_SFLFS_MASK | ACCR_HSS_MASK | | ||
144 | ACCR_DMCFS_MASK; | ||
145 | |||
146 | accr &= ~mask; | ||
147 | accr |= ACCR_SMCFS(info->smcfs) | ACCR_SFLFS(info->sflfs) | | ||
148 | ACCR_HSS(info->hss) | ACCR_DMCFS(info->dmcfs); | ||
149 | |||
150 | ACCR = accr; | ||
151 | |||
152 | while ((ACSR & mask) != (accr & mask)) | ||
153 | cpu_relax(); | ||
154 | } | ||
155 | |||
156 | static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy) | ||
157 | { | ||
158 | return cpufreq_frequency_table_verify(policy, pxa3xx_freqs_table); | ||
159 | } | ||
160 | |||
161 | static unsigned int pxa3xx_cpufreq_get(unsigned int cpu) | ||
162 | { | ||
163 | return pxa3xx_get_clk_frequency_khz(0); | ||
164 | } | ||
165 | |||
166 | static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, | ||
167 | unsigned int target_freq, | ||
168 | unsigned int relation) | ||
169 | { | ||
170 | struct pxa3xx_freq_info *next; | ||
171 | struct cpufreq_freqs freqs; | ||
172 | unsigned long flags; | ||
173 | int idx; | ||
174 | |||
175 | if (policy->cpu != 0) | ||
176 | return -EINVAL; | ||
177 | |||
178 | /* Lookup the next frequency */ | ||
179 | if (cpufreq_frequency_table_target(policy, pxa3xx_freqs_table, | ||
180 | target_freq, relation, &idx)) | ||
181 | return -EINVAL; | ||
182 | |||
183 | next = &pxa3xx_freqs[idx]; | ||
184 | |||
185 | freqs.old = policy->cur; | ||
186 | freqs.new = next->cpufreq_mhz * 1000; | ||
187 | freqs.cpu = policy->cpu; | ||
188 | |||
189 | pr_debug("CPU frequency from %d MHz to %d MHz%s\n", | ||
190 | freqs.old / 1000, freqs.new / 1000, | ||
191 | (freqs.old == freqs.new) ? " (skipped)" : ""); | ||
192 | |||
193 | if (freqs.old == target_freq) | ||
194 | return 0; | ||
195 | |||
196 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
197 | |||
198 | local_irq_save(flags); | ||
199 | __update_core_freq(next); | ||
200 | __update_bus_freq(next); | ||
201 | local_irq_restore(flags); | ||
202 | |||
203 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) | ||
209 | { | ||
210 | int ret = -EINVAL; | ||
211 | |||
212 | /* set default policy and cpuinfo */ | ||
213 | policy->cpuinfo.min_freq = 104000; | ||
214 | policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000; | ||
215 | policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ | ||
216 | policy->max = pxa3xx_get_clk_frequency_khz(0); | ||
217 | policy->cur = policy->min = policy->max; | ||
218 | |||
219 | if (cpu_is_pxa300() || cpu_is_pxa310()) | ||
220 | ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs)); | ||
221 | |||
222 | if (cpu_is_pxa320()) | ||
223 | ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa320_freqs)); | ||
224 | |||
225 | if (ret) { | ||
226 | pr_err("failed to setup frequency table\n"); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | pr_info("CPUFREQ support for PXA3xx initialized\n"); | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static struct cpufreq_driver pxa3xx_cpufreq_driver = { | ||
235 | .verify = pxa3xx_cpufreq_verify, | ||
236 | .target = pxa3xx_cpufreq_set, | ||
237 | .init = pxa3xx_cpufreq_init, | ||
238 | .get = pxa3xx_cpufreq_get, | ||
239 | .name = "pxa3xx-cpufreq", | ||
240 | }; | ||
241 | |||
242 | static int __init cpufreq_init(void) | ||
243 | { | ||
244 | if (cpu_is_pxa3xx()) | ||
245 | return cpufreq_register_driver(&pxa3xx_cpufreq_driver); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | module_init(cpufreq_init); | ||
250 | |||
251 | static void __exit cpufreq_exit(void) | ||
252 | { | ||
253 | cpufreq_unregister_driver(&pxa3xx_cpufreq_driver); | ||
254 | } | ||
255 | module_exit(cpufreq_exit); | ||
256 | |||
257 | MODULE_DESCRIPTION("CPU frequency scaling driver for PXA3xx"); | ||
258 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/mach-pxa/include/mach/generic.h b/arch/arm/mach-pxa/include/mach/generic.h new file mode 100644 index 000000000000..665542e0c9e2 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/generic.h | |||
@@ -0,0 +1 @@ | |||
#include "../../generic.h" | |||
diff --git a/arch/arm/mach-s3c24xx/cpufreq.c b/arch/arm/mach-s3c24xx/cpufreq.c index 5f181e733eee..3c0e78ede0da 100644 --- a/arch/arm/mach-s3c24xx/cpufreq.c +++ b/arch/arm/mach-s3c24xx/cpufreq.c | |||
@@ -204,7 +204,6 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, | |||
204 | freqs.old = cpu_cur.freq; | 204 | freqs.old = cpu_cur.freq; |
205 | freqs.new = cpu_new.freq; | 205 | freqs.new = cpu_new.freq; |
206 | 206 | ||
207 | freqs.freqs.cpu = 0; | ||
208 | freqs.freqs.old = cpu_cur.freq.armclk / 1000; | 207 | freqs.freqs.old = cpu_cur.freq.armclk / 1000; |
209 | freqs.freqs.new = cpu_new.freq.armclk / 1000; | 208 | freqs.freqs.new = cpu_new.freq.armclk / 1000; |
210 | 209 | ||
@@ -218,9 +217,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, | |||
218 | s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk); | 217 | s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk); |
219 | 218 | ||
220 | /* start the frequency change */ | 219 | /* start the frequency change */ |
221 | 220 | cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_PRECHANGE); | |
222 | if (policy) | ||
223 | cpufreq_notify_transition(&freqs.freqs, CPUFREQ_PRECHANGE); | ||
224 | 221 | ||
225 | /* If hclk is staying the same, then we do not need to | 222 | /* If hclk is staying the same, then we do not need to |
226 | * re-write the IO or the refresh timings whilst we are changing | 223 | * re-write the IO or the refresh timings whilst we are changing |
@@ -264,8 +261,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, | |||
264 | local_irq_restore(flags); | 261 | local_irq_restore(flags); |
265 | 262 | ||
266 | /* notify everyone we've done this */ | 263 | /* notify everyone we've done this */ |
267 | if (policy) | 264 | cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_POSTCHANGE); |
268 | cpufreq_notify_transition(&freqs.freqs, CPUFREQ_POSTCHANGE); | ||
269 | 265 | ||
270 | s3c_freq_dbg("%s: finished\n", __func__); | 266 | s3c_freq_dbg("%s: finished\n", __func__); |
271 | return 0; | 267 | return 0; |
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index ca14dbdcfb22..04f9784ff0ed 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig | |||
@@ -4,7 +4,7 @@ menu "SA11x0 Implementations" | |||
4 | 4 | ||
5 | config SA1100_ASSABET | 5 | config SA1100_ASSABET |
6 | bool "Assabet" | 6 | bool "Assabet" |
7 | select CPU_FREQ_SA1110 | 7 | select ARM_SA1110_CPUFREQ |
8 | help | 8 | help |
9 | Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 | 9 | Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 |
10 | Microprocessor Development Board (also known as the Assabet). | 10 | Microprocessor Development Board (also known as the Assabet). |
@@ -20,7 +20,7 @@ config ASSABET_NEPONSET | |||
20 | 20 | ||
21 | config SA1100_CERF | 21 | config SA1100_CERF |
22 | bool "CerfBoard" | 22 | bool "CerfBoard" |
23 | select CPU_FREQ_SA1110 | 23 | select ARM_SA1110_CPUFREQ |
24 | help | 24 | help |
25 | The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued). | 25 | The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued). |
26 | More information is available at: | 26 | More information is available at: |
@@ -47,7 +47,7 @@ endchoice | |||
47 | 47 | ||
48 | config SA1100_COLLIE | 48 | config SA1100_COLLIE |
49 | bool "Sharp Zaurus SL5500" | 49 | bool "Sharp Zaurus SL5500" |
50 | # FIXME: select CPU_FREQ_SA11x0 | 50 | # FIXME: select ARM_SA11x0_CPUFREQ |
51 | select SHARP_LOCOMO | 51 | select SHARP_LOCOMO |
52 | select SHARP_PARAM | 52 | select SHARP_PARAM |
53 | select SHARP_SCOOP | 53 | select SHARP_SCOOP |
@@ -56,7 +56,7 @@ config SA1100_COLLIE | |||
56 | 56 | ||
57 | config SA1100_H3100 | 57 | config SA1100_H3100 |
58 | bool "Compaq iPAQ H3100" | 58 | bool "Compaq iPAQ H3100" |
59 | select CPU_FREQ_SA1110 | 59 | select ARM_SA1110_CPUFREQ |
60 | select HTC_EGPIO | 60 | select HTC_EGPIO |
61 | help | 61 | help |
62 | Say Y here if you intend to run this kernel on the Compaq iPAQ | 62 | Say Y here if you intend to run this kernel on the Compaq iPAQ |
@@ -67,7 +67,7 @@ config SA1100_H3100 | |||
67 | 67 | ||
68 | config SA1100_H3600 | 68 | config SA1100_H3600 |
69 | bool "Compaq iPAQ H3600/H3700" | 69 | bool "Compaq iPAQ H3600/H3700" |
70 | select CPU_FREQ_SA1110 | 70 | select ARM_SA1110_CPUFREQ |
71 | select HTC_EGPIO | 71 | select HTC_EGPIO |
72 | help | 72 | help |
73 | Say Y here if you intend to run this kernel on the Compaq iPAQ | 73 | Say Y here if you intend to run this kernel on the Compaq iPAQ |
@@ -78,7 +78,7 @@ config SA1100_H3600 | |||
78 | 78 | ||
79 | config SA1100_BADGE4 | 79 | config SA1100_BADGE4 |
80 | bool "HP Labs BadgePAD 4" | 80 | bool "HP Labs BadgePAD 4" |
81 | select CPU_FREQ_SA1100 | 81 | select ARM_SA1100_CPUFREQ |
82 | select SA1111 | 82 | select SA1111 |
83 | help | 83 | help |
84 | Say Y here if you want to build a kernel for the HP Laboratories | 84 | Say Y here if you want to build a kernel for the HP Laboratories |
@@ -86,7 +86,7 @@ config SA1100_BADGE4 | |||
86 | 86 | ||
87 | config SA1100_JORNADA720 | 87 | config SA1100_JORNADA720 |
88 | bool "HP Jornada 720" | 88 | bool "HP Jornada 720" |
89 | # FIXME: select CPU_FREQ_SA11x0 | 89 | # FIXME: select ARM_SA11x0_CPUFREQ |
90 | select SA1111 | 90 | select SA1111 |
91 | help | 91 | help |
92 | Say Y here if you want to build a kernel for the HP Jornada 720 | 92 | Say Y here if you want to build a kernel for the HP Jornada 720 |
@@ -105,14 +105,14 @@ config SA1100_JORNADA720_SSP | |||
105 | 105 | ||
106 | config SA1100_HACKKIT | 106 | config SA1100_HACKKIT |
107 | bool "HackKit Core CPU Board" | 107 | bool "HackKit Core CPU Board" |
108 | select CPU_FREQ_SA1100 | 108 | select ARM_SA1100_CPUFREQ |
109 | help | 109 | help |
110 | Say Y here to support the HackKit Core CPU Board | 110 | Say Y here to support the HackKit Core CPU Board |
111 | <http://hackkit.eletztrick.de>; | 111 | <http://hackkit.eletztrick.de>; |
112 | 112 | ||
113 | config SA1100_LART | 113 | config SA1100_LART |
114 | bool "LART" | 114 | bool "LART" |
115 | select CPU_FREQ_SA1100 | 115 | select ARM_SA1100_CPUFREQ |
116 | help | 116 | help |
117 | Say Y here if you are using the Linux Advanced Radio Terminal | 117 | Say Y here if you are using the Linux Advanced Radio Terminal |
118 | (also known as the LART). See <http://www.lartmaker.nl/> for | 118 | (also known as the LART). See <http://www.lartmaker.nl/> for |
@@ -120,7 +120,7 @@ config SA1100_LART | |||
120 | 120 | ||
121 | config SA1100_NANOENGINE | 121 | config SA1100_NANOENGINE |
122 | bool "nanoEngine" | 122 | bool "nanoEngine" |
123 | select CPU_FREQ_SA1110 | 123 | select ARM_SA1110_CPUFREQ |
124 | select PCI | 124 | select PCI |
125 | select PCI_NANOENGINE | 125 | select PCI_NANOENGINE |
126 | help | 126 | help |
@@ -130,7 +130,7 @@ config SA1100_NANOENGINE | |||
130 | 130 | ||
131 | config SA1100_PLEB | 131 | config SA1100_PLEB |
132 | bool "PLEB" | 132 | bool "PLEB" |
133 | select CPU_FREQ_SA1100 | 133 | select ARM_SA1100_CPUFREQ |
134 | help | 134 | help |
135 | Say Y here if you are using version 1 of the Portable Linux | 135 | Say Y here if you are using version 1 of the Portable Linux |
136 | Embedded Board (also known as PLEB). | 136 | Embedded Board (also known as PLEB). |
@@ -139,7 +139,7 @@ config SA1100_PLEB | |||
139 | 139 | ||
140 | config SA1100_SHANNON | 140 | config SA1100_SHANNON |
141 | bool "Shannon" | 141 | bool "Shannon" |
142 | select CPU_FREQ_SA1100 | 142 | select ARM_SA1100_CPUFREQ |
143 | help | 143 | help |
144 | The Shannon (also known as a Tuxscreen, and also as a IS2630) was a | 144 | The Shannon (also known as a Tuxscreen, and also as a IS2630) was a |
145 | limited edition webphone produced by Philips. The Shannon is a SA1100 | 145 | limited edition webphone produced by Philips. The Shannon is a SA1100 |
@@ -148,7 +148,7 @@ config SA1100_SHANNON | |||
148 | 148 | ||
149 | config SA1100_SIMPAD | 149 | config SA1100_SIMPAD |
150 | bool "Simpad" | 150 | bool "Simpad" |
151 | select CPU_FREQ_SA1110 | 151 | select ARM_SA1110_CPUFREQ |
152 | help | 152 | help |
153 | The SIEMENS webpad SIMpad is based on the StrongARM 1110. There | 153 | The SIEMENS webpad SIMpad is based on the StrongARM 1110. There |
154 | are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB | 154 | are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB |
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 1aed9e70465d..2732eef48966 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile | |||
@@ -8,9 +8,6 @@ obj-m := | |||
8 | obj-n := | 8 | obj-n := |
9 | obj- := | 9 | obj- := |
10 | 10 | ||
11 | obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o | ||
12 | obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o | ||
13 | |||
14 | # Specific board support | 11 | # Specific board support |
15 | obj-$(CONFIG_SA1100_ASSABET) += assabet.o | 12 | obj-$(CONFIG_SA1100_ASSABET) += assabet.o |
16 | obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o | 13 | obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o |
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c deleted file mode 100644 index e8f4d1e19233..000000000000 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ /dev/null | |||
@@ -1,249 +0,0 @@ | |||
1 | /* | ||
2 | * cpu-sa1100.c: clock scaling for the SA1100 | ||
3 | * | ||
4 | * Copyright (C) 2000 2001, The Delft University of Technology | ||
5 | * | ||
6 | * Authors: | ||
7 | * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version | ||
8 | * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl): | ||
9 | * - major rewrite for linux-2.3.99 | ||
10 | * - rewritten for the more generic power management scheme in | ||
11 | * linux-2.4.5-rmk1 | ||
12 | * | ||
13 | * This software has been developed while working on the LART | ||
14 | * computing board (http://www.lartmaker.nl/), which is | ||
15 | * sponsored by the Mobile Multi-media Communications | ||
16 | * (http://www.mobimedia.org/) and Ubiquitous Communications | ||
17 | * (http://www.ubicom.tudelft.nl/) projects. | ||
18 | * | ||
19 | * The authors can be reached at: | ||
20 | * | ||
21 | * Erik Mouw | ||
22 | * Information and Communication Theory Group | ||
23 | * Faculty of Information Technology and Systems | ||
24 | * Delft University of Technology | ||
25 | * P.O. Box 5031 | ||
26 | * 2600 GA Delft | ||
27 | * The Netherlands | ||
28 | * | ||
29 | * | ||
30 | * This program is free software; you can redistribute it and/or modify | ||
31 | * it under the terms of the GNU General Public License as published by | ||
32 | * the Free Software Foundation; either version 2 of the License, or | ||
33 | * (at your option) any later version. | ||
34 | * | ||
35 | * This program is distributed in the hope that it will be useful, | ||
36 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
37 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
38 | * GNU General Public License for more details. | ||
39 | * | ||
40 | * You should have received a copy of the GNU General Public License | ||
41 | * along with this program; if not, write to the Free Software | ||
42 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
43 | * | ||
44 | * | ||
45 | * Theory of operations | ||
46 | * ==================== | ||
47 | * | ||
48 | * Clock scaling can be used to lower the power consumption of the CPU | ||
49 | * core. This will give you a somewhat longer running time. | ||
50 | * | ||
51 | * The SA-1100 has a single register to change the core clock speed: | ||
52 | * | ||
53 | * PPCR 0x90020014 PLL config | ||
54 | * | ||
55 | * However, the DRAM timings are closely related to the core clock | ||
56 | * speed, so we need to change these, too. The used registers are: | ||
57 | * | ||
58 | * MDCNFG 0xA0000000 DRAM config | ||
59 | * MDCAS0 0xA0000004 Access waveform | ||
60 | * MDCAS1 0xA0000008 Access waveform | ||
61 | * MDCAS2 0xA000000C Access waveform | ||
62 | * | ||
63 | * Care must be taken to change the DRAM parameters the correct way, | ||
64 | * because otherwise the DRAM becomes unusable and the kernel will | ||
65 | * crash. | ||
66 | * | ||
67 | * The simple solution to avoid a kernel crash is to put the actual | ||
68 | * clock change in ROM and jump to that code from the kernel. The main | ||
69 | * disadvantage is that the ROM has to be modified, which is not | ||
70 | * possible on all SA-1100 platforms. Another disadvantage is that | ||
71 | * jumping to ROM makes clock switching unnecessary complicated. | ||
72 | * | ||
73 | * The idea behind this driver is that the memory configuration can be | ||
74 | * changed while running from DRAM (even with interrupts turned on!) | ||
75 | * as long as all re-configuration steps yield a valid DRAM | ||
76 | * configuration. The advantages are clear: it will run on all SA-1100 | ||
77 | * platforms, and the code is very simple. | ||
78 | * | ||
79 | * If you really want to understand what is going on in | ||
80 | * sa1100_update_dram_timings(), you'll have to read sections 8.2, | ||
81 | * 9.5.7.3, and 10.2 from the "Intel StrongARM SA-1100 Microprocessor | ||
82 | * Developers Manual" (available for free from Intel). | ||
83 | * | ||
84 | */ | ||
85 | |||
86 | #include <linux/kernel.h> | ||
87 | #include <linux/types.h> | ||
88 | #include <linux/init.h> | ||
89 | #include <linux/cpufreq.h> | ||
90 | #include <linux/io.h> | ||
91 | |||
92 | #include <asm/cputype.h> | ||
93 | |||
94 | #include <mach/hardware.h> | ||
95 | |||
96 | #include "generic.h" | ||
97 | |||
98 | struct sa1100_dram_regs { | ||
99 | int speed; | ||
100 | u32 mdcnfg; | ||
101 | u32 mdcas0; | ||
102 | u32 mdcas1; | ||
103 | u32 mdcas2; | ||
104 | }; | ||
105 | |||
106 | |||
107 | static struct cpufreq_driver sa1100_driver; | ||
108 | |||
109 | static struct sa1100_dram_regs sa1100_dram_settings[] = { | ||
110 | /*speed, mdcnfg, mdcas0, mdcas1, mdcas2, clock freq */ | ||
111 | { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 59.0 MHz */ | ||
112 | { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 73.7 MHz */ | ||
113 | { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 88.5 MHz */ | ||
114 | {103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */ | ||
115 | {118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */ | ||
116 | {132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */ | ||
117 | {147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */ | ||
118 | {162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */ | ||
119 | {176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */ | ||
120 | {191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */ | ||
121 | {206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */ | ||
122 | {221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */ | ||
123 | {235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */ | ||
124 | {250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */ | ||
125 | {265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */ | ||
126 | {280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */ | ||
127 | { 0, 0, 0, 0, 0 } /* last entry */ | ||
128 | }; | ||
129 | |||
130 | static void sa1100_update_dram_timings(int current_speed, int new_speed) | ||
131 | { | ||
132 | struct sa1100_dram_regs *settings = sa1100_dram_settings; | ||
133 | |||
134 | /* find speed */ | ||
135 | while (settings->speed != 0) { | ||
136 | if (new_speed == settings->speed) | ||
137 | break; | ||
138 | |||
139 | settings++; | ||
140 | } | ||
141 | |||
142 | if (settings->speed == 0) { | ||
143 | panic("%s: couldn't find dram setting for speed %d\n", | ||
144 | __func__, new_speed); | ||
145 | } | ||
146 | |||
147 | /* No risk, no fun: run with interrupts on! */ | ||
148 | if (new_speed > current_speed) { | ||
149 | /* We're going FASTER, so first relax the memory | ||
150 | * timings before changing the core frequency | ||
151 | */ | ||
152 | |||
153 | /* Half the memory access clock */ | ||
154 | MDCNFG |= MDCNFG_CDB2; | ||
155 | |||
156 | /* The order of these statements IS important, keep 8 | ||
157 | * pulses!! | ||
158 | */ | ||
159 | MDCAS2 = settings->mdcas2; | ||
160 | MDCAS1 = settings->mdcas1; | ||
161 | MDCAS0 = settings->mdcas0; | ||
162 | MDCNFG = settings->mdcnfg; | ||
163 | } else { | ||
164 | /* We're going SLOWER: first decrease the core | ||
165 | * frequency and then tighten the memory settings. | ||
166 | */ | ||
167 | |||
168 | /* Half the memory access clock */ | ||
169 | MDCNFG |= MDCNFG_CDB2; | ||
170 | |||
171 | /* The order of these statements IS important, keep 8 | ||
172 | * pulses!! | ||
173 | */ | ||
174 | MDCAS0 = settings->mdcas0; | ||
175 | MDCAS1 = settings->mdcas1; | ||
176 | MDCAS2 = settings->mdcas2; | ||
177 | MDCNFG = settings->mdcnfg; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | static int sa1100_target(struct cpufreq_policy *policy, | ||
182 | unsigned int target_freq, | ||
183 | unsigned int relation) | ||
184 | { | ||
185 | unsigned int cur = sa11x0_getspeed(0); | ||
186 | unsigned int new_ppcr; | ||
187 | struct cpufreq_freqs freqs; | ||
188 | |||
189 | new_ppcr = sa11x0_freq_to_ppcr(target_freq); | ||
190 | switch (relation) { | ||
191 | case CPUFREQ_RELATION_L: | ||
192 | if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) | ||
193 | new_ppcr--; | ||
194 | break; | ||
195 | case CPUFREQ_RELATION_H: | ||
196 | if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && | ||
197 | (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) | ||
198 | new_ppcr--; | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | freqs.old = cur; | ||
203 | freqs.new = sa11x0_ppcr_to_freq(new_ppcr); | ||
204 | freqs.cpu = 0; | ||
205 | |||
206 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
207 | |||
208 | if (freqs.new > cur) | ||
209 | sa1100_update_dram_timings(cur, freqs.new); | ||
210 | |||
211 | PPCR = new_ppcr; | ||
212 | |||
213 | if (freqs.new < cur) | ||
214 | sa1100_update_dram_timings(cur, freqs.new); | ||
215 | |||
216 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int __init sa1100_cpu_init(struct cpufreq_policy *policy) | ||
222 | { | ||
223 | if (policy->cpu != 0) | ||
224 | return -EINVAL; | ||
225 | policy->cur = policy->min = policy->max = sa11x0_getspeed(0); | ||
226 | policy->cpuinfo.min_freq = 59000; | ||
227 | policy->cpuinfo.max_freq = 287000; | ||
228 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static struct cpufreq_driver sa1100_driver __refdata = { | ||
233 | .flags = CPUFREQ_STICKY, | ||
234 | .verify = sa11x0_verify_speed, | ||
235 | .target = sa1100_target, | ||
236 | .get = sa11x0_getspeed, | ||
237 | .init = sa1100_cpu_init, | ||
238 | .name = "sa1100", | ||
239 | }; | ||
240 | |||
241 | static int __init sa1100_dram_init(void) | ||
242 | { | ||
243 | if (cpu_is_sa1100()) | ||
244 | return cpufreq_register_driver(&sa1100_driver); | ||
245 | else | ||
246 | return -ENODEV; | ||
247 | } | ||
248 | |||
249 | arch_initcall(sa1100_dram_init); | ||
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c deleted file mode 100644 index 48c45b0c92bb..000000000000 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ /dev/null | |||
@@ -1,408 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-sa1100/cpu-sa1110.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Note: there are two erratas that apply to the SA1110 here: | ||
11 | * 7 - SDRAM auto-power-up failure (rev A0) | ||
12 | * 13 - Corruption of internal register reads/writes following | ||
13 | * SDRAM reads (rev A0, B0, B1) | ||
14 | * | ||
15 | * We ignore rev. A0 and B0 devices; I don't think they're worth supporting. | ||
16 | * | ||
17 | * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type | ||
18 | */ | ||
19 | #include <linux/cpufreq.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/types.h> | ||
26 | |||
27 | #include <asm/cputype.h> | ||
28 | #include <asm/mach-types.h> | ||
29 | |||
30 | #include <mach/hardware.h> | ||
31 | |||
32 | #include "generic.h" | ||
33 | |||
34 | #undef DEBUG | ||
35 | |||
36 | struct sdram_params { | ||
37 | const char name[20]; | ||
38 | u_char rows; /* bits */ | ||
39 | u_char cas_latency; /* cycles */ | ||
40 | u_char tck; /* clock cycle time (ns) */ | ||
41 | u_char trcd; /* activate to r/w (ns) */ | ||
42 | u_char trp; /* precharge to activate (ns) */ | ||
43 | u_char twr; /* write recovery time (ns) */ | ||
44 | u_short refresh; /* refresh time for array (us) */ | ||
45 | }; | ||
46 | |||
47 | struct sdram_info { | ||
48 | u_int mdcnfg; | ||
49 | u_int mdrefr; | ||
50 | u_int mdcas[3]; | ||
51 | }; | ||
52 | |||
53 | static struct sdram_params sdram_tbl[] __initdata = { | ||
54 | { /* Toshiba TC59SM716 CL2 */ | ||
55 | .name = "TC59SM716-CL2", | ||
56 | .rows = 12, | ||
57 | .tck = 10, | ||
58 | .trcd = 20, | ||
59 | .trp = 20, | ||
60 | .twr = 10, | ||
61 | .refresh = 64000, | ||
62 | .cas_latency = 2, | ||
63 | }, { /* Toshiba TC59SM716 CL3 */ | ||
64 | .name = "TC59SM716-CL3", | ||
65 | .rows = 12, | ||
66 | .tck = 8, | ||
67 | .trcd = 20, | ||
68 | .trp = 20, | ||
69 | .twr = 8, | ||
70 | .refresh = 64000, | ||
71 | .cas_latency = 3, | ||
72 | }, { /* Samsung K4S641632D TC75 */ | ||
73 | .name = "K4S641632D", | ||
74 | .rows = 14, | ||
75 | .tck = 9, | ||
76 | .trcd = 27, | ||
77 | .trp = 20, | ||
78 | .twr = 9, | ||
79 | .refresh = 64000, | ||
80 | .cas_latency = 3, | ||
81 | }, { /* Samsung K4S281632B-1H */ | ||
82 | .name = "K4S281632B-1H", | ||
83 | .rows = 12, | ||
84 | .tck = 10, | ||
85 | .trp = 20, | ||
86 | .twr = 10, | ||
87 | .refresh = 64000, | ||
88 | .cas_latency = 3, | ||
89 | }, { /* Samsung KM416S4030CT */ | ||
90 | .name = "KM416S4030CT", | ||
91 | .rows = 13, | ||
92 | .tck = 8, | ||
93 | .trcd = 24, /* 3 CLKs */ | ||
94 | .trp = 24, /* 3 CLKs */ | ||
95 | .twr = 16, /* Trdl: 2 CLKs */ | ||
96 | .refresh = 64000, | ||
97 | .cas_latency = 3, | ||
98 | }, { /* Winbond W982516AH75L CL3 */ | ||
99 | .name = "W982516AH75L", | ||
100 | .rows = 16, | ||
101 | .tck = 8, | ||
102 | .trcd = 20, | ||
103 | .trp = 20, | ||
104 | .twr = 8, | ||
105 | .refresh = 64000, | ||
106 | .cas_latency = 3, | ||
107 | }, { /* Micron MT48LC8M16A2TG-75 */ | ||
108 | .name = "MT48LC8M16A2TG-75", | ||
109 | .rows = 12, | ||
110 | .tck = 8, | ||
111 | .trcd = 20, | ||
112 | .trp = 20, | ||
113 | .twr = 8, | ||
114 | .refresh = 64000, | ||
115 | .cas_latency = 3, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | static struct sdram_params sdram_params; | ||
120 | |||
121 | /* | ||
122 | * Given a period in ns and frequency in khz, calculate the number of | ||
123 | * cycles of frequency in period. Note that we round up to the next | ||
124 | * cycle, even if we are only slightly over. | ||
125 | */ | ||
126 | static inline u_int ns_to_cycles(u_int ns, u_int khz) | ||
127 | { | ||
128 | return (ns * khz + 999999) / 1000000; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * Create the MDCAS register bit pattern. | ||
133 | */ | ||
134 | static inline void set_mdcas(u_int *mdcas, int delayed, u_int rcd) | ||
135 | { | ||
136 | u_int shift; | ||
137 | |||
138 | rcd = 2 * rcd - 1; | ||
139 | shift = delayed + 1 + rcd; | ||
140 | |||
141 | mdcas[0] = (1 << rcd) - 1; | ||
142 | mdcas[0] |= 0x55555555 << shift; | ||
143 | mdcas[1] = mdcas[2] = 0x55555555 << (shift & 1); | ||
144 | } | ||
145 | |||
146 | static void | ||
147 | sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz, | ||
148 | struct sdram_params *sdram) | ||
149 | { | ||
150 | u_int mem_khz, sd_khz, trp, twr; | ||
151 | |||
152 | mem_khz = cpu_khz / 2; | ||
153 | sd_khz = mem_khz; | ||
154 | |||
155 | /* | ||
156 | * If SDCLK would invalidate the SDRAM timings, | ||
157 | * run SDCLK at half speed. | ||
158 | * | ||
159 | * CPU steppings prior to B2 must either run the memory at | ||
160 | * half speed or use delayed read latching (errata 13). | ||
161 | */ | ||
162 | if ((ns_to_cycles(sdram->tck, sd_khz) > 1) || | ||
163 | (CPU_REVISION < CPU_SA1110_B2 && sd_khz < 62000)) | ||
164 | sd_khz /= 2; | ||
165 | |||
166 | sd->mdcnfg = MDCNFG & 0x007f007f; | ||
167 | |||
168 | twr = ns_to_cycles(sdram->twr, mem_khz); | ||
169 | |||
170 | /* trp should always be >1 */ | ||
171 | trp = ns_to_cycles(sdram->trp, mem_khz) - 1; | ||
172 | if (trp < 1) | ||
173 | trp = 1; | ||
174 | |||
175 | sd->mdcnfg |= trp << 8; | ||
176 | sd->mdcnfg |= trp << 24; | ||
177 | sd->mdcnfg |= sdram->cas_latency << 12; | ||
178 | sd->mdcnfg |= sdram->cas_latency << 28; | ||
179 | sd->mdcnfg |= twr << 14; | ||
180 | sd->mdcnfg |= twr << 30; | ||
181 | |||
182 | sd->mdrefr = MDREFR & 0xffbffff0; | ||
183 | sd->mdrefr |= 7; | ||
184 | |||
185 | if (sd_khz != mem_khz) | ||
186 | sd->mdrefr |= MDREFR_K1DB2; | ||
187 | |||
188 | /* initial number of '1's in MDCAS + 1 */ | ||
189 | set_mdcas(sd->mdcas, sd_khz >= 62000, | ||
190 | ns_to_cycles(sdram->trcd, mem_khz)); | ||
191 | |||
192 | #ifdef DEBUG | ||
193 | printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n", | ||
194 | sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], | ||
195 | sd->mdcas[2]); | ||
196 | #endif | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * Set the SDRAM refresh rate. | ||
201 | */ | ||
202 | static inline void sdram_set_refresh(u_int dri) | ||
203 | { | ||
204 | MDREFR = (MDREFR & 0xffff000f) | (dri << 4); | ||
205 | (void) MDREFR; | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * Update the refresh period. We do this such that we always refresh | ||
210 | * the SDRAMs within their permissible period. The refresh period is | ||
211 | * always a multiple of the memory clock (fixed at cpu_clock / 2). | ||
212 | * | ||
213 | * FIXME: we don't currently take account of burst accesses here, | ||
214 | * but neither do Intels DM nor Angel. | ||
215 | */ | ||
216 | static void | ||
217 | sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram) | ||
218 | { | ||
219 | u_int ns_row = (sdram->refresh * 1000) >> sdram->rows; | ||
220 | u_int dri = ns_to_cycles(ns_row, cpu_khz / 2) / 32; | ||
221 | |||
222 | #ifdef DEBUG | ||
223 | mdelay(250); | ||
224 | printk(KERN_DEBUG "new dri value = %d\n", dri); | ||
225 | #endif | ||
226 | |||
227 | sdram_set_refresh(dri); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Ok, set the CPU frequency. | ||
232 | */ | ||
233 | static int sa1110_target(struct cpufreq_policy *policy, | ||
234 | unsigned int target_freq, | ||
235 | unsigned int relation) | ||
236 | { | ||
237 | struct sdram_params *sdram = &sdram_params; | ||
238 | struct cpufreq_freqs freqs; | ||
239 | struct sdram_info sd; | ||
240 | unsigned long flags; | ||
241 | unsigned int ppcr, unused; | ||
242 | |||
243 | switch (relation) { | ||
244 | case CPUFREQ_RELATION_L: | ||
245 | ppcr = sa11x0_freq_to_ppcr(target_freq); | ||
246 | if (sa11x0_ppcr_to_freq(ppcr) > policy->max) | ||
247 | ppcr--; | ||
248 | break; | ||
249 | case CPUFREQ_RELATION_H: | ||
250 | ppcr = sa11x0_freq_to_ppcr(target_freq); | ||
251 | if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) && | ||
252 | (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min)) | ||
253 | ppcr--; | ||
254 | break; | ||
255 | default: | ||
256 | return -EINVAL; | ||
257 | } | ||
258 | |||
259 | freqs.old = sa11x0_getspeed(0); | ||
260 | freqs.new = sa11x0_ppcr_to_freq(ppcr); | ||
261 | freqs.cpu = 0; | ||
262 | |||
263 | sdram_calculate_timing(&sd, freqs.new, sdram); | ||
264 | |||
265 | #if 0 | ||
266 | /* | ||
267 | * These values are wrong according to the SA1110 documentation | ||
268 | * and errata, but they seem to work. Need to get a storage | ||
269 | * scope on to the SDRAM signals to work out why. | ||
270 | */ | ||
271 | if (policy->max < 147500) { | ||
272 | sd.mdrefr |= MDREFR_K1DB2; | ||
273 | sd.mdcas[0] = 0xaaaaaa7f; | ||
274 | } else { | ||
275 | sd.mdrefr &= ~MDREFR_K1DB2; | ||
276 | sd.mdcas[0] = 0xaaaaaa9f; | ||
277 | } | ||
278 | sd.mdcas[1] = 0xaaaaaaaa; | ||
279 | sd.mdcas[2] = 0xaaaaaaaa; | ||
280 | #endif | ||
281 | |||
282 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
283 | |||
284 | /* | ||
285 | * The clock could be going away for some time. Set the SDRAMs | ||
286 | * to refresh rapidly (every 64 memory clock cycles). To get | ||
287 | * through the whole array, we need to wait 262144 mclk cycles. | ||
288 | * We wait 20ms to be safe. | ||
289 | */ | ||
290 | sdram_set_refresh(2); | ||
291 | if (!irqs_disabled()) | ||
292 | msleep(20); | ||
293 | else | ||
294 | mdelay(20); | ||
295 | |||
296 | /* | ||
297 | * Reprogram the DRAM timings with interrupts disabled, and | ||
298 | * ensure that we are doing this within a complete cache line. | ||
299 | * This means that we won't access SDRAM for the duration of | ||
300 | * the programming. | ||
301 | */ | ||
302 | local_irq_save(flags); | ||
303 | asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); | ||
304 | udelay(10); | ||
305 | __asm__ __volatile__("\n\ | ||
306 | b 2f \n\ | ||
307 | .align 5 \n\ | ||
308 | 1: str %3, [%1, #0] @ MDCNFG \n\ | ||
309 | str %4, [%1, #28] @ MDREFR \n\ | ||
310 | str %5, [%1, #4] @ MDCAS0 \n\ | ||
311 | str %6, [%1, #8] @ MDCAS1 \n\ | ||
312 | str %7, [%1, #12] @ MDCAS2 \n\ | ||
313 | str %8, [%2, #0] @ PPCR \n\ | ||
314 | ldr %0, [%1, #0] \n\ | ||
315 | b 3f \n\ | ||
316 | 2: b 1b \n\ | ||
317 | 3: nop \n\ | ||
318 | nop" | ||
319 | : "=&r" (unused) | ||
320 | : "r" (&MDCNFG), "r" (&PPCR), "0" (sd.mdcnfg), | ||
321 | "r" (sd.mdrefr), "r" (sd.mdcas[0]), | ||
322 | "r" (sd.mdcas[1]), "r" (sd.mdcas[2]), "r" (ppcr)); | ||
323 | local_irq_restore(flags); | ||
324 | |||
325 | /* | ||
326 | * Now, return the SDRAM refresh back to normal. | ||
327 | */ | ||
328 | sdram_update_refresh(freqs.new, sdram); | ||
329 | |||
330 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int __init sa1110_cpu_init(struct cpufreq_policy *policy) | ||
336 | { | ||
337 | if (policy->cpu != 0) | ||
338 | return -EINVAL; | ||
339 | policy->cur = policy->min = policy->max = sa11x0_getspeed(0); | ||
340 | policy->cpuinfo.min_freq = 59000; | ||
341 | policy->cpuinfo.max_freq = 287000; | ||
342 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | /* sa1110_driver needs __refdata because it must remain after init registers | ||
347 | * it with cpufreq_register_driver() */ | ||
348 | static struct cpufreq_driver sa1110_driver __refdata = { | ||
349 | .flags = CPUFREQ_STICKY, | ||
350 | .verify = sa11x0_verify_speed, | ||
351 | .target = sa1110_target, | ||
352 | .get = sa11x0_getspeed, | ||
353 | .init = sa1110_cpu_init, | ||
354 | .name = "sa1110", | ||
355 | }; | ||
356 | |||
357 | static struct sdram_params *sa1110_find_sdram(const char *name) | ||
358 | { | ||
359 | struct sdram_params *sdram; | ||
360 | |||
361 | for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); | ||
362 | sdram++) | ||
363 | if (strcmp(name, sdram->name) == 0) | ||
364 | return sdram; | ||
365 | |||
366 | return NULL; | ||
367 | } | ||
368 | |||
369 | static char sdram_name[16]; | ||
370 | |||
371 | static int __init sa1110_clk_init(void) | ||
372 | { | ||
373 | struct sdram_params *sdram; | ||
374 | const char *name = sdram_name; | ||
375 | |||
376 | if (!cpu_is_sa1110()) | ||
377 | return -ENODEV; | ||
378 | |||
379 | if (!name[0]) { | ||
380 | if (machine_is_assabet()) | ||
381 | name = "TC59SM716-CL3"; | ||
382 | if (machine_is_pt_system3()) | ||
383 | name = "K4S641632D"; | ||
384 | if (machine_is_h3100()) | ||
385 | name = "KM416S4030CT"; | ||
386 | if (machine_is_jornada720()) | ||
387 | name = "K4S281632B-1H"; | ||
388 | if (machine_is_nanoengine()) | ||
389 | name = "MT48LC8M16A2TG-75"; | ||
390 | } | ||
391 | |||
392 | sdram = sa1110_find_sdram(name); | ||
393 | if (sdram) { | ||
394 | printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d" | ||
395 | " twr: %d refresh: %d cas_latency: %d\n", | ||
396 | sdram->tck, sdram->trcd, sdram->trp, | ||
397 | sdram->twr, sdram->refresh, sdram->cas_latency); | ||
398 | |||
399 | memcpy(&sdram_params, sdram, sizeof(sdram_params)); | ||
400 | |||
401 | return cpufreq_register_driver(&sa1110_driver); | ||
402 | } | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | module_param_string(sdram, sdram_name, sizeof(sdram_name), 0); | ||
408 | arch_initcall(sa1110_clk_init); | ||
diff --git a/arch/arm/mach-sa1100/include/mach/generic.h b/arch/arm/mach-sa1100/include/mach/generic.h new file mode 100644 index 000000000000..665542e0c9e2 --- /dev/null +++ b/arch/arm/mach-sa1100/include/mach/generic.h | |||
@@ -0,0 +1 @@ | |||
#include "../../generic.h" | |||
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index f6b46ae2b7f8..09b578f9eb84 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile | |||
@@ -24,7 +24,6 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o | |||
24 | endif | 24 | endif |
25 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 25 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
26 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 26 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
27 | obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o | ||
28 | obj-$(CONFIG_TEGRA_PCI) += pcie.o | 27 | obj-$(CONFIG_TEGRA_PCI) += pcie.o |
29 | 28 | ||
30 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o | 29 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o |
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c deleted file mode 100644 index e3d6e15ff188..000000000000 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ /dev/null | |||
@@ -1,293 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/cpu-tegra.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation | ||
9 | * | ||
10 | * This software is licensed under the terms of the GNU General Public | ||
11 | * License version 2, as published by the Free Software Foundation, and | ||
12 | * may be copied, distributed, and modified under those terms. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/cpufreq.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/clk.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <linux/suspend.h> | ||
32 | |||
33 | /* Frequency table index must be sequential starting at 0 */ | ||
34 | static struct cpufreq_frequency_table freq_table[] = { | ||
35 | { 0, 216000 }, | ||
36 | { 1, 312000 }, | ||
37 | { 2, 456000 }, | ||
38 | { 3, 608000 }, | ||
39 | { 4, 760000 }, | ||
40 | { 5, 816000 }, | ||
41 | { 6, 912000 }, | ||
42 | { 7, 1000000 }, | ||
43 | { 8, CPUFREQ_TABLE_END }, | ||
44 | }; | ||
45 | |||
46 | #define NUM_CPUS 2 | ||
47 | |||
48 | static struct clk *cpu_clk; | ||
49 | static struct clk *pll_x_clk; | ||
50 | static struct clk *pll_p_clk; | ||
51 | static struct clk *emc_clk; | ||
52 | |||
53 | static unsigned long target_cpu_speed[NUM_CPUS]; | ||
54 | static DEFINE_MUTEX(tegra_cpu_lock); | ||
55 | static bool is_suspended; | ||
56 | |||
57 | static int tegra_verify_speed(struct cpufreq_policy *policy) | ||
58 | { | ||
59 | return cpufreq_frequency_table_verify(policy, freq_table); | ||
60 | } | ||
61 | |||
62 | static unsigned int tegra_getspeed(unsigned int cpu) | ||
63 | { | ||
64 | unsigned long rate; | ||
65 | |||
66 | if (cpu >= NUM_CPUS) | ||
67 | return 0; | ||
68 | |||
69 | rate = clk_get_rate(cpu_clk) / 1000; | ||
70 | return rate; | ||
71 | } | ||
72 | |||
73 | static int tegra_cpu_clk_set_rate(unsigned long rate) | ||
74 | { | ||
75 | int ret; | ||
76 | |||
77 | /* | ||
78 | * Take an extra reference to the main pll so it doesn't turn | ||
79 | * off when we move the cpu off of it | ||
80 | */ | ||
81 | clk_prepare_enable(pll_x_clk); | ||
82 | |||
83 | ret = clk_set_parent(cpu_clk, pll_p_clk); | ||
84 | if (ret) { | ||
85 | pr_err("Failed to switch cpu to clock pll_p\n"); | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | if (rate == clk_get_rate(pll_p_clk)) | ||
90 | goto out; | ||
91 | |||
92 | ret = clk_set_rate(pll_x_clk, rate); | ||
93 | if (ret) { | ||
94 | pr_err("Failed to change pll_x to %lu\n", rate); | ||
95 | goto out; | ||
96 | } | ||
97 | |||
98 | ret = clk_set_parent(cpu_clk, pll_x_clk); | ||
99 | if (ret) { | ||
100 | pr_err("Failed to switch cpu to clock pll_x\n"); | ||
101 | goto out; | ||
102 | } | ||
103 | |||
104 | out: | ||
105 | clk_disable_unprepare(pll_x_clk); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static int tegra_update_cpu_speed(unsigned long rate) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | struct cpufreq_freqs freqs; | ||
113 | |||
114 | freqs.old = tegra_getspeed(0); | ||
115 | freqs.new = rate; | ||
116 | |||
117 | if (freqs.old == freqs.new) | ||
118 | return ret; | ||
119 | |||
120 | /* | ||
121 | * Vote on memory bus frequency based on cpu frequency | ||
122 | * This sets the minimum frequency, display or avp may request higher | ||
123 | */ | ||
124 | if (rate >= 816000) | ||
125 | clk_set_rate(emc_clk, 600000000); /* cpu 816 MHz, emc max */ | ||
126 | else if (rate >= 456000) | ||
127 | clk_set_rate(emc_clk, 300000000); /* cpu 456 MHz, emc 150Mhz */ | ||
128 | else | ||
129 | clk_set_rate(emc_clk, 100000000); /* emc 50Mhz */ | ||
130 | |||
131 | for_each_online_cpu(freqs.cpu) | ||
132 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
133 | |||
134 | #ifdef CONFIG_CPU_FREQ_DEBUG | ||
135 | printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n", | ||
136 | freqs.old, freqs.new); | ||
137 | #endif | ||
138 | |||
139 | ret = tegra_cpu_clk_set_rate(freqs.new * 1000); | ||
140 | if (ret) { | ||
141 | pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", | ||
142 | freqs.new); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | for_each_online_cpu(freqs.cpu) | ||
147 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static unsigned long tegra_cpu_highest_speed(void) | ||
153 | { | ||
154 | unsigned long rate = 0; | ||
155 | int i; | ||
156 | |||
157 | for_each_online_cpu(i) | ||
158 | rate = max(rate, target_cpu_speed[i]); | ||
159 | return rate; | ||
160 | } | ||
161 | |||
162 | static int tegra_target(struct cpufreq_policy *policy, | ||
163 | unsigned int target_freq, | ||
164 | unsigned int relation) | ||
165 | { | ||
166 | unsigned int idx; | ||
167 | unsigned int freq; | ||
168 | int ret = 0; | ||
169 | |||
170 | mutex_lock(&tegra_cpu_lock); | ||
171 | |||
172 | if (is_suspended) { | ||
173 | ret = -EBUSY; | ||
174 | goto out; | ||
175 | } | ||
176 | |||
177 | cpufreq_frequency_table_target(policy, freq_table, target_freq, | ||
178 | relation, &idx); | ||
179 | |||
180 | freq = freq_table[idx].frequency; | ||
181 | |||
182 | target_cpu_speed[policy->cpu] = freq; | ||
183 | |||
184 | ret = tegra_update_cpu_speed(tegra_cpu_highest_speed()); | ||
185 | |||
186 | out: | ||
187 | mutex_unlock(&tegra_cpu_lock); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static int tegra_pm_notify(struct notifier_block *nb, unsigned long event, | ||
192 | void *dummy) | ||
193 | { | ||
194 | mutex_lock(&tegra_cpu_lock); | ||
195 | if (event == PM_SUSPEND_PREPARE) { | ||
196 | is_suspended = true; | ||
197 | pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n", | ||
198 | freq_table[0].frequency); | ||
199 | tegra_update_cpu_speed(freq_table[0].frequency); | ||
200 | } else if (event == PM_POST_SUSPEND) { | ||
201 | is_suspended = false; | ||
202 | } | ||
203 | mutex_unlock(&tegra_cpu_lock); | ||
204 | |||
205 | return NOTIFY_OK; | ||
206 | } | ||
207 | |||
208 | static struct notifier_block tegra_cpu_pm_notifier = { | ||
209 | .notifier_call = tegra_pm_notify, | ||
210 | }; | ||
211 | |||
212 | static int tegra_cpu_init(struct cpufreq_policy *policy) | ||
213 | { | ||
214 | if (policy->cpu >= NUM_CPUS) | ||
215 | return -EINVAL; | ||
216 | |||
217 | clk_prepare_enable(emc_clk); | ||
218 | clk_prepare_enable(cpu_clk); | ||
219 | |||
220 | cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
221 | cpufreq_frequency_table_get_attr(freq_table, policy->cpu); | ||
222 | policy->cur = tegra_getspeed(policy->cpu); | ||
223 | target_cpu_speed[policy->cpu] = policy->cur; | ||
224 | |||
225 | /* FIXME: what's the actual transition time? */ | ||
226 | policy->cpuinfo.transition_latency = 300 * 1000; | ||
227 | |||
228 | cpumask_copy(policy->cpus, cpu_possible_mask); | ||
229 | |||
230 | if (policy->cpu == 0) | ||
231 | register_pm_notifier(&tegra_cpu_pm_notifier); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int tegra_cpu_exit(struct cpufreq_policy *policy) | ||
237 | { | ||
238 | cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
239 | clk_disable_unprepare(emc_clk); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static struct freq_attr *tegra_cpufreq_attr[] = { | ||
244 | &cpufreq_freq_attr_scaling_available_freqs, | ||
245 | NULL, | ||
246 | }; | ||
247 | |||
248 | static struct cpufreq_driver tegra_cpufreq_driver = { | ||
249 | .verify = tegra_verify_speed, | ||
250 | .target = tegra_target, | ||
251 | .get = tegra_getspeed, | ||
252 | .init = tegra_cpu_init, | ||
253 | .exit = tegra_cpu_exit, | ||
254 | .name = "tegra", | ||
255 | .attr = tegra_cpufreq_attr, | ||
256 | }; | ||
257 | |||
258 | static int __init tegra_cpufreq_init(void) | ||
259 | { | ||
260 | cpu_clk = clk_get_sys(NULL, "cpu"); | ||
261 | if (IS_ERR(cpu_clk)) | ||
262 | return PTR_ERR(cpu_clk); | ||
263 | |||
264 | pll_x_clk = clk_get_sys(NULL, "pll_x"); | ||
265 | if (IS_ERR(pll_x_clk)) | ||
266 | return PTR_ERR(pll_x_clk); | ||
267 | |||
268 | pll_p_clk = clk_get_sys(NULL, "pll_p_cclk"); | ||
269 | if (IS_ERR(pll_p_clk)) | ||
270 | return PTR_ERR(pll_p_clk); | ||
271 | |||
272 | emc_clk = clk_get_sys("cpu", "emc"); | ||
273 | if (IS_ERR(emc_clk)) { | ||
274 | clk_put(cpu_clk); | ||
275 | return PTR_ERR(emc_clk); | ||
276 | } | ||
277 | |||
278 | return cpufreq_register_driver(&tegra_cpufreq_driver); | ||
279 | } | ||
280 | |||
281 | static void __exit tegra_cpufreq_exit(void) | ||
282 | { | ||
283 | cpufreq_unregister_driver(&tegra_cpufreq_driver); | ||
284 | clk_put(emc_clk); | ||
285 | clk_put(cpu_clk); | ||
286 | } | ||
287 | |||
288 | |||
289 | MODULE_AUTHOR("Colin Cross <ccross@android.com>"); | ||
290 | MODULE_DESCRIPTION("cpufreq driver for Nvidia Tegra2"); | ||
291 | MODULE_LICENSE("GPL"); | ||
292 | module_init(tegra_cpufreq_init); | ||
293 | module_exit(tegra_cpufreq_exit); | ||
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index c1a868d398bd..22c40308360b 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
@@ -250,20 +250,7 @@ config ARCH_SUSPEND_POSSIBLE | |||
250 | def_bool y | 250 | def_bool y |
251 | 251 | ||
252 | menu "CPU Frequency scaling" | 252 | menu "CPU Frequency scaling" |
253 | |||
254 | source "drivers/cpufreq/Kconfig" | 253 | source "drivers/cpufreq/Kconfig" |
255 | |||
256 | config CPU_FREQ_AT32AP | ||
257 | bool "CPU frequency driver for AT32AP" | ||
258 | depends on CPU_FREQ && PLATFORM_AT32AP | ||
259 | default n | ||
260 | help | ||
261 | This enables the CPU frequency driver for AT32AP processors. | ||
262 | |||
263 | For details, take a look in <file:Documentation/cpu-freq>. | ||
264 | |||
265 | If in doubt, say N. | ||
266 | |||
267 | endmenu | 254 | endmenu |
268 | 255 | ||
269 | endmenu | 256 | endmenu |
diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig index f4025db184ff..d5aff36ade92 100644 --- a/arch/avr32/configs/atngw100_defconfig +++ b/arch/avr32/configs/atngw100_defconfig | |||
@@ -26,7 +26,7 @@ CONFIG_CPU_FREQ=y | |||
26 | # CONFIG_CPU_FREQ_STAT is not set | 26 | # CONFIG_CPU_FREQ_STAT is not set |
27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
29 | CONFIG_CPU_FREQ_AT32AP=y | 29 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
31 | CONFIG_NET=y | 31 | CONFIG_NET=y |
32 | CONFIG_PACKET=y | 32 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atngw100_evklcd100_defconfig b/arch/avr32/configs/atngw100_evklcd100_defconfig index c76a49b9e9d0..4abcf435d599 100644 --- a/arch/avr32/configs/atngw100_evklcd100_defconfig +++ b/arch/avr32/configs/atngw100_evklcd100_defconfig | |||
@@ -28,7 +28,7 @@ CONFIG_CPU_FREQ=y | |||
28 | # CONFIG_CPU_FREQ_STAT is not set | 28 | # CONFIG_CPU_FREQ_STAT is not set |
29 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 29 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
30 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 30 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
31 | CONFIG_CPU_FREQ_AT32AP=y | 31 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
32 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 32 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
33 | CONFIG_NET=y | 33 | CONFIG_NET=y |
34 | CONFIG_PACKET=y | 34 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atngw100_evklcd101_defconfig b/arch/avr32/configs/atngw100_evklcd101_defconfig index 2d8ab089a64e..18f3fa0470ff 100644 --- a/arch/avr32/configs/atngw100_evklcd101_defconfig +++ b/arch/avr32/configs/atngw100_evklcd101_defconfig | |||
@@ -27,7 +27,7 @@ CONFIG_CPU_FREQ=y | |||
27 | # CONFIG_CPU_FREQ_STAT is not set | 27 | # CONFIG_CPU_FREQ_STAT is not set |
28 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 28 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
29 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 29 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
30 | CONFIG_CPU_FREQ_AT32AP=y | 30 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
31 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 31 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
32 | CONFIG_NET=y | 32 | CONFIG_NET=y |
33 | CONFIG_PACKET=y | 33 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig index b189e0cab04b..06e389cfcd12 100644 --- a/arch/avr32/configs/atngw100_mrmt_defconfig +++ b/arch/avr32/configs/atngw100_mrmt_defconfig | |||
@@ -23,7 +23,7 @@ CONFIG_CPU_FREQ=y | |||
23 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | 23 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y |
24 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 24 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
25 | CONFIG_CPU_FREQ_GOV_ONDEMAND=y | 25 | CONFIG_CPU_FREQ_GOV_ONDEMAND=y |
26 | CONFIG_CPU_FREQ_AT32AP=y | 26 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
27 | CONFIG_NET=y | 27 | CONFIG_NET=y |
28 | CONFIG_PACKET=y | 28 | CONFIG_PACKET=y |
29 | CONFIG_UNIX=y | 29 | CONFIG_UNIX=y |
diff --git a/arch/avr32/configs/atngw100mkii_defconfig b/arch/avr32/configs/atngw100mkii_defconfig index 2e4de42a53c4..2518a1368d7c 100644 --- a/arch/avr32/configs/atngw100mkii_defconfig +++ b/arch/avr32/configs/atngw100mkii_defconfig | |||
@@ -26,7 +26,7 @@ CONFIG_CPU_FREQ=y | |||
26 | # CONFIG_CPU_FREQ_STAT is not set | 26 | # CONFIG_CPU_FREQ_STAT is not set |
27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
29 | CONFIG_CPU_FREQ_AT32AP=y | 29 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
31 | CONFIG_NET=y | 31 | CONFIG_NET=y |
32 | CONFIG_PACKET=y | 32 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig index fad3cd22dfd3..245ef6bd0fa6 100644 --- a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig +++ b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig | |||
@@ -29,7 +29,7 @@ CONFIG_CPU_FREQ=y | |||
29 | # CONFIG_CPU_FREQ_STAT is not set | 29 | # CONFIG_CPU_FREQ_STAT is not set |
30 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 30 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
31 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 31 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
32 | CONFIG_CPU_FREQ_AT32AP=y | 32 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
33 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 33 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
34 | CONFIG_NET=y | 34 | CONFIG_NET=y |
35 | CONFIG_PACKET=y | 35 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig index 29986230aaa5..fa6cbac6e418 100644 --- a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig +++ b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig | |||
@@ -28,7 +28,7 @@ CONFIG_CPU_FREQ=y | |||
28 | # CONFIG_CPU_FREQ_STAT is not set | 28 | # CONFIG_CPU_FREQ_STAT is not set |
29 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 29 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
30 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 30 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
31 | CONFIG_CPU_FREQ_AT32AP=y | 31 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
32 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 32 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
33 | CONFIG_NET=y | 33 | CONFIG_NET=y |
34 | CONFIG_PACKET=y | 34 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig index a582465e1cef..bbd5131021a5 100644 --- a/arch/avr32/configs/atstk1002_defconfig +++ b/arch/avr32/configs/atstk1002_defconfig | |||
@@ -25,7 +25,7 @@ CONFIG_CPU_FREQ=y | |||
25 | # CONFIG_CPU_FREQ_STAT is not set | 25 | # CONFIG_CPU_FREQ_STAT is not set |
26 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 26 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
27 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 27 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
28 | CONFIG_CPU_FREQ_AT32AP=y | 28 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
29 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 29 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
30 | CONFIG_NET=y | 30 | CONFIG_NET=y |
31 | CONFIG_PACKET=y | 31 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig index 57a79df2ce5d..c1cd726f9012 100644 --- a/arch/avr32/configs/atstk1003_defconfig +++ b/arch/avr32/configs/atstk1003_defconfig | |||
@@ -26,7 +26,7 @@ CONFIG_CPU_FREQ=y | |||
26 | # CONFIG_CPU_FREQ_STAT is not set | 26 | # CONFIG_CPU_FREQ_STAT is not set |
27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
29 | CONFIG_CPU_FREQ_AT32AP=y | 29 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
31 | CONFIG_NET=y | 31 | CONFIG_NET=y |
32 | CONFIG_PACKET=y | 32 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig index 1a49bd8c6340..754ae56b2767 100644 --- a/arch/avr32/configs/atstk1004_defconfig +++ b/arch/avr32/configs/atstk1004_defconfig | |||
@@ -26,7 +26,7 @@ CONFIG_CPU_FREQ=y | |||
26 | # CONFIG_CPU_FREQ_STAT is not set | 26 | # CONFIG_CPU_FREQ_STAT is not set |
27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
29 | CONFIG_CPU_FREQ_AT32AP=y | 29 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
31 | CONFIG_NET=y | 31 | CONFIG_NET=y |
32 | CONFIG_PACKET=y | 32 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig index 206a1b67f763..58589d8cc0ac 100644 --- a/arch/avr32/configs/atstk1006_defconfig +++ b/arch/avr32/configs/atstk1006_defconfig | |||
@@ -26,7 +26,7 @@ CONFIG_CPU_FREQ=y | |||
26 | # CONFIG_CPU_FREQ_STAT is not set | 26 | # CONFIG_CPU_FREQ_STAT is not set |
27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 27 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
29 | CONFIG_CPU_FREQ_AT32AP=y | 29 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | 30 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y |
31 | CONFIG_NET=y | 31 | CONFIG_NET=y |
32 | CONFIG_PACKET=y | 32 | CONFIG_PACKET=y |
diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig index 0421498d666b..57788a42ff83 100644 --- a/arch/avr32/configs/favr-32_defconfig +++ b/arch/avr32/configs/favr-32_defconfig | |||
@@ -27,7 +27,7 @@ CONFIG_CPU_FREQ=y | |||
27 | # CONFIG_CPU_FREQ_STAT is not set | 27 | # CONFIG_CPU_FREQ_STAT is not set |
28 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 28 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
29 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 29 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
30 | CONFIG_CPU_FREQ_AT32AP=y | 30 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
31 | CONFIG_NET=y | 31 | CONFIG_NET=y |
32 | CONFIG_PACKET=y | 32 | CONFIG_PACKET=y |
33 | CONFIG_UNIX=y | 33 | CONFIG_UNIX=y |
diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig index 82f24eb251bd..ba7c31e269cb 100644 --- a/arch/avr32/configs/hammerhead_defconfig +++ b/arch/avr32/configs/hammerhead_defconfig | |||
@@ -31,7 +31,7 @@ CONFIG_CPU_FREQ=y | |||
31 | # CONFIG_CPU_FREQ_STAT is not set | 31 | # CONFIG_CPU_FREQ_STAT is not set |
32 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 32 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
33 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 33 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
34 | CONFIG_CPU_FREQ_AT32AP=y | 34 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
35 | CONFIG_NET=y | 35 | CONFIG_NET=y |
36 | CONFIG_PACKET=y | 36 | CONFIG_PACKET=y |
37 | CONFIG_UNIX=y | 37 | CONFIG_UNIX=y |
diff --git a/arch/avr32/configs/mimc200_defconfig b/arch/avr32/configs/mimc200_defconfig index 1bee51f22154..0a8bfdc420e0 100644 --- a/arch/avr32/configs/mimc200_defconfig +++ b/arch/avr32/configs/mimc200_defconfig | |||
@@ -24,7 +24,7 @@ CONFIG_CPU_FREQ=y | |||
24 | # CONFIG_CPU_FREQ_STAT is not set | 24 | # CONFIG_CPU_FREQ_STAT is not set |
25 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 25 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
26 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 26 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
27 | CONFIG_CPU_FREQ_AT32AP=y | 27 | CONFIG_AVR32_AT32AP_CPUFREQ=y |
28 | CONFIG_NET=y | 28 | CONFIG_NET=y |
29 | CONFIG_PACKET=y | 29 | CONFIG_PACKET=y |
30 | CONFIG_UNIX=y | 30 | CONFIG_UNIX=y |
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile index 514c9a9b009a..fc09ec4bc725 100644 --- a/arch/avr32/mach-at32ap/Makefile +++ b/arch/avr32/mach-at32ap/Makefile | |||
@@ -1,7 +1,6 @@ | |||
1 | obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o | 1 | obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o |
2 | obj-y += hmatrix.o | 2 | obj-y += hmatrix.o |
3 | obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o | 3 | obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o |
4 | obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o | ||
5 | obj-$(CONFIG_PM) += pm.o | 4 | obj-$(CONFIG_PM) += pm.o |
6 | 5 | ||
7 | ifeq ($(CONFIG_PM_DEBUG),y) | 6 | ifeq ($(CONFIG_PM_DEBUG),y) |
diff --git a/arch/avr32/mach-at32ap/cpufreq.c b/arch/avr32/mach-at32ap/cpufreq.c deleted file mode 100644 index 18b765629a0c..000000000000 --- a/arch/avr32/mach-at32ap/cpufreq.c +++ /dev/null | |||
@@ -1,124 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2007 Atmel Corporation | ||
3 | * | ||
4 | * Based on MIPS implementation arch/mips/kernel/time.c | ||
5 | * Copyright 2001 MontaVista Software Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | /*#define DEBUG*/ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/cpufreq.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/export.h> | ||
22 | |||
23 | static struct clk *cpuclk; | ||
24 | |||
25 | static int at32_verify_speed(struct cpufreq_policy *policy) | ||
26 | { | ||
27 | if (policy->cpu != 0) | ||
28 | return -EINVAL; | ||
29 | |||
30 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
31 | policy->cpuinfo.max_freq); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static unsigned int at32_get_speed(unsigned int cpu) | ||
36 | { | ||
37 | /* No SMP support */ | ||
38 | if (cpu) | ||
39 | return 0; | ||
40 | return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000); | ||
41 | } | ||
42 | |||
43 | static unsigned int ref_freq; | ||
44 | static unsigned long loops_per_jiffy_ref; | ||
45 | |||
46 | static int at32_set_target(struct cpufreq_policy *policy, | ||
47 | unsigned int target_freq, | ||
48 | unsigned int relation) | ||
49 | { | ||
50 | struct cpufreq_freqs freqs; | ||
51 | long freq; | ||
52 | |||
53 | /* Convert target_freq from kHz to Hz */ | ||
54 | freq = clk_round_rate(cpuclk, target_freq * 1000); | ||
55 | |||
56 | /* Check if policy->min <= new_freq <= policy->max */ | ||
57 | if(freq < (policy->min * 1000) || freq > (policy->max * 1000)) | ||
58 | return -EINVAL; | ||
59 | |||
60 | pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000); | ||
61 | |||
62 | freqs.old = at32_get_speed(0); | ||
63 | freqs.new = (freq + 500) / 1000; | ||
64 | freqs.cpu = 0; | ||
65 | freqs.flags = 0; | ||
66 | |||
67 | if (!ref_freq) { | ||
68 | ref_freq = freqs.old; | ||
69 | loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy; | ||
70 | } | ||
71 | |||
72 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
73 | if (freqs.old < freqs.new) | ||
74 | boot_cpu_data.loops_per_jiffy = cpufreq_scale( | ||
75 | loops_per_jiffy_ref, ref_freq, freqs.new); | ||
76 | clk_set_rate(cpuclk, freq); | ||
77 | if (freqs.new < freqs.old) | ||
78 | boot_cpu_data.loops_per_jiffy = cpufreq_scale( | ||
79 | loops_per_jiffy_ref, ref_freq, freqs.new); | ||
80 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
81 | |||
82 | pr_debug("cpufreq: set frequency %lu Hz\n", freq); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) | ||
88 | { | ||
89 | if (policy->cpu != 0) | ||
90 | return -EINVAL; | ||
91 | |||
92 | cpuclk = clk_get(NULL, "cpu"); | ||
93 | if (IS_ERR(cpuclk)) { | ||
94 | pr_debug("cpufreq: could not get CPU clk\n"); | ||
95 | return PTR_ERR(cpuclk); | ||
96 | } | ||
97 | |||
98 | policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; | ||
99 | policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; | ||
100 | policy->cpuinfo.transition_latency = 0; | ||
101 | policy->cur = at32_get_speed(0); | ||
102 | policy->min = policy->cpuinfo.min_freq; | ||
103 | policy->max = policy->cpuinfo.max_freq; | ||
104 | |||
105 | printk("cpufreq: AT32AP CPU frequency driver\n"); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static struct cpufreq_driver at32_driver = { | ||
111 | .name = "at32ap", | ||
112 | .owner = THIS_MODULE, | ||
113 | .init = at32_cpufreq_driver_init, | ||
114 | .verify = at32_verify_speed, | ||
115 | .target = at32_set_target, | ||
116 | .get = at32_get_speed, | ||
117 | .flags = CPUFREQ_STICKY, | ||
118 | }; | ||
119 | |||
120 | static int __init at32_cpufreq_init(void) | ||
121 | { | ||
122 | return cpufreq_register_driver(&at32_driver); | ||
123 | } | ||
124 | late_initcall(at32_cpufreq_init); | ||
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 75f0ba29ebb9..675466d490d4 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile | |||
@@ -10,7 +10,6 @@ obj-$(CONFIG_PM) += pm.o | |||
10 | ifneq ($(CONFIG_BF60x),y) | 10 | ifneq ($(CONFIG_BF60x),y) |
11 | obj-$(CONFIG_PM) += dpmc_modes.o | 11 | obj-$(CONFIG_PM) += dpmc_modes.o |
12 | endif | 12 | endif |
13 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | ||
14 | obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o | 13 | obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o |
15 | obj-$(CONFIG_SMP) += smp.o | 14 | obj-$(CONFIG_SMP) += smp.o |
16 | obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o | 15 | obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o |
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c deleted file mode 100644 index d88bd31319e6..000000000000 --- a/arch/blackfin/mach-common/cpufreq.c +++ /dev/null | |||
@@ -1,258 +0,0 @@ | |||
1 | /* | ||
2 | * Blackfin core clock scaling | ||
3 | * | ||
4 | * Copyright 2008-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/cpufreq.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <asm/blackfin.h> | ||
18 | #include <asm/time.h> | ||
19 | #include <asm/dpmc.h> | ||
20 | |||
21 | |||
22 | /* this is the table of CCLK frequencies, in Hz */ | ||
23 | /* .index is the entry in the auxiliary dpm_state_table[] */ | ||
24 | static struct cpufreq_frequency_table bfin_freq_table[] = { | ||
25 | { | ||
26 | .frequency = CPUFREQ_TABLE_END, | ||
27 | .index = 0, | ||
28 | }, | ||
29 | { | ||
30 | .frequency = CPUFREQ_TABLE_END, | ||
31 | .index = 1, | ||
32 | }, | ||
33 | { | ||
34 | .frequency = CPUFREQ_TABLE_END, | ||
35 | .index = 2, | ||
36 | }, | ||
37 | { | ||
38 | .frequency = CPUFREQ_TABLE_END, | ||
39 | .index = 0, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | static struct bfin_dpm_state { | ||
44 | unsigned int csel; /* system clock divider */ | ||
45 | unsigned int tscale; /* change the divider on the core timer interrupt */ | ||
46 | } dpm_state_table[3]; | ||
47 | |||
48 | #if defined(CONFIG_CYCLES_CLOCKSOURCE) | ||
49 | /* | ||
50 | * normalized to maximum frequency offset for CYCLES, | ||
51 | * used in time-ts cycles clock source, but could be used | ||
52 | * somewhere also. | ||
53 | */ | ||
54 | unsigned long long __bfin_cycles_off; | ||
55 | unsigned int __bfin_cycles_mod; | ||
56 | #endif | ||
57 | |||
58 | /**************************************************************************/ | ||
59 | static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk) | ||
60 | { | ||
61 | |||
62 | unsigned long csel, min_cclk; | ||
63 | int index; | ||
64 | |||
65 | /* Anomaly 273 seems to still exist on non-BF54x w/dcache turned on */ | ||
66 | #if ANOMALY_05000273 || ANOMALY_05000274 || \ | ||
67 | (!(defined(CONFIG_BF54x) || defined(CONFIG_BF60x)) \ | ||
68 | && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE)) | ||
69 | min_cclk = sclk * 2; | ||
70 | #else | ||
71 | min_cclk = sclk; | ||
72 | #endif | ||
73 | |||
74 | #ifndef CONFIG_BF60x | ||
75 | csel = ((bfin_read_PLL_DIV() & CSEL) >> 4); | ||
76 | #else | ||
77 | csel = bfin_read32(CGU0_DIV) & 0x1F; | ||
78 | #endif | ||
79 | |||
80 | for (index = 0; (cclk >> index) >= min_cclk && csel <= 3 && index < 3; index++, csel++) { | ||
81 | bfin_freq_table[index].frequency = cclk >> index; | ||
82 | #ifndef CONFIG_BF60x | ||
83 | dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */ | ||
84 | #else | ||
85 | dpm_state_table[index].csel = csel; | ||
86 | #endif | ||
87 | dpm_state_table[index].tscale = (TIME_SCALE >> index) - 1; | ||
88 | |||
89 | pr_debug("cpufreq: freq:%d csel:0x%x tscale:%d\n", | ||
90 | bfin_freq_table[index].frequency, | ||
91 | dpm_state_table[index].csel, | ||
92 | dpm_state_table[index].tscale); | ||
93 | } | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | static void bfin_adjust_core_timer(void *info) | ||
98 | { | ||
99 | unsigned int tscale; | ||
100 | unsigned int index = *(unsigned int *)info; | ||
101 | |||
102 | /* we have to adjust the core timer, because it is using cclk */ | ||
103 | tscale = dpm_state_table[index].tscale; | ||
104 | bfin_write_TSCALE(tscale); | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | static unsigned int bfin_getfreq_khz(unsigned int cpu) | ||
109 | { | ||
110 | /* Both CoreA/B have the same core clock */ | ||
111 | return get_cclk() / 1000; | ||
112 | } | ||
113 | |||
114 | #ifdef CONFIG_BF60x | ||
115 | unsigned long cpu_set_cclk(int cpu, unsigned long new) | ||
116 | { | ||
117 | struct clk *clk; | ||
118 | int ret; | ||
119 | |||
120 | clk = clk_get(NULL, "CCLK"); | ||
121 | if (IS_ERR(clk)) | ||
122 | return -ENODEV; | ||
123 | |||
124 | ret = clk_set_rate(clk, new); | ||
125 | clk_put(clk); | ||
126 | return ret; | ||
127 | } | ||
128 | #endif | ||
129 | |||
130 | static int bfin_target(struct cpufreq_policy *poli, | ||
131 | unsigned int target_freq, unsigned int relation) | ||
132 | { | ||
133 | #ifndef CONFIG_BF60x | ||
134 | unsigned int plldiv; | ||
135 | #endif | ||
136 | unsigned int index, cpu; | ||
137 | unsigned long cclk_hz; | ||
138 | struct cpufreq_freqs freqs; | ||
139 | static unsigned long lpj_ref; | ||
140 | static unsigned int lpj_ref_freq; | ||
141 | int ret = 0; | ||
142 | |||
143 | #if defined(CONFIG_CYCLES_CLOCKSOURCE) | ||
144 | cycles_t cycles; | ||
145 | #endif | ||
146 | |||
147 | for_each_online_cpu(cpu) { | ||
148 | struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); | ||
149 | |||
150 | if (!policy) | ||
151 | continue; | ||
152 | |||
153 | if (cpufreq_frequency_table_target(policy, bfin_freq_table, | ||
154 | target_freq, relation, &index)) | ||
155 | return -EINVAL; | ||
156 | |||
157 | cclk_hz = bfin_freq_table[index].frequency; | ||
158 | |||
159 | freqs.old = bfin_getfreq_khz(0); | ||
160 | freqs.new = cclk_hz; | ||
161 | freqs.cpu = cpu; | ||
162 | |||
163 | pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n", | ||
164 | cclk_hz, target_freq, freqs.old); | ||
165 | |||
166 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
167 | if (cpu == CPUFREQ_CPU) { | ||
168 | #ifndef CONFIG_BF60x | ||
169 | plldiv = (bfin_read_PLL_DIV() & SSEL) | | ||
170 | dpm_state_table[index].csel; | ||
171 | bfin_write_PLL_DIV(plldiv); | ||
172 | #else | ||
173 | ret = cpu_set_cclk(cpu, freqs.new * 1000); | ||
174 | if (ret != 0) { | ||
175 | WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret); | ||
176 | break; | ||
177 | } | ||
178 | #endif | ||
179 | on_each_cpu(bfin_adjust_core_timer, &index, 1); | ||
180 | #if defined(CONFIG_CYCLES_CLOCKSOURCE) | ||
181 | cycles = get_cycles(); | ||
182 | SSYNC(); | ||
183 | cycles += 10; /* ~10 cycles we lose after get_cycles() */ | ||
184 | __bfin_cycles_off += | ||
185 | (cycles << __bfin_cycles_mod) - (cycles << index); | ||
186 | __bfin_cycles_mod = index; | ||
187 | #endif | ||
188 | if (!lpj_ref_freq) { | ||
189 | lpj_ref = loops_per_jiffy; | ||
190 | lpj_ref_freq = freqs.old; | ||
191 | } | ||
192 | if (freqs.new != freqs.old) { | ||
193 | loops_per_jiffy = cpufreq_scale(lpj_ref, | ||
194 | lpj_ref_freq, freqs.new); | ||
195 | } | ||
196 | } | ||
197 | /* TODO: just test case for cycles clock source, remove later */ | ||
198 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
199 | } | ||
200 | |||
201 | pr_debug("cpufreq: done\n"); | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | static int bfin_verify_speed(struct cpufreq_policy *policy) | ||
206 | { | ||
207 | return cpufreq_frequency_table_verify(policy, bfin_freq_table); | ||
208 | } | ||
209 | |||
210 | static int __bfin_cpu_init(struct cpufreq_policy *policy) | ||
211 | { | ||
212 | |||
213 | unsigned long cclk, sclk; | ||
214 | |||
215 | cclk = get_cclk() / 1000; | ||
216 | sclk = get_sclk() / 1000; | ||
217 | |||
218 | if (policy->cpu == CPUFREQ_CPU) | ||
219 | bfin_init_tables(cclk, sclk); | ||
220 | |||
221 | policy->cpuinfo.transition_latency = 50000; /* 50us assumed */ | ||
222 | |||
223 | policy->cur = cclk; | ||
224 | cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu); | ||
225 | return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table); | ||
226 | } | ||
227 | |||
228 | static struct freq_attr *bfin_freq_attr[] = { | ||
229 | &cpufreq_freq_attr_scaling_available_freqs, | ||
230 | NULL, | ||
231 | }; | ||
232 | |||
233 | static struct cpufreq_driver bfin_driver = { | ||
234 | .verify = bfin_verify_speed, | ||
235 | .target = bfin_target, | ||
236 | .get = bfin_getfreq_khz, | ||
237 | .init = __bfin_cpu_init, | ||
238 | .name = "bfin cpufreq", | ||
239 | .owner = THIS_MODULE, | ||
240 | .attr = bfin_freq_attr, | ||
241 | }; | ||
242 | |||
243 | static int __init bfin_cpu_init(void) | ||
244 | { | ||
245 | return cpufreq_register_driver(&bfin_driver); | ||
246 | } | ||
247 | |||
248 | static void __exit bfin_cpu_exit(void) | ||
249 | { | ||
250 | cpufreq_unregister_driver(&bfin_driver); | ||
251 | } | ||
252 | |||
253 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
254 | MODULE_DESCRIPTION("cpufreq driver for Blackfin"); | ||
255 | MODULE_LICENSE("GPL"); | ||
256 | |||
257 | module_init(bfin_cpu_init); | ||
258 | module_exit(bfin_cpu_exit); | ||
diff --git a/arch/cris/arch-v32/mach-a3/Makefile b/arch/cris/arch-v32/mach-a3/Makefile index d366e0891988..18a227196a41 100644 --- a/arch/cris/arch-v32/mach-a3/Makefile +++ b/arch/cris/arch-v32/mach-a3/Makefile | |||
@@ -3,7 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dma.o pinmux.o io.o arbiter.o | 5 | obj-y := dma.o pinmux.o io.o arbiter.o |
6 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | ||
7 | 6 | ||
8 | clean: | 7 | clean: |
9 | 8 | ||
diff --git a/arch/cris/arch-v32/mach-a3/cpufreq.c b/arch/cris/arch-v32/mach-a3/cpufreq.c deleted file mode 100644 index ee391ecb5bc9..000000000000 --- a/arch/cris/arch-v32/mach-a3/cpufreq.c +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/cpufreq.h> | ||
4 | #include <hwregs/reg_map.h> | ||
5 | #include <hwregs/reg_rdwr.h> | ||
6 | #include <hwregs/clkgen_defs.h> | ||
7 | #include <hwregs/ddr2_defs.h> | ||
8 | |||
9 | static int | ||
10 | cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, | ||
11 | void *data); | ||
12 | |||
13 | static struct notifier_block cris_sdram_freq_notifier_block = { | ||
14 | .notifier_call = cris_sdram_freq_notifier | ||
15 | }; | ||
16 | |||
17 | static struct cpufreq_frequency_table cris_freq_table[] = { | ||
18 | {0x01, 6000}, | ||
19 | {0x02, 200000}, | ||
20 | {0, CPUFREQ_TABLE_END}, | ||
21 | }; | ||
22 | |||
23 | static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) | ||
24 | { | ||
25 | reg_clkgen_rw_clk_ctrl clk_ctrl; | ||
26 | clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); | ||
27 | return clk_ctrl.pll ? 200000 : 6000; | ||
28 | } | ||
29 | |||
30 | static void cris_freq_set_cpu_state(unsigned int state) | ||
31 | { | ||
32 | int i = 0; | ||
33 | struct cpufreq_freqs freqs; | ||
34 | reg_clkgen_rw_clk_ctrl clk_ctrl; | ||
35 | clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); | ||
36 | |||
37 | #ifdef CONFIG_SMP | ||
38 | for_each_present_cpu(i) | ||
39 | #endif | ||
40 | { | ||
41 | freqs.old = cris_freq_get_cpu_frequency(i); | ||
42 | freqs.new = cris_freq_table[state].frequency; | ||
43 | freqs.cpu = i; | ||
44 | } | ||
45 | |||
46 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
47 | |||
48 | local_irq_disable(); | ||
49 | |||
50 | /* Even though we may be SMP they will share the same clock | ||
51 | * so all settings are made on CPU0. */ | ||
52 | if (cris_freq_table[state].frequency == 200000) | ||
53 | clk_ctrl.pll = 1; | ||
54 | else | ||
55 | clk_ctrl.pll = 0; | ||
56 | REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl); | ||
57 | |||
58 | local_irq_enable(); | ||
59 | |||
60 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
61 | }; | ||
62 | |||
63 | static int cris_freq_verify(struct cpufreq_policy *policy) | ||
64 | { | ||
65 | return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]); | ||
66 | } | ||
67 | |||
68 | static int cris_freq_target(struct cpufreq_policy *policy, | ||
69 | unsigned int target_freq, | ||
70 | unsigned int relation) | ||
71 | { | ||
72 | unsigned int newstate = 0; | ||
73 | |||
74 | if (cpufreq_frequency_table_target(policy, cris_freq_table, | ||
75 | target_freq, relation, &newstate)) | ||
76 | return -EINVAL; | ||
77 | |||
78 | cris_freq_set_cpu_state(newstate); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int cris_freq_cpu_init(struct cpufreq_policy *policy) | ||
84 | { | ||
85 | int result; | ||
86 | |||
87 | /* cpuinfo and default policy values */ | ||
88 | policy->cpuinfo.transition_latency = 1000000; /* 1ms */ | ||
89 | policy->cur = cris_freq_get_cpu_frequency(0); | ||
90 | |||
91 | result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table); | ||
92 | if (result) | ||
93 | return (result); | ||
94 | |||
95 | cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | static int cris_freq_cpu_exit(struct cpufreq_policy *policy) | ||
102 | { | ||
103 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | |||
108 | static struct freq_attr *cris_freq_attr[] = { | ||
109 | &cpufreq_freq_attr_scaling_available_freqs, | ||
110 | NULL, | ||
111 | }; | ||
112 | |||
113 | static struct cpufreq_driver cris_freq_driver = { | ||
114 | .get = cris_freq_get_cpu_frequency, | ||
115 | .verify = cris_freq_verify, | ||
116 | .target = cris_freq_target, | ||
117 | .init = cris_freq_cpu_init, | ||
118 | .exit = cris_freq_cpu_exit, | ||
119 | .name = "cris_freq", | ||
120 | .owner = THIS_MODULE, | ||
121 | .attr = cris_freq_attr, | ||
122 | }; | ||
123 | |||
124 | static int __init cris_freq_init(void) | ||
125 | { | ||
126 | int ret; | ||
127 | ret = cpufreq_register_driver(&cris_freq_driver); | ||
128 | cpufreq_register_notifier(&cris_sdram_freq_notifier_block, | ||
129 | CPUFREQ_TRANSITION_NOTIFIER); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static int | ||
134 | cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, | ||
135 | void *data) | ||
136 | { | ||
137 | int i; | ||
138 | struct cpufreq_freqs *freqs = data; | ||
139 | if (val == CPUFREQ_PRECHANGE) { | ||
140 | reg_ddr2_rw_cfg cfg = | ||
141 | REG_RD(ddr2, regi_ddr2_ctrl, rw_cfg); | ||
142 | cfg.ref_interval = (freqs->new == 200000 ? 1560 : 46); | ||
143 | |||
144 | if (freqs->new == 200000) | ||
145 | for (i = 0; i < 50000; i++); | ||
146 | REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing); | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | |||
152 | module_init(cris_freq_init); | ||
diff --git a/arch/cris/arch-v32/mach-fs/Makefile b/arch/cris/arch-v32/mach-fs/Makefile index d366e0891988..18a227196a41 100644 --- a/arch/cris/arch-v32/mach-fs/Makefile +++ b/arch/cris/arch-v32/mach-fs/Makefile | |||
@@ -3,7 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dma.o pinmux.o io.o arbiter.o | 5 | obj-y := dma.o pinmux.o io.o arbiter.o |
6 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | ||
7 | 6 | ||
8 | clean: | 7 | clean: |
9 | 8 | ||
diff --git a/arch/cris/arch-v32/mach-fs/cpufreq.c b/arch/cris/arch-v32/mach-fs/cpufreq.c deleted file mode 100644 index d92cf70d1cbe..000000000000 --- a/arch/cris/arch-v32/mach-fs/cpufreq.c +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/cpufreq.h> | ||
4 | #include <hwregs/reg_map.h> | ||
5 | #include <arch/hwregs/reg_rdwr.h> | ||
6 | #include <arch/hwregs/config_defs.h> | ||
7 | #include <arch/hwregs/bif_core_defs.h> | ||
8 | |||
9 | static int | ||
10 | cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, | ||
11 | void *data); | ||
12 | |||
13 | static struct notifier_block cris_sdram_freq_notifier_block = { | ||
14 | .notifier_call = cris_sdram_freq_notifier | ||
15 | }; | ||
16 | |||
17 | static struct cpufreq_frequency_table cris_freq_table[] = { | ||
18 | {0x01, 6000}, | ||
19 | {0x02, 200000}, | ||
20 | {0, CPUFREQ_TABLE_END}, | ||
21 | }; | ||
22 | |||
23 | static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) | ||
24 | { | ||
25 | reg_config_rw_clk_ctrl clk_ctrl; | ||
26 | clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl); | ||
27 | return clk_ctrl.pll ? 200000 : 6000; | ||
28 | } | ||
29 | |||
30 | static void cris_freq_set_cpu_state(unsigned int state) | ||
31 | { | ||
32 | int i; | ||
33 | struct cpufreq_freqs freqs; | ||
34 | reg_config_rw_clk_ctrl clk_ctrl; | ||
35 | clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl); | ||
36 | |||
37 | for_each_possible_cpu(i) { | ||
38 | freqs.old = cris_freq_get_cpu_frequency(i); | ||
39 | freqs.new = cris_freq_table[state].frequency; | ||
40 | freqs.cpu = i; | ||
41 | } | ||
42 | |||
43 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
44 | |||
45 | local_irq_disable(); | ||
46 | |||
47 | /* Even though we may be SMP they will share the same clock | ||
48 | * so all settings are made on CPU0. */ | ||
49 | if (cris_freq_table[state].frequency == 200000) | ||
50 | clk_ctrl.pll = 1; | ||
51 | else | ||
52 | clk_ctrl.pll = 0; | ||
53 | REG_WR(config, regi_config, rw_clk_ctrl, clk_ctrl); | ||
54 | |||
55 | local_irq_enable(); | ||
56 | |||
57 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
58 | }; | ||
59 | |||
60 | static int cris_freq_verify(struct cpufreq_policy *policy) | ||
61 | { | ||
62 | return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]); | ||
63 | } | ||
64 | |||
65 | static int cris_freq_target(struct cpufreq_policy *policy, | ||
66 | unsigned int target_freq, unsigned int relation) | ||
67 | { | ||
68 | unsigned int newstate = 0; | ||
69 | |||
70 | if (cpufreq_frequency_table_target | ||
71 | (policy, cris_freq_table, target_freq, relation, &newstate)) | ||
72 | return -EINVAL; | ||
73 | |||
74 | cris_freq_set_cpu_state(newstate); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int cris_freq_cpu_init(struct cpufreq_policy *policy) | ||
80 | { | ||
81 | int result; | ||
82 | |||
83 | /* cpuinfo and default policy values */ | ||
84 | policy->cpuinfo.transition_latency = 1000000; /* 1ms */ | ||
85 | policy->cur = cris_freq_get_cpu_frequency(0); | ||
86 | |||
87 | result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table); | ||
88 | if (result) | ||
89 | return (result); | ||
90 | |||
91 | cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int cris_freq_cpu_exit(struct cpufreq_policy *policy) | ||
97 | { | ||
98 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static struct freq_attr *cris_freq_attr[] = { | ||
103 | &cpufreq_freq_attr_scaling_available_freqs, | ||
104 | NULL, | ||
105 | }; | ||
106 | |||
107 | static struct cpufreq_driver cris_freq_driver = { | ||
108 | .get = cris_freq_get_cpu_frequency, | ||
109 | .verify = cris_freq_verify, | ||
110 | .target = cris_freq_target, | ||
111 | .init = cris_freq_cpu_init, | ||
112 | .exit = cris_freq_cpu_exit, | ||
113 | .name = "cris_freq", | ||
114 | .owner = THIS_MODULE, | ||
115 | .attr = cris_freq_attr, | ||
116 | }; | ||
117 | |||
118 | static int __init cris_freq_init(void) | ||
119 | { | ||
120 | int ret; | ||
121 | ret = cpufreq_register_driver(&cris_freq_driver); | ||
122 | cpufreq_register_notifier(&cris_sdram_freq_notifier_block, | ||
123 | CPUFREQ_TRANSITION_NOTIFIER); | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | static int | ||
128 | cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, | ||
129 | void *data) | ||
130 | { | ||
131 | int i; | ||
132 | struct cpufreq_freqs *freqs = data; | ||
133 | if (val == CPUFREQ_PRECHANGE) { | ||
134 | reg_bif_core_rw_sdram_timing timing = | ||
135 | REG_RD(bif_core, regi_bif_core, rw_sdram_timing); | ||
136 | timing.cpd = (freqs->new == 200000 ? 0 : 1); | ||
137 | |||
138 | if (freqs->new == 200000) | ||
139 | for (i = 0; i < 50000; i++) ; | ||
140 | REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing); | ||
141 | } | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | module_init(cris_freq_init); | ||
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 9a02f71c6b1f..152b5f29d048 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -591,9 +591,9 @@ source "kernel/power/Kconfig" | |||
591 | source "drivers/acpi/Kconfig" | 591 | source "drivers/acpi/Kconfig" |
592 | 592 | ||
593 | if PM | 593 | if PM |
594 | 594 | menu "CPU Frequency scaling" | |
595 | source "arch/ia64/kernel/cpufreq/Kconfig" | 595 | source "drivers/cpufreq/Kconfig" |
596 | 596 | endmenu | |
597 | endif | 597 | endif |
598 | 598 | ||
599 | endmenu | 599 | endmenu |
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index d959c84904be..20678a9ed11a 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile | |||
@@ -23,7 +23,6 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o | |||
23 | obj-$(CONFIG_NUMA) += numa.o | 23 | obj-$(CONFIG_NUMA) += numa.o |
24 | obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o | 24 | obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o |
25 | obj-$(CONFIG_IA64_CYCLONE) += cyclone.o | 25 | obj-$(CONFIG_IA64_CYCLONE) += cyclone.o |
26 | obj-$(CONFIG_CPU_FREQ) += cpufreq/ | ||
27 | obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o | 26 | obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o |
28 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o | 27 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o |
29 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 28 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
diff --git a/arch/ia64/kernel/cpufreq/Kconfig b/arch/ia64/kernel/cpufreq/Kconfig deleted file mode 100644 index 2d9d5279b981..000000000000 --- a/arch/ia64/kernel/cpufreq/Kconfig +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | |||
2 | # | ||
3 | # CPU Frequency scaling | ||
4 | # | ||
5 | |||
6 | menu "CPU Frequency scaling" | ||
7 | |||
8 | source "drivers/cpufreq/Kconfig" | ||
9 | |||
10 | if CPU_FREQ | ||
11 | |||
12 | comment "CPUFreq processor drivers" | ||
13 | |||
14 | config IA64_ACPI_CPUFREQ | ||
15 | tristate "ACPI Processor P-States driver" | ||
16 | select CPU_FREQ_TABLE | ||
17 | depends on ACPI_PROCESSOR | ||
18 | help | ||
19 | This driver adds a CPUFreq driver which utilizes the ACPI | ||
20 | Processor Performance States. | ||
21 | |||
22 | For details, take a look at <file:Documentation/cpu-freq/>. | ||
23 | |||
24 | If in doubt, say N. | ||
25 | |||
26 | endif # CPU_FREQ | ||
27 | |||
28 | endmenu | ||
29 | |||
diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile deleted file mode 100644 index 4838f2a57c7a..000000000000 --- a/arch/ia64/kernel/cpufreq/Makefile +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | obj-$(CONFIG_IA64_ACPI_CPUFREQ) += acpi-cpufreq.o | ||
2 | |||
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c deleted file mode 100644 index f09b174244d5..000000000000 --- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c +++ /dev/null | |||
@@ -1,437 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ia64/kernel/cpufreq/acpi-cpufreq.c | ||
3 | * This file provides the ACPI based P-state support. This | ||
4 | * module works with generic cpufreq infrastructure. Most of | ||
5 | * the code is based on i386 version | ||
6 | * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c) | ||
7 | * | ||
8 | * Copyright (C) 2005 Intel Corp | ||
9 | * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/cpufreq.h> | ||
17 | #include <linux/proc_fs.h> | ||
18 | #include <linux/seq_file.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/uaccess.h> | ||
21 | #include <asm/pal.h> | ||
22 | |||
23 | #include <linux/acpi.h> | ||
24 | #include <acpi/processor.h> | ||
25 | |||
26 | MODULE_AUTHOR("Venkatesh Pallipadi"); | ||
27 | MODULE_DESCRIPTION("ACPI Processor P-States Driver"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | |||
31 | struct cpufreq_acpi_io { | ||
32 | struct acpi_processor_performance acpi_data; | ||
33 | struct cpufreq_frequency_table *freq_table; | ||
34 | unsigned int resume; | ||
35 | }; | ||
36 | |||
37 | static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; | ||
38 | |||
39 | static struct cpufreq_driver acpi_cpufreq_driver; | ||
40 | |||
41 | |||
42 | static int | ||
43 | processor_set_pstate ( | ||
44 | u32 value) | ||
45 | { | ||
46 | s64 retval; | ||
47 | |||
48 | pr_debug("processor_set_pstate\n"); | ||
49 | |||
50 | retval = ia64_pal_set_pstate((u64)value); | ||
51 | |||
52 | if (retval) { | ||
53 | pr_debug("Failed to set freq to 0x%x, with error 0x%lx\n", | ||
54 | value, retval); | ||
55 | return -ENODEV; | ||
56 | } | ||
57 | return (int)retval; | ||
58 | } | ||
59 | |||
60 | |||
61 | static int | ||
62 | processor_get_pstate ( | ||
63 | u32 *value) | ||
64 | { | ||
65 | u64 pstate_index = 0; | ||
66 | s64 retval; | ||
67 | |||
68 | pr_debug("processor_get_pstate\n"); | ||
69 | |||
70 | retval = ia64_pal_get_pstate(&pstate_index, | ||
71 | PAL_GET_PSTATE_TYPE_INSTANT); | ||
72 | *value = (u32) pstate_index; | ||
73 | |||
74 | if (retval) | ||
75 | pr_debug("Failed to get current freq with " | ||
76 | "error 0x%lx, idx 0x%x\n", retval, *value); | ||
77 | |||
78 | return (int)retval; | ||
79 | } | ||
80 | |||
81 | |||
82 | /* To be used only after data->acpi_data is initialized */ | ||
83 | static unsigned | ||
84 | extract_clock ( | ||
85 | struct cpufreq_acpi_io *data, | ||
86 | unsigned value, | ||
87 | unsigned int cpu) | ||
88 | { | ||
89 | unsigned long i; | ||
90 | |||
91 | pr_debug("extract_clock\n"); | ||
92 | |||
93 | for (i = 0; i < data->acpi_data.state_count; i++) { | ||
94 | if (value == data->acpi_data.states[i].status) | ||
95 | return data->acpi_data.states[i].core_frequency; | ||
96 | } | ||
97 | return data->acpi_data.states[i-1].core_frequency; | ||
98 | } | ||
99 | |||
100 | |||
101 | static unsigned int | ||
102 | processor_get_freq ( | ||
103 | struct cpufreq_acpi_io *data, | ||
104 | unsigned int cpu) | ||
105 | { | ||
106 | int ret = 0; | ||
107 | u32 value = 0; | ||
108 | cpumask_t saved_mask; | ||
109 | unsigned long clock_freq; | ||
110 | |||
111 | pr_debug("processor_get_freq\n"); | ||
112 | |||
113 | saved_mask = current->cpus_allowed; | ||
114 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
115 | if (smp_processor_id() != cpu) | ||
116 | goto migrate_end; | ||
117 | |||
118 | /* processor_get_pstate gets the instantaneous frequency */ | ||
119 | ret = processor_get_pstate(&value); | ||
120 | |||
121 | if (ret) { | ||
122 | set_cpus_allowed_ptr(current, &saved_mask); | ||
123 | printk(KERN_WARNING "get performance failed with error %d\n", | ||
124 | ret); | ||
125 | ret = 0; | ||
126 | goto migrate_end; | ||
127 | } | ||
128 | clock_freq = extract_clock(data, value, cpu); | ||
129 | ret = (clock_freq*1000); | ||
130 | |||
131 | migrate_end: | ||
132 | set_cpus_allowed_ptr(current, &saved_mask); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | |||
137 | static int | ||
138 | processor_set_freq ( | ||
139 | struct cpufreq_acpi_io *data, | ||
140 | unsigned int cpu, | ||
141 | int state) | ||
142 | { | ||
143 | int ret = 0; | ||
144 | u32 value = 0; | ||
145 | struct cpufreq_freqs cpufreq_freqs; | ||
146 | cpumask_t saved_mask; | ||
147 | int retval; | ||
148 | |||
149 | pr_debug("processor_set_freq\n"); | ||
150 | |||
151 | saved_mask = current->cpus_allowed; | ||
152 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
153 | if (smp_processor_id() != cpu) { | ||
154 | retval = -EAGAIN; | ||
155 | goto migrate_end; | ||
156 | } | ||
157 | |||
158 | if (state == data->acpi_data.state) { | ||
159 | if (unlikely(data->resume)) { | ||
160 | pr_debug("Called after resume, resetting to P%d\n", state); | ||
161 | data->resume = 0; | ||
162 | } else { | ||
163 | pr_debug("Already at target state (P%d)\n", state); | ||
164 | retval = 0; | ||
165 | goto migrate_end; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | pr_debug("Transitioning from P%d to P%d\n", | ||
170 | data->acpi_data.state, state); | ||
171 | |||
172 | /* cpufreq frequency struct */ | ||
173 | cpufreq_freqs.cpu = cpu; | ||
174 | cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency; | ||
175 | cpufreq_freqs.new = data->freq_table[state].frequency; | ||
176 | |||
177 | /* notify cpufreq */ | ||
178 | cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); | ||
179 | |||
180 | /* | ||
181 | * First we write the target state's 'control' value to the | ||
182 | * control_register. | ||
183 | */ | ||
184 | |||
185 | value = (u32) data->acpi_data.states[state].control; | ||
186 | |||
187 | pr_debug("Transitioning to state: 0x%08x\n", value); | ||
188 | |||
189 | ret = processor_set_pstate(value); | ||
190 | if (ret) { | ||
191 | unsigned int tmp = cpufreq_freqs.new; | ||
192 | cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); | ||
193 | cpufreq_freqs.new = cpufreq_freqs.old; | ||
194 | cpufreq_freqs.old = tmp; | ||
195 | cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); | ||
196 | cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); | ||
197 | printk(KERN_WARNING "Transition failed with error %d\n", ret); | ||
198 | retval = -ENODEV; | ||
199 | goto migrate_end; | ||
200 | } | ||
201 | |||
202 | cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); | ||
203 | |||
204 | data->acpi_data.state = state; | ||
205 | |||
206 | retval = 0; | ||
207 | |||
208 | migrate_end: | ||
209 | set_cpus_allowed_ptr(current, &saved_mask); | ||
210 | return (retval); | ||
211 | } | ||
212 | |||
213 | |||
214 | static unsigned int | ||
215 | acpi_cpufreq_get ( | ||
216 | unsigned int cpu) | ||
217 | { | ||
218 | struct cpufreq_acpi_io *data = acpi_io_data[cpu]; | ||
219 | |||
220 | pr_debug("acpi_cpufreq_get\n"); | ||
221 | |||
222 | return processor_get_freq(data, cpu); | ||
223 | } | ||
224 | |||
225 | |||
226 | static int | ||
227 | acpi_cpufreq_target ( | ||
228 | struct cpufreq_policy *policy, | ||
229 | unsigned int target_freq, | ||
230 | unsigned int relation) | ||
231 | { | ||
232 | struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; | ||
233 | unsigned int next_state = 0; | ||
234 | unsigned int result = 0; | ||
235 | |||
236 | pr_debug("acpi_cpufreq_setpolicy\n"); | ||
237 | |||
238 | result = cpufreq_frequency_table_target(policy, | ||
239 | data->freq_table, target_freq, relation, &next_state); | ||
240 | if (result) | ||
241 | return (result); | ||
242 | |||
243 | result = processor_set_freq(data, policy->cpu, next_state); | ||
244 | |||
245 | return (result); | ||
246 | } | ||
247 | |||
248 | |||
249 | static int | ||
250 | acpi_cpufreq_verify ( | ||
251 | struct cpufreq_policy *policy) | ||
252 | { | ||
253 | unsigned int result = 0; | ||
254 | struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; | ||
255 | |||
256 | pr_debug("acpi_cpufreq_verify\n"); | ||
257 | |||
258 | result = cpufreq_frequency_table_verify(policy, | ||
259 | data->freq_table); | ||
260 | |||
261 | return (result); | ||
262 | } | ||
263 | |||
264 | |||
265 | static int | ||
266 | acpi_cpufreq_cpu_init ( | ||
267 | struct cpufreq_policy *policy) | ||
268 | { | ||
269 | unsigned int i; | ||
270 | unsigned int cpu = policy->cpu; | ||
271 | struct cpufreq_acpi_io *data; | ||
272 | unsigned int result = 0; | ||
273 | |||
274 | pr_debug("acpi_cpufreq_cpu_init\n"); | ||
275 | |||
276 | data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); | ||
277 | if (!data) | ||
278 | return (-ENOMEM); | ||
279 | |||
280 | acpi_io_data[cpu] = data; | ||
281 | |||
282 | result = acpi_processor_register_performance(&data->acpi_data, cpu); | ||
283 | |||
284 | if (result) | ||
285 | goto err_free; | ||
286 | |||
287 | /* capability check */ | ||
288 | if (data->acpi_data.state_count <= 1) { | ||
289 | pr_debug("No P-States\n"); | ||
290 | result = -ENODEV; | ||
291 | goto err_unreg; | ||
292 | } | ||
293 | |||
294 | if ((data->acpi_data.control_register.space_id != | ||
295 | ACPI_ADR_SPACE_FIXED_HARDWARE) || | ||
296 | (data->acpi_data.status_register.space_id != | ||
297 | ACPI_ADR_SPACE_FIXED_HARDWARE)) { | ||
298 | pr_debug("Unsupported address space [%d, %d]\n", | ||
299 | (u32) (data->acpi_data.control_register.space_id), | ||
300 | (u32) (data->acpi_data.status_register.space_id)); | ||
301 | result = -ENODEV; | ||
302 | goto err_unreg; | ||
303 | } | ||
304 | |||
305 | /* alloc freq_table */ | ||
306 | data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * | ||
307 | (data->acpi_data.state_count + 1), | ||
308 | GFP_KERNEL); | ||
309 | if (!data->freq_table) { | ||
310 | result = -ENOMEM; | ||
311 | goto err_unreg; | ||
312 | } | ||
313 | |||
314 | /* detect transition latency */ | ||
315 | policy->cpuinfo.transition_latency = 0; | ||
316 | for (i=0; i<data->acpi_data.state_count; i++) { | ||
317 | if ((data->acpi_data.states[i].transition_latency * 1000) > | ||
318 | policy->cpuinfo.transition_latency) { | ||
319 | policy->cpuinfo.transition_latency = | ||
320 | data->acpi_data.states[i].transition_latency * 1000; | ||
321 | } | ||
322 | } | ||
323 | policy->cur = processor_get_freq(data, policy->cpu); | ||
324 | |||
325 | /* table init */ | ||
326 | for (i = 0; i <= data->acpi_data.state_count; i++) | ||
327 | { | ||
328 | data->freq_table[i].index = i; | ||
329 | if (i < data->acpi_data.state_count) { | ||
330 | data->freq_table[i].frequency = | ||
331 | data->acpi_data.states[i].core_frequency * 1000; | ||
332 | } else { | ||
333 | data->freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); | ||
338 | if (result) { | ||
339 | goto err_freqfree; | ||
340 | } | ||
341 | |||
342 | /* notify BIOS that we exist */ | ||
343 | acpi_processor_notify_smm(THIS_MODULE); | ||
344 | |||
345 | printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management " | ||
346 | "activated.\n", cpu); | ||
347 | |||
348 | for (i = 0; i < data->acpi_data.state_count; i++) | ||
349 | pr_debug(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n", | ||
350 | (i == data->acpi_data.state?'*':' '), i, | ||
351 | (u32) data->acpi_data.states[i].core_frequency, | ||
352 | (u32) data->acpi_data.states[i].power, | ||
353 | (u32) data->acpi_data.states[i].transition_latency, | ||
354 | (u32) data->acpi_data.states[i].bus_master_latency, | ||
355 | (u32) data->acpi_data.states[i].status, | ||
356 | (u32) data->acpi_data.states[i].control); | ||
357 | |||
358 | cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); | ||
359 | |||
360 | /* the first call to ->target() should result in us actually | ||
361 | * writing something to the appropriate registers. */ | ||
362 | data->resume = 1; | ||
363 | |||
364 | return (result); | ||
365 | |||
366 | err_freqfree: | ||
367 | kfree(data->freq_table); | ||
368 | err_unreg: | ||
369 | acpi_processor_unregister_performance(&data->acpi_data, cpu); | ||
370 | err_free: | ||
371 | kfree(data); | ||
372 | acpi_io_data[cpu] = NULL; | ||
373 | |||
374 | return (result); | ||
375 | } | ||
376 | |||
377 | |||
378 | static int | ||
379 | acpi_cpufreq_cpu_exit ( | ||
380 | struct cpufreq_policy *policy) | ||
381 | { | ||
382 | struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; | ||
383 | |||
384 | pr_debug("acpi_cpufreq_cpu_exit\n"); | ||
385 | |||
386 | if (data) { | ||
387 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
388 | acpi_io_data[policy->cpu] = NULL; | ||
389 | acpi_processor_unregister_performance(&data->acpi_data, | ||
390 | policy->cpu); | ||
391 | kfree(data); | ||
392 | } | ||
393 | |||
394 | return (0); | ||
395 | } | ||
396 | |||
397 | |||
398 | static struct freq_attr* acpi_cpufreq_attr[] = { | ||
399 | &cpufreq_freq_attr_scaling_available_freqs, | ||
400 | NULL, | ||
401 | }; | ||
402 | |||
403 | |||
404 | static struct cpufreq_driver acpi_cpufreq_driver = { | ||
405 | .verify = acpi_cpufreq_verify, | ||
406 | .target = acpi_cpufreq_target, | ||
407 | .get = acpi_cpufreq_get, | ||
408 | .init = acpi_cpufreq_cpu_init, | ||
409 | .exit = acpi_cpufreq_cpu_exit, | ||
410 | .name = "acpi-cpufreq", | ||
411 | .owner = THIS_MODULE, | ||
412 | .attr = acpi_cpufreq_attr, | ||
413 | }; | ||
414 | |||
415 | |||
416 | static int __init | ||
417 | acpi_cpufreq_init (void) | ||
418 | { | ||
419 | pr_debug("acpi_cpufreq_init\n"); | ||
420 | |||
421 | return cpufreq_register_driver(&acpi_cpufreq_driver); | ||
422 | } | ||
423 | |||
424 | |||
425 | static void __exit | ||
426 | acpi_cpufreq_exit (void) | ||
427 | { | ||
428 | pr_debug("acpi_cpufreq_exit\n"); | ||
429 | |||
430 | cpufreq_unregister_driver(&acpi_cpufreq_driver); | ||
431 | return; | ||
432 | } | ||
433 | |||
434 | |||
435 | late_initcall(acpi_cpufreq_init); | ||
436 | module_exit(acpi_cpufreq_exit); | ||
437 | |||
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 51244bf97271..26d21d3d6a98 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -2538,7 +2538,14 @@ source "kernel/power/Kconfig" | |||
2538 | 2538 | ||
2539 | endmenu | 2539 | endmenu |
2540 | 2540 | ||
2541 | source "arch/mips/kernel/cpufreq/Kconfig" | 2541 | config MIPS_EXTERNAL_TIMER |
2542 | bool | ||
2543 | |||
2544 | if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER | ||
2545 | menu "CPU Power Management" | ||
2546 | source "drivers/cpufreq/Kconfig" | ||
2547 | endmenu | ||
2548 | endif | ||
2542 | 2549 | ||
2543 | source "net/Kconfig" | 2550 | source "net/Kconfig" |
2544 | 2551 | ||
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index de75fb50562b..520a908d45d6 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -92,8 +92,6 @@ CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/n | |||
92 | 92 | ||
93 | obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o | 93 | obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o |
94 | 94 | ||
95 | obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/ | ||
96 | |||
97 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o | 95 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o |
98 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o | 96 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o |
99 | 97 | ||
diff --git a/arch/mips/kernel/cpufreq/Kconfig b/arch/mips/kernel/cpufreq/Kconfig deleted file mode 100644 index 58c601eee6fd..000000000000 --- a/arch/mips/kernel/cpufreq/Kconfig +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | # | ||
2 | # CPU Frequency scaling | ||
3 | # | ||
4 | |||
5 | config MIPS_EXTERNAL_TIMER | ||
6 | bool | ||
7 | |||
8 | config MIPS_CPUFREQ | ||
9 | bool | ||
10 | default y | ||
11 | depends on CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER | ||
12 | |||
13 | if MIPS_CPUFREQ | ||
14 | |||
15 | menu "CPU Frequency scaling" | ||
16 | |||
17 | source "drivers/cpufreq/Kconfig" | ||
18 | |||
19 | if CPU_FREQ | ||
20 | |||
21 | comment "CPUFreq processor drivers" | ||
22 | |||
23 | config LOONGSON2_CPUFREQ | ||
24 | tristate "Loongson2 CPUFreq Driver" | ||
25 | select CPU_FREQ_TABLE | ||
26 | depends on MIPS_CPUFREQ | ||
27 | help | ||
28 | This option adds a CPUFreq driver for loongson processors which | ||
29 | support software configurable cpu frequency. | ||
30 | |||
31 | Loongson2F and it's successors support this feature. | ||
32 | |||
33 | For details, take a look at <file:Documentation/cpu-freq/>. | ||
34 | |||
35 | If in doubt, say N. | ||
36 | |||
37 | endif # CPU_FREQ | ||
38 | |||
39 | endmenu | ||
40 | |||
41 | endif # MIPS_CPUFREQ | ||
diff --git a/arch/mips/kernel/cpufreq/Makefile b/arch/mips/kernel/cpufreq/Makefile deleted file mode 100644 index 05a5715ee38c..000000000000 --- a/arch/mips/kernel/cpufreq/Makefile +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the Linux/MIPS cpufreq. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o | ||
diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c deleted file mode 100644 index 3237c5235f9c..000000000000 --- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c +++ /dev/null | |||
@@ -1,255 +0,0 @@ | |||
1 | /* | ||
2 | * Cpufreq driver for the loongson-2 processors | ||
3 | * | ||
4 | * The 2E revision of loongson processor not support this feature. | ||
5 | * | ||
6 | * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology | ||
7 | * Author: Yanhua, yanh@lemote.com | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/cpufreq.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/sched.h> /* set_cpus_allowed() */ | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | #include <asm/clock.h> | ||
21 | |||
22 | #include <asm/mach-loongson/loongson.h> | ||
23 | |||
24 | static uint nowait; | ||
25 | |||
26 | static struct clk *cpuclk; | ||
27 | |||
28 | static void (*saved_cpu_wait) (void); | ||
29 | |||
30 | static int loongson2_cpu_freq_notifier(struct notifier_block *nb, | ||
31 | unsigned long val, void *data); | ||
32 | |||
33 | static struct notifier_block loongson2_cpufreq_notifier_block = { | ||
34 | .notifier_call = loongson2_cpu_freq_notifier | ||
35 | }; | ||
36 | |||
37 | static int loongson2_cpu_freq_notifier(struct notifier_block *nb, | ||
38 | unsigned long val, void *data) | ||
39 | { | ||
40 | if (val == CPUFREQ_POSTCHANGE) | ||
41 | current_cpu_data.udelay_val = loops_per_jiffy; | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static unsigned int loongson2_cpufreq_get(unsigned int cpu) | ||
47 | { | ||
48 | return clk_get_rate(cpuclk); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Here we notify other drivers of the proposed change and the final change. | ||
53 | */ | ||
54 | static int loongson2_cpufreq_target(struct cpufreq_policy *policy, | ||
55 | unsigned int target_freq, | ||
56 | unsigned int relation) | ||
57 | { | ||
58 | unsigned int cpu = policy->cpu; | ||
59 | unsigned int newstate = 0; | ||
60 | cpumask_t cpus_allowed; | ||
61 | struct cpufreq_freqs freqs; | ||
62 | unsigned int freq; | ||
63 | |||
64 | if (!cpu_online(cpu)) | ||
65 | return -ENODEV; | ||
66 | |||
67 | cpus_allowed = current->cpus_allowed; | ||
68 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
69 | |||
70 | if (cpufreq_frequency_table_target | ||
71 | (policy, &loongson2_clockmod_table[0], target_freq, relation, | ||
72 | &newstate)) | ||
73 | return -EINVAL; | ||
74 | |||
75 | freq = | ||
76 | ((cpu_clock_freq / 1000) * | ||
77 | loongson2_clockmod_table[newstate].index) / 8; | ||
78 | if (freq < policy->min || freq > policy->max) | ||
79 | return -EINVAL; | ||
80 | |||
81 | pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000); | ||
82 | |||
83 | freqs.cpu = cpu; | ||
84 | freqs.old = loongson2_cpufreq_get(cpu); | ||
85 | freqs.new = freq; | ||
86 | freqs.flags = 0; | ||
87 | |||
88 | if (freqs.new == freqs.old) | ||
89 | return 0; | ||
90 | |||
91 | /* notifiers */ | ||
92 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
93 | |||
94 | set_cpus_allowed_ptr(current, &cpus_allowed); | ||
95 | |||
96 | /* setting the cpu frequency */ | ||
97 | clk_set_rate(cpuclk, freq); | ||
98 | |||
99 | /* notifiers */ | ||
100 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
101 | |||
102 | pr_debug("cpufreq: set frequency %u kHz\n", freq); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
108 | { | ||
109 | int i; | ||
110 | unsigned long rate; | ||
111 | int ret; | ||
112 | |||
113 | if (!cpu_online(policy->cpu)) | ||
114 | return -ENODEV; | ||
115 | |||
116 | cpuclk = clk_get(NULL, "cpu_clk"); | ||
117 | if (IS_ERR(cpuclk)) { | ||
118 | printk(KERN_ERR "cpufreq: couldn't get CPU clk\n"); | ||
119 | return PTR_ERR(cpuclk); | ||
120 | } | ||
121 | |||
122 | rate = cpu_clock_freq / 1000; | ||
123 | if (!rate) { | ||
124 | clk_put(cpuclk); | ||
125 | return -EINVAL; | ||
126 | } | ||
127 | ret = clk_set_rate(cpuclk, rate); | ||
128 | if (ret) { | ||
129 | clk_put(cpuclk); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | /* clock table init */ | ||
134 | for (i = 2; | ||
135 | (loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END); | ||
136 | i++) | ||
137 | loongson2_clockmod_table[i].frequency = (rate * i) / 8; | ||
138 | |||
139 | policy->cur = loongson2_cpufreq_get(policy->cpu); | ||
140 | |||
141 | cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0], | ||
142 | policy->cpu); | ||
143 | |||
144 | return cpufreq_frequency_table_cpuinfo(policy, | ||
145 | &loongson2_clockmod_table[0]); | ||
146 | } | ||
147 | |||
148 | static int loongson2_cpufreq_verify(struct cpufreq_policy *policy) | ||
149 | { | ||
150 | return cpufreq_frequency_table_verify(policy, | ||
151 | &loongson2_clockmod_table[0]); | ||
152 | } | ||
153 | |||
154 | static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) | ||
155 | { | ||
156 | clk_put(cpuclk); | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static struct freq_attr *loongson2_table_attr[] = { | ||
161 | &cpufreq_freq_attr_scaling_available_freqs, | ||
162 | NULL, | ||
163 | }; | ||
164 | |||
165 | static struct cpufreq_driver loongson2_cpufreq_driver = { | ||
166 | .owner = THIS_MODULE, | ||
167 | .name = "loongson2", | ||
168 | .init = loongson2_cpufreq_cpu_init, | ||
169 | .verify = loongson2_cpufreq_verify, | ||
170 | .target = loongson2_cpufreq_target, | ||
171 | .get = loongson2_cpufreq_get, | ||
172 | .exit = loongson2_cpufreq_exit, | ||
173 | .attr = loongson2_table_attr, | ||
174 | }; | ||
175 | |||
176 | static struct platform_device_id platform_device_ids[] = { | ||
177 | { | ||
178 | .name = "loongson2_cpufreq", | ||
179 | }, | ||
180 | {} | ||
181 | }; | ||
182 | |||
183 | MODULE_DEVICE_TABLE(platform, platform_device_ids); | ||
184 | |||
185 | static struct platform_driver platform_driver = { | ||
186 | .driver = { | ||
187 | .name = "loongson2_cpufreq", | ||
188 | .owner = THIS_MODULE, | ||
189 | }, | ||
190 | .id_table = platform_device_ids, | ||
191 | }; | ||
192 | |||
193 | /* | ||
194 | * This is the simple version of Loongson-2 wait, Maybe we need do this in | ||
195 | * interrupt disabled context. | ||
196 | */ | ||
197 | |||
198 | static DEFINE_SPINLOCK(loongson2_wait_lock); | ||
199 | |||
200 | static void loongson2_cpu_wait(void) | ||
201 | { | ||
202 | unsigned long flags; | ||
203 | u32 cpu_freq; | ||
204 | |||
205 | spin_lock_irqsave(&loongson2_wait_lock, flags); | ||
206 | cpu_freq = LOONGSON_CHIPCFG0; | ||
207 | LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ | ||
208 | LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ | ||
209 | spin_unlock_irqrestore(&loongson2_wait_lock, flags); | ||
210 | } | ||
211 | |||
212 | static int __init cpufreq_init(void) | ||
213 | { | ||
214 | int ret; | ||
215 | |||
216 | /* Register platform stuff */ | ||
217 | ret = platform_driver_register(&platform_driver); | ||
218 | if (ret) | ||
219 | return ret; | ||
220 | |||
221 | pr_info("cpufreq: Loongson-2F CPU frequency driver.\n"); | ||
222 | |||
223 | cpufreq_register_notifier(&loongson2_cpufreq_notifier_block, | ||
224 | CPUFREQ_TRANSITION_NOTIFIER); | ||
225 | |||
226 | ret = cpufreq_register_driver(&loongson2_cpufreq_driver); | ||
227 | |||
228 | if (!ret && !nowait) { | ||
229 | saved_cpu_wait = cpu_wait; | ||
230 | cpu_wait = loongson2_cpu_wait; | ||
231 | } | ||
232 | |||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static void __exit cpufreq_exit(void) | ||
237 | { | ||
238 | if (!nowait && saved_cpu_wait) | ||
239 | cpu_wait = saved_cpu_wait; | ||
240 | cpufreq_unregister_driver(&loongson2_cpufreq_driver); | ||
241 | cpufreq_unregister_notifier(&loongson2_cpufreq_notifier_block, | ||
242 | CPUFREQ_TRANSITION_NOTIFIER); | ||
243 | |||
244 | platform_driver_unregister(&platform_driver); | ||
245 | } | ||
246 | |||
247 | module_init(cpufreq_init); | ||
248 | module_exit(cpufreq_exit); | ||
249 | |||
250 | module_param(nowait, uint, 0644); | ||
251 | MODULE_PARM_DESC(nowait, "Disable Loongson-2F specific wait"); | ||
252 | |||
253 | MODULE_AUTHOR("Yanhua <yanh@lemote.com>"); | ||
254 | MODULE_DESCRIPTION("cpufreq driver for Loongson2F"); | ||
255 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 53aaefeb3386..9978f594cac0 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -113,34 +113,10 @@ config CBE_THERM | |||
113 | default m | 113 | default m |
114 | depends on CBE_RAS && SPU_BASE | 114 | depends on CBE_RAS && SPU_BASE |
115 | 115 | ||
116 | config CBE_CPUFREQ | ||
117 | tristate "CBE frequency scaling" | ||
118 | depends on CBE_RAS && CPU_FREQ | ||
119 | default m | ||
120 | help | ||
121 | This adds the cpufreq driver for Cell BE processors. | ||
122 | For details, take a look at <file:Documentation/cpu-freq/>. | ||
123 | If you don't have such processor, say N | ||
124 | |||
125 | config CBE_CPUFREQ_PMI_ENABLE | ||
126 | bool "CBE frequency scaling using PMI interface" | ||
127 | depends on CBE_CPUFREQ | ||
128 | default n | ||
129 | help | ||
130 | Select this, if you want to use the PMI interface | ||
131 | to switch frequencies. Using PMI, the | ||
132 | processor will not only be able to run at lower speed, | ||
133 | but also at lower core voltage. | ||
134 | |||
135 | config CBE_CPUFREQ_PMI | ||
136 | tristate | ||
137 | depends on CBE_CPUFREQ_PMI_ENABLE | ||
138 | default CBE_CPUFREQ | ||
139 | |||
140 | config PPC_PMI | 116 | config PPC_PMI |
141 | tristate | 117 | tristate |
142 | default y | 118 | default y |
143 | depends on CBE_CPUFREQ_PMI || PPC_IBM_CELL_POWERBUTTON | 119 | depends on CPU_FREQ_CBE_PMI || PPC_IBM_CELL_POWERBUTTON |
144 | help | 120 | help |
145 | PMI (Platform Management Interrupt) is a way to | 121 | PMI (Platform Management Interrupt) is a way to |
146 | communicate with the BMC (Baseboard Management Controller). | 122 | communicate with the BMC (Baseboard Management Controller). |
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index a4a89350bcfc..fe053e7c73ee 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
@@ -5,9 +5,6 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += iommu.o setup.o spider-pic.o \ | |||
5 | obj-$(CONFIG_CBE_RAS) += ras.o | 5 | obj-$(CONFIG_CBE_RAS) += ras.o |
6 | 6 | ||
7 | obj-$(CONFIG_CBE_THERM) += cbe_thermal.o | 7 | obj-$(CONFIG_CBE_THERM) += cbe_thermal.o |
8 | obj-$(CONFIG_CBE_CPUFREQ_PMI) += cbe_cpufreq_pmi.o | ||
9 | obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o | ||
10 | cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o | ||
11 | obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o | 8 | obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o |
12 | 9 | ||
13 | obj-$(CONFIG_PPC_IBM_CELL_POWERBUTTON) += cbe_powerbutton.o | 10 | obj-$(CONFIG_PPC_IBM_CELL_POWERBUTTON) += cbe_powerbutton.o |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c deleted file mode 100644 index d4c39e32f147..000000000000 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | /* | ||
2 | * cpufreq driver for the cell processor | ||
3 | * | ||
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007 | ||
5 | * | ||
6 | * Author: Christian Krafft <krafft@de.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/cpufreq.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/of_platform.h> | ||
26 | |||
27 | #include <asm/machdep.h> | ||
28 | #include <asm/prom.h> | ||
29 | #include <asm/cell-regs.h> | ||
30 | #include "cbe_cpufreq.h" | ||
31 | |||
32 | static DEFINE_MUTEX(cbe_switch_mutex); | ||
33 | |||
34 | |||
35 | /* the CBE supports an 8 step frequency scaling */ | ||
36 | static struct cpufreq_frequency_table cbe_freqs[] = { | ||
37 | {1, 0}, | ||
38 | {2, 0}, | ||
39 | {3, 0}, | ||
40 | {4, 0}, | ||
41 | {5, 0}, | ||
42 | {6, 0}, | ||
43 | {8, 0}, | ||
44 | {10, 0}, | ||
45 | {0, CPUFREQ_TABLE_END}, | ||
46 | }; | ||
47 | |||
48 | /* | ||
49 | * hardware specific functions | ||
50 | */ | ||
51 | |||
52 | static int set_pmode(unsigned int cpu, unsigned int slow_mode) | ||
53 | { | ||
54 | int rc; | ||
55 | |||
56 | if (cbe_cpufreq_has_pmi) | ||
57 | rc = cbe_cpufreq_set_pmode_pmi(cpu, slow_mode); | ||
58 | else | ||
59 | rc = cbe_cpufreq_set_pmode(cpu, slow_mode); | ||
60 | |||
61 | pr_debug("register contains slow mode %d\n", cbe_cpufreq_get_pmode(cpu)); | ||
62 | |||
63 | return rc; | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * cpufreq functions | ||
68 | */ | ||
69 | |||
70 | static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
71 | { | ||
72 | const u32 *max_freqp; | ||
73 | u32 max_freq; | ||
74 | int i, cur_pmode; | ||
75 | struct device_node *cpu; | ||
76 | |||
77 | cpu = of_get_cpu_node(policy->cpu, NULL); | ||
78 | |||
79 | if (!cpu) | ||
80 | return -ENODEV; | ||
81 | |||
82 | pr_debug("init cpufreq on CPU %d\n", policy->cpu); | ||
83 | |||
84 | /* | ||
85 | * Let's check we can actually get to the CELL regs | ||
86 | */ | ||
87 | if (!cbe_get_cpu_pmd_regs(policy->cpu) || | ||
88 | !cbe_get_cpu_mic_tm_regs(policy->cpu)) { | ||
89 | pr_info("invalid CBE regs pointers for cpufreq\n"); | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | max_freqp = of_get_property(cpu, "clock-frequency", NULL); | ||
94 | |||
95 | of_node_put(cpu); | ||
96 | |||
97 | if (!max_freqp) | ||
98 | return -EINVAL; | ||
99 | |||
100 | /* we need the freq in kHz */ | ||
101 | max_freq = *max_freqp / 1000; | ||
102 | |||
103 | pr_debug("max clock-frequency is at %u kHz\n", max_freq); | ||
104 | pr_debug("initializing frequency table\n"); | ||
105 | |||
106 | /* initialize frequency table */ | ||
107 | for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { | ||
108 | cbe_freqs[i].frequency = max_freq / cbe_freqs[i].index; | ||
109 | pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); | ||
110 | } | ||
111 | |||
112 | /* if DEBUG is enabled set_pmode() measures the latency | ||
113 | * of a transition */ | ||
114 | policy->cpuinfo.transition_latency = 25000; | ||
115 | |||
116 | cur_pmode = cbe_cpufreq_get_pmode(policy->cpu); | ||
117 | pr_debug("current pmode is at %d\n",cur_pmode); | ||
118 | |||
119 | policy->cur = cbe_freqs[cur_pmode].frequency; | ||
120 | |||
121 | #ifdef CONFIG_SMP | ||
122 | cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu)); | ||
123 | #endif | ||
124 | |||
125 | cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); | ||
126 | |||
127 | /* this ensures that policy->cpuinfo_min | ||
128 | * and policy->cpuinfo_max are set correctly */ | ||
129 | return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs); | ||
130 | } | ||
131 | |||
132 | static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) | ||
133 | { | ||
134 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int cbe_cpufreq_verify(struct cpufreq_policy *policy) | ||
139 | { | ||
140 | return cpufreq_frequency_table_verify(policy, cbe_freqs); | ||
141 | } | ||
142 | |||
143 | static int cbe_cpufreq_target(struct cpufreq_policy *policy, | ||
144 | unsigned int target_freq, | ||
145 | unsigned int relation) | ||
146 | { | ||
147 | int rc; | ||
148 | struct cpufreq_freqs freqs; | ||
149 | unsigned int cbe_pmode_new; | ||
150 | |||
151 | cpufreq_frequency_table_target(policy, | ||
152 | cbe_freqs, | ||
153 | target_freq, | ||
154 | relation, | ||
155 | &cbe_pmode_new); | ||
156 | |||
157 | freqs.old = policy->cur; | ||
158 | freqs.new = cbe_freqs[cbe_pmode_new].frequency; | ||
159 | freqs.cpu = policy->cpu; | ||
160 | |||
161 | mutex_lock(&cbe_switch_mutex); | ||
162 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
163 | |||
164 | pr_debug("setting frequency for cpu %d to %d kHz, " \ | ||
165 | "1/%d of max frequency\n", | ||
166 | policy->cpu, | ||
167 | cbe_freqs[cbe_pmode_new].frequency, | ||
168 | cbe_freqs[cbe_pmode_new].index); | ||
169 | |||
170 | rc = set_pmode(policy->cpu, cbe_pmode_new); | ||
171 | |||
172 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
173 | mutex_unlock(&cbe_switch_mutex); | ||
174 | |||
175 | return rc; | ||
176 | } | ||
177 | |||
178 | static struct cpufreq_driver cbe_cpufreq_driver = { | ||
179 | .verify = cbe_cpufreq_verify, | ||
180 | .target = cbe_cpufreq_target, | ||
181 | .init = cbe_cpufreq_cpu_init, | ||
182 | .exit = cbe_cpufreq_cpu_exit, | ||
183 | .name = "cbe-cpufreq", | ||
184 | .owner = THIS_MODULE, | ||
185 | .flags = CPUFREQ_CONST_LOOPS, | ||
186 | }; | ||
187 | |||
188 | /* | ||
189 | * module init and destoy | ||
190 | */ | ||
191 | |||
192 | static int __init cbe_cpufreq_init(void) | ||
193 | { | ||
194 | if (!machine_is(cell)) | ||
195 | return -ENODEV; | ||
196 | |||
197 | return cpufreq_register_driver(&cbe_cpufreq_driver); | ||
198 | } | ||
199 | |||
200 | static void __exit cbe_cpufreq_exit(void) | ||
201 | { | ||
202 | cpufreq_unregister_driver(&cbe_cpufreq_driver); | ||
203 | } | ||
204 | |||
205 | module_init(cbe_cpufreq_init); | ||
206 | module_exit(cbe_cpufreq_exit); | ||
207 | |||
208 | MODULE_LICENSE("GPL"); | ||
209 | MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); | ||
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.h b/arch/powerpc/platforms/cell/cbe_cpufreq.h deleted file mode 100644 index c1d86bfa92ff..000000000000 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * cbe_cpufreq.h | ||
3 | * | ||
4 | * This file contains the definitions used by the cbe_cpufreq driver. | ||
5 | * | ||
6 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007 | ||
7 | * | ||
8 | * Author: Christian Krafft <krafft@de.ibm.com> | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/cpufreq.h> | ||
13 | #include <linux/types.h> | ||
14 | |||
15 | int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode); | ||
16 | int cbe_cpufreq_get_pmode(int cpu); | ||
17 | |||
18 | int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode); | ||
19 | |||
20 | #if defined(CONFIG_CBE_CPUFREQ_PMI) || defined(CONFIG_CBE_CPUFREQ_PMI_MODULE) | ||
21 | extern bool cbe_cpufreq_has_pmi; | ||
22 | #else | ||
23 | #define cbe_cpufreq_has_pmi (0) | ||
24 | #endif | ||
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c deleted file mode 100644 index 20472e487b6f..000000000000 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c +++ /dev/null | |||
@@ -1,115 +0,0 @@ | |||
1 | /* | ||
2 | * pervasive backend for the cbe_cpufreq driver | ||
3 | * | ||
4 | * This driver makes use of the pervasive unit to | ||
5 | * engage the desired frequency. | ||
6 | * | ||
7 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007 | ||
8 | * | ||
9 | * Author: Christian Krafft <krafft@de.ibm.com> | ||
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 as published by | ||
13 | * the Free Software Foundation; either version 2, or (at your option) | ||
14 | * any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/io.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/time.h> | ||
29 | #include <asm/machdep.h> | ||
30 | #include <asm/hw_irq.h> | ||
31 | #include <asm/cell-regs.h> | ||
32 | |||
33 | #include "cbe_cpufreq.h" | ||
34 | |||
35 | /* to write to MIC register */ | ||
36 | static u64 MIC_Slow_Fast_Timer_table[] = { | ||
37 | [0 ... 7] = 0x007fc00000000000ull, | ||
38 | }; | ||
39 | |||
40 | /* more values for the MIC */ | ||
41 | static u64 MIC_Slow_Next_Timer_table[] = { | ||
42 | 0x0000240000000000ull, | ||
43 | 0x0000268000000000ull, | ||
44 | 0x000029C000000000ull, | ||
45 | 0x00002D0000000000ull, | ||
46 | 0x0000300000000000ull, | ||
47 | 0x0000334000000000ull, | ||
48 | 0x000039C000000000ull, | ||
49 | 0x00003FC000000000ull, | ||
50 | }; | ||
51 | |||
52 | |||
53 | int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode) | ||
54 | { | ||
55 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
56 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; | ||
57 | unsigned long flags; | ||
58 | u64 value; | ||
59 | #ifdef DEBUG | ||
60 | long time; | ||
61 | #endif | ||
62 | |||
63 | local_irq_save(flags); | ||
64 | |||
65 | mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu); | ||
66 | pmd_regs = cbe_get_cpu_pmd_regs(cpu); | ||
67 | |||
68 | #ifdef DEBUG | ||
69 | time = jiffies; | ||
70 | #endif | ||
71 | |||
72 | out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]); | ||
73 | out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]); | ||
74 | |||
75 | out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]); | ||
76 | out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]); | ||
77 | |||
78 | value = in_be64(&pmd_regs->pmcr); | ||
79 | /* set bits to zero */ | ||
80 | value &= 0xFFFFFFFFFFFFFFF8ull; | ||
81 | /* set bits to next pmode */ | ||
82 | value |= pmode; | ||
83 | |||
84 | out_be64(&pmd_regs->pmcr, value); | ||
85 | |||
86 | #ifdef DEBUG | ||
87 | /* wait until new pmode appears in status register */ | ||
88 | value = in_be64(&pmd_regs->pmsr) & 0x07; | ||
89 | while (value != pmode) { | ||
90 | cpu_relax(); | ||
91 | value = in_be64(&pmd_regs->pmsr) & 0x07; | ||
92 | } | ||
93 | |||
94 | time = jiffies - time; | ||
95 | time = jiffies_to_msecs(time); | ||
96 | pr_debug("had to wait %lu ms for a transition using " \ | ||
97 | "pervasive unit\n", time); | ||
98 | #endif | ||
99 | local_irq_restore(flags); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | |||
105 | int cbe_cpufreq_get_pmode(int cpu) | ||
106 | { | ||
107 | int ret; | ||
108 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
109 | |||
110 | pmd_regs = cbe_get_cpu_pmd_regs(cpu); | ||
111 | ret = in_be64(&pmd_regs->pmsr) & 0x07; | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c deleted file mode 100644 index 60a07a4f9326..000000000000 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c +++ /dev/null | |||
@@ -1,156 +0,0 @@ | |||
1 | /* | ||
2 | * pmi backend for the cbe_cpufreq driver | ||
3 | * | ||
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007 | ||
5 | * | ||
6 | * Author: Christian Krafft <krafft@de.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/timer.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/of_platform.h> | ||
28 | |||
29 | #include <asm/processor.h> | ||
30 | #include <asm/prom.h> | ||
31 | #include <asm/pmi.h> | ||
32 | #include <asm/cell-regs.h> | ||
33 | |||
34 | #ifdef DEBUG | ||
35 | #include <asm/time.h> | ||
36 | #endif | ||
37 | |||
38 | #include "cbe_cpufreq.h" | ||
39 | |||
40 | static u8 pmi_slow_mode_limit[MAX_CBE]; | ||
41 | |||
42 | bool cbe_cpufreq_has_pmi = false; | ||
43 | EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi); | ||
44 | |||
45 | /* | ||
46 | * hardware specific functions | ||
47 | */ | ||
48 | |||
49 | int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode) | ||
50 | { | ||
51 | int ret; | ||
52 | pmi_message_t pmi_msg; | ||
53 | #ifdef DEBUG | ||
54 | long time; | ||
55 | #endif | ||
56 | pmi_msg.type = PMI_TYPE_FREQ_CHANGE; | ||
57 | pmi_msg.data1 = cbe_cpu_to_node(cpu); | ||
58 | pmi_msg.data2 = pmode; | ||
59 | |||
60 | #ifdef DEBUG | ||
61 | time = jiffies; | ||
62 | #endif | ||
63 | pmi_send_message(pmi_msg); | ||
64 | |||
65 | #ifdef DEBUG | ||
66 | time = jiffies - time; | ||
67 | time = jiffies_to_msecs(time); | ||
68 | pr_debug("had to wait %lu ms for a transition using " \ | ||
69 | "PMI\n", time); | ||
70 | #endif | ||
71 | ret = pmi_msg.data2; | ||
72 | pr_debug("PMI returned slow mode %d\n", ret); | ||
73 | |||
74 | return ret; | ||
75 | } | ||
76 | EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi); | ||
77 | |||
78 | |||
79 | static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg) | ||
80 | { | ||
81 | u8 node, slow_mode; | ||
82 | |||
83 | BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE); | ||
84 | |||
85 | node = pmi_msg.data1; | ||
86 | slow_mode = pmi_msg.data2; | ||
87 | |||
88 | pmi_slow_mode_limit[node] = slow_mode; | ||
89 | |||
90 | pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node, slow_mode); | ||
91 | } | ||
92 | |||
93 | static int pmi_notifier(struct notifier_block *nb, | ||
94 | unsigned long event, void *data) | ||
95 | { | ||
96 | struct cpufreq_policy *policy = data; | ||
97 | struct cpufreq_frequency_table *cbe_freqs; | ||
98 | u8 node; | ||
99 | |||
100 | /* Should this really be called for CPUFREQ_ADJUST, CPUFREQ_INCOMPATIBLE | ||
101 | * and CPUFREQ_NOTIFY policy events?) | ||
102 | */ | ||
103 | if (event == CPUFREQ_START) | ||
104 | return 0; | ||
105 | |||
106 | cbe_freqs = cpufreq_frequency_get_table(policy->cpu); | ||
107 | node = cbe_cpu_to_node(policy->cpu); | ||
108 | |||
109 | pr_debug("got notified, event=%lu, node=%u\n", event, node); | ||
110 | |||
111 | if (pmi_slow_mode_limit[node] != 0) { | ||
112 | pr_debug("limiting node %d to slow mode %d\n", | ||
113 | node, pmi_slow_mode_limit[node]); | ||
114 | |||
115 | cpufreq_verify_within_limits(policy, 0, | ||
116 | |||
117 | cbe_freqs[pmi_slow_mode_limit[node]].frequency); | ||
118 | } | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static struct notifier_block pmi_notifier_block = { | ||
124 | .notifier_call = pmi_notifier, | ||
125 | }; | ||
126 | |||
127 | static struct pmi_handler cbe_pmi_handler = { | ||
128 | .type = PMI_TYPE_FREQ_CHANGE, | ||
129 | .handle_pmi_message = cbe_cpufreq_handle_pmi, | ||
130 | }; | ||
131 | |||
132 | |||
133 | |||
134 | static int __init cbe_cpufreq_pmi_init(void) | ||
135 | { | ||
136 | cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0; | ||
137 | |||
138 | if (!cbe_cpufreq_has_pmi) | ||
139 | return -ENODEV; | ||
140 | |||
141 | cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static void __exit cbe_cpufreq_pmi_exit(void) | ||
147 | { | ||
148 | cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); | ||
149 | pmi_unregister_handler(&cbe_pmi_handler); | ||
150 | } | ||
151 | |||
152 | module_init(cbe_cpufreq_pmi_init); | ||
153 | module_exit(cbe_cpufreq_pmi_exit); | ||
154 | |||
155 | MODULE_LICENSE("GPL"); | ||
156 | MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); | ||
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c index 890f30e70f98..be1e7958909e 100644 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/arch/powerpc/platforms/pasemi/cpufreq.c | |||
@@ -273,10 +273,9 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy, | |||
273 | 273 | ||
274 | freqs.old = policy->cur; | 274 | freqs.old = policy->cur; |
275 | freqs.new = pas_freqs[pas_astate_new].frequency; | 275 | freqs.new = pas_freqs[pas_astate_new].frequency; |
276 | freqs.cpu = policy->cpu; | ||
277 | 276 | ||
278 | mutex_lock(&pas_switch_mutex); | 277 | mutex_lock(&pas_switch_mutex); |
279 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 278 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); |
280 | 279 | ||
281 | pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", | 280 | pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", |
282 | policy->cpu, | 281 | policy->cpu, |
@@ -288,7 +287,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy, | |||
288 | for_each_online_cpu(i) | 287 | for_each_online_cpu(i) |
289 | set_astate(i, pas_astate_new); | 288 | set_astate(i, pas_astate_new); |
290 | 289 | ||
291 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 290 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); |
292 | mutex_unlock(&pas_switch_mutex); | 291 | mutex_unlock(&pas_switch_mutex); |
293 | 292 | ||
294 | ppc_proc_freq = freqs.new * 1000ul; | 293 | ppc_proc_freq = freqs.new * 1000ul; |
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 311b804353b1..3104fad82480 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c | |||
@@ -335,7 +335,8 @@ static int pmu_set_cpu_speed(int low_speed) | |||
335 | return 0; | 335 | return 0; |
336 | } | 336 | } |
337 | 337 | ||
338 | static int do_set_cpu_speed(int speed_mode, int notify) | 338 | static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode, |
339 | int notify) | ||
339 | { | 340 | { |
340 | struct cpufreq_freqs freqs; | 341 | struct cpufreq_freqs freqs; |
341 | unsigned long l3cr; | 342 | unsigned long l3cr; |
@@ -343,13 +344,12 @@ static int do_set_cpu_speed(int speed_mode, int notify) | |||
343 | 344 | ||
344 | freqs.old = cur_freq; | 345 | freqs.old = cur_freq; |
345 | freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; | 346 | freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; |
346 | freqs.cpu = smp_processor_id(); | ||
347 | 347 | ||
348 | if (freqs.old == freqs.new) | 348 | if (freqs.old == freqs.new) |
349 | return 0; | 349 | return 0; |
350 | 350 | ||
351 | if (notify) | 351 | if (notify) |
352 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 352 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); |
353 | if (speed_mode == CPUFREQ_LOW && | 353 | if (speed_mode == CPUFREQ_LOW && |
354 | cpu_has_feature(CPU_FTR_L3CR)) { | 354 | cpu_has_feature(CPU_FTR_L3CR)) { |
355 | l3cr = _get_L3CR(); | 355 | l3cr = _get_L3CR(); |
@@ -366,7 +366,7 @@ static int do_set_cpu_speed(int speed_mode, int notify) | |||
366 | _set_L3CR(prev_l3cr); | 366 | _set_L3CR(prev_l3cr); |
367 | } | 367 | } |
368 | if (notify) | 368 | if (notify) |
369 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 369 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); |
370 | cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; | 370 | cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; |
371 | 371 | ||
372 | return 0; | 372 | return 0; |
@@ -393,7 +393,7 @@ static int pmac_cpufreq_target( struct cpufreq_policy *policy, | |||
393 | target_freq, relation, &newstate)) | 393 | target_freq, relation, &newstate)) |
394 | return -EINVAL; | 394 | return -EINVAL; |
395 | 395 | ||
396 | rc = do_set_cpu_speed(newstate, 1); | 396 | rc = do_set_cpu_speed(policy, newstate, 1); |
397 | 397 | ||
398 | ppc_proc_freq = cur_freq * 1000ul; | 398 | ppc_proc_freq = cur_freq * 1000ul; |
399 | return rc; | 399 | return rc; |
@@ -442,7 +442,7 @@ static int pmac_cpufreq_suspend(struct cpufreq_policy *policy) | |||
442 | no_schedule = 1; | 442 | no_schedule = 1; |
443 | sleep_freq = cur_freq; | 443 | sleep_freq = cur_freq; |
444 | if (cur_freq == low_freq && !is_pmu_based) | 444 | if (cur_freq == low_freq && !is_pmu_based) |
445 | do_set_cpu_speed(CPUFREQ_HIGH, 0); | 445 | do_set_cpu_speed(policy, CPUFREQ_HIGH, 0); |
446 | return 0; | 446 | return 0; |
447 | } | 447 | } |
448 | 448 | ||
@@ -458,7 +458,7 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy) | |||
458 | * is that we force a switch to whatever it was, which is | 458 | * is that we force a switch to whatever it was, which is |
459 | * probably high speed due to our suspend() routine | 459 | * probably high speed due to our suspend() routine |
460 | */ | 460 | */ |
461 | do_set_cpu_speed(sleep_freq == low_freq ? | 461 | do_set_cpu_speed(policy, sleep_freq == low_freq ? |
462 | CPUFREQ_LOW : CPUFREQ_HIGH, 0); | 462 | CPUFREQ_LOW : CPUFREQ_HIGH, 0); |
463 | 463 | ||
464 | ppc_proc_freq = cur_freq * 1000ul; | 464 | ppc_proc_freq = cur_freq * 1000ul; |
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 9650c6029c82..7ba423431cfe 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c | |||
@@ -339,11 +339,10 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy, | |||
339 | 339 | ||
340 | freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; | 340 | freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; |
341 | freqs.new = g5_cpu_freqs[newstate].frequency; | 341 | freqs.new = g5_cpu_freqs[newstate].frequency; |
342 | freqs.cpu = 0; | ||
343 | 342 | ||
344 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 343 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); |
345 | rc = g5_switch_freq(newstate); | 344 | rc = g5_switch_freq(newstate); |
346 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 345 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); |
347 | 346 | ||
348 | mutex_unlock(&g5_switch_mutex); | 347 | mutex_unlock(&g5_switch_mutex); |
349 | 348 | ||
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 5e859633ce69..06e3163bdc11 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -624,25 +624,7 @@ config SH_CLK_CPG_LEGACY | |||
624 | endmenu | 624 | endmenu |
625 | 625 | ||
626 | menu "CPU Frequency scaling" | 626 | menu "CPU Frequency scaling" |
627 | |||
628 | source "drivers/cpufreq/Kconfig" | 627 | source "drivers/cpufreq/Kconfig" |
629 | |||
630 | config SH_CPU_FREQ | ||
631 | tristate "SuperH CPU Frequency driver" | ||
632 | depends on CPU_FREQ | ||
633 | select CPU_FREQ_TABLE | ||
634 | help | ||
635 | This adds the cpufreq driver for SuperH. Any CPU that supports | ||
636 | clock rate rounding through the clock framework can use this | ||
637 | driver. While it will make the kernel slightly larger, this is | ||
638 | harmless for CPUs that don't support rate rounding. The driver | ||
639 | will also generate a notice in the boot log before disabling | ||
640 | itself if the CPU in question is not capable of rate rounding. | ||
641 | |||
642 | For details, take a look at <file:Documentation/cpu-freq>. | ||
643 | |||
644 | If unsure, say N. | ||
645 | |||
646 | endmenu | 628 | endmenu |
647 | 629 | ||
648 | source "arch/sh/drivers/Kconfig" | 630 | source "arch/sh/drivers/Kconfig" |
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index f259b37874e9..261c8bfd75ce 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -31,7 +31,6 @@ obj-$(CONFIG_VSYSCALL) += vsyscall/ | |||
31 | obj-$(CONFIG_SMP) += smp.o | 31 | obj-$(CONFIG_SMP) += smp.o |
32 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o | 32 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o |
33 | obj-$(CONFIG_KGDB) += kgdb.o | 33 | obj-$(CONFIG_KGDB) += kgdb.o |
34 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o | ||
35 | obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o | 34 | obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o |
36 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 35 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
37 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 36 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c deleted file mode 100644 index e68b45b6f3f9..000000000000 --- a/arch/sh/kernel/cpufreq.c +++ /dev/null | |||
@@ -1,201 +0,0 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpufreq.c | ||
3 | * | ||
4 | * cpufreq driver for the SuperH processors. | ||
5 | * | ||
6 | * Copyright (C) 2002 - 2012 Paul Mundt | ||
7 | * Copyright (C) 2002 M. R. Brown | ||
8 | * | ||
9 | * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c | ||
10 | * | ||
11 | * Copyright (C) 2004-2007 Atmel Corporation | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General Public | ||
14 | * License. See the file "COPYING" in the main directory of this archive | ||
15 | * for more details. | ||
16 | */ | ||
17 | #define pr_fmt(fmt) "cpufreq: " fmt | ||
18 | |||
19 | #include <linux/types.h> | ||
20 | #include <linux/cpufreq.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/cpumask.h> | ||
26 | #include <linux/cpu.h> | ||
27 | #include <linux/smp.h> | ||
28 | #include <linux/sched.h> /* set_cpus_allowed() */ | ||
29 | #include <linux/clk.h> | ||
30 | #include <linux/percpu.h> | ||
31 | #include <linux/sh_clk.h> | ||
32 | |||
33 | static DEFINE_PER_CPU(struct clk, sh_cpuclk); | ||
34 | |||
35 | static unsigned int sh_cpufreq_get(unsigned int cpu) | ||
36 | { | ||
37 | return (clk_get_rate(&per_cpu(sh_cpuclk, cpu)) + 500) / 1000; | ||
38 | } | ||
39 | |||
40 | /* | ||
41 | * Here we notify other drivers of the proposed change and the final change. | ||
42 | */ | ||
43 | static int sh_cpufreq_target(struct cpufreq_policy *policy, | ||
44 | unsigned int target_freq, | ||
45 | unsigned int relation) | ||
46 | { | ||
47 | unsigned int cpu = policy->cpu; | ||
48 | struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); | ||
49 | cpumask_t cpus_allowed; | ||
50 | struct cpufreq_freqs freqs; | ||
51 | struct device *dev; | ||
52 | long freq; | ||
53 | |||
54 | if (!cpu_online(cpu)) | ||
55 | return -ENODEV; | ||
56 | |||
57 | cpus_allowed = current->cpus_allowed; | ||
58 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
59 | |||
60 | BUG_ON(smp_processor_id() != cpu); | ||
61 | |||
62 | dev = get_cpu_device(cpu); | ||
63 | |||
64 | /* Convert target_freq from kHz to Hz */ | ||
65 | freq = clk_round_rate(cpuclk, target_freq * 1000); | ||
66 | |||
67 | if (freq < (policy->min * 1000) || freq > (policy->max * 1000)) | ||
68 | return -EINVAL; | ||
69 | |||
70 | dev_dbg(dev, "requested frequency %u Hz\n", target_freq * 1000); | ||
71 | |||
72 | freqs.cpu = cpu; | ||
73 | freqs.old = sh_cpufreq_get(cpu); | ||
74 | freqs.new = (freq + 500) / 1000; | ||
75 | freqs.flags = 0; | ||
76 | |||
77 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
78 | set_cpus_allowed_ptr(current, &cpus_allowed); | ||
79 | clk_set_rate(cpuclk, freq); | ||
80 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
81 | |||
82 | dev_dbg(dev, "set frequency %lu Hz\n", freq); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int sh_cpufreq_verify(struct cpufreq_policy *policy) | ||
88 | { | ||
89 | struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu); | ||
90 | struct cpufreq_frequency_table *freq_table; | ||
91 | |||
92 | freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; | ||
93 | if (freq_table) | ||
94 | return cpufreq_frequency_table_verify(policy, freq_table); | ||
95 | |||
96 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
97 | policy->cpuinfo.max_freq); | ||
98 | |||
99 | policy->min = (clk_round_rate(cpuclk, 1) + 500) / 1000; | ||
100 | policy->max = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; | ||
101 | |||
102 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
103 | policy->cpuinfo.max_freq); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
109 | { | ||
110 | unsigned int cpu = policy->cpu; | ||
111 | struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); | ||
112 | struct cpufreq_frequency_table *freq_table; | ||
113 | struct device *dev; | ||
114 | |||
115 | if (!cpu_online(cpu)) | ||
116 | return -ENODEV; | ||
117 | |||
118 | dev = get_cpu_device(cpu); | ||
119 | |||
120 | cpuclk = clk_get(dev, "cpu_clk"); | ||
121 | if (IS_ERR(cpuclk)) { | ||
122 | dev_err(dev, "couldn't get CPU clk\n"); | ||
123 | return PTR_ERR(cpuclk); | ||
124 | } | ||
125 | |||
126 | policy->cur = policy->min = policy->max = sh_cpufreq_get(cpu); | ||
127 | |||
128 | freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; | ||
129 | if (freq_table) { | ||
130 | int result; | ||
131 | |||
132 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
133 | if (!result) | ||
134 | cpufreq_frequency_table_get_attr(freq_table, cpu); | ||
135 | } else { | ||
136 | dev_notice(dev, "no frequency table found, falling back " | ||
137 | "to rate rounding.\n"); | ||
138 | |||
139 | policy->cpuinfo.min_freq = | ||
140 | (clk_round_rate(cpuclk, 1) + 500) / 1000; | ||
141 | policy->cpuinfo.max_freq = | ||
142 | (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; | ||
143 | } | ||
144 | |||
145 | policy->min = policy->cpuinfo.min_freq; | ||
146 | policy->max = policy->cpuinfo.max_freq; | ||
147 | |||
148 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | ||
149 | |||
150 | dev_info(dev, "CPU Frequencies - Minimum %u.%03u MHz, " | ||
151 | "Maximum %u.%03u MHz.\n", | ||
152 | policy->min / 1000, policy->min % 1000, | ||
153 | policy->max / 1000, policy->max % 1000); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy) | ||
159 | { | ||
160 | unsigned int cpu = policy->cpu; | ||
161 | struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); | ||
162 | |||
163 | cpufreq_frequency_table_put_attr(cpu); | ||
164 | clk_put(cpuclk); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static struct freq_attr *sh_freq_attr[] = { | ||
170 | &cpufreq_freq_attr_scaling_available_freqs, | ||
171 | NULL, | ||
172 | }; | ||
173 | |||
174 | static struct cpufreq_driver sh_cpufreq_driver = { | ||
175 | .owner = THIS_MODULE, | ||
176 | .name = "sh", | ||
177 | .get = sh_cpufreq_get, | ||
178 | .target = sh_cpufreq_target, | ||
179 | .verify = sh_cpufreq_verify, | ||
180 | .init = sh_cpufreq_cpu_init, | ||
181 | .exit = sh_cpufreq_cpu_exit, | ||
182 | .attr = sh_freq_attr, | ||
183 | }; | ||
184 | |||
185 | static int __init sh_cpufreq_module_init(void) | ||
186 | { | ||
187 | pr_notice("SuperH CPU frequency driver.\n"); | ||
188 | return cpufreq_register_driver(&sh_cpufreq_driver); | ||
189 | } | ||
190 | |||
191 | static void __exit sh_cpufreq_module_exit(void) | ||
192 | { | ||
193 | cpufreq_unregister_driver(&sh_cpufreq_driver); | ||
194 | } | ||
195 | |||
196 | module_init(sh_cpufreq_module_init); | ||
197 | module_exit(sh_cpufreq_module_exit); | ||
198 | |||
199 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); | ||
200 | MODULE_DESCRIPTION("cpufreq driver for SuperH"); | ||
201 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 3d361f236308..c85b76100e3f 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -254,29 +254,6 @@ config HOTPLUG_CPU | |||
254 | 254 | ||
255 | if SPARC64 | 255 | if SPARC64 |
256 | source "drivers/cpufreq/Kconfig" | 256 | source "drivers/cpufreq/Kconfig" |
257 | |||
258 | config US3_FREQ | ||
259 | tristate "UltraSPARC-III CPU Frequency driver" | ||
260 | depends on CPU_FREQ | ||
261 | select CPU_FREQ_TABLE | ||
262 | help | ||
263 | This adds the CPUFreq driver for UltraSPARC-III processors. | ||
264 | |||
265 | For details, take a look at <file:Documentation/cpu-freq>. | ||
266 | |||
267 | If in doubt, say N. | ||
268 | |||
269 | config US2E_FREQ | ||
270 | tristate "UltraSPARC-IIe CPU Frequency driver" | ||
271 | depends on CPU_FREQ | ||
272 | select CPU_FREQ_TABLE | ||
273 | help | ||
274 | This adds the CPUFreq driver for UltraSPARC-IIe processors. | ||
275 | |||
276 | For details, take a look at <file:Documentation/cpu-freq>. | ||
277 | |||
278 | If in doubt, say N. | ||
279 | |||
280 | endif | 257 | endif |
281 | 258 | ||
282 | config US3_MC | 259 | config US3_MC |
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 6cf591b7e1c6..5276fd4e9d03 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile | |||
@@ -102,9 +102,6 @@ obj-$(CONFIG_PCI_MSI) += pci_msi.o | |||
102 | 102 | ||
103 | obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o | 103 | obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o |
104 | 104 | ||
105 | # sparc64 cpufreq | ||
106 | obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o | ||
107 | obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o | ||
108 | obj-$(CONFIG_US3_MC) += chmc.o | 105 | obj-$(CONFIG_US3_MC) += chmc.o |
109 | 106 | ||
110 | obj-$(CONFIG_KPROBES) += kprobes.o | 107 | obj-$(CONFIG_KPROBES) += kprobes.o |
diff --git a/arch/sparc/kernel/us2e_cpufreq.c b/arch/sparc/kernel/us2e_cpufreq.c deleted file mode 100644 index 489fc15f3194..000000000000 --- a/arch/sparc/kernel/us2e_cpufreq.c +++ /dev/null | |||
@@ -1,413 +0,0 @@ | |||
1 | /* us2e_cpufreq.c: UltraSPARC-IIe cpu frequency support | ||
2 | * | ||
3 | * Copyright (C) 2003 David S. Miller (davem@redhat.com) | ||
4 | * | ||
5 | * Many thanks to Dominik Brodowski for fixing up the cpufreq | ||
6 | * infrastructure in order to make this driver easier to implement. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/cpufreq.h> | ||
14 | #include <linux/threads.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/asi.h> | ||
20 | #include <asm/timer.h> | ||
21 | |||
22 | static struct cpufreq_driver *cpufreq_us2e_driver; | ||
23 | |||
24 | struct us2e_freq_percpu_info { | ||
25 | struct cpufreq_frequency_table table[6]; | ||
26 | }; | ||
27 | |||
28 | /* Indexed by cpu number. */ | ||
29 | static struct us2e_freq_percpu_info *us2e_freq_table; | ||
30 | |||
31 | #define HBIRD_MEM_CNTL0_ADDR 0x1fe0000f010UL | ||
32 | #define HBIRD_ESTAR_MODE_ADDR 0x1fe0000f080UL | ||
33 | |||
34 | /* UltraSPARC-IIe has five dividers: 1, 2, 4, 6, and 8. These are controlled | ||
35 | * in the ESTAR mode control register. | ||
36 | */ | ||
37 | #define ESTAR_MODE_DIV_1 0x0000000000000000UL | ||
38 | #define ESTAR_MODE_DIV_2 0x0000000000000001UL | ||
39 | #define ESTAR_MODE_DIV_4 0x0000000000000003UL | ||
40 | #define ESTAR_MODE_DIV_6 0x0000000000000002UL | ||
41 | #define ESTAR_MODE_DIV_8 0x0000000000000004UL | ||
42 | #define ESTAR_MODE_DIV_MASK 0x0000000000000007UL | ||
43 | |||
44 | #define MCTRL0_SREFRESH_ENAB 0x0000000000010000UL | ||
45 | #define MCTRL0_REFR_COUNT_MASK 0x0000000000007f00UL | ||
46 | #define MCTRL0_REFR_COUNT_SHIFT 8 | ||
47 | #define MCTRL0_REFR_INTERVAL 7800 | ||
48 | #define MCTRL0_REFR_CLKS_P_CNT 64 | ||
49 | |||
50 | static unsigned long read_hbreg(unsigned long addr) | ||
51 | { | ||
52 | unsigned long ret; | ||
53 | |||
54 | __asm__ __volatile__("ldxa [%1] %2, %0" | ||
55 | : "=&r" (ret) | ||
56 | : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)); | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static void write_hbreg(unsigned long addr, unsigned long val) | ||
61 | { | ||
62 | __asm__ __volatile__("stxa %0, [%1] %2\n\t" | ||
63 | "membar #Sync" | ||
64 | : /* no outputs */ | ||
65 | : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E) | ||
66 | : "memory"); | ||
67 | if (addr == HBIRD_ESTAR_MODE_ADDR) { | ||
68 | /* Need to wait 16 clock cycles for the PLL to lock. */ | ||
69 | udelay(1); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static void self_refresh_ctl(int enable) | ||
74 | { | ||
75 | unsigned long mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); | ||
76 | |||
77 | if (enable) | ||
78 | mctrl |= MCTRL0_SREFRESH_ENAB; | ||
79 | else | ||
80 | mctrl &= ~MCTRL0_SREFRESH_ENAB; | ||
81 | write_hbreg(HBIRD_MEM_CNTL0_ADDR, mctrl); | ||
82 | (void) read_hbreg(HBIRD_MEM_CNTL0_ADDR); | ||
83 | } | ||
84 | |||
85 | static void frob_mem_refresh(int cpu_slowing_down, | ||
86 | unsigned long clock_tick, | ||
87 | unsigned long old_divisor, unsigned long divisor) | ||
88 | { | ||
89 | unsigned long old_refr_count, refr_count, mctrl; | ||
90 | |||
91 | refr_count = (clock_tick * MCTRL0_REFR_INTERVAL); | ||
92 | refr_count /= (MCTRL0_REFR_CLKS_P_CNT * divisor * 1000000000UL); | ||
93 | |||
94 | mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); | ||
95 | old_refr_count = (mctrl & MCTRL0_REFR_COUNT_MASK) | ||
96 | >> MCTRL0_REFR_COUNT_SHIFT; | ||
97 | |||
98 | mctrl &= ~MCTRL0_REFR_COUNT_MASK; | ||
99 | mctrl |= refr_count << MCTRL0_REFR_COUNT_SHIFT; | ||
100 | write_hbreg(HBIRD_MEM_CNTL0_ADDR, mctrl); | ||
101 | mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); | ||
102 | |||
103 | if (cpu_slowing_down && !(mctrl & MCTRL0_SREFRESH_ENAB)) { | ||
104 | unsigned long usecs; | ||
105 | |||
106 | /* We have to wait for both refresh counts (old | ||
107 | * and new) to go to zero. | ||
108 | */ | ||
109 | usecs = (MCTRL0_REFR_CLKS_P_CNT * | ||
110 | (refr_count + old_refr_count) * | ||
111 | 1000000UL * | ||
112 | old_divisor) / clock_tick; | ||
113 | udelay(usecs + 1UL); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | static void us2e_transition(unsigned long estar, unsigned long new_bits, | ||
118 | unsigned long clock_tick, | ||
119 | unsigned long old_divisor, unsigned long divisor) | ||
120 | { | ||
121 | unsigned long flags; | ||
122 | |||
123 | local_irq_save(flags); | ||
124 | |||
125 | estar &= ~ESTAR_MODE_DIV_MASK; | ||
126 | |||
127 | /* This is based upon the state transition diagram in the IIe manual. */ | ||
128 | if (old_divisor == 2 && divisor == 1) { | ||
129 | self_refresh_ctl(0); | ||
130 | write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); | ||
131 | frob_mem_refresh(0, clock_tick, old_divisor, divisor); | ||
132 | } else if (old_divisor == 1 && divisor == 2) { | ||
133 | frob_mem_refresh(1, clock_tick, old_divisor, divisor); | ||
134 | write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); | ||
135 | self_refresh_ctl(1); | ||
136 | } else if (old_divisor == 1 && divisor > 2) { | ||
137 | us2e_transition(estar, ESTAR_MODE_DIV_2, clock_tick, | ||
138 | 1, 2); | ||
139 | us2e_transition(estar, new_bits, clock_tick, | ||
140 | 2, divisor); | ||
141 | } else if (old_divisor > 2 && divisor == 1) { | ||
142 | us2e_transition(estar, ESTAR_MODE_DIV_2, clock_tick, | ||
143 | old_divisor, 2); | ||
144 | us2e_transition(estar, new_bits, clock_tick, | ||
145 | 2, divisor); | ||
146 | } else if (old_divisor < divisor) { | ||
147 | frob_mem_refresh(0, clock_tick, old_divisor, divisor); | ||
148 | write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); | ||
149 | } else if (old_divisor > divisor) { | ||
150 | write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); | ||
151 | frob_mem_refresh(1, clock_tick, old_divisor, divisor); | ||
152 | } else { | ||
153 | BUG(); | ||
154 | } | ||
155 | |||
156 | local_irq_restore(flags); | ||
157 | } | ||
158 | |||
159 | static unsigned long index_to_estar_mode(unsigned int index) | ||
160 | { | ||
161 | switch (index) { | ||
162 | case 0: | ||
163 | return ESTAR_MODE_DIV_1; | ||
164 | |||
165 | case 1: | ||
166 | return ESTAR_MODE_DIV_2; | ||
167 | |||
168 | case 2: | ||
169 | return ESTAR_MODE_DIV_4; | ||
170 | |||
171 | case 3: | ||
172 | return ESTAR_MODE_DIV_6; | ||
173 | |||
174 | case 4: | ||
175 | return ESTAR_MODE_DIV_8; | ||
176 | |||
177 | default: | ||
178 | BUG(); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | static unsigned long index_to_divisor(unsigned int index) | ||
183 | { | ||
184 | switch (index) { | ||
185 | case 0: | ||
186 | return 1; | ||
187 | |||
188 | case 1: | ||
189 | return 2; | ||
190 | |||
191 | case 2: | ||
192 | return 4; | ||
193 | |||
194 | case 3: | ||
195 | return 6; | ||
196 | |||
197 | case 4: | ||
198 | return 8; | ||
199 | |||
200 | default: | ||
201 | BUG(); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static unsigned long estar_to_divisor(unsigned long estar) | ||
206 | { | ||
207 | unsigned long ret; | ||
208 | |||
209 | switch (estar & ESTAR_MODE_DIV_MASK) { | ||
210 | case ESTAR_MODE_DIV_1: | ||
211 | ret = 1; | ||
212 | break; | ||
213 | case ESTAR_MODE_DIV_2: | ||
214 | ret = 2; | ||
215 | break; | ||
216 | case ESTAR_MODE_DIV_4: | ||
217 | ret = 4; | ||
218 | break; | ||
219 | case ESTAR_MODE_DIV_6: | ||
220 | ret = 6; | ||
221 | break; | ||
222 | case ESTAR_MODE_DIV_8: | ||
223 | ret = 8; | ||
224 | break; | ||
225 | default: | ||
226 | BUG(); | ||
227 | } | ||
228 | |||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | static unsigned int us2e_freq_get(unsigned int cpu) | ||
233 | { | ||
234 | cpumask_t cpus_allowed; | ||
235 | unsigned long clock_tick, estar; | ||
236 | |||
237 | if (!cpu_online(cpu)) | ||
238 | return 0; | ||
239 | |||
240 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); | ||
241 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
242 | |||
243 | clock_tick = sparc64_get_clock_tick(cpu) / 1000; | ||
244 | estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR); | ||
245 | |||
246 | set_cpus_allowed_ptr(current, &cpus_allowed); | ||
247 | |||
248 | return clock_tick / estar_to_divisor(estar); | ||
249 | } | ||
250 | |||
251 | static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index) | ||
252 | { | ||
253 | unsigned long new_bits, new_freq; | ||
254 | unsigned long clock_tick, divisor, old_divisor, estar; | ||
255 | cpumask_t cpus_allowed; | ||
256 | struct cpufreq_freqs freqs; | ||
257 | |||
258 | if (!cpu_online(cpu)) | ||
259 | return; | ||
260 | |||
261 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); | ||
262 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
263 | |||
264 | new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000; | ||
265 | new_bits = index_to_estar_mode(index); | ||
266 | divisor = index_to_divisor(index); | ||
267 | new_freq /= divisor; | ||
268 | |||
269 | estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR); | ||
270 | |||
271 | old_divisor = estar_to_divisor(estar); | ||
272 | |||
273 | freqs.old = clock_tick / old_divisor; | ||
274 | freqs.new = new_freq; | ||
275 | freqs.cpu = cpu; | ||
276 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
277 | |||
278 | if (old_divisor != divisor) | ||
279 | us2e_transition(estar, new_bits, clock_tick * 1000, | ||
280 | old_divisor, divisor); | ||
281 | |||
282 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
283 | |||
284 | set_cpus_allowed_ptr(current, &cpus_allowed); | ||
285 | } | ||
286 | |||
287 | static int us2e_freq_target(struct cpufreq_policy *policy, | ||
288 | unsigned int target_freq, | ||
289 | unsigned int relation) | ||
290 | { | ||
291 | unsigned int new_index = 0; | ||
292 | |||
293 | if (cpufreq_frequency_table_target(policy, | ||
294 | &us2e_freq_table[policy->cpu].table[0], | ||
295 | target_freq, relation, &new_index)) | ||
296 | return -EINVAL; | ||
297 | |||
298 | us2e_set_cpu_divider_index(policy->cpu, new_index); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int us2e_freq_verify(struct cpufreq_policy *policy) | ||
304 | { | ||
305 | return cpufreq_frequency_table_verify(policy, | ||
306 | &us2e_freq_table[policy->cpu].table[0]); | ||
307 | } | ||
308 | |||
309 | static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) | ||
310 | { | ||
311 | unsigned int cpu = policy->cpu; | ||
312 | unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; | ||
313 | struct cpufreq_frequency_table *table = | ||
314 | &us2e_freq_table[cpu].table[0]; | ||
315 | |||
316 | table[0].index = 0; | ||
317 | table[0].frequency = clock_tick / 1; | ||
318 | table[1].index = 1; | ||
319 | table[1].frequency = clock_tick / 2; | ||
320 | table[2].index = 2; | ||
321 | table[2].frequency = clock_tick / 4; | ||
322 | table[2].index = 3; | ||
323 | table[2].frequency = clock_tick / 6; | ||
324 | table[2].index = 4; | ||
325 | table[2].frequency = clock_tick / 8; | ||
326 | table[2].index = 5; | ||
327 | table[3].frequency = CPUFREQ_TABLE_END; | ||
328 | |||
329 | policy->cpuinfo.transition_latency = 0; | ||
330 | policy->cur = clock_tick; | ||
331 | |||
332 | return cpufreq_frequency_table_cpuinfo(policy, table); | ||
333 | } | ||
334 | |||
335 | static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) | ||
336 | { | ||
337 | if (cpufreq_us2e_driver) | ||
338 | us2e_set_cpu_divider_index(policy->cpu, 0); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int __init us2e_freq_init(void) | ||
344 | { | ||
345 | unsigned long manuf, impl, ver; | ||
346 | int ret; | ||
347 | |||
348 | if (tlb_type != spitfire) | ||
349 | return -ENODEV; | ||
350 | |||
351 | __asm__("rdpr %%ver, %0" : "=r" (ver)); | ||
352 | manuf = ((ver >> 48) & 0xffff); | ||
353 | impl = ((ver >> 32) & 0xffff); | ||
354 | |||
355 | if (manuf == 0x17 && impl == 0x13) { | ||
356 | struct cpufreq_driver *driver; | ||
357 | |||
358 | ret = -ENOMEM; | ||
359 | driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); | ||
360 | if (!driver) | ||
361 | goto err_out; | ||
362 | |||
363 | us2e_freq_table = kzalloc( | ||
364 | (NR_CPUS * sizeof(struct us2e_freq_percpu_info)), | ||
365 | GFP_KERNEL); | ||
366 | if (!us2e_freq_table) | ||
367 | goto err_out; | ||
368 | |||
369 | driver->init = us2e_freq_cpu_init; | ||
370 | driver->verify = us2e_freq_verify; | ||
371 | driver->target = us2e_freq_target; | ||
372 | driver->get = us2e_freq_get; | ||
373 | driver->exit = us2e_freq_cpu_exit; | ||
374 | driver->owner = THIS_MODULE, | ||
375 | strcpy(driver->name, "UltraSPARC-IIe"); | ||
376 | |||
377 | cpufreq_us2e_driver = driver; | ||
378 | ret = cpufreq_register_driver(driver); | ||
379 | if (ret) | ||
380 | goto err_out; | ||
381 | |||
382 | return 0; | ||
383 | |||
384 | err_out: | ||
385 | if (driver) { | ||
386 | kfree(driver); | ||
387 | cpufreq_us2e_driver = NULL; | ||
388 | } | ||
389 | kfree(us2e_freq_table); | ||
390 | us2e_freq_table = NULL; | ||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | return -ENODEV; | ||
395 | } | ||
396 | |||
397 | static void __exit us2e_freq_exit(void) | ||
398 | { | ||
399 | if (cpufreq_us2e_driver) { | ||
400 | cpufreq_unregister_driver(cpufreq_us2e_driver); | ||
401 | kfree(cpufreq_us2e_driver); | ||
402 | cpufreq_us2e_driver = NULL; | ||
403 | kfree(us2e_freq_table); | ||
404 | us2e_freq_table = NULL; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); | ||
409 | MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-IIe"); | ||
410 | MODULE_LICENSE("GPL"); | ||
411 | |||
412 | module_init(us2e_freq_init); | ||
413 | module_exit(us2e_freq_exit); | ||
diff --git a/arch/sparc/kernel/us3_cpufreq.c b/arch/sparc/kernel/us3_cpufreq.c deleted file mode 100644 index eb1624b931d9..000000000000 --- a/arch/sparc/kernel/us3_cpufreq.c +++ /dev/null | |||
@@ -1,274 +0,0 @@ | |||
1 | /* us3_cpufreq.c: UltraSPARC-III cpu frequency support | ||
2 | * | ||
3 | * Copyright (C) 2003 David S. Miller (davem@redhat.com) | ||
4 | * | ||
5 | * Many thanks to Dominik Brodowski for fixing up the cpufreq | ||
6 | * infrastructure in order to make this driver easier to implement. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/cpufreq.h> | ||
14 | #include <linux/threads.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/init.h> | ||
17 | |||
18 | #include <asm/head.h> | ||
19 | #include <asm/timer.h> | ||
20 | |||
21 | static struct cpufreq_driver *cpufreq_us3_driver; | ||
22 | |||
23 | struct us3_freq_percpu_info { | ||
24 | struct cpufreq_frequency_table table[4]; | ||
25 | }; | ||
26 | |||
27 | /* Indexed by cpu number. */ | ||
28 | static struct us3_freq_percpu_info *us3_freq_table; | ||
29 | |||
30 | /* UltraSPARC-III has three dividers: 1, 2, and 32. These are controlled | ||
31 | * in the Safari config register. | ||
32 | */ | ||
33 | #define SAFARI_CFG_DIV_1 0x0000000000000000UL | ||
34 | #define SAFARI_CFG_DIV_2 0x0000000040000000UL | ||
35 | #define SAFARI_CFG_DIV_32 0x0000000080000000UL | ||
36 | #define SAFARI_CFG_DIV_MASK 0x00000000C0000000UL | ||
37 | |||
38 | static unsigned long read_safari_cfg(void) | ||
39 | { | ||
40 | unsigned long ret; | ||
41 | |||
42 | __asm__ __volatile__("ldxa [%%g0] %1, %0" | ||
43 | : "=&r" (ret) | ||
44 | : "i" (ASI_SAFARI_CONFIG)); | ||
45 | return ret; | ||
46 | } | ||
47 | |||
48 | static void write_safari_cfg(unsigned long val) | ||
49 | { | ||
50 | __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" | ||
51 | "membar #Sync" | ||
52 | : /* no outputs */ | ||
53 | : "r" (val), "i" (ASI_SAFARI_CONFIG) | ||
54 | : "memory"); | ||
55 | } | ||
56 | |||
57 | static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg) | ||
58 | { | ||
59 | unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; | ||
60 | unsigned long ret; | ||
61 | |||
62 | switch (safari_cfg & SAFARI_CFG_DIV_MASK) { | ||
63 | case SAFARI_CFG_DIV_1: | ||
64 | ret = clock_tick / 1; | ||
65 | break; | ||
66 | case SAFARI_CFG_DIV_2: | ||
67 | ret = clock_tick / 2; | ||
68 | break; | ||
69 | case SAFARI_CFG_DIV_32: | ||
70 | ret = clock_tick / 32; | ||
71 | break; | ||
72 | default: | ||
73 | BUG(); | ||
74 | } | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | static unsigned int us3_freq_get(unsigned int cpu) | ||
80 | { | ||
81 | cpumask_t cpus_allowed; | ||
82 | unsigned long reg; | ||
83 | unsigned int ret; | ||
84 | |||
85 | if (!cpu_online(cpu)) | ||
86 | return 0; | ||
87 | |||
88 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); | ||
89 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
90 | |||
91 | reg = read_safari_cfg(); | ||
92 | ret = get_current_freq(cpu, reg); | ||
93 | |||
94 | set_cpus_allowed_ptr(current, &cpus_allowed); | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) | ||
100 | { | ||
101 | unsigned long new_bits, new_freq, reg; | ||
102 | cpumask_t cpus_allowed; | ||
103 | struct cpufreq_freqs freqs; | ||
104 | |||
105 | if (!cpu_online(cpu)) | ||
106 | return; | ||
107 | |||
108 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); | ||
109 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | ||
110 | |||
111 | new_freq = sparc64_get_clock_tick(cpu) / 1000; | ||
112 | switch (index) { | ||
113 | case 0: | ||
114 | new_bits = SAFARI_CFG_DIV_1; | ||
115 | new_freq /= 1; | ||
116 | break; | ||
117 | case 1: | ||
118 | new_bits = SAFARI_CFG_DIV_2; | ||
119 | new_freq /= 2; | ||
120 | break; | ||
121 | case 2: | ||
122 | new_bits = SAFARI_CFG_DIV_32; | ||
123 | new_freq /= 32; | ||
124 | break; | ||
125 | |||
126 | default: | ||
127 | BUG(); | ||
128 | } | ||
129 | |||
130 | reg = read_safari_cfg(); | ||
131 | |||
132 | freqs.old = get_current_freq(cpu, reg); | ||
133 | freqs.new = new_freq; | ||
134 | freqs.cpu = cpu; | ||
135 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
136 | |||
137 | reg &= ~SAFARI_CFG_DIV_MASK; | ||
138 | reg |= new_bits; | ||
139 | write_safari_cfg(reg); | ||
140 | |||
141 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
142 | |||
143 | set_cpus_allowed_ptr(current, &cpus_allowed); | ||
144 | } | ||
145 | |||
146 | static int us3_freq_target(struct cpufreq_policy *policy, | ||
147 | unsigned int target_freq, | ||
148 | unsigned int relation) | ||
149 | { | ||
150 | unsigned int new_index = 0; | ||
151 | |||
152 | if (cpufreq_frequency_table_target(policy, | ||
153 | &us3_freq_table[policy->cpu].table[0], | ||
154 | target_freq, | ||
155 | relation, | ||
156 | &new_index)) | ||
157 | return -EINVAL; | ||
158 | |||
159 | us3_set_cpu_divider_index(policy->cpu, new_index); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int us3_freq_verify(struct cpufreq_policy *policy) | ||
165 | { | ||
166 | return cpufreq_frequency_table_verify(policy, | ||
167 | &us3_freq_table[policy->cpu].table[0]); | ||
168 | } | ||
169 | |||
170 | static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) | ||
171 | { | ||
172 | unsigned int cpu = policy->cpu; | ||
173 | unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; | ||
174 | struct cpufreq_frequency_table *table = | ||
175 | &us3_freq_table[cpu].table[0]; | ||
176 | |||
177 | table[0].index = 0; | ||
178 | table[0].frequency = clock_tick / 1; | ||
179 | table[1].index = 1; | ||
180 | table[1].frequency = clock_tick / 2; | ||
181 | table[2].index = 2; | ||
182 | table[2].frequency = clock_tick / 32; | ||
183 | table[3].index = 0; | ||
184 | table[3].frequency = CPUFREQ_TABLE_END; | ||
185 | |||
186 | policy->cpuinfo.transition_latency = 0; | ||
187 | policy->cur = clock_tick; | ||
188 | |||
189 | return cpufreq_frequency_table_cpuinfo(policy, table); | ||
190 | } | ||
191 | |||
192 | static int us3_freq_cpu_exit(struct cpufreq_policy *policy) | ||
193 | { | ||
194 | if (cpufreq_us3_driver) | ||
195 | us3_set_cpu_divider_index(policy->cpu, 0); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static int __init us3_freq_init(void) | ||
201 | { | ||
202 | unsigned long manuf, impl, ver; | ||
203 | int ret; | ||
204 | |||
205 | if (tlb_type != cheetah && tlb_type != cheetah_plus) | ||
206 | return -ENODEV; | ||
207 | |||
208 | __asm__("rdpr %%ver, %0" : "=r" (ver)); | ||
209 | manuf = ((ver >> 48) & 0xffff); | ||
210 | impl = ((ver >> 32) & 0xffff); | ||
211 | |||
212 | if (manuf == CHEETAH_MANUF && | ||
213 | (impl == CHEETAH_IMPL || | ||
214 | impl == CHEETAH_PLUS_IMPL || | ||
215 | impl == JAGUAR_IMPL || | ||
216 | impl == PANTHER_IMPL)) { | ||
217 | struct cpufreq_driver *driver; | ||
218 | |||
219 | ret = -ENOMEM; | ||
220 | driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); | ||
221 | if (!driver) | ||
222 | goto err_out; | ||
223 | |||
224 | us3_freq_table = kzalloc( | ||
225 | (NR_CPUS * sizeof(struct us3_freq_percpu_info)), | ||
226 | GFP_KERNEL); | ||
227 | if (!us3_freq_table) | ||
228 | goto err_out; | ||
229 | |||
230 | driver->init = us3_freq_cpu_init; | ||
231 | driver->verify = us3_freq_verify; | ||
232 | driver->target = us3_freq_target; | ||
233 | driver->get = us3_freq_get; | ||
234 | driver->exit = us3_freq_cpu_exit; | ||
235 | driver->owner = THIS_MODULE, | ||
236 | strcpy(driver->name, "UltraSPARC-III"); | ||
237 | |||
238 | cpufreq_us3_driver = driver; | ||
239 | ret = cpufreq_register_driver(driver); | ||
240 | if (ret) | ||
241 | goto err_out; | ||
242 | |||
243 | return 0; | ||
244 | |||
245 | err_out: | ||
246 | if (driver) { | ||
247 | kfree(driver); | ||
248 | cpufreq_us3_driver = NULL; | ||
249 | } | ||
250 | kfree(us3_freq_table); | ||
251 | us3_freq_table = NULL; | ||
252 | return ret; | ||
253 | } | ||
254 | |||
255 | return -ENODEV; | ||
256 | } | ||
257 | |||
258 | static void __exit us3_freq_exit(void) | ||
259 | { | ||
260 | if (cpufreq_us3_driver) { | ||
261 | cpufreq_unregister_driver(cpufreq_us3_driver); | ||
262 | kfree(cpufreq_us3_driver); | ||
263 | cpufreq_us3_driver = NULL; | ||
264 | kfree(us3_freq_table); | ||
265 | us3_freq_table = NULL; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); | ||
270 | MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-III"); | ||
271 | MODULE_LICENSE("GPL"); | ||
272 | |||
273 | module_init(us3_freq_init); | ||
274 | module_exit(us3_freq_exit); | ||
diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile index fa497e0efe5a..607a72f2ae35 100644 --- a/arch/unicore32/kernel/Makefile +++ b/arch/unicore32/kernel/Makefile | |||
@@ -9,7 +9,6 @@ obj-y += setup.o signal.o sys.o stacktrace.o traps.o | |||
9 | obj-$(CONFIG_MODULES) += ksyms.o module.o | 9 | obj-$(CONFIG_MODULES) += ksyms.o module.o |
10 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 10 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
11 | 11 | ||
12 | obj-$(CONFIG_CPU_FREQ) += cpu-ucv2.o | ||
13 | obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o | 12 | obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o |
14 | 13 | ||
15 | # obj-y for architecture PKUnity v3 | 14 | # obj-y for architecture PKUnity v3 |
diff --git a/arch/unicore32/kernel/cpu-ucv2.c b/arch/unicore32/kernel/cpu-ucv2.c deleted file mode 100644 index 4a99f62584c7..000000000000 --- a/arch/unicore32/kernel/cpu-ucv2.c +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/kernel/cpu-ucv2.c: clock scaling for the UniCore-II | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> | ||
7 | * Copyright (C) 2001-2010 Guan Xuetao | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/cpufreq.h> | ||
19 | |||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | static struct cpufreq_driver ucv2_driver; | ||
23 | |||
24 | /* make sure that only the "userspace" governor is run | ||
25 | * -- anything else wouldn't make sense on this platform, anyway. | ||
26 | */ | ||
27 | int ucv2_verify_speed(struct cpufreq_policy *policy) | ||
28 | { | ||
29 | if (policy->cpu) | ||
30 | return -EINVAL; | ||
31 | |||
32 | cpufreq_verify_within_limits(policy, | ||
33 | policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); | ||
34 | |||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static unsigned int ucv2_getspeed(unsigned int cpu) | ||
39 | { | ||
40 | struct clk *mclk = clk_get(NULL, "MAIN_CLK"); | ||
41 | |||
42 | if (cpu) | ||
43 | return 0; | ||
44 | return clk_get_rate(mclk)/1000; | ||
45 | } | ||
46 | |||
47 | static int ucv2_target(struct cpufreq_policy *policy, | ||
48 | unsigned int target_freq, | ||
49 | unsigned int relation) | ||
50 | { | ||
51 | unsigned int cur = ucv2_getspeed(0); | ||
52 | struct cpufreq_freqs freqs; | ||
53 | struct clk *mclk = clk_get(NULL, "MAIN_CLK"); | ||
54 | |||
55 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
56 | |||
57 | if (!clk_set_rate(mclk, target_freq * 1000)) { | ||
58 | freqs.old = cur; | ||
59 | freqs.new = target_freq; | ||
60 | freqs.cpu = 0; | ||
61 | } | ||
62 | |||
63 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int __init ucv2_cpu_init(struct cpufreq_policy *policy) | ||
69 | { | ||
70 | if (policy->cpu != 0) | ||
71 | return -EINVAL; | ||
72 | policy->cur = ucv2_getspeed(0); | ||
73 | policy->min = policy->cpuinfo.min_freq = 250000; | ||
74 | policy->max = policy->cpuinfo.max_freq = 1000000; | ||
75 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static struct cpufreq_driver ucv2_driver = { | ||
80 | .flags = CPUFREQ_STICKY, | ||
81 | .verify = ucv2_verify_speed, | ||
82 | .target = ucv2_target, | ||
83 | .get = ucv2_getspeed, | ||
84 | .init = ucv2_cpu_init, | ||
85 | .name = "UniCore-II", | ||
86 | }; | ||
87 | |||
88 | static int __init ucv2_cpufreq_init(void) | ||
89 | { | ||
90 | return cpufreq_register_driver(&ucv2_driver); | ||
91 | } | ||
92 | |||
93 | arch_initcall(ucv2_cpufreq_init); | ||
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 93fe929d1cee..9e22520a97ee 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
@@ -182,6 +182,7 @@ | |||
182 | #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ | 182 | #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ |
183 | #define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */ | 183 | #define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */ |
184 | #define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ | 184 | #define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ |
185 | #define X86_FEATURE_PROC_FEEDBACK (7*32+ 9) /* AMD ProcFeedbackInterface */ | ||
185 | 186 | ||
186 | /* Virtualization flags: Linux defined, word 8 */ | 187 | /* Virtualization flags: Linux defined, word 8 */ |
187 | #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ | 188 | #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ |
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index ee8e9abc859f..d92b5dad15dd 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c | |||
@@ -39,8 +39,9 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
39 | { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 }, | 39 | { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 }, |
40 | { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, | 40 | { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, |
41 | { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 }, | 41 | { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 }, |
42 | { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 }, | ||
43 | { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 }, | 42 | { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 }, |
43 | { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 }, | ||
44 | { X86_FEATURE_PROC_FEEDBACK, CR_EDX,11, 0x80000007, 0 }, | ||
44 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, | 45 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, |
45 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, | 46 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, |
46 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, | 47 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, |