2 * Copyright (C) 2011 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$");
38 .word _C_LABEL(arm_cache_loc)
40 .word _C_LABEL(arm_cache_type)
48 #define PT_NOS (1 << 5)
51 #define PT_INNER_WT (1 << 0)
52 #define PT_INNER_WB ((1 << 0) | (1 << 6))
53 #define PT_INNER_WBWA (1 << 6)
55 #define PT_OUTER_WT (2 << 3)
56 #define PT_OUTER_WB (3 << 3)
57 #define PT_OUTER_WBWA (1 << 3)
60 #define PT_ATTR (PT_S|PT_INNER_WT|PT_OUTER_WT|PT_NOS)
62 #define PT_ATTR (PT_INNER_WT|PT_OUTER_WT)
67 bl _C_LABEL(armv7_idcache_wbinv_all) /* clean the D cache */
72 mcr p15, 0, r0, c2, c0, 0 /* Translation Table Base Register 0 (TTBR0) */
74 mcr p15, 0, r0, c8, c3, 0 /* invalidate I+D TLBs Inner Shareable*/
76 mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
83 ENTRY(armv7_tlb_flushID)
86 mcr p15, 0, r0, c8, c3, 0 /* flush I+D tlb */
87 mcr p15, 0, r0, c7, c1, 6 /* flush BTB */
89 mcr p15, 0, r0, c8, c7, 0 /* flush I+D tlb */
90 mcr p15, 0, r0, c7, c5, 6 /* flush BTB */
95 END(armv7_tlb_flushID)
97 ENTRY(armv7_tlb_flushID_SE)
101 mcr p15, 0, r0, c8, c3, 1 /* flush D tlb single entry Inner Shareable*/
102 mcr p15, 0, r0, c7, c1, 6 /* flush BTB Inner Shareable */
104 mcr p15, 0, r0, c8, c7, 1 /* flush D tlb single entry */
105 mcr p15, 0, r0, c7, c5, 6 /* flush BTB */
110 END(armv7_tlb_flushID_SE)
112 /* Based on algorithm from ARM Architecture Reference Manual */
113 ENTRY(armv7_dcache_wbinv_all)
114 stmdb sp!, {r4, r5, r6, r7, r8, r9}
116 /* Get cache level */
117 ldr r0, .Lcoherency_level
121 /* For each cache level */
124 /* Get cache type for given level */
134 /* Get number of ways */
136 ands r4, r4, r1, lsr #3
141 ands r7, r7, r1, lsr #13
146 orr r6, r6, r9, lsl r5
147 orr r6, r6, r7, lsl r2
149 /* Clean and invalidate data cache by way/index */
150 mcr p15, 0, r6, c7, c14, 2
161 ldmia sp!, {r4, r5, r6, r7, r8, r9}
163 END(armv7_dcache_wbinv_all)
165 ENTRY(armv7_idcache_wbinv_all)
167 bl armv7_dcache_wbinv_all
169 mcr p15, 0, r0, c7, c1, 0 /* Invalidate all I caches to PoU (ICIALLUIS) */
171 mcr p15, 0, r0, c7, c5, 0 /* Invalidate all I caches to PoU (ICIALLU) */
177 END(armv7_idcache_wbinv_all)
179 /* XXX Temporary set it to 32 for MV cores, however this value should be
180 * get from Cache Type register
185 ENTRY(armv7_dcache_wb_range)
186 ldr ip, .Larmv7_line_size
192 mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
196 dsb /* data synchronization barrier */
198 END(armv7_dcache_wb_range)
200 ENTRY(armv7_dcache_wbinv_range)
201 ldr ip, .Larmv7_line_size
207 mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
210 bhi .Larmv7_wbinv_next
211 dsb /* data synchronization barrier */
213 END(armv7_dcache_wbinv_range)
216 * Note, we must not invalidate everything. If the range is too big we
217 * must use wb-inv of the entire cache.
219 ENTRY(armv7_dcache_inv_range)
220 ldr ip, .Larmv7_line_size
226 mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
230 dsb /* data synchronization barrier */
232 END(armv7_dcache_inv_range)
234 ENTRY(armv7_idcache_wbinv_range)
235 ldr ip, .Larmv7_line_size
240 .Larmv7_id_wbinv_next:
241 mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
242 mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
245 bhi .Larmv7_id_wbinv_next
246 isb /* instruction synchronization barrier */
247 dsb /* data synchronization barrier */
249 END(armv7_idcache_wbinv_range)
251 ENTRY_NP(armv7_icache_sync_range)
252 ldr ip, .Larmv7_line_size
254 mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
255 mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
258 bhi .Larmv7_sync_next
259 isb /* instruction synchronization barrier */
260 dsb /* data synchronization barrier */
262 END(armv7_icache_sync_range)
264 ENTRY(armv7_cpu_sleep)
265 dsb /* data synchronization barrier */
266 wfi /* wait for interrupt */
270 ENTRY(armv7_context_switch)
274 mcr p15, 0, r0, c2, c0, 0 /* set the new TTB */
276 mcr p15, 0, r0, c8, c3, 0 /* and flush the I+D tlbs Inner Sharable */
278 mcr p15, 0, r0, c8, c7, 0 /* and flush the I+D tlbs */
283 END(armv7_context_switch)
285 ENTRY(armv7_drain_writebuf)
288 END(armv7_drain_writebuf)
298 mrc p15, 0, r2, c1, c0, 1
299 bic r3, r2, r0 /* Clear bits */
300 eor r3, r3, r1 /* XOR bits */
303 mcrne p15, 0, r3, c1, c0, 1