diff options
Diffstat (limited to 'arch/mips/include/asm/pm.h')
| -rw-r--r-- | arch/mips/include/asm/pm.h | 159 | 
1 files changed, 159 insertions, 0 deletions
diff --git a/arch/mips/include/asm/pm.h b/arch/mips/include/asm/pm.h new file mode 100644 index 000000000000..7c03469e043f --- /dev/null +++ b/arch/mips/include/asm/pm.h @@ -0,0 +1,159 @@ +/* + * 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 */  |