[PATCH 2/6] ARM: pm: add generic CPU suspend/resume support

Colin Cross ccross at google.com
Thu Feb 17 15:05:59 EST 2011


On Thu, Feb 17, 2011 at 2:41 AM, Lorenzo Pieralisi
<lorenzo.pieralisi at arm.com> wrote:
> Colin,
>
> On Tue, 2011-02-15 at 16:26 -0800, Colin Cross wrote:
>> On Tue, Feb 15, 2011 at 3:04 AM, Russell King - ARM Linux
>> <linux at arm.linux.org.uk> wrote:
>> > On Fri, Feb 11, 2011 at 06:50:57PM -0800, Colin Cross wrote:
>> >> > +ENDPROC(cpu_resume_turn_mmu_on)
>> >> > +cpu_resume_after_mmu:
>> >> > +       str     r5, [r2, r4, lsl #2]    @ restore old mapping
>> >> > +#ifdef MULTI_CACHE
>> >> > +       ldr     r10, =cpu_cache
>> >> > +       ldr     pc, [r10, #CACHE_FLUSH_KERN_ALL]
>> >> > +#else
>> >> > +       b       __cpuc_flush_kern_all
>> >> > +#endif
>> >
>> > I think we can eliminate this cache flush by delaying the cache enable
>> > as below.  Could you see whether Tegra 2 survives this please?
>> > Thanks.
>> >
>> > diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
>> > index bed1876..193be5f 100644
>> > --- a/arch/arm/kernel/sleep.S
>> > +++ b/arch/arm/kernel/sleep.S
>> > @@ -4,6 +4,7 @@
>> >  #include <asm/assembler.h>
>> >  #include <asm/glue-cache.h>
>> >  #include <asm/glue-proc.h>
>> > +#include <asm/system.h>
>> >        .text
>> >
>> >  /*
>> > @@ -81,25 +82,22 @@ ENTRY(cpu_resume_mmu)
>> >        str     r3, [r2, r4, lsl #2]    @ setup 1:1 mapping for mmu code
>> >        sub     r2, r2, r1
>> >        ldr     r3, =cpu_resume_after_mmu
>> > +       bic     r1, r0, #CR_C           @ ensure D-cache is disabled
>> >        b       cpu_resume_turn_mmu_on
>> >  ENDPROC(cpu_resume_mmu)
>> >        .ltorg
>> >        .align  5
>> >  cpu_resume_turn_mmu_on:
>> > -       mcr     p15, 0, r0, c1, c0, 0   @ turn on MMU, caches, etc
>> > -       mrc     p15, 0, r0, c0, c0, 0   @ read id reg
>> > -       mov     r0, r0
>> > -       mov     r0, r0
>> > +       mcr     p15, 0, r1, c1, c0, 0   @ turn on MMU, I-cache, etc
>> > +       mrc     p15, 0, r1, c0, c0, 0   @ read id reg
>> > +       mov     r1, r1
>> > +       mov     r1, r1
>> >        mov     pc, r3                  @ jump to virtual address
>> >  ENDPROC(cpu_resume_turn_mmu_on)
>> >  cpu_resume_after_mmu:
>> >        str     r5, [r2, r4, lsl #2]    @ restore old mapping
>> > -#ifdef MULTI_CACHE
>> > -       ldr     r10, =cpu_cache
>> > -       ldr     pc, [r10, #CACHE_FLUSH_KERN_ALL]
>> > -#else
>> > -       b       __cpuc_flush_kern_all
>> > -#endif
>> > +       mcr     p15, 0, r0, c1, c0, 0   @ turn on D-cache
>> > +       mov     pc, lr
>> >
>> >  /*
>> >  * Note: Yes, part of the following code is located into the .data section.
>> >
>> >
>>
>> Tested-by: Colin Cross <ccross at android.com>
>>
>> Works for Tegra 2 cpuidle and suspend.
>>
>
> When calling suspend from cpuidle, do you flush the stack (ie CPU
> context) from L2 using outer_cache functions ? This has to be done when
> one CPU is shut down with L2 enabled for the MMU off resume path to work
> properly.
Tegra2 has the power rails of the two cpus tied together, so the cpu
that suspends first only needs to go through cpu_resume if the other
cpu has also suspended and flushed the entire L2 cache.  On platforms
that can power gate the cpus individually you will need to flush the
stack and stack pointer in cpu_suspend.  I have a patch that does the
flushes in cpu_suspend, but it failed on the way back up because the
page table modifications got lost behind the L2, and I haven't retried
it since Russell fixed that.

> I think that on resume you invalidate L1 in the reset vector before
> jumping to cpu_resume, correct ?
I manually invalidate the L1 Dcache, but not the Icache.



More information about the linux-arm-kernel mailing list