123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- /*
- * Copyright (C) 2014 Imagination Technologies Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * PM helper macros for CPU power off (e.g. Suspend-to-RAM).
- */
- #ifndef __ASM_PM_H
- #define __ASM_PM_H
- #ifdef __ASSEMBLY__
- #include <asm/asm-offsets.h>
- #include <asm/asm.h>
- #include <asm/mipsregs.h>
- #include <asm/regdef.h>
- /* Save CPU state to stack for suspend to RAM */
- .macro SUSPEND_SAVE_REGS
- subu sp, PT_SIZE
- /* Call preserved GPRs */
- LONG_S $16, PT_R16(sp)
- LONG_S $17, PT_R17(sp)
- LONG_S $18, PT_R18(sp)
- LONG_S $19, PT_R19(sp)
- LONG_S $20, PT_R20(sp)
- LONG_S $21, PT_R21(sp)
- LONG_S $22, PT_R22(sp)
- LONG_S $23, PT_R23(sp)
- LONG_S $28, PT_R28(sp)
- LONG_S $30, PT_R30(sp)
- LONG_S $31, PT_R31(sp)
- /* A couple of CP0 registers with space in pt_regs */
- mfc0 k0, CP0_STATUS
- LONG_S k0, PT_STATUS(sp)
- .endm
- /* Restore CPU state from stack after resume from RAM */
- .macro RESUME_RESTORE_REGS_RETURN
- .set push
- .set noreorder
- /* A couple of CP0 registers with space in pt_regs */
- LONG_L k0, PT_STATUS(sp)
- mtc0 k0, CP0_STATUS
- /* Call preserved GPRs */
- LONG_L $16, PT_R16(sp)
- LONG_L $17, PT_R17(sp)
- LONG_L $18, PT_R18(sp)
- LONG_L $19, PT_R19(sp)
- LONG_L $20, PT_R20(sp)
- LONG_L $21, PT_R21(sp)
- LONG_L $22, PT_R22(sp)
- LONG_L $23, PT_R23(sp)
- LONG_L $28, PT_R28(sp)
- LONG_L $30, PT_R30(sp)
- LONG_L $31, PT_R31(sp)
- /* Pop and return */
- jr ra
- addiu sp, PT_SIZE
- .set pop
- .endm
- /* Get address of static suspend state into t1 */
- .macro LA_STATIC_SUSPEND
- la t1, mips_static_suspend_state
- .endm
- /* Save important CPU state for early restoration to global data */
- .macro SUSPEND_SAVE_STATIC
- #ifdef CONFIG_EVA
- /*
- * Segment configuration is saved in global data where it can be easily
- * reloaded without depending on the segment configuration.
- */
- mfc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
- LONG_S k0, SSS_SEGCTL0(t1)
- mfc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
- LONG_S k0, SSS_SEGCTL1(t1)
- mfc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
- LONG_S k0, SSS_SEGCTL2(t1)
- #endif
- /* save stack pointer (pointing to GPRs) */
- LONG_S sp, SSS_SP(t1)
- .endm
- /* Restore important CPU state early from global data */
- .macro RESUME_RESTORE_STATIC
- #ifdef CONFIG_EVA
- /*
- * Segment configuration must be restored prior to any access to
- * allocated memory, as it may reside outside of the legacy kernel
- * segments.
- */
- LONG_L k0, SSS_SEGCTL0(t1)
- mtc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
- LONG_L k0, SSS_SEGCTL1(t1)
- mtc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
- LONG_L k0, SSS_SEGCTL2(t1)
- mtc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
- tlbw_use_hazard
- #endif
- /* restore stack pointer (pointing to GPRs) */
- LONG_L sp, SSS_SP(t1)
- .endm
- /* flush caches to make sure context has reached memory */
- .macro SUSPEND_CACHE_FLUSH
- .extern __wback_cache_all
- .set push
- .set noreorder
- la t1, __wback_cache_all
- LONG_L t0, 0(t1)
- jalr t0
- nop
- .set pop
- .endm
- /* Save suspend state and flush data caches to RAM */
- .macro SUSPEND_SAVE
- SUSPEND_SAVE_REGS
- LA_STATIC_SUSPEND
- SUSPEND_SAVE_STATIC
- SUSPEND_CACHE_FLUSH
- .endm
- /* Restore saved state after resume from RAM and return */
- .macro RESUME_RESTORE_RETURN
- LA_STATIC_SUSPEND
- RESUME_RESTORE_STATIC
- RESUME_RESTORE_REGS_RETURN
- .endm
- #else /* __ASSEMBLY__ */
- /**
- * struct mips_static_suspend_state - Core saved CPU state across S2R.
- * @segctl: CP0 Segment control registers.
- * @sp: Stack frame where GP register context is saved.
- *
- * This structure contains minimal CPU state that must be saved in static kernel
- * data in order to be able to restore the rest of the state. This includes
- * segmentation configuration in the case of EVA being enabled, as they must be
- * restored prior to any kmalloc'd memory being referenced (even the stack
- * pointer).
- */
- struct mips_static_suspend_state {
- #ifdef CONFIG_EVA
- unsigned long segctl[3];
- #endif
- unsigned long sp;
- };
- #endif /* !__ASSEMBLY__ */
- #endif /* __ASM_PM_HELPERS_H */
|