[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