Path: blob/master/arch/powerpc/platforms/powermac/sleep.S
26481 views
/* SPDX-License-Identifier: GPL-2.0-or-later */1/*2* This file contains sleep low-level functions for PowerBook G3.3* Copyright (C) 1999 Benjamin Herrenschmidt ([email protected])4* and Paul Mackerras ([email protected]).5*/67#include <asm/processor.h>8#include <asm/page.h>9#include <asm/ppc_asm.h>10#include <asm/cputable.h>11#include <asm/cache.h>12#include <asm/thread_info.h>13#include <asm/asm-offsets.h>14#include <asm/mmu.h>15#include <asm/feature-fixups.h>1617#define MAGIC 0x4c617273 /* 'Lars' */1819/*20* Structure for storing CPU registers on the stack.21*/22#define SL_SP 023#define SL_PC 424#define SL_MSR 825#define SL_SDR1 0xc26#define SL_SPRG0 0x10 /* 4 sprg's */27#define SL_DBAT0 0x2028#define SL_IBAT0 0x2829#define SL_DBAT1 0x3030#define SL_IBAT1 0x3831#define SL_DBAT2 0x4032#define SL_IBAT2 0x4833#define SL_DBAT3 0x5034#define SL_IBAT3 0x5835#define SL_DBAT4 0x6036#define SL_IBAT4 0x6837#define SL_DBAT5 0x7038#define SL_IBAT5 0x7839#define SL_DBAT6 0x8040#define SL_IBAT6 0x8841#define SL_DBAT7 0x9042#define SL_IBAT7 0x9843#define SL_TB 0xa044#define SL_R2 0xa845#define SL_CR 0xac46#define SL_LR 0xb047#define SL_R12 0xb4 /* r12 to r31 */48#define SL_SIZE (SL_R12 + 80)4950.section .text51.align 55253#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \54(defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32))5556/* This gets called by via-pmu.c late during the sleep process.57* The PMU was already send the sleep command and will shut us down58* soon. We need to save all that is needed and setup the wakeup59* vector that will be called by the ROM on wakeup60*/61_GLOBAL(low_sleep_handler)62#ifndef CONFIG_PPC_BOOK3S_3263blr64#else65mflr r066lis r11,sleep_storage@ha67addi r11,r11,sleep_storage@l68stw r0,SL_LR(r11)69mfcr r070stw r0,SL_CR(r11)71stw r1,SL_SP(r11)72stw r2,SL_R2(r11)73stmw r12,SL_R12(r11)7475/* Save MSR & SDR1 */76mfmsr r477stw r4,SL_MSR(r11)78mfsdr1 r479stw r4,SL_SDR1(r11)8081/* Get a stable timebase and save it */821: mftbu r483stw r4,SL_TB(r11)84mftb r585stw r5,SL_TB+4(r11)86mftbu r387cmpw r3,r488bne 1b8990/* Save SPRGs */91mfsprg r4,092stw r4,SL_SPRG0(r11)93mfsprg r4,194stw r4,SL_SPRG0+4(r11)95mfsprg r4,296stw r4,SL_SPRG0+8(r11)97mfsprg r4,398stw r4,SL_SPRG0+12(r11)99100/* Save BATs */101mfdbatu r4,0102stw r4,SL_DBAT0(r11)103mfdbatl r4,0104stw r4,SL_DBAT0+4(r11)105mfdbatu r4,1106stw r4,SL_DBAT1(r11)107mfdbatl r4,1108stw r4,SL_DBAT1+4(r11)109mfdbatu r4,2110stw r4,SL_DBAT2(r11)111mfdbatl r4,2112stw r4,SL_DBAT2+4(r11)113mfdbatu r4,3114stw r4,SL_DBAT3(r11)115mfdbatl r4,3116stw r4,SL_DBAT3+4(r11)117mfibatu r4,0118stw r4,SL_IBAT0(r11)119mfibatl r4,0120stw r4,SL_IBAT0+4(r11)121mfibatu r4,1122stw r4,SL_IBAT1(r11)123mfibatl r4,1124stw r4,SL_IBAT1+4(r11)125mfibatu r4,2126stw r4,SL_IBAT2(r11)127mfibatl r4,2128stw r4,SL_IBAT2+4(r11)129mfibatu r4,3130stw r4,SL_IBAT3(r11)131mfibatl r4,3132stw r4,SL_IBAT3+4(r11)133134BEGIN_MMU_FTR_SECTION135mfspr r4,SPRN_DBAT4U136stw r4,SL_DBAT4(r11)137mfspr r4,SPRN_DBAT4L138stw r4,SL_DBAT4+4(r11)139mfspr r4,SPRN_DBAT5U140stw r4,SL_DBAT5(r11)141mfspr r4,SPRN_DBAT5L142stw r4,SL_DBAT5+4(r11)143mfspr r4,SPRN_DBAT6U144stw r4,SL_DBAT6(r11)145mfspr r4,SPRN_DBAT6L146stw r4,SL_DBAT6+4(r11)147mfspr r4,SPRN_DBAT7U148stw r4,SL_DBAT7(r11)149mfspr r4,SPRN_DBAT7L150stw r4,SL_DBAT7+4(r11)151mfspr r4,SPRN_IBAT4U152stw r4,SL_IBAT4(r11)153mfspr r4,SPRN_IBAT4L154stw r4,SL_IBAT4+4(r11)155mfspr r4,SPRN_IBAT5U156stw r4,SL_IBAT5(r11)157mfspr r4,SPRN_IBAT5L158stw r4,SL_IBAT5+4(r11)159mfspr r4,SPRN_IBAT6U160stw r4,SL_IBAT6(r11)161mfspr r4,SPRN_IBAT6L162stw r4,SL_IBAT6+4(r11)163mfspr r4,SPRN_IBAT7U164stw r4,SL_IBAT7(r11)165mfspr r4,SPRN_IBAT7L166stw r4,SL_IBAT7+4(r11)167END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)168169/* Backup various CPU config stuffs */170bl __save_cpu_setup171172/* The ROM can wake us up via 2 different vectors:173* - On wallstreet & lombard, we must write a magic174* value 'Lars' at address 4 and a pointer to a175* memory location containing the PC to resume from176* at address 0.177* - On Core99, we must store the wakeup vector at178* address 0x80 and eventually its parameters179* at address 0x84. I've have some trouble with those180* parameters however and I no longer use them.181*/182lis r5,grackle_wake_up@ha183addi r5,r5,grackle_wake_up@l184tophys(r5,r5)185stw r5,SL_PC(r11)186lis r4,KERNELBASE@h187tophys(r5,r11)188addi r5,r5,SL_PC189lis r6,MAGIC@ha190addi r6,r6,MAGIC@l191stw r5,0(r4)192stw r6,4(r4)193/* Setup stuffs at 0x80-0x84 for Core99 */194lis r3,core99_wake_up@ha195addi r3,r3,core99_wake_up@l196tophys(r3,r3)197stw r3,0x80(r4)198stw r5,0x84(r4)199200.globl low_cpu_offline_self201low_cpu_offline_self:202/* Flush & disable all caches */203bl flush_disable_caches204205/* Turn off data relocation. */206mfmsr r3 /* Save MSR in r7 */207rlwinm r3,r3,0,28,26 /* Turn off DR bit */208sync209mtmsr r3210isync211212BEGIN_FTR_SECTION213/* Flush any pending L2 data prefetches to work around HW bug */214sync215lis r3,0xfff0216lwz r0,0(r3) /* perform cache-inhibited load to ROM */217sync /* (caches are disabled at this point) */218END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)219220/*221* Set the HID0 and MSR for sleep.222*/223mfspr r2,SPRN_HID0224rlwinm r2,r2,0,10,7 /* clear doze, nap */225oris r2,r2,HID0_SLEEP@h226sync227isync228mtspr SPRN_HID0,r2229sync230231/* This loop puts us back to sleep in case we have a spurrious232* wakeup so that the host bridge properly stays asleep. The233* CPU will be turned off, either after a known time (about 1234* second) on wallstreet & lombard, or as soon as the CPU enters235* SLEEP mode on core99236*/237mfmsr r2238oris r2,r2,MSR_POW@h2391: sync240mtmsr r2241isync242b 1b243_ASM_NOKPROBE_SYMBOL(low_cpu_offline_self)244/*245* Here is the resume code.246*/247248249/*250* Core99 machines resume here251* r4 has the physical address of SL_PC(sp) (unused)252*/253_GLOBAL(core99_wake_up)254/* Make sure HID0 no longer contains any sleep bit and that data cache255* is disabled256*/257mfspr r3,SPRN_HID0258rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */259rlwinm 3,r3,0,18,15 /* clear DCE, ICE */260mtspr SPRN_HID0,r3261sync262isync263264/* sanitize MSR */265mfmsr r3266ori r3,r3,MSR_EE|MSR_IP267xori r3,r3,MSR_EE|MSR_IP268sync269isync270mtmsr r3271sync272isync273274/* Recover sleep storage */275lis r3,sleep_storage@ha276addi r3,r3,sleep_storage@l277tophys(r3,r3)278addi r1,r3,SL_PC279280/* Pass thru to older resume code ... */281_ASM_NOKPROBE_SYMBOL(core99_wake_up)282/*283* Here is the resume code for older machines.284* r1 has the physical address of SL_PC(sp).285*/286287grackle_wake_up:288289/* Restore the kernel's segment registers before290* we do any r1 memory access as we are not sure they291* are in a sane state above the first 256Mb region292*/293bl load_segment_registers294sync295isync296297subi r1,r1,SL_PC298299/* Restore various CPU config stuffs */300bl __restore_cpu_setup301302/* Make sure all FPRs have been initialized */303bl reloc_offset304bl __init_fpu_registers305306/* Invalidate & enable L1 cache, we don't care about307* whatever the ROM may have tried to write to memory308*/309bl __inval_enable_L1310311/* Restore the BATs, and SDR1. Then we can turn on the MMU. */312lwz r4,SL_SDR1(r1)313mtsdr1 r4314lwz r4,SL_SPRG0(r1)315mtsprg 0,r4316lwz r4,SL_SPRG0+4(r1)317mtsprg 1,r4318lwz r4,SL_SPRG0+8(r1)319mtsprg 2,r4320lwz r4,SL_SPRG0+12(r1)321mtsprg 3,r4322323lwz r4,SL_DBAT0(r1)324mtdbatu 0,r4325lwz r4,SL_DBAT0+4(r1)326mtdbatl 0,r4327lwz r4,SL_DBAT1(r1)328mtdbatu 1,r4329lwz r4,SL_DBAT1+4(r1)330mtdbatl 1,r4331lwz r4,SL_DBAT2(r1)332mtdbatu 2,r4333lwz r4,SL_DBAT2+4(r1)334mtdbatl 2,r4335lwz r4,SL_DBAT3(r1)336mtdbatu 3,r4337lwz r4,SL_DBAT3+4(r1)338mtdbatl 3,r4339lwz r4,SL_IBAT0(r1)340mtibatu 0,r4341lwz r4,SL_IBAT0+4(r1)342mtibatl 0,r4343lwz r4,SL_IBAT1(r1)344mtibatu 1,r4345lwz r4,SL_IBAT1+4(r1)346mtibatl 1,r4347lwz r4,SL_IBAT2(r1)348mtibatu 2,r4349lwz r4,SL_IBAT2+4(r1)350mtibatl 2,r4351lwz r4,SL_IBAT3(r1)352mtibatu 3,r4353lwz r4,SL_IBAT3+4(r1)354mtibatl 3,r4355356BEGIN_MMU_FTR_SECTION357lwz r4,SL_DBAT4(r1)358mtspr SPRN_DBAT4U,r4359lwz r4,SL_DBAT4+4(r1)360mtspr SPRN_DBAT4L,r4361lwz r4,SL_DBAT5(r1)362mtspr SPRN_DBAT5U,r4363lwz r4,SL_DBAT5+4(r1)364mtspr SPRN_DBAT5L,r4365lwz r4,SL_DBAT6(r1)366mtspr SPRN_DBAT6U,r4367lwz r4,SL_DBAT6+4(r1)368mtspr SPRN_DBAT6L,r4369lwz r4,SL_DBAT7(r1)370mtspr SPRN_DBAT7U,r4371lwz r4,SL_DBAT7+4(r1)372mtspr SPRN_DBAT7L,r4373lwz r4,SL_IBAT4(r1)374mtspr SPRN_IBAT4U,r4375lwz r4,SL_IBAT4+4(r1)376mtspr SPRN_IBAT4L,r4377lwz r4,SL_IBAT5(r1)378mtspr SPRN_IBAT5U,r4379lwz r4,SL_IBAT5+4(r1)380mtspr SPRN_IBAT5L,r4381lwz r4,SL_IBAT6(r1)382mtspr SPRN_IBAT6U,r4383lwz r4,SL_IBAT6+4(r1)384mtspr SPRN_IBAT6L,r4385lwz r4,SL_IBAT7(r1)386mtspr SPRN_IBAT7U,r4387lwz r4,SL_IBAT7+4(r1)388mtspr SPRN_IBAT7L,r4389END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)390391/* Flush all TLBs */392lis r4,0x10003931: addic. r4,r4,-0x1000394tlbie r4395blt 1b396sync397398/* Restore TB */399li r3,0400mttbl r3401lwz r3,SL_TB(r1)402lwz r4,SL_TB+4(r1)403mttbu r3404mttbl r4405406/* Restore the callee-saved registers and return */407lwz r0,SL_CR(r1)408mtcr r0409lwz r2,SL_R2(r1)410lmw r12,SL_R12(r1)411412/* restore the MSR and SP and turn on the MMU and return */413lwz r3,SL_MSR(r1)414lwz r4,SL_LR(r1)415lwz r1,SL_SP(r1)416mtsrr0 r4417mtsrr1 r3418sync419isync420rfi421_ASM_NOKPROBE_SYMBOL(grackle_wake_up)422423#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */424425.section .bss426.balign L1_CACHE_BYTES427sleep_storage:428.space SL_SIZE429.balign L1_CACHE_BYTES, 0430431#endif /* CONFIG_PPC_BOOK3S_32 */432.section .text433434435