diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/include/asm/cpuidle.h | 29 | ||||
-rw-r--r-- | arch/arm/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kernel/cpuidle.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-at91/cpuidle.c | 67 | ||||
-rw-r--r-- | arch/arm/mach-davinci/cpuidle.c | 83 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/cpuidle.c | 72 | ||||
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 42 | ||||
-rw-r--r-- | arch/arm/mach-omap2/cpuidle44xx.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/cpuidle.c | 31 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/shmobile/cpuidle.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 4 |
12 files changed, 165 insertions, 220 deletions
diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h new file mode 100644 index 000000000000..2fca60ab513a --- /dev/null +++ b/arch/arm/include/asm/cpuidle.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __ASM_ARM_CPUIDLE_H | ||
2 | #define __ASM_ARM_CPUIDLE_H | ||
3 | |||
4 | #ifdef CONFIG_CPU_IDLE | ||
5 | extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | ||
6 | struct cpuidle_driver *drv, int index); | ||
7 | #else | ||
8 | static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | ||
9 | struct cpuidle_driver *drv, int index) { return -ENODEV; } | ||
10 | #endif | ||
11 | |||
12 | /* Common ARM WFI state */ | ||
13 | #define ARM_CPUIDLE_WFI_STATE_PWR(p) {\ | ||
14 | .enter = arm_cpuidle_simple_enter,\ | ||
15 | .exit_latency = 1,\ | ||
16 | .target_residency = 1,\ | ||
17 | .power_usage = p,\ | ||
18 | .flags = CPUIDLE_FLAG_TIME_VALID,\ | ||
19 | .name = "WFI",\ | ||
20 | .desc = "ARM WFI",\ | ||
21 | } | ||
22 | |||
23 | /* | ||
24 | * in case power_specified == 1, give a default WFI power value needed | ||
25 | * by some governors | ||
26 | */ | ||
27 | #define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX) | ||
28 | |||
29 | #endif | ||
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 43b740d0e374..940c27fde498 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -21,7 +21,7 @@ obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o | |||
21 | 21 | ||
22 | obj-$(CONFIG_LEDS) += leds.o | 22 | obj-$(CONFIG_LEDS) += leds.o |
23 | obj-$(CONFIG_OC_ETM) += etm.o | 23 | obj-$(CONFIG_OC_ETM) += etm.o |
24 | 24 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | |
25 | obj-$(CONFIG_ISA_DMA_API) += dma.o | 25 | obj-$(CONFIG_ISA_DMA_API) += dma.o |
26 | obj-$(CONFIG_ARCH_ACORN) += ecard.o | 26 | obj-$(CONFIG_ARCH_ACORN) += ecard.o |
27 | obj-$(CONFIG_FIQ) += fiq.o fiqasm.o | 27 | obj-$(CONFIG_FIQ) += fiq.o fiqasm.o |
diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c new file mode 100644 index 000000000000..89545f6c8403 --- /dev/null +++ b/arch/arm/kernel/cpuidle.c | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Linaro Ltd. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/cpuidle.h> | ||
13 | #include <asm/proc-fns.h> | ||
14 | |||
15 | int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | ||
16 | struct cpuidle_driver *drv, int index) | ||
17 | { | ||
18 | cpu_do_idle(); | ||
19 | |||
20 | return index; | ||
21 | } | ||
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index a851e6c98421..d40b3f317f7f 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c | |||
@@ -17,9 +17,10 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/cpuidle.h> | 19 | #include <linux/cpuidle.h> |
20 | #include <asm/proc-fns.h> | ||
21 | #include <linux/io.h> | 20 | #include <linux/io.h> |
22 | #include <linux/export.h> | 21 | #include <linux/export.h> |
22 | #include <asm/proc-fns.h> | ||
23 | #include <asm/cpuidle.h> | ||
23 | 24 | ||
24 | #include "pm.h" | 25 | #include "pm.h" |
25 | 26 | ||
@@ -27,66 +28,46 @@ | |||
27 | 28 | ||
28 | static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device); | 29 | static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device); |
29 | 30 | ||
30 | static struct cpuidle_driver at91_idle_driver = { | ||
31 | .name = "at91_idle", | ||
32 | .owner = THIS_MODULE, | ||
33 | }; | ||
34 | |||
35 | /* Actual code that puts the SoC in different idle states */ | 31 | /* Actual code that puts the SoC in different idle states */ |
36 | static int at91_enter_idle(struct cpuidle_device *dev, | 32 | static int at91_enter_idle(struct cpuidle_device *dev, |
37 | struct cpuidle_driver *drv, | 33 | struct cpuidle_driver *drv, |
38 | int index) | 34 | int index) |
39 | { | 35 | { |
40 | struct timeval before, after; | ||
41 | int idle_time; | ||
42 | u32 saved_lpr; | 36 | u32 saved_lpr; |
43 | 37 | ||
44 | local_irq_disable(); | 38 | __asm__("b 1f; .align 5; 1:\n" |
45 | do_gettimeofday(&before); | 39 | " mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ |
46 | if (index == 0) | 40 | |
47 | /* Wait for interrupt state */ | 41 | saved_lpr = sdram_selfrefresh_enable(); |
48 | cpu_do_idle(); | 42 | cpu_do_idle(); |
49 | else if (index == 1) { | 43 | sdram_selfrefresh_disable(saved_lpr); |
50 | asm("b 1f; .align 5; 1:"); | ||
51 | asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ | ||
52 | saved_lpr = sdram_selfrefresh_enable(); | ||
53 | cpu_do_idle(); | ||
54 | sdram_selfrefresh_disable(saved_lpr); | ||
55 | } | ||
56 | do_gettimeofday(&after); | ||
57 | local_irq_enable(); | ||
58 | idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + | ||
59 | (after.tv_usec - before.tv_usec); | ||
60 | 44 | ||
61 | dev->last_residency = idle_time; | ||
62 | return index; | 45 | return index; |
63 | } | 46 | } |
64 | 47 | ||
48 | static struct cpuidle_driver at91_idle_driver = { | ||
49 | .name = "at91_idle", | ||
50 | .owner = THIS_MODULE, | ||
51 | .en_core_tk_irqen = 1, | ||
52 | .states[0] = ARM_CPUIDLE_WFI_STATE, | ||
53 | .states[1] = { | ||
54 | .enter = at91_enter_idle, | ||
55 | .exit_latency = 10, | ||
56 | .target_residency = 100000, | ||
57 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
58 | .name = "RAM_SR", | ||
59 | .desc = "WFI and DDR Self Refresh", | ||
60 | }, | ||
61 | .state_count = AT91_MAX_STATES, | ||
62 | }; | ||
63 | |||
65 | /* Initialize CPU idle by registering the idle states */ | 64 | /* Initialize CPU idle by registering the idle states */ |
66 | static int at91_init_cpuidle(void) | 65 | static int at91_init_cpuidle(void) |
67 | { | 66 | { |
68 | struct cpuidle_device *device; | 67 | struct cpuidle_device *device; |
69 | struct cpuidle_driver *driver = &at91_idle_driver; | ||
70 | 68 | ||
71 | device = &per_cpu(at91_cpuidle_device, smp_processor_id()); | 69 | device = &per_cpu(at91_cpuidle_device, smp_processor_id()); |
72 | device->state_count = AT91_MAX_STATES; | 70 | device->state_count = AT91_MAX_STATES; |
73 | driver->state_count = AT91_MAX_STATES; | ||
74 | |||
75 | /* Wait for interrupt state */ | ||
76 | driver->states[0].enter = at91_enter_idle; | ||
77 | driver->states[0].exit_latency = 1; | ||
78 | driver->states[0].target_residency = 10000; | ||
79 | driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; | ||
80 | strcpy(driver->states[0].name, "WFI"); | ||
81 | strcpy(driver->states[0].desc, "Wait for interrupt"); | ||
82 | |||
83 | /* Wait for interrupt and RAM self refresh state */ | ||
84 | driver->states[1].enter = at91_enter_idle; | ||
85 | driver->states[1].exit_latency = 10; | ||
86 | driver->states[1].target_residency = 10000; | ||
87 | driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; | ||
88 | strcpy(driver->states[1].name, "RAM_SR"); | ||
89 | strcpy(driver->states[1].desc, "WFI and RAM Self Refresh"); | ||
90 | 71 | ||
91 | cpuidle_register_driver(&at91_idle_driver); | 72 | cpuidle_register_driver(&at91_idle_driver); |
92 | 73 | ||
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index a30c7c5a6d83..9107691adbdb 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/export.h> | 19 | #include <linux/export.h> |
20 | #include <asm/proc-fns.h> | 20 | #include <asm/proc-fns.h> |
21 | #include <asm/cpuidle.h> | ||
21 | 22 | ||
22 | #include <mach/cpuidle.h> | 23 | #include <mach/cpuidle.h> |
23 | #include <mach/ddr2.h> | 24 | #include <mach/ddr2.h> |
@@ -30,12 +31,43 @@ struct davinci_ops { | |||
30 | u32 flags; | 31 | u32 flags; |
31 | }; | 32 | }; |
32 | 33 | ||
34 | /* Actual code that puts the SoC in different idle states */ | ||
35 | static int davinci_enter_idle(struct cpuidle_device *dev, | ||
36 | struct cpuidle_driver *drv, | ||
37 | int index) | ||
38 | { | ||
39 | struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; | ||
40 | struct davinci_ops *ops = cpuidle_get_statedata(state_usage); | ||
41 | |||
42 | if (ops && ops->enter) | ||
43 | ops->enter(ops->flags); | ||
44 | |||
45 | index = cpuidle_wrap_enter(dev, drv, index, | ||
46 | arm_cpuidle_simple_enter); | ||
47 | |||
48 | if (ops && ops->exit) | ||
49 | ops->exit(ops->flags); | ||
50 | |||
51 | return index; | ||
52 | } | ||
53 | |||
33 | /* fields in davinci_ops.flags */ | 54 | /* fields in davinci_ops.flags */ |
34 | #define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) | 55 | #define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) |
35 | 56 | ||
36 | static struct cpuidle_driver davinci_idle_driver = { | 57 | static struct cpuidle_driver davinci_idle_driver = { |
37 | .name = "cpuidle-davinci", | 58 | .name = "cpuidle-davinci", |
38 | .owner = THIS_MODULE, | 59 | .owner = THIS_MODULE, |
60 | .en_core_tk_irqen = 1, | ||
61 | .states[0] = ARM_CPUIDLE_WFI_STATE, | ||
62 | .states[1] = { | ||
63 | .enter = davinci_enter_idle, | ||
64 | .exit_latency = 10, | ||
65 | .target_residency = 100000, | ||
66 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
67 | .name = "DDR SR", | ||
68 | .desc = "WFI and DDR Self Refresh", | ||
69 | }, | ||
70 | .state_count = DAVINCI_CPUIDLE_MAX_STATES, | ||
39 | }; | 71 | }; |
40 | 72 | ||
41 | static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); | 73 | static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); |
@@ -77,41 +109,10 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { | |||
77 | }, | 109 | }, |
78 | }; | 110 | }; |
79 | 111 | ||
80 | /* Actual code that puts the SoC in different idle states */ | ||
81 | static int davinci_enter_idle(struct cpuidle_device *dev, | ||
82 | struct cpuidle_driver *drv, | ||
83 | int index) | ||
84 | { | ||
85 | struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; | ||
86 | struct davinci_ops *ops = cpuidle_get_statedata(state_usage); | ||
87 | struct timeval before, after; | ||
88 | int idle_time; | ||
89 | |||
90 | local_irq_disable(); | ||
91 | do_gettimeofday(&before); | ||
92 | |||
93 | if (ops && ops->enter) | ||
94 | ops->enter(ops->flags); | ||
95 | /* Wait for interrupt state */ | ||
96 | cpu_do_idle(); | ||
97 | if (ops && ops->exit) | ||
98 | ops->exit(ops->flags); | ||
99 | |||
100 | do_gettimeofday(&after); | ||
101 | local_irq_enable(); | ||
102 | idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + | ||
103 | (after.tv_usec - before.tv_usec); | ||
104 | |||
105 | dev->last_residency = idle_time; | ||
106 | |||
107 | return index; | ||
108 | } | ||
109 | |||
110 | static int __init davinci_cpuidle_probe(struct platform_device *pdev) | 112 | static int __init davinci_cpuidle_probe(struct platform_device *pdev) |
111 | { | 113 | { |
112 | int ret; | 114 | int ret; |
113 | struct cpuidle_device *device; | 115 | struct cpuidle_device *device; |
114 | struct cpuidle_driver *driver = &davinci_idle_driver; | ||
115 | struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; | 116 | struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; |
116 | 117 | ||
117 | device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); | 118 | device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); |
@@ -123,27 +124,11 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) | |||
123 | 124 | ||
124 | ddr2_reg_base = pdata->ddr2_ctlr_base; | 125 | ddr2_reg_base = pdata->ddr2_ctlr_base; |
125 | 126 | ||
126 | /* Wait for interrupt state */ | ||
127 | driver->states[0].enter = davinci_enter_idle; | ||
128 | driver->states[0].exit_latency = 1; | ||
129 | driver->states[0].target_residency = 10000; | ||
130 | driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; | ||
131 | strcpy(driver->states[0].name, "WFI"); | ||
132 | strcpy(driver->states[0].desc, "Wait for interrupt"); | ||
133 | |||
134 | /* Wait for interrupt and DDR self refresh state */ | ||
135 | driver->states[1].enter = davinci_enter_idle; | ||
136 | driver->states[1].exit_latency = 10; | ||
137 | driver->states[1].target_residency = 10000; | ||
138 | driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; | ||
139 | strcpy(driver->states[1].name, "DDR SR"); | ||
140 | strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); | ||
141 | if (pdata->ddr2_pdown) | 127 | if (pdata->ddr2_pdown) |
142 | davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; | 128 | davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; |
143 | cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); | 129 | cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); |
144 | 130 | ||
145 | device->state_count = DAVINCI_CPUIDLE_MAX_STATES; | 131 | device->state_count = DAVINCI_CPUIDLE_MAX_STATES; |
146 | driver->state_count = DAVINCI_CPUIDLE_MAX_STATES; | ||
147 | 132 | ||
148 | ret = cpuidle_register_driver(&davinci_idle_driver); | 133 | ret = cpuidle_register_driver(&davinci_idle_driver); |
149 | if (ret) { | 134 | if (ret) { |
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c index 7088180b018b..0f1710941878 100644 --- a/arch/arm/mach-kirkwood/cpuidle.c +++ b/arch/arm/mach-kirkwood/cpuidle.c | |||
@@ -20,77 +20,47 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/export.h> | 21 | #include <linux/export.h> |
22 | #include <asm/proc-fns.h> | 22 | #include <asm/proc-fns.h> |
23 | #include <asm/cpuidle.h> | ||
23 | #include <mach/kirkwood.h> | 24 | #include <mach/kirkwood.h> |
24 | 25 | ||
25 | #define KIRKWOOD_MAX_STATES 2 | 26 | #define KIRKWOOD_MAX_STATES 2 |
26 | 27 | ||
27 | static struct cpuidle_driver kirkwood_idle_driver = { | ||
28 | .name = "kirkwood_idle", | ||
29 | .owner = THIS_MODULE, | ||
30 | }; | ||
31 | |||
32 | static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); | ||
33 | |||
34 | /* Actual code that puts the SoC in different idle states */ | 28 | /* Actual code that puts the SoC in different idle states */ |
35 | static int kirkwood_enter_idle(struct cpuidle_device *dev, | 29 | static int kirkwood_enter_idle(struct cpuidle_device *dev, |
36 | struct cpuidle_driver *drv, | 30 | struct cpuidle_driver *drv, |
37 | int index) | 31 | int index) |
38 | { | 32 | { |
39 | struct timeval before, after; | 33 | writel(0x7, DDR_OPERATION_BASE); |
40 | int idle_time; | 34 | cpu_do_idle(); |
41 | |||
42 | local_irq_disable(); | ||
43 | do_gettimeofday(&before); | ||
44 | if (index == 0) | ||
45 | /* Wait for interrupt state */ | ||
46 | cpu_do_idle(); | ||
47 | else if (index == 1) { | ||
48 | /* | ||
49 | * Following write will put DDR in self refresh. | ||
50 | * Note that we have 256 cycles before DDR puts it | ||
51 | * self in self-refresh, so the wait-for-interrupt | ||
52 | * call afterwards won't get the DDR from self refresh | ||
53 | * mode. | ||
54 | */ | ||
55 | writel(0x7, DDR_OPERATION_BASE); | ||
56 | cpu_do_idle(); | ||
57 | } | ||
58 | do_gettimeofday(&after); | ||
59 | local_irq_enable(); | ||
60 | idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + | ||
61 | (after.tv_usec - before.tv_usec); | ||
62 | |||
63 | /* Update last residency */ | ||
64 | dev->last_residency = idle_time; | ||
65 | 35 | ||
66 | return index; | 36 | return index; |
67 | } | 37 | } |
68 | 38 | ||
39 | static struct cpuidle_driver kirkwood_idle_driver = { | ||
40 | .name = "kirkwood_idle", | ||
41 | .owner = THIS_MODULE, | ||
42 | .en_core_tk_irqen = 1, | ||
43 | .states[0] = ARM_CPUIDLE_WFI_STATE, | ||
44 | .states[1] = { | ||
45 | .enter = kirkwood_enter_idle, | ||
46 | .exit_latency = 10, | ||
47 | .target_residency = 100000, | ||
48 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
49 | .name = "DDR SR", | ||
50 | .desc = "WFI and DDR Self Refresh", | ||
51 | }, | ||
52 | .state_count = KIRKWOOD_MAX_STATES, | ||
53 | }; | ||
54 | |||
55 | static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); | ||
56 | |||
69 | /* Initialize CPU idle by registering the idle states */ | 57 | /* Initialize CPU idle by registering the idle states */ |
70 | static int kirkwood_init_cpuidle(void) | 58 | static int kirkwood_init_cpuidle(void) |
71 | { | 59 | { |
72 | struct cpuidle_device *device; | 60 | struct cpuidle_device *device; |
73 | struct cpuidle_driver *driver = &kirkwood_idle_driver; | ||
74 | 61 | ||
75 | device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); | 62 | device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); |
76 | device->state_count = KIRKWOOD_MAX_STATES; | 63 | device->state_count = KIRKWOOD_MAX_STATES; |
77 | driver->state_count = KIRKWOOD_MAX_STATES; | ||
78 | |||
79 | /* Wait for interrupt state */ | ||
80 | driver->states[0].enter = kirkwood_enter_idle; | ||
81 | driver->states[0].exit_latency = 1; | ||
82 | driver->states[0].target_residency = 10000; | ||
83 | driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; | ||
84 | strcpy(driver->states[0].name, "WFI"); | ||
85 | strcpy(driver->states[0].desc, "Wait for interrupt"); | ||
86 | |||
87 | /* Wait for interrupt and DDR self refresh state */ | ||
88 | driver->states[1].enter = kirkwood_enter_idle; | ||
89 | driver->states[1].exit_latency = 10; | ||
90 | driver->states[1].target_residency = 10000; | ||
91 | driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; | ||
92 | strcpy(driver->states[1].name, "DDR SR"); | ||
93 | strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); | ||
94 | 64 | ||
95 | cpuidle_register_driver(&kirkwood_idle_driver); | 65 | cpuidle_register_driver(&kirkwood_idle_driver); |
96 | if (cpuidle_register_device(device)) { | 66 | if (cpuidle_register_device(device)) { |
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 464cffde58fe..535866489ce3 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
@@ -87,29 +87,14 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm, | |||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | /** | 90 | static int __omap3_enter_idle(struct cpuidle_device *dev, |
91 | * omap3_enter_idle - Programs OMAP3 to enter the specified state | ||
92 | * @dev: cpuidle device | ||
93 | * @drv: cpuidle driver | ||
94 | * @index: the index of state to be entered | ||
95 | * | ||
96 | * Called from the CPUidle framework to program the device to the | ||
97 | * specified target state selected by the governor. | ||
98 | */ | ||
99 | static int omap3_enter_idle(struct cpuidle_device *dev, | ||
100 | struct cpuidle_driver *drv, | 91 | struct cpuidle_driver *drv, |
101 | int index) | 92 | int index) |
102 | { | 93 | { |
103 | struct omap3_idle_statedata *cx = | 94 | struct omap3_idle_statedata *cx = |
104 | cpuidle_get_statedata(&dev->states_usage[index]); | 95 | cpuidle_get_statedata(&dev->states_usage[index]); |
105 | struct timespec ts_preidle, ts_postidle, ts_idle; | ||
106 | u32 mpu_state = cx->mpu_state, core_state = cx->core_state; | 96 | u32 mpu_state = cx->mpu_state, core_state = cx->core_state; |
107 | int idle_time; | ||
108 | |||
109 | /* Used to keep track of the total time in idle */ | ||
110 | getnstimeofday(&ts_preidle); | ||
111 | 97 | ||
112 | local_irq_disable(); | ||
113 | local_fiq_disable(); | 98 | local_fiq_disable(); |
114 | 99 | ||
115 | pwrdm_set_next_pwrst(mpu_pd, mpu_state); | 100 | pwrdm_set_next_pwrst(mpu_pd, mpu_state); |
@@ -148,22 +133,29 @@ static int omap3_enter_idle(struct cpuidle_device *dev, | |||
148 | } | 133 | } |
149 | 134 | ||
150 | return_sleep_time: | 135 | return_sleep_time: |
151 | getnstimeofday(&ts_postidle); | ||
152 | ts_idle = timespec_sub(ts_postidle, ts_preidle); | ||
153 | 136 | ||
154 | local_irq_enable(); | ||
155 | local_fiq_enable(); | 137 | local_fiq_enable(); |
156 | 138 | ||
157 | idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ | ||
158 | USEC_PER_SEC; | ||
159 | |||
160 | /* Update cpuidle counters */ | ||
161 | dev->last_residency = idle_time; | ||
162 | |||
163 | return index; | 139 | return index; |
164 | } | 140 | } |
165 | 141 | ||
166 | /** | 142 | /** |
143 | * omap3_enter_idle - Programs OMAP3 to enter the specified state | ||
144 | * @dev: cpuidle device | ||
145 | * @drv: cpuidle driver | ||
146 | * @index: the index of state to be entered | ||
147 | * | ||
148 | * Called from the CPUidle framework to program the device to the | ||
149 | * specified target state selected by the governor. | ||
150 | */ | ||
151 | static inline int omap3_enter_idle(struct cpuidle_device *dev, | ||
152 | struct cpuidle_driver *drv, | ||
153 | int index) | ||
154 | { | ||
155 | return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle); | ||
156 | } | ||
157 | |||
158 | /** | ||
167 | * next_valid_state - Find next valid C-state | 159 | * next_valid_state - Find next valid C-state |
168 | * @dev: cpuidle device | 160 | * @dev: cpuidle device |
169 | * @drv: cpuidle driver | 161 | * @drv: cpuidle driver |
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index 72e018b9b260..f386cbe9c889 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c | |||
@@ -62,15 +62,9 @@ static int omap4_enter_idle(struct cpuidle_device *dev, | |||
62 | { | 62 | { |
63 | struct omap4_idle_statedata *cx = | 63 | struct omap4_idle_statedata *cx = |
64 | cpuidle_get_statedata(&dev->states_usage[index]); | 64 | cpuidle_get_statedata(&dev->states_usage[index]); |
65 | struct timespec ts_preidle, ts_postidle, ts_idle; | ||
66 | u32 cpu1_state; | 65 | u32 cpu1_state; |
67 | int idle_time; | ||
68 | int cpu_id = smp_processor_id(); | 66 | int cpu_id = smp_processor_id(); |
69 | 67 | ||
70 | /* Used to keep track of the total time in idle */ | ||
71 | getnstimeofday(&ts_preidle); | ||
72 | |||
73 | local_irq_disable(); | ||
74 | local_fiq_disable(); | 68 | local_fiq_disable(); |
75 | 69 | ||
76 | /* | 70 | /* |
@@ -128,26 +122,17 @@ static int omap4_enter_idle(struct cpuidle_device *dev, | |||
128 | if (index > 0) | 122 | if (index > 0) |
129 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); | 123 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); |
130 | 124 | ||
131 | getnstimeofday(&ts_postidle); | ||
132 | ts_idle = timespec_sub(ts_postidle, ts_preidle); | ||
133 | |||
134 | local_irq_enable(); | ||
135 | local_fiq_enable(); | 125 | local_fiq_enable(); |
136 | 126 | ||
137 | idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ | ||
138 | USEC_PER_SEC; | ||
139 | |||
140 | /* Update cpuidle counters */ | ||
141 | dev->last_residency = idle_time; | ||
142 | |||
143 | return index; | 127 | return index; |
144 | } | 128 | } |
145 | 129 | ||
146 | DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); | 130 | DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); |
147 | 131 | ||
148 | struct cpuidle_driver omap4_idle_driver = { | 132 | struct cpuidle_driver omap4_idle_driver = { |
149 | .name = "omap4_idle", | 133 | .name = "omap4_idle", |
150 | .owner = THIS_MODULE, | 134 | .owner = THIS_MODULE, |
135 | .en_core_tk_irqen = 1, | ||
151 | }; | 136 | }; |
152 | 137 | ||
153 | static inline void _fill_cstate(struct cpuidle_driver *drv, | 138 | static inline void _fill_cstate(struct cpuidle_driver *drv, |
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c index 1b2334277e85..ca23b202b02d 100644 --- a/arch/arm/mach-shmobile/cpuidle.c +++ b/arch/arm/mach-shmobile/cpuidle.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
17 | #include <asm/cpuidle.h> | ||
17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
18 | 19 | ||
19 | static void shmobile_enter_wfi(void) | 20 | static void shmobile_enter_wfi(void) |
@@ -29,37 +30,19 @@ static int shmobile_cpuidle_enter(struct cpuidle_device *dev, | |||
29 | struct cpuidle_driver *drv, | 30 | struct cpuidle_driver *drv, |
30 | int index) | 31 | int index) |
31 | { | 32 | { |
32 | ktime_t before, after; | ||
33 | |||
34 | before = ktime_get(); | ||
35 | |||
36 | local_irq_disable(); | ||
37 | local_fiq_disable(); | ||
38 | |||
39 | shmobile_cpuidle_modes[index](); | 33 | shmobile_cpuidle_modes[index](); |
40 | 34 | ||
41 | local_irq_enable(); | ||
42 | local_fiq_enable(); | ||
43 | |||
44 | after = ktime_get(); | ||
45 | dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10; | ||
46 | |||
47 | return index; | 35 | return index; |
48 | } | 36 | } |
49 | 37 | ||
50 | static struct cpuidle_device shmobile_cpuidle_dev; | 38 | static struct cpuidle_device shmobile_cpuidle_dev; |
51 | static struct cpuidle_driver shmobile_cpuidle_driver = { | 39 | static struct cpuidle_driver shmobile_cpuidle_driver = { |
52 | .name = "shmobile_cpuidle", | 40 | .name = "shmobile_cpuidle", |
53 | .owner = THIS_MODULE, | 41 | .owner = THIS_MODULE, |
54 | .states[0] = { | 42 | .en_core_tk_irqen = 1, |
55 | .name = "C1", | 43 | .states[0] = ARM_CPUIDLE_WFI_STATE, |
56 | .desc = "WFI", | 44 | .safe_state_index = 0, /* C1 */ |
57 | .exit_latency = 1, | 45 | .state_count = 1, |
58 | .target_residency = 1 * 2, | ||
59 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
60 | }, | ||
61 | .safe_state_index = 0, /* C1 */ | ||
62 | .state_count = 1, | ||
63 | }; | 46 | }; |
64 | 47 | ||
65 | void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); | 48 | void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); |
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index 6d62eb40e750..1ddc876d3b26 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c | |||
@@ -29,7 +29,6 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev, | |||
29 | int index) | 29 | int index) |
30 | { | 30 | { |
31 | unsigned long allowed_mode = SUSP_SH_SLEEP; | 31 | unsigned long allowed_mode = SUSP_SH_SLEEP; |
32 | ktime_t before, after; | ||
33 | int requested_state = index; | 32 | int requested_state = index; |
34 | int allowed_state; | 33 | int allowed_state; |
35 | int k; | 34 | int k; |
@@ -47,19 +46,16 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev, | |||
47 | */ | 46 | */ |
48 | k = min_t(int, allowed_state, requested_state); | 47 | k = min_t(int, allowed_state, requested_state); |
49 | 48 | ||
50 | before = ktime_get(); | ||
51 | sh_mobile_call_standby(cpuidle_mode[k]); | 49 | sh_mobile_call_standby(cpuidle_mode[k]); |
52 | after = ktime_get(); | ||
53 | |||
54 | dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10; | ||
55 | 50 | ||
56 | return k; | 51 | return k; |
57 | } | 52 | } |
58 | 53 | ||
59 | static struct cpuidle_device cpuidle_dev; | 54 | static struct cpuidle_device cpuidle_dev; |
60 | static struct cpuidle_driver cpuidle_driver = { | 55 | static struct cpuidle_driver cpuidle_driver = { |
61 | .name = "sh_idle", | 56 | .name = "sh_idle", |
62 | .owner = THIS_MODULE, | 57 | .owner = THIS_MODULE, |
58 | .en_core_tk_irqen = 1, | ||
63 | }; | 59 | }; |
64 | 60 | ||
65 | void sh_mobile_setup_cpuidle(void) | 61 | void sh_mobile_setup_cpuidle(void) |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index ce664f33ea8e..bbcc2c389ade 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -642,6 +642,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) | |||
642 | kfree(buffer.pointer); | 642 | kfree(buffer.pointer); |
643 | buffer.length = ACPI_ALLOCATE_BUFFER; | 643 | buffer.length = ACPI_ALLOCATE_BUFFER; |
644 | buffer.pointer = NULL; | 644 | buffer.pointer = NULL; |
645 | lapic = NULL; | ||
645 | 646 | ||
646 | if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) | 647 | if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) |
647 | goto out; | 648 | goto out; |
@@ -650,7 +651,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) | |||
650 | goto free_tmp_map; | 651 | goto free_tmp_map; |
651 | 652 | ||
652 | cpumask_copy(tmp_map, cpu_present_mask); | 653 | cpumask_copy(tmp_map, cpu_present_mask); |
653 | acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED); | 654 | acpi_register_lapic(physid, ACPI_MADT_ENABLED); |
654 | 655 | ||
655 | /* | 656 | /* |
656 | * If mp_register_lapic successfully generates a new logical cpu | 657 | * If mp_register_lapic successfully generates a new logical cpu |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 66d250c00d11..93a2a0932b51 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/tboot.h> | 50 | #include <linux/tboot.h> |
51 | #include <linux/stackprotector.h> | 51 | #include <linux/stackprotector.h> |
52 | #include <linux/gfp.h> | 52 | #include <linux/gfp.h> |
53 | #include <linux/cpuidle.h> | ||
53 | 54 | ||
54 | #include <asm/acpi.h> | 55 | #include <asm/acpi.h> |
55 | #include <asm/desc.h> | 56 | #include <asm/desc.h> |
@@ -1422,7 +1423,8 @@ void native_play_dead(void) | |||
1422 | tboot_shutdown(TB_SHUTDOWN_WFS); | 1423 | tboot_shutdown(TB_SHUTDOWN_WFS); |
1423 | 1424 | ||
1424 | mwait_play_dead(); /* Only returns on failure */ | 1425 | mwait_play_dead(); /* Only returns on failure */ |
1425 | hlt_play_dead(); | 1426 | if (cpuidle_play_dead()) |
1427 | hlt_play_dead(); | ||
1426 | } | 1428 | } |
1427 | 1429 | ||
1428 | #else /* ... !CONFIG_HOTPLUG_CPU */ | 1430 | #else /* ... !CONFIG_HOTPLUG_CPU */ |