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

Reply via email to