1183835Sraj/*-
2183835Sraj * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
3183835Sraj * All rights reserved.
4183835Sraj *
5183835Sraj * Developed by Semihalf.
6183835Sraj *
7183835Sraj * Redistribution and use in source and binary forms, with or without
8183835Sraj * modification, are permitted provided that the following conditions
9183835Sraj * are met:
10183835Sraj * 1. Redistributions of source code must retain the above copyright
11183835Sraj *    notice, this list of conditions and the following disclaimer.
12183835Sraj * 2. Redistributions in binary form must reproduce the above copyright
13183835Sraj *    notice, this list of conditions and the following disclaimer in the
14183835Sraj *    documentation and/or other materials provided with the distribution.
15183835Sraj * 3. Neither the name of MARVELL nor the names of contributors
16183835Sraj *    may be used to endorse or promote products derived from this software
17183835Sraj *    without specific prior written permission.
18183835Sraj *
19183835Sraj * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20183835Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21183835Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22183835Sraj * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23183835Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24183835Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25183835Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26183835Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27183835Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28183835Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29183835Sraj * SUCH DAMAGE.
30183835Sraj */
31183835Sraj
32271398Sandrew#include <machine/armreg.h>
33183835Sraj#include <machine/asm.h>
34183835Sraj__FBSDID("$FreeBSD: releng/11.0/sys/arm/arm/cpufunc_asm_sheeva.S 275417 2014-12-02 18:35:34Z andrew $");
35183835Sraj
36183835Sraj#include <machine/param.h>
37183835Sraj
38186933Sraj.Lsheeva_cache_line_size:
39183835Sraj	.word	_C_LABEL(arm_pdcache_line_size)
40186933Sraj.Lsheeva_asm_page_mask:
41183835Sraj	.word	_C_LABEL(PAGE_MASK)
42183835Sraj
43186933SrajENTRY(sheeva_setttb)
44183835Sraj	/* Disable irqs */
45183835Sraj	mrs	r2, cpsr
46271398Sandrew	orr	r3, r2, #PSR_I | PSR_F
47183835Sraj	msr	cpsr_c, r3
48183835Sraj
49183835Sraj	mov	r1, #0
50183835Sraj	mcr	p15, 0, r1, c7, c5, 0	/* Invalidate ICache */
51275417Sandrew1:	mrc	p15, 0, APSR_nzcv, c7, c14, 3	/* Test, clean and invalidate DCache */
52183835Sraj	bne	1b			/* More to do? */
53183835Sraj
54183835Sraj	mcr	p15, 1, r1, c15, c9, 0	/* Clean L2 */
55183835Sraj	mcr	p15, 1, r1, c15, c11, 0	/* Invalidate L2 */
56183835Sraj
57183835Sraj	/* Reenable irqs */
58183835Sraj	msr	cpsr_c, r2
59183835Sraj
60183835Sraj	mcr	p15, 0, r1, c7, c10, 4	/* drain the write buffer */
61183835Sraj
62183835Sraj	mcr	p15, 0, r0, c2, c0, 0	/* load new TTB */
63183835Sraj
64183835Sraj	mcr	p15, 0, r0, c8, c7, 0	/* invalidate I+D TLBs */
65183835Sraj	RET
66248361SandrewEND(sheeva_setttb)
67183835Sraj
68186933SrajENTRY(sheeva_dcache_wbinv_range)
69183835Sraj	str	lr, [sp, #-4]!
70183835Sraj	mrs	lr, cpsr
71183835Sraj	/* Start with cache line aligned address */
72186933Sraj	ldr	ip, .Lsheeva_cache_line_size
73183835Sraj	ldr	ip, [ip]
74183835Sraj	sub	ip, ip, #1
75183835Sraj	and	r2, r0, ip
76183835Sraj	add	r1, r1, r2
77183835Sraj	add	r1, r1, ip
78183835Sraj	bics	r1, r1, ip
79183835Sraj	bics	r0, r0, ip
80183835Sraj
81186933Sraj	ldr	ip, .Lsheeva_asm_page_mask
82183835Sraj	and	r2, r0, ip
83183835Sraj	rsb	r2, r2, #PAGE_SIZE
84183835Sraj	cmp	r1, r2
85183835Sraj	movcc	ip, r1
86183835Sraj	movcs	ip, r2
87183835Sraj1:
88183835Sraj	add	r3, r0, ip
89183835Sraj	sub	r2, r3, #1
90183835Sraj	/* Disable irqs */
91271398Sandrew	orr	r3, lr, #PSR_I | PSR_F
92183835Sraj	msr	cpsr_c, r3
93183835Sraj	mcr	p15, 5, r0, c15, c15, 0	/* Clean and inv zone start address */
94183835Sraj	mcr	p15, 5, r2, c15, c15, 1	/* Clean and inv zone end address */
95183835Sraj	/* Enable irqs */
96183835Sraj	msr	cpsr_c, lr
97183835Sraj
98183835Sraj	add	r0, r0, ip
99183835Sraj	sub	r1, r1, ip
100183835Sraj	cmp	r1, #PAGE_SIZE
101183835Sraj	movcc	ip, r1
102183835Sraj	movcs	ip, #PAGE_SIZE
103183835Sraj	cmp	r1, #0
104183835Sraj	bne	1b
105183835Sraj	mov	r0, #0
106183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
107183835Sraj	ldr	lr, [sp], #4
108183835Sraj	RET
109248361SandrewEND(sheeva_dcache_wbinv_range)
110183835Sraj
111186933SrajENTRY(sheeva_idcache_wbinv_range)
112183835Sraj	str	lr, [sp, #-4]!
113183835Sraj	mrs	lr, cpsr
114183835Sraj	/* Start with cache line aligned address */
115186933Sraj	ldr	ip, .Lsheeva_cache_line_size
116183835Sraj	ldr	ip, [ip]
117183835Sraj	sub	ip, ip, #1
118183835Sraj	and	r2, r0, ip
119183835Sraj	add	r1, r1, r2
120183835Sraj	add	r1, r1, ip
121183835Sraj	bics	r1, r1, ip
122183835Sraj	bics	r0, r0, ip
123183835Sraj
124186933Sraj	ldr	ip, .Lsheeva_asm_page_mask
125183835Sraj	and	r2, r0, ip
126183835Sraj	rsb	r2, r2, #PAGE_SIZE
127183835Sraj	cmp	r1, r2
128183835Sraj	movcc	ip, r1
129183835Sraj	movcs	ip, r2
130183835Sraj1:
131183835Sraj	add	r3, r0, ip
132183835Sraj	sub	r2, r3, #1
133183835Sraj	/* Disable irqs */
134271398Sandrew	orr	r3, lr, #PSR_I | PSR_F
135183835Sraj	msr	cpsr_c, r3
136183835Sraj	mcr	p15, 5, r0, c15, c15, 0	/* Clean and inv zone start address */
137183835Sraj	mcr	p15, 5, r2, c15, c15, 1	/* Clean and inv zone end address */
138183835Sraj	/* Enable irqs */
139183835Sraj	msr	cpsr_c, lr
140183835Sraj
141183835Sraj	/* Invalidate and clean icache line by line */
142186933Sraj	ldr	r3, .Lsheeva_cache_line_size
143183835Sraj	ldr	r3, [r3]
144183835Sraj2:
145183835Sraj	mcr	p15, 0, r0, c7, c5, 1
146183835Sraj	add	r0, r0, r3
147183835Sraj	cmp	r2, r0
148183835Sraj	bhi	2b
149183835Sraj
150183835Sraj	add	r0, r2, #1
151183835Sraj	sub	r1, r1, ip
152183835Sraj	cmp	r1, #PAGE_SIZE
153183835Sraj	movcc	ip, r1
154183835Sraj	movcs	ip, #PAGE_SIZE
155183835Sraj	cmp	r1, #0
156183835Sraj	bne	1b
157183835Sraj	mov	r0, #0
158183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
159183835Sraj	ldr	lr, [sp], #4
160183835Sraj	RET
161248361SandrewEND(sheeva_idcache_wbinv_range)
162183835Sraj
163186933SrajENTRY(sheeva_dcache_inv_range)
164183835Sraj	str	lr, [sp, #-4]!
165183835Sraj	mrs	lr, cpsr
166183835Sraj	/* Start with cache line aligned address */
167186933Sraj	ldr	ip, .Lsheeva_cache_line_size
168183835Sraj	ldr	ip, [ip]
169183835Sraj	sub	ip, ip, #1
170183835Sraj	and	r2, r0, ip
171183835Sraj	add	r1, r1, r2
172183835Sraj	add	r1, r1, ip
173183835Sraj	bics	r1, r1, ip
174183835Sraj	bics	r0, r0, ip
175183835Sraj
176186933Sraj	ldr	ip, .Lsheeva_asm_page_mask
177183835Sraj	and	r2, r0, ip
178183835Sraj	rsb	r2, r2, #PAGE_SIZE
179183835Sraj	cmp	r1, r2
180183835Sraj	movcc	ip, r1
181183835Sraj	movcs	ip, r2
182183835Sraj1:
183183835Sraj	add	r3, r0, ip
184183835Sraj	sub	r2, r3, #1
185183835Sraj	/* Disable irqs */
186271398Sandrew	orr	r3, lr, #PSR_I | PSR_F
187183835Sraj	msr	cpsr_c, r3
188183835Sraj	mcr	p15, 5, r0, c15, c14, 0	/* Inv zone start address */
189183835Sraj	mcr	p15, 5, r2, c15, c14, 1	/* Inv zone end address */
190183835Sraj	/* Enable irqs */
191183835Sraj	msr	cpsr_c, lr
192183835Sraj
193183835Sraj	add	r0, r0, ip
194183835Sraj	sub	r1, r1, ip
195183835Sraj	cmp	r1, #PAGE_SIZE
196183835Sraj	movcc	ip, r1
197183835Sraj	movcs	ip, #PAGE_SIZE
198183835Sraj	cmp	r1, #0
199183835Sraj	bne	1b
200183835Sraj	mov	r0, #0
201183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
202183835Sraj	ldr	lr, [sp], #4
203183835Sraj	RET
204248361SandrewEND(sheeva_dcache_inv_range)
205183835Sraj
206186933SrajENTRY(sheeva_dcache_wb_range)
207183835Sraj	str	lr, [sp, #-4]!
208183835Sraj	mrs	lr, cpsr
209183835Sraj	/* Start with cache line aligned address */
210186933Sraj	ldr	ip, .Lsheeva_cache_line_size
211183835Sraj	ldr	ip, [ip]
212183835Sraj	sub	ip, ip, #1
213183835Sraj	and	r2, r0, ip
214183835Sraj	add	r1, r1, r2
215183835Sraj	add	r1, r1, ip
216183835Sraj	bics	r1, r1, ip
217183835Sraj	bics	r0, r0, ip
218183835Sraj
219186933Sraj	ldr	ip, .Lsheeva_asm_page_mask
220183835Sraj	and	r2, r0, ip
221183835Sraj	rsb	r2, r2, #PAGE_SIZE
222183835Sraj	cmp	r1, r2
223183835Sraj	movcc	ip, r1
224183835Sraj	movcs	ip, r2
225183835Sraj1:
226183835Sraj	add	r3, r0, ip
227183835Sraj	sub	r2, r3, #1
228183835Sraj	/* Disable irqs */
229271398Sandrew	orr	r3, lr, #PSR_I | PSR_F
230183835Sraj	msr	cpsr_c, r3
231183835Sraj	mcr	p15, 5, r0, c15, c13, 0	/* Clean zone start address */
232183835Sraj	mcr	p15, 5, r2, c15, c13, 1	/* Clean zone end address */
233183835Sraj	/* Enable irqs */
234183835Sraj	msr	cpsr_c, lr
235183835Sraj
236183835Sraj	add	r0, r0, ip
237183835Sraj	sub	r1, r1, ip
238183835Sraj	cmp	r1, #PAGE_SIZE
239183835Sraj	movcc	ip, r1
240183835Sraj	movcs	ip, #PAGE_SIZE
241183835Sraj	cmp	r1, #0
242183835Sraj	bne	1b
243183835Sraj	mov	r0, #0
244183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
245183835Sraj	ldr	lr, [sp], #4
246183835Sraj	RET
247248361SandrewEND(sheeva_dcache_wb_range)
248183835Sraj
249186933SrajENTRY(sheeva_l2cache_wbinv_range)
250183835Sraj	str	lr, [sp, #-4]!
251183835Sraj	mrs	lr, cpsr
252183835Sraj	/* Start with cache line aligned address */
253186933Sraj	ldr	ip, .Lsheeva_cache_line_size
254183835Sraj	ldr	ip, [ip]
255183835Sraj	sub	ip, ip, #1
256183835Sraj	and	r2, r0, ip
257183835Sraj	add	r1, r1, r2
258183835Sraj	add	r1, r1, ip
259183835Sraj	bics	r1, r1, ip
260183835Sraj	bics	r0, r0, ip
261183835Sraj
262186933Sraj	ldr	ip, .Lsheeva_asm_page_mask
263183835Sraj	and	r2, r0, ip
264183835Sraj	rsb	r2, r2, #PAGE_SIZE
265183835Sraj	cmp	r1, r2
266183835Sraj	movcc	ip, r1
267183835Sraj	movcs	ip, r2
268183835Sraj1:
269183835Sraj	add	r3, r0, ip
270183835Sraj	sub	r2, r3, #1
271183835Sraj	/* Disable irqs */
272271398Sandrew	orr	r3, lr, #PSR_I | PSR_F
273183835Sraj	msr	cpsr_c, r3
274183835Sraj	mcr	p15, 1, r0, c15, c9, 4	/* Clean L2 zone start address */
275183835Sraj	mcr	p15, 1, r2, c15, c9, 5	/* Clean L2 zone end address */
276183835Sraj	mcr	p15, 1, r0, c15, c11, 4	/* Inv L2 zone start address */
277183835Sraj	mcr	p15, 1, r2, c15, c11, 5	/* Inv L2 zone end address */
278183835Sraj	/* Enable irqs */
279183835Sraj	msr	cpsr_c, lr
280183835Sraj
281183835Sraj	add	r0, r0, ip
282183835Sraj	sub	r1, r1, ip
283183835Sraj	cmp	r1, #PAGE_SIZE
284183835Sraj	movcc	ip, r1
285183835Sraj	movcs	ip, #PAGE_SIZE
286183835Sraj	cmp	r1, #0
287183835Sraj	bne	1b
288183835Sraj	mov	r0, #0
289183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
290183835Sraj	ldr	lr, [sp], #4
291183835Sraj	RET
292248361SandrewEND(sheeva_l2cache_wbinv_range)
293183835Sraj
294186933SrajENTRY(sheeva_l2cache_inv_range)
295183835Sraj	str	lr, [sp, #-4]!
296183835Sraj	mrs	lr, cpsr
297183835Sraj	/* Start with cache line aligned address */
298186933Sraj	ldr	ip, .Lsheeva_cache_line_size
299183835Sraj	ldr	ip, [ip]
300183835Sraj	sub	ip, ip, #1
301183835Sraj	and	r2, r0, ip
302183835Sraj	add	r1, r1, r2
303183835Sraj	add	r1, r1, ip
304183835Sraj	bics	r1, r1, ip
305183835Sraj	bics	r0, r0, ip
306183835Sraj
307186933Sraj	ldr	ip, .Lsheeva_asm_page_mask
308183835Sraj	and	r2, r0, ip
309183835Sraj	rsb	r2, r2, #PAGE_SIZE
310183835Sraj	cmp	r1, r2
311183835Sraj	movcc	ip, r1
312183835Sraj	movcs	ip, r2
313183835Sraj1:
314183835Sraj	add	r3, r0, ip
315183835Sraj	sub	r2, r3, #1
316183835Sraj	/* Disable irqs */
317271398Sandrew	orr	r3, lr, #PSR_I | PSR_F
318183835Sraj	msr	cpsr_c, r3
319183835Sraj	mcr	p15, 1, r0, c15, c11, 4	/* Inv L2 zone start address */
320183835Sraj	mcr	p15, 1, r2, c15, c11, 5	/* Inv L2 zone end address */
321183835Sraj	/* Enable irqs */
322183835Sraj	msr	cpsr_c, lr
323183835Sraj
324183835Sraj	add	r0, r0, ip
325183835Sraj	sub	r1, r1, ip
326183835Sraj	cmp	r1, #PAGE_SIZE
327183835Sraj	movcc	ip, r1
328183835Sraj	movcs	ip, #PAGE_SIZE
329183835Sraj	cmp	r1, #0
330183835Sraj	bne	1b
331183835Sraj	mov	r0, #0
332183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
333183835Sraj	ldr	lr, [sp], #4
334183835Sraj	RET
335248361SandrewEND(sheeva_l2cache_inv_range)
336183835Sraj
337186933SrajENTRY(sheeva_l2cache_wb_range)
338183835Sraj	str	lr, [sp, #-4]!
339183835Sraj	mrs	lr, cpsr
340183835Sraj	/* Start with cache line aligned address */
341186933Sraj	ldr	ip, .Lsheeva_cache_line_size
342183835Sraj	ldr	ip, [ip]
343183835Sraj	sub	ip, ip, #1
344183835Sraj	and	r2, r0, ip
345183835Sraj	add	r1, r1, r2
346183835Sraj	add	r1, r1, ip
347183835Sraj	bics	r1, r1, ip
348183835Sraj	bics	r0, r0, ip
349183835Sraj
350186933Sraj	ldr	ip, .Lsheeva_asm_page_mask
351183835Sraj	and	r2, r0,	ip
352183835Sraj	rsb	r2, r2, #PAGE_SIZE
353183835Sraj	cmp	r1, r2
354183835Sraj	movcc	ip, r1
355183835Sraj	movcs	ip, r2
356183835Sraj1:
357183835Sraj	add	r3, r0, ip
358183835Sraj	sub	r2, r3, #1
359183835Sraj	/* Disable irqs */
360271398Sandrew	orr	r3, lr, #PSR_I | PSR_F
361183835Sraj	msr	cpsr_c, r3
362183835Sraj	mcr	p15, 1, r0, c15, c9, 4	/* Clean L2 zone start address */
363183835Sraj	mcr	p15, 1, r2, c15, c9, 5	/* Clean L2 zone end address */
364183835Sraj	/* Enable irqs */
365183835Sraj	msr	cpsr_c, lr
366183835Sraj
367183835Sraj	add	r0, r0, ip
368183835Sraj	sub	r1, r1, ip
369183835Sraj	cmp	r1, #PAGE_SIZE
370183835Sraj	movcc	ip, r1
371183835Sraj	movcs	ip, #PAGE_SIZE
372183835Sraj	cmp	r1, #0
373183835Sraj	bne	1b
374183835Sraj	mov	r0, #0
375183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
376183835Sraj	ldr	lr, [sp], #4
377183835Sraj	RET
378248361SandrewEND(sheeva_l2cache_wb_range)
379183835Sraj
380186933SrajENTRY(sheeva_l2cache_wbinv_all)
381250695Sgber	/* Disable irqs */
382250695Sgber	mrs	r1, cpsr
383271398Sandrew	orr	r2, r1, #PSR_I | PSR_F
384250695Sgber	msr	cpsr_c, r2
385250695Sgber
386183835Sraj	mov	r0, #0
387183835Sraj	mcr	p15, 1, r0, c15, c9, 0	/* Clean L2 */
388183835Sraj	mcr	p15, 1, r0, c15, c11, 0	/* Invalidate L2 */
389250695Sgber
390250695Sgber	msr	cpsr_c, r1		/* Reenable irqs */
391250695Sgber
392183835Sraj	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
393183835Sraj	RET
394248361SandrewEND(sheeva_l2cache_wbinv_all)
395183835Sraj
396191141Sraj/* This function modifies register value as follows:
397191141Sraj *
398191141Sraj * arg1  arg		EFFECT (bit value saved into register)
399191141Sraj *    0     0           not changed
400191141Sraj *    0     1           negated
401191141Sraj *    1     0           cleared
402191141Sraj *    1     1           set
403191141Sraj */
404186933SrajENTRY(sheeva_control_ext)
405183835Sraj	mrc	p15, 1, r3, c15, c1, 0	/* Read the control register */
406183835Sraj	bic	r2, r3, r0		/* Clear bits */
407183835Sraj	eor     r2, r2, r1		/* XOR bits */
408183835Sraj
409183835Sraj	teq	r2, r3			/* Only write if there is a change */
410183835Sraj	mcrne	p15, 1, r2, c15, c1, 0	/* Write new control register */
411183835Sraj	mov	r0, r3			/* Return old value */
412183835Sraj	RET
413248361SandrewEND(sheeva_control_ext)
414212825Smav
415212825SmavENTRY(sheeva_cpu_sleep)
416212825Smav	mov	r0, #0
417212825Smav	mcr	p15, 0, r0, c7, c10, 4	/* Drain write buffer */
418212825Smav	mcr	p15, 0, r0, c7, c0, 4	/* Wait for interrupt */
419212825Smav	mov	pc, lr
420248361SandrewEND(sheeva_cpu_sleep)
421212825Smav
422