root/arch/powerpc/platforms/52xx/lite5200_sleep.S

/* [<][>][^][v][top][bottom][index][help] */
   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
  35 registers:
  36         .space 0x5c*4
  37         .text
  38 
  39 /* ---------------------------------------------------------------------- */
  40 /* low-power mode with help of M68HLC908QT1 */
  41 
  42         .globl lite5200_low_power
  43 lite5200_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* 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
  82 1:
  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 
 107 sram_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         addi    r12, r13, r12 /* end */
 185     1:
 186         mftb    r13     /* current */
 187         cmp     cr0, r13, r12
 188         blt     1b
 189         blr
 190 
 191 sram_code_end:
 192 
 193 
 194 
 195 /* uboot jumps here on resume */
 196 lite5200_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
 216 mmu_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 
 252 
 253 /* ---------------------------------------------------------------------- */
 254 /* boring code: helpers */
 255 
 256 /* save registers */
 257 #define SAVE_BAT(n, addr)               \
 258         SAVE_SPRN(DBAT##n##L, addr);    \
 259         SAVE_SPRN(DBAT##n##U, addr+1);  \
 260         SAVE_SPRN(IBAT##n##L, addr+2);  \
 261         SAVE_SPRN(IBAT##n##U, addr+3);
 262 
 263 #define SAVE_SR(n, addr)                \
 264         mfsr    r10, n;                 \
 265         stw     r10, ((addr)*4)(r4);
 266 
 267 #define SAVE_4SR(n, addr)       \
 268         SAVE_SR(n, addr);       \
 269         SAVE_SR(n+1, addr+1);   \
 270         SAVE_SR(n+2, addr+2);   \
 271         SAVE_SR(n+3, addr+3);
 272 
 273 save_regs:
 274         stw     r0, 0(r4)
 275         stw     r1, 0x4(r4)
 276         stw     r2, 0x8(r4)
 277         stmw    r11, 0xc(r4) /* 0xc -> 0x5f, (0x18*4-1) */
 278 
 279         SAVE_SPRN(HID0, 0x18)
 280         SAVE_SPRN(HID1, 0x19)
 281         SAVE_SPRN(HID2, 0x1a)
 282         mfmsr   r10
 283         stw     r10, (4*0x1b)(r4)
 284         /*SAVE_SPRN(LR, 0x1c) have to save it before the call */
 285         /* 0x1d reserved by 0xf0 */
 286         SAVE_SPRN(RPA,   0x1e)
 287         SAVE_SPRN(SDR1,  0x1f)
 288 
 289         /* save MMU regs */
 290         SAVE_BAT(0, 0x20)
 291         SAVE_BAT(1, 0x24)
 292         SAVE_BAT(2, 0x28)
 293         SAVE_BAT(3, 0x2c)
 294         SAVE_BAT(4, 0x30)
 295         SAVE_BAT(5, 0x34)
 296         SAVE_BAT(6, 0x38)
 297         SAVE_BAT(7, 0x3c)
 298 
 299         SAVE_4SR(0, 0x40)
 300         SAVE_4SR(4, 0x44)
 301         SAVE_4SR(8, 0x48)
 302         SAVE_4SR(12, 0x4c)
 303 
 304         SAVE_SPRN(SPRG0, 0x50)
 305         SAVE_SPRN(SPRG1, 0x51)
 306         SAVE_SPRN(SPRG2, 0x52)
 307         SAVE_SPRN(SPRG3, 0x53)
 308         SAVE_SPRN(SPRG4, 0x54)
 309         SAVE_SPRN(SPRG5, 0x55)
 310         SAVE_SPRN(SPRG6, 0x56)
 311         SAVE_SPRN(SPRG7, 0x57)
 312 
 313         SAVE_SPRN(IABR,  0x58)
 314         SAVE_SPRN(DABR,  0x59)
 315         SAVE_SPRN(TBRL,  0x5a)
 316         SAVE_SPRN(TBRU,  0x5b)
 317 
 318         blr
 319 
 320 
 321 /* restore registers */
 322 #define LOAD_BAT(n, addr)               \
 323         LOAD_SPRN(DBAT##n##L, addr);    \
 324         LOAD_SPRN(DBAT##n##U, addr+1);  \
 325         LOAD_SPRN(IBAT##n##L, addr+2);  \
 326         LOAD_SPRN(IBAT##n##U, addr+3);
 327 
 328 #define LOAD_SR(n, addr)                \
 329         lwz     r10, ((addr)*4)(r4);    \
 330         mtsr    n, r10;
 331 
 332 #define LOAD_4SR(n, addr)       \
 333         LOAD_SR(n, addr);       \
 334         LOAD_SR(n+1, addr+1);   \
 335         LOAD_SR(n+2, addr+2);   \
 336         LOAD_SR(n+3, addr+3);
 337 
 338 restore_regs:
 339         lis     r4, registers@h
 340         ori     r4, r4, registers@l
 341 
 342         /* MMU is not up yet */
 343         subis   r4, r4, CONFIG_KERNEL_START@h
 344 
 345         lwz     r0, 0(r4)
 346         lwz     r1, 0x4(r4)
 347         lwz     r2, 0x8(r4)
 348         lmw     r11, 0xc(r4)
 349 
 350         /*
 351          * these are a bit tricky
 352          *
 353          * 0x18 - HID0
 354          * 0x19 - HID1
 355          * 0x1a - HID2
 356          * 0x1b - MSR
 357          * 0x1c - LR
 358          * 0x1d - reserved by 0xf0 (BDI2000)
 359          */
 360         LOAD_SPRN(RPA,   0x1e);
 361         LOAD_SPRN(SDR1,  0x1f);
 362 
 363         /* restore MMU regs */
 364         LOAD_BAT(0, 0x20)
 365         LOAD_BAT(1, 0x24)
 366         LOAD_BAT(2, 0x28)
 367         LOAD_BAT(3, 0x2c)
 368         LOAD_BAT(4, 0x30)
 369         LOAD_BAT(5, 0x34)
 370         LOAD_BAT(6, 0x38)
 371         LOAD_BAT(7, 0x3c)
 372 
 373         LOAD_4SR(0, 0x40)
 374         LOAD_4SR(4, 0x44)
 375         LOAD_4SR(8, 0x48)
 376         LOAD_4SR(12, 0x4c)
 377 
 378         /* rest of regs */
 379         LOAD_SPRN(SPRG0, 0x50);
 380         LOAD_SPRN(SPRG1, 0x51);
 381         LOAD_SPRN(SPRG2, 0x52);
 382         LOAD_SPRN(SPRG3, 0x53);
 383         LOAD_SPRN(SPRG4, 0x54);
 384         LOAD_SPRN(SPRG5, 0x55);
 385         LOAD_SPRN(SPRG6, 0x56);
 386         LOAD_SPRN(SPRG7, 0x57);
 387 
 388         LOAD_SPRN(IABR,  0x58);
 389         LOAD_SPRN(DABR,  0x59);
 390         LOAD_SPRN(TBWL,  0x5a); /* these two have separate R/W regs */
 391         LOAD_SPRN(TBWU,  0x5b);
 392 
 393         blr
 394 
 395 
 396 
 397 /* cache flushing code. copied from arch/ppc/boot/util.S */
 398 #define NUM_CACHE_LINES (128*8)
 399 
 400 /*
 401  * Flush data cache
 402  * Do this by just reading lots of stuff into the cache.
 403  */
 404 flush_data_cache:
 405         lis     r3,CONFIG_KERNEL_START@h
 406         ori     r3,r3,CONFIG_KERNEL_START@l
 407         li      r4,NUM_CACHE_LINES
 408         mtctr   r4
 409 1:
 410         lwz     r4,0(r3)
 411         addi    r3,r3,L1_CACHE_BYTES    /* Next line, please */
 412         bdnz    1b
 413         blr

/* [<][>][^][v][top][bottom][index][help] */