2 * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
5 * Developed by Semihalf.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of MARVELL nor the names of contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <machine/asm.h>
33 __FBSDID("$FreeBSD$");
35 #include <machine/param.h>
37 .Lferoceon_cache_line_size:
38 .word _C_LABEL(arm_pdcache_line_size)
39 .Lferoceon_asm_page_mask:
40 .word _C_LABEL(PAGE_MASK)
42 ENTRY(feroceon_setttb)
45 orr r3, r2, #I32_bit | F32_bit
49 mcr p15, 0, r1, c7, c5, 0 /* Invalidate ICache */
50 1: mrc p15, 0, r15, c7, c14, 3 /* Test, clean and invalidate DCache */
51 bne 1b /* More to do? */
53 mcr p15, 1, r1, c15, c9, 0 /* Clean L2 */
54 mcr p15, 1, r1, c15, c11, 0 /* Invalidate L2 */
59 mcr p15, 0, r1, c7, c10, 4 /* drain the write buffer */
61 mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
63 mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
66 ENTRY(feroceon_dcache_wbinv_range)
69 /* Start with cache line aligned address */
70 ldr ip, .Lferoceon_cache_line_size
79 ldr ip, .Lferoceon_asm_page_mask
81 rsb r2, r2, #PAGE_SIZE
89 orr r3, lr, #I32_bit | F32_bit
91 mcr p15, 5, r0, c15, c15, 0 /* Clean and inv zone start address */
92 mcr p15, 5, r2, c15, c15, 1 /* Clean and inv zone end address */
104 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
108 ENTRY(feroceon_idcache_wbinv_range)
111 /* Start with cache line aligned address */
112 ldr ip, .Lferoceon_cache_line_size
121 ldr ip, .Lferoceon_asm_page_mask
123 rsb r2, r2, #PAGE_SIZE
131 orr r3, lr, #I32_bit | F32_bit
133 mcr p15, 5, r0, c15, c15, 0 /* Clean and inv zone start address */
134 mcr p15, 5, r2, c15, c15, 1 /* Clean and inv zone end address */
138 /* Invalidate and clean icache line by line */
139 ldr r3, .Lferoceon_cache_line_size
142 mcr p15, 0, r0, c7, c5, 1
155 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
159 ENTRY(feroceon_dcache_inv_range)
162 /* Start with cache line aligned address */
163 ldr ip, .Lferoceon_cache_line_size
172 ldr ip, .Lferoceon_asm_page_mask
174 rsb r2, r2, #PAGE_SIZE
182 orr r3, lr, #I32_bit | F32_bit
184 mcr p15, 5, r0, c15, c14, 0 /* Inv zone start address */
185 mcr p15, 5, r2, c15, c14, 1 /* Inv zone end address */
197 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
201 ENTRY(feroceon_dcache_wb_range)
204 /* Start with cache line aligned address */
205 ldr ip, .Lferoceon_cache_line_size
214 ldr ip, .Lferoceon_asm_page_mask
216 rsb r2, r2, #PAGE_SIZE
224 orr r3, lr, #I32_bit | F32_bit
226 mcr p15, 5, r0, c15, c13, 0 /* Clean zone start address */
227 mcr p15, 5, r2, c15, c13, 1 /* Clean zone end address */
239 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
243 ENTRY(feroceon_l2cache_wbinv_range)
246 /* Start with cache line aligned address */
247 ldr ip, .Lferoceon_cache_line_size
256 ldr ip, .Lferoceon_asm_page_mask
258 rsb r2, r2, #PAGE_SIZE
266 orr r3, lr, #I32_bit | F32_bit
268 mcr p15, 1, r0, c15, c9, 4 /* Clean L2 zone start address */
269 mcr p15, 1, r2, c15, c9, 5 /* Clean L2 zone end address */
270 mcr p15, 1, r0, c15, c11, 4 /* Inv L2 zone start address */
271 mcr p15, 1, r2, c15, c11, 5 /* Inv L2 zone end address */
283 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
287 ENTRY(feroceon_l2cache_inv_range)
290 /* Start with cache line aligned address */
291 ldr ip, .Lferoceon_cache_line_size
300 ldr ip, .Lferoceon_asm_page_mask
302 rsb r2, r2, #PAGE_SIZE
310 orr r3, lr, #I32_bit | F32_bit
312 mcr p15, 1, r0, c15, c11, 4 /* Inv L2 zone start address */
313 mcr p15, 1, r2, c15, c11, 5 /* Inv L2 zone end address */
325 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
329 ENTRY(feroceon_l2cache_wb_range)
332 /* Start with cache line aligned address */
333 ldr ip, .Lferoceon_cache_line_size
342 ldr ip, .Lferoceon_asm_page_mask
344 rsb r2, r2, #PAGE_SIZE
352 orr r3, lr, #I32_bit | F32_bit
354 mcr p15, 1, r0, c15, c9, 4 /* Clean L2 zone start address */
355 mcr p15, 1, r2, c15, c9, 5 /* Clean L2 zone end address */
367 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
371 ENTRY(feroceon_l2cache_wbinv_all)
373 mcr p15, 1, r0, c15, c9, 0 /* Clean L2 */
374 mcr p15, 1, r0, c15, c11, 0 /* Invalidate L2 */
375 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
378 ENTRY(feroceon_control_ext)
379 mrc p15, 1, r3, c15, c1, 0 /* Read the control register */
380 bic r2, r3, r0 /* Clear bits */
381 eor r2, r2, r1 /* XOR bits */
383 teq r2, r3 /* Only write if there is a change */
384 mcrne p15, 1, r2, c15, c1, 0 /* Write new control register */
385 mov r0, r3 /* Return old value */