1/*
2 * Copyright (C) 2014 Imagination Technologies Ltd
3 *
4 * This program is free software; you can redistribute	it and/or modify it
5 * under  the terms of	the GNU General	 Public License as published by the
6 * Free Software Foundation;  either version 2 of the  License, or (at your
7 * option) any later version.
8 *
9 * PM helper macros for CPU power off (e.g. Suspend-to-RAM).
10 */
11
12#ifndef __ASM_PM_H
13#define __ASM_PM_H
14
15#ifdef __ASSEMBLY__
16
17#include <asm/asm-offsets.h>
18#include <asm/asm.h>
19#include <asm/mipsregs.h>
20#include <asm/regdef.h>
21
22/* Save CPU state to stack for suspend to RAM */
23.macro SUSPEND_SAVE_REGS
24	subu	sp, PT_SIZE
25	/* Call preserved GPRs */
26	LONG_S	$16, PT_R16(sp)
27	LONG_S	$17, PT_R17(sp)
28	LONG_S	$18, PT_R18(sp)
29	LONG_S	$19, PT_R19(sp)
30	LONG_S	$20, PT_R20(sp)
31	LONG_S	$21, PT_R21(sp)
32	LONG_S	$22, PT_R22(sp)
33	LONG_S	$23, PT_R23(sp)
34	LONG_S	$28, PT_R28(sp)
35	LONG_S	$30, PT_R30(sp)
36	LONG_S	$31, PT_R31(sp)
37	/* A couple of CP0 registers with space in pt_regs */
38	mfc0	k0, CP0_STATUS
39	LONG_S	k0, PT_STATUS(sp)
40.endm
41
42/* Restore CPU state from stack after resume from RAM */
43.macro RESUME_RESTORE_REGS_RETURN
44	.set	push
45	.set	noreorder
46	/* A couple of CP0 registers with space in pt_regs */
47	LONG_L	k0, PT_STATUS(sp)
48	mtc0	k0, CP0_STATUS
49	/* Call preserved GPRs */
50	LONG_L	$16, PT_R16(sp)
51	LONG_L	$17, PT_R17(sp)
52	LONG_L	$18, PT_R18(sp)
53	LONG_L	$19, PT_R19(sp)
54	LONG_L	$20, PT_R20(sp)
55	LONG_L	$21, PT_R21(sp)
56	LONG_L	$22, PT_R22(sp)
57	LONG_L	$23, PT_R23(sp)
58	LONG_L	$28, PT_R28(sp)
59	LONG_L	$30, PT_R30(sp)
60	LONG_L	$31, PT_R31(sp)
61	/* Pop and return */
62	jr	ra
63	 addiu	sp, PT_SIZE
64	.set	pop
65.endm
66
67/* Get address of static suspend state into t1 */
68.macro LA_STATIC_SUSPEND
69	la	t1, mips_static_suspend_state
70.endm
71
72/* Save important CPU state for early restoration to global data */
73.macro SUSPEND_SAVE_STATIC
74#ifdef CONFIG_EVA
75	/*
76	 * Segment configuration is saved in global data where it can be easily
77	 * reloaded without depending on the segment configuration.
78	 */
79	mfc0	k0, CP0_PAGEMASK, 2	/* SegCtl0 */
80	LONG_S	k0, SSS_SEGCTL0(t1)
81	mfc0	k0, CP0_PAGEMASK, 3	/* SegCtl1 */
82	LONG_S	k0, SSS_SEGCTL1(t1)
83	mfc0	k0, CP0_PAGEMASK, 4	/* SegCtl2 */
84	LONG_S	k0, SSS_SEGCTL2(t1)
85#endif
86	/* save stack pointer (pointing to GPRs) */
87	LONG_S	sp, SSS_SP(t1)
88.endm
89
90/* Restore important CPU state early from global data */
91.macro RESUME_RESTORE_STATIC
92#ifdef CONFIG_EVA
93	/*
94	 * Segment configuration must be restored prior to any access to
95	 * allocated memory, as it may reside outside of the legacy kernel
96	 * segments.
97	 */
98	LONG_L	k0, SSS_SEGCTL0(t1)
99	mtc0	k0, CP0_PAGEMASK, 2	/* SegCtl0 */
100	LONG_L	k0, SSS_SEGCTL1(t1)
101	mtc0	k0, CP0_PAGEMASK, 3	/* SegCtl1 */
102	LONG_L	k0, SSS_SEGCTL2(t1)
103	mtc0	k0, CP0_PAGEMASK, 4	/* SegCtl2 */
104	tlbw_use_hazard
105#endif
106	/* restore stack pointer (pointing to GPRs) */
107	LONG_L	sp, SSS_SP(t1)
108.endm
109
110/* flush caches to make sure context has reached memory */
111.macro SUSPEND_CACHE_FLUSH
112	.extern	__wback_cache_all
113	.set	push
114	.set	noreorder
115	la	t1, __wback_cache_all
116	LONG_L	t0, 0(t1)
117	jalr	t0
118	 nop
119	.set	pop
120 .endm
121
122/* Save suspend state and flush data caches to RAM */
123.macro SUSPEND_SAVE
124	SUSPEND_SAVE_REGS
125	LA_STATIC_SUSPEND
126	SUSPEND_SAVE_STATIC
127	SUSPEND_CACHE_FLUSH
128.endm
129
130/* Restore saved state after resume from RAM and return */
131.macro RESUME_RESTORE_RETURN
132	LA_STATIC_SUSPEND
133	RESUME_RESTORE_STATIC
134	RESUME_RESTORE_REGS_RETURN
135.endm
136
137#else /* __ASSEMBLY__ */
138
139/**
140 * struct mips_static_suspend_state - Core saved CPU state across S2R.
141 * @segctl:	CP0 Segment control registers.
142 * @sp:		Stack frame where GP register context is saved.
143 *
144 * This structure contains minimal CPU state that must be saved in static kernel
145 * data in order to be able to restore the rest of the state. This includes
146 * segmentation configuration in the case of EVA being enabled, as they must be
147 * restored prior to any kmalloc'd memory being referenced (even the stack
148 * pointer).
149 */
150struct mips_static_suspend_state {
151#ifdef CONFIG_EVA
152	unsigned long segctl[3];
153#endif
154	unsigned long sp;
155};
156
157#endif /* !__ASSEMBLY__ */
158
159#endif /* __ASM_PM_HELPERS_H */
160