diff options
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. | |||
15 | cpuidle driver initializes the cpuidle_device structure for each CPU device | 15 | cpuidle driver initializes the cpuidle_device structure for each CPU device |
16 | and registers with cpuidle using cpuidle_register_device. | 16 | and registers with cpuidle using cpuidle_register_device. |
17 | 17 | ||
18 | If all the idle states are the same, the wrapper function cpuidle_register | ||
19 | could be used instead. | ||
20 | |||
18 | It can also support the dynamic changes (like battery <-> AC), by using | 21 | It can also support the dynamic changes (like battery <-> AC), by using |
19 | cpuidle_pause_and_lock, cpuidle_disable_device and cpuidle_enable_device, | 22 | cpuidle_pause_and_lock, cpuidle_disable_device and cpuidle_enable_device, |
20 | cpuidle_resume_and_unlock. | 23 | cpuidle_resume_and_unlock. |
21 | 24 | ||
22 | Interfaces: | 25 | Interfaces: |
26 | extern int cpuidle_register(struct cpuidle_driver *drv, | ||
27 | const struct cpumask *const coupled_cpus); | ||
28 | extern int cpuidle_unregister(struct cpuidle_driver *drv); | ||
23 | extern int cpuidle_register_driver(struct cpuidle_driver *drv); | 29 | extern int cpuidle_register_driver(struct cpuidle_driver *drv); |
24 | extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); | 30 | extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); |
25 | extern int cpuidle_register_device(struct cpuidle_device *dev); | 31 | extern 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 | |||
2206 | F: drivers/cpufreq/ | 2206 | F: drivers/cpufreq/ |
2207 | F: include/linux/cpufreq.h | 2207 | F: include/linux/cpufreq.h |
2208 | 2208 | ||
2209 | CPUIDLE DRIVERS | ||
2210 | M: Rafael J. Wysocki <rjw@sisk.pl> | ||
2211 | M: Daniel Lezcano <daniel.lezcano@linaro.org> | ||
2212 | L: linux-pm@vger.kernel.org | ||
2213 | S: Maintained | ||
2214 | T: git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git | ||
2215 | F: drivers/cpuidle/* | ||
2216 | F: include/linux/cpuidle.h | ||
2217 | |||
2209 | CPUID/MSR DRIVER | 2218 | CPUID/MSR DRIVER |
2210 | M: "H. Peter Anvin" <hpa@zytor.com> | 2219 | M: "H. Peter Anvin" <hpa@zytor.com> |
2211 | S: Maintained | 2220 | S: 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 | |||
56 | CONFIG_ZBOOT_ROM_TEXT=0x0 | 56 | CONFIG_ZBOOT_ROM_TEXT=0x0 |
57 | CONFIG_ZBOOT_ROM_BSS=0x0 | 57 | CONFIG_ZBOOT_ROM_BSS=0x0 |
58 | CONFIG_CPU_IDLE=y | 58 | CONFIG_CPU_IDLE=y |
59 | CONFIG_CPU_IDLE_KIRKWOOD=y | ||
60 | CONFIG_NET=y | 59 | CONFIG_NET=y |
61 | CONFIG_PACKET=y | 60 | CONFIG_PACKET=y |
62 | CONFIG_UNIX=y | 61 | CONFIG_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 | ||
30 | static 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 */ |
33 | static int at91_enter_idle(struct cpuidle_device *dev, | 31 | static 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, | |||
47 | static struct cpuidle_driver at91_idle_driver = { | 45 | static 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 */ |
64 | static int at91_init_cpuidle(void) | 61 | static 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 | ||
80 | device_initcall(at91_init_cpuidle); | 66 | device_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 | ||
28 | static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); | ||
29 | static void __iomem *ddr2_reg_base; | 28 | static void __iomem *ddr2_reg_base; |
30 | static bool ddr2_pdown; | 29 | static 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 */ |
52 | static int davinci_enter_idle(struct cpuidle_device *dev, | 51 | static 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, | |||
66 | static struct cpuidle_driver davinci_idle_driver = { | 61 | static 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 | ||
82 | static int __init davinci_cpuidle_probe(struct platform_device *pdev) | 76 | static 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 | ||
115 | static struct platform_driver davinci_cpuidle_driver = { | 92 | static 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); | |||
58 | static struct cpuidle_driver exynos4_idle_driver = { | 58 | static 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 | |||
30 | obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o | 30 | obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o |
31 | 31 | ||
32 | ifeq ($(CONFIG_CPU_IDLE),y) | 32 | ifeq ($(CONFIG_CPU_IDLE),y) |
33 | obj-y += cpuidle.o | 33 | obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o |
34 | obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o | 34 | obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o |
35 | endif | 35 | endif |
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 | |||
13 | static 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 | |||
20 | static 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 | |||
34 | int __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); | |||
21 | static int imx6q_enter_wait(struct cpuidle_device *dev, | 20 | static 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(); |
44 | done: | 39 | done: |
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 | */ | ||
55 | static 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 | |||
62 | static struct cpuidle_driver imx6q_cpuidle_driver = { | 45 | static 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 | |||
20 | static struct cpuidle_device __percpu * imx_cpuidle_devices; | ||
21 | |||
22 | static 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 | |||
35 | int __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 | |||
74 | uninit: | ||
75 | imx_cpuidle_devices_uninit(); | ||
76 | |||
77 | unregister_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 |
16 | extern int imx_cpuidle_init(struct cpuidle_driver *drv); | 14 | extern int imx5_cpuidle_init(void); |
17 | extern int imx6q_cpuidle_init(void); | 15 | extern int imx6q_cpuidle_init(void); |
18 | #else | 16 | #else |
19 | static inline int imx_cpuidle_init(struct cpuidle_driver *drv) | 17 | static inline int imx5_cpuidle_init(void) |
20 | { | 18 | { |
21 | return -ENODEV; | 19 | return 0; |
22 | } | 20 | } |
23 | static inline int imx6q_cpuidle_init(void) | 21 | static 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 | ||
152 | static 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 | |||
164 | static 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 | |||
179 | static int __init imx5_pm_common_init(void) | 152 | static 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 | ||
200 | void __init imx51_pm_init(void) | 172 | void __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); | |||
249 | extern int omap4_finish_suspend(unsigned long cpu_state); | 249 | extern int omap4_finish_suspend(unsigned long cpu_state); |
250 | extern void omap4_cpu_resume(void); | 250 | extern void omap4_cpu_resume(void); |
251 | extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); | 251 | extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); |
252 | extern u32 omap4_mpuss_read_prev_context_state(void); | ||
253 | #else | 252 | #else |
254 | static inline int omap4_enter_lowpower(unsigned int cpu, | 253 | static 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) | |||
277 | static inline void omap4_cpu_resume(void) | 276 | static inline void omap4_cpu_resume(void) |
278 | {} | 277 | {} |
279 | 278 | ||
280 | static inline u32 omap4_mpuss_read_prev_context_state(void) | ||
281 | { | ||
282 | return 0; | ||
283 | } | ||
284 | #endif | 279 | #endif |
285 | 280 | ||
286 | struct omap_sdrc_params; | 281 | struct 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 | |
104 | static 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 | */ | ||
109 | static 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 | */ | ||
160 | static 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 | ||
274 | static DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); | ||
275 | |||
276 | static struct cpuidle_driver omap3_idle_driver = { | 263 | static 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 | */ |
349 | int __init omap3_idle_init(void) | 336 | int __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 */ |
27 | struct omap4_idle_statedata { | 27 | struct 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 | ||
33 | static struct omap4_idle_statedata omap4_idle_data[] = { | 33 | static 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 | ||
54 | static atomic_t abort_barrier; | 54 | static atomic_t abort_barrier; |
55 | static bool cpu_done[NR_CPUS]; | 55 | static bool cpu_done[NR_CPUS]; |
56 | static 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 | */ |
69 | static int omap4_enter_idle_simple(struct cpuidle_device *dev, | 70 | static 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 | ||
80 | static int omap4_enter_idle_coupled(struct cpuidle_device *dev, | 81 | static 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 | |||
157 | fail: | 154 | fail: |
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 | */ | ||
170 | static 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 | |||
176 | static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); | ||
177 | |||
178 | static struct cpuidle_driver omap4_idle_driver = { | 163 | static 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 | */ |
223 | int __init omap4_idle_init(void) | 209 | int __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 | */ | ||
146 | u32 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 | ||
43 | static DEFINE_PER_CPU(struct cpuidle_device, s3c64xx_cpuidle_device); | ||
44 | |||
45 | static struct cpuidle_driver s3c64xx_cpuidle_driver = { | 43 | static 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 | ||
62 | static int __init s3c64xx_init_cpuidle(void) | 59 | static 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 | } |
76 | device_initcall(s3c64xx_init_cpuidle); | 63 | device_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 | ||
19 | int shmobile_enter_wfi(struct cpuidle_device *dev, struct cpuidle_driver *drv, | ||
20 | int index) | ||
21 | { | ||
22 | cpu_do_idle(); | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | static struct cpuidle_device shmobile_cpuidle_dev; | ||
27 | static struct cpuidle_driver shmobile_cpuidle_default_driver = { | 19 | static 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 | ||
37 | static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver; | 27 | static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver; |
38 | 28 | ||
39 | void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv) | 29 | void __init shmobile_cpuidle_set_driver(struct cpuidle_driver *drv) |
40 | { | 30 | { |
41 | cpuidle_drv = drv; | 31 | cpuidle_drv = drv; |
42 | } | 32 | } |
43 | 33 | ||
44 | int shmobile_cpuidle_init(void) | 34 | int __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); | |||
13 | extern void shmobile_handle_irq_intc(struct pt_regs *); | 13 | extern void shmobile_handle_irq_intc(struct pt_regs *); |
14 | extern struct platform_suspend_ops shmobile_suspend_ops; | 14 | extern struct platform_suspend_ops shmobile_suspend_ops; |
15 | struct cpuidle_driver; | 15 | struct cpuidle_driver; |
16 | struct cpuidle_device; | ||
17 | extern int shmobile_enter_wfi(struct cpuidle_device *dev, | ||
18 | struct cpuidle_driver *drv, int index); | ||
19 | extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv); | 16 | extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv); |
20 | 17 | ||
21 | extern void sh7372_init_irq(void); | 18 | extern 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, | |||
410 | static struct cpuidle_driver sh7372_cpuidle_driver = { | 410 | static 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 | ||
453 | static void sh7372_cpuidle_init(void) | 451 | static 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 |
458 | static void sh7372_cpuidle_init(void) {} | 456 | static 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 @@ | |||
23 | static struct cpuidle_driver tegra_idle_driver = { | 23 | static 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 | ||
33 | static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device); | ||
34 | |||
35 | int __init tegra114_cpuidle_init(void) | 32 | int __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; | |||
43 | static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, | 43 | static 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 | ||
48 | static 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 | |||
64 | static struct cpuidle_driver tegra_idle_driver = { | 51 | static 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 | ||
70 | static 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 |
74 | static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); | 75 | static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); |
@@ -217,39 +218,8 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, | |||
217 | 218 | ||
218 | int __init tegra20_cpuidle_init(void) | 219 | int __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, | |||
43 | static struct cpuidle_driver tegra_idle_driver = { | 43 | static 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 | ||
68 | static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device); | ||
69 | |||
70 | #ifdef CONFIG_PM_SLEEP | 67 | #ifdef CONFIG_PM_SLEEP |
71 | static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev, | 68 | static 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 | ||
158 | int __init tegra30_cpuidle_init(void) | 155 | int __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 | ||
23 | static atomic_t master = ATOMIC_INIT(0); | 22 | static atomic_t master = ATOMIC_INIT(0); |
24 | static DEFINE_SPINLOCK(master_lock); | 23 | static DEFINE_SPINLOCK(master_lock); |
25 | static DEFINE_PER_CPU(struct cpuidle_device, ux500_cpuidle_device); | ||
26 | 24 | ||
27 | static inline int ux500_enter_idle(struct cpuidle_device *dev, | 25 | static 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 | ||
99 | static struct cpuidle_driver ux500_idle_driver = { | 93 | static 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 | */ | ||
122 | static 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 | |||
128 | int __init ux500_idle_init(void) | 112 | int __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 | } | ||
160 | out: | ||
161 | return ret; | ||
162 | |||
163 | out_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 | ||
173 | device_initcall(ux500_idle_init); | 121 | device_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 | ||
25 | struct cpuidle_driver pseries_idle_driver = { | 25 | struct 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; | |||
33 | static struct cpuidle_device __percpu *pseries_cpuidle_devices; | 33 | static struct cpuidle_device __percpu *pseries_cpuidle_devices; |
34 | static struct cpuidle_state *cpuidle_state_table; | 34 | static struct cpuidle_state *cpuidle_state_table; |
35 | 35 | ||
36 | static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before) | 36 | static 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 | ||
48 | static inline s64 idle_loop_epilog(unsigned long in_purr, ktime_t kt_before) | 46 | static 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 | ||
56 | static int snooze_loop(struct cpuidle_device *dev, | 52 | static 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 { | |||
14 | void sh_mobile_call_standby(unsigned long mode); | 14 | void sh_mobile_call_standby(unsigned long mode); |
15 | 15 | ||
16 | #ifdef CONFIG_CPU_IDLE | 16 | #ifdef CONFIG_CPU_IDLE |
17 | void sh_mobile_setup_cpuidle(void); | 17 | int sh_mobile_setup_cpuidle(void); |
18 | #else | 18 | #else |
19 | static inline void sh_mobile_setup_cpuidle(void) {} | 19 | static 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 | ||
54 | static struct cpuidle_device cpuidle_dev; | ||
55 | static struct cpuidle_driver cpuidle_driver = { | 54 | static 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 | ||
61 | void sh_mobile_setup_cpuidle(void) | 92 | int __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 = { | |||
150 | static int __init sh_pm_init(void) | 150 | static 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 | ||
157 | late_initcall(sh_pm_init); | 156 | late_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, | |||
373 | static struct cpuidle_driver apm_idle_driver = { | 373 | static 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, | |||
918 | struct cpuidle_driver acpi_idle_driver = { | 918 | struct 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 | ||
42 | config 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 | |||
48 | endif | 42 | endif |
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/ | |||
6 | obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o | 6 | obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o |
7 | 7 | ||
8 | obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o | 8 | obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o |
9 | obj-$(CONFIG_CPU_IDLE_KIRKWOOD) += cpuidle-kirkwood.o | 9 | obj-$(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 @@ | |||
35 | extern void highbank_set_cpu_jump(int cpu, void *jump_addr); | 37 | extern void highbank_set_cpu_jump(int cpu, void *jump_addr); |
36 | extern void *scu_base_addr; | 38 | extern void *scu_base_addr; |
37 | 39 | ||
38 | static struct cpuidle_device __percpu *calxeda_idle_cpuidle_devices; | ||
39 | |||
40 | static inline unsigned int get_auxcr(void) | 40 | static 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 | ||
88 | static 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 | |||
101 | static struct cpuidle_driver calxeda_idle_driver = { | 88 | static 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 | ||
119 | static int __init calxeda_cpuidle_init(void) | 105 | static 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 | |||
155 | uninit: | ||
156 | calxeda_idle_cpuidle_devices_uninit(); | ||
157 | unregister_drv: | ||
158 | cpuidle_unregister_driver(drv); | ||
159 | return ret; | ||
160 | } | 111 | } |
161 | module_init(calxeda_cpuidle_init); | 112 | module_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, | |||
41 | static struct cpuidle_driver kirkwood_idle_driver = { | 42 | static 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 | }; |
56 | static struct cpuidle_device *device; | ||
57 | |||
58 | static 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 */ |
61 | static int kirkwood_cpuidle_probe(struct platform_device *pdev) | 58 | static 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 | ||
84 | int kirkwood_cpuidle_remove(struct platform_device *pdev) | 73 | int 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 | ||
25 | DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); | 26 | DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); |
27 | DEFINE_PER_CPU(struct cpuidle_device, cpuidle_dev); | ||
26 | 28 | ||
27 | DEFINE_MUTEX(cpuidle_lock); | 29 | DEFINE_MUTEX(cpuidle_lock); |
28 | LIST_HEAD(cpuidle_detected_devices); | 30 | LIST_HEAD(cpuidle_detected_devices); |
@@ -42,24 +44,6 @@ void disable_cpuidle(void) | |||
42 | 44 | ||
43 | static int __cpuidle_register_device(struct cpuidle_device *dev); | 45 | static int __cpuidle_register_device(struct cpuidle_device *dev); |
44 | 46 | ||
45 | static 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 | |||
52 | static 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 | |||
58 | typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev, | ||
59 | struct cpuidle_driver *drv, int index); | ||
60 | |||
61 | static 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 | */ |
91 | int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, | 75 | int 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 | */ | ||
231 | int 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 |
257 | static int poll_idle(struct cpuidle_device *dev, | 234 | static 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 | ||
481 | EXPORT_SYMBOL_GPL(cpuidle_unregister_device); | 455 | EXPORT_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 | */ | ||
464 | void 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 | } | ||
476 | EXPORT_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 | */ | ||
489 | int 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 | } | ||
526 | EXPORT_SYMBOL_GPL(cpuidle_register); | ||
527 | |||
483 | #ifdef CONFIG_SMP | 528 | #ifdef CONFIG_SMP |
484 | 529 | ||
485 | static void smp_callback(void *v) | 530 | static 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); | |||
19 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); | 21 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); |
20 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); | 22 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); |
21 | 23 | ||
22 | static void __cpuidle_driver_init(struct cpuidle_driver *drv) | 24 | static void cpuidle_setup_broadcast_timer(void *arg) |
23 | { | 25 | { |
26 | int cpu = smp_processor_id(); | ||
27 | clockevents_notify((long)(arg), &cpu); | ||
28 | } | ||
29 | |||
30 | static 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 | ||
27 | static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) | 48 | static 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 @@ | |||
71 | static struct cpuidle_driver intel_idle_driver = { | 71 | static 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 */ |
77 | static int max_cstate = CPUIDLE_STATE_MAX - 1; | 76 | static 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 *)¤t_thread_info()->flags, 0, 0); | 343 | __monitor((void *)¤t_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 */ | ||
12 | enum 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 */ | ||
30 | enum 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 |
174 | extern void clockevents_notify(unsigned long reason, void *arg); | 174 | extern void clockevents_notify(unsigned long reason, void *arg); |
175 | #else | 175 | #else |
176 | # define clockevents_notify(reason, arg) do { } while (0) | 176 | static 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); | |||
181 | static inline void clockevents_suspend(void) {} | 181 | static inline void clockevents_suspend(void) {} |
182 | static inline void clockevents_resume(void) {} | 182 | static inline void clockevents_resume(void) {} |
183 | 183 | ||
184 | #define clockevents_notify(reason, arg) do { } while (0) | 184 | static 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); | |||
122 | extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); | 123 | extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); |
123 | extern int cpuidle_register_device(struct cpuidle_device *dev); | 124 | extern int cpuidle_register_device(struct cpuidle_device *dev); |
124 | extern void cpuidle_unregister_device(struct cpuidle_device *dev); | 125 | extern void cpuidle_unregister_device(struct cpuidle_device *dev); |
125 | 126 | extern int cpuidle_register(struct cpuidle_driver *drv, | |
127 | const struct cpumask *const coupled_cpus); | ||
128 | extern void cpuidle_unregister(struct cpuidle_driver *drv); | ||
126 | extern void cpuidle_pause_and_lock(void); | 129 | extern void cpuidle_pause_and_lock(void); |
127 | extern void cpuidle_resume_and_unlock(void); | 130 | extern void cpuidle_resume_and_unlock(void); |
128 | extern void cpuidle_pause(void); | 131 | extern void cpuidle_pause(void); |
129 | extern void cpuidle_resume(void); | 132 | extern void cpuidle_resume(void); |
130 | extern int cpuidle_enable_device(struct cpuidle_device *dev); | 133 | extern int cpuidle_enable_device(struct cpuidle_device *dev); |
131 | extern void cpuidle_disable_device(struct cpuidle_device *dev); | 134 | extern void cpuidle_disable_device(struct cpuidle_device *dev); |
132 | extern 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)); | ||
136 | extern int cpuidle_play_dead(void); | 135 | extern int cpuidle_play_dead(void); |
137 | 136 | ||
138 | extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); | 137 | extern 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) { } | |||
151 | static inline int cpuidle_register_device(struct cpuidle_device *dev) | 150 | static inline int cpuidle_register_device(struct cpuidle_device *dev) |
152 | {return -ENODEV; } | 151 | {return -ENODEV; } |
153 | static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } | 152 | static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } |
154 | 153 | static inline int cpuidle_register(struct cpuidle_driver *drv, | |
154 | const struct cpumask *const coupled_cpus) | ||
155 | {return -ENODEV; } | ||
156 | static inline void cpuidle_unregister(struct cpuidle_driver *drv) { } | ||
155 | static inline void cpuidle_pause_and_lock(void) { } | 157 | static inline void cpuidle_pause_and_lock(void) { } |
156 | static inline void cpuidle_resume_and_unlock(void) { } | 158 | static inline void cpuidle_resume_and_unlock(void) { } |
157 | static inline void cpuidle_pause(void) { } | 159 | static inline void cpuidle_pause(void) { } |
@@ -159,11 +161,6 @@ static inline void cpuidle_resume(void) { } | |||
159 | static inline int cpuidle_enable_device(struct cpuidle_device *dev) | 161 | static inline int cpuidle_enable_device(struct cpuidle_device *dev) |
160 | {return -ENODEV; } | 162 | {return -ENODEV; } |
161 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } | 163 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } |
162 | static 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; } | ||
167 | static inline int cpuidle_play_dead(void) {return -ENODEV; } | 164 | static inline int cpuidle_play_dead(void) {return -ENODEV; } |
168 | #endif | 165 | #endif |
169 | 166 | ||