1/* 2 * linux/arch/unicore32/kernel/sleep.S 3 * 4 * Code specific to PKUnity SoC and UniCore ISA 5 * 6 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> 7 * Copyright (C) 2001-2010 Guan Xuetao 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14#include <linux/linkage.h> 15#include <asm/assembler.h> 16#include <mach/hardware.h> 17 18 .text 19 20pkunity_cpu_save_cp: 21 22 @ get coprocessor registers 23 24 movc r3, p0.c7, #0 @ PID 25 movc r4, p0.c2, #0 @ translation table base addr 26 movc r5, p0.c1, #0 @ control reg 27 28 29 @ store them plus current virtual stack ptr on stack 30 mov r6, sp 31 stm.w (r3 - r6), [sp-] 32 33 mov pc, lr 34 35pkunity_cpu_save_sp: 36 @ preserve phys address of stack 37 mov r0, sp 38 stw.w lr, [sp+], #-4 39 b.l sleep_phys_sp 40 ldw r1, =sleep_save_sp 41 stw r0, [r1] 42 ldw.w pc, [sp]+, #4 43 44/* 45 * puv3_cpu_suspend() 46 * 47 * Forces CPU into sleep state. 48 * 49 * r0 = value for PWRMODE M field for desired sleep state 50 */ 51 52ENTRY(puv3_cpu_suspend) 53 stm.w (r16 - r27, lr), [sp-] @ save registers on stack 54 stm.w (r4 - r15), [sp-] @ save registers on stack 55 56#ifdef CONFIG_UNICORE_FPU_F64 57 sfm.w (f0 - f7 ), [sp-] 58 sfm.w (f8 - f15), [sp-] 59 sfm.w (f16 - f23), [sp-] 60 sfm.w (f24 - f31), [sp-] 61 cff r4, s31 62 stm.w (r4), [sp-] 63#endif 64 b.l pkunity_cpu_save_cp 65 66 b.l pkunity_cpu_save_sp 67 68 @ clean data cache 69 mov r1, #0 70 movc p0.c5, r1, #14 71 nop 72 nop 73 nop 74 nop 75 76 77 78 @ DDR2 BaseAddr 79 ldw r0, =(PKUNITY_DDR2CTRL_BASE) 80 81 @ PM BaseAddr 82 ldw r1, =(PKUNITY_PM_BASE) 83 84 @ set PLL_SYS_CFG reg, 275 85 movl r6, #0x00002401 86 stw r6, [r1+], #0x18 87 @ set PLL_DDR_CFG reg, 66MHz 88 movl r6, #0x00100c00 89 stw r6, [r1+], #0x1c 90 91 @ set wake up source 92 movl r8, #0x800001ff @ epip4d 93 stw r8, [r1+], #0xc 94 95 @ set PGSR 96 movl r5, #0x40000 97 stw r5, [r1+], #0x10 98 99 @ prepare DDR2 refresh settings 100 ldw r5, [r0+], #0x24 101 or r5, r5, #0x00000001 102 103 @ prepare PMCR for PLL changing 104 movl r6, #0xc 105 106 @ prepare for closing PLL 107 movl r7, #0x1 108 109 @ prepare sleep mode 110 mov r8, #0x1 111 112@ movl r0, 0x11111111 113@ put_word_ocd r0 114 b pkunity_cpu_do_suspend 115 116 .ltorg 117 .align 5 118pkunity_cpu_do_suspend: 119 b 101f 120 @ put DDR2 into self-refresh 121100: stw r5, [r0+], #0x24 122 @ change PLL 123 stw r6, [r1] 124 b 1f 125 126 .ltorg 127 .align 5 128101: b 102f 129 @ wait for PLL changing complete 1301: ldw r6, [r1+], #0x44 131 csub.a r6, #0x1 132 bne 1b 133 b 2f 134 135 .ltorg 136 .align 5 137102: b 100b 138 @ close PLL 1392: stw r7, [r1+], #0x4 140 @ enter sleep mode 141 stw r8, [r1] 1423: b 3b 143 144 145 146 147/* 148 * puv3_cpu_resume() 149 * 150 * entry point from bootloader into kernel during resume 151 * 152 * Note: Yes, part of the following code is located into the .data section. 153 * This is to allow sleep_save_sp to be accessed with a relative load 154 * while we can't rely on any MMU translation. We could have put 155 * sleep_save_sp in the .text section as well, but some setups might 156 * insist on it to be truly read-only. 157 */ 158 159 .data 160 .align 5 161ENTRY(puv3_cpu_resume) 162@ movl r0, 0x20202020 163@ put_word_ocd r0 164 165 ldw r0, sleep_save_sp @ stack phys addr 166 ldw r2, =resume_after_mmu @ its absolute virtual address 167 ldm (r3 - r6), [r0]+ @ CP regs + virt stack ptr 168 mov sp, r6 @ CP regs + virt stack ptr 169 170 mov r1, #0 171 movc p0.c6, r1, #6 @ invalidate I & D TLBs 172 movc p0.c5, r1, #28 @ invalidate I & D caches, BTB 173 174 movc p0.c7, r3, #0 @ PID 175 movc p0.c2, r4, #0 @ translation table base addr 176 movc p0.c1, r5, #0 @ control reg, turn on mmu 177 nop 178 jump r2 179 nop 180 nop 181 nop 182 nop 183 nop 184 185sleep_save_sp: 186 .word 0 @ preserve stack phys ptr here 187 188 .text 189resume_after_mmu: 190@ movl r0, 0x30303030 191@ put_word_ocd r0 192 193#ifdef CONFIG_UNICORE_FPU_F64 194 lfm.w (f0 - f7 ), [sp]+ 195 lfm.w (f8 - f15), [sp]+ 196 lfm.w (f16 - f23), [sp]+ 197 lfm.w (f24 - f31), [sp]+ 198 ldm.w (r4), [sp]+ 199 ctf r4, s31 200#endif 201 ldm.w (r4 - r15), [sp]+ @ restore registers from stack 202 ldm.w (r16 - r27, pc), [sp]+ @ return to caller 203