lite5200_sleep.S (7896B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2#include <asm/reg.h> 3#include <asm/ppc_asm.h> 4#include <asm/processor.h> 5#include <asm/cache.h> 6 7 8#define SDRAM_CTRL 0x104 9#define SC_MODE_EN (1<<31) 10#define SC_CKE (1<<30) 11#define SC_REF_EN (1<<28) 12#define SC_SOFT_PRE (1<<1) 13 14#define GPIOW_GPIOE 0xc00 15#define GPIOW_DDR 0xc08 16#define GPIOW_DVO 0xc0c 17 18#define CDM_CE 0x214 19#define CDM_SDRAM (1<<3) 20 21 22/* helpers... beware: r10 and r4 are overwritten */ 23#define SAVE_SPRN(reg, addr) \ 24 mfspr r10, SPRN_##reg; \ 25 stw r10, ((addr)*4)(r4); 26 27#define LOAD_SPRN(reg, addr) \ 28 lwz r10, ((addr)*4)(r4); \ 29 mtspr SPRN_##reg, r10; \ 30 sync; \ 31 isync; 32 33 34 .data 35registers: 36 .space 0x5c*4 37 .text 38 39/* ---------------------------------------------------------------------- */ 40/* low-power mode with help of M68HLC908QT1 */ 41 42 .globl lite5200_low_power 43lite5200_low_power: 44 45 mr r7, r3 /* save SRAM va */ 46 mr r8, r4 /* save MBAR va */ 47 48 /* setup wakeup address for u-boot at physical location 0x0 */ 49 lis r3, CONFIG_KERNEL_START@h 50 lis r4, lite5200_wakeup@h 51 ori r4, r4, lite5200_wakeup@l 52 sub r4, r4, r3 53 stw r4, 0(r3) 54 55 56 /* 57 * save stuff BDI overwrites 58 * 0xf0 (0xe0->0x100 gets overwritten when BDI connected; 59 * even when CONFIG_BDI_SWITCH is disabled and MMU XLAT commented; heisenbug?)) 60 * WARNING: self-refresh doesn't seem to work when BDI2000 is connected, 61 * possibly because BDI sets SDRAM registers before wakeup code does 62 */ 63 lis r4, registers@h 64 ori r4, r4, registers@l 65 lwz r10, 0xf0(r3) 66 stw r10, (0x1d*4)(r4) 67 68 /* save registers to r4 [destroys r10] */ 69 SAVE_SPRN(LR, 0x1c) 70 bl save_regs 71 72 /* flush caches [destroys r3, r4] */ 73 bl flush_data_cache 74 75 76 /* copy code to sram */ 77 mr r4, r7 78 li r3, (sram_code_end - sram_code)/4 79 mtctr r3 80 lis r3, sram_code@h 81 ori r3, r3, sram_code@l 821: 83 lwz r5, 0(r3) 84 stw r5, 0(r4) 85 addi r3, r3, 4 86 addi r4, r4, 4 87 bdnz 1b 88 89 /* get tb_ticks_per_usec */ 90 lis r3, tb_ticks_per_usec@h 91 lwz r11, tb_ticks_per_usec@l(r3) 92 93 /* disable I and D caches */ 94 mfspr r3, SPRN_HID0 95 ori r3, r3, HID0_ICE | HID0_DCE 96 xori r3, r3, HID0_ICE | HID0_DCE 97 sync; isync; 98 mtspr SPRN_HID0, r3 99 sync; isync; 100 101 /* jump to sram */ 102 mtlr r7 103 blrl 104 /* doesn't return */ 105 106 107sram_code: 108 /* self refresh */ 109 lwz r4, SDRAM_CTRL(r8) 110 111 /* send NOP (precharge) */ 112 oris r4, r4, SC_MODE_EN@h /* mode_en */ 113 stw r4, SDRAM_CTRL(r8) 114 sync 115 116 ori r4, r4, SC_SOFT_PRE /* soft_pre */ 117 stw r4, SDRAM_CTRL(r8) 118 sync 119 xori r4, r4, SC_SOFT_PRE 120 121 xoris r4, r4, SC_MODE_EN@h /* !mode_en */ 122 stw r4, SDRAM_CTRL(r8) 123 sync 124 125 /* delay (for NOP to finish) */ 126 li r12, 1 127 bl udelay 128 129 /* 130 * mode_en must not be set when enabling self-refresh 131 * send AR with CKE low (self-refresh) 132 */ 133 oris r4, r4, (SC_REF_EN | SC_CKE)@h 134 xoris r4, r4, (SC_CKE)@h /* ref_en !cke */ 135 stw r4, SDRAM_CTRL(r8) 136 sync 137 138 /* delay (after !CKE there should be two cycles) */ 139 li r12, 1 140 bl udelay 141 142 /* disable clock */ 143 lwz r4, CDM_CE(r8) 144 ori r4, r4, CDM_SDRAM 145 xori r4, r4, CDM_SDRAM 146 stw r4, CDM_CE(r8) 147 sync 148 149 /* delay a bit */ 150 li r12, 1 151 bl udelay 152 153 154 /* turn off with QT chip */ 155 li r4, 0x02 156 stb r4, GPIOW_GPIOE(r8) /* enable gpio_wkup1 */ 157 sync 158 159 stb r4, GPIOW_DVO(r8) /* "output" high */ 160 sync 161 stb r4, GPIOW_DDR(r8) /* output */ 162 sync 163 stb r4, GPIOW_DVO(r8) /* output high */ 164 sync 165 166 /* 10uS delay */ 167 li r12, 10 168 bl udelay 169 170 /* turn off */ 171 li r4, 0 172 stb r4, GPIOW_DVO(r8) /* output low */ 173 sync 174 175 /* wait until we're offline */ 176 1: 177 b 1b 178 179 180 /* local udelay in sram is needed */ 181 udelay: /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */ 182 mullw r12, r12, r11 183 mftb r13 /* start */ 184 add r12, r13, r12 /* end */ 185 1: 186 mftb r13 /* current */ 187 cmp cr0, r13, r12 188 blt 1b 189 blr 190 191sram_code_end: 192 193 194 195/* uboot jumps here on resume */ 196lite5200_wakeup: 197 bl restore_regs 198 199 200 /* HIDs, MSR */ 201 LOAD_SPRN(HID1, 0x19) 202 LOAD_SPRN(HID2, 0x1a) 203 204 205 /* address translation is tricky (see turn_on_mmu) */ 206 mfmsr r10 207 ori r10, r10, MSR_DR | MSR_IR 208 209 210 mtspr SPRN_SRR1, r10 211 lis r10, mmu_on@h 212 ori r10, r10, mmu_on@l 213 mtspr SPRN_SRR0, r10 214 sync 215 rfi 216mmu_on: 217 /* kernel offset (r4 is still set from restore_registers) */ 218 addis r4, r4, CONFIG_KERNEL_START@h 219 220 221 /* restore MSR */ 222 lwz r10, (4*0x1b)(r4) 223 mtmsr r10 224 sync; isync; 225 226 /* invalidate caches */ 227 mfspr r10, SPRN_HID0 228 ori r5, r10, HID0_ICFI | HID0_DCI 229 mtspr SPRN_HID0, r5 /* invalidate caches */ 230 sync; isync; 231 mtspr SPRN_HID0, r10 232 sync; isync; 233 234 /* enable caches */ 235 lwz r10, (4*0x18)(r4) 236 mtspr SPRN_HID0, r10 /* restore (enable caches, DPM) */ 237 /* ^ this has to be after address translation set in MSR */ 238 sync 239 isync 240 241 242 /* restore 0xf0 (BDI2000) */ 243 lis r3, CONFIG_KERNEL_START@h 244 lwz r10, (0x1d*4)(r4) 245 stw r10, 0xf0(r3) 246 247 LOAD_SPRN(LR, 0x1c) 248 249 250 blr 251_ASM_NOKPROBE_SYMBOL(lite5200_wakeup) 252 253 254/* ---------------------------------------------------------------------- */ 255/* boring code: helpers */ 256 257/* save registers */ 258#define SAVE_BAT(n, addr) \ 259 SAVE_SPRN(DBAT##n##L, addr); \ 260 SAVE_SPRN(DBAT##n##U, addr+1); \ 261 SAVE_SPRN(IBAT##n##L, addr+2); \ 262 SAVE_SPRN(IBAT##n##U, addr+3); 263 264#define SAVE_SR(n, addr) \ 265 mfsr r10, n; \ 266 stw r10, ((addr)*4)(r4); 267 268#define SAVE_4SR(n, addr) \ 269 SAVE_SR(n, addr); \ 270 SAVE_SR(n+1, addr+1); \ 271 SAVE_SR(n+2, addr+2); \ 272 SAVE_SR(n+3, addr+3); 273 274save_regs: 275 stw r0, 0(r4) 276 stw r1, 0x4(r4) 277 stw r2, 0x8(r4) 278 stmw r11, 0xc(r4) /* 0xc -> 0x5f, (0x18*4-1) */ 279 280 SAVE_SPRN(HID0, 0x18) 281 SAVE_SPRN(HID1, 0x19) 282 SAVE_SPRN(HID2, 0x1a) 283 mfmsr r10 284 stw r10, (4*0x1b)(r4) 285 /*SAVE_SPRN(LR, 0x1c) have to save it before the call */ 286 /* 0x1d reserved by 0xf0 */ 287 SAVE_SPRN(RPA, 0x1e) 288 SAVE_SPRN(SDR1, 0x1f) 289 290 /* save MMU regs */ 291 SAVE_BAT(0, 0x20) 292 SAVE_BAT(1, 0x24) 293 SAVE_BAT(2, 0x28) 294 SAVE_BAT(3, 0x2c) 295 SAVE_BAT(4, 0x30) 296 SAVE_BAT(5, 0x34) 297 SAVE_BAT(6, 0x38) 298 SAVE_BAT(7, 0x3c) 299 300 SAVE_4SR(0, 0x40) 301 SAVE_4SR(4, 0x44) 302 SAVE_4SR(8, 0x48) 303 SAVE_4SR(12, 0x4c) 304 305 SAVE_SPRN(SPRG0, 0x50) 306 SAVE_SPRN(SPRG1, 0x51) 307 SAVE_SPRN(SPRG2, 0x52) 308 SAVE_SPRN(SPRG3, 0x53) 309 SAVE_SPRN(SPRG4, 0x54) 310 SAVE_SPRN(SPRG5, 0x55) 311 SAVE_SPRN(SPRG6, 0x56) 312 SAVE_SPRN(SPRG7, 0x57) 313 314 SAVE_SPRN(IABR, 0x58) 315 SAVE_SPRN(DABR, 0x59) 316 SAVE_SPRN(TBRL, 0x5a) 317 SAVE_SPRN(TBRU, 0x5b) 318 319 blr 320 321 322/* restore registers */ 323#define LOAD_BAT(n, addr) \ 324 LOAD_SPRN(DBAT##n##L, addr); \ 325 LOAD_SPRN(DBAT##n##U, addr+1); \ 326 LOAD_SPRN(IBAT##n##L, addr+2); \ 327 LOAD_SPRN(IBAT##n##U, addr+3); 328 329#define LOAD_SR(n, addr) \ 330 lwz r10, ((addr)*4)(r4); \ 331 mtsr n, r10; 332 333#define LOAD_4SR(n, addr) \ 334 LOAD_SR(n, addr); \ 335 LOAD_SR(n+1, addr+1); \ 336 LOAD_SR(n+2, addr+2); \ 337 LOAD_SR(n+3, addr+3); 338 339restore_regs: 340 lis r4, registers@h 341 ori r4, r4, registers@l 342 343 /* MMU is not up yet */ 344 subis r4, r4, CONFIG_KERNEL_START@h 345 346 lwz r0, 0(r4) 347 lwz r1, 0x4(r4) 348 lwz r2, 0x8(r4) 349 lmw r11, 0xc(r4) 350 351 /* 352 * these are a bit tricky 353 * 354 * 0x18 - HID0 355 * 0x19 - HID1 356 * 0x1a - HID2 357 * 0x1b - MSR 358 * 0x1c - LR 359 * 0x1d - reserved by 0xf0 (BDI2000) 360 */ 361 LOAD_SPRN(RPA, 0x1e); 362 LOAD_SPRN(SDR1, 0x1f); 363 364 /* restore MMU regs */ 365 LOAD_BAT(0, 0x20) 366 LOAD_BAT(1, 0x24) 367 LOAD_BAT(2, 0x28) 368 LOAD_BAT(3, 0x2c) 369 LOAD_BAT(4, 0x30) 370 LOAD_BAT(5, 0x34) 371 LOAD_BAT(6, 0x38) 372 LOAD_BAT(7, 0x3c) 373 374 LOAD_4SR(0, 0x40) 375 LOAD_4SR(4, 0x44) 376 LOAD_4SR(8, 0x48) 377 LOAD_4SR(12, 0x4c) 378 379 /* rest of regs */ 380 LOAD_SPRN(SPRG0, 0x50); 381 LOAD_SPRN(SPRG1, 0x51); 382 LOAD_SPRN(SPRG2, 0x52); 383 LOAD_SPRN(SPRG3, 0x53); 384 LOAD_SPRN(SPRG4, 0x54); 385 LOAD_SPRN(SPRG5, 0x55); 386 LOAD_SPRN(SPRG6, 0x56); 387 LOAD_SPRN(SPRG7, 0x57); 388 389 LOAD_SPRN(IABR, 0x58); 390 LOAD_SPRN(DABR, 0x59); 391 LOAD_SPRN(TBWL, 0x5a); /* these two have separate R/W regs */ 392 LOAD_SPRN(TBWU, 0x5b); 393 394 blr 395_ASM_NOKPROBE_SYMBOL(restore_regs) 396 397 398 399/* cache flushing code. copied from arch/ppc/boot/util.S */ 400#define NUM_CACHE_LINES (128*8) 401 402/* 403 * Flush data cache 404 * Do this by just reading lots of stuff into the cache. 405 */ 406flush_data_cache: 407 lis r3,CONFIG_KERNEL_START@h 408 ori r3,r3,CONFIG_KERNEL_START@l 409 li r4,NUM_CACHE_LINES 410 mtctr r4 4111: 412 lwz r4,0(r3) 413 addi r3,r3,L1_CACHE_BYTES /* Next line, please */ 414 bdnz 1b 415 blr