18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2014 Imagination Technologies Ltd 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * PM helper macros for CPU power off (e.g. Suspend-to-RAM). 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef __ASM_PM_H 98c2ecf20Sopenharmony_ci#define __ASM_PM_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#ifdef __ASSEMBLY__ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 148c2ecf20Sopenharmony_ci#include <asm/asm.h> 158c2ecf20Sopenharmony_ci#include <asm/mipsregs.h> 168c2ecf20Sopenharmony_ci#include <asm/regdef.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* Save CPU state to stack for suspend to RAM */ 198c2ecf20Sopenharmony_ci.macro SUSPEND_SAVE_REGS 208c2ecf20Sopenharmony_ci subu sp, PT_SIZE 218c2ecf20Sopenharmony_ci /* Call preserved GPRs */ 228c2ecf20Sopenharmony_ci LONG_S $16, PT_R16(sp) 238c2ecf20Sopenharmony_ci LONG_S $17, PT_R17(sp) 248c2ecf20Sopenharmony_ci LONG_S $18, PT_R18(sp) 258c2ecf20Sopenharmony_ci LONG_S $19, PT_R19(sp) 268c2ecf20Sopenharmony_ci LONG_S $20, PT_R20(sp) 278c2ecf20Sopenharmony_ci LONG_S $21, PT_R21(sp) 288c2ecf20Sopenharmony_ci LONG_S $22, PT_R22(sp) 298c2ecf20Sopenharmony_ci LONG_S $23, PT_R23(sp) 308c2ecf20Sopenharmony_ci LONG_S $28, PT_R28(sp) 318c2ecf20Sopenharmony_ci LONG_S $30, PT_R30(sp) 328c2ecf20Sopenharmony_ci LONG_S $31, PT_R31(sp) 338c2ecf20Sopenharmony_ci /* A couple of CP0 registers with space in pt_regs */ 348c2ecf20Sopenharmony_ci mfc0 k0, CP0_STATUS 358c2ecf20Sopenharmony_ci LONG_S k0, PT_STATUS(sp) 368c2ecf20Sopenharmony_ci.endm 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* Restore CPU state from stack after resume from RAM */ 398c2ecf20Sopenharmony_ci.macro RESUME_RESTORE_REGS_RETURN 408c2ecf20Sopenharmony_ci .set push 418c2ecf20Sopenharmony_ci .set noreorder 428c2ecf20Sopenharmony_ci /* A couple of CP0 registers with space in pt_regs */ 438c2ecf20Sopenharmony_ci LONG_L k0, PT_STATUS(sp) 448c2ecf20Sopenharmony_ci mtc0 k0, CP0_STATUS 458c2ecf20Sopenharmony_ci /* Call preserved GPRs */ 468c2ecf20Sopenharmony_ci LONG_L $16, PT_R16(sp) 478c2ecf20Sopenharmony_ci LONG_L $17, PT_R17(sp) 488c2ecf20Sopenharmony_ci LONG_L $18, PT_R18(sp) 498c2ecf20Sopenharmony_ci LONG_L $19, PT_R19(sp) 508c2ecf20Sopenharmony_ci LONG_L $20, PT_R20(sp) 518c2ecf20Sopenharmony_ci LONG_L $21, PT_R21(sp) 528c2ecf20Sopenharmony_ci LONG_L $22, PT_R22(sp) 538c2ecf20Sopenharmony_ci LONG_L $23, PT_R23(sp) 548c2ecf20Sopenharmony_ci LONG_L $28, PT_R28(sp) 558c2ecf20Sopenharmony_ci LONG_L $30, PT_R30(sp) 568c2ecf20Sopenharmony_ci LONG_L $31, PT_R31(sp) 578c2ecf20Sopenharmony_ci /* Pop and return */ 588c2ecf20Sopenharmony_ci jr ra 598c2ecf20Sopenharmony_ci addiu sp, PT_SIZE 608c2ecf20Sopenharmony_ci .set pop 618c2ecf20Sopenharmony_ci.endm 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* Get address of static suspend state into t1 */ 648c2ecf20Sopenharmony_ci.macro LA_STATIC_SUSPEND 658c2ecf20Sopenharmony_ci la t1, mips_static_suspend_state 668c2ecf20Sopenharmony_ci.endm 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Save important CPU state for early restoration to global data */ 698c2ecf20Sopenharmony_ci.macro SUSPEND_SAVE_STATIC 708c2ecf20Sopenharmony_ci#ifdef CONFIG_EVA 718c2ecf20Sopenharmony_ci /* 728c2ecf20Sopenharmony_ci * Segment configuration is saved in global data where it can be easily 738c2ecf20Sopenharmony_ci * reloaded without depending on the segment configuration. 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ci mfc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */ 768c2ecf20Sopenharmony_ci LONG_S k0, SSS_SEGCTL0(t1) 778c2ecf20Sopenharmony_ci mfc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */ 788c2ecf20Sopenharmony_ci LONG_S k0, SSS_SEGCTL1(t1) 798c2ecf20Sopenharmony_ci mfc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */ 808c2ecf20Sopenharmony_ci LONG_S k0, SSS_SEGCTL2(t1) 818c2ecf20Sopenharmony_ci#endif 828c2ecf20Sopenharmony_ci /* save stack pointer (pointing to GPRs) */ 838c2ecf20Sopenharmony_ci LONG_S sp, SSS_SP(t1) 848c2ecf20Sopenharmony_ci.endm 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* Restore important CPU state early from global data */ 878c2ecf20Sopenharmony_ci.macro RESUME_RESTORE_STATIC 888c2ecf20Sopenharmony_ci#ifdef CONFIG_EVA 898c2ecf20Sopenharmony_ci /* 908c2ecf20Sopenharmony_ci * Segment configuration must be restored prior to any access to 918c2ecf20Sopenharmony_ci * allocated memory, as it may reside outside of the legacy kernel 928c2ecf20Sopenharmony_ci * segments. 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_ci LONG_L k0, SSS_SEGCTL0(t1) 958c2ecf20Sopenharmony_ci mtc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */ 968c2ecf20Sopenharmony_ci LONG_L k0, SSS_SEGCTL1(t1) 978c2ecf20Sopenharmony_ci mtc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */ 988c2ecf20Sopenharmony_ci LONG_L k0, SSS_SEGCTL2(t1) 998c2ecf20Sopenharmony_ci mtc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */ 1008c2ecf20Sopenharmony_ci tlbw_use_hazard 1018c2ecf20Sopenharmony_ci#endif 1028c2ecf20Sopenharmony_ci /* restore stack pointer (pointing to GPRs) */ 1038c2ecf20Sopenharmony_ci LONG_L sp, SSS_SP(t1) 1048c2ecf20Sopenharmony_ci.endm 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* flush caches to make sure context has reached memory */ 1078c2ecf20Sopenharmony_ci.macro SUSPEND_CACHE_FLUSH 1088c2ecf20Sopenharmony_ci .extern __wback_cache_all 1098c2ecf20Sopenharmony_ci .set push 1108c2ecf20Sopenharmony_ci .set noreorder 1118c2ecf20Sopenharmony_ci la t1, __wback_cache_all 1128c2ecf20Sopenharmony_ci LONG_L t0, 0(t1) 1138c2ecf20Sopenharmony_ci jalr t0 1148c2ecf20Sopenharmony_ci nop 1158c2ecf20Sopenharmony_ci .set pop 1168c2ecf20Sopenharmony_ci .endm 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* Save suspend state and flush data caches to RAM */ 1198c2ecf20Sopenharmony_ci.macro SUSPEND_SAVE 1208c2ecf20Sopenharmony_ci SUSPEND_SAVE_REGS 1218c2ecf20Sopenharmony_ci LA_STATIC_SUSPEND 1228c2ecf20Sopenharmony_ci SUSPEND_SAVE_STATIC 1238c2ecf20Sopenharmony_ci SUSPEND_CACHE_FLUSH 1248c2ecf20Sopenharmony_ci.endm 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/* Restore saved state after resume from RAM and return */ 1278c2ecf20Sopenharmony_ci.macro RESUME_RESTORE_RETURN 1288c2ecf20Sopenharmony_ci LA_STATIC_SUSPEND 1298c2ecf20Sopenharmony_ci RESUME_RESTORE_STATIC 1308c2ecf20Sopenharmony_ci RESUME_RESTORE_REGS_RETURN 1318c2ecf20Sopenharmony_ci.endm 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#else /* __ASSEMBLY__ */ 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci/** 1368c2ecf20Sopenharmony_ci * struct mips_static_suspend_state - Core saved CPU state across S2R. 1378c2ecf20Sopenharmony_ci * @segctl: CP0 Segment control registers. 1388c2ecf20Sopenharmony_ci * @sp: Stack frame where GP register context is saved. 1398c2ecf20Sopenharmony_ci * 1408c2ecf20Sopenharmony_ci * This structure contains minimal CPU state that must be saved in static kernel 1418c2ecf20Sopenharmony_ci * data in order to be able to restore the rest of the state. This includes 1428c2ecf20Sopenharmony_ci * segmentation configuration in the case of EVA being enabled, as they must be 1438c2ecf20Sopenharmony_ci * restored prior to any kmalloc'd memory being referenced (even the stack 1448c2ecf20Sopenharmony_ci * pointer). 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_cistruct mips_static_suspend_state { 1478c2ecf20Sopenharmony_ci#ifdef CONFIG_EVA 1488c2ecf20Sopenharmony_ci unsigned long segctl[3]; 1498c2ecf20Sopenharmony_ci#endif 1508c2ecf20Sopenharmony_ci unsigned long sp; 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci#endif /* __ASM_PM_HELPERS_H */ 156