diff options
author | Santosh Shilimkar <santosh.shilimkar@ti.com> | 2010-06-16 12:49:48 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2011-12-08 14:29:00 -0500 |
commit | b5b4f2881f619460fdb165111bac10a3dd8eebee (patch) | |
tree | 2f41f00e91f11ef77ff47dd0f65fc31b67aeb9c7 | |
parent | a6e48358d15fec2f3f9e86a6d6fc62422141a3a9 (diff) |
ARM: OMAP4: PM: Program CPU1 to hit OFF when off-lined
Program non-boot CPUs to hit lowest supported power state
when it is off-lined using cpu hotplug framework.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Tested-by: Vishwanath BS <vishwanath.bs@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
-rw-r--r-- | arch/arm/mach-omap2/common.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-hotplug.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-wakeupgen.c | 32 |
4 files changed, 80 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 36cdba7727f2..c078db1b3de8 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h | |||
@@ -200,6 +200,7 @@ extern int omap4_mpuss_init(void); | |||
200 | extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state); | 200 | extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state); |
201 | extern int omap4_finish_suspend(unsigned long cpu_state); | 201 | extern int omap4_finish_suspend(unsigned long cpu_state); |
202 | extern void omap4_cpu_resume(void); | 202 | extern void omap4_cpu_resume(void); |
203 | extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); | ||
203 | #else | 204 | #else |
204 | static inline int omap4_enter_lowpower(unsigned int cpu, | 205 | static inline int omap4_enter_lowpower(unsigned int cpu, |
205 | unsigned int power_state) | 206 | unsigned int power_state) |
@@ -208,6 +209,12 @@ static inline int omap4_enter_lowpower(unsigned int cpu, | |||
208 | return 0; | 209 | return 0; |
209 | } | 210 | } |
210 | 211 | ||
212 | static inline int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) | ||
213 | { | ||
214 | cpu_do_idle(); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
211 | static inline int omap4_mpuss_init(void) | 218 | static inline int omap4_mpuss_init(void) |
212 | { | 219 | { |
213 | return 0; | 220 | return 0; |
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index e5a1c3f40a86..adbe4d8c7caf 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #include "common.h" | 23 | #include "common.h" |
24 | 24 | ||
25 | #include "powerdomain.h" | ||
26 | |||
25 | int platform_cpu_kill(unsigned int cpu) | 27 | int platform_cpu_kill(unsigned int cpu) |
26 | { | 28 | { |
27 | return 1; | 29 | return 1; |
@@ -33,6 +35,8 @@ int platform_cpu_kill(unsigned int cpu) | |||
33 | */ | 35 | */ |
34 | void platform_cpu_die(unsigned int cpu) | 36 | void platform_cpu_die(unsigned int cpu) |
35 | { | 37 | { |
38 | unsigned int this_cpu; | ||
39 | |||
36 | flush_cache_all(); | 40 | flush_cache_all(); |
37 | dsb(); | 41 | dsb(); |
38 | 42 | ||
@@ -40,15 +44,15 @@ void platform_cpu_die(unsigned int cpu) | |||
40 | * we're ready for shutdown now, so do it | 44 | * we're ready for shutdown now, so do it |
41 | */ | 45 | */ |
42 | if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0) | 46 | if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0) |
43 | printk(KERN_CRIT "Secure clear status failed\n"); | 47 | pr_err("Secure clear status failed\n"); |
44 | 48 | ||
45 | for (;;) { | 49 | for (;;) { |
46 | /* | 50 | /* |
47 | * Execute WFI | 51 | * Enter into low power state |
48 | */ | 52 | */ |
49 | do_wfi(); | 53 | omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF); |
50 | 54 | this_cpu = smp_processor_id(); | |
51 | if (omap_read_auxcoreboot0() == cpu) { | 55 | if (omap_read_auxcoreboot0() == this_cpu) { |
52 | /* | 56 | /* |
53 | * OK, proper wakeup, we're done | 57 | * OK, proper wakeup, we're done |
54 | */ | 58 | */ |
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 867fee51e42c..9c1c12b8c5e1 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c | |||
@@ -192,6 +192,38 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) | |||
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
194 | 194 | ||
195 | /** | ||
196 | * omap4_hotplug_cpu: OMAP4 CPU hotplug entry | ||
197 | * @cpu : CPU ID | ||
198 | * @power_state: CPU low power state. | ||
199 | */ | ||
200 | int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) | ||
201 | { | ||
202 | unsigned int cpu_state = 0; | ||
203 | |||
204 | if (omap_rev() == OMAP4430_REV_ES1_0) | ||
205 | return -ENXIO; | ||
206 | |||
207 | if (power_state == PWRDM_POWER_OFF) | ||
208 | cpu_state = 1; | ||
209 | |||
210 | clear_cpu_prev_pwrst(cpu); | ||
211 | set_cpu_next_pwrst(cpu, power_state); | ||
212 | set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup)); | ||
213 | scu_pwrst_prepare(cpu, power_state); | ||
214 | |||
215 | /* | ||
216 | * CPU never retuns back if targetted power state is OFF mode. | ||
217 | * CPU ONLINE follows normal CPU ONLINE ptah via | ||
218 | * omap_secondary_startup(). | ||
219 | */ | ||
220 | omap4_finish_suspend(cpu_state); | ||
221 | |||
222 | set_cpu_next_pwrst(cpu, PWRDM_POWER_ON); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | |||
195 | /* | 227 | /* |
196 | * Initialise OMAP4 MPUSS | 228 | * Initialise OMAP4 MPUSS |
197 | */ | 229 | */ |
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index a8a8d0efe350..701dfecad64b 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c | |||
@@ -180,6 +180,36 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set) | |||
180 | spin_unlock_irqrestore(&wakeupgen_lock, flags); | 180 | spin_unlock_irqrestore(&wakeupgen_lock, flags); |
181 | } | 181 | } |
182 | 182 | ||
183 | #ifdef CONFIG_HOTPLUG_CPU | ||
184 | static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self, | ||
185 | unsigned long action, void *hcpu) | ||
186 | { | ||
187 | unsigned int cpu = (unsigned int)hcpu; | ||
188 | |||
189 | switch (action) { | ||
190 | case CPU_ONLINE: | ||
191 | wakeupgen_irqmask_all(cpu, 0); | ||
192 | break; | ||
193 | case CPU_DEAD: | ||
194 | wakeupgen_irqmask_all(cpu, 1); | ||
195 | break; | ||
196 | } | ||
197 | return NOTIFY_OK; | ||
198 | } | ||
199 | |||
200 | static struct notifier_block __refdata irq_hotplug_notifier = { | ||
201 | .notifier_call = irq_cpu_hotplug_notify, | ||
202 | }; | ||
203 | |||
204 | static void __init irq_hotplug_init(void) | ||
205 | { | ||
206 | register_hotcpu_notifier(&irq_hotplug_notifier); | ||
207 | } | ||
208 | #else | ||
209 | static void __init irq_hotplug_init(void) | ||
210 | {} | ||
211 | #endif | ||
212 | |||
183 | /* | 213 | /* |
184 | * Initialise the wakeupgen module. | 214 | * Initialise the wakeupgen module. |
185 | */ | 215 | */ |
@@ -222,5 +252,7 @@ int __init omap_wakeupgen_init(void) | |||
222 | for (i = 0; i < NR_IRQS; i++) | 252 | for (i = 0; i < NR_IRQS; i++) |
223 | irq_target_cpu[i] = boot_cpu; | 253 | irq_target_cpu[i] = boot_cpu; |
224 | 254 | ||
255 | irq_hotplug_init(); | ||
256 | |||
225 | return 0; | 257 | return 0; |
226 | } | 258 | } |