Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * This file contains sleep low-level functions for PowerBook G3.
0004  *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
0005  *    and Paul Mackerras (paulus@samba.org).
0006  */
0007 
0008 #include <asm/processor.h>
0009 #include <asm/page.h>
0010 #include <asm/ppc_asm.h>
0011 #include <asm/cputable.h>
0012 #include <asm/cache.h>
0013 #include <asm/thread_info.h>
0014 #include <asm/asm-offsets.h>
0015 #include <asm/mmu.h>
0016 #include <asm/feature-fixups.h>
0017 
0018 #define MAGIC   0x4c617273  /* 'Lars' */
0019 
0020 /*
0021  * Structure for storing CPU registers on the stack.
0022  */
0023 #define SL_SP       0
0024 #define SL_PC       4
0025 #define SL_MSR      8
0026 #define SL_SDR1     0xc
0027 #define SL_SPRG0    0x10    /* 4 sprg's */
0028 #define SL_DBAT0    0x20
0029 #define SL_IBAT0    0x28
0030 #define SL_DBAT1    0x30
0031 #define SL_IBAT1    0x38
0032 #define SL_DBAT2    0x40
0033 #define SL_IBAT2    0x48
0034 #define SL_DBAT3    0x50
0035 #define SL_IBAT3    0x58
0036 #define SL_DBAT4    0x60
0037 #define SL_IBAT4    0x68
0038 #define SL_DBAT5    0x70
0039 #define SL_IBAT5    0x78
0040 #define SL_DBAT6    0x80
0041 #define SL_IBAT6    0x88
0042 #define SL_DBAT7    0x90
0043 #define SL_IBAT7    0x98
0044 #define SL_TB       0xa0
0045 #define SL_R2       0xa8
0046 #define SL_CR       0xac
0047 #define SL_LR       0xb0
0048 #define SL_R12      0xb4    /* r12 to r31 */
0049 #define SL_SIZE     (SL_R12 + 80)
0050 
0051     .section .text
0052     .align  5
0053 
0054 #if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \
0055     (defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32))
0056 
0057 /* This gets called by via-pmu.c late during the sleep process.
0058  * The PMU was already send the sleep command and will shut us down
0059  * soon. We need to save all that is needed and setup the wakeup
0060  * vector that will be called by the ROM on wakeup
0061  */
0062 _GLOBAL(low_sleep_handler)
0063 #ifndef CONFIG_PPC_BOOK3S_32
0064     blr
0065 #else
0066     mflr    r0
0067     lis r11,sleep_storage@ha
0068     addi    r11,r11,sleep_storage@l
0069     stw r0,SL_LR(r11)
0070     mfcr    r0
0071     stw r0,SL_CR(r11)
0072     stw r1,SL_SP(r11)
0073     stw r2,SL_R2(r11)
0074     stmw    r12,SL_R12(r11)
0075 
0076     /* Save MSR & SDR1 */
0077     mfmsr   r4
0078     stw r4,SL_MSR(r11)
0079     mfsdr1  r4
0080     stw r4,SL_SDR1(r11)
0081 
0082     /* Get a stable timebase and save it */
0083 1:  mftbu   r4
0084     stw r4,SL_TB(r11)
0085     mftb    r5
0086     stw r5,SL_TB+4(r11)
0087     mftbu   r3
0088     cmpw    r3,r4
0089     bne 1b
0090 
0091     /* Save SPRGs */
0092     mfsprg  r4,0
0093     stw r4,SL_SPRG0(r11)
0094     mfsprg  r4,1
0095     stw r4,SL_SPRG0+4(r11)
0096     mfsprg  r4,2
0097     stw r4,SL_SPRG0+8(r11)
0098     mfsprg  r4,3
0099     stw r4,SL_SPRG0+12(r11)
0100 
0101     /* Save BATs */
0102     mfdbatu r4,0
0103     stw r4,SL_DBAT0(r11)
0104     mfdbatl r4,0
0105     stw r4,SL_DBAT0+4(r11)
0106     mfdbatu r4,1
0107     stw r4,SL_DBAT1(r11)
0108     mfdbatl r4,1
0109     stw r4,SL_DBAT1+4(r11)
0110     mfdbatu r4,2
0111     stw r4,SL_DBAT2(r11)
0112     mfdbatl r4,2
0113     stw r4,SL_DBAT2+4(r11)
0114     mfdbatu r4,3
0115     stw r4,SL_DBAT3(r11)
0116     mfdbatl r4,3
0117     stw r4,SL_DBAT3+4(r11)
0118     mfibatu r4,0
0119     stw r4,SL_IBAT0(r11)
0120     mfibatl r4,0
0121     stw r4,SL_IBAT0+4(r11)
0122     mfibatu r4,1
0123     stw r4,SL_IBAT1(r11)
0124     mfibatl r4,1
0125     stw r4,SL_IBAT1+4(r11)
0126     mfibatu r4,2
0127     stw r4,SL_IBAT2(r11)
0128     mfibatl r4,2
0129     stw r4,SL_IBAT2+4(r11)
0130     mfibatu r4,3
0131     stw r4,SL_IBAT3(r11)
0132     mfibatl r4,3
0133     stw r4,SL_IBAT3+4(r11)
0134 
0135 BEGIN_MMU_FTR_SECTION
0136     mfspr   r4,SPRN_DBAT4U
0137     stw r4,SL_DBAT4(r11)
0138     mfspr   r4,SPRN_DBAT4L
0139     stw r4,SL_DBAT4+4(r11)
0140     mfspr   r4,SPRN_DBAT5U
0141     stw r4,SL_DBAT5(r11)
0142     mfspr   r4,SPRN_DBAT5L
0143     stw r4,SL_DBAT5+4(r11)
0144     mfspr   r4,SPRN_DBAT6U
0145     stw r4,SL_DBAT6(r11)
0146     mfspr   r4,SPRN_DBAT6L
0147     stw r4,SL_DBAT6+4(r11)
0148     mfspr   r4,SPRN_DBAT7U
0149     stw r4,SL_DBAT7(r11)
0150     mfspr   r4,SPRN_DBAT7L
0151     stw r4,SL_DBAT7+4(r11)
0152     mfspr   r4,SPRN_IBAT4U
0153     stw r4,SL_IBAT4(r11)
0154     mfspr   r4,SPRN_IBAT4L
0155     stw r4,SL_IBAT4+4(r11)
0156     mfspr   r4,SPRN_IBAT5U
0157     stw r4,SL_IBAT5(r11)
0158     mfspr   r4,SPRN_IBAT5L
0159     stw r4,SL_IBAT5+4(r11)
0160     mfspr   r4,SPRN_IBAT6U
0161     stw r4,SL_IBAT6(r11)
0162     mfspr   r4,SPRN_IBAT6L
0163     stw r4,SL_IBAT6+4(r11)
0164     mfspr   r4,SPRN_IBAT7U
0165     stw r4,SL_IBAT7(r11)
0166     mfspr   r4,SPRN_IBAT7L
0167     stw r4,SL_IBAT7+4(r11)
0168 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
0169 
0170     /* Backup various CPU config stuffs */
0171     bl  __save_cpu_setup
0172 
0173     /* The ROM can wake us up via 2 different vectors:
0174      *  - On wallstreet & lombard, we must write a magic
0175      *    value 'Lars' at address 4 and a pointer to a
0176      *    memory location containing the PC to resume from
0177      *    at address 0.
0178      *  - On Core99, we must store the wakeup vector at
0179      *    address 0x80 and eventually it's parameters
0180      *    at address 0x84. I've have some trouble with those
0181      *    parameters however and I no longer use them.
0182      */
0183     lis r5,grackle_wake_up@ha
0184     addi    r5,r5,grackle_wake_up@l
0185     tophys(r5,r5)
0186     stw r5,SL_PC(r11)
0187     lis r4,KERNELBASE@h
0188     tophys(r5,r11)
0189     addi    r5,r5,SL_PC
0190     lis r6,MAGIC@ha
0191     addi    r6,r6,MAGIC@l
0192     stw r5,0(r4)
0193     stw r6,4(r4)
0194     /* Setup stuffs at 0x80-0x84 for Core99 */
0195     lis r3,core99_wake_up@ha
0196     addi    r3,r3,core99_wake_up@l
0197     tophys(r3,r3)
0198     stw r3,0x80(r4)
0199     stw r5,0x84(r4)
0200 
0201     .globl  low_cpu_offline_self
0202 low_cpu_offline_self:
0203     /* Flush & disable all caches */
0204     bl  flush_disable_caches
0205 
0206     /* Turn off data relocation. */
0207     mfmsr   r3      /* Save MSR in r7 */
0208     rlwinm  r3,r3,0,28,26   /* Turn off DR bit */
0209     sync
0210     mtmsr   r3
0211     isync
0212 
0213 BEGIN_FTR_SECTION
0214     /* Flush any pending L2 data prefetches to work around HW bug */
0215     sync
0216     lis r3,0xfff0
0217     lwz r0,0(r3)    /* perform cache-inhibited load to ROM */
0218     sync            /* (caches are disabled at this point) */
0219 END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
0220 
0221 /*
0222  * Set the HID0 and MSR for sleep.
0223  */
0224     mfspr   r2,SPRN_HID0
0225     rlwinm  r2,r2,0,10,7    /* clear doze, nap */
0226     oris    r2,r2,HID0_SLEEP@h
0227     sync
0228     isync
0229     mtspr   SPRN_HID0,r2
0230     sync
0231 
0232 /* This loop puts us back to sleep in case we have a spurrious
0233  * wakeup so that the host bridge properly stays asleep. The
0234  * CPU will be turned off, either after a known time (about 1
0235  * second) on wallstreet & lombard, or as soon as the CPU enters
0236  * SLEEP mode on core99
0237  */
0238     mfmsr   r2
0239     oris    r2,r2,MSR_POW@h
0240 1:  sync
0241     mtmsr   r2
0242     isync
0243     b   1b
0244 _ASM_NOKPROBE_SYMBOL(low_cpu_offline_self)
0245 /*
0246  * Here is the resume code.
0247  */
0248 
0249 
0250 /*
0251  * Core99 machines resume here
0252  * r4 has the physical address of SL_PC(sp) (unused)
0253  */
0254 _GLOBAL(core99_wake_up)
0255     /* Make sure HID0 no longer contains any sleep bit and that data cache
0256      * is disabled
0257      */
0258     mfspr   r3,SPRN_HID0
0259     rlwinm  r3,r3,0,11,7        /* clear SLEEP, NAP, DOZE bits */
0260     rlwinm  3,r3,0,18,15        /* clear DCE, ICE */
0261     mtspr   SPRN_HID0,r3
0262     sync
0263     isync
0264 
0265     /* sanitize MSR */
0266     mfmsr   r3
0267     ori r3,r3,MSR_EE|MSR_IP
0268     xori    r3,r3,MSR_EE|MSR_IP
0269     sync
0270     isync
0271     mtmsr   r3
0272     sync
0273     isync
0274 
0275     /* Recover sleep storage */
0276     lis r3,sleep_storage@ha
0277     addi    r3,r3,sleep_storage@l
0278     tophys(r3,r3)
0279     addi    r1,r3,SL_PC
0280 
0281     /* Pass thru to older resume code ... */
0282 _ASM_NOKPROBE_SYMBOL(core99_wake_up)
0283 /*
0284  * Here is the resume code for older machines.
0285  * r1 has the physical address of SL_PC(sp).
0286  */
0287 
0288 grackle_wake_up:
0289 
0290     /* Restore the kernel's segment registers before
0291      * we do any r1 memory access as we are not sure they
0292      * are in a sane state above the first 256Mb region
0293      */
0294     bl  load_segment_registers
0295     sync
0296     isync
0297 
0298     subi    r1,r1,SL_PC
0299 
0300     /* Restore various CPU config stuffs */
0301     bl  __restore_cpu_setup
0302 
0303     /* Make sure all FPRs have been initialized */
0304     bl  reloc_offset
0305     bl  __init_fpu_registers
0306 
0307     /* Invalidate & enable L1 cache, we don't care about
0308      * whatever the ROM may have tried to write to memory
0309      */
0310     bl  __inval_enable_L1
0311 
0312     /* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
0313     lwz r4,SL_SDR1(r1)
0314     mtsdr1  r4
0315     lwz r4,SL_SPRG0(r1)
0316     mtsprg  0,r4
0317     lwz r4,SL_SPRG0+4(r1)
0318     mtsprg  1,r4
0319     lwz r4,SL_SPRG0+8(r1)
0320     mtsprg  2,r4
0321     lwz r4,SL_SPRG0+12(r1)
0322     mtsprg  3,r4
0323 
0324     lwz r4,SL_DBAT0(r1)
0325     mtdbatu 0,r4
0326     lwz r4,SL_DBAT0+4(r1)
0327     mtdbatl 0,r4
0328     lwz r4,SL_DBAT1(r1)
0329     mtdbatu 1,r4
0330     lwz r4,SL_DBAT1+4(r1)
0331     mtdbatl 1,r4
0332     lwz r4,SL_DBAT2(r1)
0333     mtdbatu 2,r4
0334     lwz r4,SL_DBAT2+4(r1)
0335     mtdbatl 2,r4
0336     lwz r4,SL_DBAT3(r1)
0337     mtdbatu 3,r4
0338     lwz r4,SL_DBAT3+4(r1)
0339     mtdbatl 3,r4
0340     lwz r4,SL_IBAT0(r1)
0341     mtibatu 0,r4
0342     lwz r4,SL_IBAT0+4(r1)
0343     mtibatl 0,r4
0344     lwz r4,SL_IBAT1(r1)
0345     mtibatu 1,r4
0346     lwz r4,SL_IBAT1+4(r1)
0347     mtibatl 1,r4
0348     lwz r4,SL_IBAT2(r1)
0349     mtibatu 2,r4
0350     lwz r4,SL_IBAT2+4(r1)
0351     mtibatl 2,r4
0352     lwz r4,SL_IBAT3(r1)
0353     mtibatu 3,r4
0354     lwz r4,SL_IBAT3+4(r1)
0355     mtibatl 3,r4
0356 
0357 BEGIN_MMU_FTR_SECTION
0358     lwz r4,SL_DBAT4(r1)
0359     mtspr   SPRN_DBAT4U,r4
0360     lwz r4,SL_DBAT4+4(r1)
0361     mtspr   SPRN_DBAT4L,r4
0362     lwz r4,SL_DBAT5(r1)
0363     mtspr   SPRN_DBAT5U,r4
0364     lwz r4,SL_DBAT5+4(r1)
0365     mtspr   SPRN_DBAT5L,r4
0366     lwz r4,SL_DBAT6(r1)
0367     mtspr   SPRN_DBAT6U,r4
0368     lwz r4,SL_DBAT6+4(r1)
0369     mtspr   SPRN_DBAT6L,r4
0370     lwz r4,SL_DBAT7(r1)
0371     mtspr   SPRN_DBAT7U,r4
0372     lwz r4,SL_DBAT7+4(r1)
0373     mtspr   SPRN_DBAT7L,r4
0374     lwz r4,SL_IBAT4(r1)
0375     mtspr   SPRN_IBAT4U,r4
0376     lwz r4,SL_IBAT4+4(r1)
0377     mtspr   SPRN_IBAT4L,r4
0378     lwz r4,SL_IBAT5(r1)
0379     mtspr   SPRN_IBAT5U,r4
0380     lwz r4,SL_IBAT5+4(r1)
0381     mtspr   SPRN_IBAT5L,r4
0382     lwz r4,SL_IBAT6(r1)
0383     mtspr   SPRN_IBAT6U,r4
0384     lwz r4,SL_IBAT6+4(r1)
0385     mtspr   SPRN_IBAT6L,r4
0386     lwz r4,SL_IBAT7(r1)
0387     mtspr   SPRN_IBAT7U,r4
0388     lwz r4,SL_IBAT7+4(r1)
0389     mtspr   SPRN_IBAT7L,r4
0390 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
0391 
0392     /* Flush all TLBs */
0393     lis r4,0x1000
0394 1:  addic.  r4,r4,-0x1000
0395     tlbie   r4
0396     blt 1b
0397     sync
0398 
0399     /* Restore TB */
0400     li  r3,0
0401     mttbl   r3
0402     lwz r3,SL_TB(r1)
0403     lwz r4,SL_TB+4(r1)
0404     mttbu   r3
0405     mttbl   r4
0406 
0407     /* Restore the callee-saved registers and return */
0408     lwz r0,SL_CR(r1)
0409     mtcr    r0
0410     lwz r2,SL_R2(r1)
0411     lmw r12,SL_R12(r1)
0412 
0413     /* restore the MSR and SP and turn on the MMU and return */
0414     lwz r3,SL_MSR(r1)
0415     lwz r4,SL_LR(r1)
0416     lwz r1,SL_SP(r1)
0417     mtsrr0  r4
0418     mtsrr1  r3
0419     sync
0420     isync
0421     rfi
0422 _ASM_NOKPROBE_SYMBOL(grackle_wake_up)
0423 
0424 #endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
0425 
0426     .section .bss
0427     .balign L1_CACHE_BYTES
0428 sleep_storage:
0429     .space SL_SIZE
0430     .balign L1_CACHE_BYTES, 0
0431 
0432 #endif /* CONFIG_PPC_BOOK3S_32 */
0433     .section .text