1/*-
2 * Copyright (c) 2011 Oleksandr Tymoshenko
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <machine/asm.h>
30#include <machine/cpuregs.h>
31#include <machine/octeon_cop2.h>
32
33#include "assym.inc"
34
35.set noreorder
36
37#define SAVE_COP2_REGISTER(reg)				\
38	dmfc2	t1, reg; sd	t1, reg##_OFFSET(a0)
39
40
41#define RESTORE_COP2_REGISTER(reg)			\
42	ld	t1, reg##_OFFSET(a0); dmtc2	t1, reg##_SET
43
44LEAF(octeon_cop2_save)
45
46	/* save original cop2 status in t2*/
47	mfc0	t2, MIPS_COP_0_STATUS
48	or	t0, t2, MIPS_SR_COP_2_BIT
49	and	t0, t0, ~MIPS_SR_INT_IE
50	mtc0	t0, MIPS_COP_0_STATUS
51
52	/* Get CvmCtl register */
53	dmfc0	t0, $9, 7
54
55	/* CRC state */
56	SAVE_COP2_REGISTER(COP2_CRC_IV)
57	SAVE_COP2_REGISTER(COP2_CRC_LENGTH)
58	SAVE_COP2_REGISTER(COP2_CRC_POLY)
59
60	/* if CvmCtl[NODFA_CP2] -> save_nodfa */
61	bbit1	t0, 28, save_nodfa
62	nop
63
64	/* LLM state */
65	SAVE_COP2_REGISTER(COP2_LLM_DAT0)
66	SAVE_COP2_REGISTER(COP2_LLM_DAT1)
67
68save_nodfa:
69	/* crypto stuff is irrelevant if CvmCtl[NOCRYPTO]  */
70	bbit1	t0, 26, save_done
71	nop
72
73	SAVE_COP2_REGISTER(COP2_3DES_IV)
74	SAVE_COP2_REGISTER(COP2_3DES_KEY0)
75	SAVE_COP2_REGISTER(COP2_3DES_KEY1)
76	SAVE_COP2_REGISTER(COP2_3DES_KEY2)
77	SAVE_COP2_REGISTER(COP2_3DES_RESULT)
78
79	SAVE_COP2_REGISTER(COP2_AES_INP0)
80	SAVE_COP2_REGISTER(COP2_AES_IV0)
81	SAVE_COP2_REGISTER(COP2_AES_IV1)
82	SAVE_COP2_REGISTER(COP2_AES_KEY0)
83	SAVE_COP2_REGISTER(COP2_AES_KEY1)
84	SAVE_COP2_REGISTER(COP2_AES_KEY2)
85	SAVE_COP2_REGISTER(COP2_AES_KEY3)
86	SAVE_COP2_REGISTER(COP2_AES_KEYLEN)
87	SAVE_COP2_REGISTER(COP2_AES_RESULT0)
88	SAVE_COP2_REGISTER(COP2_AES_RESULT1)
89
90	dmfc0	t0, $15
91	li	t1, 0x000d0000 /* Octeon Pass1 */
92	beq	t0, t1, save_pass1
93	nop
94
95	SAVE_COP2_REGISTER(COP2_HSH_DATW0)
96	SAVE_COP2_REGISTER(COP2_HSH_DATW1)
97	SAVE_COP2_REGISTER(COP2_HSH_DATW2)
98	SAVE_COP2_REGISTER(COP2_HSH_DATW3)
99	SAVE_COP2_REGISTER(COP2_HSH_DATW4)
100	SAVE_COP2_REGISTER(COP2_HSH_DATW5)
101	SAVE_COP2_REGISTER(COP2_HSH_DATW6)
102	SAVE_COP2_REGISTER(COP2_HSH_DATW7)
103	SAVE_COP2_REGISTER(COP2_HSH_DATW8)
104	SAVE_COP2_REGISTER(COP2_HSH_DATW9)
105	SAVE_COP2_REGISTER(COP2_HSH_DATW10)
106	SAVE_COP2_REGISTER(COP2_HSH_DATW11)
107	SAVE_COP2_REGISTER(COP2_HSH_DATW12)
108	SAVE_COP2_REGISTER(COP2_HSH_DATW13)
109	SAVE_COP2_REGISTER(COP2_HSH_DATW14)
110	SAVE_COP2_REGISTER(COP2_HSH_IVW0)
111	SAVE_COP2_REGISTER(COP2_HSH_IVW1)
112	SAVE_COP2_REGISTER(COP2_HSH_IVW2)
113	SAVE_COP2_REGISTER(COP2_HSH_IVW3)
114	SAVE_COP2_REGISTER(COP2_HSH_IVW4)
115	SAVE_COP2_REGISTER(COP2_HSH_IVW5)
116	SAVE_COP2_REGISTER(COP2_HSH_IVW6)
117	SAVE_COP2_REGISTER(COP2_HSH_IVW7)
118	SAVE_COP2_REGISTER(COP2_GFM_MULT0)
119	SAVE_COP2_REGISTER(COP2_GFM_MULT1)
120	SAVE_COP2_REGISTER(COP2_GFM_POLY)
121	SAVE_COP2_REGISTER(COP2_GFM_RESULT0)
122	SAVE_COP2_REGISTER(COP2_GFM_RESULT1)
123	/* restore saved COP2 status */
124	mtc0	t2, MIPS_COP_0_STATUS
125	jr ra
126	nop
127
128save_pass1:
129	SAVE_COP2_REGISTER(COP2_HSH_DATW0_PASS1)
130	SAVE_COP2_REGISTER(COP2_HSH_DATW1_PASS1)
131	SAVE_COP2_REGISTER(COP2_HSH_DATW2_PASS1)
132	SAVE_COP2_REGISTER(COP2_HSH_DATW3_PASS1)
133	SAVE_COP2_REGISTER(COP2_HSH_DATW4_PASS1)
134	SAVE_COP2_REGISTER(COP2_HSH_DATW5_PASS1)
135	SAVE_COP2_REGISTER(COP2_HSH_DATW6_PASS1)
136	SAVE_COP2_REGISTER(COP2_HSH_IVW0_PASS1)
137	SAVE_COP2_REGISTER(COP2_HSH_IVW1_PASS1)
138	SAVE_COP2_REGISTER(COP2_HSH_IVW2_PASS1)
139
140save_done:
141	/* restore saved COP2 status */
142	mtc0	t2, MIPS_COP_0_STATUS
143	jr ra
144	nop
145END(octeon_cop2_save)
146
147LEAF(octeon_cop2_restore)
148	/* save original cop2 status in t2*/
149	mfc0	t2, MIPS_COP_0_STATUS
150	or	t0, t2, MIPS_SR_COP_2_BIT
151	and	t0, t0, ~MIPS_SR_INT_IE
152	mtc0	t0, MIPS_COP_0_STATUS
153	/* Get CvmCtl register */
154	dmfc0	t0, $9, 7
155
156	/* CRC state */
157	RESTORE_COP2_REGISTER(COP2_CRC_IV)
158	RESTORE_COP2_REGISTER(COP2_CRC_LENGTH)
159	RESTORE_COP2_REGISTER(COP2_CRC_POLY)
160
161	/* if CvmCtl[NODFA_CP2] -> save_nodfa */
162	bbit1	t0, 28, restore_nodfa
163	nop
164
165	/* LLM state */
166	RESTORE_COP2_REGISTER(COP2_LLM_DAT0)
167	RESTORE_COP2_REGISTER(COP2_LLM_DAT1)
168
169restore_nodfa:
170	/* crypto stuff is irrelevant if CvmCtl[NOCRYPTO]  */
171	bbit1	t0, 26, restore_done
172	nop
173
174	RESTORE_COP2_REGISTER(COP2_3DES_IV)
175	RESTORE_COP2_REGISTER(COP2_3DES_KEY0)
176	RESTORE_COP2_REGISTER(COP2_3DES_KEY1)
177	RESTORE_COP2_REGISTER(COP2_3DES_KEY2)
178	RESTORE_COP2_REGISTER(COP2_3DES_RESULT)
179
180	RESTORE_COP2_REGISTER(COP2_AES_INP0)
181	RESTORE_COP2_REGISTER(COP2_AES_IV0)
182	RESTORE_COP2_REGISTER(COP2_AES_IV1)
183	RESTORE_COP2_REGISTER(COP2_AES_KEY0)
184	RESTORE_COP2_REGISTER(COP2_AES_KEY1)
185	RESTORE_COP2_REGISTER(COP2_AES_KEY2)
186	RESTORE_COP2_REGISTER(COP2_AES_KEY3)
187	RESTORE_COP2_REGISTER(COP2_AES_KEYLEN)
188	RESTORE_COP2_REGISTER(COP2_AES_RESULT0)
189	RESTORE_COP2_REGISTER(COP2_AES_RESULT1)
190
191	dmfc0	t0, $15
192	li	t1, 0x000d0000 /* Octeon Pass1 */
193	beq	t0, t1, restore_pass1
194	nop
195
196	RESTORE_COP2_REGISTER(COP2_HSH_DATW0)
197	RESTORE_COP2_REGISTER(COP2_HSH_DATW1)
198	RESTORE_COP2_REGISTER(COP2_HSH_DATW2)
199	RESTORE_COP2_REGISTER(COP2_HSH_DATW3)
200	RESTORE_COP2_REGISTER(COP2_HSH_DATW4)
201	RESTORE_COP2_REGISTER(COP2_HSH_DATW5)
202	RESTORE_COP2_REGISTER(COP2_HSH_DATW6)
203	RESTORE_COP2_REGISTER(COP2_HSH_DATW7)
204	RESTORE_COP2_REGISTER(COP2_HSH_DATW8)
205	RESTORE_COP2_REGISTER(COP2_HSH_DATW9)
206	RESTORE_COP2_REGISTER(COP2_HSH_DATW10)
207	RESTORE_COP2_REGISTER(COP2_HSH_DATW11)
208	RESTORE_COP2_REGISTER(COP2_HSH_DATW12)
209	RESTORE_COP2_REGISTER(COP2_HSH_DATW13)
210	RESTORE_COP2_REGISTER(COP2_HSH_DATW14)
211	RESTORE_COP2_REGISTER(COP2_HSH_IVW0)
212	RESTORE_COP2_REGISTER(COP2_HSH_IVW1)
213	RESTORE_COP2_REGISTER(COP2_HSH_IVW2)
214	RESTORE_COP2_REGISTER(COP2_HSH_IVW3)
215	RESTORE_COP2_REGISTER(COP2_HSH_IVW4)
216	RESTORE_COP2_REGISTER(COP2_HSH_IVW5)
217	RESTORE_COP2_REGISTER(COP2_HSH_IVW6)
218	RESTORE_COP2_REGISTER(COP2_HSH_IVW7)
219	RESTORE_COP2_REGISTER(COP2_GFM_MULT0)
220	RESTORE_COP2_REGISTER(COP2_GFM_MULT1)
221	RESTORE_COP2_REGISTER(COP2_GFM_POLY)
222	RESTORE_COP2_REGISTER(COP2_GFM_RESULT0)
223	RESTORE_COP2_REGISTER(COP2_GFM_RESULT1)
224	/* restore saved COP2 status */
225	mtc0	t2, MIPS_COP_0_STATUS
226	jr ra
227	nop
228
229restore_pass1:
230	RESTORE_COP2_REGISTER(COP2_HSH_DATW0_PASS1)
231	RESTORE_COP2_REGISTER(COP2_HSH_DATW1_PASS1)
232	RESTORE_COP2_REGISTER(COP2_HSH_DATW2_PASS1)
233	RESTORE_COP2_REGISTER(COP2_HSH_DATW3_PASS1)
234	RESTORE_COP2_REGISTER(COP2_HSH_DATW4_PASS1)
235	RESTORE_COP2_REGISTER(COP2_HSH_DATW5_PASS1)
236	RESTORE_COP2_REGISTER(COP2_HSH_DATW6_PASS1)
237	RESTORE_COP2_REGISTER(COP2_HSH_IVW0_PASS1)
238	RESTORE_COP2_REGISTER(COP2_HSH_IVW1_PASS1)
239	RESTORE_COP2_REGISTER(COP2_HSH_IVW2_PASS1)
240
241restore_done:
242	/* restore saved COP2 status */
243	mtc0	t2, MIPS_COP_0_STATUS
244	jr ra
245	nop
246END(octeon_cop2_restore)
247