cpufunc_asm_armv7.S revision 266332
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: stable/10/sys/arm/arm/cpufunc_asm_armv7.S 266332 2014-05-17 17:54:38Z 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#ifdef SMP
75 	mcr     p15, 0, r0, c8, c3, 0   /* invalidate I+D TLBs Inner Shareable*/
76#else
77 	mcr     p15, 0, r0, c8, c7, 0   /* invalidate I+D TLBs */
78#endif
79 	dsb
80 	isb
81	RET
82END(armv7_setttb)
83
84ENTRY(armv7_tlb_flushID)
85	dsb
86#ifdef SMP
87	mcr	p15, 0, r0, c8, c3, 0	/* flush Unified TLB all entries Inner Shareable */
88	mcr	p15, 0, r0, c7, c1, 6	/* flush BTB Inner Shareable */
89#else
90	mcr	p15, 0, r0, c8, c7, 0	/* flush Unified TLB all entries */
91	mcr	p15, 0, r0, c7, c5, 6	/* flush BTB */
92#endif
93	dsb
94	isb
95	mov	pc, lr
96END(armv7_tlb_flushID)
97
98ENTRY(armv7_tlb_flushID_SE)
99	ldr	r1, .Lpage_mask
100	bic	r0, r0, r1
101#ifdef SMP
102	mcr	p15, 0, r0, c8, c3, 3	/* flush Unified TLB single entry Inner Shareable */
103	mcr	p15, 0, r0, c7, c1, 6	/* flush BTB Inner Shareable */
104#else
105	mcr	p15, 0, r0, c8, c7, 1	/* flush Unified TLB single entry */
106	mcr	p15, 0, r0, c7, c5, 6	/* flush BTB */
107#endif
108	dsb
109	isb
110	mov	pc, lr
111END(armv7_tlb_flushID_SE)
112
113/* Based on algorithm from ARM Architecture Reference Manual */
114ENTRY(armv7_dcache_wbinv_all)
115	stmdb	sp!, {r4, r5, r6, r7, r8, r9}
116
117	/* Get cache level */
118	ldr	r0, .Lcoherency_level
119	ldr	r3, [r0]
120	cmp	r3, #0
121	beq	Finished
122	/* For each cache level */
123	mov	r8, #0
124Loop1:
125	/* Get cache type for given level */
126	mov	r2, r8, lsl #2
127	add	r2, r2, r2
128	ldr	r0, .Lcache_type
129	ldr	r1, [r0, r2]
130
131	/* Get line size */
132	and	r2, r1, #7
133	add	r2, r2, #4
134
135	/* Get number of ways */
136	ldr	r4, .Lway_mask
137	ands	r4, r4, r1, lsr #3
138	clz	r5, r4
139
140	/* Get max index */
141	ldr	r7, .Lmax_index
142	ands	r7, r7, r1, lsr #13
143Loop2:
144	mov	r9, r4
145Loop3:
146	mov	r6, r8, lsl #1
147	orr	r6, r6, r9, lsl r5
148	orr	r6, r6, r7, lsl r2
149
150	/* Clean and invalidate data cache by way/index */
151	mcr	p15, 0, r6, c7, c14, 2
152	subs	r9, r9, #1
153	bge	Loop3
154	subs	r7, r7, #1
155	bge	Loop2
156Skip:
157	add	r8, r8, #1
158	cmp	r3, r8
159	bne Loop1
160Finished:
161	dsb
162	ldmia	sp!, {r4, r5, r6, r7, r8, r9}
163	RET
164END(armv7_dcache_wbinv_all)
165
166ENTRY(armv7_idcache_wbinv_all)
167	stmdb	sp!, {lr}
168	bl armv7_dcache_wbinv_all
169#ifdef SMP
170	mcr	p15, 0, r0, c7, c1, 0	/* Invalidate all I caches to PoU (ICIALLUIS) */
171#else
172	mcr	p15, 0, r0, c7, c5, 0	/* Invalidate all I caches to PoU (ICIALLU) */
173#endif
174	dsb
175	isb
176	ldmia	sp!, {lr}
177	RET
178END(armv7_idcache_wbinv_all)
179
180/* XXX Temporary set it to 32 for MV cores, however this value should be
181 * get from Cache Type register
182 */
183.Larmv7_line_size:
184	.word	32
185
186ENTRY(armv7_dcache_wb_range)
187	ldr	ip, .Larmv7_line_size
188	sub	r3, ip, #1
189	and	r2, r0, r3
190	add	r1, r1, r2
191	bic	r0, r0, r3
192.Larmv7_wb_next:
193	mcr	p15, 0, r0, c7, c10, 1	/* Clean D cache SE with VA */
194	add	r0, r0, ip
195	subs	r1, r1, ip
196	bhi	.Larmv7_wb_next
197	dsb				/* data synchronization barrier */
198	RET
199END(armv7_dcache_wb_range)
200
201ENTRY(armv7_dcache_wbinv_range)
202	ldr	ip, .Larmv7_line_size
203	sub     r3, ip, #1
204	and     r2, r0, r3
205	add     r1, r1, r2
206	bic     r0, r0, r3
207.Larmv7_wbinv_next:
208	mcr	p15, 0, r0, c7, c14, 1	/* Purge D cache SE with VA */
209	add	r0, r0, ip
210	subs	r1, r1, ip
211	bhi	.Larmv7_wbinv_next
212	dsb				/* data synchronization barrier */
213	RET
214END(armv7_dcache_wbinv_range)
215
216/*
217 * Note, we must not invalidate everything.  If the range is too big we
218 * must use wb-inv of the entire cache.
219 */
220ENTRY(armv7_dcache_inv_range)
221	ldr	ip, .Larmv7_line_size
222	sub     r3, ip, #1
223	and     r2, r0, r3
224	add     r1, r1, r2
225	bic     r0, r0, r3
226.Larmv7_inv_next:
227	mcr	p15, 0, r0, c7, c6, 1	/* Invalidate D cache SE with VA */
228	add	r0, r0, ip
229	subs	r1, r1, ip
230	bhi	.Larmv7_inv_next
231	dsb				/* data synchronization barrier */
232	RET
233END(armv7_dcache_inv_range)
234
235ENTRY(armv7_idcache_wbinv_range)
236	ldr	ip, .Larmv7_line_size
237	sub     r3, ip, #1
238	and     r2, r0, r3
239	add     r1, r1, r2
240	bic     r0, r0, r3
241.Larmv7_id_wbinv_next:
242	mcr	p15, 0, r0, c7, c5, 1	/* Invalidate I cache SE with VA */
243	mcr	p15, 0, r0, c7, c14, 1	/* Purge D cache SE with VA */
244	add	r0, r0, ip
245	subs	r1, r1, ip
246	bhi	.Larmv7_id_wbinv_next
247	isb				/* instruction synchronization barrier */
248	dsb				/* data synchronization barrier */
249	RET
250END(armv7_idcache_wbinv_range)
251
252ENTRY_NP(armv7_icache_sync_range)
253	ldr	ip, .Larmv7_line_size
254.Larmv7_sync_next:
255	mcr	p15, 0, r0, c7, c5, 1	/* Invalidate I cache SE with VA */
256	mcr	p15, 0, r0, c7, c10, 1	/* Clean D cache SE with VA */
257	add	r0, r0, ip
258	subs	r1, r1, ip
259	bhi	.Larmv7_sync_next
260	isb				/* instruction synchronization barrier */
261	dsb				/* data synchronization barrier */
262	RET
263END(armv7_icache_sync_range)
264
265ENTRY(armv7_cpu_sleep)
266	dsb				/* data synchronization barrier */
267	wfi  				/* wait for interrupt */
268	RET
269END(armv7_cpu_sleep)
270
271ENTRY(armv7_context_switch)
272	dsb
273	orr     r0, r0, #PT_ATTR
274
275	mcr	p15, 0, r0, c2, c0, 0	/* set the new TTB */
276#ifdef SMP
277	mcr	p15, 0, r0, c8, c3, 0	/* and flush the I+D tlbs Inner Sharable */
278#else
279	mcr	p15, 0, r0, c8, c7, 0	/* and flush the I+D tlbs */
280#endif
281	dsb
282	isb
283	RET
284END(armv7_context_switch)
285
286ENTRY(armv7_drain_writebuf)
287	dsb
288	RET
289END(armv7_drain_writebuf)
290
291ENTRY(armv7_sev)
292	dsb
293	sev
294	nop
295	RET
296END(armv7_sev)
297
298ENTRY(armv7_auxctrl)
299	mrc p15, 0, r2, c1, c0, 1
300	bic r3, r2, r0	/* Clear bits */
301	eor r3, r3, r1  /* XOR bits */
302
303	teq r2, r3
304	mcrne p15, 0, r3, c1, c0, 1
305	mov r0, r2
306	RET
307END(armv7_auxctrl)
308
309ENTRY(armv7_idcache_inv_all)
310	mov     r0, #0
311	mcr     p15, 2, r0, c0, c0, 0   @ set cache level to L1
312	mrc     p15, 1, r0, c0, c0, 0   @ read CCSIDR
313
314	ubfx    r2, r0, #13, #15        @ get num sets - 1 from CCSIDR
315	ubfx    r3, r0, #3, #10         @ get numways - 1 from CCSIDR
316	clz     r1, r3                  @ number of bits to MSB of way
317	lsl     r3, r3, r1              @ shift into position
318	mov     ip, #1                  @
319	lsl     ip, ip, r1              @ ip now contains the way decr
320
321	ubfx    r0, r0, #0, #3          @ get linesize from CCSIDR
322	add     r0, r0, #4              @ apply bias
323	lsl     r2, r2, r0              @ shift sets by log2(linesize)
324	add     r3, r3, r2              @ merge numsets - 1 with numways - 1
325	sub     ip, ip, r2              @ subtract numsets - 1 from way decr
326	mov     r1, #1
327	lsl     r1, r1, r0              @ r1 now contains the set decr
328	mov     r2, ip                  @ r2 now contains set way decr
329
330	/* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
3311:      mcr     p15, 0, r3, c7, c6, 2   @ invalidate line
332	movs    r0, r3                  @ get current way/set
333	beq     2f                      @ at 0 means we are done.
334	movs    r0, r0, lsl #10         @ clear way bits leaving only set bits
335	subne   r3, r3, r1              @ non-zero?, decrement set #
336	subeq   r3, r3, r2              @ zero?, decrement way # and restore set count
337	b       1b
338
3392:	dsb                             @ wait for stores to finish
340	mov     r0, #0                  @ and ...
341	mcr     p15, 0, r0, c7, c5, 0   @ invalidate instruction+branch cache
342	isb                             @ instruction sync barrier
343	bx      lr                      @ return
344END(armv7_l1cache_inv_all)
345
346ENTRY_NP(armv7_sleep)
347	dsb
348	wfi
349	bx	lr
350END(armv7_sleep)
351
352