aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-08 06:32:07 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-08 06:32:07 -0400
commitf69e44b2059f2238ac558b4a115ebcdefe20b9be (patch)
treebe2a95654d7c9cb38bbcbb7a83b862db359c79e1
parent0f0c8aa0d0562954cdfa135efb827067de7ba855 (diff)
parentb6269efb146eb8770d753e3dc1c561f1cffb631a (diff)
Merge branch 'pm-cpuidle-next' into linux-next
* pm-cpuidle-next: cpuidle: imx6: remove timer broadcast initialization cpuidle: OMAP4: remove timer broadcast initialization cpuidle: ux500: remove timer broadcast initialization cpuidle: initialize the broadcast timer framework timer: move enum definition out of ifdef section cpuidle: kirkwood: fix coccicheck warnings cpuidle / kirkwood: remove redundant Kconfig option cpuidle / ux500 : use CPUIDLE_FLAG_TIMER_STOP flag cpuidle / imx6 : use CPUIDLE_FLAG_TIMER_STOP flag cpuidle / omap4 : use CPUIDLE_FLAG_TIMER_STOP flag cpuidle : handle clockevent notify from the cpuidle framework
-rw-r--r--arch/arm/configs/kirkwood_defconfig1
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c23
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c25
-rw-r--r--arch/arm/mach-ux500/cpuidle.c25
-rw-r--r--drivers/cpuidle/Kconfig6
-rw-r--r--drivers/cpuidle/Makefile2
-rw-r--r--drivers/cpuidle/cpuidle-kirkwood.c6
-rw-r--r--drivers/cpuidle/cpuidle.c9
-rw-r--r--drivers/cpuidle/driver.c31
-rw-r--r--include/linux/clockchips.h32
-rw-r--r--include/linux/cpuidle.h3
11 files changed, 69 insertions, 94 deletions
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 13482ea58b09..93f3794ba5cb 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -56,7 +56,6 @@ CONFIG_AEABI=y
56CONFIG_ZBOOT_ROM_TEXT=0x0 56CONFIG_ZBOOT_ROM_TEXT=0x0
57CONFIG_ZBOOT_ROM_BSS=0x0 57CONFIG_ZBOOT_ROM_BSS=0x0
58CONFIG_CPU_IDLE=y 58CONFIG_CPU_IDLE=y
59CONFIG_CPU_IDLE_KIRKWOOD=y
60CONFIG_NET=y 59CONFIG_NET=y
61CONFIG_PACKET=y 60CONFIG_PACKET=y
62CONFIG_UNIX=y 61CONFIG_UNIX=y
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index d533e2695f0e..a783a6314b4f 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -6,7 +6,6 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include <linux/clockchips.h>
10#include <linux/cpuidle.h> 9#include <linux/cpuidle.h>
11#include <linux/module.h> 10#include <linux/module.h>
12#include <asm/cpuidle.h> 11#include <asm/cpuidle.h>
@@ -21,10 +20,6 @@ static DEFINE_SPINLOCK(master_lock);
21static int imx6q_enter_wait(struct cpuidle_device *dev, 20static int imx6q_enter_wait(struct cpuidle_device *dev,
22 struct cpuidle_driver *drv, int index) 21 struct cpuidle_driver *drv, int index)
23{ 22{
24 int cpu = dev->cpu;
25
26 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
27
28 if (atomic_inc_return(&master) == num_online_cpus()) { 23 if (atomic_inc_return(&master) == num_online_cpus()) {
29 /* 24 /*
30 * With this lock, we prevent other cpu to exit and enter 25 * With this lock, we prevent other cpu to exit and enter
@@ -43,22 +38,10 @@ idle:
43 cpu_do_idle(); 38 cpu_do_idle();
44done: 39done:
45 atomic_dec(&master); 40 atomic_dec(&master);
46 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
47 41
48 return index; 42 return index;
49} 43}
50 44
51/*
52 * For each cpu, setup the broadcast timer because local timer
53 * stops for the states other than WFI.
54 */
55static void imx6q_setup_broadcast_timer(void *arg)
56{
57 int cpu = smp_processor_id();
58
59 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
60}
61
62static struct cpuidle_driver imx6q_cpuidle_driver = { 45static struct cpuidle_driver imx6q_cpuidle_driver = {
63 .name = "imx6q_cpuidle", 46 .name = "imx6q_cpuidle",
64 .owner = THIS_MODULE, 47 .owner = THIS_MODULE,
@@ -70,7 +53,8 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {
70 { 53 {
71 .exit_latency = 50, 54 .exit_latency = 50,
72 .target_residency = 75, 55 .target_residency = 75,
73 .flags = CPUIDLE_FLAG_TIME_VALID, 56 .flags = CPUIDLE_FLAG_TIME_VALID |
57 CPUIDLE_FLAG_TIMER_STOP,
74 .enter = imx6q_enter_wait, 58 .enter = imx6q_enter_wait,
75 .name = "WAIT", 59 .name = "WAIT",
76 .desc = "Clock off", 60 .desc = "Clock off",
@@ -88,8 +72,5 @@ int __init imx6q_cpuidle_init(void)
88 /* Set chicken bit to get a reliable WAIT mode support */ 72 /* Set chicken bit to get a reliable WAIT mode support */
89 imx6q_set_chicken_bit(); 73 imx6q_set_chicken_bit();
90 74
91 /* Configure the broadcast timer on each cpu */
92 on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1);
93
94 return imx_cpuidle_init(&imx6q_cpuidle_driver); 75 return imx_cpuidle_init(&imx6q_cpuidle_driver);
95} 76}
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index d639aef0deda..f4b1b234939e 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -14,7 +14,6 @@
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
19#include <asm/proc-fns.h> 18#include <asm/proc-fns.h>
20 19
@@ -82,7 +81,6 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
82 int index) 81 int index)
83{ 82{
84 struct omap4_idle_statedata *cx = &omap4_idle_data[index]; 83 struct omap4_idle_statedata *cx = &omap4_idle_data[index];
85 int cpu_id = smp_processor_id();
86 84
87 local_fiq_disable(); 85 local_fiq_disable();
88 86
@@ -109,8 +107,6 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
109 } 107 }
110 } 108 }
111 109
112 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
113
114 /* 110 /*
115 * Call idle CPU PM enter notifier chain so that 111 * Call idle CPU PM enter notifier chain so that
116 * VFP and per CPU interrupt context is saved. 112 * VFP and per CPU interrupt context is saved.
@@ -152,8 +148,6 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
152 if (omap4_mpuss_read_prev_context_state()) 148 if (omap4_mpuss_read_prev_context_state())
153 cpu_cluster_pm_exit(); 149 cpu_cluster_pm_exit();
154 150
155 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
156
157fail: 151fail:
158 cpuidle_coupled_parallel_barrier(dev, &abort_barrier); 152 cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
159 cpu_done[dev->cpu] = false; 153 cpu_done[dev->cpu] = false;
@@ -163,16 +157,6 @@ fail:
163 return index; 157 return index;
164} 158}
165 159
166/*
167 * For each cpu, setup the broadcast timer because local timers
168 * stops for the states above C1.
169 */
170static void omap_setup_broadcast_timer(void *arg)
171{
172 int cpu = smp_processor_id();
173 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
174}
175
176static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); 160static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
177 161
178static struct cpuidle_driver omap4_idle_driver = { 162static struct cpuidle_driver omap4_idle_driver = {
@@ -193,7 +177,8 @@ static struct cpuidle_driver omap4_idle_driver = {
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 |
181 CPUIDLE_FLAG_TIMER_STOP,
197 .enter = omap4_enter_idle_coupled, 182 .enter = omap4_enter_idle_coupled,
198 .name = "C2", 183 .name = "C2",
199 .desc = "MPUSS CSWR", 184 .desc = "MPUSS CSWR",
@@ -202,7 +187,8 @@ static struct cpuidle_driver omap4_idle_driver = {
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 |
191 CPUIDLE_FLAG_TIMER_STOP,
206 .enter = omap4_enter_idle_coupled, 192 .enter = omap4_enter_idle_coupled,
207 .name = "C3", 193 .name = "C3",
208 .desc = "MPUSS OSWR", 194 .desc = "MPUSS OSWR",
@@ -236,9 +222,6 @@ int __init omap4_idle_init(void)
236 if (!cpu_clkdm[0] || !cpu_clkdm[1]) 222 if (!cpu_clkdm[0] || !cpu_clkdm[1])
237 return -ENODEV; 223 return -ENODEV;
238 224
239 /* Configure the broadcast timer on each cpu */
240 on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
241
242 for_each_cpu(cpu_id, cpu_online_mask) { 225 for_each_cpu(cpu_id, cpu_online_mask) {
243 dev = &per_cpu(omap4_idle_dev, cpu_id); 226 dev = &per_cpu(omap4_idle_dev, cpu_id);
244 dev->cpu = cpu_id; 227 dev->cpu = cpu_id;
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c
index ce9149302cc3..1b16d9ebecda 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>
@@ -30,8 +29,6 @@ static inline int ux500_enter_idle(struct cpuidle_device *dev,
30 int this_cpu = smp_processor_id(); 29 int this_cpu = smp_processor_id();
31 bool recouple = false; 30 bool recouple = false;
32 31
33 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu);
34
35 if (atomic_inc_return(&master) == num_online_cpus()) { 32 if (atomic_inc_return(&master) == num_online_cpus()) {
36 33
37 /* With this lock, we prevent the other cpu to exit and enter 34 /* With this lock, we prevent the other cpu to exit and enter
@@ -91,8 +88,6 @@ out:
91 spin_unlock(&master_lock); 88 spin_unlock(&master_lock);
92 } 89 }
93 90
94 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &this_cpu);
95
96 return index; 91 return index;
97} 92}
98 93
@@ -106,7 +101,8 @@ static struct cpuidle_driver ux500_idle_driver = {
106 .enter = ux500_enter_idle, 101 .enter = ux500_enter_idle,
107 .exit_latency = 70, 102 .exit_latency = 70,
108 .target_residency = 260, 103 .target_residency = 260,
109 .flags = CPUIDLE_FLAG_TIME_VALID, 104 .flags = CPUIDLE_FLAG_TIME_VALID |
105 CPUIDLE_FLAG_TIMER_STOP,
110 .name = "ApIdle", 106 .name = "ApIdle",
111 .desc = "ARM Retention", 107 .desc = "ARM Retention",
112 }, 108 },
@@ -115,16 +111,6 @@ static struct cpuidle_driver ux500_idle_driver = {
115 .state_count = 2, 111 .state_count = 2,
116}; 112};
117 113
118/*
119 * For each cpu, setup the broadcast timer because we will
120 * need to migrate the timers for the states >= ApIdle.
121 */
122static void ux500_setup_broadcast_timer(void *arg)
123{
124 int cpu = smp_processor_id();
125 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
126}
127
128int __init ux500_idle_init(void) 114int __init ux500_idle_init(void)
129{ 115{
130 int ret, cpu; 116 int ret, cpu;
@@ -134,13 +120,6 @@ int __init ux500_idle_init(void)
134 prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | 120 prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
135 PRCMU_WAKEUP(ABB)); 121 PRCMU_WAKEUP(ABB));
136 122
137 /*
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); 123 ret = cpuidle_register_driver(&ux500_idle_driver);
145 if (ret) { 124 if (ret) {
146 printk(KERN_ERR "failed to register ux500 idle driver\n"); 125 printk(KERN_ERR "failed to register ux500 idle driver\n");
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 071e2c3eec4f..c4cc27e5c8a5 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -39,10 +39,4 @@ config CPU_IDLE_CALXEDA
39 help 39 help
40 Select this to enable cpuidle on Calxeda processors. 40 Select this to enable cpuidle on Calxeda processors.
41 41
42config CPU_IDLE_KIRKWOOD
43 bool "CPU Idle Driver for Kirkwood processors"
44 depends on ARCH_KIRKWOOD
45 help
46 Select this to enable cpuidle on Kirkwood processors.
47
48endif 42endif
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 24c6e7d945ed..0d8bd55e776f 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -6,4 +6,4 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
6obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o 6obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
7 7
8obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o 8obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o
9obj-$(CONFIG_CPU_IDLE_KIRKWOOD) += cpuidle-kirkwood.o 9obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o
diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c
index 670aa1e55cd6..53aad7324965 100644
--- a/drivers/cpuidle/cpuidle-kirkwood.c
+++ b/drivers/cpuidle/cpuidle-kirkwood.c
@@ -66,9 +66,9 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev)
66 if (res == NULL) 66 if (res == NULL)
67 return -EINVAL; 67 return -EINVAL;
68 68
69 ddr_operation_base = devm_request_and_ioremap(&pdev->dev, res); 69 ddr_operation_base = devm_ioremap_resource(&pdev->dev, res);
70 if (!ddr_operation_base) 70 if (IS_ERR(ddr_operation_base))
71 return -EADDRNOTAVAIL; 71 return PTR_ERR(ddr_operation_base);
72 72
73 device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); 73 device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
74 device->state_count = KIRKWOOD_MAX_STATES; 74 device->state_count = KIRKWOOD_MAX_STATES;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index eba69290e074..c50037029184 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>
@@ -146,12 +147,20 @@ int cpuidle_idle_call(void)
146 147
147 trace_cpu_idle_rcuidle(next_state, dev->cpu); 148 trace_cpu_idle_rcuidle(next_state, dev->cpu);
148 149
150 if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
151 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
152 &dev->cpu);
153
149 if (cpuidle_state_is_coupled(dev, drv, next_state)) 154 if (cpuidle_state_is_coupled(dev, drv, next_state))
150 entered_state = cpuidle_enter_state_coupled(dev, drv, 155 entered_state = cpuidle_enter_state_coupled(dev, drv,
151 next_state); 156 next_state);
152 else 157 else
153 entered_state = cpuidle_enter_state(dev, drv, next_state); 158 entered_state = cpuidle_enter_state(dev, drv, next_state);
154 159
160 if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
161 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
162 &dev->cpu);
163
155 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); 164 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
156 165
157 /* give the governor an opportunity to reflect on the outcome */ 166 /* give the governor an opportunity to reflect on the outcome */
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 422c7b69ba7c..8dfaaae94444 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -11,6 +11,8 @@
11#include <linux/mutex.h> 11#include <linux/mutex.h>
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/cpuidle.h> 13#include <linux/cpuidle.h>
14#include <linux/cpumask.h>
15#include <linux/clockchips.h>
14 16
15#include "cpuidle.h" 17#include "cpuidle.h"
16 18
@@ -19,9 +21,28 @@ DEFINE_SPINLOCK(cpuidle_driver_lock);
19static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); 21static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
20static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); 22static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
21 23
22static void __cpuidle_driver_init(struct cpuidle_driver *drv) 24static void cpuidle_setup_broadcast_timer(void *arg)
23{ 25{
26 int cpu = smp_processor_id();
27 clockevents_notify((long)(arg), &cpu);
28}
29
30static void __cpuidle_driver_init(struct cpuidle_driver *drv, int cpu)
31{
32 int i;
33
24 drv->refcnt = 0; 34 drv->refcnt = 0;
35
36 for (i = drv->state_count - 1; i >= 0 ; i--) {
37
38 if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP))
39 continue;
40
41 drv->bctimer = 1;
42 on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer,
43 (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1);
44 break;
45 }
25} 46}
26 47
27static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) 48static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
@@ -35,7 +56,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
35 if (__cpuidle_get_cpu_driver(cpu)) 56 if (__cpuidle_get_cpu_driver(cpu))
36 return -EBUSY; 57 return -EBUSY;
37 58
38 __cpuidle_driver_init(drv); 59 __cpuidle_driver_init(drv, cpu);
39 60
40 __cpuidle_set_cpu_driver(drv, cpu); 61 __cpuidle_set_cpu_driver(drv, cpu);
41 62
@@ -49,6 +70,12 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
49 70
50 if (!WARN_ON(drv->refcnt > 0)) 71 if (!WARN_ON(drv->refcnt > 0))
51 __cpuidle_set_cpu_driver(NULL, cpu); 72 __cpuidle_set_cpu_driver(NULL, cpu);
73
74 if (drv->bctimer) {
75 drv->bctimer = 0;
76 on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer,
77 (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1);
78 }
52} 79}
53 80
54#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS 81#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 66346521cb65..f9fd93758333 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -8,6 +8,20 @@
8#ifndef _LINUX_CLOCKCHIPS_H 8#ifndef _LINUX_CLOCKCHIPS_H
9#define _LINUX_CLOCKCHIPS_H 9#define _LINUX_CLOCKCHIPS_H
10 10
11/* Clock event notification values */
12enum clock_event_nofitiers {
13 CLOCK_EVT_NOTIFY_ADD,
14 CLOCK_EVT_NOTIFY_BROADCAST_ON,
15 CLOCK_EVT_NOTIFY_BROADCAST_OFF,
16 CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
17 CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
18 CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
19 CLOCK_EVT_NOTIFY_SUSPEND,
20 CLOCK_EVT_NOTIFY_RESUME,
21 CLOCK_EVT_NOTIFY_CPU_DYING,
22 CLOCK_EVT_NOTIFY_CPU_DEAD,
23};
24
11#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD 25#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
12 26
13#include <linux/clocksource.h> 27#include <linux/clocksource.h>
@@ -26,20 +40,6 @@ enum clock_event_mode {
26 CLOCK_EVT_MODE_RESUME, 40 CLOCK_EVT_MODE_RESUME,
27}; 41};
28 42
29/* Clock event notification values */
30enum clock_event_nofitiers {
31 CLOCK_EVT_NOTIFY_ADD,
32 CLOCK_EVT_NOTIFY_BROADCAST_ON,
33 CLOCK_EVT_NOTIFY_BROADCAST_OFF,
34 CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
35 CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
36 CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
37 CLOCK_EVT_NOTIFY_SUSPEND,
38 CLOCK_EVT_NOTIFY_RESUME,
39 CLOCK_EVT_NOTIFY_CPU_DYING,
40 CLOCK_EVT_NOTIFY_CPU_DEAD,
41};
42
43/* 43/*
44 * Clock event features 44 * Clock event features
45 */ 45 */
@@ -173,7 +173,7 @@ extern int tick_receive_broadcast(void);
173#ifdef CONFIG_GENERIC_CLOCKEVENTS 173#ifdef CONFIG_GENERIC_CLOCKEVENTS
174extern void clockevents_notify(unsigned long reason, void *arg); 174extern void clockevents_notify(unsigned long reason, void *arg);
175#else 175#else
176# define clockevents_notify(reason, arg) do { } while (0) 176static inline void clockevents_notify(unsigned long reason, void *arg) {}
177#endif 177#endif
178 178
179#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */ 179#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
@@ -181,7 +181,7 @@ extern void clockevents_notify(unsigned long reason, void *arg);
181static inline void clockevents_suspend(void) {} 181static inline void clockevents_suspend(void) {}
182static inline void clockevents_resume(void) {} 182static inline void clockevents_resume(void) {}
183 183
184#define clockevents_notify(reason, arg) do { } while (0) 184static inline void clockevents_notify(unsigned long reason, void *arg) {}
185 185
186#endif 186#endif
187 187
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 480c14dc1ddd..fc3e5808b7ff 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
@@ -106,6 +107,8 @@ struct cpuidle_driver {
106 107
107 /* set to 1 to use the core cpuidle time keeping (for all states). */ 108 /* set to 1 to use the core cpuidle time keeping (for all states). */
108 unsigned int en_core_tk_irqen:1; 109 unsigned int en_core_tk_irqen:1;
110 /* used by the cpuidle framework to setup the broadcast timer */
111 unsigned int bctimer:1;
109 /* states array must be ordered in decreasing power consumption */ 112 /* states array must be ordered in decreasing power consumption */
110 struct cpuidle_state states[CPUIDLE_STATE_MAX]; 113 struct cpuidle_state states[CPUIDLE_STATE_MAX];
111 int state_count; 114 int state_count;