1/*	$NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $	*/
2
3/*-
4 * Copyright (c) 2007 Olivier Houchard
5 * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
6 * All rights reserved.
7 *
8 * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed for the NetBSD Project by
21 *	Wasabi Systems, Inc.
22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23 *    or promote products derived from this software without specific prior
24 *    written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *
38 */
39
40/*-
41 * Copyright (c) 2001 Matt Thomas.
42 * Copyright (c) 1997,1998 Mark Brinicombe.
43 * Copyright (c) 1997 Causality Limited
44 * All rights reserved.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 *    notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 *    notice, this list of conditions and the following disclaimer in the
53 *    documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 *    must display the following acknowledgement:
56 *	This product includes software developed by Causality Limited.
57 * 4. The name of Causality Limited may not be used to endorse or promote
58 *    products derived from this software without specific prior written
59 *    permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
62 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
65 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
66 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
67 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 *
73 * XScale core 3 assembly functions for CPU / MMU / TLB specific operations
74 */
75
76#include <machine/armreg.h>
77#include <machine/asm.h>
78__FBSDID("$FreeBSD: stable/11/sys/arm/arm/cpufunc_asm_xscale_c3.S 331890 2018-04-02 22:02:49Z gonzo $");
79
80/*
81 * Size of the XScale core D-cache.
82 */
83#define	DCACHE_SIZE		0x00008000
84
85/*
86 * CPWAIT -- Canonical method to wait for CP15 update.
87 * From: Intel 80200 manual, section 2.3.3.
88 *
89 * NOTE: Clobbers the specified temp reg.
90 */
91#define	CPWAIT_BRANCH							 \
92	sub	pc, pc, #4
93
94#define	CPWAIT(tmp)							 \
95	mrc	p15, 0, tmp, c2, c0, 0	/* arbitrary read of CP15 */	;\
96	mov	tmp, tmp		/* wait for it to complete */	;\
97	CPWAIT_BRANCH			/* branch to next insn */
98
99#define	CPWAIT_AND_RETURN_SHIFTER	lsr #32
100
101#define	CPWAIT_AND_RETURN(tmp)						 \
102	mrc	p15, 0, tmp, c2, c0, 0	/* arbitrary read of CP15 */	;\
103	/* Wait for it to complete and branch to the return address */	 \
104	sub	pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
105
106#define ARM_USE_L2_CACHE
107
108#define L2_CACHE_SIZE		0x80000
109#define L2_CACHE_WAYS		8
110#define L2_CACHE_LINE_SIZE	32
111#define L2_CACHE_SETS		(L2_CACHE_SIZE / \
112    (L2_CACHE_WAYS * L2_CACHE_LINE_SIZE))
113
114#define L1_DCACHE_SIZE		32 * 1024
115#define L1_DCACHE_WAYS		4
116#define L1_DCACHE_LINE_SIZE	32
117#define L1_DCACHE_SETS		(L1_DCACHE_SIZE / \
118    (L1_DCACHE_WAYS * L1_DCACHE_LINE_SIZE))
119#ifdef CACHE_CLEAN_BLOCK_INTR
120#define	XSCALE_CACHE_CLEAN_BLOCK					\
121	stmfd	sp!, {r4}					;	\
122	mrs	r4, cpsr					;	\
123	orr	r0, r4, #(PSR_I | PSR_F)			;	\
124	msr	cpsr_fsxc, r0
125
126#define	XSCALE_CACHE_CLEAN_UNBLOCK					\
127	msr	cpsr_fsxc, r4					;	\
128	ldmfd	sp!, {r4}
129#else
130#define	XSCALE_CACHE_CLEAN_BLOCK
131#define	XSCALE_CACHE_CLEAN_UNBLOCK
132#endif /* CACHE_CLEAN_BLOCK_INTR */
133
134
135ENTRY_NP(xscalec3_cache_syncI)
136EENTRY_NP(xscalec3_cache_purgeID)
137	mcr	p15, 0, r0, c7, c5, 0	/* flush I cache (D cleaned below) */
138EENTRY_NP(xscalec3_cache_cleanID)
139EENTRY_NP(xscalec3_cache_purgeD)
140EENTRY(xscalec3_cache_cleanD)
141
142	XSCALE_CACHE_CLEAN_BLOCK
143	mov	r0, #0
1441:
145	mov	r1, r0, asl #30
146	mov	r2, #0
1472:
148	orr	r3, r1, r2, asl #5
149	mcr	p15, 0, r3, c7, c14, 2	/* clean and invalidate */
150	add	r2, r2, #1
151	cmp	r2, #L1_DCACHE_SETS
152	bne	2b
153	add	r0, r0, #1
154	cmp	r0, #4
155	bne	1b
156	CPWAIT(r0)
157	XSCALE_CACHE_CLEAN_UNBLOCK
158	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
159
160	RET
161EEND(xscalec3_cache_purgeID)
162EEND(xscalec3_cache_cleanID)
163EEND(xscalec3_cache_purgeD)
164EEND(xscalec3_cache_cleanD)
165END(xscalec3_cache_syncI)
166
167ENTRY(xscalec3_cache_purgeID_rng)
168
169	cmp	r1, #0x4000
170	bcs	_C_LABEL(xscalec3_cache_cleanID)
171	and	r2, r0, #0x1f
172	add	r1, r1, r2
173	bic	r0, r0, #0x1f
174
1751:	mcr	p15, 0, r0, c7, c14, 1	/* clean/invalidate L1 D cache entry */
176	nop
177	mcr	p15, 0, r0, c7, c5, 1	/* flush I cache single entry */
178	add	r0, r0, #32
179	subs	r1, r1, #32
180	bhi	1b
181
182	CPWAIT(r0)
183
184	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
185
186	CPWAIT_AND_RETURN(r0)
187END(xscalec3_cache_purgeID_rng)
188
189ENTRY(xscalec3_cache_syncI_rng)
190	cmp	r1, #0x4000
191	bcs	_C_LABEL(xscalec3_cache_syncI)
192
193	and	r2, r0, #0x1f
194	add	r1, r1, r2
195	bic	r0, r0, #0x1f
196
1971:	mcr	p15, 0, r0, c7, c10, 1	/* clean D cache entry */
198	mcr	p15, 0, r0, c7, c5, 1	/* flush I cache single entry */
199	add	r0, r0, #32
200	subs	r1, r1, #32
201	bhi	1b
202
203	CPWAIT(r0)
204
205	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
206
207	CPWAIT_AND_RETURN(r0)
208END(xscalec3_cache_syncI_rng)
209
210ENTRY(xscalec3_cache_purgeD_rng)
211
212	cmp	r1, #0x4000
213	bcs	_C_LABEL(xscalec3_cache_cleanID)
214	and	r2, r0, #0x1f
215	add	r1, r1, r2
216	bic	r0, r0, #0x1f
217
2181:	mcr	p15, 0, r0, c7, c14, 1	/* Clean and invalidate D cache entry */
219	add	r0, r0, #32
220	subs	r1, r1, #32
221	bhi	1b
222
223	CPWAIT(r0)
224
225	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
226
227	CPWAIT_AND_RETURN(r0)
228END(xscalec3_cache_purgeD_rng)
229
230ENTRY(xscalec3_cache_cleanID_rng)
231EENTRY(xscalec3_cache_cleanD_rng)
232
233	cmp	r1, #0x4000
234	bcs	_C_LABEL(xscalec3_cache_cleanID)
235	and	r2, r0, #0x1f
236	add	r1, r1, r2
237	bic	r0, r0, #0x1f
238
2391:	mcr	p15, 0, r0, c7, c10, 1	/* clean L1 D cache entry */
240	nop
241	add	r0, r0, #32
242	subs	r1, r1, #32
243	bhi	1b
244
245	CPWAIT(r0)
246
247	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
248
249	CPWAIT_AND_RETURN(r0)
250EEND(xscalec3_cache_cleanD_rng)
251END(xscalec3_cache_cleanID_rng)
252
253ENTRY(xscalec3_l2cache_purge)
254	/* Clean-up the L2 cache */
255	mcr	p15, 0, r0, c7, c10, 5	/* Data memory barrier */
256	mov	r0, #0
2571:
258	mov	r1, r0, asl #29
259	mov	r2, #0
2602:
261	orr	r3, r1, r2, asl #5
262	mcr	p15, 1, r3, c7, c15, 2
263	add	r2, r2, #1
264	cmp	r2, #L2_CACHE_SETS
265	bne	2b
266	add	r0, r0, #1
267	cmp	r0, #8
268	bne	1b
269	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
270
271	CPWAIT(r0)
272	mcr	p15, 0, r0, c7, c10, 5	/* Data memory barrier */
273	RET
274END(xscalec3_l2cache_purge)
275
276ENTRY(xscalec3_l2cache_clean_rng)
277	mcr	p15, 0, r0, c7, c10, 5	/* Data memory barrier */
278
279	and	r2, r0, #0x1f
280	add	r1, r1, r2
281	bic	r0, r0, #0x1f
282
2831:	mcr	p15, 1, r0, c7, c11, 1	/* Clean L2 D cache entry */
284	add	r0, r0, #32
285	subs	r1, r1, #32
286	bhi	1b
287
288
289	CPWAIT(r0)
290
291	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
292	mcr	p15, 0, r0, c7, c10, 5
293
294	CPWAIT_AND_RETURN(r0)
295END(xscalec3_l2cache_clean_rng)
296
297ENTRY(xscalec3_l2cache_purge_rng)
298
299	mcr	p15, 0, r0, c7, c10, 5	/* Data memory barrier */
300
301	and	r2, r0, #0x1f
302	add	r1, r1, r2
303	bic	r0, r0, #0x1f
304
3051:	mcr	p15, 1, r0, c7, c11, 1	/* Clean L2 D cache entry */
306	mcr	p15, 1, r0, c7, c7, 1   /* Invalidate L2 D cache entry */
307	add	r0, r0, #32
308	subs	r1, r1, #32
309	bhi	1b
310
311	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
312	mcr	p15, 0, r0, c7, c10, 5
313
314	CPWAIT_AND_RETURN(r0)
315END(xscalec3_l2cache_purge_rng)
316
317ENTRY(xscalec3_l2cache_flush_rng)
318	mcr	p15, 0, r0, c7, c10, 5	/* Data memory barrier */
319
320	and	r2, r0, #0x1f
321	add	r1, r1, r2
322	bic	r0, r0, #0x1f
323
3241:	mcr	p15, 1, r0, c7, c7, 1   /* Invalidate L2 cache line */
325	add	r0, r0, #32
326	subs	r1, r1, #32
327	bhi	1b
328	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
329	mcr	p15, 0, r0, c7, c10, 5
330	CPWAIT_AND_RETURN(r0)
331END(xscalec3_l2cache_flush_rng)
332
333/*
334 * Functions to set the MMU Translation Table Base register
335 *
336 * We need to clean and flush the cache as it uses virtual
337 * addresses that are about to change.
338 */
339ENTRY(xscalec3_setttb)
340#ifdef CACHE_CLEAN_BLOCK_INTR
341	mrs	r3, cpsr
342	orr	r1, r3, #(PSR_I | PSR_F)
343	msr	cpsr_fsxc, r1
344#endif
345	stmfd	sp!, {r0-r3, lr}
346	bl	_C_LABEL(xscalec3_cache_cleanID)
347	mcr	p15, 0, r0, c7, c5, 0	/* invalidate I$ and BTB */
348	mcr	p15, 0, r0, c7, c10, 4	/* drain write and fill buffer */
349
350	CPWAIT(r0)
351
352	ldmfd	sp!, {r0-r3, lr}
353
354#ifdef ARM_USE_L2_CACHE
355	orr	r0, r0, #0x18	/* cache the page table in L2 */
356#endif
357	/* Write the TTB */
358	mcr	p15, 0, r0, c2, c0, 0
359
360	/* If we have updated the TTB we must flush the TLB */
361	mcr	p15, 0, r0, c8, c7, 0	/* invalidate I+D TLB */
362
363	CPWAIT(r0)
364
365#ifdef CACHE_CLEAN_BLOCK_INTR
366	msr	cpsr_fsxc, r3
367#endif
368	RET
369END(xscalec3_setttb)
370
371/*
372 * Context switch.
373 *
374 * These is the CPU-specific parts of the context switcher cpu_switch()
375 * These functions actually perform the TTB reload.
376 *
377 * NOTE: Special calling convention
378 *	r1, r4-r13 must be preserved
379 */
380ENTRY(xscalec3_context_switch)
381	/*
382	 * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
383	 * Thus the data cache will contain only kernel data and the
384	 * instruction cache will contain only kernel code, and all
385	 * kernel mappings are shared by all processes.
386	 */
387#ifdef ARM_USE_L2_CACHE
388	orr	r0, r0, #0x18	/* Cache the page table in L2 */
389#endif
390	/* Write the TTB */
391	mcr	p15, 0, r0, c2, c0, 0
392
393	/* If we have updated the TTB we must flush the TLB */
394	mcr	p15, 0, r0, c8, c7, 0	/* flush the I+D tlb */
395
396	CPWAIT_AND_RETURN(r0)
397END(xscalec3_context_switch)
398
399