On Fri, Sep 09, 2011 at 07:41:08PM +0530, Shilimkar, Santosh wrote: > On Fri, Sep 9, 2011 at 7:43 PM, Shawn Guo <shawn....@freescale.com> wrote: > > On Fri, Sep 09, 2011 at 01:39:51PM +0530, Santosh wrote: > >> On Friday 09 September 2011 01:34 PM, Shawn Guo wrote: > >> >Hi Santosh, > >> > > >> >On Sun, Sep 04, 2011 at 07:24:15PM +0530, Santosh Shilimkar wrote: > >> >>This patch adds the CPU0 and CPU1 off mode support. CPUX close switch > >> >>retention (CSWR) is not supported by hardware design. > >> >> > >> >>The CPUx OFF mode isn't supported on OMAP4430 ES1.0 > >> >> > >> >>CPUx sleep code is common for hotplug, suspend and CPUilde. > >> >> > >> >>Signed-off-by: Santosh Shilimkar<santosh.shilim...@ti.com> > >> >>Cc: Kevin Hilman<khil...@ti.com> > >> >>--- > >> >> arch/arm/mach-omap2/Makefile | 3 +- > >> >> arch/arm/mach-omap2/include/mach/omap-secure.h | 8 + > >> >> arch/arm/mach-omap2/include/mach/omap4-common.h | 25 +++ > >> >> arch/arm/mach-omap2/omap-mpuss-lowpower.c | 249 > >> >> +++++++++++++++++++++++ > >> >> arch/arm/mach-omap2/omap-smp.c | 6 + > >> >> arch/arm/mach-omap2/omap4-sar-layout.h | 9 + > >> >> arch/arm/mach-omap2/pm44xx.c | 6 + > >> >> arch/arm/mach-omap2/sleep44xx.S | 213 > >> >> +++++++++++++++++++ > >> >> 8 files changed, 518 insertions(+), 1 deletions(-) > >> >> create mode 100644 arch/arm/mach-omap2/omap-mpuss-lowpower.c > >> >> > >> > > >> >[...] > >> > > >> >>diff --git a/arch/arm/mach-omap2/sleep44xx.S > >> >>b/arch/arm/mach-omap2/sleep44xx.S > >> >>index 049f426..230ab8c 100644 > >> >>--- a/arch/arm/mach-omap2/sleep44xx.S > >> >>+++ b/arch/arm/mach-omap2/sleep44xx.S > >> >>@@ -11,8 +11,221 @@ > >> >> > >> >> #include<linux/linkage.h> > >> >> #include<asm/system.h> > >> >>+#include<asm/smp_scu.h> > >> >>+#include<asm/memory.h> > >> >>+#include<asm/hardware/cache-l2x0.h> > >> >> > >> >>+#include<plat/omap44xx.h> > >> >> #include<mach/omap4-common.h> > >> >>+#include<mach/omap-secure.h> > >> >>+ > >> >>+#include "omap4-sar-layout.h" > >> >>+ > >> >>+#ifdef CONFIG_SMP > >> >>+ > >> >>+.macro DO_SMC > >> >>+ dsb > >> >>+ smc #0 > >> >>+ dsb > >> >>+.endm > >> >>+ > >> >>+ppa_zero_params: > >> >>+ .word 0x0 > >> >>+ > >> >>+/* > >> >>+ * ============================= > >> >>+ * == CPU suspend finisher == > >> >>+ * ============================= > >> >>+ * > >> >>+ * void omap4_finish_suspend(unsigned long cpu_state) > >> >>+ * > >> >>+ * This function code saves the CPU context and performs the CPU > >> >>+ * power down sequence. Calling WFI effectively changes the CPU > >> >>+ * power domains states to the desired target power state. > >> >>+ * > >> >>+ * @cpu_state : contains context save state (r0) > >> >>+ * 0 - No context lost > >> >>+ * 1 - CPUx L1 and logic lost: MPUSS CSWR > >> >>+ * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR > >> >>+ * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF > >> > > >> >I was told by rmk that same as imx6q, omap44xx will retain L2 content > >> >across suspen/resume cycle. Then what does "L2 lost" mean here? Or > >> >what rmk meant is the case cpu_state == 2? > >> > > >> Yes. > >> > >> The last case is entire SOC OFF. We call Device OFF in OMAP. > >> All voltages will scale to 0 V. This isn't supported by this > >> series. > >> > > Then the second question would be what the following patch in this > > series is for. > > > > [PATCH 20/25] OMAP4: PM: Add L2X0 cache lowpower support > > > > I could have read the patch incorrectly, but it seems l2x_clean_inv > > will also be called for "MPUSS OSWR" in which case L2 is retained? > > Shouldn't L2 for this case have been handled by rmk's patch (ARM: pm: > > add L2 cache cleaning for suspend)? > > > Yes you did read it wrongly :) > It won't be called for OSWR > Come on, man. It's really hard for me who is still at entry level of assembly to understand that. So please help me out.
The following is a copy from arch/arm/mach-omap2/sleep44xx.S after I apply this patch series on v3.1-rc4. > /* > * ============================= > * == CPU suspend finisher == > * ============================= > * > * void omap4_finish_suspend(unsigned long cpu_state) > * > * This function code saves the CPU context and performs the CPU > * power down sequence. Calling WFI effectively changes the CPU > * power domains states to the desired target power state. > * > * @cpu_state : contains context save state (r0) So cpu_state is passed in r0. > * 0 - No context lost > * 1 - CPUx L1 and logic lost: MPUSS CSWR > * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR > * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF > * @return: This function never returns for CPU OFF and DORMANT power states. > * Post WFI, CPU transitions to DORMANT or OFF power state and on wake-up > * from this follows a full CPU reset path via ROM code to CPU restore code. > * It returns to the caller for CPU INACTIVE and ON power states or in case > * CPU failed to transition to targeted OFF/DORMANT state. > */ > ENTRY(omap4_finish_suspend) > stmfd sp!, {lr} > cmp r0, #0x0 > beq do_WFI @ No lowpower state, jump to WFI The case "0" is handled here. > > /* > * Flush all data from the L1 data cache before disabling > * SCTLR.C bit. > */ > bl omap4_get_sar_ram_base Isn't r0 lost here? > ldr r9, [r0, #OMAP_TYPE_OFFSET] > cmp r9, #0x1 @ Check for HS device > bne skip_secure_l1_clean > mov r0, #SCU_PM_NORMAL > mov r1, #0xFF @ clean seucre L1 > stmfd r13!, {r4-r12, r14} > ldr r12, =OMAP4_MON_SCU_PWR_INDEX > DO_SMC > ldmfd r13!, {r4-r12, r14} > skip_secure_l1_clean: > > /* > * Clear the SCTLR.C bit to prevent further data cache > * allocation. Clearing SCTLR.C would make all the data accesses > * strongly ordered and would not hit the cache. > */ > mrc p15, 0, r0, c1, c0, 0 > bic r0, r0, #(1 << 2) @ Disable the C bit > mcr p15, 0, r0, c1, c0, 0 > isb > > /* > * Invalidate L1 data cache. Even though only invalidate is > * necessary exported flush API is used here. Doing clean > * on already clean cache would be almost NOP. > */ > bl v7_flush_dcache_all > > /* > * Switch the CPU from Symmetric Multiprocessing (SMP) mode > * to AsymmetricMultiprocessing (AMP) mode by programming > * the SCU power status to DORMANT or OFF mode. > * This enables the CPU to be taken out of coherency by > * preventing the CPU from receiving cache, TLB, or BTB > * maintenance operations broadcast by other CPUs in the cluster. > */ > bl omap4_get_sar_ram_base > mov r8, r0 > ldr r9, [r8, #OMAP_TYPE_OFFSET] > cmp r9, #0x1 @ Check for HS device > bne scu_gp_set > mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR > ands r0, r0, #0x0f > ldreq r0, [r8, #SCU_OFFSET0] > ldrne r0, [r8, #SCU_OFFSET1] > mov r1, #0x00 > stmfd r13!, {r4-r12, r14} > ldr r12, =OMAP4_MON_SCU_PWR_INDEX > DO_SMC > ldmfd r13!, {r4-r12, r14} > b skip_scu_gp_set > scu_gp_set: > mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR > ands r0, r0, #0x0f > ldreq r1, [r8, #SCU_OFFSET0] > ldrne r1, [r8, #SCU_OFFSET1] > bl omap4_get_scu_base > bl scu_power_mode > skip_scu_gp_set: > 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 > #ifdef CONFIG_CACHE_L2X0 > /* > * Clean and invalidate the L2 cache. > * Common cache-l2x0.c functions can't be used here since it > * uses spinlocks. We are out of coherency here with data cache > * disabled. The spinlock implementation uses exclusive load/store > * instruction which can fail without data cache being enabled. > * OMAP4 hardware doesn't support exclusive monitor which can > * overcome exclusive access issue. Because of this, CPU can > * lead to deadlock. > */ > l2x_clean_inv: > bl omap4_get_sar_ram_base > mov r8, r0 > mrc p15, 0, r5, c0, c0, 5 @ Read MPIDR > ands r5, r5, #0x0f > ldreq r0, [r8, #L2X0_SAVE_OFFSET0] > ldrne r0, [r8, #L2X0_SAVE_OFFSET1] > cmp r0, #3 > bne do_WFI It looks like you are bypassing L2 clean and invalidate for cases "1" and "2" here. But I really do not understand how you get r0 back here. Regards, Shawn > #ifdef CONFIG_PL310_ERRATA_727915 > mov r0, #0x03 > mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX > DO_SMC > #endif > bl omap4_get_l2cache_base > mov r2, r0 > ldr r0, =0xffff > str r0, [r2, #L2X0_CLEAN_INV_WAY] > wait: > ldr r0, [r2, #L2X0_CLEAN_INV_WAY] > ldr r1, =0xffff > ands r0, r0, r1 > bne wait > #ifdef CONFIG_PL310_ERRATA_727915 > mov r0, #0x00 > mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX > DO_SMC > #endif > l2x_sync: > bl omap4_get_l2cache_base > mov r2, r0 > mov r0, #0x0 > str r0, [r2, #L2X0_CACHE_SYNC] > sync: > ldr r0, [r2, #L2X0_CACHE_SYNC] > ands r0, r0, #0x1 > bne sync > #endif > > 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 > > /* > * Ensure the CPU power state is set to NORMAL in > * SCU power state so that CPU is back in coherency. > * In non-coherent mode CPU can lock-up and lead to > * system deadlock. > */ > 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 > bl omap4_get_sar_ram_base > mov r8, r0 > ldr r9, [r8, #OMAP_TYPE_OFFSET] > cmp r9, #0x1 @ Check for HS device > bne scu_gp_clear > mov r0, #SCU_PM_NORMAL > mov r1, #0x00 > stmfd r13!, {r4-r12, r14} > ldr r12, =OMAP4_MON_SCU_PWR_INDEX > DO_SMC > ldmfd r13!, {r4-r12, r14} > b skip_scu_gp_clear > scu_gp_clear: > bl omap4_get_scu_base > mov r1, #SCU_PM_NORMAL > bl scu_power_mode > skip_scu_gp_clear: > isb > dsb > ldmfd sp!, {pc} > ENDPROC(omap4_finish_suspend) -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html