aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-07 13:26:02 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-07 13:26:02 -0500
commit15d4cb9013ab7cdf10760aeabd07b007d635b321 (patch)
tree6c49842895e8f925881e4d0ccbc597b7081c8508
parentadf9684588ec1769b77a9e1c7c68fbad49ec5e43 (diff)
parentfbbcdc0744dace5fcc8147d11c5fb0791126848a (diff)
Merge branch 'pm-cpufreq'
* pm-cpufreq: intel_pstate: skip the driver if ACPI has power mgmt option cpufreq: ondemand: Remove redundant return statement cpufreq: move freq change notifications to cpufreq core cpufreq: distinguish drivers that do asynchronous notifications cpufreq/intel_pstate: Add static declarations to internal functions cpufreq: arm_big_little: reconfigure switcher behavior at run time cpufreq: arm_big_little: add in-kernel switching (IKS) support ARM: vexpress/TC2: register vexpress-spc cpufreq device cpufreq: arm_big_little: add vexpress SPC interface driver ARM: vexpress/TC2: add cpu clock support ARM: vexpress/TC2: add support for CPU DVFS
-rw-r--r--arch/arm/mach-vexpress/Kconfig12
-rw-r--r--arch/arm/mach-vexpress/Makefile3
-rw-r--r--arch/arm/mach-vexpress/spc.c366
-rw-r--r--arch/arm/mach-vexpress/spc.h2
-rw-r--r--arch/arm/mach-vexpress/tc2_pm.c7
-rw-r--r--drivers/cpufreq/Kconfig.arm8
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c14
-rw-r--r--drivers/cpufreq/arm_big_little.c419
-rw-r--r--drivers/cpufreq/arm_big_little.h5
-rw-r--r--drivers/cpufreq/at32ap-cpufreq.c22
-rw-r--r--drivers/cpufreq/blackfin-cpufreq.c22
-rw-r--r--drivers/cpufreq/cpufreq-cpu0.c33
-rw-r--r--drivers/cpufreq/cpufreq.c40
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c1
-rw-r--r--drivers/cpufreq/cris-artpec3-cpufreq.c8
-rw-r--r--drivers/cpufreq/cris-etraxfs-cpufreq.c8
-rw-r--r--drivers/cpufreq/davinci-cpufreq.c30
-rw-r--r--drivers/cpufreq/dbx500-cpufreq.c22
-rw-r--r--drivers/cpufreq/e_powersaver.c23
-rw-r--r--drivers/cpufreq/elanfreq.c13
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c28
-rw-r--r--drivers/cpufreq/exynos5440-cpufreq.c2
-rw-r--r--drivers/cpufreq/ia64-acpi-cpufreq.c19
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c37
-rw-r--r--drivers/cpufreq/intel_pstate.c78
-rw-r--r--drivers/cpufreq/kirkwood-cpufreq.c54
-rw-r--r--drivers/cpufreq/loongson2_cpufreq.c16
-rw-r--r--drivers/cpufreq/maple-cpufreq.c18
-rw-r--r--drivers/cpufreq/omap-cpufreq.c38
-rw-r--r--drivers/cpufreq/p4-clockmod.c10
-rw-r--r--drivers/cpufreq/pasemi-cpufreq.c14
-rw-r--r--drivers/cpufreq/pmac32-cpufreq.c20
-rw-r--r--drivers/cpufreq/pmac64-cpufreq.c18
-rw-r--r--drivers/cpufreq/powernow-k8.c1
-rw-r--r--drivers/cpufreq/ppc-corenet-cpufreq.c19
-rw-r--r--drivers/cpufreq/ppc_cbe_cpufreq.c19
-rw-r--r--drivers/cpufreq/pxa2xx-cpufreq.c27
-rw-r--r--drivers/cpufreq/pxa3xx-cpufreq.c12
-rw-r--r--drivers/cpufreq/s3c2416-cpufreq.c21
-rw-r--r--drivers/cpufreq/s3c64xx-cpufreq.c48
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c16
-rw-r--r--drivers/cpufreq/sa1100-cpufreq.c17
-rw-r--r--drivers/cpufreq/sa1110-cpufreq.c12
-rw-r--r--drivers/cpufreq/sc520_freq.c11
-rw-r--r--drivers/cpufreq/sparc-us2e-cpufreq.c7
-rw-r--r--drivers/cpufreq/sparc-us3-cpufreq.c7
-rw-r--r--drivers/cpufreq/spear-cpufreq.c13
-rw-r--r--drivers/cpufreq/speedstep-centrino.c21
-rw-r--r--drivers/cpufreq/speedstep-ich.c9
-rw-r--r--drivers/cpufreq/speedstep-smi.c7
-rw-r--r--drivers/cpufreq/tegra-cpufreq.c25
-rw-r--r--drivers/cpufreq/vexpress-spc-cpufreq.c70
-rw-r--r--include/linux/cpufreq.h7
54 files changed, 1124 insertions, 656 deletions
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 365795447804..c77170c04fd0 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -66,10 +66,22 @@ config ARCH_VEXPRESS_DCSCB
66 This is needed to provide CPU and cluster power management 66 This is needed to provide CPU and cluster power management
67 on RTSM implementing big.LITTLE. 67 on RTSM implementing big.LITTLE.
68 68
69config ARCH_VEXPRESS_SPC
70 bool "Versatile Express Serial Power Controller (SPC)"
71 select ARCH_HAS_CPUFREQ
72 select ARCH_HAS_OPP
73 select PM_OPP
74 help
75 The TC2 (A15x2 A7x3) versatile express core tile integrates a logic
76 block called Serial Power Controller (SPC) that provides the interface
77 between the dual cluster test-chip and the M3 microcontroller that
78 carries out power management.
79
69config ARCH_VEXPRESS_TC2_PM 80config ARCH_VEXPRESS_TC2_PM
70 bool "Versatile Express TC2 power management" 81 bool "Versatile Express TC2 power management"
71 depends on MCPM 82 depends on MCPM
72 select ARM_CCI 83 select ARM_CCI
84 select ARCH_VEXPRESS_SPC
73 help 85 help
74 Support for CPU and cluster power management on Versatile Express 86 Support for CPU and cluster power management on Versatile Express
75 with a TC2 (A15x2 A7x3) big.LITTLE core tile. 87 with a TC2 (A15x2 A7x3) big.LITTLE core tile.
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 505e64ab3eae..0997e0b7494c 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -8,7 +8,8 @@ obj-y := v2m.o
8obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o 8obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o
9obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o 9obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o
10CFLAGS_dcscb.o += -march=armv7-a 10CFLAGS_dcscb.o += -march=armv7-a
11obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o spc.o 11obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o
12obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o
12CFLAGS_tc2_pm.o += -march=armv7-a 13CFLAGS_tc2_pm.o += -march=armv7-a
13obj-$(CONFIG_SMP) += platsmp.o 14obj-$(CONFIG_SMP) += platsmp.o
14obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 15obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c
index eefb029197ca..033d34dcbd3f 100644
--- a/arch/arm/mach-vexpress/spc.c
+++ b/arch/arm/mach-vexpress/spc.c
@@ -17,14 +17,31 @@
17 * GNU General Public License for more details. 17 * GNU General Public License for more details.
18 */ 18 */
19 19
20#include <linux/clk-provider.h>
21#include <linux/clkdev.h>
22#include <linux/cpu.h>
23#include <linux/delay.h>
20#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/interrupt.h>
21#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/platform_device.h>
28#include <linux/pm_opp.h>
22#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/semaphore.h>
23 31
24#include <asm/cacheflush.h> 32#include <asm/cacheflush.h>
25 33
26#define SPCLOG "vexpress-spc: " 34#define SPCLOG "vexpress-spc: "
27 35
36#define PERF_LVL_A15 0x00
37#define PERF_REQ_A15 0x04
38#define PERF_LVL_A7 0x08
39#define PERF_REQ_A7 0x0c
40#define COMMS 0x10
41#define COMMS_REQ 0x14
42#define PWC_STATUS 0x18
43#define PWC_FLAG 0x1c
44
28/* SPC wake-up IRQs status and mask */ 45/* SPC wake-up IRQs status and mask */
29#define WAKE_INT_MASK 0x24 46#define WAKE_INT_MASK 0x24
30#define WAKE_INT_RAW 0x28 47#define WAKE_INT_RAW 0x28
@@ -36,12 +53,45 @@
36#define A15_BX_ADDR0 0x68 53#define A15_BX_ADDR0 0x68
37#define A7_BX_ADDR0 0x78 54#define A7_BX_ADDR0 0x78
38 55
56/* SPC system config interface registers */
57#define SYSCFG_WDATA 0x70
58#define SYSCFG_RDATA 0x74
59
60/* A15/A7 OPP virtual register base */
61#define A15_PERFVAL_BASE 0xC10
62#define A7_PERFVAL_BASE 0xC30
63
64/* Config interface control bits */
65#define SYSCFG_START (1 << 31)
66#define SYSCFG_SCC (6 << 20)
67#define SYSCFG_STAT (14 << 20)
68
39/* wake-up interrupt masks */ 69/* wake-up interrupt masks */
40#define GBL_WAKEUP_INT_MSK (0x3 << 10) 70#define GBL_WAKEUP_INT_MSK (0x3 << 10)
41 71
42/* TC2 static dual-cluster configuration */ 72/* TC2 static dual-cluster configuration */
43#define MAX_CLUSTERS 2 73#define MAX_CLUSTERS 2
44 74
75/*
76 * Even though the SPC takes max 3-5 ms to complete any OPP/COMMS
77 * operation, the operation could start just before jiffie is about
78 * to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz
79 */
80#define TIMEOUT_US 20000
81
82#define MAX_OPPS 8
83#define CA15_DVFS 0
84#define CA7_DVFS 1
85#define SPC_SYS_CFG 2
86#define STAT_COMPLETE(type) ((1 << 0) << (type << 2))
87#define STAT_ERR(type) ((1 << 1) << (type << 2))
88#define RESPONSE_MASK(type) (STAT_COMPLETE(type) | STAT_ERR(type))
89
90struct ve_spc_opp {
91 unsigned long freq;
92 unsigned long u_volt;
93};
94
45struct ve_spc_drvdata { 95struct ve_spc_drvdata {
46 void __iomem *baseaddr; 96 void __iomem *baseaddr;
47 /* 97 /*
@@ -49,6 +99,12 @@ struct ve_spc_drvdata {
49 * It corresponds to A15 processors MPIDR[15:8] bitfield 99 * It corresponds to A15 processors MPIDR[15:8] bitfield
50 */ 100 */
51 u32 a15_clusid; 101 u32 a15_clusid;
102 uint32_t cur_rsp_mask;
103 uint32_t cur_rsp_stat;
104 struct semaphore sem;
105 struct completion done;
106 struct ve_spc_opp *opps[MAX_CLUSTERS];
107 int num_opps[MAX_CLUSTERS];
52}; 108};
53 109
54static struct ve_spc_drvdata *info; 110static struct ve_spc_drvdata *info;
@@ -157,8 +213,197 @@ void ve_spc_powerdown(u32 cluster, bool enable)
157 writel_relaxed(enable, info->baseaddr + pwdrn_reg); 213 writel_relaxed(enable, info->baseaddr + pwdrn_reg);
158} 214}
159 215
160int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid) 216static int ve_spc_get_performance(int cluster, u32 *freq)
217{
218 struct ve_spc_opp *opps = info->opps[cluster];
219 u32 perf_cfg_reg = 0;
220 u32 perf;
221
222 perf_cfg_reg = cluster_is_a15(cluster) ? PERF_LVL_A15 : PERF_LVL_A7;
223
224 perf = readl_relaxed(info->baseaddr + perf_cfg_reg);
225 if (perf >= info->num_opps[cluster])
226 return -EINVAL;
227
228 opps += perf;
229 *freq = opps->freq;
230
231 return 0;
232}
233
234/* find closest match to given frequency in OPP table */
235static int ve_spc_round_performance(int cluster, u32 freq)
236{
237 int idx, max_opp = info->num_opps[cluster];
238 struct ve_spc_opp *opps = info->opps[cluster];
239 u32 fmin = 0, fmax = ~0, ftmp;
240
241 freq /= 1000; /* OPP entries in kHz */
242 for (idx = 0; idx < max_opp; idx++, opps++) {
243 ftmp = opps->freq;
244 if (ftmp >= freq) {
245 if (ftmp <= fmax)
246 fmax = ftmp;
247 } else {
248 if (ftmp >= fmin)
249 fmin = ftmp;
250 }
251 }
252 if (fmax != ~0)
253 return fmax * 1000;
254 else
255 return fmin * 1000;
256}
257
258static int ve_spc_find_performance_index(int cluster, u32 freq)
259{
260 int idx, max_opp = info->num_opps[cluster];
261 struct ve_spc_opp *opps = info->opps[cluster];
262
263 for (idx = 0; idx < max_opp; idx++, opps++)
264 if (opps->freq == freq)
265 break;
266 return (idx == max_opp) ? -EINVAL : idx;
267}
268
269static int ve_spc_waitforcompletion(int req_type)
270{
271 int ret = wait_for_completion_interruptible_timeout(
272 &info->done, usecs_to_jiffies(TIMEOUT_US));
273 if (ret == 0)
274 ret = -ETIMEDOUT;
275 else if (ret > 0)
276 ret = info->cur_rsp_stat & STAT_COMPLETE(req_type) ? 0 : -EIO;
277 return ret;
278}
279
280static int ve_spc_set_performance(int cluster, u32 freq)
281{
282 u32 perf_cfg_reg, perf_stat_reg;
283 int ret, perf, req_type;
284
285 if (cluster_is_a15(cluster)) {
286 req_type = CA15_DVFS;
287 perf_cfg_reg = PERF_LVL_A15;
288 perf_stat_reg = PERF_REQ_A15;
289 } else {
290 req_type = CA7_DVFS;
291 perf_cfg_reg = PERF_LVL_A7;
292 perf_stat_reg = PERF_REQ_A7;
293 }
294
295 perf = ve_spc_find_performance_index(cluster, freq);
296
297 if (perf < 0)
298 return perf;
299
300 if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
301 return -ETIME;
302
303 init_completion(&info->done);
304 info->cur_rsp_mask = RESPONSE_MASK(req_type);
305
306 writel(perf, info->baseaddr + perf_cfg_reg);
307 ret = ve_spc_waitforcompletion(req_type);
308
309 info->cur_rsp_mask = 0;
310 up(&info->sem);
311
312 return ret;
313}
314
315static int ve_spc_read_sys_cfg(int func, int offset, uint32_t *data)
316{
317 int ret;
318
319 if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
320 return -ETIME;
321
322 init_completion(&info->done);
323 info->cur_rsp_mask = RESPONSE_MASK(SPC_SYS_CFG);
324
325 /* Set the control value */
326 writel(SYSCFG_START | func | offset >> 2, info->baseaddr + COMMS);
327 ret = ve_spc_waitforcompletion(SPC_SYS_CFG);
328
329 if (ret == 0)
330 *data = readl(info->baseaddr + SYSCFG_RDATA);
331
332 info->cur_rsp_mask = 0;
333 up(&info->sem);
334
335 return ret;
336}
337
338static irqreturn_t ve_spc_irq_handler(int irq, void *data)
339{
340 struct ve_spc_drvdata *drv_data = data;
341 uint32_t status = readl_relaxed(drv_data->baseaddr + PWC_STATUS);
342
343 if (info->cur_rsp_mask & status) {
344 info->cur_rsp_stat = status;
345 complete(&drv_data->done);
346 }
347
348 return IRQ_HANDLED;
349}
350
351/*
352 * +--------------------------+
353 * | 31 20 | 19 0 |
354 * +--------------------------+
355 * | u_volt | freq(kHz) |
356 * +--------------------------+
357 */
358#define MULT_FACTOR 20
359#define VOLT_SHIFT 20
360#define FREQ_MASK (0xFFFFF)
361static int ve_spc_populate_opps(uint32_t cluster)
161{ 362{
363 uint32_t data = 0, off, ret, idx;
364 struct ve_spc_opp *opps;
365
366 opps = kzalloc(sizeof(*opps) * MAX_OPPS, GFP_KERNEL);
367 if (!opps)
368 return -ENOMEM;
369
370 info->opps[cluster] = opps;
371
372 off = cluster_is_a15(cluster) ? A15_PERFVAL_BASE : A7_PERFVAL_BASE;
373 for (idx = 0; idx < MAX_OPPS; idx++, off += 4, opps++) {
374 ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data);
375 if (!ret) {
376 opps->freq = (data & FREQ_MASK) * MULT_FACTOR;
377 opps->u_volt = data >> VOLT_SHIFT;
378 } else {
379 break;
380 }
381 }
382 info->num_opps[cluster] = idx;
383
384 return ret;
385}
386
387static int ve_init_opp_table(struct device *cpu_dev)
388{
389 int cluster = topology_physical_package_id(cpu_dev->id);
390 int idx, ret = 0, max_opp = info->num_opps[cluster];
391 struct ve_spc_opp *opps = info->opps[cluster];
392
393 for (idx = 0; idx < max_opp; idx++, opps++) {
394 ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt);
395 if (ret) {
396 dev_warn(cpu_dev, "failed to add opp %lu %lu\n",
397 opps->freq, opps->u_volt);
398 return ret;
399 }
400 }
401 return ret;
402}
403
404int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq)
405{
406 int ret;
162 info = kzalloc(sizeof(*info), GFP_KERNEL); 407 info = kzalloc(sizeof(*info), GFP_KERNEL);
163 if (!info) { 408 if (!info) {
164 pr_err(SPCLOG "unable to allocate mem\n"); 409 pr_err(SPCLOG "unable to allocate mem\n");
@@ -168,6 +413,25 @@ int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid)
168 info->baseaddr = baseaddr; 413 info->baseaddr = baseaddr;
169 info->a15_clusid = a15_clusid; 414 info->a15_clusid = a15_clusid;
170 415
416 if (irq <= 0) {
417 pr_err(SPCLOG "Invalid IRQ %d\n", irq);
418 kfree(info);
419 return -EINVAL;
420 }
421
422 init_completion(&info->done);
423
424 readl_relaxed(info->baseaddr + PWC_STATUS);
425
426 ret = request_irq(irq, ve_spc_irq_handler, IRQF_TRIGGER_HIGH
427 | IRQF_ONESHOT, "vexpress-spc", info);
428 if (ret) {
429 pr_err(SPCLOG "IRQ %d request failed\n", irq);
430 kfree(info);
431 return -ENODEV;
432 }
433
434 sema_init(&info->sem, 1);
171 /* 435 /*
172 * Multi-cluster systems may need this data when non-coherent, during 436 * Multi-cluster systems may need this data when non-coherent, during
173 * cluster power-up/power-down. Make sure driver info reaches main 437 * cluster power-up/power-down. Make sure driver info reaches main
@@ -178,3 +442,103 @@ int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid)
178 442
179 return 0; 443 return 0;
180} 444}
445
446struct clk_spc {
447 struct clk_hw hw;
448 int cluster;
449};
450
451#define to_clk_spc(spc) container_of(spc, struct clk_spc, hw)
452static unsigned long spc_recalc_rate(struct clk_hw *hw,
453 unsigned long parent_rate)
454{
455 struct clk_spc *spc = to_clk_spc(hw);
456 u32 freq;
457
458 if (ve_spc_get_performance(spc->cluster, &freq))
459 return -EIO;
460
461 return freq * 1000;
462}
463
464static long spc_round_rate(struct clk_hw *hw, unsigned long drate,
465 unsigned long *parent_rate)
466{
467 struct clk_spc *spc = to_clk_spc(hw);
468
469 return ve_spc_round_performance(spc->cluster, drate);
470}
471
472static int spc_set_rate(struct clk_hw *hw, unsigned long rate,
473 unsigned long parent_rate)
474{
475 struct clk_spc *spc = to_clk_spc(hw);
476
477 return ve_spc_set_performance(spc->cluster, rate / 1000);
478}
479
480static struct clk_ops clk_spc_ops = {
481 .recalc_rate = spc_recalc_rate,
482 .round_rate = spc_round_rate,
483 .set_rate = spc_set_rate,
484};
485
486static struct clk *ve_spc_clk_register(struct device *cpu_dev)
487{
488 struct clk_init_data init;
489 struct clk_spc *spc;
490
491 spc = kzalloc(sizeof(*spc), GFP_KERNEL);
492 if (!spc) {
493 pr_err("could not allocate spc clk\n");
494 return ERR_PTR(-ENOMEM);
495 }
496
497 spc->hw.init = &init;
498 spc->cluster = topology_physical_package_id(cpu_dev->id);
499
500 init.name = dev_name(cpu_dev);
501 init.ops = &clk_spc_ops;
502 init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
503 init.num_parents = 0;
504
505 return devm_clk_register(cpu_dev, &spc->hw);
506}
507
508static int __init ve_spc_clk_init(void)
509{
510 int cpu;
511 struct clk *clk;
512
513 if (!info)
514 return 0; /* Continue only if SPC is initialised */
515
516 if (ve_spc_populate_opps(0) || ve_spc_populate_opps(1)) {
517 pr_err("failed to build OPP table\n");
518 return -ENODEV;
519 }
520
521 for_each_possible_cpu(cpu) {
522 struct device *cpu_dev = get_cpu_device(cpu);
523 if (!cpu_dev) {
524 pr_warn("failed to get cpu%d device\n", cpu);
525 continue;
526 }
527 clk = ve_spc_clk_register(cpu_dev);
528 if (IS_ERR(clk)) {
529 pr_warn("failed to register cpu%d clock\n", cpu);
530 continue;
531 }
532 if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
533 pr_warn("failed to register cpu%d clock lookup\n", cpu);
534 continue;
535 }
536
537 if (ve_init_opp_table(cpu_dev))
538 pr_warn("failed to initialise cpu%d opp table\n", cpu);
539 }
540
541 platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
542 return 0;
543}
544module_init(ve_spc_clk_init);
diff --git a/arch/arm/mach-vexpress/spc.h b/arch/arm/mach-vexpress/spc.h
index 5f7e4a446a17..dbd44c3720f9 100644
--- a/arch/arm/mach-vexpress/spc.h
+++ b/arch/arm/mach-vexpress/spc.h
@@ -15,7 +15,7 @@
15#ifndef __SPC_H_ 15#ifndef __SPC_H_
16#define __SPC_H_ 16#define __SPC_H_
17 17
18int __init ve_spc_init(void __iomem *base, u32 a15_clusid); 18int __init ve_spc_init(void __iomem *base, u32 a15_clusid, int irq);
19void ve_spc_global_wakeup_irq(bool set); 19void ve_spc_global_wakeup_irq(bool set);
20void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set); 20void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set);
21void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr); 21void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr);
diff --git a/arch/arm/mach-vexpress/tc2_pm.c b/arch/arm/mach-vexpress/tc2_pm.c
index e6eb48192912..d38130aba464 100644
--- a/arch/arm/mach-vexpress/tc2_pm.c
+++ b/arch/arm/mach-vexpress/tc2_pm.c
@@ -16,6 +16,7 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/of_irq.h>
19#include <linux/spinlock.h> 20#include <linux/spinlock.h>
20#include <linux/errno.h> 21#include <linux/errno.h>
21#include <linux/irqchip/arm-gic.h> 22#include <linux/irqchip/arm-gic.h>
@@ -311,7 +312,7 @@ static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
311 312
312static int __init tc2_pm_init(void) 313static int __init tc2_pm_init(void)
313{ 314{
314 int ret; 315 int ret, irq;
315 void __iomem *scc; 316 void __iomem *scc;
316 u32 a15_cluster_id, a7_cluster_id, sys_info; 317 u32 a15_cluster_id, a7_cluster_id, sys_info;
317 struct device_node *np; 318 struct device_node *np;
@@ -336,13 +337,15 @@ static int __init tc2_pm_init(void)
336 tc2_nr_cpus[a15_cluster_id] = (sys_info >> 16) & 0xf; 337 tc2_nr_cpus[a15_cluster_id] = (sys_info >> 16) & 0xf;
337 tc2_nr_cpus[a7_cluster_id] = (sys_info >> 20) & 0xf; 338 tc2_nr_cpus[a7_cluster_id] = (sys_info >> 20) & 0xf;
338 339
340 irq = irq_of_parse_and_map(np, 0);
341
339 /* 342 /*
340 * A subset of the SCC registers is also used to communicate 343 * A subset of the SCC registers is also used to communicate
341 * with the SPC (power controller). We need to be able to 344 * with the SPC (power controller). We need to be able to
342 * drive it very early in the boot process to power up 345 * drive it very early in the boot process to power up
343 * processors, so we initialize the SPC driver here. 346 * processors, so we initialize the SPC driver here.
344 */ 347 */
345 ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id); 348 ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id, irq);
346 if (ret) 349 if (ret)
347 return ret; 350 return ret;
348 351
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 701ec95ce954..ce52ed949249 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -224,3 +224,11 @@ config ARM_TEGRA_CPUFREQ
224 default y 224 default y
225 help 225 help
226 This adds the CPUFreq driver support for TEGRA SOCs. 226 This adds the CPUFreq driver support for TEGRA SOCs.
227
228config ARM_VEXPRESS_SPC_CPUFREQ
229 tristate "Versatile Express SPC based CPUfreq driver"
230 select ARM_BIG_LITTLE_CPUFREQ
231 depends on ARCH_VEXPRESS_SPC
232 help
233 This add the CPUfreq driver support for Versatile Express
234 big.LITTLE platforms using SPC for power management.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index b7948bbbbf1f..74945652dd7a 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
74obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o 74obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
75obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o 75obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
76obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o 76obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o
77obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
77 78
78################################################################################## 79##################################################################################
79# PowerPC platform drivers 80# PowerPC platform drivers
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index e4bc19552d2b..caf41ebea184 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -428,14 +428,10 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
428{ 428{
429 struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); 429 struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
430 struct acpi_processor_performance *perf; 430 struct acpi_processor_performance *perf;
431 struct cpufreq_freqs freqs;
432 struct drv_cmd cmd; 431 struct drv_cmd cmd;
433 unsigned int next_perf_state = 0; /* Index into perf table */ 432 unsigned int next_perf_state = 0; /* Index into perf table */
434 int result = 0; 433 int result = 0;
435 434
436 pr_debug("acpi_cpufreq_target %d (%d)\n",
437 data->freq_table[index].frequency, policy->cpu);
438
439 if (unlikely(data == NULL || 435 if (unlikely(data == NULL ||
440 data->acpi_data == NULL || data->freq_table == NULL)) { 436 data->acpi_data == NULL || data->freq_table == NULL)) {
441 return -ENODEV; 437 return -ENODEV;
@@ -483,23 +479,17 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
483 else 479 else
484 cmd.mask = cpumask_of(policy->cpu); 480 cmd.mask = cpumask_of(policy->cpu);
485 481
486 freqs.old = perf->states[perf->state].core_frequency * 1000;
487 freqs.new = data->freq_table[index].frequency;
488 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
489
490 drv_write(&cmd); 482 drv_write(&cmd);
491 483
492 if (acpi_pstate_strict) { 484 if (acpi_pstate_strict) {
493 if (!check_freqs(cmd.mask, freqs.new, data)) { 485 if (!check_freqs(cmd.mask, data->freq_table[index].frequency,
486 data)) {
494 pr_debug("acpi_cpufreq_target failed (%d)\n", 487 pr_debug("acpi_cpufreq_target failed (%d)\n",
495 policy->cpu); 488 policy->cpu);
496 result = -EAGAIN; 489 result = -EAGAIN;
497 freqs.new = freqs.old;
498 } 490 }
499 } 491 }
500 492
501 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
502
503 if (!result) 493 if (!result)
504 perf->state = next_perf_state; 494 perf->state = next_perf_state;
505 495
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 163e3378fe17..5519933813ea 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -24,91 +24,319 @@
24#include <linux/cpufreq.h> 24#include <linux/cpufreq.h>
25#include <linux/cpumask.h> 25#include <linux/cpumask.h>
26#include <linux/export.h> 26#include <linux/export.h>
27#include <linux/mutex.h>
27#include <linux/of_platform.h> 28#include <linux/of_platform.h>
28#include <linux/pm_opp.h> 29#include <linux/pm_opp.h>
29#include <linux/slab.h> 30#include <linux/slab.h>
30#include <linux/topology.h> 31#include <linux/topology.h>
31#include <linux/types.h> 32#include <linux/types.h>
33#include <asm/bL_switcher.h>
32 34
33#include "arm_big_little.h" 35#include "arm_big_little.h"
34 36
35/* Currently we support only two clusters */ 37/* Currently we support only two clusters */
38#define A15_CLUSTER 0
39#define A7_CLUSTER 1
36#define MAX_CLUSTERS 2 40#define MAX_CLUSTERS 2
37 41
42#ifdef CONFIG_BL_SWITCHER
43static bool bL_switching_enabled;
44#define is_bL_switching_enabled() bL_switching_enabled
45#define set_switching_enabled(x) (bL_switching_enabled = (x))
46#else
47#define is_bL_switching_enabled() false
48#define set_switching_enabled(x) do { } while (0)
49#endif
50
51#define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq)
52#define VIRT_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq >> 1 : freq)
53
38static struct cpufreq_arm_bL_ops *arm_bL_ops; 54static struct cpufreq_arm_bL_ops *arm_bL_ops;
39static struct clk *clk[MAX_CLUSTERS]; 55static struct clk *clk[MAX_CLUSTERS];
40static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; 56static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1];
41static atomic_t cluster_usage[MAX_CLUSTERS] = {ATOMIC_INIT(0), ATOMIC_INIT(0)}; 57static atomic_t cluster_usage[MAX_CLUSTERS + 1];
58
59static unsigned int clk_big_min; /* (Big) clock frequencies */
60static unsigned int clk_little_max; /* Maximum clock frequency (Little) */
61
62static DEFINE_PER_CPU(unsigned int, physical_cluster);
63static DEFINE_PER_CPU(unsigned int, cpu_last_req_freq);
64
65static struct mutex cluster_lock[MAX_CLUSTERS];
66
67static inline int raw_cpu_to_cluster(int cpu)
68{
69 return topology_physical_package_id(cpu);
70}
71
72static inline int cpu_to_cluster(int cpu)
73{
74 return is_bL_switching_enabled() ?
75 MAX_CLUSTERS : raw_cpu_to_cluster(cpu);
76}
77
78static unsigned int find_cluster_maxfreq(int cluster)
79{
80 int j;
81 u32 max_freq = 0, cpu_freq;
82
83 for_each_online_cpu(j) {
84 cpu_freq = per_cpu(cpu_last_req_freq, j);
85
86 if ((cluster == per_cpu(physical_cluster, j)) &&
87 (max_freq < cpu_freq))
88 max_freq = cpu_freq;
89 }
90
91 pr_debug("%s: cluster: %d, max freq: %d\n", __func__, cluster,
92 max_freq);
93
94 return max_freq;
95}
96
97static unsigned int clk_get_cpu_rate(unsigned int cpu)
98{
99 u32 cur_cluster = per_cpu(physical_cluster, cpu);
100 u32 rate = clk_get_rate(clk[cur_cluster]) / 1000;
101
102 /* For switcher we use virtual A7 clock rates */
103 if (is_bL_switching_enabled())
104 rate = VIRT_FREQ(cur_cluster, rate);
105
106 pr_debug("%s: cpu: %d, cluster: %d, freq: %u\n", __func__, cpu,
107 cur_cluster, rate);
108
109 return rate;
110}
111
112static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
113{
114 if (is_bL_switching_enabled()) {
115 pr_debug("%s: freq: %d\n", __func__, per_cpu(cpu_last_req_freq,
116 cpu));
117
118 return per_cpu(cpu_last_req_freq, cpu);
119 } else {
120 return clk_get_cpu_rate(cpu);
121 }
122}
42 123
43static unsigned int bL_cpufreq_get(unsigned int cpu) 124static unsigned int
125bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
44{ 126{
45 u32 cur_cluster = cpu_to_cluster(cpu); 127 u32 new_rate, prev_rate;
128 int ret;
129 bool bLs = is_bL_switching_enabled();
130
131 mutex_lock(&cluster_lock[new_cluster]);
132
133 if (bLs) {
134 prev_rate = per_cpu(cpu_last_req_freq, cpu);
135 per_cpu(cpu_last_req_freq, cpu) = rate;
136 per_cpu(physical_cluster, cpu) = new_cluster;
137
138 new_rate = find_cluster_maxfreq(new_cluster);
139 new_rate = ACTUAL_FREQ(new_cluster, new_rate);
140 } else {
141 new_rate = rate;
142 }
143
144 pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
145 __func__, cpu, old_cluster, new_cluster, new_rate);
146
147 ret = clk_set_rate(clk[new_cluster], new_rate * 1000);
148 if (WARN_ON(ret)) {
149 pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
150 new_cluster);
151 if (bLs) {
152 per_cpu(cpu_last_req_freq, cpu) = prev_rate;
153 per_cpu(physical_cluster, cpu) = old_cluster;
154 }
155
156 mutex_unlock(&cluster_lock[new_cluster]);
157
158 return ret;
159 }
160
161 mutex_unlock(&cluster_lock[new_cluster]);
162
163 /* Recalc freq for old cluster when switching clusters */
164 if (old_cluster != new_cluster) {
165 pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d\n",
166 __func__, cpu, old_cluster, new_cluster);
167
168 /* Switch cluster */
169 bL_switch_request(cpu, new_cluster);
170
171 mutex_lock(&cluster_lock[old_cluster]);
46 172
47 return clk_get_rate(clk[cur_cluster]) / 1000; 173 /* Set freq of old cluster if there are cpus left on it */
174 new_rate = find_cluster_maxfreq(old_cluster);
175 new_rate = ACTUAL_FREQ(old_cluster, new_rate);
176
177 if (new_rate) {
178 pr_debug("%s: Updating rate of old cluster: %d, to freq: %d\n",
179 __func__, old_cluster, new_rate);
180
181 if (clk_set_rate(clk[old_cluster], new_rate * 1000))
182 pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n",
183 __func__, ret, old_cluster);
184 }
185 mutex_unlock(&cluster_lock[old_cluster]);
186 }
187
188 return 0;
48} 189}
49 190
50/* Set clock frequency */ 191/* Set clock frequency */
51static int bL_cpufreq_set_target(struct cpufreq_policy *policy, 192static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
52 unsigned int index) 193 unsigned int index)
53{ 194{
54 struct cpufreq_freqs freqs; 195 u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster;
55 u32 cpu = policy->cpu, cur_cluster; 196 unsigned int freqs_new;
56 int ret = 0; 197
198 cur_cluster = cpu_to_cluster(cpu);
199 new_cluster = actual_cluster = per_cpu(physical_cluster, cpu);
200
201 freqs_new = freq_table[cur_cluster][index].frequency;
202
203 if (is_bL_switching_enabled()) {
204 if ((actual_cluster == A15_CLUSTER) &&
205 (freqs_new < clk_big_min)) {
206 new_cluster = A7_CLUSTER;
207 } else if ((actual_cluster == A7_CLUSTER) &&
208 (freqs_new > clk_little_max)) {
209 new_cluster = A15_CLUSTER;
210 }
211 }
57 212
58 cur_cluster = cpu_to_cluster(policy->cpu); 213 return bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new);
214}
59 215
60 freqs.old = bL_cpufreq_get(policy->cpu); 216static inline u32 get_table_count(struct cpufreq_frequency_table *table)
61 freqs.new = freq_table[cur_cluster][index].frequency; 217{
218 int count;
62 219
63 pr_debug("%s: cpu: %d, cluster: %d, oldfreq: %d, target freq: %d, new freq: %d\n", 220 for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++)
64 __func__, cpu, cur_cluster, freqs.old, freqs.new, 221 ;
65 freqs.new);
66 222
67 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 223 return count;
224}
68 225
69 ret = clk_set_rate(clk[cur_cluster], freqs.new * 1000); 226/* get the minimum frequency in the cpufreq_frequency_table */
70 if (ret) { 227static inline u32 get_table_min(struct cpufreq_frequency_table *table)
71 pr_err("clk_set_rate failed: %d\n", ret); 228{
72 freqs.new = freqs.old; 229 int i;
230 uint32_t min_freq = ~0;
231 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++)
232 if (table[i].frequency < min_freq)
233 min_freq = table[i].frequency;
234 return min_freq;
235}
236
237/* get the maximum frequency in the cpufreq_frequency_table */
238static inline u32 get_table_max(struct cpufreq_frequency_table *table)
239{
240 int i;
241 uint32_t max_freq = 0;
242 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++)
243 if (table[i].frequency > max_freq)
244 max_freq = table[i].frequency;
245 return max_freq;
246}
247
248static int merge_cluster_tables(void)
249{
250 int i, j, k = 0, count = 1;
251 struct cpufreq_frequency_table *table;
252
253 for (i = 0; i < MAX_CLUSTERS; i++)
254 count += get_table_count(freq_table[i]);
255
256 table = kzalloc(sizeof(*table) * count, GFP_KERNEL);
257 if (!table)
258 return -ENOMEM;
259
260 freq_table[MAX_CLUSTERS] = table;
261
262 /* Add in reverse order to get freqs in increasing order */
263 for (i = MAX_CLUSTERS - 1; i >= 0; i--) {
264 for (j = 0; freq_table[i][j].frequency != CPUFREQ_TABLE_END;
265 j++) {
266 table[k].frequency = VIRT_FREQ(i,
267 freq_table[i][j].frequency);
268 pr_debug("%s: index: %d, freq: %d\n", __func__, k,
269 table[k].frequency);
270 k++;
271 }
73 } 272 }
74 273
75 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); 274 table[k].driver_data = k;
275 table[k].frequency = CPUFREQ_TABLE_END;
76 276
77 return ret; 277 pr_debug("%s: End, table: %p, count: %d\n", __func__, table, k);
278
279 return 0;
280}
281
282static void _put_cluster_clk_and_freq_table(struct device *cpu_dev)
283{
284 u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
285
286 if (!freq_table[cluster])
287 return;
288
289 clk_put(clk[cluster]);
290 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
291 dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster);
78} 292}
79 293
80static void put_cluster_clk_and_freq_table(struct device *cpu_dev) 294static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
81{ 295{
82 u32 cluster = cpu_to_cluster(cpu_dev->id); 296 u32 cluster = cpu_to_cluster(cpu_dev->id);
297 int i;
298
299 if (atomic_dec_return(&cluster_usage[cluster]))
300 return;
301
302 if (cluster < MAX_CLUSTERS)
303 return _put_cluster_clk_and_freq_table(cpu_dev);
304
305 for_each_present_cpu(i) {
306 struct device *cdev = get_cpu_device(i);
307 if (!cdev) {
308 pr_err("%s: failed to get cpu%d device\n", __func__, i);
309 return;
310 }
83 311
84 if (!atomic_dec_return(&cluster_usage[cluster])) { 312 _put_cluster_clk_and_freq_table(cdev);
85 clk_put(clk[cluster]);
86 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
87 dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster);
88 } 313 }
314
315 /* free virtual table */
316 kfree(freq_table[cluster]);
89} 317}
90 318
91static int get_cluster_clk_and_freq_table(struct device *cpu_dev) 319static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
92{ 320{
93 u32 cluster = cpu_to_cluster(cpu_dev->id); 321 u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
94 char name[14] = "cpu-cluster."; 322 char name[14] = "cpu-cluster.";
95 int ret; 323 int ret;
96 324
97 if (atomic_inc_return(&cluster_usage[cluster]) != 1) 325 if (freq_table[cluster])
98 return 0; 326 return 0;
99 327
100 ret = arm_bL_ops->init_opp_table(cpu_dev); 328 ret = arm_bL_ops->init_opp_table(cpu_dev);
101 if (ret) { 329 if (ret) {
102 dev_err(cpu_dev, "%s: init_opp_table failed, cpu: %d, err: %d\n", 330 dev_err(cpu_dev, "%s: init_opp_table failed, cpu: %d, err: %d\n",
103 __func__, cpu_dev->id, ret); 331 __func__, cpu_dev->id, ret);
104 goto atomic_dec; 332 goto out;
105 } 333 }
106 334
107 ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]); 335 ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
108 if (ret) { 336 if (ret) {
109 dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n", 337 dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n",
110 __func__, cpu_dev->id, ret); 338 __func__, cpu_dev->id, ret);
111 goto atomic_dec; 339 goto out;
112 } 340 }
113 341
114 name[12] = cluster + '0'; 342 name[12] = cluster + '0';
@@ -125,13 +353,72 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
125 ret = PTR_ERR(clk[cluster]); 353 ret = PTR_ERR(clk[cluster]);
126 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); 354 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
127 355
128atomic_dec: 356out:
129 atomic_dec(&cluster_usage[cluster]);
130 dev_err(cpu_dev, "%s: Failed to get data for cluster: %d\n", __func__, 357 dev_err(cpu_dev, "%s: Failed to get data for cluster: %d\n", __func__,
131 cluster); 358 cluster);
132 return ret; 359 return ret;
133} 360}
134 361
362static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
363{
364 u32 cluster = cpu_to_cluster(cpu_dev->id);
365 int i, ret;
366
367 if (atomic_inc_return(&cluster_usage[cluster]) != 1)
368 return 0;
369
370 if (cluster < MAX_CLUSTERS) {
371 ret = _get_cluster_clk_and_freq_table(cpu_dev);
372 if (ret)
373 atomic_dec(&cluster_usage[cluster]);
374 return ret;
375 }
376
377 /*
378 * Get data for all clusters and fill virtual cluster with a merge of
379 * both
380 */
381 for_each_present_cpu(i) {
382 struct device *cdev = get_cpu_device(i);
383 if (!cdev) {
384 pr_err("%s: failed to get cpu%d device\n", __func__, i);
385 return -ENODEV;
386 }
387
388 ret = _get_cluster_clk_and_freq_table(cdev);
389 if (ret)
390 goto put_clusters;
391 }
392
393 ret = merge_cluster_tables();
394 if (ret)
395 goto put_clusters;
396
397 /* Assuming 2 cluster, set clk_big_min and clk_little_max */
398 clk_big_min = get_table_min(freq_table[0]);
399 clk_little_max = VIRT_FREQ(1, get_table_max(freq_table[1]));
400
401 pr_debug("%s: cluster: %d, clk_big_min: %d, clk_little_max: %d\n",
402 __func__, cluster, clk_big_min, clk_little_max);
403
404 return 0;
405
406put_clusters:
407 for_each_present_cpu(i) {
408 struct device *cdev = get_cpu_device(i);
409 if (!cdev) {
410 pr_err("%s: failed to get cpu%d device\n", __func__, i);
411 return -ENODEV;
412 }
413
414 _put_cluster_clk_and_freq_table(cdev);
415 }
416
417 atomic_dec(&cluster_usage[cluster]);
418
419 return ret;
420}
421
135/* Per-CPU initialization */ 422/* Per-CPU initialization */
136static int bL_cpufreq_init(struct cpufreq_policy *policy) 423static int bL_cpufreq_init(struct cpufreq_policy *policy)
137{ 424{
@@ -158,13 +445,23 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
158 return ret; 445 return ret;
159 } 446 }
160 447
448 if (cur_cluster < MAX_CLUSTERS) {
449 cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
450
451 per_cpu(physical_cluster, policy->cpu) = cur_cluster;
452 } else {
453 /* Assumption: during init, we are always running on A15 */
454 per_cpu(physical_cluster, policy->cpu) = A15_CLUSTER;
455 }
456
161 if (arm_bL_ops->get_transition_latency) 457 if (arm_bL_ops->get_transition_latency)
162 policy->cpuinfo.transition_latency = 458 policy->cpuinfo.transition_latency =
163 arm_bL_ops->get_transition_latency(cpu_dev); 459 arm_bL_ops->get_transition_latency(cpu_dev);
164 else 460 else
165 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 461 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
166 462
167 cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); 463 if (is_bL_switching_enabled())
464 per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);
168 465
169 dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu); 466 dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu);
170 return 0; 467 return 0;
@@ -194,15 +491,47 @@ static struct cpufreq_driver bL_cpufreq_driver = {
194 CPUFREQ_HAVE_GOVERNOR_PER_POLICY, 491 CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
195 .verify = cpufreq_generic_frequency_table_verify, 492 .verify = cpufreq_generic_frequency_table_verify,
196 .target_index = bL_cpufreq_set_target, 493 .target_index = bL_cpufreq_set_target,
197 .get = bL_cpufreq_get, 494 .get = bL_cpufreq_get_rate,
198 .init = bL_cpufreq_init, 495 .init = bL_cpufreq_init,
199 .exit = bL_cpufreq_exit, 496 .exit = bL_cpufreq_exit,
200 .attr = cpufreq_generic_attr, 497 .attr = cpufreq_generic_attr,
201}; 498};
202 499
500static int bL_cpufreq_switcher_notifier(struct notifier_block *nfb,
501 unsigned long action, void *_arg)
502{
503 pr_debug("%s: action: %ld\n", __func__, action);
504
505 switch (action) {
506 case BL_NOTIFY_PRE_ENABLE:
507 case BL_NOTIFY_PRE_DISABLE:
508 cpufreq_unregister_driver(&bL_cpufreq_driver);
509 break;
510
511 case BL_NOTIFY_POST_ENABLE:
512 set_switching_enabled(true);
513 cpufreq_register_driver(&bL_cpufreq_driver);
514 break;
515
516 case BL_NOTIFY_POST_DISABLE:
517 set_switching_enabled(false);
518 cpufreq_register_driver(&bL_cpufreq_driver);
519 break;
520
521 default:
522 return NOTIFY_DONE;
523 }
524
525 return NOTIFY_OK;
526}
527
528static struct notifier_block bL_switcher_notifier = {
529 .notifier_call = bL_cpufreq_switcher_notifier,
530};
531
203int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) 532int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
204{ 533{
205 int ret; 534 int ret, i;
206 535
207 if (arm_bL_ops) { 536 if (arm_bL_ops) {
208 pr_debug("%s: Already registered: %s, exiting\n", __func__, 537 pr_debug("%s: Already registered: %s, exiting\n", __func__,
@@ -217,16 +546,29 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
217 546
218 arm_bL_ops = ops; 547 arm_bL_ops = ops;
219 548
549 ret = bL_switcher_get_enabled();
550 set_switching_enabled(ret);
551
552 for (i = 0; i < MAX_CLUSTERS; i++)
553 mutex_init(&cluster_lock[i]);
554
220 ret = cpufreq_register_driver(&bL_cpufreq_driver); 555 ret = cpufreq_register_driver(&bL_cpufreq_driver);
221 if (ret) { 556 if (ret) {
222 pr_info("%s: Failed registering platform driver: %s, err: %d\n", 557 pr_info("%s: Failed registering platform driver: %s, err: %d\n",
223 __func__, ops->name, ret); 558 __func__, ops->name, ret);
224 arm_bL_ops = NULL; 559 arm_bL_ops = NULL;
225 } else { 560 } else {
226 pr_info("%s: Registered platform driver: %s\n", __func__, 561 ret = bL_switcher_register_notifier(&bL_switcher_notifier);
227 ops->name); 562 if (ret) {
563 cpufreq_unregister_driver(&bL_cpufreq_driver);
564 arm_bL_ops = NULL;
565 } else {
566 pr_info("%s: Registered platform driver: %s\n",
567 __func__, ops->name);
568 }
228 } 569 }
229 570
571 bL_switcher_put_enabled();
230 return ret; 572 return ret;
231} 573}
232EXPORT_SYMBOL_GPL(bL_cpufreq_register); 574EXPORT_SYMBOL_GPL(bL_cpufreq_register);
@@ -239,7 +581,10 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops)
239 return; 581 return;
240 } 582 }
241 583
584 bL_switcher_get_enabled();
585 bL_switcher_unregister_notifier(&bL_switcher_notifier);
242 cpufreq_unregister_driver(&bL_cpufreq_driver); 586 cpufreq_unregister_driver(&bL_cpufreq_driver);
587 bL_switcher_put_enabled();
243 pr_info("%s: Un-registered platform driver: %s\n", __func__, 588 pr_info("%s: Un-registered platform driver: %s\n", __func__,
244 arm_bL_ops->name); 589 arm_bL_ops->name);
245 arm_bL_ops = NULL; 590 arm_bL_ops = NULL;
diff --git a/drivers/cpufreq/arm_big_little.h b/drivers/cpufreq/arm_big_little.h
index 79b2ce17884d..70f18fc12d4a 100644
--- a/drivers/cpufreq/arm_big_little.h
+++ b/drivers/cpufreq/arm_big_little.h
@@ -34,11 +34,6 @@ struct cpufreq_arm_bL_ops {
34 int (*init_opp_table)(struct device *cpu_dev); 34 int (*init_opp_table)(struct device *cpu_dev);
35}; 35};
36 36
37static inline int cpu_to_cluster(int cpu)
38{
39 return topology_physical_package_id(cpu);
40}
41
42int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops); 37int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops);
43void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops); 38void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops);
44 39
diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c
index 81d07527bde6..856ad80418ae 100644
--- a/drivers/cpufreq/at32ap-cpufreq.c
+++ b/drivers/cpufreq/at32ap-cpufreq.c
@@ -37,27 +37,23 @@ static unsigned long loops_per_jiffy_ref;
37 37
38static int at32_set_target(struct cpufreq_policy *policy, unsigned int index) 38static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
39{ 39{
40 struct cpufreq_freqs freqs; 40 unsigned int old_freq, new_freq;
41 41
42 freqs.old = at32_get_speed(0); 42 old_freq = at32_get_speed(0);
43 freqs.new = freq_table[index].frequency; 43 new_freq = freq_table[index].frequency;
44 44
45 if (!ref_freq) { 45 if (!ref_freq) {
46 ref_freq = freqs.old; 46 ref_freq = old_freq;
47 loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy; 47 loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy;
48 } 48 }
49 49
50 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 50 if (old_freq < new_freq)
51 if (freqs.old < freqs.new)
52 boot_cpu_data.loops_per_jiffy = cpufreq_scale( 51 boot_cpu_data.loops_per_jiffy = cpufreq_scale(
53 loops_per_jiffy_ref, ref_freq, freqs.new); 52 loops_per_jiffy_ref, ref_freq, new_freq);
54 clk_set_rate(cpuclk, freqs.new * 1000); 53 clk_set_rate(cpuclk, new_freq * 1000);
55 if (freqs.new < freqs.old) 54 if (new_freq < old_freq)
56 boot_cpu_data.loops_per_jiffy = cpufreq_scale( 55 boot_cpu_data.loops_per_jiffy = cpufreq_scale(
57 loops_per_jiffy_ref, ref_freq, freqs.new); 56 loops_per_jiffy_ref, ref_freq, new_freq);
58 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
59
60 pr_debug("cpufreq: set frequency %u Hz\n", freqs.new * 1000);
61 57
62 return 0; 58 return 0;
63} 59}
diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c
index 12528b28d45d..e9e63fc9c2c9 100644
--- a/drivers/cpufreq/blackfin-cpufreq.c
+++ b/drivers/cpufreq/blackfin-cpufreq.c
@@ -132,27 +132,23 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index)
132#ifndef CONFIG_BF60x 132#ifndef CONFIG_BF60x
133 unsigned int plldiv; 133 unsigned int plldiv;
134#endif 134#endif
135 struct cpufreq_freqs freqs;
136 static unsigned long lpj_ref; 135 static unsigned long lpj_ref;
137 static unsigned int lpj_ref_freq; 136 static unsigned int lpj_ref_freq;
137 unsigned int old_freq, new_freq;
138 int ret = 0; 138 int ret = 0;
139 139
140#if defined(CONFIG_CYCLES_CLOCKSOURCE) 140#if defined(CONFIG_CYCLES_CLOCKSOURCE)
141 cycles_t cycles; 141 cycles_t cycles;
142#endif 142#endif
143 143
144 freqs.old = bfin_getfreq_khz(0); 144 old_freq = bfin_getfreq_khz(0);
145 freqs.new = bfin_freq_table[index].frequency; 145 new_freq = bfin_freq_table[index].frequency;
146 146
147 pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
148 freqs.new, freqs.new, freqs.old);
149
150 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
151#ifndef CONFIG_BF60x 147#ifndef CONFIG_BF60x
152 plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel; 148 plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
153 bfin_write_PLL_DIV(plldiv); 149 bfin_write_PLL_DIV(plldiv);
154#else 150#else
155 ret = cpu_set_cclk(policy->cpu, freqs.new * 1000); 151 ret = cpu_set_cclk(policy->cpu, new_freq * 1000);
156 if (ret != 0) { 152 if (ret != 0) {
157 WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret); 153 WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret);
158 return ret; 154 return ret;
@@ -168,17 +164,13 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index)
168#endif 164#endif
169 if (!lpj_ref_freq) { 165 if (!lpj_ref_freq) {
170 lpj_ref = loops_per_jiffy; 166 lpj_ref = loops_per_jiffy;
171 lpj_ref_freq = freqs.old; 167 lpj_ref_freq = old_freq;
172 } 168 }
173 if (freqs.new != freqs.old) { 169 if (new_freq != old_freq) {
174 loops_per_jiffy = cpufreq_scale(lpj_ref, 170 loops_per_jiffy = cpufreq_scale(lpj_ref,
175 lpj_ref_freq, freqs.new); 171 lpj_ref_freq, new_freq);
176 } 172 }
177 173
178 /* TODO: just test case for cycles clock source, remove later */
179 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
180
181 pr_debug("cpufreq: done\n");
182 return ret; 174 return ret;
183} 175}
184 176
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 4dbe7efd86e5..d4585ce2346c 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -37,20 +37,19 @@ static unsigned int cpu0_get_speed(unsigned int cpu)
37 37
38static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) 38static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
39{ 39{
40 struct cpufreq_freqs freqs;
41 struct dev_pm_opp *opp; 40 struct dev_pm_opp *opp;
42 unsigned long volt = 0, volt_old = 0, tol = 0; 41 unsigned long volt = 0, volt_old = 0, tol = 0;
42 unsigned int old_freq, new_freq;
43 long freq_Hz, freq_exact; 43 long freq_Hz, freq_exact;
44 int ret; 44 int ret;
45 45
46 freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); 46 freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
47 if (freq_Hz < 0) 47 if (freq_Hz < 0)
48 freq_Hz = freq_table[index].frequency * 1000; 48 freq_Hz = freq_table[index].frequency * 1000;
49 freq_exact = freq_Hz;
50 freqs.new = freq_Hz / 1000;
51 freqs.old = clk_get_rate(cpu_clk) / 1000;
52 49
53 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 50 freq_exact = freq_Hz;
51 new_freq = freq_Hz / 1000;
52 old_freq = clk_get_rate(cpu_clk) / 1000;
54 53
55 if (!IS_ERR(cpu_reg)) { 54 if (!IS_ERR(cpu_reg)) {
56 rcu_read_lock(); 55 rcu_read_lock();
@@ -58,9 +57,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
58 if (IS_ERR(opp)) { 57 if (IS_ERR(opp)) {
59 rcu_read_unlock(); 58 rcu_read_unlock();
60 pr_err("failed to find OPP for %ld\n", freq_Hz); 59 pr_err("failed to find OPP for %ld\n", freq_Hz);
61 freqs.new = freqs.old; 60 return PTR_ERR(opp);
62 ret = PTR_ERR(opp);
63 goto post_notify;
64 } 61 }
65 volt = dev_pm_opp_get_voltage(opp); 62 volt = dev_pm_opp_get_voltage(opp);
66 rcu_read_unlock(); 63 rcu_read_unlock();
@@ -69,16 +66,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
69 } 66 }
70 67
71 pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n", 68 pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
72 freqs.old / 1000, volt_old ? volt_old / 1000 : -1, 69 old_freq / 1000, volt_old ? volt_old / 1000 : -1,
73 freqs.new / 1000, volt ? volt / 1000 : -1); 70 new_freq / 1000, volt ? volt / 1000 : -1);
74 71
75 /* scaling up? scale voltage before frequency */ 72 /* scaling up? scale voltage before frequency */
76 if (!IS_ERR(cpu_reg) && freqs.new > freqs.old) { 73 if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
77 ret = regulator_set_voltage_tol(cpu_reg, volt, tol); 74 ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
78 if (ret) { 75 if (ret) {
79 pr_err("failed to scale voltage up: %d\n", ret); 76 pr_err("failed to scale voltage up: %d\n", ret);
80 freqs.new = freqs.old; 77 return ret;
81 goto post_notify;
82 } 78 }
83 } 79 }
84 80
@@ -87,23 +83,18 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
87 pr_err("failed to set clock rate: %d\n", ret); 83 pr_err("failed to set clock rate: %d\n", ret);
88 if (!IS_ERR(cpu_reg)) 84 if (!IS_ERR(cpu_reg))
89 regulator_set_voltage_tol(cpu_reg, volt_old, tol); 85 regulator_set_voltage_tol(cpu_reg, volt_old, tol);
90 freqs.new = freqs.old; 86 return ret;
91 goto post_notify;
92 } 87 }
93 88
94 /* scaling down? scale voltage after frequency */ 89 /* scaling down? scale voltage after frequency */
95 if (!IS_ERR(cpu_reg) && freqs.new < freqs.old) { 90 if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
96 ret = regulator_set_voltage_tol(cpu_reg, volt, tol); 91 ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
97 if (ret) { 92 if (ret) {
98 pr_err("failed to scale voltage down: %d\n", ret); 93 pr_err("failed to scale voltage down: %d\n", ret);
99 clk_set_rate(cpu_clk, freqs.old * 1000); 94 clk_set_rate(cpu_clk, old_freq * 1000);
100 freqs.new = freqs.old;
101 } 95 }
102 } 96 }
103 97
104post_notify:
105 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
106
107 return ret; 98 return ret;
108} 99}
109 100
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6c9cbb9ebd1f..02d534da22dd 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1669,6 +1669,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
1669 retval = cpufreq_driver->target(policy, target_freq, relation); 1669 retval = cpufreq_driver->target(policy, target_freq, relation);
1670 else if (cpufreq_driver->target_index) { 1670 else if (cpufreq_driver->target_index) {
1671 struct cpufreq_frequency_table *freq_table; 1671 struct cpufreq_frequency_table *freq_table;
1672 struct cpufreq_freqs freqs;
1673 bool notify;
1672 int index; 1674 int index;
1673 1675
1674 freq_table = cpufreq_frequency_get_table(policy->cpu); 1676 freq_table = cpufreq_frequency_get_table(policy->cpu);
@@ -1684,10 +1686,42 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
1684 goto out; 1686 goto out;
1685 } 1687 }
1686 1688
1687 if (freq_table[index].frequency == policy->cur) 1689 if (freq_table[index].frequency == policy->cur) {
1688 retval = 0; 1690 retval = 0;
1689 else 1691 goto out;
1690 retval = cpufreq_driver->target_index(policy, index); 1692 }
1693
1694 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
1695
1696 if (notify) {
1697 freqs.old = policy->cur;
1698 freqs.new = freq_table[index].frequency;
1699 freqs.flags = 0;
1700
1701 pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
1702 __func__, policy->cpu, freqs.old,
1703 freqs.new);
1704
1705 cpufreq_notify_transition(policy, &freqs,
1706 CPUFREQ_PRECHANGE);
1707 }
1708
1709 retval = cpufreq_driver->target_index(policy, index);
1710 if (retval)
1711 pr_err("%s: Failed to change cpu frequency: %d\n",
1712 __func__, retval);
1713
1714 if (notify) {
1715 /*
1716 * Notify with old freq in case we failed to change
1717 * frequency
1718 */
1719 if (retval)
1720 freqs.new = freqs.old;
1721
1722 cpufreq_notify_transition(policy, &freqs,
1723 CPUFREQ_POSTCHANGE);
1724 }
1691 } 1725 }
1692 1726
1693out: 1727out:
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 32f26f6e17c5..18d409189092 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -168,7 +168,6 @@ static void od_check_cpu(int cpu, unsigned int load)
168 dbs_info->rate_mult = 168 dbs_info->rate_mult =
169 od_tuners->sampling_down_factor; 169 od_tuners->sampling_down_factor;
170 dbs_freq_increase(policy, policy->max); 170 dbs_freq_increase(policy, policy->max);
171 return;
172 } else { 171 } else {
173 /* Calculate the next frequency proportional to load */ 172 /* Calculate the next frequency proportional to load */
174 unsigned int freq_next; 173 unsigned int freq_next;
diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c
index 841857cf1562..86559040c54c 100644
--- a/drivers/cpufreq/cris-artpec3-cpufreq.c
+++ b/drivers/cpufreq/cris-artpec3-cpufreq.c
@@ -29,15 +29,9 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
29 29
30static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) 30static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state)
31{ 31{
32 struct cpufreq_freqs freqs;
33 reg_clkgen_rw_clk_ctrl clk_ctrl; 32 reg_clkgen_rw_clk_ctrl clk_ctrl;
34 clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); 33 clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
35 34
36 freqs.old = cris_freq_get_cpu_frequency(policy->cpu);
37 freqs.new = cris_freq_table[state].frequency;
38
39 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
40
41 local_irq_disable(); 35 local_irq_disable();
42 36
43 /* Even though we may be SMP they will share the same clock 37 /* Even though we may be SMP they will share the same clock
@@ -50,8 +44,6 @@ static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state)
50 44
51 local_irq_enable(); 45 local_irq_enable();
52 46
53 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
54
55 return 0; 47 return 0;
56} 48}
57 49
diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c
index c58811abd961..26d940d40b1d 100644
--- a/drivers/cpufreq/cris-etraxfs-cpufreq.c
+++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c
@@ -29,15 +29,9 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
29 29
30static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) 30static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state)
31{ 31{
32 struct cpufreq_freqs freqs;
33 reg_config_rw_clk_ctrl clk_ctrl; 32 reg_config_rw_clk_ctrl clk_ctrl;
34 clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl); 33 clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl);
35 34
36 freqs.old = cris_freq_get_cpu_frequency(policy->cpu);
37 freqs.new = cris_freq_table[state].frequency;
38
39 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
40
41 local_irq_disable(); 35 local_irq_disable();
42 36
43 /* Even though we may be SMP they will share the same clock 37 /* Even though we may be SMP they will share the same clock
@@ -50,8 +44,6 @@ static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state)
50 44
51 local_irq_enable(); 45 local_irq_enable();
52 46
53 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
54
55 return 0; 47 return 0;
56} 48}
57 49
diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c
index 1f5d8a569c77..5e8a854381b7 100644
--- a/drivers/cpufreq/davinci-cpufreq.c
+++ b/drivers/cpufreq/davinci-cpufreq.c
@@ -68,46 +68,36 @@ static unsigned int davinci_getspeed(unsigned int cpu)
68 68
69static int davinci_target(struct cpufreq_policy *policy, unsigned int idx) 69static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
70{ 70{
71 int ret = 0;
72 struct cpufreq_freqs freqs;
73 struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; 71 struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
74 struct clk *armclk = cpufreq.armclk; 72 struct clk *armclk = cpufreq.armclk;
73 unsigned int old_freq, new_freq;
74 int ret = 0;
75 75
76 freqs.old = davinci_getspeed(0); 76 old_freq = davinci_getspeed(0);
77 freqs.new = pdata->freq_table[idx].frequency; 77 new_freq = pdata->freq_table[idx].frequency;
78
79 dev_dbg(cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new);
80
81 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
82 78
83 /* if moving to higher frequency, up the voltage beforehand */ 79 /* if moving to higher frequency, up the voltage beforehand */
84 if (pdata->set_voltage && freqs.new > freqs.old) { 80 if (pdata->set_voltage && new_freq > old_freq) {
85 ret = pdata->set_voltage(idx); 81 ret = pdata->set_voltage(idx);
86 if (ret) 82 if (ret)
87 goto out; 83 return ret;
88 } 84 }
89 85
90 ret = clk_set_rate(armclk, idx); 86 ret = clk_set_rate(armclk, idx);
91 if (ret) 87 if (ret)
92 goto out; 88 return ret;
93 89
94 if (cpufreq.asyncclk) { 90 if (cpufreq.asyncclk) {
95 ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate); 91 ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate);
96 if (ret) 92 if (ret)
97 goto out; 93 return ret;
98 } 94 }
99 95
100 /* if moving to lower freq, lower the voltage after lowering freq */ 96 /* if moving to lower freq, lower the voltage after lowering freq */
101 if (pdata->set_voltage && freqs.new < freqs.old) 97 if (pdata->set_voltage && new_freq < old_freq)
102 pdata->set_voltage(idx); 98 pdata->set_voltage(idx);
103 99
104out: 100 return 0;
105 if (ret)
106 freqs.new = freqs.old;
107
108 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
109
110 return ret;
111} 101}
112 102
113static int davinci_cpu_init(struct cpufreq_policy *policy) 103static int davinci_cpu_init(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c
index 238b16976be1..0e67ab96321a 100644
--- a/drivers/cpufreq/dbx500-cpufreq.c
+++ b/drivers/cpufreq/dbx500-cpufreq.c
@@ -22,28 +22,8 @@ static struct clk *armss_clk;
22static int dbx500_cpufreq_target(struct cpufreq_policy *policy, 22static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
23 unsigned int index) 23 unsigned int index)
24{ 24{
25 struct cpufreq_freqs freqs;
26 int ret;
27
28 freqs.old = policy->cur;
29 freqs.new = freq_table[index].frequency;
30
31 /* pre-change notification */
32 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
33
34 /* update armss clk frequency */ 25 /* update armss clk frequency */
35 ret = clk_set_rate(armss_clk, freqs.new * 1000); 26 return clk_set_rate(armss_clk, freq_table[index].frequency * 1000);
36
37 if (ret) {
38 pr_err("dbx500-cpufreq: Failed to set armss_clk to %d Hz: error %d\n",
39 freqs.new * 1000, ret);
40 freqs.new = freqs.old;
41 }
42
43 /* post change notification */
44 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
45
46 return ret;
47} 27}
48 28
49static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu) 29static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu)
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index b39c4ef60a7a..9012b8bb6b64 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -107,15 +107,9 @@ static int eps_set_state(struct eps_cpu_data *centaur,
107 struct cpufreq_policy *policy, 107 struct cpufreq_policy *policy,
108 u32 dest_state) 108 u32 dest_state)
109{ 109{
110 struct cpufreq_freqs freqs;
111 u32 lo, hi; 110 u32 lo, hi;
112 int err = 0;
113 int i; 111 int i;
114 112
115 freqs.old = eps_get(policy->cpu);
116 freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff);
117 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
118
119 /* Wait while CPU is busy */ 113 /* Wait while CPU is busy */
120 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 114 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
121 i = 0; 115 i = 0;
@@ -124,8 +118,7 @@ static int eps_set_state(struct eps_cpu_data *centaur,
124 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 118 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
125 i++; 119 i++;
126 if (unlikely(i > 64)) { 120 if (unlikely(i > 64)) {
127 err = -ENODEV; 121 return -ENODEV;
128 goto postchange;
129 } 122 }
130 } 123 }
131 /* Set new multiplier and voltage */ 124 /* Set new multiplier and voltage */
@@ -137,16 +130,10 @@ static int eps_set_state(struct eps_cpu_data *centaur,
137 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 130 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
138 i++; 131 i++;
139 if (unlikely(i > 64)) { 132 if (unlikely(i > 64)) {
140 err = -ENODEV; 133 return -ENODEV;
141 goto postchange;
142 } 134 }
143 } while (lo & ((1 << 16) | (1 << 17))); 135 } while (lo & ((1 << 16) | (1 << 17)));
144 136
145 /* Return current frequency */
146postchange:
147 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
148 freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
149
150#ifdef DEBUG 137#ifdef DEBUG
151 { 138 {
152 u8 current_multiplier, current_voltage; 139 u8 current_multiplier, current_voltage;
@@ -161,11 +148,7 @@ postchange:
161 current_multiplier); 148 current_multiplier);
162 } 149 }
163#endif 150#endif
164 if (err) 151 return 0;
165 freqs.new = freqs.old;
166
167 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
168 return err;
169} 152}
170 153
171static int eps_target(struct cpufreq_policy *policy, unsigned int index) 154static int eps_target(struct cpufreq_policy *policy, unsigned int index)
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c
index 4ab41539514f..de08acff5101 100644
--- a/drivers/cpufreq/elanfreq.c
+++ b/drivers/cpufreq/elanfreq.c
@@ -108,17 +108,6 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
108static int elanfreq_target(struct cpufreq_policy *policy, 108static int elanfreq_target(struct cpufreq_policy *policy,
109 unsigned int state) 109 unsigned int state)
110{ 110{
111 struct cpufreq_freqs freqs;
112
113 freqs.old = elanfreq_get_cpu_frequency(0);
114 freqs.new = elan_multiplier[state].clock;
115
116 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
117
118 printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",
119 elan_multiplier[state].clock);
120
121
122 /* 111 /*
123 * Access to the Elan's internal registers is indexed via 112 * Access to the Elan's internal registers is indexed via
124 * 0x22: Chip Setup & Control Register Index Register (CSCI) 113 * 0x22: Chip Setup & Control Register Index Register (CSCI)
@@ -149,8 +138,6 @@ static int elanfreq_target(struct cpufreq_policy *policy,
149 udelay(10000); 138 udelay(10000);
150 local_irq_enable(); 139 local_irq_enable();
151 140
152 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
153
154 return 0; 141 return 0;
155} 142}
156/* 143/*
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 9982fcb82257..7b6dc06b1bd4 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -25,7 +25,6 @@
25static struct exynos_dvfs_info *exynos_info; 25static struct exynos_dvfs_info *exynos_info;
26 26
27static struct regulator *arm_regulator; 27static struct regulator *arm_regulator;
28static struct cpufreq_freqs freqs;
29 28
30static unsigned int locking_frequency; 29static unsigned int locking_frequency;
31static bool frequency_locked; 30static bool frequency_locked;
@@ -59,18 +58,18 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
59 struct cpufreq_policy *policy = cpufreq_cpu_get(0); 58 struct cpufreq_policy *policy = cpufreq_cpu_get(0);
60 unsigned int arm_volt, safe_arm_volt = 0; 59 unsigned int arm_volt, safe_arm_volt = 0;
61 unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz; 60 unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
61 unsigned int old_freq;
62 int index, old_index; 62 int index, old_index;
63 int ret = 0; 63 int ret = 0;
64 64
65 freqs.old = policy->cur; 65 old_freq = policy->cur;
66 freqs.new = target_freq;
67 66
68 /* 67 /*
69 * The policy max have been changed so that we cannot get proper 68 * The policy max have been changed so that we cannot get proper
70 * old_index with cpufreq_frequency_table_target(). Thus, ignore 69 * old_index with cpufreq_frequency_table_target(). Thus, ignore
71 * policy and get the index from the raw freqeuncy table. 70 * policy and get the index from the raw freqeuncy table.
72 */ 71 */
73 old_index = exynos_cpufreq_get_index(freqs.old); 72 old_index = exynos_cpufreq_get_index(old_freq);
74 if (old_index < 0) { 73 if (old_index < 0) {
75 ret = old_index; 74 ret = old_index;
76 goto out; 75 goto out;
@@ -95,17 +94,14 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
95 } 94 }
96 arm_volt = volt_table[index]; 95 arm_volt = volt_table[index];
97 96
98 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
99
100 /* When the new frequency is higher than current frequency */ 97 /* When the new frequency is higher than current frequency */
101 if ((freqs.new > freqs.old) && !safe_arm_volt) { 98 if ((target_freq > old_freq) && !safe_arm_volt) {
102 /* Firstly, voltage up to increase frequency */ 99 /* Firstly, voltage up to increase frequency */
103 ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt); 100 ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
104 if (ret) { 101 if (ret) {
105 pr_err("%s: failed to set cpu voltage to %d\n", 102 pr_err("%s: failed to set cpu voltage to %d\n",
106 __func__, arm_volt); 103 __func__, arm_volt);
107 freqs.new = freqs.old; 104 return ret;
108 goto post_notify;
109 } 105 }
110 } 106 }
111 107
@@ -115,22 +111,15 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
115 if (ret) { 111 if (ret) {
116 pr_err("%s: failed to set cpu voltage to %d\n", 112 pr_err("%s: failed to set cpu voltage to %d\n",
117 __func__, safe_arm_volt); 113 __func__, safe_arm_volt);
118 freqs.new = freqs.old; 114 return ret;
119 goto post_notify;
120 } 115 }
121 } 116 }
122 117
123 exynos_info->set_freq(old_index, index); 118 exynos_info->set_freq(old_index, index);
124 119
125post_notify:
126 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
127
128 if (ret)
129 goto out;
130
131 /* When the new frequency is lower than current frequency */ 120 /* When the new frequency is lower than current frequency */
132 if ((freqs.new < freqs.old) || 121 if ((target_freq < old_freq) ||
133 ((freqs.new > freqs.old) && safe_arm_volt)) { 122 ((target_freq > old_freq) && safe_arm_volt)) {
134 /* down the voltage after frequency change */ 123 /* down the voltage after frequency change */
135 ret = regulator_set_voltage(arm_regulator, arm_volt, 124 ret = regulator_set_voltage(arm_regulator, arm_volt,
136 arm_volt); 125 arm_volt);
@@ -142,7 +131,6 @@ post_notify:
142 } 131 }
143 132
144out: 133out:
145
146 cpufreq_cpu_put(policy); 134 cpufreq_cpu_put(policy);
147 135
148 return ret; 136 return ret;
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c
index 1bf9b060d522..76bef8b078cb 100644
--- a/drivers/cpufreq/exynos5440-cpufreq.c
+++ b/drivers/cpufreq/exynos5440-cpufreq.c
@@ -312,7 +312,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
312} 312}
313 313
314static struct cpufreq_driver exynos_driver = { 314static struct cpufreq_driver exynos_driver = {
315 .flags = CPUFREQ_STICKY, 315 .flags = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION,
316 .verify = cpufreq_generic_frequency_table_verify, 316 .verify = cpufreq_generic_frequency_table_verify,
317 .target_index = exynos_target, 317 .target_index = exynos_target,
318 .get = exynos_getspeed, 318 .get = exynos_getspeed,
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
index 4695fa22406a..53c6ac637e10 100644
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ b/drivers/cpufreq/ia64-acpi-cpufreq.c
@@ -141,7 +141,6 @@ processor_set_freq (
141{ 141{
142 int ret = 0; 142 int ret = 0;
143 u32 value = 0; 143 u32 value = 0;
144 struct cpufreq_freqs cpufreq_freqs;
145 cpumask_t saved_mask; 144 cpumask_t saved_mask;
146 int retval; 145 int retval;
147 146
@@ -168,13 +167,6 @@ processor_set_freq (
168 pr_debug("Transitioning from P%d to P%d\n", 167 pr_debug("Transitioning from P%d to P%d\n",
169 data->acpi_data.state, state); 168 data->acpi_data.state, state);
170 169
171 /* cpufreq frequency struct */
172 cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
173 cpufreq_freqs.new = data->freq_table[state].frequency;
174
175 /* notify cpufreq */
176 cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_PRECHANGE);
177
178 /* 170 /*
179 * First we write the target state's 'control' value to the 171 * First we write the target state's 'control' value to the
180 * control_register. 172 * control_register.
@@ -186,22 +178,11 @@ processor_set_freq (
186 178
187 ret = processor_set_pstate(value); 179 ret = processor_set_pstate(value);
188 if (ret) { 180 if (ret) {
189 unsigned int tmp = cpufreq_freqs.new;
190 cpufreq_notify_transition(policy, &cpufreq_freqs,
191 CPUFREQ_POSTCHANGE);
192 cpufreq_freqs.new = cpufreq_freqs.old;
193 cpufreq_freqs.old = tmp;
194 cpufreq_notify_transition(policy, &cpufreq_freqs,
195 CPUFREQ_PRECHANGE);
196 cpufreq_notify_transition(policy, &cpufreq_freqs,
197 CPUFREQ_POSTCHANGE);
198 printk(KERN_WARNING "Transition failed with error %d\n", ret); 181 printk(KERN_WARNING "Transition failed with error %d\n", ret);
199 retval = -ENODEV; 182 retval = -ENODEV;
200 goto migrate_end; 183 goto migrate_end;
201 } 184 }
202 185
203 cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_POSTCHANGE);
204
205 data->acpi_data.state = state; 186 data->acpi_data.state = state;
206 187
207 retval = 0; 188 retval = 0;
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 07af3b0de069..4b3f18e5f36b 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -42,14 +42,14 @@ static unsigned int imx6q_get_speed(unsigned int cpu)
42 42
43static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) 43static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
44{ 44{
45 struct cpufreq_freqs freqs;
46 struct dev_pm_opp *opp; 45 struct dev_pm_opp *opp;
47 unsigned long freq_hz, volt, volt_old; 46 unsigned long freq_hz, volt, volt_old;
47 unsigned int old_freq, new_freq;
48 int ret; 48 int ret;
49 49
50 freqs.new = freq_table[index].frequency; 50 new_freq = freq_table[index].frequency;
51 freq_hz = freqs.new * 1000; 51 freq_hz = new_freq * 1000;
52 freqs.old = clk_get_rate(arm_clk) / 1000; 52 old_freq = clk_get_rate(arm_clk) / 1000;
53 53
54 rcu_read_lock(); 54 rcu_read_lock();
55 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); 55 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
@@ -64,26 +64,23 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
64 volt_old = regulator_get_voltage(arm_reg); 64 volt_old = regulator_get_voltage(arm_reg);
65 65
66 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", 66 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
67 freqs.old / 1000, volt_old / 1000, 67 old_freq / 1000, volt_old / 1000,
68 freqs.new / 1000, volt / 1000); 68 new_freq / 1000, volt / 1000);
69
70 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
71 69
72 /* scaling up? scale voltage before frequency */ 70 /* scaling up? scale voltage before frequency */
73 if (freqs.new > freqs.old) { 71 if (new_freq > old_freq) {
74 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 72 ret = regulator_set_voltage_tol(arm_reg, volt, 0);
75 if (ret) { 73 if (ret) {
76 dev_err(cpu_dev, 74 dev_err(cpu_dev,
77 "failed to scale vddarm up: %d\n", ret); 75 "failed to scale vddarm up: %d\n", ret);
78 freqs.new = freqs.old; 76 return ret;
79 goto post_notify;
80 } 77 }
81 78
82 /* 79 /*
83 * Need to increase vddpu and vddsoc for safety 80 * Need to increase vddpu and vddsoc for safety
84 * if we are about to run at 1.2 GHz. 81 * if we are about to run at 1.2 GHz.
85 */ 82 */
86 if (freqs.new == FREQ_1P2_GHZ / 1000) { 83 if (new_freq == FREQ_1P2_GHZ / 1000) {
87 regulator_set_voltage_tol(pu_reg, 84 regulator_set_voltage_tol(pu_reg,
88 PU_SOC_VOLTAGE_HIGH, 0); 85 PU_SOC_VOLTAGE_HIGH, 0);
89 regulator_set_voltage_tol(soc_reg, 86 regulator_set_voltage_tol(soc_reg,
@@ -103,21 +100,20 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
103 clk_set_parent(step_clk, pll2_pfd2_396m_clk); 100 clk_set_parent(step_clk, pll2_pfd2_396m_clk);
104 clk_set_parent(pll1_sw_clk, step_clk); 101 clk_set_parent(pll1_sw_clk, step_clk);
105 if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { 102 if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
106 clk_set_rate(pll1_sys_clk, freqs.new * 1000); 103 clk_set_rate(pll1_sys_clk, new_freq * 1000);
107 clk_set_parent(pll1_sw_clk, pll1_sys_clk); 104 clk_set_parent(pll1_sw_clk, pll1_sys_clk);
108 } 105 }
109 106
110 /* Ensure the arm clock divider is what we expect */ 107 /* Ensure the arm clock divider is what we expect */
111 ret = clk_set_rate(arm_clk, freqs.new * 1000); 108 ret = clk_set_rate(arm_clk, new_freq * 1000);
112 if (ret) { 109 if (ret) {
113 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); 110 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
114 regulator_set_voltage_tol(arm_reg, volt_old, 0); 111 regulator_set_voltage_tol(arm_reg, volt_old, 0);
115 freqs.new = freqs.old; 112 return ret;
116 goto post_notify;
117 } 113 }
118 114
119 /* scaling down? scale voltage after frequency */ 115 /* scaling down? scale voltage after frequency */
120 if (freqs.new < freqs.old) { 116 if (new_freq < old_freq) {
121 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 117 ret = regulator_set_voltage_tol(arm_reg, volt, 0);
122 if (ret) { 118 if (ret) {
123 dev_warn(cpu_dev, 119 dev_warn(cpu_dev,
@@ -125,7 +121,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
125 ret = 0; 121 ret = 0;
126 } 122 }
127 123
128 if (freqs.old == FREQ_1P2_GHZ / 1000) { 124 if (old_freq == FREQ_1P2_GHZ / 1000) {
129 regulator_set_voltage_tol(pu_reg, 125 regulator_set_voltage_tol(pu_reg,
130 PU_SOC_VOLTAGE_NORMAL, 0); 126 PU_SOC_VOLTAGE_NORMAL, 0);
131 regulator_set_voltage_tol(soc_reg, 127 regulator_set_voltage_tol(soc_reg,
@@ -133,10 +129,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
133 } 129 }
134 } 130 }
135 131
136post_notify: 132 return 0;
137 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
138
139 return ret;
140} 133}
141 134
142static int imx6q_cpufreq_init(struct cpufreq_policy *policy) 135static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 89925513fea5..5f1cbae36961 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -25,6 +25,7 @@
25#include <linux/types.h> 25#include <linux/types.h>
26#include <linux/fs.h> 26#include <linux/fs.h>
27#include <linux/debugfs.h> 27#include <linux/debugfs.h>
28#include <linux/acpi.h>
28#include <trace/events/power.h> 29#include <trace/events/power.h>
29 30
30#include <asm/div64.h> 31#include <asm/div64.h>
@@ -759,7 +760,7 @@ static int intel_pstate_msrs_not_valid(void)
759 return 0; 760 return 0;
760} 761}
761 762
762void copy_pid_params(struct pstate_adjust_policy *policy) 763static void copy_pid_params(struct pstate_adjust_policy *policy)
763{ 764{
764 pid_params.sample_rate_ms = policy->sample_rate_ms; 765 pid_params.sample_rate_ms = policy->sample_rate_ms;
765 pid_params.p_gain_pct = policy->p_gain_pct; 766 pid_params.p_gain_pct = policy->p_gain_pct;
@@ -769,7 +770,7 @@ void copy_pid_params(struct pstate_adjust_policy *policy)
769 pid_params.setpoint = policy->setpoint; 770 pid_params.setpoint = policy->setpoint;
770} 771}
771 772
772void copy_cpu_funcs(struct pstate_funcs *funcs) 773static void copy_cpu_funcs(struct pstate_funcs *funcs)
773{ 774{
774 pstate_funcs.get_max = funcs->get_max; 775 pstate_funcs.get_max = funcs->get_max;
775 pstate_funcs.get_min = funcs->get_min; 776 pstate_funcs.get_min = funcs->get_min;
@@ -777,6 +778,72 @@ void copy_cpu_funcs(struct pstate_funcs *funcs)
777 pstate_funcs.set = funcs->set; 778 pstate_funcs.set = funcs->set;
778} 779}
779 780
781#if IS_ENABLED(CONFIG_ACPI)
782#include <acpi/processor.h>
783
784static bool intel_pstate_no_acpi_pss(void)
785{
786 int i;
787
788 for_each_possible_cpu(i) {
789 acpi_status status;
790 union acpi_object *pss;
791 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
792 struct acpi_processor *pr = per_cpu(processors, i);
793
794 if (!pr)
795 continue;
796
797 status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
798 if (ACPI_FAILURE(status))
799 continue;
800
801 pss = buffer.pointer;
802 if (pss && pss->type == ACPI_TYPE_PACKAGE) {
803 kfree(pss);
804 return false;
805 }
806
807 kfree(pss);
808 }
809
810 return true;
811}
812
813struct hw_vendor_info {
814 u16 valid;
815 char oem_id[ACPI_OEM_ID_SIZE];
816 char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
817};
818
819/* Hardware vendor-specific info that has its own power management modes */
820static struct hw_vendor_info vendor_info[] = {
821 {1, "HP ", "ProLiant"},
822 {0, "", ""},
823};
824
825static bool intel_pstate_platform_pwr_mgmt_exists(void)
826{
827 struct acpi_table_header hdr;
828 struct hw_vendor_info *v_info;
829
830 if (acpi_disabled
831 || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
832 return false;
833
834 for (v_info = vendor_info; v_info->valid; v_info++) {
835 if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE)
836 && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE)
837 && intel_pstate_no_acpi_pss())
838 return true;
839 }
840
841 return false;
842}
843#else /* CONFIG_ACPI not enabled */
844static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
845#endif /* CONFIG_ACPI */
846
780static int __init intel_pstate_init(void) 847static int __init intel_pstate_init(void)
781{ 848{
782 int cpu, rc = 0; 849 int cpu, rc = 0;
@@ -790,6 +857,13 @@ static int __init intel_pstate_init(void)
790 if (!id) 857 if (!id)
791 return -ENODEV; 858 return -ENODEV;
792 859
860 /*
861 * The Intel pstate driver will be ignored if the platform
862 * firmware has its own power management modes.
863 */
864 if (intel_pstate_platform_pwr_mgmt_exists())
865 return -ENODEV;
866
793 cpu_info = (struct cpu_defaults *)id->driver_data; 867 cpu_info = (struct cpu_defaults *)id->driver_data;
794 868
795 copy_pid_params(&cpu_info->pid_policy); 869 copy_pid_params(&cpu_info->pid_policy);
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index 0ae4dd7e1f2d..0767a4e29dfe 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -58,48 +58,34 @@ static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
58static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, 58static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
59 unsigned int index) 59 unsigned int index)
60{ 60{
61 struct cpufreq_freqs freqs;
62 unsigned int state = kirkwood_freq_table[index].driver_data; 61 unsigned int state = kirkwood_freq_table[index].driver_data;
63 unsigned long reg; 62 unsigned long reg;
64 63
65 freqs.old = kirkwood_cpufreq_get_cpu_frequency(0); 64 local_irq_disable();
66 freqs.new = kirkwood_freq_table[index].frequency;
67 65
68 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 66 /* Disable interrupts to the CPU */
67 reg = readl_relaxed(priv.base);
68 reg |= CPU_SW_INT_BLK;
69 writel_relaxed(reg, priv.base);
69 70
70 dev_dbg(priv.dev, "Attempting to set frequency to %i KHz\n", 71 switch (state) {
71 kirkwood_freq_table[index].frequency); 72 case STATE_CPU_FREQ:
72 dev_dbg(priv.dev, "old frequency was %i KHz\n", 73 clk_disable(priv.powersave_clk);
73 kirkwood_cpufreq_get_cpu_frequency(0)); 74 break;
74 75 case STATE_DDR_FREQ:
75 if (freqs.old != freqs.new) { 76 clk_enable(priv.powersave_clk);
76 local_irq_disable(); 77 break;
77 78 }
78 /* Disable interrupts to the CPU */
79 reg = readl_relaxed(priv.base);
80 reg |= CPU_SW_INT_BLK;
81 writel_relaxed(reg, priv.base);
82
83 switch (state) {
84 case STATE_CPU_FREQ:
85 clk_disable(priv.powersave_clk);
86 break;
87 case STATE_DDR_FREQ:
88 clk_enable(priv.powersave_clk);
89 break;
90 }
91 79
92 /* Wait-for-Interrupt, while the hardware changes frequency */ 80 /* Wait-for-Interrupt, while the hardware changes frequency */
93 cpu_do_idle(); 81 cpu_do_idle();
94 82
95 /* Enable interrupts to the CPU */ 83 /* Enable interrupts to the CPU */
96 reg = readl_relaxed(priv.base); 84 reg = readl_relaxed(priv.base);
97 reg &= ~CPU_SW_INT_BLK; 85 reg &= ~CPU_SW_INT_BLK;
98 writel_relaxed(reg, priv.base); 86 writel_relaxed(reg, priv.base);
99 87
100 local_irq_enable(); 88 local_irq_enable();
101 }
102 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
103 89
104 return 0; 90 return 0;
105} 91}
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index 41a8e2cdf940..a43609218105 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -57,7 +57,6 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
57{ 57{
58 unsigned int cpu = policy->cpu; 58 unsigned int cpu = policy->cpu;
59 cpumask_t cpus_allowed; 59 cpumask_t cpus_allowed;
60 struct cpufreq_freqs freqs;
61 unsigned int freq; 60 unsigned int freq;
62 61
63 cpus_allowed = current->cpus_allowed; 62 cpus_allowed = current->cpus_allowed;
@@ -67,26 +66,11 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
67 ((cpu_clock_freq / 1000) * 66 ((cpu_clock_freq / 1000) *
68 loongson2_clockmod_table[index].driver_data) / 8; 67 loongson2_clockmod_table[index].driver_data) / 8;
69 68
70 pr_debug("cpufreq: requested frequency %u Hz\n",
71 loongson2_clockmod_table[index].frequency * 1000);
72
73 freqs.old = loongson2_cpufreq_get(cpu);
74 freqs.new = freq;
75 freqs.flags = 0;
76
77 /* notifiers */
78 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
79
80 set_cpus_allowed_ptr(current, &cpus_allowed); 69 set_cpus_allowed_ptr(current, &cpus_allowed);
81 70
82 /* setting the cpu frequency */ 71 /* setting the cpu frequency */
83 clk_set_rate(cpuclk, freq); 72 clk_set_rate(cpuclk, freq);
84 73
85 /* notifiers */
86 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
87
88 pr_debug("cpufreq: set frequency %u kHz\n", freq);
89
90 return 0; 74 return 0;
91} 75}
92 76
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
index 4e2da0874bfb..c4dfa42a75ac 100644
--- a/drivers/cpufreq/maple-cpufreq.c
+++ b/drivers/cpufreq/maple-cpufreq.c
@@ -69,8 +69,6 @@ static struct cpufreq_frequency_table maple_cpu_freqs[] = {
69 */ 69 */
70static int maple_pmode_cur; 70static int maple_pmode_cur;
71 71
72static DEFINE_MUTEX(maple_switch_mutex);
73
74static const u32 *maple_pmode_data; 72static const u32 *maple_pmode_data;
75static int maple_pmode_max; 73static int maple_pmode_max;
76 74
@@ -133,21 +131,7 @@ static int maple_scom_query_freq(void)
133static int maple_cpufreq_target(struct cpufreq_policy *policy, 131static int maple_cpufreq_target(struct cpufreq_policy *policy,
134 unsigned int index) 132 unsigned int index)
135{ 133{
136 struct cpufreq_freqs freqs; 134 return maple_scom_switch_freq(index);
137 int rc;
138
139 mutex_lock(&maple_switch_mutex);
140
141 freqs.old = maple_cpu_freqs[maple_pmode_cur].frequency;
142 freqs.new = maple_cpu_freqs[index].frequency;
143
144 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
145 rc = maple_scom_switch_freq(index);
146 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
147
148 mutex_unlock(&maple_switch_mutex);
149
150 return rc;
151} 135}
152 136
153static unsigned int maple_cpufreq_get_speed(unsigned int cpu) 137static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index b5512712298f..be6d14307aa8 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -53,15 +53,14 @@ static unsigned int omap_getspeed(unsigned int cpu)
53 53
54static int omap_target(struct cpufreq_policy *policy, unsigned int index) 54static int omap_target(struct cpufreq_policy *policy, unsigned int index)
55{ 55{
56 int r, ret = 0;
57 struct cpufreq_freqs freqs;
58 struct dev_pm_opp *opp; 56 struct dev_pm_opp *opp;
59 unsigned long freq, volt = 0, volt_old = 0, tol = 0; 57 unsigned long freq, volt = 0, volt_old = 0, tol = 0;
58 unsigned int old_freq, new_freq;
60 59
61 freqs.old = omap_getspeed(policy->cpu); 60 old_freq = omap_getspeed(policy->cpu);
62 freqs.new = freq_table[index].frequency; 61 new_freq = freq_table[index].frequency;
63 62
64 freq = freqs.new * 1000; 63 freq = new_freq * 1000;
65 ret = clk_round_rate(mpu_clk, freq); 64 ret = clk_round_rate(mpu_clk, freq);
66 if (IS_ERR_VALUE(ret)) { 65 if (IS_ERR_VALUE(ret)) {
67 dev_warn(mpu_dev, 66 dev_warn(mpu_dev,
@@ -77,7 +76,7 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int index)
77 if (IS_ERR(opp)) { 76 if (IS_ERR(opp)) {
78 rcu_read_unlock(); 77 rcu_read_unlock();
79 dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", 78 dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
80 __func__, freqs.new); 79 __func__, new_freq);
81 return -EINVAL; 80 return -EINVAL;
82 } 81 }
83 volt = dev_pm_opp_get_voltage(opp); 82 volt = dev_pm_opp_get_voltage(opp);
@@ -87,43 +86,32 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int index)
87 } 86 }
88 87
89 dev_dbg(mpu_dev, "cpufreq-omap: %u MHz, %ld mV --> %u MHz, %ld mV\n", 88 dev_dbg(mpu_dev, "cpufreq-omap: %u MHz, %ld mV --> %u MHz, %ld mV\n",
90 freqs.old / 1000, volt_old ? volt_old / 1000 : -1, 89 old_freq / 1000, volt_old ? volt_old / 1000 : -1,
91 freqs.new / 1000, volt ? volt / 1000 : -1); 90 new_freq / 1000, volt ? volt / 1000 : -1);
92
93 /* notifiers */
94 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
95 91
96 /* scaling up? scale voltage before frequency */ 92 /* scaling up? scale voltage before frequency */
97 if (mpu_reg && (freqs.new > freqs.old)) { 93 if (mpu_reg && (new_freq > old_freq)) {
98 r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); 94 r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol);
99 if (r < 0) { 95 if (r < 0) {
100 dev_warn(mpu_dev, "%s: unable to scale voltage up.\n", 96 dev_warn(mpu_dev, "%s: unable to scale voltage up.\n",
101 __func__); 97 __func__);
102 freqs.new = freqs.old; 98 return r;
103 goto done;
104 } 99 }
105 } 100 }
106 101
107 ret = clk_set_rate(mpu_clk, freqs.new * 1000); 102 ret = clk_set_rate(mpu_clk, new_freq * 1000);
108 103
109 /* scaling down? scale voltage after frequency */ 104 /* scaling down? scale voltage after frequency */
110 if (mpu_reg && (freqs.new < freqs.old)) { 105 if (mpu_reg && (new_freq < old_freq)) {
111 r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); 106 r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol);
112 if (r < 0) { 107 if (r < 0) {
113 dev_warn(mpu_dev, "%s: unable to scale voltage down.\n", 108 dev_warn(mpu_dev, "%s: unable to scale voltage down.\n",
114 __func__); 109 __func__);
115 ret = clk_set_rate(mpu_clk, freqs.old * 1000); 110 clk_set_rate(mpu_clk, old_freq * 1000);
116 freqs.new = freqs.old; 111 return r;
117 goto done;
118 } 112 }
119 } 113 }
120 114
121 freqs.new = omap_getspeed(policy->cpu);
122
123done:
124 /* notifiers */
125 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
126
127 return ret; 115 return ret;
128} 116}
129 117
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
index 3c23053afdfd..3d1cba9fd5f9 100644
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -107,15 +107,8 @@ static struct cpufreq_frequency_table p4clockmod_table[] = {
107 107
108static int cpufreq_p4_target(struct cpufreq_policy *policy, unsigned int index) 108static int cpufreq_p4_target(struct cpufreq_policy *policy, unsigned int index)
109{ 109{
110 struct cpufreq_freqs freqs;
111 int i; 110 int i;
112 111
113 freqs.old = cpufreq_p4_get(policy->cpu);
114 freqs.new = stock_freq * p4clockmod_table[index].driver_data / 8;
115
116 /* notifiers */
117 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
118
119 /* run on each logical CPU, 112 /* run on each logical CPU,
120 * see section 13.15.3 of IA32 Intel Architecture Software 113 * see section 13.15.3 of IA32 Intel Architecture Software
121 * Developer's Manual, Volume 3 114 * Developer's Manual, Volume 3
@@ -123,9 +116,6 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, unsigned int index)
123 for_each_cpu(i, policy->cpus) 116 for_each_cpu(i, policy->cpus)
124 cpufreq_p4_setdc(i, p4clockmod_table[index].driver_data); 117 cpufreq_p4_setdc(i, p4clockmod_table[index].driver_data);
125 118
126 /* notifiers */
127 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
128
129 return 0; 119 return 0;
130} 120}
131 121
diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c
index 17424ddc7f67..1c331369b15b 100644
--- a/drivers/cpufreq/pasemi-cpufreq.c
+++ b/drivers/cpufreq/pasemi-cpufreq.c
@@ -51,8 +51,6 @@
51static void __iomem *sdcpwr_mapbase; 51static void __iomem *sdcpwr_mapbase;
52static void __iomem *sdcasr_mapbase; 52static void __iomem *sdcasr_mapbase;
53 53
54static DEFINE_MUTEX(pas_switch_mutex);
55
56/* Current astate, is used when waking up from power savings on 54/* Current astate, is used when waking up from power savings on
57 * one core, in case the other core has switched states during 55 * one core, in case the other core has switched states during
58 * the idle time. 56 * the idle time.
@@ -242,15 +240,8 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
242static int pas_cpufreq_target(struct cpufreq_policy *policy, 240static int pas_cpufreq_target(struct cpufreq_policy *policy,
243 unsigned int pas_astate_new) 241 unsigned int pas_astate_new)
244{ 242{
245 struct cpufreq_freqs freqs;
246 int i; 243 int i;
247 244
248 freqs.old = policy->cur;
249 freqs.new = pas_freqs[pas_astate_new].frequency;
250
251 mutex_lock(&pas_switch_mutex);
252 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
253
254 pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", 245 pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
255 policy->cpu, 246 policy->cpu,
256 pas_freqs[pas_astate_new].frequency, 247 pas_freqs[pas_astate_new].frequency,
@@ -261,10 +252,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy,
261 for_each_online_cpu(i) 252 for_each_online_cpu(i)
262 set_astate(i, pas_astate_new); 253 set_astate(i, pas_astate_new);
263 254
264 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); 255 ppc_proc_freq = pas_freqs[pas_astate_new].frequency * 1000ul;
265 mutex_unlock(&pas_switch_mutex);
266
267 ppc_proc_freq = freqs.new * 1000ul;
268 return 0; 256 return 0;
269} 257}
270 258
diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c
index 05f705e1b7a2..cf55d202f332 100644
--- a/drivers/cpufreq/pmac32-cpufreq.c
+++ b/drivers/cpufreq/pmac32-cpufreq.c
@@ -331,21 +331,11 @@ static int pmu_set_cpu_speed(int low_speed)
331 return 0; 331 return 0;
332} 332}
333 333
334static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode, 334static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode)
335 int notify)
336{ 335{
337 struct cpufreq_freqs freqs;
338 unsigned long l3cr; 336 unsigned long l3cr;
339 static unsigned long prev_l3cr; 337 static unsigned long prev_l3cr;
340 338
341 freqs.old = cur_freq;
342 freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
343
344 if (freqs.old == freqs.new)
345 return 0;
346
347 if (notify)
348 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
349 if (speed_mode == CPUFREQ_LOW && 339 if (speed_mode == CPUFREQ_LOW &&
350 cpu_has_feature(CPU_FTR_L3CR)) { 340 cpu_has_feature(CPU_FTR_L3CR)) {
351 l3cr = _get_L3CR(); 341 l3cr = _get_L3CR();
@@ -361,8 +351,6 @@ static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode,
361 if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) 351 if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
362 _set_L3CR(prev_l3cr); 352 _set_L3CR(prev_l3cr);
363 } 353 }
364 if (notify)
365 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
366 cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; 354 cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
367 355
368 return 0; 356 return 0;
@@ -378,7 +366,7 @@ static int pmac_cpufreq_target( struct cpufreq_policy *policy,
378{ 366{
379 int rc; 367 int rc;
380 368
381 rc = do_set_cpu_speed(policy, index, 1); 369 rc = do_set_cpu_speed(policy, index);
382 370
383 ppc_proc_freq = cur_freq * 1000ul; 371 ppc_proc_freq = cur_freq * 1000ul;
384 return rc; 372 return rc;
@@ -420,7 +408,7 @@ static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)
420 no_schedule = 1; 408 no_schedule = 1;
421 sleep_freq = cur_freq; 409 sleep_freq = cur_freq;
422 if (cur_freq == low_freq && !is_pmu_based) 410 if (cur_freq == low_freq && !is_pmu_based)
423 do_set_cpu_speed(policy, CPUFREQ_HIGH, 0); 411 do_set_cpu_speed(policy, CPUFREQ_HIGH);
424 return 0; 412 return 0;
425} 413}
426 414
@@ -437,7 +425,7 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
437 * probably high speed due to our suspend() routine 425 * probably high speed due to our suspend() routine
438 */ 426 */
439 do_set_cpu_speed(policy, sleep_freq == low_freq ? 427 do_set_cpu_speed(policy, sleep_freq == low_freq ?
440 CPUFREQ_LOW : CPUFREQ_HIGH, 0); 428 CPUFREQ_LOW : CPUFREQ_HIGH);
441 429
442 ppc_proc_freq = cur_freq * 1000ul; 430 ppc_proc_freq = cur_freq * 1000ul;
443 431
diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c
index 234b598ce416..6a338f8c3860 100644
--- a/drivers/cpufreq/pmac64-cpufreq.c
+++ b/drivers/cpufreq/pmac64-cpufreq.c
@@ -79,8 +79,6 @@ static void (*g5_switch_volt)(int speed_mode);
79static int (*g5_switch_freq)(int speed_mode); 79static int (*g5_switch_freq)(int speed_mode);
80static int (*g5_query_freq)(void); 80static int (*g5_query_freq)(void);
81 81
82static DEFINE_MUTEX(g5_switch_mutex);
83
84static unsigned long transition_latency; 82static unsigned long transition_latency;
85 83
86#ifdef CONFIG_PMAC_SMU 84#ifdef CONFIG_PMAC_SMU
@@ -314,21 +312,7 @@ static int g5_pfunc_query_freq(void)
314 312
315static int g5_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) 313static int g5_cpufreq_target(struct cpufreq_policy *policy, unsigned int index)
316{ 314{
317 struct cpufreq_freqs freqs; 315 return g5_switch_freq(index);
318 int rc;
319
320 mutex_lock(&g5_switch_mutex);
321
322 freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency;
323 freqs.new = g5_cpu_freqs[index].frequency;
324
325 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
326 rc = g5_switch_freq(index);
327 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
328
329 mutex_unlock(&g5_switch_mutex);
330
331 return rc;
332} 316}
333 317
334static unsigned int g5_cpufreq_get_speed(unsigned int cpu) 318static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index 62a1ce47d3df..0023c7d40a51 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1204,6 +1204,7 @@ out:
1204} 1204}
1205 1205
1206static struct cpufreq_driver cpufreq_amd64_driver = { 1206static struct cpufreq_driver cpufreq_amd64_driver = {
1207 .flags = CPUFREQ_ASYNC_NOTIFICATION,
1207 .verify = cpufreq_generic_frequency_table_verify, 1208 .verify = cpufreq_generic_frequency_table_verify,
1208 .target_index = powernowk8_target, 1209 .target_index = powernowk8_target,
1209 .bios_limit = acpi_processor_get_bios_limit, 1210 .bios_limit = acpi_processor_get_bios_limit,
diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c
index 79d8e9c46b6d..3f7be46d2b27 100644
--- a/drivers/cpufreq/ppc-corenet-cpufreq.c
+++ b/drivers/cpufreq/ppc-corenet-cpufreq.c
@@ -69,8 +69,6 @@ static const struct soc_data sdata[] = {
69static u32 min_cpufreq; 69static u32 min_cpufreq;
70static const u32 *fmask; 70static const u32 *fmask;
71 71
72/* serialize frequency changes */
73static DEFINE_MUTEX(cpufreq_lock);
74static DEFINE_PER_CPU(struct cpu_data *, cpu_data); 72static DEFINE_PER_CPU(struct cpu_data *, cpu_data);
75 73
76/* cpumask in a cluster */ 74/* cpumask in a cluster */
@@ -253,26 +251,11 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
253static int corenet_cpufreq_target(struct cpufreq_policy *policy, 251static int corenet_cpufreq_target(struct cpufreq_policy *policy,
254 unsigned int index) 252 unsigned int index)
255{ 253{
256 struct cpufreq_freqs freqs;
257 struct clk *parent; 254 struct clk *parent;
258 int ret;
259 struct cpu_data *data = per_cpu(cpu_data, policy->cpu); 255 struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
260 256
261 freqs.old = policy->cur;
262 freqs.new = data->table[index].frequency;
263
264 mutex_lock(&cpufreq_lock);
265 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
266
267 parent = of_clk_get(data->parent, data->table[index].driver_data); 257 parent = of_clk_get(data->parent, data->table[index].driver_data);
268 ret = clk_set_parent(data->clk, parent); 258 return clk_set_parent(data->clk, parent);
269 if (ret)
270 freqs.new = freqs.old;
271
272 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
273 mutex_unlock(&cpufreq_lock);
274
275 return ret;
276} 259}
277 260
278static struct cpufreq_driver ppc_corenet_cpufreq_driver = { 261static struct cpufreq_driver ppc_corenet_cpufreq_driver = {
diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c
index 52f707d5f458..e42ca9c31cea 100644
--- a/drivers/cpufreq/ppc_cbe_cpufreq.c
+++ b/drivers/cpufreq/ppc_cbe_cpufreq.c
@@ -30,9 +30,6 @@
30 30
31#include "ppc_cbe_cpufreq.h" 31#include "ppc_cbe_cpufreq.h"
32 32
33static DEFINE_MUTEX(cbe_switch_mutex);
34
35
36/* the CBE supports an 8 step frequency scaling */ 33/* the CBE supports an 8 step frequency scaling */
37static struct cpufreq_frequency_table cbe_freqs[] = { 34static struct cpufreq_frequency_table cbe_freqs[] = {
38 {1, 0}, 35 {1, 0},
@@ -131,27 +128,13 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
131static int cbe_cpufreq_target(struct cpufreq_policy *policy, 128static int cbe_cpufreq_target(struct cpufreq_policy *policy,
132 unsigned int cbe_pmode_new) 129 unsigned int cbe_pmode_new)
133{ 130{
134 int rc;
135 struct cpufreq_freqs freqs;
136
137 freqs.old = policy->cur;
138 freqs.new = cbe_freqs[cbe_pmode_new].frequency;
139
140 mutex_lock(&cbe_switch_mutex);
141 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
142
143 pr_debug("setting frequency for cpu %d to %d kHz, " \ 131 pr_debug("setting frequency for cpu %d to %d kHz, " \
144 "1/%d of max frequency\n", 132 "1/%d of max frequency\n",
145 policy->cpu, 133 policy->cpu,
146 cbe_freqs[cbe_pmode_new].frequency, 134 cbe_freqs[cbe_pmode_new].frequency,
147 cbe_freqs[cbe_pmode_new].driver_data); 135 cbe_freqs[cbe_pmode_new].driver_data);
148 136
149 rc = set_pmode(policy->cpu, cbe_pmode_new); 137 return set_pmode(policy->cpu, cbe_pmode_new);
150
151 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
152 mutex_unlock(&cbe_switch_mutex);
153
154 return rc;
155} 138}
156 139
157static struct cpufreq_driver cbe_cpufreq_driver = { 140static struct cpufreq_driver cbe_cpufreq_driver = {
diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c
index 183bc13f13e5..0a0f4369636a 100644
--- a/drivers/cpufreq/pxa2xx-cpufreq.c
+++ b/drivers/cpufreq/pxa2xx-cpufreq.c
@@ -271,7 +271,6 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx)
271{ 271{
272 struct cpufreq_frequency_table *pxa_freqs_table; 272 struct cpufreq_frequency_table *pxa_freqs_table;
273 pxa_freqs_t *pxa_freq_settings; 273 pxa_freqs_t *pxa_freq_settings;
274 struct cpufreq_freqs freqs;
275 unsigned long flags; 274 unsigned long flags;
276 unsigned int new_freq_cpu, new_freq_mem; 275 unsigned int new_freq_cpu, new_freq_mem;
277 unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; 276 unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg;
@@ -282,24 +281,17 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx)
282 281
283 new_freq_cpu = pxa_freq_settings[idx].khz; 282 new_freq_cpu = pxa_freq_settings[idx].khz;
284 new_freq_mem = pxa_freq_settings[idx].membus; 283 new_freq_mem = pxa_freq_settings[idx].membus;
285 freqs.old = policy->cur;
286 freqs.new = new_freq_cpu;
287 284
288 if (freq_debug) 285 if (freq_debug)
289 pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", 286 pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n",
290 freqs.new / 1000, (pxa_freq_settings[idx].div2) ? 287 new_freq_cpu / 1000, (pxa_freq_settings[idx].div2) ?
291 (new_freq_mem / 2000) : (new_freq_mem / 1000)); 288 (new_freq_mem / 2000) : (new_freq_mem / 1000));
292 289
293 if (vcc_core && freqs.new > freqs.old) 290 if (vcc_core && new_freq_cpu > policy->cur) {
294 ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); 291 ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
295 if (ret) 292 if (ret)
296 return ret; 293 return ret;
297 /* 294 }
298 * Tell everyone what we're about to do...
299 * you should add a notify client with any platform specific
300 * Vcc changing capability
301 */
302 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
303 295
304 /* Calculate the next MDREFR. If we're slowing down the SDRAM clock 296 /* Calculate the next MDREFR. If we're slowing down the SDRAM clock
305 * we need to preset the smaller DRI before the change. If we're 297 * we need to preset the smaller DRI before the change. If we're
@@ -350,13 +342,6 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx)
350 local_irq_restore(flags); 342 local_irq_restore(flags);
351 343
352 /* 344 /*
353 * Tell everyone what we've just done...
354 * you should add a notify client with any platform specific
355 * SDRAM refresh timer adjustments
356 */
357 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
358
359 /*
360 * Even if voltage setting fails, we don't report it, as the frequency 345 * Even if voltage setting fails, we don't report it, as the frequency
361 * change succeeded. The voltage reduction is not a critical failure, 346 * change succeeded. The voltage reduction is not a critical failure,
362 * only power savings will suffer from this. 347 * only power savings will suffer from this.
@@ -365,7 +350,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx)
365 * bug is triggered (seems a deadlock). Should anybody find out where, 350 * bug is triggered (seems a deadlock). Should anybody find out where,
366 * the "return 0" should become a "return ret". 351 * the "return 0" should become a "return ret".
367 */ 352 */
368 if (vcc_core && freqs.new < freqs.old) 353 if (vcc_core && new_freq_cpu < policy->cur)
369 ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); 354 ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
370 355
371 return 0; 356 return 0;
diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c
index 132e37d578c2..93840048dd11 100644
--- a/drivers/cpufreq/pxa3xx-cpufreq.c
+++ b/drivers/cpufreq/pxa3xx-cpufreq.c
@@ -158,7 +158,6 @@ static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
158static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, unsigned int index) 158static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, unsigned int index)
159{ 159{
160 struct pxa3xx_freq_info *next; 160 struct pxa3xx_freq_info *next;
161 struct cpufreq_freqs freqs;
162 unsigned long flags; 161 unsigned long flags;
163 162
164 if (policy->cpu != 0) 163 if (policy->cpu != 0)
@@ -166,22 +165,11 @@ static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, unsigned int index)
166 165
167 next = &pxa3xx_freqs[index]; 166 next = &pxa3xx_freqs[index];
168 167
169 freqs.old = policy->cur;
170 freqs.new = next->cpufreq_mhz * 1000;
171
172 pr_debug("CPU frequency from %d MHz to %d MHz%s\n",
173 freqs.old / 1000, freqs.new / 1000,
174 (freqs.old == freqs.new) ? " (skipped)" : "");
175
176 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
177
178 local_irq_save(flags); 168 local_irq_save(flags);
179 __update_core_freq(next); 169 __update_core_freq(next);
180 __update_bus_freq(next); 170 __update_bus_freq(next);
181 local_irq_restore(flags); 171 local_irq_restore(flags);
182 172
183 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
184
185 return 0; 173 return 0;
186} 174}
187 175
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c
index 4188accd34ab..8d904a00027b 100644
--- a/drivers/cpufreq/s3c2416-cpufreq.c
+++ b/drivers/cpufreq/s3c2416-cpufreq.c
@@ -220,7 +220,7 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
220 unsigned int index) 220 unsigned int index)
221{ 221{
222 struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; 222 struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
223 struct cpufreq_freqs freqs; 223 unsigned int new_freq;
224 int idx, ret, to_dvs = 0; 224 int idx, ret, to_dvs = 0;
225 225
226 mutex_lock(&cpufreq_lock); 226 mutex_lock(&cpufreq_lock);
@@ -237,25 +237,14 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
237 goto out; 237 goto out;
238 } 238 }
239 239
240 freqs.flags = 0;
241 freqs.old = s3c_freq->is_dvs ? FREQ_DVS
242 : clk_get_rate(s3c_freq->armclk) / 1000;
243
244 /* When leavin dvs mode, always switch the armdiv to the hclk rate 240 /* When leavin dvs mode, always switch the armdiv to the hclk rate
245 * The S3C2416 has stability issues when switching directly to 241 * The S3C2416 has stability issues when switching directly to
246 * higher frequencies. 242 * higher frequencies.
247 */ 243 */
248 freqs.new = (s3c_freq->is_dvs && !to_dvs) 244 new_freq = (s3c_freq->is_dvs && !to_dvs)
249 ? clk_get_rate(s3c_freq->hclk) / 1000 245 ? clk_get_rate(s3c_freq->hclk) / 1000
250 : s3c_freq->freq_table[index].frequency; 246 : s3c_freq->freq_table[index].frequency;
251 247
252 pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
253
254 if (!to_dvs && freqs.old == freqs.new)
255 goto out;
256
257 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
258
259 if (to_dvs) { 248 if (to_dvs) {
260 pr_debug("cpufreq: enter dvs\n"); 249 pr_debug("cpufreq: enter dvs\n");
261 ret = s3c2416_cpufreq_enter_dvs(s3c_freq, idx); 250 ret = s3c2416_cpufreq_enter_dvs(s3c_freq, idx);
@@ -263,12 +252,10 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
263 pr_debug("cpufreq: leave dvs\n"); 252 pr_debug("cpufreq: leave dvs\n");
264 ret = s3c2416_cpufreq_leave_dvs(s3c_freq, idx); 253 ret = s3c2416_cpufreq_leave_dvs(s3c_freq, idx);
265 } else { 254 } else {
266 pr_debug("cpufreq: change armdiv to %dkHz\n", freqs.new); 255 pr_debug("cpufreq: change armdiv to %dkHz\n", new_freq);
267 ret = s3c2416_cpufreq_set_armdiv(s3c_freq, freqs.new); 256 ret = s3c2416_cpufreq_set_armdiv(s3c_freq, new_freq);
268 } 257 }
269 258
270 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
271
272out: 259out:
273 mutex_unlock(&cpufreq_lock); 260 mutex_unlock(&cpufreq_lock);
274 261
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 8bdcf32a4418..67e302eeefec 100644
--- a/drivers/cpufreq/s3c64xx-cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -65,54 +65,46 @@ static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
65static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy, 65static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
66 unsigned int index) 66 unsigned int index)
67{ 67{
68 int ret;
69 struct cpufreq_freqs freqs;
70 struct s3c64xx_dvfs *dvfs; 68 struct s3c64xx_dvfs *dvfs;
69 unsigned int old_freq, new_freq;
70 int ret;
71 71
72 freqs.old = clk_get_rate(armclk) / 1000; 72 old_freq = clk_get_rate(armclk) / 1000;
73 freqs.new = s3c64xx_freq_table[index].frequency; 73 new_freq = s3c64xx_freq_table[index].frequency;
74 freqs.flags = 0;
75 dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[index].driver_data]; 74 dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[index].driver_data];
76 75
77 pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new);
78
79 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
80
81#ifdef CONFIG_REGULATOR 76#ifdef CONFIG_REGULATOR
82 if (vddarm && freqs.new > freqs.old) { 77 if (vddarm && new_freq > old_freq) {
83 ret = regulator_set_voltage(vddarm, 78 ret = regulator_set_voltage(vddarm,
84 dvfs->vddarm_min, 79 dvfs->vddarm_min,
85 dvfs->vddarm_max); 80 dvfs->vddarm_max);
86 if (ret != 0) { 81 if (ret != 0) {
87 pr_err("Failed to set VDDARM for %dkHz: %d\n", 82 pr_err("Failed to set VDDARM for %dkHz: %d\n",
88 freqs.new, ret); 83 new_freq, ret);
89 freqs.new = freqs.old; 84 return ret;
90 goto post_notify;
91 } 85 }
92 } 86 }
93#endif 87#endif
94 88
95 ret = clk_set_rate(armclk, freqs.new * 1000); 89 ret = clk_set_rate(armclk, new_freq * 1000);
96 if (ret < 0) { 90 if (ret < 0) {
97 pr_err("Failed to set rate %dkHz: %d\n", 91 pr_err("Failed to set rate %dkHz: %d\n",
98 freqs.new, ret); 92 new_freq, ret);
99 freqs.new = freqs.old; 93 return ret;
100 } 94 }
101 95
102post_notify:
103 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
104 if (ret)
105 goto err;
106
107#ifdef CONFIG_REGULATOR 96#ifdef CONFIG_REGULATOR
108 if (vddarm && freqs.new < freqs.old) { 97 if (vddarm && new_freq < old_freq) {
109 ret = regulator_set_voltage(vddarm, 98 ret = regulator_set_voltage(vddarm,
110 dvfs->vddarm_min, 99 dvfs->vddarm_min,
111 dvfs->vddarm_max); 100 dvfs->vddarm_max);
112 if (ret != 0) { 101 if (ret != 0) {
113 pr_err("Failed to set VDDARM for %dkHz: %d\n", 102 pr_err("Failed to set VDDARM for %dkHz: %d\n",
114 freqs.new, ret); 103 new_freq, ret);
115 goto err_clk; 104 if (clk_set_rate(armclk, old_freq * 1000) < 0)
105 pr_err("Failed to restore original clock rate\n");
106
107 return ret;
116 } 108 }
117 } 109 }
118#endif 110#endif
@@ -121,14 +113,6 @@ post_notify:
121 clk_get_rate(armclk) / 1000); 113 clk_get_rate(armclk) / 1000);
122 114
123 return 0; 115 return 0;
124
125err_clk:
126 if (clk_set_rate(armclk, freqs.old * 1000) < 0)
127 pr_err("Failed to restore original clock rate\n");
128err:
129 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
130
131 return ret;
132} 116}
133 117
134#ifdef CONFIG_REGULATOR 118#ifdef CONFIG_REGULATOR
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 5978b94e0340..e3973dae28a7 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -26,7 +26,6 @@
26static struct clk *cpu_clk; 26static struct clk *cpu_clk;
27static struct clk *dmc0_clk; 27static struct clk *dmc0_clk;
28static struct clk *dmc1_clk; 28static struct clk *dmc1_clk;
29static struct cpufreq_freqs freqs;
30static DEFINE_MUTEX(set_freq_lock); 29static DEFINE_MUTEX(set_freq_lock);
31 30
32/* APLL M,P,S values for 1G/800Mhz */ 31/* APLL M,P,S values for 1G/800Mhz */
@@ -179,6 +178,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
179 unsigned int priv_index; 178 unsigned int priv_index;
180 unsigned int pll_changing = 0; 179 unsigned int pll_changing = 0;
181 unsigned int bus_speed_changing = 0; 180 unsigned int bus_speed_changing = 0;
181 unsigned int old_freq, new_freq;
182 int arm_volt, int_volt; 182 int arm_volt, int_volt;
183 int ret = 0; 183 int ret = 0;
184 184
@@ -193,12 +193,12 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
193 goto exit; 193 goto exit;
194 } 194 }
195 195
196 freqs.old = s5pv210_getspeed(0); 196 old_freq = s5pv210_getspeed(0);
197 freqs.new = s5pv210_freq_table[index].frequency; 197 new_freq = s5pv210_freq_table[index].frequency;
198 198
199 /* Finding current running level index */ 199 /* Finding current running level index */
200 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, 200 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
201 freqs.old, CPUFREQ_RELATION_H, 201 old_freq, CPUFREQ_RELATION_H,
202 &priv_index)) { 202 &priv_index)) {
203 ret = -EINVAL; 203 ret = -EINVAL;
204 goto exit; 204 goto exit;
@@ -207,7 +207,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
207 arm_volt = dvs_conf[index].arm_volt; 207 arm_volt = dvs_conf[index].arm_volt;
208 int_volt = dvs_conf[index].int_volt; 208 int_volt = dvs_conf[index].int_volt;
209 209
210 if (freqs.new > freqs.old) { 210 if (new_freq > old_freq) {
211 ret = regulator_set_voltage(arm_regulator, 211 ret = regulator_set_voltage(arm_regulator,
212 arm_volt, arm_volt_max); 212 arm_volt, arm_volt_max);
213 if (ret) 213 if (ret)
@@ -219,8 +219,6 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
219 goto exit; 219 goto exit;
220 } 220 }
221 221
222 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
223
224 /* Check if there need to change PLL */ 222 /* Check if there need to change PLL */
225 if ((index == L0) || (priv_index == L0)) 223 if ((index == L0) || (priv_index == L0))
226 pll_changing = 1; 224 pll_changing = 1;
@@ -431,9 +429,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
431 } 429 }
432 } 430 }
433 431
434 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); 432 if (new_freq < old_freq) {
435
436 if (freqs.new < freqs.old) {
437 regulator_set_voltage(int_regulator, 433 regulator_set_voltage(int_regulator,
438 int_volt, int_volt_max); 434 int_volt, int_volt_max);
439 435
diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c
index b0da1fe40b1d..623da742f8e7 100644
--- a/drivers/cpufreq/sa1100-cpufreq.c
+++ b/drivers/cpufreq/sa1100-cpufreq.c
@@ -180,22 +180,17 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
180static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr) 180static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr)
181{ 181{
182 unsigned int cur = sa11x0_getspeed(0); 182 unsigned int cur = sa11x0_getspeed(0);
183 struct cpufreq_freqs freqs; 183 unsigned int new_freq;
184 184
185 freqs.old = cur; 185 new_freq = sa11x0_freq_table[ppcr].frequency;
186 freqs.new = sa11x0_freq_table[ppcr].frequency;
187 186
188 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 187 if (new_freq > cur)
189 188 sa1100_update_dram_timings(cur, new_freq);
190 if (freqs.new > cur)
191 sa1100_update_dram_timings(cur, freqs.new);
192 189
193 PPCR = ppcr; 190 PPCR = ppcr;
194 191
195 if (freqs.new < cur) 192 if (new_freq < cur)
196 sa1100_update_dram_timings(cur, freqs.new); 193 sa1100_update_dram_timings(cur, new_freq);
197
198 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
199 194
200 return 0; 195 return 0;
201} 196}
diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c
index 55b1818c3e49..2c2b2e601d13 100644
--- a/drivers/cpufreq/sa1110-cpufreq.c
+++ b/drivers/cpufreq/sa1110-cpufreq.c
@@ -232,15 +232,11 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
232static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr) 232static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr)
233{ 233{
234 struct sdram_params *sdram = &sdram_params; 234 struct sdram_params *sdram = &sdram_params;
235 struct cpufreq_freqs freqs;
236 struct sdram_info sd; 235 struct sdram_info sd;
237 unsigned long flags; 236 unsigned long flags;
238 unsigned int unused; 237 unsigned int unused;
239 238
240 freqs.old = sa11x0_getspeed(0); 239 sdram_calculate_timing(&sd, sa11x0_freq_table[ppcr].frequency, sdram);
241 freqs.new = sa11x0_freq_table[ppcr].frequency;
242
243 sdram_calculate_timing(&sd, freqs.new, sdram);
244 240
245#if 0 241#if 0
246 /* 242 /*
@@ -259,8 +255,6 @@ static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr)
259 sd.mdcas[2] = 0xaaaaaaaa; 255 sd.mdcas[2] = 0xaaaaaaaa;
260#endif 256#endif
261 257
262 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
263
264 /* 258 /*
265 * The clock could be going away for some time. Set the SDRAMs 259 * The clock could be going away for some time. Set the SDRAMs
266 * to refresh rapidly (every 64 memory clock cycles). To get 260 * to refresh rapidly (every 64 memory clock cycles). To get
@@ -305,9 +299,7 @@ static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr)
305 /* 299 /*
306 * Now, return the SDRAM refresh back to normal. 300 * Now, return the SDRAM refresh back to normal.
307 */ 301 */
308 sdram_update_refresh(freqs.new, sdram); 302 sdram_update_refresh(sa11x0_freq_table[ppcr].frequency, sdram);
309
310 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
311 303
312 return 0; 304 return 0;
313} 305}
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c
index 6c86452e1737..6adb354e359c 100644
--- a/drivers/cpufreq/sc520_freq.c
+++ b/drivers/cpufreq/sc520_freq.c
@@ -56,17 +56,8 @@ static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
56static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state) 56static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state)
57{ 57{
58 58
59 struct cpufreq_freqs freqs;
60 u8 clockspeed_reg; 59 u8 clockspeed_reg;
61 60
62 freqs.old = sc520_freq_get_cpu_frequency(0);
63 freqs.new = sc520_freq_table[state].frequency;
64
65 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
66
67 pr_debug("attempting to set frequency to %i kHz\n",
68 sc520_freq_table[state].frequency);
69
70 local_irq_disable(); 61 local_irq_disable();
71 62
72 clockspeed_reg = *cpuctl & ~0x03; 63 clockspeed_reg = *cpuctl & ~0x03;
@@ -74,8 +65,6 @@ static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state)
74 65
75 local_irq_enable(); 66 local_irq_enable();
76 67
77 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
78
79 return 0; 68 return 0;
80} 69}
81 70
diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c
index 3bf5b8f03661..62aa23e219d4 100644
--- a/drivers/cpufreq/sparc-us2e-cpufreq.c
+++ b/drivers/cpufreq/sparc-us2e-cpufreq.c
@@ -251,7 +251,6 @@ static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index)
251 unsigned long new_bits, new_freq; 251 unsigned long new_bits, new_freq;
252 unsigned long clock_tick, divisor, old_divisor, estar; 252 unsigned long clock_tick, divisor, old_divisor, estar;
253 cpumask_t cpus_allowed; 253 cpumask_t cpus_allowed;
254 struct cpufreq_freqs freqs;
255 254
256 cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); 255 cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
257 set_cpus_allowed_ptr(current, cpumask_of(cpu)); 256 set_cpus_allowed_ptr(current, cpumask_of(cpu));
@@ -265,16 +264,10 @@ static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index)
265 264
266 old_divisor = estar_to_divisor(estar); 265 old_divisor = estar_to_divisor(estar);
267 266
268 freqs.old = clock_tick / old_divisor;
269 freqs.new = new_freq;
270 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
271
272 if (old_divisor != divisor) 267 if (old_divisor != divisor)
273 us2e_transition(estar, new_bits, clock_tick * 1000, 268 us2e_transition(estar, new_bits, clock_tick * 1000,
274 old_divisor, divisor); 269 old_divisor, divisor);
275 270
276 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
277
278 set_cpus_allowed_ptr(current, &cpus_allowed); 271 set_cpus_allowed_ptr(current, &cpus_allowed);
279 272
280 return 0; 273 return 0;
diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c
index 2e54d55915df..724ffbd7105d 100644
--- a/drivers/cpufreq/sparc-us3-cpufreq.c
+++ b/drivers/cpufreq/sparc-us3-cpufreq.c
@@ -98,7 +98,6 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
98 unsigned int cpu = policy->cpu; 98 unsigned int cpu = policy->cpu;
99 unsigned long new_bits, new_freq, reg; 99 unsigned long new_bits, new_freq, reg;
100 cpumask_t cpus_allowed; 100 cpumask_t cpus_allowed;
101 struct cpufreq_freqs freqs;
102 101
103 cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); 102 cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
104 set_cpus_allowed_ptr(current, cpumask_of(cpu)); 103 set_cpus_allowed_ptr(current, cpumask_of(cpu));
@@ -124,16 +123,10 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
124 123
125 reg = read_safari_cfg(); 124 reg = read_safari_cfg();
126 125
127 freqs.old = get_current_freq(cpu, reg);
128 freqs.new = new_freq;
129 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
130
131 reg &= ~SAFARI_CFG_DIV_MASK; 126 reg &= ~SAFARI_CFG_DIV_MASK;
132 reg |= new_bits; 127 reg |= new_bits;
133 write_safari_cfg(reg); 128 write_safari_cfg(reg);
134 129
135 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
136
137 set_cpus_allowed_ptr(current, &cpus_allowed); 130 set_cpus_allowed_ptr(current, &cpus_allowed);
138 131
139 return 0; 132 return 0;
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
index 11a65be3fd76..d02ccd19c9c4 100644
--- a/drivers/cpufreq/spear-cpufreq.c
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -107,12 +107,10 @@ static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq)
107static int spear_cpufreq_target(struct cpufreq_policy *policy, 107static int spear_cpufreq_target(struct cpufreq_policy *policy,
108 unsigned int index) 108 unsigned int index)
109{ 109{
110 struct cpufreq_freqs freqs;
111 long newfreq; 110 long newfreq;
112 struct clk *srcclk; 111 struct clk *srcclk;
113 int ret, mult = 1; 112 int ret, mult = 1;
114 113
115 freqs.old = spear_cpufreq_get(0);
116 newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000; 114 newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000;
117 115
118 if (of_machine_is_compatible("st,spear1340")) { 116 if (of_machine_is_compatible("st,spear1340")) {
@@ -145,23 +143,14 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
145 return newfreq; 143 return newfreq;
146 } 144 }
147 145
148 freqs.new = newfreq / 1000;
149 freqs.new /= mult;
150
151 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
152
153 if (mult == 2) 146 if (mult == 2)
154 ret = spear1340_set_cpu_rate(srcclk, newfreq); 147 ret = spear1340_set_cpu_rate(srcclk, newfreq);
155 else 148 else
156 ret = clk_set_rate(spear_cpufreq.clk, newfreq); 149 ret = clk_set_rate(spear_cpufreq.clk, newfreq);
157 150
158 /* Get current rate after clk_set_rate, in case of failure */ 151 if (ret)
159 if (ret) {
160 pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret); 152 pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret);
161 freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000;
162 }
163 153
164 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
165 return ret; 154 return ret;
166} 155}
167 156
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
index c51ec8c0e3a8..4e1daca5ce3b 100644
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -423,9 +423,8 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
423static int centrino_target(struct cpufreq_policy *policy, unsigned int index) 423static int centrino_target(struct cpufreq_policy *policy, unsigned int index)
424{ 424{
425 unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu; 425 unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu;
426 struct cpufreq_freqs freqs;
427 int retval = 0; 426 int retval = 0;
428 unsigned int j, first_cpu, tmp; 427 unsigned int j, first_cpu;
429 struct cpufreq_frequency_table *op_points; 428 struct cpufreq_frequency_table *op_points;
430 cpumask_var_t covered_cpus; 429 cpumask_var_t covered_cpus;
431 430
@@ -473,16 +472,6 @@ static int centrino_target(struct cpufreq_policy *policy, unsigned int index)
473 goto out; 472 goto out;
474 } 473 }
475 474
476 freqs.old = extract_clock(oldmsr, cpu, 0);
477 freqs.new = extract_clock(msr, cpu, 0);
478
479 pr_debug("target=%dkHz old=%d new=%d msr=%04x\n",
480 op_points->frequency, freqs.old, freqs.new,
481 msr);
482
483 cpufreq_notify_transition(policy, &freqs,
484 CPUFREQ_PRECHANGE);
485
486 first_cpu = 0; 475 first_cpu = 0;
487 /* all but 16 LSB are reserved, treat them with care */ 476 /* all but 16 LSB are reserved, treat them with care */
488 oldmsr &= ~0xffff; 477 oldmsr &= ~0xffff;
@@ -497,8 +486,6 @@ static int centrino_target(struct cpufreq_policy *policy, unsigned int index)
497 cpumask_set_cpu(j, covered_cpus); 486 cpumask_set_cpu(j, covered_cpus);
498 } 487 }
499 488
500 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
501
502 if (unlikely(retval)) { 489 if (unlikely(retval)) {
503 /* 490 /*
504 * We have failed halfway through the frequency change. 491 * We have failed halfway through the frequency change.
@@ -509,12 +496,6 @@ static int centrino_target(struct cpufreq_policy *policy, unsigned int index)
509 496
510 for_each_cpu(j, covered_cpus) 497 for_each_cpu(j, covered_cpus)
511 wrmsr_on_cpu(j, MSR_IA32_PERF_CTL, oldmsr, h); 498 wrmsr_on_cpu(j, MSR_IA32_PERF_CTL, oldmsr, h);
512
513 tmp = freqs.new;
514 freqs.new = freqs.old;
515 freqs.old = tmp;
516 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
517 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
518 } 499 }
519 retval = 0; 500 retval = 0;
520 501
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
index 707721ebb853..7639b2be2a90 100644
--- a/drivers/cpufreq/speedstep-ich.c
+++ b/drivers/cpufreq/speedstep-ich.c
@@ -258,21 +258,12 @@ static unsigned int speedstep_get(unsigned int cpu)
258static int speedstep_target(struct cpufreq_policy *policy, unsigned int index) 258static int speedstep_target(struct cpufreq_policy *policy, unsigned int index)
259{ 259{
260 unsigned int policy_cpu; 260 unsigned int policy_cpu;
261 struct cpufreq_freqs freqs;
262 261
263 policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask); 262 policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
264 freqs.old = speedstep_get(policy_cpu);
265 freqs.new = speedstep_freqs[index].frequency;
266
267 pr_debug("transiting from %u to %u kHz\n", freqs.old, freqs.new);
268
269 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
270 263
271 smp_call_function_single(policy_cpu, _speedstep_set_state, &index, 264 smp_call_function_single(policy_cpu, _speedstep_set_state, &index,
272 true); 265 true);
273 266
274 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
275
276 return 0; 267 return 0;
277} 268}
278 269
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index 19446e479ccc..0f5326d6f79f 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -241,14 +241,7 @@ static void speedstep_set_state(unsigned int state)
241 */ 241 */
242static int speedstep_target(struct cpufreq_policy *policy, unsigned int index) 242static int speedstep_target(struct cpufreq_policy *policy, unsigned int index)
243{ 243{
244 struct cpufreq_freqs freqs;
245
246 freqs.old = speedstep_freqs[speedstep_get_state()].frequency;
247 freqs.new = speedstep_freqs[index].frequency;
248
249 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
250 speedstep_set_state(index); 244 speedstep_set_state(index);
251 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
252 245
253 return 0; 246 return 0;
254} 247}
diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c
index bd7d89c013a5..f42df7ec03c5 100644
--- a/drivers/cpufreq/tegra-cpufreq.c
+++ b/drivers/cpufreq/tegra-cpufreq.c
@@ -102,12 +102,8 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
102 unsigned long rate) 102 unsigned long rate)
103{ 103{
104 int ret = 0; 104 int ret = 0;
105 struct cpufreq_freqs freqs;
106 105
107 freqs.old = tegra_getspeed(0); 106 if (tegra_getspeed(0) == rate)
108 freqs.new = rate;
109
110 if (freqs.old == freqs.new)
111 return ret; 107 return ret;
112 108
113 /* 109 /*
@@ -121,21 +117,10 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
121 else 117 else
122 clk_set_rate(emc_clk, 100000000); /* emc 50Mhz */ 118 clk_set_rate(emc_clk, 100000000); /* emc 50Mhz */
123 119
124 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 120 ret = tegra_cpu_clk_set_rate(rate * 1000);
125 121 if (ret)
126#ifdef CONFIG_CPU_FREQ_DEBUG 122 pr_err("cpu-tegra: Failed to set cpu frequency to %lu kHz\n",
127 printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n", 123 rate);
128 freqs.old, freqs.new);
129#endif
130
131 ret = tegra_cpu_clk_set_rate(freqs.new * 1000);
132 if (ret) {
133 pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
134 freqs.new);
135 freqs.new = freqs.old;
136 }
137
138 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
139 124
140 return ret; 125 return ret;
141} 126}
diff --git a/drivers/cpufreq/vexpress-spc-cpufreq.c b/drivers/cpufreq/vexpress-spc-cpufreq.c
new file mode 100644
index 000000000000..7f7c9c01b44e
--- /dev/null
+++ b/drivers/cpufreq/vexpress-spc-cpufreq.c
@@ -0,0 +1,70 @@
1/*
2 * Versatile Express SPC CPUFreq Interface driver
3 *
4 * It provides necessary ops to arm_big_little cpufreq driver.
5 *
6 * Copyright (C) 2013 ARM Ltd.
7 * Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
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 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
14 * kind, whether express or implied; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/cpufreq.h>
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/pm_opp.h>
25#include <linux/types.h>
26
27#include "arm_big_little.h"
28
29static int ve_spc_init_opp_table(struct device *cpu_dev)
30{
31 /*
32 * platform specific SPC code must initialise the opp table
33 * so just check if the OPP count is non-zero
34 */
35 return dev_pm_opp_get_opp_count(cpu_dev) <= 0;
36}
37
38static int ve_spc_get_transition_latency(struct device *cpu_dev)
39{
40 return 1000000; /* 1 ms */
41}
42
43static struct cpufreq_arm_bL_ops ve_spc_cpufreq_ops = {
44 .name = "vexpress-spc",
45 .get_transition_latency = ve_spc_get_transition_latency,
46 .init_opp_table = ve_spc_init_opp_table,
47};
48
49static int ve_spc_cpufreq_probe(struct platform_device *pdev)
50{
51 return bL_cpufreq_register(&ve_spc_cpufreq_ops);
52}
53
54static int ve_spc_cpufreq_remove(struct platform_device *pdev)
55{
56 bL_cpufreq_unregister(&ve_spc_cpufreq_ops);
57 return 0;
58}
59
60static struct platform_driver ve_spc_cpufreq_platdrv = {
61 .driver = {
62 .name = "vexpress-spc-cpufreq",
63 .owner = THIS_MODULE,
64 },
65 .probe = ve_spc_cpufreq_probe,
66 .remove = ve_spc_cpufreq_remove,
67};
68module_platform_driver(ve_spc_cpufreq_platdrv);
69
70MODULE_LICENSE("GPL");
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 93a8c34d6c7f..5bd6ab9b0c27 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -237,6 +237,13 @@ struct cpufreq_driver {
237 */ 237 */
238#define CPUFREQ_HAVE_GOVERNOR_PER_POLICY (1 << 3) 238#define CPUFREQ_HAVE_GOVERNOR_PER_POLICY (1 << 3)
239 239
240/*
241 * Driver will do POSTCHANGE notifications from outside of their ->target()
242 * routine and so must set cpufreq_driver->flags with this flag, so that core
243 * can handle them specially.
244 */
245#define CPUFREQ_ASYNC_NOTIFICATION (1 << 4)
246
240int cpufreq_register_driver(struct cpufreq_driver *driver_data); 247int cpufreq_register_driver(struct cpufreq_driver *driver_data);
241int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); 248int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
242 249