160 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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 */
 | 
