Message ID | 1364205910-32392-9-git-send-email-santosh.shilimkar@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Santosh Shilimkar <santosh.shilimkar@ti.com> writes: > Add power management code to handle the CPU off mode to enable CPUP hotplug > mode for OMAP5 devices. Separate suspend finisher is used for OMAP5(Cortex-A15) > because it doesn't use SCU power status register and external PL310 L2 cache > which makes code flow bit different. > > Acked-by: Nishanth Menon <nm@ti.com> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> [...] > @@ -436,14 +445,21 @@ int __init omap4_mpuss_init(void) > > if (cpu_is_omap44xx()) { > omap_pm_ops.finish_suspend = omap4_finish_suspend; > + omap_pm_ops.hotplug_restart = omap_secondary_startup; > omap_pm_ops.resume = omap4_cpu_resume; > omap_pm_ops.scu_prepare = scu_pwrst_prepare; > cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; > } else if (soc_is_omap54xx()) { > + omap_pm_ops.finish_suspend = omap5_finish_suspend; > + omap_pm_ops.hotplug_restart = omap5_secondary_startup; > cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; > enable_mercury_retention_mode(); > } > > + /* Over-write the OMAP4 hook to take care of ROM BUG */ > + if (cpu_is_omap446x()) > + omap_pm_ops.hotplug_restart = omap_secondary_startup_4460; A couple nits... I think this would go better at the end of the 'if omap44xx' block above. Also, while you're hear, maybe it's time to rename the current secondary startup functions to match the new one. IOW omap4_..., omap4460_... and omap5_... Kevin
On Thursday 04 April 2013 02:19 AM, Kevin Hilman wrote: > Santosh Shilimkar <santosh.shilimkar@ti.com> writes: > >> Add power management code to handle the CPU off mode to enable CPUP hotplug >> mode for OMAP5 devices. Separate suspend finisher is used for OMAP5(Cortex-A15) >> because it doesn't use SCU power status register and external PL310 L2 cache >> which makes code flow bit different. >> >> Acked-by: Nishanth Menon <nm@ti.com> >> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> > > [...] > >> @@ -436,14 +445,21 @@ int __init omap4_mpuss_init(void) >> >> if (cpu_is_omap44xx()) { >> omap_pm_ops.finish_suspend = omap4_finish_suspend; >> + omap_pm_ops.hotplug_restart = omap_secondary_startup; >> omap_pm_ops.resume = omap4_cpu_resume; >> omap_pm_ops.scu_prepare = scu_pwrst_prepare; >> cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; >> } else if (soc_is_omap54xx()) { >> + omap_pm_ops.finish_suspend = omap5_finish_suspend; >> + omap_pm_ops.hotplug_restart = omap5_secondary_startup; >> cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; >> enable_mercury_retention_mode(); >> } >> >> + /* Over-write the OMAP4 hook to take care of ROM BUG */ >> + if (cpu_is_omap446x()) >> + omap_pm_ops.hotplug_restart = omap_secondary_startup_4460; > > A couple nits... > > I think this would go better at the end of the 'if omap44xx' block > above. > Nishant commented on this as well. The indentation was looking ugly and I thought its better to have this BUG hunk separate. I prefer it this way though if you really insist, i have to change it. > Also, while you're hear, maybe it's time to rename the current secondary > startup functions to match the new one. IOW omap4_..., omap4460_... and omap5_... > Good idea. Will do it in a separate patch since these have been there in few files. Regards, Santosh
Santosh Shilimkar <santosh.shilimkar@ti.com> writes: > On Thursday 04 April 2013 02:19 AM, Kevin Hilman wrote: >> Santosh Shilimkar <santosh.shilimkar@ti.com> writes: >> >>> Add power management code to handle the CPU off mode to enable CPUP hotplug >>> mode for OMAP5 devices. Separate suspend finisher is used for OMAP5(Cortex-A15) >>> because it doesn't use SCU power status register and external PL310 L2 cache >>> which makes code flow bit different. >>> >>> Acked-by: Nishanth Menon <nm@ti.com> >>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> >> >> [...] >> >>> @@ -436,14 +445,21 @@ int __init omap4_mpuss_init(void) >>> >>> if (cpu_is_omap44xx()) { >>> omap_pm_ops.finish_suspend = omap4_finish_suspend; >>> + omap_pm_ops.hotplug_restart = omap_secondary_startup; >>> omap_pm_ops.resume = omap4_cpu_resume; >>> omap_pm_ops.scu_prepare = scu_pwrst_prepare; >>> cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; >>> } else if (soc_is_omap54xx()) { >>> + omap_pm_ops.finish_suspend = omap5_finish_suspend; >>> + omap_pm_ops.hotplug_restart = omap5_secondary_startup; >>> cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; >>> enable_mercury_retention_mode(); >>> } >>> >>> + /* Over-write the OMAP4 hook to take care of ROM BUG */ >>> + if (cpu_is_omap446x()) >>> + omap_pm_ops.hotplug_restart = omap_secondary_startup_4460; >> >> A couple nits... >> >> I think this would go better at the end of the 'if omap44xx' block >> above. >> > Nishant commented on this as well. The indentation was looking ugly > and I thought its better to have this BUG hunk separate. I prefer > it this way though if you really insist, i have to change it. I insist. >> Also, while you're hear, maybe it's time to rename the current secondary >> startup functions to match the new one. IOW omap4_..., omap4460_... and omap5_... >> > Good idea. Will do it in a separate patch since these have been there in few > files. OK. Thanks, Kevin
On Thursday 04 April 2013 11:01 PM, Kevin Hilman wrote: > Santosh Shilimkar <santosh.shilimkar@ti.com> writes: > >> On Thursday 04 April 2013 02:19 AM, Kevin Hilman wrote: >>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes: >>> >>>> Add power management code to handle the CPU off mode to enable CPUP hotplug >>>> mode for OMAP5 devices. Separate suspend finisher is used for OMAP5(Cortex-A15) >>>> because it doesn't use SCU power status register and external PL310 L2 cache >>>> which makes code flow bit different. >>>> >>>> Acked-by: Nishanth Menon <nm@ti.com> >>>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> >>> >>> [...] >>> >>>> @@ -436,14 +445,21 @@ int __init omap4_mpuss_init(void) >>>> >>>> if (cpu_is_omap44xx()) { >>>> omap_pm_ops.finish_suspend = omap4_finish_suspend; >>>> + omap_pm_ops.hotplug_restart = omap_secondary_startup; >>>> omap_pm_ops.resume = omap4_cpu_resume; >>>> omap_pm_ops.scu_prepare = scu_pwrst_prepare; >>>> cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; >>>> } else if (soc_is_omap54xx()) { >>>> + omap_pm_ops.finish_suspend = omap5_finish_suspend; >>>> + omap_pm_ops.hotplug_restart = omap5_secondary_startup; >>>> cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; >>>> enable_mercury_retention_mode(); >>>> } >>>> >>>> + /* Over-write the OMAP4 hook to take care of ROM BUG */ >>>> + if (cpu_is_omap446x()) >>>> + omap_pm_ops.hotplug_restart = omap_secondary_startup_4460; >>> >>> A couple nits... >>> >>> I think this would go better at the end of the 'if omap44xx' block >>> above. >>> >> Nishant commented on this as well. The indentation was looking ugly >> and I thought its better to have this BUG hunk separate. I prefer >> it this way though if you really insist, i have to change it. > > I insist. > Will update the patch accordingly then. Regards, Santosh
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index d390d18..096f489 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -81,6 +81,7 @@ struct omap4_cpu_pm_info { * @finish_suspend: CPU suspend finisher function pointer * @resume: CPU resume function pointer * @scu_prepare: CPU Snoop Control program function pointer + * @hotplug_restart: CPU hotplug restart kernel hook pointer * * Structure holds functions pointer for CPU low power operations like * suspend, resume and scu programming. @@ -89,10 +90,12 @@ struct cpu_pm_ops { int (*finish_suspend)(unsigned long cpu_state); void (*resume)(void); void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state); + void (*hotplug_restart)(void); }; extern int omap4_finish_suspend(unsigned long cpu_state); extern void omap4_cpu_resume(void); +extern int omap5_finish_suspend(unsigned long cpu_state); static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); static struct powerdomain *mpuss_pd; @@ -115,6 +118,7 @@ struct cpu_pm_ops omap_pm_ops = { .finish_suspend = default_finish_suspend, .resume = dummy_cpu_resume, .scu_prepare = dummy_scu_prepare, + .hotplug_restart = dummy_cpu_resume, }; /* @@ -327,7 +331,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); - set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup)); + set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart)); omap_pm_ops.scu_prepare(cpu, power_state); /* @@ -370,6 +374,7 @@ static void enable_mercury_retention_mode(void) int __init omap4_mpuss_init(void) { struct omap4_cpu_pm_info *pm_info; + u32 cpu_wakeup_addr = 0; if (omap_rev() == OMAP4430_REV_ES1_0) { WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); @@ -379,9 +384,13 @@ int __init omap4_mpuss_init(void) sar_base = omap4_get_sar_ram_base(); /* Initilaise per CPU PM information */ + if (cpu_is_omap44xx()) + cpu_wakeup_addr = CPU0_WAKEUP_NS_PA_ADDR_OFFSET; + else if (soc_is_omap54xx()) + cpu_wakeup_addr = OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET; pm_info = &per_cpu(omap4_pm_info, 0x0); pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; - pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; + pm_info->wkup_sar_addr = sar_base + cpu_wakeup_addr; pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm"); if (!pm_info->pwrdm) { @@ -396,14 +405,14 @@ int __init omap4_mpuss_init(void) /* Initialise CPU0 power domain state to ON */ pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); + if (cpu_is_omap44xx()) + cpu_wakeup_addr = CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + else if (soc_is_omap54xx()) + cpu_wakeup_addr = OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET; pm_info = &per_cpu(omap4_pm_info, 0x1); pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; - pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + pm_info->wkup_sar_addr = sar_base + cpu_wakeup_addr; pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; - if (cpu_is_omap446x()) - pm_info->secondary_startup = omap_secondary_startup_4460; - else - pm_info->secondary_startup = omap_secondary_startup; pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); if (!pm_info->pwrdm) { @@ -436,14 +445,21 @@ int __init omap4_mpuss_init(void) if (cpu_is_omap44xx()) { omap_pm_ops.finish_suspend = omap4_finish_suspend; + omap_pm_ops.hotplug_restart = omap_secondary_startup; omap_pm_ops.resume = omap4_cpu_resume; omap_pm_ops.scu_prepare = scu_pwrst_prepare; cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; } else if (soc_is_omap54xx()) { + omap_pm_ops.finish_suspend = omap5_finish_suspend; + omap_pm_ops.hotplug_restart = omap5_secondary_startup; cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; enable_mercury_retention_mode(); } + /* Over-write the OMAP4 hook to take care of ROM BUG */ + if (cpu_is_omap446x()) + omap_pm_ops.hotplug_restart = omap_secondary_startup_4460; + return 0; } diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h index 82b3c4c..6f4dbee 100644 --- a/arch/arm/mach-omap2/omap-secure.h +++ b/arch/arm/mach-omap2/omap-secure.h @@ -41,6 +41,7 @@ #define OMAP4_MON_L2X0_CTRL_INDEX 0x102 #define OMAP4_MON_L2X0_AUXCTRL_INDEX 0x109 #define OMAP4_MON_L2X0_PREFETCH_INDEX 0x113 +#define OMAP5_MON_CACHES_CLEAN_INDEX 0x103 #define OMAP5_MON_AMBA_IF_INDEX 0x108 diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h index 792b106..5b2966a 100644 --- a/arch/arm/mach-omap2/omap4-sar-layout.h +++ b/arch/arm/mach-omap2/omap4-sar-layout.h @@ -31,6 +31,8 @@ /* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */ #define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04 #define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08 +#define OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xe00 +#define OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xe04 #define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500) #define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504) diff --git a/arch/arm/mach-omap2/sleep_omap4plus.S b/arch/arm/mach-omap2/sleep_omap4plus.S index 88ff83a..5a372a6 100644 --- a/arch/arm/mach-omap2/sleep_omap4plus.S +++ b/arch/arm/mach-omap2/sleep_omap4plus.S @@ -326,6 +326,90 @@ skip_l2en: b cpu_resume @ Jump to generic resume ENDPROC(omap4_cpu_resume) + +/* + * ================================ + * == OMAP5 CPU suspend finisher == + * ================================ + * + * OMAP5 MPUSS states for the context save: + * save_state = + * 0 - Nothing lost and no need to save: MPUSS INA/CSWR + * 1 - CPUx L1 and logic lost: CPU OFF, MPUSS INA/CSWR + */ +ENTRY(omap5_finish_suspend) + stmfd sp!, {r4-r12, lr} + cmp r0, #0x0 + beq do_wfi @ No lowpower state, jump to WFI + + /* + * Flush all data from the L1 data cache before disabling + * SCTLR.C bit. Since we modify stack here, we must clean and + * invalidate the local cache here to avoid stack corruption. + */ + bl omap4_get_sar_ram_base + ldr r9, [r0, #OMAP_TYPE_OFFSET] + cmp r9, #0x1 @ Check for HS device + bne skip_secure_l1_clean_op + mov r0, #0 @ Clean secure L1 + stmfd r13!, {r4-r12, r14} + ldr r12, =OMAP5_MON_CACHES_CLEAN_INDEX + DO_SMC + ldmfd r13!, {r4-r12, r14} +skip_secure_l1_clean_op: + bl v7_flush_dcache_louis + + /* + * Clear the SCTLR.C bit to prevent further data cache + * allocation. + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + isb + + /* + * Clean and invalidate all data from the L1 data cache. The L2 + * duplicate snoop tag RAM for this processor is now empty. This + * prevents any new data cache snoops or data cache maintenance + * operations from other processors in the MPCore device being + * issued to this processor. + */ + bl v7_flush_dcache_louis + + /* + * Take CPU out of Symmetric Multiprocessing (SMP) mode and thus + * preventing the CPU from receiving cache, TLB, or BTB + * maintenance operations broadcast by other CPUs in the cluster. + */ + mrc p15, 0, r0, c1, c1, 2 @ Read NSACR data + tst r0, #(1 << 18) + mrcne p15, 0, r0, c1, c0, 1 + bicne r0, r0, #(1 << 6) @ Disable SMP bit + mcrne p15, 0, r0, c1, c0, 1 + isb + dsb + +do_wfi: + bl omap_do_wfi + + /* + * CPU is here when it failed to enter OFF/DORMANT or + * no low power state was attempted. + */ + mrc p15, 0, r0, c1, c0, 0 + tst r0, #(1 << 2) @ Check C bit enabled? + orreq r0, r0, #(1 << 2) @ Enable the C bit + mcreq p15, 0, r0, c1, c0, 0 + isb + mrc p15, 0, r0, c1, c0, 1 + tst r0, #(1 << 6) @ Check SMP bit enabled? + orreq r0, r0, #(1 << 6) + mcreq p15, 0, r0, c1, c0, 1 + isb + dsb + ldmfd sp!, {r4-r12, pc} +ENDPROC(omap5_finish_suspend) #endif #ifndef CONFIG_OMAP4_ERRATA_I688