linux/arch/powerpc/platforms/powermac/sleep.S
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 * This file contains sleep low-level functions for PowerBook G3.
   4 *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
   5 *    and Paul Mackerras (paulus@samba.org).
   6 */
   7
   8#include <asm/processor.h>
   9#include <asm/page.h>
  10#include <asm/ppc_asm.h>
  11#include <asm/cputable.h>
  12#include <asm/cache.h>
  13#include <asm/thread_info.h>
  14#include <asm/asm-offsets.h>
  15#include <asm/mmu.h>
  16#include <asm/feature-fixups.h>
  17
  18#define MAGIC   0x4c617273      /* 'Lars' */
  19
  20/*
  21 * Structure for storing CPU registers on the stack.
  22 */
  23#define SL_SP           0
  24#define SL_PC           4
  25#define SL_MSR          8
  26#define SL_SDR1         0xc
  27#define SL_SPRG0        0x10    /* 4 sprg's */
  28#define SL_DBAT0        0x20
  29#define SL_IBAT0        0x28
  30#define SL_DBAT1        0x30
  31#define SL_IBAT1        0x38
  32#define SL_DBAT2        0x40
  33#define SL_IBAT2        0x48
  34#define SL_DBAT3        0x50
  35#define SL_IBAT3        0x58
  36#define SL_DBAT4        0x60
  37#define SL_IBAT4        0x68
  38#define SL_DBAT5        0x70
  39#define SL_IBAT5        0x78
  40#define SL_DBAT6        0x80
  41#define SL_IBAT6        0x88
  42#define SL_DBAT7        0x90
  43#define SL_IBAT7        0x98
  44#define SL_TB           0xa0
  45#define SL_R2           0xa8
  46#define SL_CR           0xac
  47#define SL_LR           0xb0
  48#define SL_R12          0xb4    /* r12 to r31 */
  49#define SL_SIZE         (SL_R12 + 80)
  50
  51        .section .text
  52        .align  5
  53
  54#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \
  55    (defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32))
  56
  57/* This gets called by via-pmu.c late during the sleep process.
  58 * The PMU was already send the sleep command and will shut us down
  59 * soon. We need to save all that is needed and setup the wakeup
  60 * vector that will be called by the ROM on wakeup
  61 */
  62_GLOBAL(low_sleep_handler)
  63#ifndef CONFIG_PPC_BOOK3S_32
  64        blr
  65#else
  66        mflr    r0
  67        lis     r11,sleep_storage@ha
  68        addi    r11,r11,sleep_storage@l
  69        stw     r0,SL_LR(r11)
  70        mfcr    r0
  71        stw     r0,SL_CR(r11)
  72        stw     r1,SL_SP(r11)
  73        stw     r2,SL_R2(r11)
  74        stmw    r12,SL_R12(r11)
  75
  76        /* Save MSR & SDR1 */
  77        mfmsr   r4
  78        stw     r4,SL_MSR(r11)
  79        mfsdr1  r4
  80        stw     r4,SL_SDR1(r11)
  81
  82        /* Get a stable timebase and save it */
  831:      mftbu   r4
  84        stw     r4,SL_TB(r11)
  85        mftb    r5
  86        stw     r5,SL_TB+4(r11)
  87        mftbu   r3
  88        cmpw    r3,r4
  89        bne     1b
  90
  91        /* Save SPRGs */
  92        mfsprg  r4,0
  93        stw     r4,SL_SPRG0(r11)
  94        mfsprg  r4,1
  95        stw     r4,SL_SPRG0+4(r11)
  96        mfsprg  r4,2
  97        stw     r4,SL_SPRG0+8(r11)
  98        mfsprg  r4,3
  99        stw     r4,SL_SPRG0+12(r11)
 100
 101        /* Save BATs */
 102        mfdbatu r4,0
 103        stw     r4,SL_DBAT0(r11)
 104        mfdbatl r4,0
 105        stw     r4,SL_DBAT0+4(r11)
 106        mfdbatu r4,1
 107        stw     r4,SL_DBAT1(r11)
 108        mfdbatl r4,1
 109        stw     r4,SL_DBAT1+4(r11)
 110        mfdbatu r4,2
 111        stw     r4,SL_DBAT2(r11)
 112        mfdbatl r4,2
 113        stw     r4,SL_DBAT2+4(r11)
 114        mfdbatu r4,3
 115        stw     r4,SL_DBAT3(r11)
 116        mfdbatl r4,3
 117        stw     r4,SL_DBAT3+4(r11)
 118        mfibatu r4,0
 119        stw     r4,SL_IBAT0(r11)
 120        mfibatl r4,0
 121        stw     r4,SL_IBAT0+4(r11)
 122        mfibatu r4,1
 123        stw     r4,SL_IBAT1(r11)
 124        mfibatl r4,1
 125        stw     r4,SL_IBAT1+4(r11)
 126        mfibatu r4,2
 127        stw     r4,SL_IBAT2(r11)
 128        mfibatl r4,2
 129        stw     r4,SL_IBAT2+4(r11)
 130        mfibatu r4,3
 131        stw     r4,SL_IBAT3(r11)
 132        mfibatl r4,3
 133        stw     r4,SL_IBAT3+4(r11)
 134
 135BEGIN_MMU_FTR_SECTION
 136        mfspr   r4,SPRN_DBAT4U
 137        stw     r4,SL_DBAT4(r11)
 138        mfspr   r4,SPRN_DBAT4L
 139        stw     r4,SL_DBAT4+4(r11)
 140        mfspr   r4,SPRN_DBAT5U
 141        stw     r4,SL_DBAT5(r11)
 142        mfspr   r4,SPRN_DBAT5L
 143        stw     r4,SL_DBAT5+4(r11)
 144        mfspr   r4,SPRN_DBAT6U
 145        stw     r4,SL_DBAT6(r11)
 146        mfspr   r4,SPRN_DBAT6L
 147        stw     r4,SL_DBAT6+4(r11)
 148        mfspr   r4,SPRN_DBAT7U
 149        stw     r4,SL_DBAT7(r11)
 150        mfspr   r4,SPRN_DBAT7L
 151        stw     r4,SL_DBAT7+4(r11)
 152        mfspr   r4,SPRN_IBAT4U
 153        stw     r4,SL_IBAT4(r11)
 154        mfspr   r4,SPRN_IBAT4L
 155        stw     r4,SL_IBAT4+4(r11)
 156        mfspr   r4,SPRN_IBAT5U
 157        stw     r4,SL_IBAT5(r11)
 158        mfspr   r4,SPRN_IBAT5L
 159        stw     r4,SL_IBAT5+4(r11)
 160        mfspr   r4,SPRN_IBAT6U
 161        stw     r4,SL_IBAT6(r11)
 162        mfspr   r4,SPRN_IBAT6L
 163        stw     r4,SL_IBAT6+4(r11)
 164        mfspr   r4,SPRN_IBAT7U
 165        stw     r4,SL_IBAT7(r11)
 166        mfspr   r4,SPRN_IBAT7L
 167        stw     r4,SL_IBAT7+4(r11)
 168END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
 169
 170        /* Backup various CPU config stuffs */
 171        bl      __save_cpu_setup
 172
 173        /* The ROM can wake us up via 2 different vectors:
 174         *  - On wallstreet & lombard, we must write a magic
 175         *    value 'Lars' at address 4 and a pointer to a
 176         *    memory location containing the PC to resume from
 177         *    at address 0.
 178         *  - On Core99, we must store the wakeup vector at
 179         *    address 0x80 and eventually it's parameters
 180         *    at address 0x84. I've have some trouble with those
 181         *    parameters however and I no longer use them.
 182         */
 183        lis     r5,grackle_wake_up@ha
 184        addi    r5,r5,grackle_wake_up@l
 185        tophys(r5,r5)
 186        stw     r5,SL_PC(r11)
 187        lis     r4,KERNELBASE@h
 188        tophys(r5,r11)
 189        addi    r5,r5,SL_PC
 190        lis     r6,MAGIC@ha
 191        addi    r6,r6,MAGIC@l
 192        stw     r5,0(r4)
 193        stw     r6,4(r4)
 194        /* Setup stuffs at 0x80-0x84 for Core99 */
 195        lis     r3,core99_wake_up@ha
 196        addi    r3,r3,core99_wake_up@l
 197        tophys(r3,r3)
 198        stw     r3,0x80(r4)
 199        stw     r5,0x84(r4)
 200
 201        .globl  low_cpu_offline_self
 202low_cpu_offline_self:
 203        /* Flush & disable all caches */
 204        bl      flush_disable_caches
 205
 206        /* Turn off data relocation. */
 207        mfmsr   r3              /* Save MSR in r7 */
 208        rlwinm  r3,r3,0,28,26   /* Turn off DR bit */
 209        sync
 210        mtmsr   r3
 211        isync
 212
 213BEGIN_FTR_SECTION
 214        /* Flush any pending L2 data prefetches to work around HW bug */
 215        sync
 216        lis     r3,0xfff0
 217        lwz     r0,0(r3)        /* perform cache-inhibited load to ROM */
 218        sync                    /* (caches are disabled at this point) */
 219END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
 220
 221/*
 222 * Set the HID0 and MSR for sleep.
 223 */
 224        mfspr   r2,SPRN_HID0
 225        rlwinm  r2,r2,0,10,7    /* clear doze, nap */
 226        oris    r2,r2,HID0_SLEEP@h
 227        sync
 228        isync
 229        mtspr   SPRN_HID0,r2
 230        sync
 231
 232/* This loop puts us back to sleep in case we have a spurrious
 233 * wakeup so that the host bridge properly stays asleep. The
 234 * CPU will be turned off, either after a known time (about 1
 235 * second) on wallstreet & lombard, or as soon as the CPU enters
 236 * SLEEP mode on core99
 237 */
 238        mfmsr   r2
 239        oris    r2,r2,MSR_POW@h
 2401:      sync
 241        mtmsr   r2
 242        isync
 243        b       1b
 244_ASM_NOKPROBE_SYMBOL(low_cpu_offline_self)
 245/*
 246 * Here is the resume code.
 247 */
 248
 249
 250/*
 251 * Core99 machines resume here
 252 * r4 has the physical address of SL_PC(sp) (unused)
 253 */
 254_GLOBAL(core99_wake_up)
 255        /* Make sure HID0 no longer contains any sleep bit and that data cache
 256         * is disabled
 257         */
 258        mfspr   r3,SPRN_HID0
 259        rlwinm  r3,r3,0,11,7            /* clear SLEEP, NAP, DOZE bits */
 260        rlwinm  3,r3,0,18,15            /* clear DCE, ICE */
 261        mtspr   SPRN_HID0,r3
 262        sync
 263        isync
 264
 265        /* sanitize MSR */
 266        mfmsr   r3
 267        ori     r3,r3,MSR_EE|MSR_IP
 268        xori    r3,r3,MSR_EE|MSR_IP
 269        sync
 270        isync
 271        mtmsr   r3
 272        sync
 273        isync
 274
 275        /* Recover sleep storage */
 276        lis     r3,sleep_storage@ha
 277        addi    r3,r3,sleep_storage@l
 278        tophys(r3,r3)
 279        addi    r1,r3,SL_PC
 280
 281        /* Pass thru to older resume code ... */
 282_ASM_NOKPROBE_SYMBOL(core99_wake_up)
 283/*
 284 * Here is the resume code for older machines.
 285 * r1 has the physical address of SL_PC(sp).
 286 */
 287
 288grackle_wake_up:
 289
 290        /* Restore the kernel's segment registers before
 291         * we do any r1 memory access as we are not sure they
 292         * are in a sane state above the first 256Mb region
 293         */
 294        bl      load_segment_registers
 295        sync
 296        isync
 297
 298        subi    r1,r1,SL_PC
 299
 300        /* Restore various CPU config stuffs */
 301        bl      __restore_cpu_setup
 302
 303        /* Make sure all FPRs have been initialized */
 304        bl      reloc_offset
 305        bl      __init_fpu_registers
 306
 307        /* Invalidate & enable L1 cache, we don't care about
 308         * whatever the ROM may have tried to write to memory
 309         */
 310        bl      __inval_enable_L1
 311
 312        /* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
 313        lwz     r4,SL_SDR1(r1)
 314        mtsdr1  r4
 315        lwz     r4,SL_SPRG0(r1)
 316        mtsprg  0,r4
 317        lwz     r4,SL_SPRG0+4(r1)
 318        mtsprg  1,r4
 319        lwz     r4,SL_SPRG0+8(r1)
 320        mtsprg  2,r4
 321        lwz     r4,SL_SPRG0+12(r1)
 322        mtsprg  3,r4
 323
 324        lwz     r4,SL_DBAT0(r1)
 325        mtdbatu 0,r4
 326        lwz     r4,SL_DBAT0+4(r1)
 327        mtdbatl 0,r4
 328        lwz     r4,SL_DBAT1(r1)
 329        mtdbatu 1,r4
 330        lwz     r4,SL_DBAT1+4(r1)
 331        mtdbatl 1,r4
 332        lwz     r4,SL_DBAT2(r1)
 333        mtdbatu 2,r4
 334        lwz     r4,SL_DBAT2+4(r1)
 335        mtdbatl 2,r4
 336        lwz     r4,SL_DBAT3(r1)
 337        mtdbatu 3,r4
 338        lwz     r4,SL_DBAT3+4(r1)
 339        mtdbatl 3,r4
 340        lwz     r4,SL_IBAT0(r1)
 341        mtibatu 0,r4
 342        lwz     r4,SL_IBAT0+4(r1)
 343        mtibatl 0,r4
 344        lwz     r4,SL_IBAT1(r1)
 345        mtibatu 1,r4
 346        lwz     r4,SL_IBAT1+4(r1)
 347        mtibatl 1,r4
 348        lwz     r4,SL_IBAT2(r1)
 349        mtibatu 2,r4
 350        lwz     r4,SL_IBAT2+4(r1)
 351        mtibatl 2,r4
 352        lwz     r4,SL_IBAT3(r1)
 353        mtibatu 3,r4
 354        lwz     r4,SL_IBAT3+4(r1)
 355        mtibatl 3,r4
 356
 357BEGIN_MMU_FTR_SECTION
 358        lwz     r4,SL_DBAT4(r1)
 359        mtspr   SPRN_DBAT4U,r4
 360        lwz     r4,SL_DBAT4+4(r1)
 361        mtspr   SPRN_DBAT4L,r4
 362        lwz     r4,SL_DBAT5(r1)
 363        mtspr   SPRN_DBAT5U,r4
 364        lwz     r4,SL_DBAT5+4(r1)
 365        mtspr   SPRN_DBAT5L,r4
 366        lwz     r4,SL_DBAT6(r1)
 367        mtspr   SPRN_DBAT6U,r4
 368        lwz     r4,SL_DBAT6+4(r1)
 369        mtspr   SPRN_DBAT6L,r4
 370        lwz     r4,SL_DBAT7(r1)
 371        mtspr   SPRN_DBAT7U,r4
 372        lwz     r4,SL_DBAT7+4(r1)
 373        mtspr   SPRN_DBAT7L,r4
 374        lwz     r4,SL_IBAT4(r1)
 375        mtspr   SPRN_IBAT4U,r4
 376        lwz     r4,SL_IBAT4+4(r1)
 377        mtspr   SPRN_IBAT4L,r4
 378        lwz     r4,SL_IBAT5(r1)
 379        mtspr   SPRN_IBAT5U,r4
 380        lwz     r4,SL_IBAT5+4(r1)
 381        mtspr   SPRN_IBAT5L,r4
 382        lwz     r4,SL_IBAT6(r1)
 383        mtspr   SPRN_IBAT6U,r4
 384        lwz     r4,SL_IBAT6+4(r1)
 385        mtspr   SPRN_IBAT6L,r4
 386        lwz     r4,SL_IBAT7(r1)
 387        mtspr   SPRN_IBAT7U,r4
 388        lwz     r4,SL_IBAT7+4(r1)
 389        mtspr   SPRN_IBAT7L,r4
 390END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
 391
 392        /* Flush all TLBs */
 393        lis     r4,0x1000
 3941:      addic.  r4,r4,-0x1000
 395        tlbie   r4
 396        blt     1b
 397        sync
 398
 399        /* Restore TB */
 400        li      r3,0
 401        mttbl   r3
 402        lwz     r3,SL_TB(r1)
 403        lwz     r4,SL_TB+4(r1)
 404        mttbu   r3
 405        mttbl   r4
 406
 407        /* Restore the callee-saved registers and return */
 408        lwz     r0,SL_CR(r1)
 409        mtcr    r0
 410        lwz     r2,SL_R2(r1)
 411        lmw     r12,SL_R12(r1)
 412
 413        /* restore the MSR and SP and turn on the MMU and return */
 414        lwz     r3,SL_MSR(r1)
 415        lwz     r4,SL_LR(r1)
 416        lwz     r1,SL_SP(r1)
 417        mtsrr0  r4
 418        mtsrr1  r3
 419        sync
 420        isync
 421        rfi
 422_ASM_NOKPROBE_SYMBOL(grackle_wake_up)
 423
 424#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
 425
 426        .section .bss
 427        .balign L1_CACHE_BYTES
 428sleep_storage:
 429        .space SL_SIZE
 430        .balign L1_CACHE_BYTES, 0
 431
 432#endif /* CONFIG_PPC_BOOK3S_32 */
 433        .section .text
 434