/*
* Save CPU state for a suspend
+ * r0 = phys addr of temporary page tables
* r1 = v:p offset
* r2 = suspend function arg0
* r3 = suspend function
*/
ENTRY(__cpu_suspend)
stmfd sp!, {r4 - r11, lr}
+ mov r4, r0
#ifdef MULTI_CPU
ldr r10, =processor
ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
sub sp, sp, r5 @ allocate CPU state on stack
mov r0, sp @ save pointer to CPU save block
add ip, ip, r1 @ convert resume fn to phys
- stmfd sp!, {r6, ip} @ save virt SP, phys resume fn
+ stmfd sp!, {r4, r6, ip} @ save phys pgd, virt SP, phys resume fn
ldr r5, =sleep_save_sp
add r6, sp, r1 @ convert SP to phys
stmfd sp!, {r2, r3} @ save suspend func arg and pointer
.ltorg
cpu_suspend_abort:
- ldmia sp!, {r2 - r3} @ pop virt SP, phys resume fn
+ ldmia sp!, {r1 - r3} @ pop phys pgd, virt SP, phys resume fn
teq r0, #0
moveq r0, #1 @ force non-zero value
mov sp, r2
/*
* r0 = control register value
- * r1 = v:p offset (preserved by cpu_do_resume)
- * r2 = phys page table base
- * r3 = L1 section flags
*/
ENTRY(cpu_resume_mmu)
ldr r3, =cpu_resume_after_mmu
ldr r0, sleep_save_sp @ stack phys addr
#endif
setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off
- @ load stack, resume fn
- ARM( ldmia r0!, {sp, pc} )
-THUMB( ldmia r0!, {r2, r3} )
-THUMB( mov sp, r2 )
-THUMB( bx r3 )
+ @ load phys pgd, stack, resume fn
+ ARM( ldmia r0!, {r1, sp, pc} )
+THUMB( ldmia r0!, {r1, r2, r3} )
+THUMB( mov sp, r2 )
+THUMB( bx r3 )
ENDPROC(cpu_resume)
sleep_save_sp:
return -EINVAL;
/*
- * Temporarily switch the page tables to our suspend page
- * tables, which contain the temporary identity mapping
- * required for resuming.
+ * Provide a temporary page table with an identity mapping for
+ * the MMU-enable code, required for resuming. On successful
+ * resume (indicated by a zero return code), we need to switch
+ * back to the correct page tables.
*/
- cpu_switch_mm(suspend_pgd, mm);
- ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
- cpu_switch_mm(mm->pgd, mm);
- local_flush_tlb_all();
+ ret = __cpu_suspend(virt_to_phys(suspend_pgd),
+ PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+ if (ret == 0) {
+ cpu_switch_mm(mm->pgd, mm);
+ local_flush_tlb_all();
+ }
return ret;
}
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm920_suspend_size
-.equ cpu_arm920_suspend_size, 4 * 4
+.equ cpu_arm920_suspend_size, 4 * 3
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_arm920_do_suspend)
- stmfd sp!, {r4 - r7, lr}
+ stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c13, c0, 0 @ PID
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
- mrc p15, 0, r6, c2, c0, 0 @ TTB address
- mrc p15, 0, r7, c1, c0, 0 @ Control register
- stmia r0, {r4 - r7}
- ldmfd sp!, {r4 - r7, pc}
+ mrc p15, 0, r6, c1, c0, 0 @ Control register
+ stmia r0, {r4 - r6}
+ ldmfd sp!, {r4 - r6, pc}
ENDPROC(cpu_arm920_do_suspend)
ENTRY(cpu_arm920_do_resume)
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs
mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches
- ldmia r0, {r4 - r7}
+ ldmia r0, {r4 - r6}
mcr p15, 0, r4, c13, c0, 0 @ PID
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
- mcr p15, 0, r6, c2, c0, 0 @ TTB address
- mov r0, r7 @ control register
+ mcr p15, 0, r1, c2, c0, 0 @ TTB address
+ mov r0, r6 @ control register
b cpu_resume_mmu
ENDPROC(cpu_arm920_do_resume)
#endif
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm926_suspend_size
-.equ cpu_arm926_suspend_size, 4 * 4
+.equ cpu_arm926_suspend_size, 4 * 3
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_arm926_do_suspend)
- stmfd sp!, {r4 - r7, lr}
+ stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c13, c0, 0 @ PID
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
- mrc p15, 0, r6, c2, c0, 0 @ TTB address
- mrc p15, 0, r7, c1, c0, 0 @ Control register
- stmia r0, {r4 - r7}
- ldmfd sp!, {r4 - r7, pc}
+ mrc p15, 0, r6, c1, c0, 0 @ Control register
+ stmia r0, {r4 - r6}
+ ldmfd sp!, {r4 - r6, pc}
ENDPROC(cpu_arm926_do_suspend)
ENTRY(cpu_arm926_do_resume)
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs
mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches
- ldmia r0, {r4 - r7}
+ ldmia r0, {r4 - r6}
mcr p15, 0, r4, c13, c0, 0 @ PID
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
- mcr p15, 0, r6, c2, c0, 0 @ TTB address
- mov r0, r7 @ control register
+ mcr p15, 0, r1, c2, c0, 0 @ TTB address
+ mov r0, r6 @ control register
b cpu_resume_mmu
ENDPROC(cpu_arm926_do_resume)
#endif
mov pc, lr
.globl cpu_sa1100_suspend_size
-.equ cpu_sa1100_suspend_size, 4*4
+.equ cpu_sa1100_suspend_size, 4 * 3
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_sa1100_do_suspend)
- stmfd sp!, {r4 - r7, lr}
+ stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c3, c0, 0 @ domain ID
- mrc p15, 0, r5, c2, c0, 0 @ translation table base addr
- mrc p15, 0, r6, c13, c0, 0 @ PID
- mrc p15, 0, r7, c1, c0, 0 @ control reg
- stmia r0, {r4 - r7} @ store cp regs
- ldmfd sp!, {r4 - r7, pc}
+ mrc p15, 0, r5, c13, c0, 0 @ PID
+ mrc p15, 0, r6, c1, c0, 0 @ control reg
+ stmia r0, {r4 - r6} @ store cp regs
+ ldmfd sp!, {r4 - r6, pc}
ENDPROC(cpu_sa1100_do_suspend)
ENTRY(cpu_sa1100_do_resume)
- ldmia r0, {r4 - r7} @ load cp regs
+ ldmia r0, {r4 - r6} @ load cp regs
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ flush I+D TLBs
mcr p15, 0, ip, c7, c7, 0 @ flush I&D cache
mcr p15, 0, ip, c9, c0, 5 @ allow user space to use RB
mcr p15, 0, r4, c3, c0, 0 @ domain ID
- mcr p15, 0, r5, c2, c0, 0 @ translation table base addr
- mcr p15, 0, r6, c13, c0, 0 @ PID
- mov r0, r7 @ control register
+ mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r5, c13, c0, 0 @ PID
+ mov r0, r6 @ control register
b cpu_resume_mmu
ENDPROC(cpu_sa1100_do_resume)
#endif
/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
.globl cpu_v6_suspend_size
-.equ cpu_v6_suspend_size, 4 * 8
+.equ cpu_v6_suspend_size, 4 * 7
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_v6_do_suspend)
- stmfd sp!, {r4 - r11, lr}
+ stmfd sp!, {r4 - r10, lr}
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
mrc p15, 0, r5, c13, c0, 1 @ Context ID
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
- mrc p15, 0, r7, c2, c0, 0 @ Translation table base 0
- mrc p15, 0, r8, c2, c0, 1 @ Translation table base 1
- mrc p15, 0, r9, c1, c0, 1 @ auxiliary control register
- mrc p15, 0, r10, c1, c0, 2 @ co-processor access control
- mrc p15, 0, r11, c1, c0, 0 @ control register
- stmia r0, {r4 - r11}
- ldmfd sp!, {r4- r11, pc}
+ mrc p15, 0, r7, c2, c0, 1 @ Translation table base 1
+ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control register
+ mrc p15, 0, r9, c1, c0, 2 @ co-processor access control
+ mrc p15, 0, r10, c1, c0, 0 @ control register
+ stmia r0, {r4 - r10}
+ ldmfd sp!, {r4- r10, pc}
ENDPROC(cpu_v6_do_suspend)
ENTRY(cpu_v6_do_resume)
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcr p15, 0, ip, c7, c15, 0 @ clean+invalidate cache
mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
- ldmia r0, {r4 - r11}
+ ldmia r0, {r4 - r10}
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
mcr p15, 0, r5, c13, c0, 1 @ Context ID
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
- mcr p15, 0, r7, c2, c0, 0 @ Translation table base 0
- mcr p15, 0, r8, c2, c0, 1 @ Translation table base 1
- mcr p15, 0, r9, c1, c0, 1 @ auxiliary control register
- mcr p15, 0, r10, c1, c0, 2 @ co-processor access control
+ ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
+ ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
+ mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0
+ mcr p15, 0, r7, c2, c0, 1 @ Translation table base 1
+ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control register
+ mcr p15, 0, r9, c1, c0, 2 @ co-processor access control
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
mcr p15, 0, ip, c7, c5, 4 @ ISB
- mov r0, r11 @ control register
+ mov r0, r10 @ control register
b cpu_resume_mmu
ENDPROC(cpu_v6_do_resume)
#endif
/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
.globl cpu_v7_suspend_size
-.equ cpu_v7_suspend_size, 4 * 9
+.equ cpu_v7_suspend_size, 4 * 8
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_v7_do_suspend)
- stmfd sp!, {r4 - r11, lr}
+ stmfd sp!, {r4 - r10, lr}
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
mrc p15, 0, r5, c13, c0, 1 @ Context ID
mrc p15, 0, r6, c13, c0, 3 @ User r/o thread ID
stmia r0!, {r4 - r6}
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
- mrc p15, 0, r7, c2, c0, 0 @ TTB 0
- mrc p15, 0, r8, c2, c0, 1 @ TTB 1
- mrc p15, 0, r9, c1, c0, 0 @ Control register
- mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
- mrc p15, 0, r11, c1, c0, 2 @ Co-processor access control
- stmia r0, {r6 - r11}
- ldmfd sp!, {r4 - r11, pc}
+ mrc p15, 0, r7, c2, c0, 1 @ TTB 1
+ mrc p15, 0, r8, c1, c0, 0 @ Control register
+ mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
+ mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
+ stmia r0, {r6 - r10}
+ ldmfd sp!, {r4 - r10, pc}
ENDPROC(cpu_v7_do_suspend)
ENTRY(cpu_v7_do_resume)
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
mcr p15, 0, r5, c13, c0, 1 @ Context ID
mcr p15, 0, r6, c13, c0, 3 @ User r/o thread ID
- ldmia r0, {r6 - r11}
+ ldmia r0, {r6 - r10}
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
- mcr p15, 0, r7, c2, c0, 0 @ TTB 0
- mcr p15, 0, r8, c2, c0, 1 @ TTB 1
+ ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
+ ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
+ mcr p15, 0, r1, c2, c0, 0 @ TTB 0
+ mcr p15, 0, r7, c2, c0, 1 @ TTB 1
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
- teq r4, r10 @ Is it already set?
- mcrne p15, 0, r10, c1, c0, 1 @ No, so write it
- mcr p15, 0, r11, c1, c0, 2 @ Co-processor access control
+ teq r4, r9 @ Is it already set?
+ mcrne p15, 0, r9, c1, c0, 1 @ No, so write it
+ mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control
ldr r4, =PRRR @ PRRR
ldr r5, =NMRR @ NMRR
mcr p15, 0, r4, c10, c2, 0 @ write PRRR
mcr p15, 0, r5, c10, c2, 1 @ write NMRR
isb
dsb
- mov r0, r9 @ control register
+ mov r0, r8 @ control register
b cpu_resume_mmu
ENDPROC(cpu_v7_do_resume)
#endif
.align
.globl cpu_xsc3_suspend_size
-.equ cpu_xsc3_suspend_size, 4 * 7
+.equ cpu_xsc3_suspend_size, 4 * 6
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_xsc3_do_suspend)
- stmfd sp!, {r4 - r10, lr}
+ stmfd sp!, {r4 - r9, lr}
mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
mrc p15, 0, r5, c15, c1, 0 @ CP access reg
mrc p15, 0, r6, c13, c0, 0 @ PID
mrc p15, 0, r7, c3, c0, 0 @ domain ID
- mrc p15, 0, r8, c2, c0, 0 @ translation table base addr
- mrc p15, 0, r9, c1, c0, 1 @ auxiliary control reg
- mrc p15, 0, r10, c1, c0, 0 @ control reg
+ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+ mrc p15, 0, r9, c1, c0, 0 @ control reg
bic r4, r4, #2 @ clear frequency change bit
- stmia r0, {r4 - r10} @ store cp regs
- ldmia sp!, {r4 - r10, pc}
+ stmia r0, {r4 - r9} @ store cp regs
+ ldmia sp!, {r4 - r9, pc}
ENDPROC(cpu_xsc3_do_suspend)
ENTRY(cpu_xsc3_do_resume)
- ldmia r0, {r4 - r10} @ load cp regs
+ ldmia r0, {r4 - r9} @ load cp regs
mov ip, #0
mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB
mcr p15, 0, ip, c7, c10, 4 @ drain write (&fill) buffer
mcr p15, 0, r5, c15, c1, 0 @ CP access reg
mcr p15, 0, r6, c13, c0, 0 @ PID
mcr p15, 0, r7, c3, c0, 0 @ domain ID
- mcr p15, 0, r8, c2, c0, 0 @ translation table base addr
- mcr p15, 0, r9, c1, c0, 1 @ auxiliary control reg
- mov r0, r10 @ control register
+ orr r1, r1, #0x18 @ cache the page table in L2
+ mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+ mov r0, r9 @ control register
b cpu_resume_mmu
ENDPROC(cpu_xsc3_do_resume)
#endif
.align
.globl cpu_xscale_suspend_size
-.equ cpu_xscale_suspend_size, 4 * 7
+.equ cpu_xscale_suspend_size, 4 * 6
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_xscale_do_suspend)
- stmfd sp!, {r4 - r10, lr}
+ stmfd sp!, {r4 - r9, lr}
mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
mrc p15, 0, r5, c15, c1, 0 @ CP access reg
mrc p15, 0, r6, c13, c0, 0 @ PID
mrc p15, 0, r7, c3, c0, 0 @ domain ID
- mrc p15, 0, r8, c2, c0, 0 @ translation table base addr
- mrc p15, 0, r9, c1, c1, 0 @ auxiliary control reg
- mrc p15, 0, r10, c1, c0, 0 @ control reg
+ mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg
+ mrc p15, 0, r9, c1, c0, 0 @ control reg
bic r4, r4, #2 @ clear frequency change bit
- stmia r0, {r4 - r10} @ store cp regs
- ldmfd sp!, {r4 - r10, pc}
+ stmia r0, {r4 - r9} @ store cp regs
+ ldmfd sp!, {r4 - r9, pc}
ENDPROC(cpu_xscale_do_suspend)
ENTRY(cpu_xscale_do_resume)
- ldmia r0, {r4 - r10} @ load cp regs
+ ldmia r0, {r4 - r9} @ load cp regs
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB
mcr p15, 0, r5, c15, c1, 0 @ CP access reg
mcr p15, 0, r6, c13, c0, 0 @ PID
mcr p15, 0, r7, c3, c0, 0 @ domain ID
- mcr p15, 0, r8, c2, c0, 0 @ translation table base addr
- mcr p15, 0, r9, c1, c1, 0 @ auxiliary control reg
- mov r0, r10 @ control register
+ mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg
+ mov r0, r9 @ control register
b cpu_resume_mmu
ENDPROC(cpu_xscale_do_resume)
#endif