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