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