1/* 2 * SA11x0 Assembler Sleep/WakeUp Management Routines 3 * 4 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License. 8 * 9 * History: 10 * 11 * 2001-02-06: Cliff Brake Initial code 12 * 13 * 2001-08-29: Nicolas Pitre Simplified. 14 * 15 * 2002-05-27: Nicolas Pitre Revisited, more cleanup and simplification. 16 * Storage is on the stack now. 17 */ 18 19#include <linux/linkage.h> 20#include <asm/assembler.h> 21#include <asm/hardware.h> 22 23 24 25 .text 26 27 28 29/* 30 * sa1100_cpu_suspend() 31 * 32 * Causes sa11x0 to enter sleep state 33 * 34 */ 35 36ENTRY(sa1100_cpu_suspend) 37 38 stmfd sp!, {r4 - r12, lr} @ save registers on stack 39 40 @ get coprocessor registers 41 mrc p15, 0, r4, c3, c0, 0 @ domain ID 42 mrc p15, 0, r5, c2, c0, 0 @ translation table base addr 43 mrc p15, 0, r6, c13, c0, 0 @ PID 44 mrc p15, 0, r7, c1, c0, 0 @ control reg 45 46 @ store them plus current virtual stack ptr on stack 47 mov r8, sp 48 stmfd sp!, {r4 - r8} 49 50 @ preserve phys address of stack 51 mov r0, sp 52 bl sleep_phys_sp 53 ldr r1, =sleep_save_sp 54 str r0, [r1] 55 56 @ clean data cache and invalidate WB 57 bl v4wb_flush_kern_cache_all 58 59 @ disable clock switching 60 mcr p15, 0, r1, c15, c2, 2 61 62 @ Adjust memory timing before lowering CPU clock 63 @ Clock speed adjustment without changing memory timing makes 64 @ CPU hang in some cases 65 ldr r0, =MDREFR 66 ldr r1, [r0] 67 orr r1, r1, #MDREFR_K1DB2 68 str r1, [r0] 69 70 @ delay 90us and set CPU PLL to lowest speed 71 @ fixes resume problem on high speed SA1110 72 mov r0, #90 73 bl __udelay 74 ldr r0, =PPCR 75 mov r1, #0 76 str r1, [r0] 77 mov r0, #90 78 bl __udelay 79 80 /* 81 * SA1110 SDRAM controller workaround. register values: 82 * 83 * r0 = &MSC0 84 * r1 = &MSC1 85 * r2 = &MSC2 86 * r3 = MSC0 value 87 * r4 = MSC1 value 88 * r5 = MSC2 value 89 * r6 = &MDREFR 90 * r7 = first MDREFR value 91 * r8 = second MDREFR value 92 * r9 = &MDCNFG 93 * r10 = MDCNFG value 94 * r11 = third MDREFR value 95 * r12 = &PMCR 96 * r13 = PMCR value (1) 97 */ 98 99 ldr r0, =MSC0 100 ldr r1, =MSC1 101 ldr r2, =MSC2 102 103 ldr r3, [r0] 104 bic r3, r3, #FMsk(MSC_RT) 105 bic r3, r3, #FMsk(MSC_RT)<<16 106 107 ldr r4, [r1] 108 bic r4, r4, #FMsk(MSC_RT) 109 bic r4, r4, #FMsk(MSC_RT)<<16 110 111 ldr r5, [r2] 112 bic r5, r5, #FMsk(MSC_RT) 113 bic r5, r5, #FMsk(MSC_RT)<<16 114 115 ldr r6, =MDREFR 116 117 ldr r7, [r6] 118 bic r7, r7, #0x0000FF00 119 bic r7, r7, #0x000000F0 120 orr r8, r7, #MDREFR_SLFRSH 121 122 ldr r9, =MDCNFG 123 ldr r10, [r9] 124 bic r10, r10, #(MDCNFG_DE0+MDCNFG_DE1) 125 bic r10, r10, #(MDCNFG_DE2+MDCNFG_DE3) 126 127 bic r11, r8, #MDREFR_SLFRSH 128 bic r11, r11, #MDREFR_E1PIN 129 130 ldr r12, =PMCR 131 132 mov r13, #PMCR_SF 133 134 b sa1110_sdram_controller_fix 135 136 .align 5 137sa1110_sdram_controller_fix: 138 139 @ Step 1 clear RT field of all MSCx registers 140 str r3, [r0] 141 str r4, [r1] 142 str r5, [r2] 143 144 @ Step 2 clear DRI field in MDREFR 145 str r7, [r6] 146 147 @ Step 3 set SLFRSH bit in MDREFR 148 str r8, [r6] 149 150 @ Step 4 clear DE bis in MDCNFG 151 str r10, [r9] 152 153 @ Step 5 clear DRAM refresh control register 154 str r11, [r6] 155 156 @ Wow, now the hardware suspend request pins can be used, that makes them functional for 157 @ about 7 ns out of the entire time that the CPU is running! 158 159 @ Step 6 set force sleep bit in PMCR 160 161 str r13, [r12] 162 16320: b 20b @ loop waiting for sleep 164 165/* 166 * cpu_sa1100_resume() 167 * 168 * entry point from bootloader into kernel during resume 169 * 170 * Note: Yes, part of the following code is located into the .data section. 171 * This is to allow sleep_save_sp to be accessed with a relative load 172 * while we can't rely on any MMU translation. We could have put 173 * sleep_save_sp in the .text section as well, but some setups might 174 * insist on it to be truly read-only. 175 */ 176 177 .data 178 .align 5 179ENTRY(sa1100_cpu_resume) 180 mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC 181 msr cpsr_c, r0 @ set SVC, irqs off 182 183 ldr r0, sleep_save_sp @ stack phys addr 184 ldr r2, =resume_after_mmu @ its absolute virtual address 185 ldmfd r0, {r4 - r7, sp} @ CP regs + virt stack ptr 186 187 mov r1, #0 188 mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs 189 mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache 190 mcr p15, 0, r1, c9, c0, 0 @ invalidate RB 191 mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB 192 193 mcr p15, 0, r4, c3, c0, 0 @ domain ID 194 mcr p15, 0, r5, c2, c0, 0 @ translation table base addr 195 mcr p15, 0, r6, c13, c0, 0 @ PID 196 b resume_turn_on_mmu @ cache align execution 197 198 .align 5 199resume_turn_on_mmu: 200 mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, caches, etc. 201 nop 202 mov pc, r2 @ jump to virtual addr 203 nop 204 nop 205 nop 206 207sleep_save_sp: 208 .word 0 @ preserve stack phys ptr here 209 210 .text 211resume_after_mmu: 212 mcr p15, 0, r1, c15, c1, 2 @ enable clock switching 213 ldmfd sp!, {r4 - r12, pc} @ return to caller 214 215 216