cpufunc_asm_armv7.S revision 264994
1/*-
2 * Copyright (c) 2010 Per Odlund <per.odlund@armagedon.se>
3 * Copyright (C) 2011 MARVELL INTERNATIONAL LTD.
4 * All rights reserved.
5 *
6 * Developed by Semihalf.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of MARVELL nor the names of contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <machine/asm.h>
34__FBSDID("$FreeBSD: head/sys/arm/arm/cpufunc_asm_armv7.S 264994 2014-04-27 00:46:01Z ian $");
35
36	.cpu cortex-a8
37
38.Lcoherency_level:
39	.word	_C_LABEL(arm_cache_loc)
40.Lcache_type:
41	.word	_C_LABEL(arm_cache_type)
42.Lway_mask:
43	.word	0x3ff
44.Lmax_index:
45	.word	0x7fff
46.Lpage_mask:
47	.word	0xfff
48
49#define PT_NOS          (1 << 5)
50#define PT_S 	        (1 << 1)
51#define PT_INNER_NC	0
52#define PT_INNER_WT	(1 << 0)
53#define PT_INNER_WB	((1 << 0) | (1 << 6))
54#define PT_INNER_WBWA	(1 << 6)
55#define PT_OUTER_NC	0
56#define PT_OUTER_WT	(2 << 3)
57#define PT_OUTER_WB	(3 << 3)
58#define PT_OUTER_WBWA	(1 << 3)
59
60#ifdef SMP
61#define PT_ATTR	(PT_S|PT_INNER_WBWA|PT_OUTER_WBWA|PT_NOS)
62#else
63#define PT_ATTR	(PT_INNER_WBWA|PT_OUTER_WBWA)
64#endif
65
66ENTRY(armv7_setttb)
67	stmdb   sp!, {r0, lr}
68 	bl      _C_LABEL(armv7_idcache_wbinv_all) /* clean the D cache */
69 	ldmia   sp!, {r0, lr}
70 	dsb
71
72	orr 	r0, r0, #PT_ATTR
73 	mcr	p15, 0, r0, c2, c0, 0	/* Translation Table Base Register 0 (TTBR0) */
74	isb
75#ifdef SMP
76 	mcr     p15, 0, r0, c8, c3, 0   /* invalidate I+D TLBs Inner Shareable*/
77#else
78 	mcr     p15, 0, r0, c8, c7, 0   /* invalidate I+D TLBs */
79#endif
80 	dsb
81 	isb
82	RET
83END(armv7_setttb)
84
85ENTRY(armv7_tlb_flushID)
86	dsb
87#ifdef SMP
88	mcr	p15, 0, r0, c8, c3, 0	/* flush Unified TLB all entries Inner Shareable */
89	mcr	p15, 0, r0, c7, c1, 6	/* flush BTB Inner Shareable */
90#else
91	mcr	p15, 0, r0, c8, c7, 0	/* flush Unified TLB all entries */
92	mcr	p15, 0, r0, c7, c5, 6	/* flush BTB */
93#endif
94	dsb
95	isb
96	mov	pc, lr
97END(armv7_tlb_flushID)
98
99ENTRY(armv7_tlb_flushID_SE)
100	ldr	r1, .Lpage_mask
101	bic	r0, r0, r1
102#ifdef SMP
103	mcr	p15, 0, r0, c8, c3, 3	/* flush Unified TLB single entry Inner Shareable */
104	mcr	p15, 0, r0, c7, c1, 6	/* flush BTB Inner Shareable */
105#else
106	mcr	p15, 0, r0, c8, c7, 1	/* flush Unified TLB single entry */
107	mcr	p15, 0, r0, c7, c5, 6	/* flush BTB */
108#endif
109	dsb
110	isb
111	mov	pc, lr
112END(armv7_tlb_flushID_SE)
113
114/* Based on algorithm from ARM Architecture Reference Manual */
115ENTRY(armv7_dcache_wbinv_all)
116	stmdb	sp!, {r4, r5, r6, r7, r8, r9}
117
118	/* Get cache level */
119	ldr	r0, .Lcoherency_level
120	ldr	r3, [r0]
121	cmp	r3, #0
122	beq	Finished
123	/* For each cache level */
124	mov	r8, #0
125Loop1:
126	/* Get cache type for given level */
127	mov	r2, r8, lsl #2
128	add	r2, r2, r2
129	ldr	r0, .Lcache_type
130	ldr	r1, [r0, r2]
131
132	/* Get line size */
133	and	r2, r1, #7
134	add	r2, r2, #4
135
136	/* Get number of ways */
137	ldr	r4, .Lway_mask
138	ands	r4, r4, r1, lsr #3
139	clz	r5, r4
140
141	/* Get max index */
142	ldr	r7, .Lmax_index
143	ands	r7, r7, r1, lsr #13
144Loop2:
145	mov	r9, r4
146Loop3:
147	mov	r6, r8, lsl #1
148	orr	r6, r6, r9, lsl r5
149	orr	r6, r6, r7, lsl r2
150
151	/* Clean and invalidate data cache by way/index */
152	mcr	p15, 0, r6, c7, c14, 2
153	subs	r9, r9, #1
154	bge	Loop3
155	subs	r7, r7, #1
156	bge	Loop2
157Skip:
158	add	r8, r8, #1
159	cmp	r3, r8
160	bne Loop1
161Finished:
162	dsb
163	ldmia	sp!, {r4, r5, r6, r7, r8, r9}
164	RET
165END(armv7_dcache_wbinv_all)
166
167ENTRY(armv7_idcache_wbinv_all)
168	stmdb	sp!, {lr}
169	bl armv7_dcache_wbinv_all
170#ifdef SMP
171	mcr	p15, 0, r0, c7, c1, 0	/* Invalidate all I caches to PoU (ICIALLUIS) */
172#else
173	mcr	p15, 0, r0, c7, c5, 0	/* Invalidate all I caches to PoU (ICIALLU) */
174#endif
175	dsb
176	isb
177	ldmia	sp!, {lr}
178	RET
179END(armv7_idcache_wbinv_all)
180
181/* XXX Temporary set it to 32 for MV cores, however this value should be
182 * get from Cache Type register
183 */
184.Larmv7_line_size:
185	.word	32
186
187ENTRY(armv7_dcache_wb_range)
188	ldr	ip, .Larmv7_line_size
189	sub	r3, ip, #1
190	and	r2, r0, r3
191	add	r1, r1, r2
192	bic	r0, r0, r3
193.Larmv7_wb_next:
194	mcr	p15, 0, r0, c7, c10, 1	/* Clean D cache SE with VA */
195	add	r0, r0, ip
196	subs	r1, r1, ip
197	bhi	.Larmv7_wb_next
198	dsb				/* data synchronization barrier */
199	RET
200END(armv7_dcache_wb_range)
201
202ENTRY(armv7_dcache_wbinv_range)
203	ldr	ip, .Larmv7_line_size
204	sub     r3, ip, #1
205	and     r2, r0, r3
206	add     r1, r1, r2
207	bic     r0, r0, r3
208.Larmv7_wbinv_next:
209	mcr	p15, 0, r0, c7, c14, 1	/* Purge D cache SE with VA */
210	add	r0, r0, ip
211	subs	r1, r1, ip
212	bhi	.Larmv7_wbinv_next
213	dsb				/* data synchronization barrier */
214	RET
215END(armv7_dcache_wbinv_range)
216
217/*
218 * Note, we must not invalidate everything.  If the range is too big we
219 * must use wb-inv of the entire cache.
220 */
221ENTRY(armv7_dcache_inv_range)
222	ldr	ip, .Larmv7_line_size
223	sub     r3, ip, #1
224	and     r2, r0, r3
225	add     r1, r1, r2
226	bic     r0, r0, r3
227.Larmv7_inv_next:
228	mcr	p15, 0, r0, c7, c6, 1	/* Invalidate D cache SE with VA */
229	add	r0, r0, ip
230	subs	r1, r1, ip
231	bhi	.Larmv7_inv_next
232	dsb				/* data synchronization barrier */
233	RET
234END(armv7_dcache_inv_range)
235
236ENTRY(armv7_idcache_wbinv_range)
237	ldr	ip, .Larmv7_line_size
238	sub     r3, ip, #1
239	and     r2, r0, r3
240	add     r1, r1, r2
241	bic     r0, r0, r3
242.Larmv7_id_wbinv_next:
243	mcr	p15, 0, r0, c7, c5, 1	/* Invalidate I cache SE with VA */
244	mcr	p15, 0, r0, c7, c14, 1	/* Purge D cache SE with VA */
245	add	r0, r0, ip
246	subs	r1, r1, ip
247	bhi	.Larmv7_id_wbinv_next
248	isb				/* instruction synchronization barrier */
249	dsb				/* data synchronization barrier */
250	RET
251END(armv7_idcache_wbinv_range)
252
253ENTRY_NP(armv7_icache_sync_all)
254	mcr	p15, 0, r0, c7, c1, 0	/* Invalidate all I cache to PoU Inner Shareable */
255	isb				/* instruction synchronization barrier */
256	dsb				/* data synchronization barrier */
257	RET
258END(armv7_icache_sync_all)
259
260ENTRY_NP(armv7_icache_sync_range)
261	ldr	ip, .Larmv7_line_size
262.Larmv7_sync_next:
263	mcr	p15, 0, r0, c7, c5, 1	/* Invalidate I cache SE with VA */
264	mcr	p15, 0, r0, c7, c10, 1	/* Clean D cache SE with VA */
265	add	r0, r0, ip
266	subs	r1, r1, ip
267	bhi	.Larmv7_sync_next
268	isb				/* instruction synchronization barrier */
269	dsb				/* data synchronization barrier */
270	RET
271END(armv7_icache_sync_range)
272
273ENTRY(armv7_cpu_sleep)
274	dsb				/* data synchronization barrier */
275	wfi  				/* wait for interrupt */
276	RET
277END(armv7_cpu_sleep)
278
279ENTRY(armv7_context_switch)
280	dsb
281	orr     r0, r0, #PT_ATTR
282
283	mcr	p15, 0, r0, c2, c0, 0	/* set the new TTB */
284	isb
285#ifdef SMP
286	mcr	p15, 0, r0, c8, c3, 0	/* and flush the I+D tlbs Inner Sharable */
287#else
288	mcr	p15, 0, r0, c8, c7, 0	/* and flush the I+D tlbs */
289#endif
290	dsb
291	isb
292	RET
293END(armv7_context_switch)
294
295ENTRY(armv7_drain_writebuf)
296	dsb
297	RET
298END(armv7_drain_writebuf)
299
300ENTRY(armv7_sev)
301	dsb
302	sev
303	nop
304	RET
305END(armv7_sev)
306
307ENTRY(armv7_auxctrl)
308	mrc p15, 0, r2, c1, c0, 1
309	bic r3, r2, r0	/* Clear bits */
310	eor r3, r3, r1  /* XOR bits */
311
312	teq r2, r3
313	mcrne p15, 0, r3, c1, c0, 1
314	mov r0, r2
315	RET
316END(armv7_auxctrl)
317
318ENTRY(armv7_idcache_inv_all)
319	mov     r0, #0
320	mcr     p15, 2, r0, c0, c0, 0   @ set cache level to L1
321	mrc     p15, 1, r0, c0, c0, 0   @ read CCSIDR
322
323	ubfx    r2, r0, #13, #15        @ get num sets - 1 from CCSIDR
324	ubfx    r3, r0, #3, #10         @ get numways - 1 from CCSIDR
325	clz     r1, r3                  @ number of bits to MSB of way
326	lsl     r3, r3, r1              @ shift into position
327	mov     ip, #1                  @
328	lsl     ip, ip, r1              @ ip now contains the way decr
329
330	ubfx    r0, r0, #0, #3          @ get linesize from CCSIDR
331	add     r0, r0, #4              @ apply bias
332	lsl     r2, r2, r0              @ shift sets by log2(linesize)
333	add     r3, r3, r2              @ merge numsets - 1 with numways - 1
334	sub     ip, ip, r2              @ subtract numsets - 1 from way decr
335	mov     r1, #1
336	lsl     r1, r1, r0              @ r1 now contains the set decr
337	mov     r2, ip                  @ r2 now contains set way decr
338
339	/* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
3401:      mcr     p15, 0, r3, c7, c6, 2   @ invalidate line
341	movs    r0, r3                  @ get current way/set
342	beq     2f                      @ at 0 means we are done.
343	movs    r0, r0, lsl #10         @ clear way bits leaving only set bits
344	subne   r3, r3, r1              @ non-zero?, decrement set #
345	subeq   r3, r3, r2              @ zero?, decrement way # and restore set count
346	b       1b
347
3482:	dsb                             @ wait for stores to finish
349	mov     r0, #0                  @ and ...
350	mcr     p15, 0, r0, c7, c5, 0   @ invalidate instruction+branch cache
351	isb                             @ instruction sync barrier
352	bx      lr                      @ return
353END(armv7_l1cache_inv_all)
354
355ENTRY_NP(armv7_sleep)
356	dsb
357	wfi
358	bx	lr
359END(armv7_sleep)
360
361