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