aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-27 20:10:46 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-27 20:10:46 -0400
commit885f925eef411f549f17bc64dd054a3269cf66cd (patch)
tree6bac783d573a51e497ad28c19b5a71defac85f39 /arch
parente4f5a3adc454745fea35f1c312e14cbeba6e0ea4 (diff)
parent45c009a9a447655aecbdb06c86126f05d0272171 (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')
-rw-r--r--arch/arm/Kconfig25
-rw-r--r--arch/arm/mach-davinci/Makefile1
-rw-r--r--arch/arm/mach-davinci/cpufreq.c248
-rw-r--r--arch/arm/mach-exynos/Kconfig2
-rw-r--r--arch/arm/mach-imx/cpufreq.c8
-rw-r--r--arch/arm/mach-integrator/Makefile1
-rw-r--r--arch/arm/mach-integrator/cpu.c224
-rw-r--r--arch/arm/mach-omap2/pm.c9
-rw-r--r--arch/arm/mach-pxa/Makefile6
-rw-r--r--arch/arm/mach-pxa/cpufreq-pxa2xx.c494
-rw-r--r--arch/arm/mach-pxa/cpufreq-pxa3xx.c258
-rw-r--r--arch/arm/mach-pxa/include/mach/generic.h1
-rw-r--r--arch/arm/mach-s3c24xx/cpufreq.c8
-rw-r--r--arch/arm/mach-sa1100/Kconfig26
-rw-r--r--arch/arm/mach-sa1100/Makefile3
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c249
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1110.c408
-rw-r--r--arch/arm/mach-sa1100/include/mach/generic.h1
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c293
-rw-r--r--arch/avr32/Kconfig13
-rw-r--r--arch/avr32/configs/atngw100_defconfig2
-rw-r--r--arch/avr32/configs/atngw100_evklcd100_defconfig2
-rw-r--r--arch/avr32/configs/atngw100_evklcd101_defconfig2
-rw-r--r--arch/avr32/configs/atngw100_mrmt_defconfig2
-rw-r--r--arch/avr32/configs/atngw100mkii_defconfig2
-rw-r--r--arch/avr32/configs/atngw100mkii_evklcd100_defconfig2
-rw-r--r--arch/avr32/configs/atngw100mkii_evklcd101_defconfig2
-rw-r--r--arch/avr32/configs/atstk1002_defconfig2
-rw-r--r--arch/avr32/configs/atstk1003_defconfig2
-rw-r--r--arch/avr32/configs/atstk1004_defconfig2
-rw-r--r--arch/avr32/configs/atstk1006_defconfig2
-rw-r--r--arch/avr32/configs/favr-32_defconfig2
-rw-r--r--arch/avr32/configs/hammerhead_defconfig2
-rw-r--r--arch/avr32/configs/mimc200_defconfig2
-rw-r--r--arch/avr32/mach-at32ap/Makefile1
-rw-r--r--arch/avr32/mach-at32ap/cpufreq.c124
-rw-r--r--arch/blackfin/mach-common/Makefile1
-rw-r--r--arch/blackfin/mach-common/cpufreq.c258
-rw-r--r--arch/cris/arch-v32/mach-a3/Makefile1
-rw-r--r--arch/cris/arch-v32/mach-a3/cpufreq.c152
-rw-r--r--arch/cris/arch-v32/mach-fs/Makefile1
-rw-r--r--arch/cris/arch-v32/mach-fs/cpufreq.c145
-rw-r--r--arch/ia64/Kconfig6
-rw-r--r--arch/ia64/kernel/Makefile1
-rw-r--r--arch/ia64/kernel/cpufreq/Kconfig29
-rw-r--r--arch/ia64/kernel/cpufreq/Makefile2
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-cpufreq.c437
-rw-r--r--arch/mips/Kconfig9
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/cpufreq/Kconfig41
-rw-r--r--arch/mips/kernel/cpufreq/Makefile5
-rw-r--r--arch/mips/kernel/cpufreq/loongson2_cpufreq.c255
-rw-r--r--arch/powerpc/platforms/cell/Kconfig26
-rw-r--r--arch/powerpc/platforms/cell/Makefile3
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c209
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.h24
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c115
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c156
-rw-r--r--arch/powerpc/platforms/pasemi/cpufreq.c5
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_32.c14
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c5
-rw-r--r--arch/sh/Kconfig18
-rw-r--r--arch/sh/kernel/Makefile1
-rw-r--r--arch/sh/kernel/cpufreq.c201
-rw-r--r--arch/sparc/Kconfig23
-rw-r--r--arch/sparc/kernel/Makefile3
-rw-r--r--arch/sparc/kernel/us2e_cpufreq.c413
-rw-r--r--arch/sparc/kernel/us3_cpufreq.c274
-rw-r--r--arch/unicore32/kernel/Makefile1
-rw-r--r--arch/unicore32/kernel/cpu-ucv2.c93
-rw-r--r--arch/x86/include/asm/cpufeature.h1
-rw-r--r--arch/x86/kernel/cpu/scattered.c3
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
2160menu "CPU Power Management" 2160menu "CPU Power Management"
2161 2161
2162if ARCH_HAS_CPUFREQ 2162if ARCH_HAS_CPUFREQ
2163
2164source "drivers/cpufreq/Kconfig" 2163source "drivers/cpufreq/Kconfig"
2165 2164
2166config CPU_FREQ_IMX 2165config 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
2173config CPU_FREQ_SA1100
2174 bool
2175
2176config CPU_FREQ_SA1110
2177 bool
2178
2179config 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
2190config 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
2197config CPU_FREQ_S3C 2172config 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
37obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o 37obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o
38 38
39# Power Management 39# Power Management
40obj-$(CONFIG_CPU_FREQ) += cpufreq.o
41obj-$(CONFIG_CPU_IDLE) += cpuidle.o 40obj-$(CONFIG_CPU_IDLE) += cpuidle.o
42obj-$(CONFIG_SUSPEND) += pm.o sleep.o 41obj-$(CONFIG_SUSPEND) += pm.o sleep.o
43obj-$(CONFIG_HAVE_CLK) += pm_domain.o 42obj-$(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
35struct davinci_cpufreq {
36 struct device *dev;
37 struct clk *armclk;
38 struct clk *asyncclk;
39 unsigned long asyncrate;
40};
41static struct davinci_cpufreq cpufreq;
42
43static 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
65static 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
73static 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
128out:
129 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
130
131 return ret;
132}
133
134static 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
176static int davinci_cpu_exit(struct cpufreq_policy *policy)
177{
178 cpufreq_frequency_table_put_attr(policy->cpu);
179 return 0;
180}
181
182static struct freq_attr *davinci_cpufreq_attr[] = {
183 &cpufreq_freq_attr_scaling_available_freqs,
184 NULL,
185};
186
187static 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
198static 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
225static 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
235static 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
243int __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
9obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o 9obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
10 10
11obj-$(CONFIG_PCI) += pci_v3.o pci.o 11obj-$(CONFIG_PCI) += pci_v3.o pci.o
12obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
13obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o 12obj-$(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
26static 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
33static 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
45static 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 */
60static 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
82static 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
159static 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
189static 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
201static 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
209static int __init integrator_cpu_init(void)
210{
211 return cpufreq_register_driver(&integrator_driver);
212}
213
214static void __exit integrator_cpu_exit(void)
215{
216 cpufreq_unregister_driver(&integrator_driver);
217}
218
219MODULE_AUTHOR ("Russell M. King");
220MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
221MODULE_LICENSE ("GPL");
222
223module_init(integrator_cpu_init);
224module_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
268static inline void omap_init_cpufreq(void)
269{
270 struct platform_device_info devinfo = { .name = "omap-cpufreq", };
271 platform_device_register_full(&devinfo);
272}
273
268static int __init omap2_common_pm_init(void) 274static 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
8obj-$(CONFIG_PM) += pm.o sleep.o standby.o 8obj-$(CONFIG_PM) += pm.o sleep.o standby.o
9 9
10ifeq ($(CONFIG_CPU_FREQ),y)
11obj-$(CONFIG_PXA25x) += cpufreq-pxa2xx.o
12obj-$(CONFIG_PXA27x) += cpufreq-pxa2xx.o
13obj-$(CONFIG_PXA3xx) += cpufreq-pxa3xx.o
14endif
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
47static unsigned int freq_debug;
48module_param(freq_debug, uint, 0);
49MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0");
50#else
51#define freq_debug 0
52#endif
53
54static struct regulator *vcc_core;
55
56static unsigned int pxa27x_maxfreq;
57module_param(pxa27x_maxfreq, uint, 0);
58MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz"
59 "(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)");
60
61typedef 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 */
73static 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
91static 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 */
103static 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
116static struct cpufreq_frequency_table
117 pxa255_run_freq_table[NUM_PXA25x_RUN_FREQS+1];
118static struct cpufreq_frequency_table
119 pxa255_turbo_freq_table[NUM_PXA25x_TURBO_FREQS+1];
120
121static unsigned int pxa255_turbo_table;
122module_param(pxa255_turbo_table, uint, 0);
123MODULE_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
158static 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)
169static struct cpufreq_frequency_table
170 pxa27x_freq_table[NUM_PXA27x_FREQS+1];
171
172extern unsigned get_clk_frequency_khz(int info);
173
174#ifdef CONFIG_REGULATOR
175
176static 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
196static __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
207static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq)
208{
209 return 0;
210}
211
212static __init void pxa_cpufreq_init_voltages(void) { }
213#endif
214
215static 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
233static 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
245static 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
259static 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 */
267static 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
283static unsigned int pxa_cpufreq_get(unsigned int cpu)
284{
285 return get_clk_frequency_khz(0);
286}
287
288static 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\
3651: \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\
3712: b 1b \n\
3723: 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
402static 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
468static 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
476static 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
484static void __exit pxa_cpu_exit(void)
485{
486 cpufreq_unregister_driver(&pxa_cpufreq_driver);
487}
488
489
490MODULE_AUTHOR("Intrinsyc Software Inc.");
491MODULE_DESCRIPTION("CPU frequency changing driver for the PXA architecture");
492MODULE_LICENSE("GPL");
493module_init(pxa_cpu_init);
494module_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
44struct 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
72static 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
80static 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
89static unsigned int pxa3xx_freqs_num;
90static struct pxa3xx_freq_info *pxa3xx_freqs;
91static struct cpufreq_frequency_table *pxa3xx_freqs_table;
92
93static 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
117static 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
138static 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
156static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy)
157{
158 return cpufreq_frequency_table_verify(policy, pxa3xx_freqs_table);
159}
160
161static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
162{
163 return pxa3xx_get_clk_frequency_khz(0);
164}
165
166static 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
208static 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
234static 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
242static int __init cpufreq_init(void)
243{
244 if (cpu_is_pxa3xx())
245 return cpufreq_register_driver(&pxa3xx_cpufreq_driver);
246
247 return 0;
248}
249module_init(cpufreq_init);
250
251static void __exit cpufreq_exit(void)
252{
253 cpufreq_unregister_driver(&pxa3xx_cpufreq_driver);
254}
255module_exit(cpufreq_exit);
256
257MODULE_DESCRIPTION("CPU frequency scaling driver for PXA3xx");
258MODULE_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
5config SA1100_ASSABET 5config 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
21config SA1100_CERF 21config 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
48config SA1100_COLLIE 48config 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
57config SA1100_H3100 57config 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
68config SA1100_H3600 68config 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
79config SA1100_BADGE4 79config 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
87config SA1100_JORNADA720 87config 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
106config SA1100_HACKKIT 106config 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
113config SA1100_LART 113config 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
121config SA1100_NANOENGINE 121config 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
131config SA1100_PLEB 131config 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
140config SA1100_SHANNON 140config 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
149config SA1100_SIMPAD 149config 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 :=
8obj-n := 8obj-n :=
9obj- := 9obj- :=
10 10
11obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o
12obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o
13
14# Specific board support 11# Specific board support
15obj-$(CONFIG_SA1100_ASSABET) += assabet.o 12obj-$(CONFIG_SA1100_ASSABET) += assabet.o
16obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o 13obj-$(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
98struct sa1100_dram_regs {
99 int speed;
100 u32 mdcnfg;
101 u32 mdcas0;
102 u32 mdcas1;
103 u32 mdcas2;
104};
105
106
107static struct cpufreq_driver sa1100_driver;
108
109static 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
130static 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
181static 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
221static 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
232static 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
241static 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
249arch_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
36struct 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
47struct sdram_info {
48 u_int mdcnfg;
49 u_int mdrefr;
50 u_int mdcas[3];
51};
52
53static 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
119static 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 */
126static 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 */
134static 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
146static void
147sdram_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 */
202static 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 */
216static void
217sdram_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 */
233static 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\
3081: 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\
3162: b 1b \n\
3173: 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
335static 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() */
348static 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
357static 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
369static char sdram_name[16];
370
371static 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
407module_param_string(sdram, sdram_name, sizeof(sdram_name), 0);
408arch_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
24endif 24endif
25obj-$(CONFIG_SMP) += platsmp.o headsmp.o 25obj-$(CONFIG_SMP) += platsmp.o headsmp.o
26obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 26obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
27obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
28obj-$(CONFIG_TEGRA_PCI) += pcie.o 27obj-$(CONFIG_TEGRA_PCI) += pcie.o
29 28
30obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o 29obj-$(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 */
34static 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
48static struct clk *cpu_clk;
49static struct clk *pll_x_clk;
50static struct clk *pll_p_clk;
51static struct clk *emc_clk;
52
53static unsigned long target_cpu_speed[NUM_CPUS];
54static DEFINE_MUTEX(tegra_cpu_lock);
55static bool is_suspended;
56
57static int tegra_verify_speed(struct cpufreq_policy *policy)
58{
59 return cpufreq_frequency_table_verify(policy, freq_table);
60}
61
62static 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
73static 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
104out:
105 clk_disable_unprepare(pll_x_clk);
106 return ret;
107}
108
109static 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
152static 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
162static 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
186out:
187 mutex_unlock(&tegra_cpu_lock);
188 return ret;
189}
190
191static 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
208static struct notifier_block tegra_cpu_pm_notifier = {
209 .notifier_call = tegra_pm_notify,
210};
211
212static 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
236static 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
243static struct freq_attr *tegra_cpufreq_attr[] = {
244 &cpufreq_freq_attr_scaling_available_freqs,
245 NULL,
246};
247
248static 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
258static 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
281static 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
289MODULE_AUTHOR("Colin Cross <ccross@android.com>");
290MODULE_DESCRIPTION("cpufreq driver for Nvidia Tegra2");
291MODULE_LICENSE("GPL");
292module_init(tegra_cpufreq_init);
293module_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
252menu "CPU Frequency scaling" 252menu "CPU Frequency scaling"
253
254source "drivers/cpufreq/Kconfig" 253source "drivers/cpufreq/Kconfig"
255
256config 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
267endmenu 254endmenu
268 255
269endmenu 256endmenu
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
27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
28CONFIG_CPU_FREQ_GOV_USERSPACE=y 28CONFIG_CPU_FREQ_GOV_USERSPACE=y
29CONFIG_CPU_FREQ_AT32AP=y 29CONFIG_AVR32_AT32AP_CPUFREQ=y
30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
31CONFIG_NET=y 31CONFIG_NET=y
32CONFIG_PACKET=y 32CONFIG_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
29CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 29CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
30CONFIG_CPU_FREQ_GOV_USERSPACE=y 30CONFIG_CPU_FREQ_GOV_USERSPACE=y
31CONFIG_CPU_FREQ_AT32AP=y 31CONFIG_AVR32_AT32AP_CPUFREQ=y
32CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 32CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
33CONFIG_NET=y 33CONFIG_NET=y
34CONFIG_PACKET=y 34CONFIG_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
28CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 28CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
29CONFIG_CPU_FREQ_GOV_USERSPACE=y 29CONFIG_CPU_FREQ_GOV_USERSPACE=y
30CONFIG_CPU_FREQ_AT32AP=y 30CONFIG_AVR32_AT32AP_CPUFREQ=y
31CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 31CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
32CONFIG_NET=y 32CONFIG_NET=y
33CONFIG_PACKET=y 33CONFIG_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
23CONFIG_CPU_FREQ_GOV_POWERSAVE=y 23CONFIG_CPU_FREQ_GOV_POWERSAVE=y
24CONFIG_CPU_FREQ_GOV_USERSPACE=y 24CONFIG_CPU_FREQ_GOV_USERSPACE=y
25CONFIG_CPU_FREQ_GOV_ONDEMAND=y 25CONFIG_CPU_FREQ_GOV_ONDEMAND=y
26CONFIG_CPU_FREQ_AT32AP=y 26CONFIG_AVR32_AT32AP_CPUFREQ=y
27CONFIG_NET=y 27CONFIG_NET=y
28CONFIG_PACKET=y 28CONFIG_PACKET=y
29CONFIG_UNIX=y 29CONFIG_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
27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
28CONFIG_CPU_FREQ_GOV_USERSPACE=y 28CONFIG_CPU_FREQ_GOV_USERSPACE=y
29CONFIG_CPU_FREQ_AT32AP=y 29CONFIG_AVR32_AT32AP_CPUFREQ=y
30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
31CONFIG_NET=y 31CONFIG_NET=y
32CONFIG_PACKET=y 32CONFIG_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
30CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 30CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
31CONFIG_CPU_FREQ_GOV_USERSPACE=y 31CONFIG_CPU_FREQ_GOV_USERSPACE=y
32CONFIG_CPU_FREQ_AT32AP=y 32CONFIG_AVR32_AT32AP_CPUFREQ=y
33CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 33CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
34CONFIG_NET=y 34CONFIG_NET=y
35CONFIG_PACKET=y 35CONFIG_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
29CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 29CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
30CONFIG_CPU_FREQ_GOV_USERSPACE=y 30CONFIG_CPU_FREQ_GOV_USERSPACE=y
31CONFIG_CPU_FREQ_AT32AP=y 31CONFIG_AVR32_AT32AP_CPUFREQ=y
32CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 32CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
33CONFIG_NET=y 33CONFIG_NET=y
34CONFIG_PACKET=y 34CONFIG_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
26CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 26CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
27CONFIG_CPU_FREQ_GOV_USERSPACE=y 27CONFIG_CPU_FREQ_GOV_USERSPACE=y
28CONFIG_CPU_FREQ_AT32AP=y 28CONFIG_AVR32_AT32AP_CPUFREQ=y
29CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 29CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
30CONFIG_NET=y 30CONFIG_NET=y
31CONFIG_PACKET=y 31CONFIG_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
27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
28CONFIG_CPU_FREQ_GOV_USERSPACE=y 28CONFIG_CPU_FREQ_GOV_USERSPACE=y
29CONFIG_CPU_FREQ_AT32AP=y 29CONFIG_AVR32_AT32AP_CPUFREQ=y
30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
31CONFIG_NET=y 31CONFIG_NET=y
32CONFIG_PACKET=y 32CONFIG_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
27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
28CONFIG_CPU_FREQ_GOV_USERSPACE=y 28CONFIG_CPU_FREQ_GOV_USERSPACE=y
29CONFIG_CPU_FREQ_AT32AP=y 29CONFIG_AVR32_AT32AP_CPUFREQ=y
30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
31CONFIG_NET=y 31CONFIG_NET=y
32CONFIG_PACKET=y 32CONFIG_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
27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 27CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
28CONFIG_CPU_FREQ_GOV_USERSPACE=y 28CONFIG_CPU_FREQ_GOV_USERSPACE=y
29CONFIG_CPU_FREQ_AT32AP=y 29CONFIG_AVR32_AT32AP_CPUFREQ=y
30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y 30CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
31CONFIG_NET=y 31CONFIG_NET=y
32CONFIG_PACKET=y 32CONFIG_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
28CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 28CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
29CONFIG_CPU_FREQ_GOV_USERSPACE=y 29CONFIG_CPU_FREQ_GOV_USERSPACE=y
30CONFIG_CPU_FREQ_AT32AP=y 30CONFIG_AVR32_AT32AP_CPUFREQ=y
31CONFIG_NET=y 31CONFIG_NET=y
32CONFIG_PACKET=y 32CONFIG_PACKET=y
33CONFIG_UNIX=y 33CONFIG_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
32CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 32CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
33CONFIG_CPU_FREQ_GOV_USERSPACE=y 33CONFIG_CPU_FREQ_GOV_USERSPACE=y
34CONFIG_CPU_FREQ_AT32AP=y 34CONFIG_AVR32_AT32AP_CPUFREQ=y
35CONFIG_NET=y 35CONFIG_NET=y
36CONFIG_PACKET=y 36CONFIG_PACKET=y
37CONFIG_UNIX=y 37CONFIG_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
25CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y 25CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
26CONFIG_CPU_FREQ_GOV_USERSPACE=y 26CONFIG_CPU_FREQ_GOV_USERSPACE=y
27CONFIG_CPU_FREQ_AT32AP=y 27CONFIG_AVR32_AT32AP_CPUFREQ=y
28CONFIG_NET=y 28CONFIG_NET=y
29CONFIG_PACKET=y 29CONFIG_PACKET=y
30CONFIG_UNIX=y 30CONFIG_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 @@
1obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o 1obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o
2obj-y += hmatrix.o 2obj-y += hmatrix.o
3obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o 3obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o
4obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
5obj-$(CONFIG_PM) += pm.o 4obj-$(CONFIG_PM) += pm.o
6 5
7ifeq ($(CONFIG_PM_DEBUG),y) 6ifeq ($(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
23static struct clk *cpuclk;
24
25static 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
35static 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
43static unsigned int ref_freq;
44static unsigned long loops_per_jiffy_ref;
45
46static 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
87static 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
110static 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
120static int __init at32_cpufreq_init(void)
121{
122 return cpufreq_register_driver(&at32_driver);
123}
124late_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
10ifneq ($(CONFIG_BF60x),y) 10ifneq ($(CONFIG_BF60x),y)
11obj-$(CONFIG_PM) += dpmc_modes.o 11obj-$(CONFIG_PM) += dpmc_modes.o
12endif 12endif
13obj-$(CONFIG_CPU_FREQ) += cpufreq.o
14obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o 13obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
15obj-$(CONFIG_SMP) += smp.o 14obj-$(CONFIG_SMP) += smp.o
16obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o 15obj-$(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[] */
24static 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
43static 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 */
54unsigned long long __bfin_cycles_off;
55unsigned int __bfin_cycles_mod;
56#endif
57
58/**************************************************************************/
59static 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
97static 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
108static 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
115unsigned 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
130static 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
205static int bfin_verify_speed(struct cpufreq_policy *policy)
206{
207 return cpufreq_frequency_table_verify(policy, bfin_freq_table);
208}
209
210static 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
228static struct freq_attr *bfin_freq_attr[] = {
229 &cpufreq_freq_attr_scaling_available_freqs,
230 NULL,
231};
232
233static 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
243static int __init bfin_cpu_init(void)
244{
245 return cpufreq_register_driver(&bfin_driver);
246}
247
248static void __exit bfin_cpu_exit(void)
249{
250 cpufreq_unregister_driver(&bfin_driver);
251}
252
253MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
254MODULE_DESCRIPTION("cpufreq driver for Blackfin");
255MODULE_LICENSE("GPL");
256
257module_init(bfin_cpu_init);
258module_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
5obj-y := dma.o pinmux.o io.o arbiter.o 5obj-y := dma.o pinmux.o io.o arbiter.o
6obj-$(CONFIG_CPU_FREQ) += cpufreq.o
7 6
8clean: 7clean:
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
9static int
10cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
11 void *data);
12
13static struct notifier_block cris_sdram_freq_notifier_block = {
14 .notifier_call = cris_sdram_freq_notifier
15};
16
17static struct cpufreq_frequency_table cris_freq_table[] = {
18 {0x01, 6000},
19 {0x02, 200000},
20 {0, CPUFREQ_TABLE_END},
21};
22
23static 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
30static 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
63static int cris_freq_verify(struct cpufreq_policy *policy)
64{
65 return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
66}
67
68static 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
83static 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
101static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
102{
103 cpufreq_frequency_table_put_attr(policy->cpu);
104 return 0;
105}
106
107
108static struct freq_attr *cris_freq_attr[] = {
109 &cpufreq_freq_attr_scaling_available_freqs,
110 NULL,
111};
112
113static 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
124static 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
133static int
134cris_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
152module_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
5obj-y := dma.o pinmux.o io.o arbiter.o 5obj-y := dma.o pinmux.o io.o arbiter.o
6obj-$(CONFIG_CPU_FREQ) += cpufreq.o
7 6
8clean: 7clean:
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
9static int
10cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
11 void *data);
12
13static struct notifier_block cris_sdram_freq_notifier_block = {
14 .notifier_call = cris_sdram_freq_notifier
15};
16
17static struct cpufreq_frequency_table cris_freq_table[] = {
18 {0x01, 6000},
19 {0x02, 200000},
20 {0, CPUFREQ_TABLE_END},
21};
22
23static 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
30static 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
60static int cris_freq_verify(struct cpufreq_policy *policy)
61{
62 return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
63}
64
65static 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
79static 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
96static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
97{
98 cpufreq_frequency_table_put_attr(policy->cpu);
99 return 0;
100}
101
102static struct freq_attr *cris_freq_attr[] = {
103 &cpufreq_freq_attr_scaling_available_freqs,
104 NULL,
105};
106
107static 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
118static 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
127static int
128cris_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
145module_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"
591source "drivers/acpi/Kconfig" 591source "drivers/acpi/Kconfig"
592 592
593if PM 593if PM
594 594menu "CPU Frequency scaling"
595source "arch/ia64/kernel/cpufreq/Kconfig" 595source "drivers/cpufreq/Kconfig"
596 596endmenu
597endif 597endif
598 598
599endmenu 599endmenu
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
23obj-$(CONFIG_NUMA) += numa.o 23obj-$(CONFIG_NUMA) += numa.o
24obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o 24obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o
25obj-$(CONFIG_IA64_CYCLONE) += cyclone.o 25obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
26obj-$(CONFIG_CPU_FREQ) += cpufreq/
27obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o 26obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
28obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o 27obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
29obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 28obj-$(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
6menu "CPU Frequency scaling"
7
8source "drivers/cpufreq/Kconfig"
9
10if CPU_FREQ
11
12comment "CPUFreq processor drivers"
13
14config 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
26endif # CPU_FREQ
27
28endmenu
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 @@
1obj-$(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
26MODULE_AUTHOR("Venkatesh Pallipadi");
27MODULE_DESCRIPTION("ACPI Processor P-States Driver");
28MODULE_LICENSE("GPL");
29
30
31struct cpufreq_acpi_io {
32 struct acpi_processor_performance acpi_data;
33 struct cpufreq_frequency_table *freq_table;
34 unsigned int resume;
35};
36
37static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
38
39static struct cpufreq_driver acpi_cpufreq_driver;
40
41
42static int
43processor_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
61static int
62processor_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 */
83static unsigned
84extract_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
101static unsigned int
102processor_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
131migrate_end:
132 set_cpus_allowed_ptr(current, &saved_mask);
133 return ret;
134}
135
136
137static int
138processor_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
208migrate_end:
209 set_cpus_allowed_ptr(current, &saved_mask);
210 return (retval);
211}
212
213
214static unsigned int
215acpi_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
226static int
227acpi_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
249static int
250acpi_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
265static int
266acpi_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
378static int
379acpi_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
398static struct freq_attr* acpi_cpufreq_attr[] = {
399 &cpufreq_freq_attr_scaling_available_freqs,
400 NULL,
401};
402
403
404static 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
416static int __init
417acpi_cpufreq_init (void)
418{
419 pr_debug("acpi_cpufreq_init\n");
420
421 return cpufreq_register_driver(&acpi_cpufreq_driver);
422}
423
424
425static void __exit
426acpi_cpufreq_exit (void)
427{
428 pr_debug("acpi_cpufreq_exit\n");
429
430 cpufreq_unregister_driver(&acpi_cpufreq_driver);
431 return;
432}
433
434
435late_initcall(acpi_cpufreq_init);
436module_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
2539endmenu 2539endmenu
2540 2540
2541source "arch/mips/kernel/cpufreq/Kconfig" 2541config MIPS_EXTERNAL_TIMER
2542 bool
2543
2544if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
2545menu "CPU Power Management"
2546source "drivers/cpufreq/Kconfig"
2547endmenu
2548endif
2542 2549
2543source "net/Kconfig" 2550source "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
93obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o 93obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o
94 94
95obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/
96
97obj-$(CONFIG_PERF_EVENTS) += perf_event.o 95obj-$(CONFIG_PERF_EVENTS) += perf_event.o
98obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o 96obj-$(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
5config MIPS_EXTERNAL_TIMER
6 bool
7
8config MIPS_CPUFREQ
9 bool
10 default y
11 depends on CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
12
13if MIPS_CPUFREQ
14
15menu "CPU Frequency scaling"
16
17source "drivers/cpufreq/Kconfig"
18
19if CPU_FREQ
20
21comment "CPUFreq processor drivers"
22
23config 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
37endif # CPU_FREQ
38
39endmenu
40
41endif # 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
5obj-$(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
24static uint nowait;
25
26static struct clk *cpuclk;
27
28static void (*saved_cpu_wait) (void);
29
30static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
31 unsigned long val, void *data);
32
33static struct notifier_block loongson2_cpufreq_notifier_block = {
34 .notifier_call = loongson2_cpu_freq_notifier
35};
36
37static 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
46static 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 */
54static 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
107static 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
148static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
149{
150 return cpufreq_frequency_table_verify(policy,
151 &loongson2_clockmod_table[0]);
152}
153
154static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
155{
156 clk_put(cpuclk);
157 return 0;
158}
159
160static struct freq_attr *loongson2_table_attr[] = {
161 &cpufreq_freq_attr_scaling_available_freqs,
162 NULL,
163};
164
165static 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
176static struct platform_device_id platform_device_ids[] = {
177 {
178 .name = "loongson2_cpufreq",
179 },
180 {}
181};
182
183MODULE_DEVICE_TABLE(platform, platform_device_ids);
184
185static 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
198static DEFINE_SPINLOCK(loongson2_wait_lock);
199
200static 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
212static 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
236static 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
247module_init(cpufreq_init);
248module_exit(cpufreq_exit);
249
250module_param(nowait, uint, 0644);
251MODULE_PARM_DESC(nowait, "Disable Loongson-2F specific wait");
252
253MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
254MODULE_DESCRIPTION("cpufreq driver for Loongson2F");
255MODULE_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
116config 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
125config 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
135config CBE_CPUFREQ_PMI
136 tristate
137 depends on CBE_CPUFREQ_PMI_ENABLE
138 default CBE_CPUFREQ
139
140config PPC_PMI 116config 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 \
5obj-$(CONFIG_CBE_RAS) += ras.o 5obj-$(CONFIG_CBE_RAS) += ras.o
6 6
7obj-$(CONFIG_CBE_THERM) += cbe_thermal.o 7obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
8obj-$(CONFIG_CBE_CPUFREQ_PMI) += cbe_cpufreq_pmi.o
9obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o
10cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o
11obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o 8obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o
12 9
13obj-$(CONFIG_PPC_IBM_CELL_POWERBUTTON) += cbe_powerbutton.o 10obj-$(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
32static DEFINE_MUTEX(cbe_switch_mutex);
33
34
35/* the CBE supports an 8 step frequency scaling */
36static 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
52static 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
70static 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
132static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
133{
134 cpufreq_frequency_table_put_attr(policy->cpu);
135 return 0;
136}
137
138static int cbe_cpufreq_verify(struct cpufreq_policy *policy)
139{
140 return cpufreq_frequency_table_verify(policy, cbe_freqs);
141}
142
143static 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
178static 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
192static 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
200static void __exit cbe_cpufreq_exit(void)
201{
202 cpufreq_unregister_driver(&cbe_cpufreq_driver);
203}
204
205module_init(cbe_cpufreq_init);
206module_exit(cbe_cpufreq_exit);
207
208MODULE_LICENSE("GPL");
209MODULE_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
15int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode);
16int cbe_cpufreq_get_pmode(int cpu);
17
18int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode);
19
20#if defined(CONFIG_CBE_CPUFREQ_PMI) || defined(CONFIG_CBE_CPUFREQ_PMI_MODULE)
21extern 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 */
36static u64 MIC_Slow_Fast_Timer_table[] = {
37 [0 ... 7] = 0x007fc00000000000ull,
38};
39
40/* more values for the MIC */
41static 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
53int 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
105int 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
40static u8 pmi_slow_mode_limit[MAX_CBE];
41
42bool cbe_cpufreq_has_pmi = false;
43EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi);
44
45/*
46 * hardware specific functions
47 */
48
49int 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}
76EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi);
77
78
79static 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
93static 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
123static struct notifier_block pmi_notifier_block = {
124 .notifier_call = pmi_notifier,
125};
126
127static struct pmi_handler cbe_pmi_handler = {
128 .type = PMI_TYPE_FREQ_CHANGE,
129 .handle_pmi_message = cbe_cpufreq_handle_pmi,
130};
131
132
133
134static 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
146static 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
152module_init(cbe_cpufreq_pmi_init);
153module_exit(cbe_cpufreq_pmi_exit);
154
155MODULE_LICENSE("GPL");
156MODULE_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
338static int do_set_cpu_speed(int speed_mode, int notify) 338static 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
624endmenu 624endmenu
625 625
626menu "CPU Frequency scaling" 626menu "CPU Frequency scaling"
627
628source "drivers/cpufreq/Kconfig" 627source "drivers/cpufreq/Kconfig"
629
630config 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
646endmenu 628endmenu
647 629
648source "arch/sh/drivers/Kconfig" 630source "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/
31obj-$(CONFIG_SMP) += smp.o 31obj-$(CONFIG_SMP) += smp.o
32obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o 32obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
33obj-$(CONFIG_KGDB) += kgdb.o 33obj-$(CONFIG_KGDB) += kgdb.o
34obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
35obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o 34obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o
36obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 35obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
37obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 36obj-$(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
33static DEFINE_PER_CPU(struct clk, sh_cpuclk);
34
35static 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 */
43static 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
87static 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
108static 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
158static 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
169static struct freq_attr *sh_freq_attr[] = {
170 &cpufreq_freq_attr_scaling_available_freqs,
171 NULL,
172};
173
174static 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
185static 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
191static void __exit sh_cpufreq_module_exit(void)
192{
193 cpufreq_unregister_driver(&sh_cpufreq_driver);
194}
195
196module_init(sh_cpufreq_module_init);
197module_exit(sh_cpufreq_module_exit);
198
199MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
200MODULE_DESCRIPTION("cpufreq driver for SuperH");
201MODULE_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
255if SPARC64 255if SPARC64
256source "drivers/cpufreq/Kconfig" 256source "drivers/cpufreq/Kconfig"
257
258config 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
269config 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
280endif 257endif
281 258
282config US3_MC 259config 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
103obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o 103obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o
104 104
105# sparc64 cpufreq
106obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
107obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
108obj-$(CONFIG_US3_MC) += chmc.o 105obj-$(CONFIG_US3_MC) += chmc.o
109 106
110obj-$(CONFIG_KPROBES) += kprobes.o 107obj-$(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
22static struct cpufreq_driver *cpufreq_us2e_driver;
23
24struct us2e_freq_percpu_info {
25 struct cpufreq_frequency_table table[6];
26};
27
28/* Indexed by cpu number. */
29static 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
50static 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
60static 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
73static 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
85static 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
117static 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
159static 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
182static 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
205static 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
232static 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
251static 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
287static 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
303static 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
309static 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
335static 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
343static 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
384err_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
397static 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
408MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
409MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-IIe");
410MODULE_LICENSE("GPL");
411
412module_init(us2e_freq_init);
413module_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
21static struct cpufreq_driver *cpufreq_us3_driver;
22
23struct us3_freq_percpu_info {
24 struct cpufreq_frequency_table table[4];
25};
26
27/* Indexed by cpu number. */
28static 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
38static 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
48static 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
57static 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
79static 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
99static 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
146static 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
164static 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
170static 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
192static 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
200static 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
245err_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
258static 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
269MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
270MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-III");
271MODULE_LICENSE("GPL");
272
273module_init(us3_freq_init);
274module_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
9obj-$(CONFIG_MODULES) += ksyms.o module.o 9obj-$(CONFIG_MODULES) += ksyms.o module.o
10obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 10obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
11 11
12obj-$(CONFIG_CPU_FREQ) += cpu-ucv2.o
13obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o 12obj-$(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
22static 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 */
27int 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
38static 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
47static 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
68static 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
79static 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
88static int __init ucv2_cpufreq_init(void)
89{
90 return cpufreq_register_driver(&ucv2_driver);
91}
92
93arch_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 },