| /* | |
| * linux/arch/unicore32/kernel/sleep.S | |
| * | |
| * Code specific to PKUnity SoC and UniCore ISA | |
| * | |
| * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> | |
| * Copyright (C) 2001-2010 Guan Xuetao | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License version 2 as | |
| * published by the Free Software Foundation. | |
| */ | |
| #include <linux/linkage.h> | |
| #include <asm/assembler.h> | |
| #include <mach/hardware.h> | |
| .text | |
| pkunity_cpu_save_cp: | |
| @ get coprocessor registers | |
| movc r3, p0.c7, #0 @ PID | |
| movc r4, p0.c2, #0 @ translation table base addr | |
| movc r5, p0.c1, #0 @ control reg | |
| @ store them plus current virtual stack ptr on stack | |
| mov r6, sp | |
| stm.w (r3 - r6), [sp-] | |
| mov pc, lr | |
| pkunity_cpu_save_sp: | |
| @ preserve phys address of stack | |
| mov r0, sp | |
| stw.w lr, [sp+], #-4 | |
| b.l sleep_phys_sp | |
| ldw r1, =sleep_save_sp | |
| stw r0, [r1] | |
| ldw.w pc, [sp]+, #4 | |
| /* | |
| * puv3_cpu_suspend() | |
| * | |
| * Forces CPU into sleep state. | |
| * | |
| * r0 = value for PWRMODE M field for desired sleep state | |
| */ | |
| ENTRY(puv3_cpu_suspend) | |
| stm.w (r16 - r27, lr), [sp-] @ save registers on stack | |
| stm.w (r4 - r15), [sp-] @ save registers on stack | |
| #ifdef CONFIG_UNICORE_FPU_F64 | |
| sfm.w (f0 - f7 ), [sp-] | |
| sfm.w (f8 - f15), [sp-] | |
| sfm.w (f16 - f23), [sp-] | |
| sfm.w (f24 - f31), [sp-] | |
| cff r4, s31 | |
| stm.w (r4), [sp-] | |
| #endif | |
| b.l pkunity_cpu_save_cp | |
| b.l pkunity_cpu_save_sp | |
| @ clean data cache | |
| mov r1, #0 | |
| movc p0.c5, r1, #14 | |
| nop | |
| nop | |
| nop | |
| nop | |
| @ DDR2 BaseAddr | |
| ldw r0, =(PKUNITY_DDR2CTRL_BASE) | |
| @ PM BaseAddr | |
| ldw r1, =(PKUNITY_PM_BASE) | |
| @ set PLL_SYS_CFG reg, 275 | |
| movl r6, #0x00002401 | |
| stw r6, [r1+], #0x18 | |
| @ set PLL_DDR_CFG reg, 66MHz | |
| movl r6, #0x00100c00 | |
| stw r6, [r1+], #0x1c | |
| @ set wake up source | |
| movl r8, #0x800001ff @ epip4d | |
| stw r8, [r1+], #0xc | |
| @ set PGSR | |
| movl r5, #0x40000 | |
| stw r5, [r1+], #0x10 | |
| @ prepare DDR2 refresh settings | |
| ldw r5, [r0+], #0x24 | |
| or r5, r5, #0x00000001 | |
| @ prepare PMCR for PLL changing | |
| movl r6, #0xc | |
| @ prepare for closing PLL | |
| movl r7, #0x1 | |
| @ prepare sleep mode | |
| mov r8, #0x1 | |
| @ movl r0, 0x11111111 | |
| @ put_word_ocd r0 | |
| b pkunity_cpu_do_suspend | |
| .ltorg | |
| .align 5 | |
| pkunity_cpu_do_suspend: | |
| b 101f | |
| @ put DDR2 into self-refresh | |
| 100: stw r5, [r0+], #0x24 | |
| @ change PLL | |
| stw r6, [r1] | |
| b 1f | |
| .ltorg | |
| .align 5 | |
| 101: b 102f | |
| @ wait for PLL changing complete | |
| 1: ldw r6, [r1+], #0x44 | |
| csub.a r6, #0x1 | |
| bne 1b | |
| b 2f | |
| .ltorg | |
| .align 5 | |
| 102: b 100b | |
| @ close PLL | |
| 2: stw r7, [r1+], #0x4 | |
| @ enter sleep mode | |
| stw r8, [r1] | |
| 3: b 3b | |
| /* | |
| * puv3_cpu_resume() | |
| * | |
| * entry point from bootloader into kernel during resume | |
| * | |
| * Note: Yes, part of the following code is located into the .data section. | |
| * This is to allow sleep_save_sp to be accessed with a relative load | |
| * while we can't rely on any MMU translation. We could have put | |
| * sleep_save_sp in the .text section as well, but some setups might | |
| * insist on it to be truly read-only. | |
| */ | |
| .data | |
| .align 5 | |
| ENTRY(puv3_cpu_resume) | |
| @ movl r0, 0x20202020 | |
| @ put_word_ocd r0 | |
| ldw r0, sleep_save_sp @ stack phys addr | |
| ldw r2, =resume_after_mmu @ its absolute virtual address | |
| ldm (r3 - r6), [r0]+ @ CP regs + virt stack ptr | |
| mov sp, r6 @ CP regs + virt stack ptr | |
| mov r1, #0 | |
| movc p0.c6, r1, #6 @ invalidate I & D TLBs | |
| movc p0.c5, r1, #28 @ invalidate I & D caches, BTB | |
| movc p0.c7, r3, #0 @ PID | |
| movc p0.c2, r4, #0 @ translation table base addr | |
| movc p0.c1, r5, #0 @ control reg, turn on mmu | |
| nop | |
| jump r2 | |
| nop | |
| nop | |
| nop | |
| nop | |
| nop | |
| sleep_save_sp: | |
| .word 0 @ preserve stack phys ptr here | |
| .text | |
| resume_after_mmu: | |
| @ movl r0, 0x30303030 | |
| @ put_word_ocd r0 | |
| #ifdef CONFIG_UNICORE_FPU_F64 | |
| lfm.w (f0 - f7 ), [sp]+ | |
| lfm.w (f8 - f15), [sp]+ | |
| lfm.w (f16 - f23), [sp]+ | |
| lfm.w (f24 - f31), [sp]+ | |
| ldm.w (r4), [sp]+ | |
| ctf r4, s31 | |
| #endif | |
| ldm.w (r4 - r15), [sp]+ @ restore registers from stack | |
| ldm.w (r16 - r27, pc), [sp]+ @ return to caller |