diff options
Diffstat (limited to 'arch/arm/mach-ux500/cpuidle.c')
-rw-r--r-- | arch/arm/mach-ux500/cpuidle.c | 58 |
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 | ||
26 | static atomic_t master = ATOMIC_INIT(0); | 25 | static atomic_t master = ATOMIC_INIT(0); |
27 | static DEFINE_SPINLOCK(master_lock); | 26 | static DEFINE_SPINLOCK(master_lock); |
28 | static DEFINE_PER_CPU(struct cpuidle_device, ux500_cpuidle_device); | ||
29 | 27 | ||
30 | static inline int ux500_enter_idle(struct cpuidle_device *dev, | 28 | static 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 | ||
102 | static struct cpuidle_driver ux500_idle_driver = { | 96 | static 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 | */ | ||
125 | static 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 | |||
131 | int __init ux500_idle_init(void) | 115 | int __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 | } | ||
163 | out: | ||
164 | return ret; | ||
165 | |||
166 | out_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 | ||
176 | device_initcall(ux500_idle_init); | 124 | device_initcall(ux500_idle_init); |