aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ux500/cpuidle.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ux500/cpuidle.c')
-rw-r--r--arch/arm/mach-ux500/cpuidle.c58
1 files changed, 3 insertions, 55 deletions
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c
index 654115afb367..317a2be129fb 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>
@@ -25,7 +24,6 @@
25 24
26static atomic_t master = ATOMIC_INIT(0); 25static atomic_t master = ATOMIC_INIT(0);
27static DEFINE_SPINLOCK(master_lock); 26static DEFINE_SPINLOCK(master_lock);
28static DEFINE_PER_CPU(struct cpuidle_device, ux500_cpuidle_device);
29 27
30static inline int ux500_enter_idle(struct cpuidle_device *dev, 28static inline int ux500_enter_idle(struct cpuidle_device *dev,
31 struct cpuidle_driver *drv, int index) 29 struct cpuidle_driver *drv, int index)
@@ -33,8 +31,6 @@ static inline int ux500_enter_idle(struct cpuidle_device *dev,
33 int this_cpu = smp_processor_id(); 31 int this_cpu = smp_processor_id();
34 bool recouple = false; 32 bool recouple = false;
35 33
36 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu);
37
38 if (atomic_inc_return(&master) == num_online_cpus()) { 34 if (atomic_inc_return(&master) == num_online_cpus()) {
39 35
40 /* With this lock, we prevent the other cpu to exit and enter 36 /* With this lock, we prevent the other cpu to exit and enter
@@ -94,22 +90,20 @@ out:
94 spin_unlock(&master_lock); 90 spin_unlock(&master_lock);
95 } 91 }
96 92
97 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &this_cpu);
98
99 return index; 93 return index;
100} 94}
101 95
102static struct cpuidle_driver ux500_idle_driver = { 96static struct cpuidle_driver ux500_idle_driver = {
103 .name = "ux500_idle", 97 .name = "ux500_idle",
104 .owner = THIS_MODULE, 98 .owner = THIS_MODULE,
105 .en_core_tk_irqen = 1,
106 .states = { 99 .states = {
107 ARM_CPUIDLE_WFI_STATE, 100 ARM_CPUIDLE_WFI_STATE,
108 { 101 {
109 .enter = ux500_enter_idle, 102 .enter = ux500_enter_idle,
110 .exit_latency = 70, 103 .exit_latency = 70,
111 .target_residency = 260, 104 .target_residency = 260,
112 .flags = CPUIDLE_FLAG_TIME_VALID, 105 .flags = CPUIDLE_FLAG_TIME_VALID |
106 CPUIDLE_FLAG_TIMER_STOP,
113 .name = "ApIdle", 107 .name = "ApIdle",
114 .desc = "ARM Retention", 108 .desc = "ARM Retention",
115 }, 109 },
@@ -118,59 +112,13 @@ static struct cpuidle_driver ux500_idle_driver = {
118 .state_count = 2, 112 .state_count = 2,
119}; 113};
120 114
121/*
122 * For each cpu, setup the broadcast timer because we will
123 * need to migrate the timers for the states >= ApIdle.
124 */
125static void ux500_setup_broadcast_timer(void *arg)
126{
127 int cpu = smp_processor_id();
128 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
129}
130
131int __init ux500_idle_init(void) 115int __init ux500_idle_init(void)
132{ 116{
133 int ret, cpu;
134 struct cpuidle_device *device;
135
136 /* Configure wake up reasons */ 117 /* Configure wake up reasons */
137 prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | 118 prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
138 PRCMU_WAKEUP(ABB)); 119 PRCMU_WAKEUP(ABB));
139 120
140 /* 121 return cpuidle_register(&ux500_idle_driver, NULL);
141 * Configure the timer broadcast for each cpu, that must
142 * be done from the cpu context, so we use a smp cross
143 * call with 'on_each_cpu'.
144 */
145 on_each_cpu(ux500_setup_broadcast_timer, NULL, 1);
146
147 ret = cpuidle_register_driver(&ux500_idle_driver);
148 if (ret) {
149 printk(KERN_ERR "failed to register ux500 idle driver\n");
150 return ret;
151 }
152
153 for_each_online_cpu(cpu) {
154 device = &per_cpu(ux500_cpuidle_device, cpu);
155 device->cpu = cpu;
156 ret = cpuidle_register_device(device);
157 if (ret) {
158 printk(KERN_ERR "Failed to register cpuidle "
159 "device for cpu%d\n", cpu);
160 goto out_unregister;
161 }
162 }
163out:
164 return ret;
165
166out_unregister:
167 for_each_online_cpu(cpu) {
168 device = &per_cpu(ux500_cpuidle_device, cpu);
169 cpuidle_unregister_device(device);
170 }
171
172 cpuidle_unregister_driver(&ux500_idle_driver);
173 goto out;
174} 122}
175 123
176device_initcall(ux500_idle_init); 124device_initcall(ux500_idle_init);