aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/cpuidle/driver.txt6
-rw-r--r--MAINTAINERS9
-rw-r--r--arch/arm/configs/kirkwood_defconfig1
-rw-r--r--arch/arm/mach-at91/cpuidle.c18
-rw-r--r--arch/arm/mach-davinci/cpuidle.c29
-rw-r--r--arch/arm/mach-exynos/cpuidle.c1
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/cpuidle-imx5.c37
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c26
-rw-r--r--arch/arm/mach-imx/cpuidle.c80
-rw-r--r--arch/arm/mach-imx/cpuidle.h10
-rw-r--r--arch/arm/mach-imx/pm-imx5.c30
-rw-r--r--arch/arm/mach-omap2/common.h5
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c52
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c84
-rw-r--r--arch/arm/mach-omap2/omap-mpuss-lowpower.c14
-rw-r--r--arch/arm/mach-s3c64xx/cpuidle.c15
-rw-r--r--arch/arm/mach-shmobile/cpuidle.c23
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h3
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c6
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra114.c28
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra20.c72
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra30.c29
-rw-r--r--arch/arm/mach-ux500/cpuidle.c58
-rw-r--r--arch/powerpc/platforms/pseries/processor_idle.c34
-rw-r--r--arch/sh/include/asm/suspend.h4
-rw-r--r--arch/sh/kernel/cpu/shmobile/cpuidle.c101
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm.c3
-rw-r--r--arch/x86/kernel/apm_32.c1
-rw-r--r--drivers/acpi/processor_idle.c1
-rw-r--r--drivers/cpuidle/Kconfig6
-rw-r--r--drivers/cpuidle/Makefile2
-rw-r--r--drivers/cpuidle/cpuidle-calxeda.c57
-rw-r--r--drivers/cpuidle/cpuidle-kirkwood.c29
-rw-r--r--drivers/cpuidle/cpuidle.c153
-rw-r--r--drivers/cpuidle/driver.c31
-rw-r--r--drivers/idle/intel_idle.c4
-rw-r--r--include/linux/clockchips.h32
-rw-r--r--include/linux/cpuidle.h23
39 files changed, 362 insertions, 757 deletions
diff --git a/Documentation/cpuidle/driver.txt b/Documentation/cpuidle/driver.txt
index 7a9e09ece931..1b0d81d92583 100644
--- a/Documentation/cpuidle/driver.txt
+++ b/Documentation/cpuidle/driver.txt
@@ -15,11 +15,17 @@ has mechanisms in place to support actual entry-exit into CPU idle states.
15cpuidle driver initializes the cpuidle_device structure for each CPU device 15cpuidle driver initializes the cpuidle_device structure for each CPU device
16and registers with cpuidle using cpuidle_register_device. 16and registers with cpuidle using cpuidle_register_device.
17 17
18If all the idle states are the same, the wrapper function cpuidle_register
19could be used instead.
20
18It can also support the dynamic changes (like battery <-> AC), by using 21It can also support the dynamic changes (like battery <-> AC), by using
19cpuidle_pause_and_lock, cpuidle_disable_device and cpuidle_enable_device, 22cpuidle_pause_and_lock, cpuidle_disable_device and cpuidle_enable_device,
20cpuidle_resume_and_unlock. 23cpuidle_resume_and_unlock.
21 24
22Interfaces: 25Interfaces:
26extern int cpuidle_register(struct cpuidle_driver *drv,
27 const struct cpumask *const coupled_cpus);
28extern int cpuidle_unregister(struct cpuidle_driver *drv);
23extern int cpuidle_register_driver(struct cpuidle_driver *drv); 29extern int cpuidle_register_driver(struct cpuidle_driver *drv);
24extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); 30extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
25extern int cpuidle_register_device(struct cpuidle_device *dev); 31extern int cpuidle_register_device(struct cpuidle_device *dev);
diff --git a/MAINTAINERS b/MAINTAINERS
index 8bdd7a7ef2f4..1bef08d407f3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2206,6 +2206,15 @@ S: Maintained
2206F: drivers/cpufreq/ 2206F: drivers/cpufreq/
2207F: include/linux/cpufreq.h 2207F: include/linux/cpufreq.h
2208 2208
2209CPUIDLE DRIVERS
2210M: Rafael J. Wysocki <rjw@sisk.pl>
2211M: Daniel Lezcano <daniel.lezcano@linaro.org>
2212L: linux-pm@vger.kernel.org
2213S: Maintained
2214T: git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
2215F: drivers/cpuidle/*
2216F: include/linux/cpuidle.h
2217
2209CPUID/MSR DRIVER 2218CPUID/MSR DRIVER
2210M: "H. Peter Anvin" <hpa@zytor.com> 2219M: "H. Peter Anvin" <hpa@zytor.com>
2211S: Maintained 2220S: Maintained
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 13482ea58b09..93f3794ba5cb 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -56,7 +56,6 @@ CONFIG_AEABI=y
56CONFIG_ZBOOT_ROM_TEXT=0x0 56CONFIG_ZBOOT_ROM_TEXT=0x0
57CONFIG_ZBOOT_ROM_BSS=0x0 57CONFIG_ZBOOT_ROM_BSS=0x0
58CONFIG_CPU_IDLE=y 58CONFIG_CPU_IDLE=y
59CONFIG_CPU_IDLE_KIRKWOOD=y
60CONFIG_NET=y 59CONFIG_NET=y
61CONFIG_PACKET=y 60CONFIG_PACKET=y
62CONFIG_UNIX=y 61CONFIG_UNIX=y
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
index 0c6381516a5a..48f1228c611c 100644
--- a/arch/arm/mach-at91/cpuidle.c
+++ b/arch/arm/mach-at91/cpuidle.c
@@ -27,8 +27,6 @@
27 27
28#define AT91_MAX_STATES 2 28#define AT91_MAX_STATES 2
29 29
30static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device);
31
32/* Actual code that puts the SoC in different idle states */ 30/* Actual code that puts the SoC in different idle states */
33static int at91_enter_idle(struct cpuidle_device *dev, 31static int at91_enter_idle(struct cpuidle_device *dev,
34 struct cpuidle_driver *drv, 32 struct cpuidle_driver *drv,
@@ -47,7 +45,6 @@ static int at91_enter_idle(struct cpuidle_device *dev,
47static struct cpuidle_driver at91_idle_driver = { 45static struct cpuidle_driver at91_idle_driver = {
48 .name = "at91_idle", 46 .name = "at91_idle",
49 .owner = THIS_MODULE, 47 .owner = THIS_MODULE,
50 .en_core_tk_irqen = 1,
51 .states[0] = ARM_CPUIDLE_WFI_STATE, 48 .states[0] = ARM_CPUIDLE_WFI_STATE,
52 .states[1] = { 49 .states[1] = {
53 .enter = at91_enter_idle, 50 .enter = at91_enter_idle,
@@ -61,20 +58,9 @@ static struct cpuidle_driver at91_idle_driver = {
61}; 58};
62 59
63/* Initialize CPU idle by registering the idle states */ 60/* Initialize CPU idle by registering the idle states */
64static int at91_init_cpuidle(void) 61static int __init at91_init_cpuidle(void)
65{ 62{
66 struct cpuidle_device *device; 63 return cpuidle_register(&at91_idle_driver, NULL);
67
68 device = &per_cpu(at91_cpuidle_device, smp_processor_id());
69 device->state_count = AT91_MAX_STATES;
70
71 cpuidle_register_driver(&at91_idle_driver);
72
73 if (cpuidle_register_device(device)) {
74 printk(KERN_ERR "at91_init_cpuidle: Failed registering\n");
75 return -EIO;
76 }
77 return 0;
78} 64}
79 65
80device_initcall(at91_init_cpuidle); 66device_initcall(at91_init_cpuidle);
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index 5ac9e9384b15..36aef3a7dedb 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -25,7 +25,6 @@
25 25
26#define DAVINCI_CPUIDLE_MAX_STATES 2 26#define DAVINCI_CPUIDLE_MAX_STATES 2
27 27
28static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device);
29static void __iomem *ddr2_reg_base; 28static void __iomem *ddr2_reg_base;
30static bool ddr2_pdown; 29static bool ddr2_pdown;
31 30
@@ -50,14 +49,10 @@ static void davinci_save_ddr_power(int enter, bool pdown)
50 49
51/* Actual code that puts the SoC in different idle states */ 50/* Actual code that puts the SoC in different idle states */
52static int davinci_enter_idle(struct cpuidle_device *dev, 51static int davinci_enter_idle(struct cpuidle_device *dev,
53 struct cpuidle_driver *drv, 52 struct cpuidle_driver *drv, int index)
54 int index)
55{ 53{
56 davinci_save_ddr_power(1, ddr2_pdown); 54 davinci_save_ddr_power(1, ddr2_pdown);
57 55 cpu_do_idle();
58 index = cpuidle_wrap_enter(dev, drv, index,
59 arm_cpuidle_simple_enter);
60
61 davinci_save_ddr_power(0, ddr2_pdown); 56 davinci_save_ddr_power(0, ddr2_pdown);
62 57
63 return index; 58 return index;
@@ -66,7 +61,6 @@ static int davinci_enter_idle(struct cpuidle_device *dev,
66static struct cpuidle_driver davinci_idle_driver = { 61static struct cpuidle_driver davinci_idle_driver = {
67 .name = "cpuidle-davinci", 62 .name = "cpuidle-davinci",
68 .owner = THIS_MODULE, 63 .owner = THIS_MODULE,
69 .en_core_tk_irqen = 1,
70 .states[0] = ARM_CPUIDLE_WFI_STATE, 64 .states[0] = ARM_CPUIDLE_WFI_STATE,
71 .states[1] = { 65 .states[1] = {
72 .enter = davinci_enter_idle, 66 .enter = davinci_enter_idle,
@@ -81,12 +75,8 @@ static struct cpuidle_driver davinci_idle_driver = {
81 75
82static int __init davinci_cpuidle_probe(struct platform_device *pdev) 76static int __init davinci_cpuidle_probe(struct platform_device *pdev)
83{ 77{
84 int ret;
85 struct cpuidle_device *device;
86 struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; 78 struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
87 79
88 device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
89
90 if (!pdata) { 80 if (!pdata) {
91 dev_err(&pdev->dev, "cannot get platform data\n"); 81 dev_err(&pdev->dev, "cannot get platform data\n");
92 return -ENOENT; 82 return -ENOENT;
@@ -96,20 +86,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
96 86
97 ddr2_pdown = pdata->ddr2_pdown; 87 ddr2_pdown = pdata->ddr2_pdown;
98 88
99 ret = cpuidle_register_driver(&davinci_idle_driver); 89 return cpuidle_register(&davinci_idle_driver, NULL);
100 if (ret) {
101 dev_err(&pdev->dev, "failed to register driver\n");
102 return ret;
103 }
104
105 ret = cpuidle_register_device(device);
106 if (ret) {
107 dev_err(&pdev->dev, "failed to register device\n");
108 cpuidle_unregister_driver(&davinci_idle_driver);
109 return ret;
110 }
111
112 return 0;
113} 90}
114 91
115static struct platform_driver davinci_cpuidle_driver = { 92static struct platform_driver davinci_cpuidle_driver = {
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index fcfe0251aa3e..498a7a23e260 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -58,7 +58,6 @@ static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
58static struct cpuidle_driver exynos4_idle_driver = { 58static struct cpuidle_driver exynos4_idle_driver = {
59 .name = "exynos4_idle", 59 .name = "exynos4_idle",
60 .owner = THIS_MODULE, 60 .owner = THIS_MODULE,
61 .en_core_tk_irqen = 1,
62}; 61};
63 62
64/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ 63/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index c4ce0906d76a..cb70961b6239 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -30,7 +30,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
30obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o 30obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
31 31
32ifeq ($(CONFIG_CPU_IDLE),y) 32ifeq ($(CONFIG_CPU_IDLE),y)
33obj-y += cpuidle.o 33obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
34obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o 34obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
35endif 35endif
36 36
diff --git a/arch/arm/mach-imx/cpuidle-imx5.c b/arch/arm/mach-imx/cpuidle-imx5.c
new file mode 100644
index 000000000000..5a47e3c6172f
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx5.c
@@ -0,0 +1,37 @@
1/*
2 * Copyright (C) 2012 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/cpuidle.h>
10#include <linux/module.h>
11#include <asm/system_misc.h>
12
13static int imx5_cpuidle_enter(struct cpuidle_device *dev,
14 struct cpuidle_driver *drv, int index)
15{
16 arm_pm_idle();
17 return index;
18}
19
20static struct cpuidle_driver imx5_cpuidle_driver = {
21 .name = "imx5_cpuidle",
22 .owner = THIS_MODULE,
23 .states[0] = {
24 .enter = imx5_cpuidle_enter,
25 .exit_latency = 2,
26 .target_residency = 1,
27 .flags = CPUIDLE_FLAG_TIME_VALID,
28 .name = "IMX5 SRPG",
29 .desc = "CPU state retained,powered off",
30 },
31 .state_count = 1,
32};
33
34int __init imx5_cpuidle_init(void)
35{
36 return cpuidle_register(&imx5_cpuidle_driver, NULL);
37}
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index d533e2695f0e..23ddfb693b2d 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -6,7 +6,6 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include <linux/clockchips.h>
10#include <linux/cpuidle.h> 9#include <linux/cpuidle.h>
11#include <linux/module.h> 10#include <linux/module.h>
12#include <asm/cpuidle.h> 11#include <asm/cpuidle.h>
@@ -21,10 +20,6 @@ static DEFINE_SPINLOCK(master_lock);
21static int imx6q_enter_wait(struct cpuidle_device *dev, 20static int imx6q_enter_wait(struct cpuidle_device *dev,
22 struct cpuidle_driver *drv, int index) 21 struct cpuidle_driver *drv, int index)
23{ 22{
24 int cpu = dev->cpu;
25
26 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
27
28 if (atomic_inc_return(&master) == num_online_cpus()) { 23 if (atomic_inc_return(&master) == num_online_cpus()) {
29 /* 24 /*
30 * With this lock, we prevent other cpu to exit and enter 25 * With this lock, we prevent other cpu to exit and enter
@@ -43,26 +38,13 @@ idle:
43 cpu_do_idle(); 38 cpu_do_idle();
44done: 39done:
45 atomic_dec(&master); 40 atomic_dec(&master);
46 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
47 41
48 return index; 42 return index;
49} 43}
50 44
51/*
52 * For each cpu, setup the broadcast timer because local timer
53 * stops for the states other than WFI.
54 */
55static void imx6q_setup_broadcast_timer(void *arg)
56{
57 int cpu = smp_processor_id();
58
59 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
60}
61
62static struct cpuidle_driver imx6q_cpuidle_driver = { 45static struct cpuidle_driver imx6q_cpuidle_driver = {
63 .name = "imx6q_cpuidle", 46 .name = "imx6q_cpuidle",
64 .owner = THIS_MODULE, 47 .owner = THIS_MODULE,
65 .en_core_tk_irqen = 1,
66 .states = { 48 .states = {
67 /* WFI */ 49 /* WFI */
68 ARM_CPUIDLE_WFI_STATE, 50 ARM_CPUIDLE_WFI_STATE,
@@ -70,7 +52,8 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {
70 { 52 {
71 .exit_latency = 50, 53 .exit_latency = 50,
72 .target_residency = 75, 54 .target_residency = 75,
73 .flags = CPUIDLE_FLAG_TIME_VALID, 55 .flags = CPUIDLE_FLAG_TIME_VALID |
56 CPUIDLE_FLAG_TIMER_STOP,
74 .enter = imx6q_enter_wait, 57 .enter = imx6q_enter_wait,
75 .name = "WAIT", 58 .name = "WAIT",
76 .desc = "Clock off", 59 .desc = "Clock off",
@@ -88,8 +71,5 @@ int __init imx6q_cpuidle_init(void)
88 /* Set chicken bit to get a reliable WAIT mode support */ 71 /* Set chicken bit to get a reliable WAIT mode support */
89 imx6q_set_chicken_bit(); 72 imx6q_set_chicken_bit();
90 73
91 /* Configure the broadcast timer on each cpu */ 74 return cpuidle_register(&imx6q_cpuidle_driver, NULL);
92 on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1);
93
94 return imx_cpuidle_init(&imx6q_cpuidle_driver);
95} 75}
diff --git a/arch/arm/mach-imx/cpuidle.c b/arch/arm/mach-imx/cpuidle.c
deleted file mode 100644
index d4cb511a44a8..000000000000
--- a/arch/arm/mach-imx/cpuidle.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * Copyright 2012 Freescale Semiconductor, Inc.
3 * Copyright 2012 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/cpuidle.h>
14#include <linux/err.h>
15#include <linux/hrtimer.h>
16#include <linux/io.h>
17#include <linux/kernel.h>
18#include <linux/slab.h>
19
20static struct cpuidle_device __percpu * imx_cpuidle_devices;
21
22static void __init imx_cpuidle_devices_uninit(void)
23{
24 int cpu_id;
25 struct cpuidle_device *dev;
26
27 for_each_possible_cpu(cpu_id) {
28 dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
29 cpuidle_unregister_device(dev);
30 }
31
32 free_percpu(imx_cpuidle_devices);
33}
34
35int __init imx_cpuidle_init(struct cpuidle_driver *drv)
36{
37 struct cpuidle_device *dev;
38 int cpu_id, ret;
39
40 if (drv->state_count > CPUIDLE_STATE_MAX) {
41 pr_err("%s: state_count exceeds maximum\n", __func__);
42 return -EINVAL;
43 }
44
45 ret = cpuidle_register_driver(drv);
46 if (ret) {
47 pr_err("%s: Failed to register cpuidle driver with error: %d\n",
48 __func__, ret);
49 return ret;
50 }
51
52 imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
53 if (imx_cpuidle_devices == NULL) {
54 ret = -ENOMEM;
55 goto unregister_drv;
56 }
57
58 /* initialize state data for each cpuidle_device */
59 for_each_possible_cpu(cpu_id) {
60 dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
61 dev->cpu = cpu_id;
62 dev->state_count = drv->state_count;
63
64 ret = cpuidle_register_device(dev);
65 if (ret) {
66 pr_err("%s: Failed to register cpu %u, error: %d\n",
67 __func__, cpu_id, ret);
68 goto uninit;
69 }
70 }
71
72 return 0;
73
74uninit:
75 imx_cpuidle_devices_uninit();
76
77unregister_drv:
78 cpuidle_unregister_driver(drv);
79 return ret;
80}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index e092d1359d94..786f98ecc145 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -10,18 +10,16 @@
10 * http://www.gnu.org/copyleft/gpl.html 10 * http://www.gnu.org/copyleft/gpl.html
11 */ 11 */
12 12
13#include <linux/cpuidle.h>
14
15#ifdef CONFIG_CPU_IDLE 13#ifdef CONFIG_CPU_IDLE
16extern int imx_cpuidle_init(struct cpuidle_driver *drv); 14extern int imx5_cpuidle_init(void);
17extern int imx6q_cpuidle_init(void); 15extern int imx6q_cpuidle_init(void);
18#else 16#else
19static inline int imx_cpuidle_init(struct cpuidle_driver *drv) 17static inline int imx5_cpuidle_init(void)
20{ 18{
21 return -ENODEV; 19 return 0;
22} 20}
23static inline int imx6q_cpuidle_init(void) 21static inline int imx6q_cpuidle_init(void)
24{ 22{
25 return -ENODEV; 23 return 0;
26} 24}
27#endif 25#endif
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index f67fd7ee8127..82e79c658eb2 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -149,33 +149,6 @@ static void imx5_pm_idle(void)
149 imx5_cpu_do_idle(); 149 imx5_cpu_do_idle();
150} 150}
151 151
152static int imx5_cpuidle_enter(struct cpuidle_device *dev,
153 struct cpuidle_driver *drv, int idx)
154{
155 int ret;
156
157 ret = imx5_cpu_do_idle();
158 if (ret < 0)
159 return ret;
160
161 return idx;
162}
163
164static struct cpuidle_driver imx5_cpuidle_driver = {
165 .name = "imx5_cpuidle",
166 .owner = THIS_MODULE,
167 .en_core_tk_irqen = 1,
168 .states[0] = {
169 .enter = imx5_cpuidle_enter,
170 .exit_latency = 2,
171 .target_residency = 1,
172 .flags = CPUIDLE_FLAG_TIME_VALID,
173 .name = "IMX5 SRPG",
174 .desc = "CPU state retained,powered off",
175 },
176 .state_count = 1,
177};
178
179static int __init imx5_pm_common_init(void) 152static int __init imx5_pm_common_init(void)
180{ 153{
181 int ret; 154 int ret;
@@ -193,8 +166,7 @@ static int __init imx5_pm_common_init(void)
193 /* Set the registers to the default cpu idle state. */ 166 /* Set the registers to the default cpu idle state. */
194 mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); 167 mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
195 168
196 imx_cpuidle_init(&imx5_cpuidle_driver); 169 return imx5_cpuidle_init();
197 return 0;
198} 170}
199 171
200void __init imx51_pm_init(void) 172void __init imx51_pm_init(void)
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index d6ba13e1c540..14522d077c88 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -249,7 +249,6 @@ extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
249extern int omap4_finish_suspend(unsigned long cpu_state); 249extern int omap4_finish_suspend(unsigned long cpu_state);
250extern void omap4_cpu_resume(void); 250extern void omap4_cpu_resume(void);
251extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); 251extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
252extern u32 omap4_mpuss_read_prev_context_state(void);
253#else 252#else
254static inline int omap4_enter_lowpower(unsigned int cpu, 253static inline int omap4_enter_lowpower(unsigned int cpu,
255 unsigned int power_state) 254 unsigned int power_state)
@@ -277,10 +276,6 @@ static inline int omap4_finish_suspend(unsigned long cpu_state)
277static inline void omap4_cpu_resume(void) 276static inline void omap4_cpu_resume(void)
278{} 277{}
279 278
280static inline u32 omap4_mpuss_read_prev_context_state(void)
281{
282 return 0;
283}
284#endif 279#endif
285 280
286struct omap_sdrc_params; 281struct omap_sdrc_params;
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 80392fca86c6..cca045c95fbf 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -26,6 +26,7 @@
26#include <linux/cpuidle.h> 26#include <linux/cpuidle.h>
27#include <linux/export.h> 27#include <linux/export.h>
28#include <linux/cpu_pm.h> 28#include <linux/cpu_pm.h>
29#include <asm/cpuidle.h>
29 30
30#include "powerdomain.h" 31#include "powerdomain.h"
31#include "clockdomain.h" 32#include "clockdomain.h"
@@ -99,11 +100,15 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
99 }, 100 },
100}; 101};
101 102
102/* Private functions */ 103/**
103 104 * omap3_enter_idle - Programs OMAP3 to enter the specified state
104static int __omap3_enter_idle(struct cpuidle_device *dev, 105 * @dev: cpuidle device
105 struct cpuidle_driver *drv, 106 * @drv: cpuidle driver
106 int index) 107 * @index: the index of state to be entered
108 */
109static int omap3_enter_idle(struct cpuidle_device *dev,
110 struct cpuidle_driver *drv,
111 int index)
107{ 112{
108 struct omap3_idle_statedata *cx = &omap3_idle_data[index]; 113 struct omap3_idle_statedata *cx = &omap3_idle_data[index];
109 114
@@ -149,22 +154,6 @@ return_sleep_time:
149} 154}
150 155
151/** 156/**
152 * omap3_enter_idle - Programs OMAP3 to enter the specified state
153 * @dev: cpuidle device
154 * @drv: cpuidle driver
155 * @index: the index of state to be entered
156 *
157 * Called from the CPUidle framework to program the device to the
158 * specified target state selected by the governor.
159 */
160static inline int omap3_enter_idle(struct cpuidle_device *dev,
161 struct cpuidle_driver *drv,
162 int index)
163{
164 return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle);
165}
166
167/**
168 * next_valid_state - Find next valid C-state 157 * next_valid_state - Find next valid C-state
169 * @dev: cpuidle device 158 * @dev: cpuidle device
170 * @drv: cpuidle driver 159 * @drv: cpuidle driver
@@ -271,11 +260,9 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
271 return ret; 260 return ret;
272} 261}
273 262
274static DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
275
276static struct cpuidle_driver omap3_idle_driver = { 263static struct cpuidle_driver omap3_idle_driver = {
277 .name = "omap3_idle", 264 .name = "omap3_idle",
278 .owner = THIS_MODULE, 265 .owner = THIS_MODULE,
279 .states = { 266 .states = {
280 { 267 {
281 .enter = omap3_enter_idle_bm, 268 .enter = omap3_enter_idle_bm,
@@ -348,8 +335,6 @@ static struct cpuidle_driver omap3_idle_driver = {
348 */ 335 */
349int __init omap3_idle_init(void) 336int __init omap3_idle_init(void)
350{ 337{
351 struct cpuidle_device *dev;
352
353 mpu_pd = pwrdm_lookup("mpu_pwrdm"); 338 mpu_pd = pwrdm_lookup("mpu_pwrdm");
354 core_pd = pwrdm_lookup("core_pwrdm"); 339 core_pd = pwrdm_lookup("core_pwrdm");
355 per_pd = pwrdm_lookup("per_pwrdm"); 340 per_pd = pwrdm_lookup("per_pwrdm");
@@ -358,16 +343,5 @@ int __init omap3_idle_init(void)
358 if (!mpu_pd || !core_pd || !per_pd || !cam_pd) 343 if (!mpu_pd || !core_pd || !per_pd || !cam_pd)
359 return -ENODEV; 344 return -ENODEV;
360 345
361 cpuidle_register_driver(&omap3_idle_driver); 346 return cpuidle_register(&omap3_idle_driver, NULL);
362
363 dev = &per_cpu(omap3_idle_dev, smp_processor_id());
364 dev->cpu = 0;
365
366 if (cpuidle_register_device(dev)) {
367 printk(KERN_ERR "%s: CPUidle register device failed\n",
368 __func__);
369 return -EIO;
370 }
371
372 return 0;
373} 347}
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index d639aef0deda..5a286b56205e 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * OMAP4 CPU idle Routines 2 * OMAP4+ CPU idle Routines
3 * 3 *
4 * Copyright (C) 2011 Texas Instruments, Inc. 4 * Copyright (C) 2011-2013 Texas Instruments, Inc.
5 * Santosh Shilimkar <santosh.shilimkar@ti.com> 5 * Santosh Shilimkar <santosh.shilimkar@ti.com>
6 * Rajendra Nayak <rnayak@ti.com> 6 * Rajendra Nayak <rnayak@ti.com>
7 * 7 *
@@ -14,8 +14,8 @@
14#include <linux/cpuidle.h> 14#include <linux/cpuidle.h>
15#include <linux/cpu_pm.h> 15#include <linux/cpu_pm.h>
16#include <linux/export.h> 16#include <linux/export.h>
17#include <linux/clockchips.h>
18 17
18#include <asm/cpuidle.h>
19#include <asm/proc-fns.h> 19#include <asm/proc-fns.h>
20 20
21#include "common.h" 21#include "common.h"
@@ -24,13 +24,13 @@
24#include "clockdomain.h" 24#include "clockdomain.h"
25 25
26/* Machine specific information */ 26/* Machine specific information */
27struct omap4_idle_statedata { 27struct idle_statedata {
28 u32 cpu_state; 28 u32 cpu_state;
29 u32 mpu_logic_state; 29 u32 mpu_logic_state;
30 u32 mpu_state; 30 u32 mpu_state;
31}; 31};
32 32
33static struct omap4_idle_statedata omap4_idle_data[] = { 33static struct idle_statedata omap4_idle_data[] = {
34 { 34 {
35 .cpu_state = PWRDM_POWER_ON, 35 .cpu_state = PWRDM_POWER_ON,
36 .mpu_state = PWRDM_POWER_ON, 36 .mpu_state = PWRDM_POWER_ON,
@@ -53,11 +53,12 @@ static struct clockdomain *cpu_clkdm[NR_CPUS];
53 53
54static atomic_t abort_barrier; 54static atomic_t abort_barrier;
55static bool cpu_done[NR_CPUS]; 55static bool cpu_done[NR_CPUS];
56static struct idle_statedata *state_ptr = &omap4_idle_data[0];
56 57
57/* Private functions */ 58/* Private functions */
58 59
59/** 60/**
60 * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions 61 * omap_enter_idle_[simple/coupled] - OMAP4PLUS cpuidle entry functions
61 * @dev: cpuidle device 62 * @dev: cpuidle device
62 * @drv: cpuidle driver 63 * @drv: cpuidle driver
63 * @index: the index of state to be entered 64 * @index: the index of state to be entered
@@ -66,7 +67,7 @@ static bool cpu_done[NR_CPUS];
66 * specified low power state selected by the governor. 67 * specified low power state selected by the governor.
67 * Returns the amount of time spent in the low power state. 68 * Returns the amount of time spent in the low power state.
68 */ 69 */
69static int omap4_enter_idle_simple(struct cpuidle_device *dev, 70static int omap_enter_idle_simple(struct cpuidle_device *dev,
70 struct cpuidle_driver *drv, 71 struct cpuidle_driver *drv,
71 int index) 72 int index)
72{ 73{
@@ -77,12 +78,11 @@ static int omap4_enter_idle_simple(struct cpuidle_device *dev,
77 return index; 78 return index;
78} 79}
79 80
80static int omap4_enter_idle_coupled(struct cpuidle_device *dev, 81static int omap_enter_idle_coupled(struct cpuidle_device *dev,
81 struct cpuidle_driver *drv, 82 struct cpuidle_driver *drv,
82 int index) 83 int index)
83{ 84{
84 struct omap4_idle_statedata *cx = &omap4_idle_data[index]; 85 struct idle_statedata *cx = state_ptr + index;
85 int cpu_id = smp_processor_id();
86 86
87 local_fiq_disable(); 87 local_fiq_disable();
88 88
@@ -109,8 +109,6 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
109 } 109 }
110 } 110 }
111 111
112 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
113
114 /* 112 /*
115 * Call idle CPU PM enter notifier chain so that 113 * Call idle CPU PM enter notifier chain so that
116 * VFP and per CPU interrupt context is saved. 114 * VFP and per CPU interrupt context is saved.
@@ -149,11 +147,10 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
149 * Call idle CPU cluster PM exit notifier chain 147 * Call idle CPU cluster PM exit notifier chain
150 * to restore GIC and wakeupgen context. 148 * to restore GIC and wakeupgen context.
151 */ 149 */
152 if (omap4_mpuss_read_prev_context_state()) 150 if ((cx->mpu_state == PWRDM_POWER_RET) &&
151 (cx->mpu_logic_state == PWRDM_POWER_OFF))
153 cpu_cluster_pm_exit(); 152 cpu_cluster_pm_exit();
154 153
155 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
156
157fail: 154fail:
158 cpuidle_coupled_parallel_barrier(dev, &abort_barrier); 155 cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
159 cpu_done[dev->cpu] = false; 156 cpu_done[dev->cpu] = false;
@@ -163,49 +160,38 @@ fail:
163 return index; 160 return index;
164} 161}
165 162
166/*
167 * For each cpu, setup the broadcast timer because local timers
168 * stops for the states above C1.
169 */
170static void omap_setup_broadcast_timer(void *arg)
171{
172 int cpu = smp_processor_id();
173 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
174}
175
176static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
177
178static struct cpuidle_driver omap4_idle_driver = { 163static struct cpuidle_driver omap4_idle_driver = {
179 .name = "omap4_idle", 164 .name = "omap4_idle",
180 .owner = THIS_MODULE, 165 .owner = THIS_MODULE,
181 .en_core_tk_irqen = 1,
182 .states = { 166 .states = {
183 { 167 {
184 /* C1 - CPU0 ON + CPU1 ON + MPU ON */ 168 /* C1 - CPU0 ON + CPU1 ON + MPU ON */
185 .exit_latency = 2 + 2, 169 .exit_latency = 2 + 2,
186 .target_residency = 5, 170 .target_residency = 5,
187 .flags = CPUIDLE_FLAG_TIME_VALID, 171 .flags = CPUIDLE_FLAG_TIME_VALID,
188 .enter = omap4_enter_idle_simple, 172 .enter = omap_enter_idle_simple,
189 .name = "C1", 173 .name = "C1",
190 .desc = "MPUSS ON" 174 .desc = "CPUx ON, MPUSS ON"
191 }, 175 },
192 { 176 {
193 /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */ 177 /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
194 .exit_latency = 328 + 440, 178 .exit_latency = 328 + 440,
195 .target_residency = 960, 179 .target_residency = 960,
196 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED, 180 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED |
197 .enter = omap4_enter_idle_coupled, 181 CPUIDLE_FLAG_TIMER_STOP,
182 .enter = omap_enter_idle_coupled,
198 .name = "C2", 183 .name = "C2",
199 .desc = "MPUSS CSWR", 184 .desc = "CPUx OFF, MPUSS CSWR",
200 }, 185 },
201 { 186 {
202 /* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */ 187 /* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */
203 .exit_latency = 460 + 518, 188 .exit_latency = 460 + 518,
204 .target_residency = 1100, 189 .target_residency = 1100,
205 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED, 190 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED |
206 .enter = omap4_enter_idle_coupled, 191 CPUIDLE_FLAG_TIMER_STOP,
192 .enter = omap_enter_idle_coupled,
207 .name = "C3", 193 .name = "C3",
208 .desc = "MPUSS OSWR", 194 .desc = "CPUx OFF, MPUSS OSWR",
209 }, 195 },
210 }, 196 },
211 .state_count = ARRAY_SIZE(omap4_idle_data), 197 .state_count = ARRAY_SIZE(omap4_idle_data),
@@ -215,16 +201,13 @@ static struct cpuidle_driver omap4_idle_driver = {
215/* Public functions */ 201/* Public functions */
216 202
217/** 203/**
218 * omap4_idle_init - Init routine for OMAP4 idle 204 * omap4_idle_init - Init routine for OMAP4+ idle
219 * 205 *
220 * Registers the OMAP4 specific cpuidle driver to the cpuidle 206 * Registers the OMAP4+ specific cpuidle driver to the cpuidle
221 * framework with the valid set of states. 207 * framework with the valid set of states.
222 */ 208 */
223int __init omap4_idle_init(void) 209int __init omap4_idle_init(void)
224{ 210{
225 struct cpuidle_device *dev;
226 unsigned int cpu_id = 0;
227
228 mpu_pd = pwrdm_lookup("mpu_pwrdm"); 211 mpu_pd = pwrdm_lookup("mpu_pwrdm");
229 cpu_pd[0] = pwrdm_lookup("cpu0_pwrdm"); 212 cpu_pd[0] = pwrdm_lookup("cpu0_pwrdm");
230 cpu_pd[1] = pwrdm_lookup("cpu1_pwrdm"); 213 cpu_pd[1] = pwrdm_lookup("cpu1_pwrdm");
@@ -236,22 +219,5 @@ int __init omap4_idle_init(void)
236 if (!cpu_clkdm[0] || !cpu_clkdm[1]) 219 if (!cpu_clkdm[0] || !cpu_clkdm[1])
237 return -ENODEV; 220 return -ENODEV;
238 221
239 /* Configure the broadcast timer on each cpu */ 222 return cpuidle_register(&omap4_idle_driver, cpu_online_mask);
240 on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
241
242 for_each_cpu(cpu_id, cpu_online_mask) {
243 dev = &per_cpu(omap4_idle_dev, cpu_id);
244 dev->cpu = cpu_id;
245#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
246 dev->coupled_cpus = *cpu_online_mask;
247#endif
248 cpuidle_register_driver(&omap4_idle_driver);
249
250 if (cpuidle_register_device(dev)) {
251 pr_err("%s: CPUidle register failed\n", __func__);
252 return -EIO;
253 }
254 }
255
256 return 0;
257} 223}
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 8bcb64bcdcdb..e80327b6c81f 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -139,20 +139,6 @@ static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id)
139 } 139 }
140} 140}
141 141
142/**
143 * omap4_mpuss_read_prev_context_state:
144 * Function returns the MPUSS previous context state
145 */
146u32 omap4_mpuss_read_prev_context_state(void)
147{
148 u32 reg;
149
150 reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
151 OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
152 reg &= OMAP4430_LOSTCONTEXT_DFF_MASK;
153 return reg;
154}
155
156/* 142/*
157 * Store the CPU cluster state for L2X0 low power operations. 143 * Store the CPU cluster state for L2X0 low power operations.
158 */ 144 */
diff --git a/arch/arm/mach-s3c64xx/cpuidle.c b/arch/arm/mach-s3c64xx/cpuidle.c
index ead5fab0dbb5..3c8ab07c2012 100644
--- a/arch/arm/mach-s3c64xx/cpuidle.c
+++ b/arch/arm/mach-s3c64xx/cpuidle.c
@@ -40,12 +40,9 @@ static int s3c64xx_enter_idle(struct cpuidle_device *dev,
40 return index; 40 return index;
41} 41}
42 42
43static DEFINE_PER_CPU(struct cpuidle_device, s3c64xx_cpuidle_device);
44
45static struct cpuidle_driver s3c64xx_cpuidle_driver = { 43static struct cpuidle_driver s3c64xx_cpuidle_driver = {
46 .name = "s3c64xx_cpuidle", 44 .name = "s3c64xx_cpuidle",
47 .owner = THIS_MODULE, 45 .owner = THIS_MODULE,
48 .en_core_tk_irqen = 1,
49 .states = { 46 .states = {
50 { 47 {
51 .enter = s3c64xx_enter_idle, 48 .enter = s3c64xx_enter_idle,
@@ -61,16 +58,6 @@ static struct cpuidle_driver s3c64xx_cpuidle_driver = {
61 58
62static int __init s3c64xx_init_cpuidle(void) 59static int __init s3c64xx_init_cpuidle(void)
63{ 60{
64 int ret; 61 return cpuidle_register(&s3c64xx_cpuidle_driver, NULL);
65
66 cpuidle_register_driver(&s3c64xx_cpuidle_driver);
67
68 ret = cpuidle_register_device(&s3c64xx_cpuidle_device);
69 if (ret) {
70 pr_err("Failed to register cpuidle device: %d\n", ret);
71 return ret;
72 }
73
74 return 0;
75} 62}
76device_initcall(s3c64xx_init_cpuidle); 63device_initcall(s3c64xx_init_cpuidle);
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
index 9e050268cde4..0afeb5c7061c 100644
--- a/arch/arm/mach-shmobile/cpuidle.c
+++ b/arch/arm/mach-shmobile/cpuidle.c
@@ -16,39 +16,22 @@
16#include <asm/cpuidle.h> 16#include <asm/cpuidle.h>
17#include <asm/io.h> 17#include <asm/io.h>
18 18
19int shmobile_enter_wfi(struct cpuidle_device *dev, struct cpuidle_driver *drv,
20 int index)
21{
22 cpu_do_idle();
23 return 0;
24}
25
26static struct cpuidle_device shmobile_cpuidle_dev;
27static struct cpuidle_driver shmobile_cpuidle_default_driver = { 19static struct cpuidle_driver shmobile_cpuidle_default_driver = {
28 .name = "shmobile_cpuidle", 20 .name = "shmobile_cpuidle",
29 .owner = THIS_MODULE, 21 .owner = THIS_MODULE,
30 .en_core_tk_irqen = 1,
31 .states[0] = ARM_CPUIDLE_WFI_STATE, 22 .states[0] = ARM_CPUIDLE_WFI_STATE,
32 .states[0].enter = shmobile_enter_wfi,
33 .safe_state_index = 0, /* C1 */ 23 .safe_state_index = 0, /* C1 */
34 .state_count = 1, 24 .state_count = 1,
35}; 25};
36 26
37static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver; 27static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver;
38 28
39void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv) 29void __init shmobile_cpuidle_set_driver(struct cpuidle_driver *drv)
40{ 30{
41 cpuidle_drv = drv; 31 cpuidle_drv = drv;
42} 32}
43 33
44int shmobile_cpuidle_init(void) 34int __init shmobile_cpuidle_init(void)
45{ 35{
46 struct cpuidle_device *dev = &shmobile_cpuidle_dev; 36 return cpuidle_register(cpuidle_drv, NULL);
47
48 cpuidle_register_driver(cpuidle_drv);
49
50 dev->state_count = cpuidle_drv->state_count;
51 cpuidle_register_device(dev);
52
53 return 0;
54} 37}
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index e48606d8a2be..362f9b2d2c02 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -13,9 +13,6 @@ extern int shmobile_clk_init(void);
13extern void shmobile_handle_irq_intc(struct pt_regs *); 13extern void shmobile_handle_irq_intc(struct pt_regs *);
14extern struct platform_suspend_ops shmobile_suspend_ops; 14extern struct platform_suspend_ops shmobile_suspend_ops;
15struct cpuidle_driver; 15struct cpuidle_driver;
16struct cpuidle_device;
17extern int shmobile_enter_wfi(struct cpuidle_device *dev,
18 struct cpuidle_driver *drv, int index);
19extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv); 16extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
20 17
21extern void sh7372_init_irq(void); 18extern void sh7372_init_irq(void);
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index a0826a48dd08..dec9293bb90d 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -410,11 +410,9 @@ static int sh7372_enter_a4s(struct cpuidle_device *dev,
410static struct cpuidle_driver sh7372_cpuidle_driver = { 410static struct cpuidle_driver sh7372_cpuidle_driver = {
411 .name = "sh7372_cpuidle", 411 .name = "sh7372_cpuidle",
412 .owner = THIS_MODULE, 412 .owner = THIS_MODULE,
413 .en_core_tk_irqen = 1,
414 .state_count = 5, 413 .state_count = 5,
415 .safe_state_index = 0, /* C1 */ 414 .safe_state_index = 0, /* C1 */
416 .states[0] = ARM_CPUIDLE_WFI_STATE, 415 .states[0] = ARM_CPUIDLE_WFI_STATE,
417 .states[0].enter = shmobile_enter_wfi,
418 .states[1] = { 416 .states[1] = {
419 .name = "C2", 417 .name = "C2",
420 .desc = "Core Standby Mode", 418 .desc = "Core Standby Mode",
@@ -450,12 +448,12 @@ static struct cpuidle_driver sh7372_cpuidle_driver = {
450 }, 448 },
451}; 449};
452 450
453static void sh7372_cpuidle_init(void) 451static void __init sh7372_cpuidle_init(void)
454{ 452{
455 shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver); 453 shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver);
456} 454}
457#else 455#else
458static void sh7372_cpuidle_init(void) {} 456static void __init sh7372_cpuidle_init(void) {}
459#endif 457#endif
460 458
461#ifdef CONFIG_SUSPEND 459#ifdef CONFIG_SUSPEND
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
index 0f4e8c483b34..1d1c6023f4a2 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -23,39 +23,13 @@
23static struct cpuidle_driver tegra_idle_driver = { 23static struct cpuidle_driver tegra_idle_driver = {
24 .name = "tegra_idle", 24 .name = "tegra_idle",
25 .owner = THIS_MODULE, 25 .owner = THIS_MODULE,
26 .en_core_tk_irqen = 1,
27 .state_count = 1, 26 .state_count = 1,
28 .states = { 27 .states = {
29 [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), 28 [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
30 }, 29 },
31}; 30};
32 31
33static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
34
35int __init tegra114_cpuidle_init(void) 32int __init tegra114_cpuidle_init(void)
36{ 33{
37 int ret; 34 return cpuidle_register(&tegra_idle_driver, NULL);
38 unsigned int cpu;
39 struct cpuidle_device *dev;
40 struct cpuidle_driver *drv = &tegra_idle_driver;
41
42 ret = cpuidle_register_driver(&tegra_idle_driver);
43 if (ret) {
44 pr_err("CPUidle driver registration failed\n");
45 return ret;
46 }
47
48 for_each_possible_cpu(cpu) {
49 dev = &per_cpu(tegra_idle_device, cpu);
50 dev->cpu = cpu;
51
52 dev->state_count = drv->state_count;
53 ret = cpuidle_register_device(dev);
54 if (ret) {
55 pr_err("CPU%u: CPUidle device registration failed\n",
56 cpu);
57 return ret;
58 }
59 }
60 return 0;
61} 35}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index 825ced4f7a40..590ec25855dd 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -43,32 +43,33 @@ static atomic_t abort_barrier;
43static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, 43static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
44 struct cpuidle_driver *drv, 44 struct cpuidle_driver *drv,
45 int index); 45 int index);
46#define TEGRA20_MAX_STATES 2
47#else
48#define TEGRA20_MAX_STATES 1
46#endif 49#endif
47 50
48static struct cpuidle_state tegra_idle_states[] = {
49 [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
50#ifdef CONFIG_PM_SLEEP
51 [1] = {
52 .enter = tegra20_idle_lp2_coupled,
53 .exit_latency = 5000,
54 .target_residency = 10000,
55 .power_usage = 0,
56 .flags = CPUIDLE_FLAG_TIME_VALID |
57 CPUIDLE_FLAG_COUPLED,
58 .name = "powered-down",
59 .desc = "CPU power gated",
60 },
61#endif
62};
63
64static struct cpuidle_driver tegra_idle_driver = { 51static struct cpuidle_driver tegra_idle_driver = {
65 .name = "tegra_idle", 52 .name = "tegra_idle",
66 .owner = THIS_MODULE, 53 .owner = THIS_MODULE,
67 .en_core_tk_irqen = 1, 54 .states = {
55 ARM_CPUIDLE_WFI_STATE_PWR(600),
56#ifdef CONFIG_PM_SLEEP
57 {
58 .enter = tegra20_idle_lp2_coupled,
59 .exit_latency = 5000,
60 .target_residency = 10000,
61 .power_usage = 0,
62 .flags = CPUIDLE_FLAG_TIME_VALID |
63 CPUIDLE_FLAG_COUPLED,
64 .name = "powered-down",
65 .desc = "CPU power gated",
66 },
67#endif
68 },
69 .state_count = TEGRA20_MAX_STATES,
70 .safe_state_index = 0,
68}; 71};
69 72
70static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
71
72#ifdef CONFIG_PM_SLEEP 73#ifdef CONFIG_PM_SLEEP
73#ifdef CONFIG_SMP 74#ifdef CONFIG_SMP
74static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); 75static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
@@ -217,39 +218,8 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
217 218
218int __init tegra20_cpuidle_init(void) 219int __init tegra20_cpuidle_init(void)
219{ 220{
220 int ret;
221 unsigned int cpu;
222 struct cpuidle_device *dev;
223 struct cpuidle_driver *drv = &tegra_idle_driver;
224
225#ifdef CONFIG_PM_SLEEP 221#ifdef CONFIG_PM_SLEEP
226 tegra_tear_down_cpu = tegra20_tear_down_cpu; 222 tegra_tear_down_cpu = tegra20_tear_down_cpu;
227#endif 223#endif
228 224 return cpuidle_register(&tegra_idle_driver, cpu_possible_mask);
229 drv->state_count = ARRAY_SIZE(tegra_idle_states);
230 memcpy(drv->states, tegra_idle_states,
231 drv->state_count * sizeof(drv->states[0]));
232
233 ret = cpuidle_register_driver(&tegra_idle_driver);
234 if (ret) {
235 pr_err("CPUidle driver registration failed\n");
236 return ret;
237 }
238
239 for_each_possible_cpu(cpu) {
240 dev = &per_cpu(tegra_idle_device, cpu);
241 dev->cpu = cpu;
242#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
243 dev->coupled_cpus = *cpu_possible_mask;
244#endif
245
246 dev->state_count = drv->state_count;
247 ret = cpuidle_register_device(dev);
248 if (ret) {
249 pr_err("CPU%u: CPUidle device registration failed\n",
250 cpu);
251 return ret;
252 }
253 }
254 return 0;
255} 225}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
index 8b50cf4ddd6f..36dc2befa9d8 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -43,7 +43,6 @@ static int tegra30_idle_lp2(struct cpuidle_device *dev,
43static struct cpuidle_driver tegra_idle_driver = { 43static struct cpuidle_driver tegra_idle_driver = {
44 .name = "tegra_idle", 44 .name = "tegra_idle",
45 .owner = THIS_MODULE, 45 .owner = THIS_MODULE,
46 .en_core_tk_irqen = 1,
47#ifdef CONFIG_PM_SLEEP 46#ifdef CONFIG_PM_SLEEP
48 .state_count = 2, 47 .state_count = 2,
49#else 48#else
@@ -65,8 +64,6 @@ static struct cpuidle_driver tegra_idle_driver = {
65 }, 64 },
66}; 65};
67 66
68static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
69
70#ifdef CONFIG_PM_SLEEP 67#ifdef CONFIG_PM_SLEEP
71static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev, 68static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
72 struct cpuidle_driver *drv, 69 struct cpuidle_driver *drv,
@@ -157,32 +154,8 @@ static int tegra30_idle_lp2(struct cpuidle_device *dev,
157 154
158int __init tegra30_cpuidle_init(void) 155int __init tegra30_cpuidle_init(void)
159{ 156{
160 int ret;
161 unsigned int cpu;
162 struct cpuidle_device *dev;
163 struct cpuidle_driver *drv = &tegra_idle_driver;
164
165#ifdef CONFIG_PM_SLEEP 157#ifdef CONFIG_PM_SLEEP
166 tegra_tear_down_cpu = tegra30_tear_down_cpu; 158 tegra_tear_down_cpu = tegra30_tear_down_cpu;
167#endif 159#endif
168 160 return cpuidle_register(&tegra_idle_driver, NULL);
169 ret = cpuidle_register_driver(&tegra_idle_driver);
170 if (ret) {
171 pr_err("CPUidle driver registration failed\n");
172 return ret;
173 }
174
175 for_each_possible_cpu(cpu) {
176 dev = &per_cpu(tegra_idle_device, cpu);
177 dev->cpu = cpu;
178
179 dev->state_count = drv->state_count;
180 ret = cpuidle_register_device(dev);
181 if (ret) {
182 pr_err("CPU%u: CPUidle device registration failed\n",
183 cpu);
184 return ret;
185 }
186 }
187 return 0;
188} 161}
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c
index ce9149302cc3..488e07472d98 100644
--- a/arch/arm/mach-ux500/cpuidle.c
+++ b/arch/arm/mach-ux500/cpuidle.c
@@ -11,7 +11,6 @@
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/cpuidle.h> 13#include <linux/cpuidle.h>
14#include <linux/clockchips.h>
15#include <linux/spinlock.h> 14#include <linux/spinlock.h>
16#include <linux/atomic.h> 15#include <linux/atomic.h>
17#include <linux/smp.h> 16#include <linux/smp.h>
@@ -22,7 +21,6 @@
22 21
23static atomic_t master = ATOMIC_INIT(0); 22static atomic_t master = ATOMIC_INIT(0);
24static DEFINE_SPINLOCK(master_lock); 23static DEFINE_SPINLOCK(master_lock);
25static DEFINE_PER_CPU(struct cpuidle_device, ux500_cpuidle_device);
26 24
27static inline int ux500_enter_idle(struct cpuidle_device *dev, 25static inline int ux500_enter_idle(struct cpuidle_device *dev,
28 struct cpuidle_driver *drv, int index) 26 struct cpuidle_driver *drv, int index)
@@ -30,8 +28,6 @@ static inline int ux500_enter_idle(struct cpuidle_device *dev,
30 int this_cpu = smp_processor_id(); 28 int this_cpu = smp_processor_id();
31 bool recouple = false; 29 bool recouple = false;
32 30
33 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu);
34
35 if (atomic_inc_return(&master) == num_online_cpus()) { 31 if (atomic_inc_return(&master) == num_online_cpus()) {
36 32
37 /* With this lock, we prevent the other cpu to exit and enter 33 /* With this lock, we prevent the other cpu to exit and enter
@@ -91,22 +87,20 @@ out:
91 spin_unlock(&master_lock); 87 spin_unlock(&master_lock);
92 } 88 }
93 89
94 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &this_cpu);
95
96 return index; 90 return index;
97} 91}
98 92
99static struct cpuidle_driver ux500_idle_driver = { 93static struct cpuidle_driver ux500_idle_driver = {
100 .name = "ux500_idle", 94 .name = "ux500_idle",
101 .owner = THIS_MODULE, 95 .owner = THIS_MODULE,
102 .en_core_tk_irqen = 1,
103 .states = { 96 .states = {
104 ARM_CPUIDLE_WFI_STATE, 97 ARM_CPUIDLE_WFI_STATE,
105 { 98 {
106 .enter = ux500_enter_idle, 99 .enter = ux500_enter_idle,
107 .exit_latency = 70, 100 .exit_latency = 70,
108 .target_residency = 260, 101 .target_residency = 260,
109 .flags = CPUIDLE_FLAG_TIME_VALID, 102 .flags = CPUIDLE_FLAG_TIME_VALID |
103 CPUIDLE_FLAG_TIMER_STOP,
110 .name = "ApIdle", 104 .name = "ApIdle",
111 .desc = "ARM Retention", 105 .desc = "ARM Retention",
112 }, 106 },
@@ -115,59 +109,13 @@ static struct cpuidle_driver ux500_idle_driver = {
115 .state_count = 2, 109 .state_count = 2,
116}; 110};
117 111
118/*
119 * For each cpu, setup the broadcast timer because we will
120 * need to migrate the timers for the states >= ApIdle.
121 */
122static void ux500_setup_broadcast_timer(void *arg)
123{
124 int cpu = smp_processor_id();
125 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
126}
127
128int __init ux500_idle_init(void) 112int __init ux500_idle_init(void)
129{ 113{
130 int ret, cpu;
131 struct cpuidle_device *device;
132
133 /* Configure wake up reasons */ 114 /* Configure wake up reasons */
134 prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | 115 prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
135 PRCMU_WAKEUP(ABB)); 116 PRCMU_WAKEUP(ABB));
136 117
137 /* 118 return cpuidle_register(&ux500_idle_driver, NULL);
138 * Configure the timer broadcast for each cpu, that must
139 * be done from the cpu context, so we use a smp cross
140 * call with 'on_each_cpu'.
141 */
142 on_each_cpu(ux500_setup_broadcast_timer, NULL, 1);
143
144 ret = cpuidle_register_driver(&ux500_idle_driver);
145 if (ret) {
146 printk(KERN_ERR "failed to register ux500 idle driver\n");
147 return ret;
148 }
149
150 for_each_online_cpu(cpu) {
151 device = &per_cpu(ux500_cpuidle_device, cpu);
152 device->cpu = cpu;
153 ret = cpuidle_register_device(device);
154 if (ret) {
155 printk(KERN_ERR "Failed to register cpuidle "
156 "device for cpu%d\n", cpu);
157 goto out_unregister;
158 }
159 }
160out:
161 return ret;
162
163out_unregister:
164 for_each_online_cpu(cpu) {
165 device = &per_cpu(ux500_cpuidle_device, cpu);
166 cpuidle_unregister_device(device);
167 }
168
169 cpuidle_unregister_driver(&ux500_idle_driver);
170 goto out;
171} 119}
172 120
173device_initcall(ux500_idle_init); 121device_initcall(ux500_idle_init);
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c
index 4d806b419606..4644efa06941 100644
--- a/arch/powerpc/platforms/pseries/processor_idle.c
+++ b/arch/powerpc/platforms/pseries/processor_idle.c
@@ -23,8 +23,8 @@
23#include "pseries.h" 23#include "pseries.h"
24 24
25struct cpuidle_driver pseries_idle_driver = { 25struct cpuidle_driver pseries_idle_driver = {
26 .name = "pseries_idle", 26 .name = "pseries_idle",
27 .owner = THIS_MODULE, 27 .owner = THIS_MODULE,
28}; 28};
29 29
30#define MAX_IDLE_STATE_COUNT 2 30#define MAX_IDLE_STATE_COUNT 2
@@ -33,10 +33,8 @@ static int max_idle_state = MAX_IDLE_STATE_COUNT - 1;
33static struct cpuidle_device __percpu *pseries_cpuidle_devices; 33static struct cpuidle_device __percpu *pseries_cpuidle_devices;
34static struct cpuidle_state *cpuidle_state_table; 34static struct cpuidle_state *cpuidle_state_table;
35 35
36static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before) 36static inline void idle_loop_prolog(unsigned long *in_purr)
37{ 37{
38
39 *kt_before = ktime_get();
40 *in_purr = mfspr(SPRN_PURR); 38 *in_purr = mfspr(SPRN_PURR);
41 /* 39 /*
42 * Indicate to the HV that we are idle. Now would be 40 * Indicate to the HV that we are idle. Now would be
@@ -45,12 +43,10 @@ static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before)
45 get_lppaca()->idle = 1; 43 get_lppaca()->idle = 1;
46} 44}
47 45
48static inline s64 idle_loop_epilog(unsigned long in_purr, ktime_t kt_before) 46static inline void idle_loop_epilog(unsigned long in_purr)
49{ 47{
50 get_lppaca()->wait_state_cycles += mfspr(SPRN_PURR) - in_purr; 48 get_lppaca()->wait_state_cycles += mfspr(SPRN_PURR) - in_purr;
51 get_lppaca()->idle = 0; 49 get_lppaca()->idle = 0;
52
53 return ktime_to_us(ktime_sub(ktime_get(), kt_before));
54} 50}
55 51
56static int snooze_loop(struct cpuidle_device *dev, 52static int snooze_loop(struct cpuidle_device *dev,
@@ -58,10 +54,9 @@ static int snooze_loop(struct cpuidle_device *dev,
58 int index) 54 int index)
59{ 55{
60 unsigned long in_purr; 56 unsigned long in_purr;
61 ktime_t kt_before;
62 int cpu = dev->cpu; 57 int cpu = dev->cpu;
63 58
64 idle_loop_prolog(&in_purr, &kt_before); 59 idle_loop_prolog(&in_purr);
65 local_irq_enable(); 60 local_irq_enable();
66 set_thread_flag(TIF_POLLING_NRFLAG); 61 set_thread_flag(TIF_POLLING_NRFLAG);
67 62
@@ -75,8 +70,8 @@ static int snooze_loop(struct cpuidle_device *dev,
75 clear_thread_flag(TIF_POLLING_NRFLAG); 70 clear_thread_flag(TIF_POLLING_NRFLAG);
76 smp_mb(); 71 smp_mb();
77 72
78 dev->last_residency = 73 idle_loop_epilog(in_purr);
79 (int)idle_loop_epilog(in_purr, kt_before); 74
80 return index; 75 return index;
81} 76}
82 77
@@ -102,9 +97,8 @@ static int dedicated_cede_loop(struct cpuidle_device *dev,
102 int index) 97 int index)
103{ 98{
104 unsigned long in_purr; 99 unsigned long in_purr;
105 ktime_t kt_before;
106 100
107 idle_loop_prolog(&in_purr, &kt_before); 101 idle_loop_prolog(&in_purr);
108 get_lppaca()->donate_dedicated_cpu = 1; 102 get_lppaca()->donate_dedicated_cpu = 1;
109 103
110 ppc64_runlatch_off(); 104 ppc64_runlatch_off();
@@ -112,8 +106,9 @@ static int dedicated_cede_loop(struct cpuidle_device *dev,
112 check_and_cede_processor(); 106 check_and_cede_processor();
113 107
114 get_lppaca()->donate_dedicated_cpu = 0; 108 get_lppaca()->donate_dedicated_cpu = 0;
115 dev->last_residency = 109
116 (int)idle_loop_epilog(in_purr, kt_before); 110 idle_loop_epilog(in_purr);
111
117 return index; 112 return index;
118} 113}
119 114
@@ -122,9 +117,8 @@ static int shared_cede_loop(struct cpuidle_device *dev,
122 int index) 117 int index)
123{ 118{
124 unsigned long in_purr; 119 unsigned long in_purr;
125 ktime_t kt_before;
126 120
127 idle_loop_prolog(&in_purr, &kt_before); 121 idle_loop_prolog(&in_purr);
128 122
129 /* 123 /*
130 * Yield the processor to the hypervisor. We return if 124 * Yield the processor to the hypervisor. We return if
@@ -135,8 +129,8 @@ static int shared_cede_loop(struct cpuidle_device *dev,
135 */ 129 */
136 check_and_cede_processor(); 130 check_and_cede_processor();
137 131
138 dev->last_residency = 132 idle_loop_epilog(in_purr);
139 (int)idle_loop_epilog(in_purr, kt_before); 133
140 return index; 134 return index;
141} 135}
142 136
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
index e14567a7e9a1..70ae0b2888ab 100644
--- a/arch/sh/include/asm/suspend.h
+++ b/arch/sh/include/asm/suspend.h
@@ -14,9 +14,9 @@ struct swsusp_arch_regs {
14void sh_mobile_call_standby(unsigned long mode); 14void sh_mobile_call_standby(unsigned long mode);
15 15
16#ifdef CONFIG_CPU_IDLE 16#ifdef CONFIG_CPU_IDLE
17void sh_mobile_setup_cpuidle(void); 17int sh_mobile_setup_cpuidle(void);
18#else 18#else
19static inline void sh_mobile_setup_cpuidle(void) {} 19static inline int sh_mobile_setup_cpuidle(void) { return 0; }
20#endif 20#endif
21 21
22/* notifier chains for pre/post sleep hooks */ 22/* notifier chains for pre/post sleep hooks */
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
index 1ddc876d3b26..d30622592116 100644
--- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -51,70 +51,53 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
51 return k; 51 return k;
52} 52}
53 53
54static struct cpuidle_device cpuidle_dev;
55static struct cpuidle_driver cpuidle_driver = { 54static struct cpuidle_driver cpuidle_driver = {
56 .name = "sh_idle", 55 .name = "sh_idle",
57 .owner = THIS_MODULE, 56 .owner = THIS_MODULE,
58 .en_core_tk_irqen = 1, 57 .states = {
58 {
59 .exit_latency = 1,
60 .target_residency = 1 * 2,
61 .power_usage = 3,
62 .flags = CPUIDLE_FLAG_TIME_VALID,
63 .enter = cpuidle_sleep_enter,
64 .name = "C1",
65 .desc = "SuperH Sleep Mode",
66 },
67 {
68 .exit_latency = 100,
69 .target_residency = 1 * 2,
70 .power_usage = 1,
71 .flags = CPUIDLE_FLAG_TIME_VALID,
72 .enter = cpuidle_sleep_enter,
73 .name = "C2",
74 .desc = "SuperH Sleep Mode [SF]",
75 .disabled = true,
76 },
77 {
78 .exit_latency = 2300,
79 .target_residency = 1 * 2,
80 .power_usage = 1,
81 .flags = CPUIDLE_FLAG_TIME_VALID,
82 .enter = cpuidle_sleep_enter,
83 .name = "C3",
84 .desc = "SuperH Mobile Standby Mode [SF]",
85 .disabled = true,
86 },
87 },
88 .safe_state_index = 0,
89 .state_count = 3,
59}; 90};
60 91
61void sh_mobile_setup_cpuidle(void) 92int __init sh_mobile_setup_cpuidle(void)
62{ 93{
63 struct cpuidle_device *dev = &cpuidle_dev; 94 int ret;
64 struct cpuidle_driver *drv = &cpuidle_driver;
65 struct cpuidle_state *state;
66 int i;
67 95
96 if (sh_mobile_sleep_supported & SUSP_SH_SF)
97 cpuidle_driver.states[1].disabled = false;
68 98
69 for (i = 0; i < CPUIDLE_STATE_MAX; i++) { 99 if (sh_mobile_sleep_supported & SUSP_SH_STANDBY)
70 drv->states[i].name[0] = '\0'; 100 cpuidle_driver.states[2].disabled = false;
71 drv->states[i].desc[0] = '\0';
72 }
73 101
74 i = CPUIDLE_DRIVER_STATE_START; 102 return cpuidle_register(&cpuidle_driver);
75
76 state = &drv->states[i++];
77 snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
78 strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
79 state->exit_latency = 1;
80 state->target_residency = 1 * 2;
81 state->power_usage = 3;
82 state->flags = 0;
83 state->flags |= CPUIDLE_FLAG_TIME_VALID;
84 state->enter = cpuidle_sleep_enter;
85
86 drv->safe_state_index = i-1;
87
88 if (sh_mobile_sleep_supported & SUSP_SH_SF) {
89 state = &drv->states[i++];
90 snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
91 strncpy(state->desc, "SuperH Sleep Mode [SF]",
92 CPUIDLE_DESC_LEN);
93 state->exit_latency = 100;
94 state->target_residency = 1 * 2;
95 state->power_usage = 1;
96 state->flags = 0;
97 state->flags |= CPUIDLE_FLAG_TIME_VALID;
98 state->enter = cpuidle_sleep_enter;
99 }
100
101 if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
102 state = &drv->states[i++];
103 snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
104 strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
105 CPUIDLE_DESC_LEN);
106 state->exit_latency = 2300;
107 state->target_residency = 1 * 2;
108 state->power_usage = 1;
109 state->flags = 0;
110 state->flags |= CPUIDLE_FLAG_TIME_VALID;
111 state->enter = cpuidle_sleep_enter;
112 }
113
114 drv->state_count = i;
115 dev->state_count = i;
116
117 cpuidle_register_driver(&cpuidle_driver);
118
119 cpuidle_register_device(dev);
120} 103}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index 08d27fac8d08..ac37b7234f85 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -150,8 +150,7 @@ static const struct platform_suspend_ops sh_pm_ops = {
150static int __init sh_pm_init(void) 150static int __init sh_pm_init(void)
151{ 151{
152 suspend_set_ops(&sh_pm_ops); 152 suspend_set_ops(&sh_pm_ops);
153 sh_mobile_setup_cpuidle(); 153 return sh_mobile_setup_cpuidle();
154 return 0;
155} 154}
156 155
157late_initcall(sh_pm_init); 156late_initcall(sh_pm_init);
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 66b5faffe14a..53a4e2744846 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -373,7 +373,6 @@ static int apm_cpu_idle(struct cpuidle_device *dev,
373static struct cpuidle_driver apm_idle_driver = { 373static struct cpuidle_driver apm_idle_driver = {
374 .name = "apm_idle", 374 .name = "apm_idle",
375 .owner = THIS_MODULE, 375 .owner = THIS_MODULE,
376 .en_core_tk_irqen = 1,
377 .states = { 376 .states = {
378 { /* entry 0 is for polling */ }, 377 { /* entry 0 is for polling */ },
379 { /* entry 1 is for APM idle */ 378 { /* entry 1 is for APM idle */
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ee255c60bdac..f0df2c9434d2 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -918,7 +918,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
918struct cpuidle_driver acpi_idle_driver = { 918struct cpuidle_driver acpi_idle_driver = {
919 .name = "acpi_idle", 919 .name = "acpi_idle",
920 .owner = THIS_MODULE, 920 .owner = THIS_MODULE,
921 .en_core_tk_irqen = 1,
922}; 921};
923 922
924/** 923/**
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 071e2c3eec4f..c4cc27e5c8a5 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -39,10 +39,4 @@ config CPU_IDLE_CALXEDA
39 help 39 help
40 Select this to enable cpuidle on Calxeda processors. 40 Select this to enable cpuidle on Calxeda processors.
41 41
42config CPU_IDLE_KIRKWOOD
43 bool "CPU Idle Driver for Kirkwood processors"
44 depends on ARCH_KIRKWOOD
45 help
46 Select this to enable cpuidle on Kirkwood processors.
47
48endif 42endif
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 24c6e7d945ed..0d8bd55e776f 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -6,4 +6,4 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
6obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o 6obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
7 7
8obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o 8obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o
9obj-$(CONFIG_CPU_IDLE_KIRKWOOD) += cpuidle-kirkwood.o 9obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o
diff --git a/drivers/cpuidle/cpuidle-calxeda.c b/drivers/cpuidle/cpuidle-calxeda.c
index e1aab38c5a8d..223379169cb0 100644
--- a/drivers/cpuidle/cpuidle-calxeda.c
+++ b/drivers/cpuidle/cpuidle-calxeda.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Copyright 2012 Calxeda, Inc. 2 * Copyright 2012 Calxeda, Inc.
3 * 3 *
4 * Based on arch/arm/plat-mxc/cpuidle.c: 4 * Based on arch/arm/plat-mxc/cpuidle.c: #v3.7
5 * Copyright 2012 Freescale Semiconductor, Inc. 5 * Copyright 2012 Freescale Semiconductor, Inc.
6 * Copyright 2012 Linaro Ltd. 6 * Copyright 2012 Linaro Ltd.
7 * 7 *
@@ -16,6 +16,8 @@
16 * 16 *
17 * You should have received a copy of the GNU General Public License along with 17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>. 18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * Maintainer: Rob Herring <rob.herring@calxeda.com>
19 */ 21 */
20 22
21#include <linux/cpuidle.h> 23#include <linux/cpuidle.h>
@@ -35,8 +37,6 @@
35extern void highbank_set_cpu_jump(int cpu, void *jump_addr); 37extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
36extern void *scu_base_addr; 38extern void *scu_base_addr;
37 39
38static struct cpuidle_device __percpu *calxeda_idle_cpuidle_devices;
39
40static inline unsigned int get_auxcr(void) 40static inline unsigned int get_auxcr(void)
41{ 41{
42 unsigned int val; 42 unsigned int val;
@@ -85,22 +85,8 @@ static int calxeda_pwrdown_idle(struct cpuidle_device *dev,
85 return index; 85 return index;
86} 86}
87 87
88static void calxeda_idle_cpuidle_devices_uninit(void)
89{
90 int i;
91 struct cpuidle_device *dev;
92
93 for_each_possible_cpu(i) {
94 dev = per_cpu_ptr(calxeda_idle_cpuidle_devices, i);
95 cpuidle_unregister_device(dev);
96 }
97
98 free_percpu(calxeda_idle_cpuidle_devices);
99}
100
101static struct cpuidle_driver calxeda_idle_driver = { 88static struct cpuidle_driver calxeda_idle_driver = {
102 .name = "calxeda_idle", 89 .name = "calxeda_idle",
103 .en_core_tk_irqen = 1,
104 .states = { 90 .states = {
105 ARM_CPUIDLE_WFI_STATE, 91 ARM_CPUIDLE_WFI_STATE,
106 { 92 {
@@ -118,44 +104,9 @@ static struct cpuidle_driver calxeda_idle_driver = {
118 104
119static int __init calxeda_cpuidle_init(void) 105static int __init calxeda_cpuidle_init(void)
120{ 106{
121 int cpu_id;
122 int ret;
123 struct cpuidle_device *dev;
124 struct cpuidle_driver *drv = &calxeda_idle_driver;
125
126 if (!of_machine_is_compatible("calxeda,highbank")) 107 if (!of_machine_is_compatible("calxeda,highbank"))
127 return -ENODEV; 108 return -ENODEV;
128 109
129 ret = cpuidle_register_driver(drv); 110 return cpuidle_register(&calxeda_idle_driver, NULL);
130 if (ret)
131 return ret;
132
133 calxeda_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
134 if (calxeda_idle_cpuidle_devices == NULL) {
135 ret = -ENOMEM;
136 goto unregister_drv;
137 }
138
139 /* initialize state data for each cpuidle_device */
140 for_each_possible_cpu(cpu_id) {
141 dev = per_cpu_ptr(calxeda_idle_cpuidle_devices, cpu_id);
142 dev->cpu = cpu_id;
143 dev->state_count = drv->state_count;
144
145 ret = cpuidle_register_device(dev);
146 if (ret) {
147 pr_err("Failed to register cpu %u, error: %d\n",
148 cpu_id, ret);
149 goto uninit;
150 }
151 }
152
153 return 0;
154
155uninit:
156 calxeda_idle_cpuidle_devices_uninit();
157unregister_drv:
158 cpuidle_unregister_driver(drv);
159 return ret;
160} 111}
161module_init(calxeda_cpuidle_init); 112module_init(calxeda_cpuidle_init);
diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c
index 670aa1e55cd6..521b0a7fdd89 100644
--- a/drivers/cpuidle/cpuidle-kirkwood.c
+++ b/drivers/cpuidle/cpuidle-kirkwood.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * arch/arm/mach-kirkwood/cpuidle.c
3 *
4 * CPU idle Marvell Kirkwood SoCs 2 * CPU idle Marvell Kirkwood SoCs
5 * 3 *
6 * This file is licensed under the terms of the GNU General Public 4 * This file is licensed under the terms of the GNU General Public
@@ -11,6 +9,9 @@
11 * to implement two idle states - 9 * to implement two idle states -
12 * #1 wait-for-interrupt 10 * #1 wait-for-interrupt
13 * #2 wait-for-interrupt and DDR self refresh 11 * #2 wait-for-interrupt and DDR self refresh
12 *
13 * Maintainer: Jason Cooper <jason@lakedaemon.net>
14 * Maintainer: Andrew Lunn <andrew@lunn.ch>
14 */ 15 */
15 16
16#include <linux/kernel.h> 17#include <linux/kernel.h>
@@ -41,7 +42,6 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev,
41static struct cpuidle_driver kirkwood_idle_driver = { 42static struct cpuidle_driver kirkwood_idle_driver = {
42 .name = "kirkwood_idle", 43 .name = "kirkwood_idle",
43 .owner = THIS_MODULE, 44 .owner = THIS_MODULE,
44 .en_core_tk_irqen = 1,
45 .states[0] = ARM_CPUIDLE_WFI_STATE, 45 .states[0] = ARM_CPUIDLE_WFI_STATE,
46 .states[1] = { 46 .states[1] = {
47 .enter = kirkwood_enter_idle, 47 .enter = kirkwood_enter_idle,
@@ -53,9 +53,6 @@ static struct cpuidle_driver kirkwood_idle_driver = {
53 }, 53 },
54 .state_count = KIRKWOOD_MAX_STATES, 54 .state_count = KIRKWOOD_MAX_STATES,
55}; 55};
56static struct cpuidle_device *device;
57
58static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
59 56
60/* Initialize CPU idle by registering the idle states */ 57/* Initialize CPU idle by registering the idle states */
61static int kirkwood_cpuidle_probe(struct platform_device *pdev) 58static int kirkwood_cpuidle_probe(struct platform_device *pdev)
@@ -66,26 +63,16 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev)
66 if (res == NULL) 63 if (res == NULL)
67 return -EINVAL; 64 return -EINVAL;
68 65
69 ddr_operation_base = devm_request_and_ioremap(&pdev->dev, res); 66 ddr_operation_base = devm_ioremap_resource(&pdev->dev, res);
70 if (!ddr_operation_base) 67 if (IS_ERR(ddr_operation_base))
71 return -EADDRNOTAVAIL; 68 return PTR_ERR(ddr_operation_base);
72 69
73 device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); 70 return cpuidle_register(&kirkwood_idle_driver, NULL);
74 device->state_count = KIRKWOOD_MAX_STATES;
75
76 cpuidle_register_driver(&kirkwood_idle_driver);
77 if (cpuidle_register_device(device)) {
78 pr_err("kirkwood_init_cpuidle: Failed registering\n");
79 return -EIO;
80 }
81 return 0;
82} 71}
83 72
84int kirkwood_cpuidle_remove(struct platform_device *pdev) 73int kirkwood_cpuidle_remove(struct platform_device *pdev)
85{ 74{
86 cpuidle_unregister_device(device); 75 cpuidle_unregister(&kirkwood_idle_driver);
87 cpuidle_unregister_driver(&kirkwood_idle_driver);
88
89 return 0; 76 return 0;
90} 77}
91 78
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index eba69290e074..c3a93fece819 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -8,6 +8,7 @@
8 * This code is licenced under the GPL. 8 * This code is licenced under the GPL.
9 */ 9 */
10 10
11#include <linux/clockchips.h>
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/mutex.h> 13#include <linux/mutex.h>
13#include <linux/sched.h> 14#include <linux/sched.h>
@@ -23,6 +24,7 @@
23#include "cpuidle.h" 24#include "cpuidle.h"
24 25
25DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); 26DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
27DEFINE_PER_CPU(struct cpuidle_device, cpuidle_dev);
26 28
27DEFINE_MUTEX(cpuidle_lock); 29DEFINE_MUTEX(cpuidle_lock);
28LIST_HEAD(cpuidle_detected_devices); 30LIST_HEAD(cpuidle_detected_devices);
@@ -42,24 +44,6 @@ void disable_cpuidle(void)
42 44
43static int __cpuidle_register_device(struct cpuidle_device *dev); 45static int __cpuidle_register_device(struct cpuidle_device *dev);
44 46
45static inline int cpuidle_enter(struct cpuidle_device *dev,
46 struct cpuidle_driver *drv, int index)
47{
48 struct cpuidle_state *target_state = &drv->states[index];
49 return target_state->enter(dev, drv, index);
50}
51
52static inline int cpuidle_enter_tk(struct cpuidle_device *dev,
53 struct cpuidle_driver *drv, int index)
54{
55 return cpuidle_wrap_enter(dev, drv, index, cpuidle_enter);
56}
57
58typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev,
59 struct cpuidle_driver *drv, int index);
60
61static cpuidle_enter_t cpuidle_enter_ops;
62
63/** 47/**
64 * cpuidle_play_dead - cpu off-lining 48 * cpuidle_play_dead - cpu off-lining
65 * 49 *
@@ -89,11 +73,27 @@ int cpuidle_play_dead(void)
89 * @next_state: index into drv->states of the state to enter 73 * @next_state: index into drv->states of the state to enter
90 */ 74 */
91int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, 75int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
92 int next_state) 76 int index)
93{ 77{
94 int entered_state; 78 int entered_state;
95 79
96 entered_state = cpuidle_enter_ops(dev, drv, next_state); 80 struct cpuidle_state *target_state = &drv->states[index];
81 ktime_t time_start, time_end;
82 s64 diff;
83
84 time_start = ktime_get();
85
86 entered_state = target_state->enter(dev, drv, index);
87
88 time_end = ktime_get();
89
90 local_irq_enable();
91
92 diff = ktime_to_us(ktime_sub(time_end, time_start));
93 if (diff > INT_MAX)
94 diff = INT_MAX;
95
96 dev->last_residency = (int) diff;
97 97
98 if (entered_state >= 0) { 98 if (entered_state >= 0) {
99 /* Update cpuidle counters */ 99 /* Update cpuidle counters */
@@ -146,12 +146,20 @@ int cpuidle_idle_call(void)
146 146
147 trace_cpu_idle_rcuidle(next_state, dev->cpu); 147 trace_cpu_idle_rcuidle(next_state, dev->cpu);
148 148
149 if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
150 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
151 &dev->cpu);
152
149 if (cpuidle_state_is_coupled(dev, drv, next_state)) 153 if (cpuidle_state_is_coupled(dev, drv, next_state))
150 entered_state = cpuidle_enter_state_coupled(dev, drv, 154 entered_state = cpuidle_enter_state_coupled(dev, drv,
151 next_state); 155 next_state);
152 else 156 else
153 entered_state = cpuidle_enter_state(dev, drv, next_state); 157 entered_state = cpuidle_enter_state(dev, drv, next_state);
154 158
159 if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
160 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
161 &dev->cpu);
162
155 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); 163 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
156 164
157 /* give the governor an opportunity to reflect on the outcome */ 165 /* give the governor an opportunity to reflect on the outcome */
@@ -222,37 +230,6 @@ void cpuidle_resume(void)
222 mutex_unlock(&cpuidle_lock); 230 mutex_unlock(&cpuidle_lock);
223} 231}
224 232
225/**
226 * cpuidle_wrap_enter - performs timekeeping and irqen around enter function
227 * @dev: pointer to a valid cpuidle_device object
228 * @drv: pointer to a valid cpuidle_driver object
229 * @index: index of the target cpuidle state.
230 */
231int cpuidle_wrap_enter(struct cpuidle_device *dev,
232 struct cpuidle_driver *drv, int index,
233 int (*enter)(struct cpuidle_device *dev,
234 struct cpuidle_driver *drv, int index))
235{
236 ktime_t time_start, time_end;
237 s64 diff;
238
239 time_start = ktime_get();
240
241 index = enter(dev, drv, index);
242
243 time_end = ktime_get();
244
245 local_irq_enable();
246
247 diff = ktime_to_us(ktime_sub(time_end, time_start));
248 if (diff > INT_MAX)
249 diff = INT_MAX;
250
251 dev->last_residency = (int) diff;
252
253 return index;
254}
255
256#ifdef CONFIG_ARCH_HAS_CPU_RELAX 233#ifdef CONFIG_ARCH_HAS_CPU_RELAX
257static int poll_idle(struct cpuidle_device *dev, 234static int poll_idle(struct cpuidle_device *dev,
258 struct cpuidle_driver *drv, int index) 235 struct cpuidle_driver *drv, int index)
@@ -324,9 +301,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
324 return ret; 301 return ret;
325 } 302 }
326 303
327 cpuidle_enter_ops = drv->en_core_tk_irqen ?
328 cpuidle_enter_tk : cpuidle_enter;
329
330 poll_idle_init(drv); 304 poll_idle_init(drv);
331 305
332 ret = cpuidle_add_device_sysfs(dev); 306 ret = cpuidle_add_device_sysfs(dev);
@@ -480,6 +454,77 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
480 454
481EXPORT_SYMBOL_GPL(cpuidle_unregister_device); 455EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
482 456
457/**
458 * cpuidle_unregister: unregister a driver and the devices. This function
459 * can be used only if the driver has been previously registered through
460 * the cpuidle_register function.
461 *
462 * @drv: a valid pointer to a struct cpuidle_driver
463 */
464void cpuidle_unregister(struct cpuidle_driver *drv)
465{
466 int cpu;
467 struct cpuidle_device *device;
468
469 for_each_possible_cpu(cpu) {
470 device = &per_cpu(cpuidle_dev, cpu);
471 cpuidle_unregister_device(device);
472 }
473
474 cpuidle_unregister_driver(drv);
475}
476EXPORT_SYMBOL_GPL(cpuidle_unregister);
477
478/**
479 * cpuidle_register: registers the driver and the cpu devices with the
480 * coupled_cpus passed as parameter. This function is used for all common
481 * initialization pattern there are in the arch specific drivers. The
482 * devices is globally defined in this file.
483 *
484 * @drv : a valid pointer to a struct cpuidle_driver
485 * @coupled_cpus: a cpumask for the coupled states
486 *
487 * Returns 0 on success, < 0 otherwise
488 */
489int cpuidle_register(struct cpuidle_driver *drv,
490 const struct cpumask *const coupled_cpus)
491{
492 int ret, cpu;
493 struct cpuidle_device *device;
494
495 ret = cpuidle_register_driver(drv);
496 if (ret) {
497 pr_err("failed to register cpuidle driver\n");
498 return ret;
499 }
500
501 for_each_possible_cpu(cpu) {
502 device = &per_cpu(cpuidle_dev, cpu);
503 device->cpu = cpu;
504
505#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
506 /*
507 * On multiplatform for ARM, the coupled idle states could
508 * enabled in the kernel even if the cpuidle driver does not
509 * use it. Note, coupled_cpus is a struct copy.
510 */
511 if (coupled_cpus)
512 device->coupled_cpus = *coupled_cpus;
513#endif
514 ret = cpuidle_register_device(device);
515 if (!ret)
516 continue;
517
518 pr_err("Failed to register cpuidle device for cpu%d\n", cpu);
519
520 cpuidle_unregister(drv);
521 break;
522 }
523
524 return ret;
525}
526EXPORT_SYMBOL_GPL(cpuidle_register);
527
483#ifdef CONFIG_SMP 528#ifdef CONFIG_SMP
484 529
485static void smp_callback(void *v) 530static void smp_callback(void *v)
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 422c7b69ba7c..8dfaaae94444 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -11,6 +11,8 @@
11#include <linux/mutex.h> 11#include <linux/mutex.h>
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/cpuidle.h> 13#include <linux/cpuidle.h>
14#include <linux/cpumask.h>
15#include <linux/clockchips.h>
14 16
15#include "cpuidle.h" 17#include "cpuidle.h"
16 18
@@ -19,9 +21,28 @@ DEFINE_SPINLOCK(cpuidle_driver_lock);
19static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); 21static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
20static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); 22static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
21 23
22static void __cpuidle_driver_init(struct cpuidle_driver *drv) 24static void cpuidle_setup_broadcast_timer(void *arg)
23{ 25{
26 int cpu = smp_processor_id();
27 clockevents_notify((long)(arg), &cpu);
28}
29
30static void __cpuidle_driver_init(struct cpuidle_driver *drv, int cpu)
31{
32 int i;
33
24 drv->refcnt = 0; 34 drv->refcnt = 0;
35
36 for (i = drv->state_count - 1; i >= 0 ; i--) {
37
38 if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP))
39 continue;
40
41 drv->bctimer = 1;
42 on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer,
43 (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1);
44 break;
45 }
25} 46}
26 47
27static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) 48static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
@@ -35,7 +56,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
35 if (__cpuidle_get_cpu_driver(cpu)) 56 if (__cpuidle_get_cpu_driver(cpu))
36 return -EBUSY; 57 return -EBUSY;
37 58
38 __cpuidle_driver_init(drv); 59 __cpuidle_driver_init(drv, cpu);
39 60
40 __cpuidle_set_cpu_driver(drv, cpu); 61 __cpuidle_set_cpu_driver(drv, cpu);
41 62
@@ -49,6 +70,12 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
49 70
50 if (!WARN_ON(drv->refcnt > 0)) 71 if (!WARN_ON(drv->refcnt > 0))
51 __cpuidle_set_cpu_driver(NULL, cpu); 72 __cpuidle_set_cpu_driver(NULL, cpu);
73
74 if (drv->bctimer) {
75 drv->bctimer = 0;
76 on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer,
77 (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1);
78 }
52} 79}
53 80
54#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS 81#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 1a38dd7dfe4e..0e8fab1913df 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -71,7 +71,6 @@
71static struct cpuidle_driver intel_idle_driver = { 71static struct cpuidle_driver intel_idle_driver = {
72 .name = "intel_idle", 72 .name = "intel_idle",
73 .owner = THIS_MODULE, 73 .owner = THIS_MODULE,
74 .en_core_tk_irqen = 1,
75}; 74};
76/* intel_idle.max_cstate=0 disables driver */ 75/* intel_idle.max_cstate=0 disables driver */
77static int max_cstate = CPUIDLE_STATE_MAX - 1; 76static int max_cstate = CPUIDLE_STATE_MAX - 1;
@@ -339,7 +338,6 @@ static int intel_idle(struct cpuidle_device *dev,
339 if (!(lapic_timer_reliable_states & (1 << (cstate)))) 338 if (!(lapic_timer_reliable_states & (1 << (cstate))))
340 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); 339 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
341 340
342 stop_critical_timings();
343 if (!need_resched()) { 341 if (!need_resched()) {
344 342
345 __monitor((void *)&current_thread_info()->flags, 0, 0); 343 __monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -348,8 +346,6 @@ static int intel_idle(struct cpuidle_device *dev,
348 __mwait(eax, ecx); 346 __mwait(eax, ecx);
349 } 347 }
350 348
351 start_critical_timings();
352
353 if (!(lapic_timer_reliable_states & (1 << (cstate)))) 349 if (!(lapic_timer_reliable_states & (1 << (cstate))))
354 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); 350 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
355 351
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 66346521cb65..f9fd93758333 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -8,6 +8,20 @@
8#ifndef _LINUX_CLOCKCHIPS_H 8#ifndef _LINUX_CLOCKCHIPS_H
9#define _LINUX_CLOCKCHIPS_H 9#define _LINUX_CLOCKCHIPS_H
10 10
11/* Clock event notification values */
12enum clock_event_nofitiers {
13 CLOCK_EVT_NOTIFY_ADD,
14 CLOCK_EVT_NOTIFY_BROADCAST_ON,
15 CLOCK_EVT_NOTIFY_BROADCAST_OFF,
16 CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
17 CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
18 CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
19 CLOCK_EVT_NOTIFY_SUSPEND,
20 CLOCK_EVT_NOTIFY_RESUME,
21 CLOCK_EVT_NOTIFY_CPU_DYING,
22 CLOCK_EVT_NOTIFY_CPU_DEAD,
23};
24
11#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD 25#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
12 26
13#include <linux/clocksource.h> 27#include <linux/clocksource.h>
@@ -26,20 +40,6 @@ enum clock_event_mode {
26 CLOCK_EVT_MODE_RESUME, 40 CLOCK_EVT_MODE_RESUME,
27}; 41};
28 42
29/* Clock event notification values */
30enum clock_event_nofitiers {
31 CLOCK_EVT_NOTIFY_ADD,
32 CLOCK_EVT_NOTIFY_BROADCAST_ON,
33 CLOCK_EVT_NOTIFY_BROADCAST_OFF,
34 CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
35 CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
36 CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
37 CLOCK_EVT_NOTIFY_SUSPEND,
38 CLOCK_EVT_NOTIFY_RESUME,
39 CLOCK_EVT_NOTIFY_CPU_DYING,
40 CLOCK_EVT_NOTIFY_CPU_DEAD,
41};
42
43/* 43/*
44 * Clock event features 44 * Clock event features
45 */ 45 */
@@ -173,7 +173,7 @@ extern int tick_receive_broadcast(void);
173#ifdef CONFIG_GENERIC_CLOCKEVENTS 173#ifdef CONFIG_GENERIC_CLOCKEVENTS
174extern void clockevents_notify(unsigned long reason, void *arg); 174extern void clockevents_notify(unsigned long reason, void *arg);
175#else 175#else
176# define clockevents_notify(reason, arg) do { } while (0) 176static inline void clockevents_notify(unsigned long reason, void *arg) {}
177#endif 177#endif
178 178
179#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */ 179#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
@@ -181,7 +181,7 @@ extern void clockevents_notify(unsigned long reason, void *arg);
181static inline void clockevents_suspend(void) {} 181static inline void clockevents_suspend(void) {}
182static inline void clockevents_resume(void) {} 182static inline void clockevents_resume(void) {}
183 183
184#define clockevents_notify(reason, arg) do { } while (0) 184static inline void clockevents_notify(unsigned long reason, void *arg) {}
185 185
186#endif 186#endif
187 187
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 480c14dc1ddd..3c86faa59798 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -57,6 +57,7 @@ struct cpuidle_state {
57/* Idle State Flags */ 57/* Idle State Flags */
58#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ 58#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */
59#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ 59#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */
60#define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */
60 61
61#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) 62#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
62 63
@@ -104,8 +105,8 @@ struct cpuidle_driver {
104 struct module *owner; 105 struct module *owner;
105 int refcnt; 106 int refcnt;
106 107
107 /* set to 1 to use the core cpuidle time keeping (for all states). */ 108 /* used by the cpuidle framework to setup the broadcast timer */
108 unsigned int en_core_tk_irqen:1; 109 unsigned int bctimer:1;
109 /* states array must be ordered in decreasing power consumption */ 110 /* states array must be ordered in decreasing power consumption */
110 struct cpuidle_state states[CPUIDLE_STATE_MAX]; 111 struct cpuidle_state states[CPUIDLE_STATE_MAX];
111 int state_count; 112 int state_count;
@@ -122,17 +123,15 @@ extern void cpuidle_driver_unref(void);
122extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); 123extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
123extern int cpuidle_register_device(struct cpuidle_device *dev); 124extern int cpuidle_register_device(struct cpuidle_device *dev);
124extern void cpuidle_unregister_device(struct cpuidle_device *dev); 125extern void cpuidle_unregister_device(struct cpuidle_device *dev);
125 126extern int cpuidle_register(struct cpuidle_driver *drv,
127 const struct cpumask *const coupled_cpus);
128extern void cpuidle_unregister(struct cpuidle_driver *drv);
126extern void cpuidle_pause_and_lock(void); 129extern void cpuidle_pause_and_lock(void);
127extern void cpuidle_resume_and_unlock(void); 130extern void cpuidle_resume_and_unlock(void);
128extern void cpuidle_pause(void); 131extern void cpuidle_pause(void);
129extern void cpuidle_resume(void); 132extern void cpuidle_resume(void);
130extern int cpuidle_enable_device(struct cpuidle_device *dev); 133extern int cpuidle_enable_device(struct cpuidle_device *dev);
131extern void cpuidle_disable_device(struct cpuidle_device *dev); 134extern void cpuidle_disable_device(struct cpuidle_device *dev);
132extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
133 struct cpuidle_driver *drv, int index,
134 int (*enter)(struct cpuidle_device *dev,
135 struct cpuidle_driver *drv, int index));
136extern int cpuidle_play_dead(void); 135extern int cpuidle_play_dead(void);
137 136
138extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); 137extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
@@ -151,7 +150,10 @@ static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
151static inline int cpuidle_register_device(struct cpuidle_device *dev) 150static inline int cpuidle_register_device(struct cpuidle_device *dev)
152{return -ENODEV; } 151{return -ENODEV; }
153static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } 152static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
154 153static inline int cpuidle_register(struct cpuidle_driver *drv,
154 const struct cpumask *const coupled_cpus)
155{return -ENODEV; }
156static inline void cpuidle_unregister(struct cpuidle_driver *drv) { }
155static inline void cpuidle_pause_and_lock(void) { } 157static inline void cpuidle_pause_and_lock(void) { }
156static inline void cpuidle_resume_and_unlock(void) { } 158static inline void cpuidle_resume_and_unlock(void) { }
157static inline void cpuidle_pause(void) { } 159static inline void cpuidle_pause(void) { }
@@ -159,11 +161,6 @@ static inline void cpuidle_resume(void) { }
159static inline int cpuidle_enable_device(struct cpuidle_device *dev) 161static inline int cpuidle_enable_device(struct cpuidle_device *dev)
160{return -ENODEV; } 162{return -ENODEV; }
161static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } 163static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
162static inline int cpuidle_wrap_enter(struct cpuidle_device *dev,
163 struct cpuidle_driver *drv, int index,
164 int (*enter)(struct cpuidle_device *dev,
165 struct cpuidle_driver *drv, int index))
166{ return -ENODEV; }
167static inline int cpuidle_play_dead(void) {return -ENODEV; } 164static inline int cpuidle_play_dead(void) {return -ENODEV; }
168#endif 165#endif
169 166