cpu-v4.h revision 280985
1276333Sian/*-
2276333Sian * Copyright 2014 Svatopluk Kraus <onwahe@gmail.com>
3276333Sian * Copyright 2014 Michal Meloun <meloun@miracle.cz>
4276333Sian * All rights reserved.
5276333Sian *
6276333Sian * Redistribution and use in source and binary forms, with or without
7276333Sian * modification, are permitted provided that the following conditions
8276333Sian * are met:
9276333Sian * 1. Redistributions of source code must retain the above copyright
10276333Sian *    notice, this list of conditions and the following disclaimer.
11276333Sian * 2. Redistributions in binary form must reproduce the above copyright
12276333Sian *    notice, this list of conditions and the following disclaimer in the
13276333Sian *    documentation and/or other materials provided with the distribution.
14276333Sian *
15276333Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16276333Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17276333Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18276333Sian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19276333Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20276333Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21276333Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22276333Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23276333Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24276333Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25276333Sian * SUCH DAMAGE.
26276333Sian *
27276333Sian * $FreeBSD: head/sys/arm/include/cpu-v6.h 280985 2015-04-02 12:56:06Z andrew $
28276333Sian */
29276333Sian#ifndef MACHINE_CPU_V6_H
30276333Sian#define MACHINE_CPU_V6_H
31276333Sian
32276333Sian#include "machine/atomic.h"
33276333Sian#include "machine/cpufunc.h"
34276333Sian#include "machine/cpuinfo.h"
35276333Sian#include "machine/sysreg.h"
36276333Sian
37276333Sian
38276333Sian#define CPU_ASID_KERNEL 0
39276333Sian
40279811Sianvm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t);
41279811Sianvm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t);
42279811Sian
43276333Sian/*
44276333Sian * Macros to generate CP15 (system control processor) read/write functions.
45276333Sian */
46276333Sian#define _FX(s...) #s
47276333Sian
48276333Sian#define _RF0(fname, aname...)						\
49276333Sianstatic __inline register_t						\
50276333Sianfname(void)								\
51276333Sian{									\
52276333Sian	register_t reg;							\
53276333Sian	__asm __volatile("mrc\t" _FX(aname): "=r" (reg));		\
54276333Sian	return(reg);							\
55276333Sian}
56276333Sian
57280985Sandrew#define _R64F0(fname, aname)						\
58280985Sandrewstatic __inline uint64_t						\
59280985Sandrewfname(void)								\
60280985Sandrew{									\
61280985Sandrew	uint64_t reg;							\
62280985Sandrew	__asm __volatile("mrrc\t" _FX(aname): "=r" (reg));		\
63280985Sandrew	return(reg);							\
64280985Sandrew}
65280985Sandrew
66276333Sian#define _WF0(fname, aname...)						\
67276333Sianstatic __inline void							\
68276333Sianfname(void)								\
69276333Sian{									\
70276333Sian	__asm __volatile("mcr\t" _FX(aname));				\
71276333Sian}
72276333Sian
73276333Sian#define _WF1(fname, aname...)						\
74276333Sianstatic __inline void							\
75276333Sianfname(register_t reg)							\
76276333Sian{									\
77276333Sian	__asm __volatile("mcr\t" _FX(aname):: "r" (reg));		\
78276333Sian}
79276333Sian
80280985Sandrew#define _W64F1(fname, aname...)						\
81280985Sandrewstatic __inline void							\
82280985Sandrewfname(uint64_t reg)							\
83280985Sandrew{									\
84280985Sandrew	__asm __volatile("mcrr\t" _FX(aname):: "r" (reg));		\
85280985Sandrew}
86280985Sandrew
87276333Sian/*
88276333Sian * Raw CP15  maintenance operations
89276333Sian * !!! not for external use !!!
90276333Sian */
91276333Sian
92276333Sian/* TLB */
93276333Sian
94276333Sian_WF0(_CP15_TLBIALL, CP15_TLBIALL)		/* Invalidate entire unified TLB */
95276333Sian#if __ARM_ARCH >= 7 && defined SMP
96276333Sian_WF0(_CP15_TLBIALLIS, CP15_TLBIALLIS)		/* Invalidate entire unified TLB IS */
97276333Sian#endif
98276333Sian_WF1(_CP15_TLBIASID, CP15_TLBIASID(%0))		/* Invalidate unified TLB by ASID */
99276333Sian#if __ARM_ARCH >= 7 && defined SMP
100276333Sian_WF1(_CP15_TLBIASIDIS, CP15_TLBIASIDIS(%0))	/* Invalidate unified TLB by ASID IS */
101276333Sian#endif
102276333Sian_WF1(_CP15_TLBIMVAA, CP15_TLBIMVAA(%0))		/* Invalidate unified TLB by MVA, all ASID */
103276333Sian#if __ARM_ARCH >= 7 && defined SMP
104276333Sian_WF1(_CP15_TLBIMVAAIS, CP15_TLBIMVAAIS(%0))	/* Invalidate unified TLB by MVA, all ASID IS */
105276333Sian#endif
106276333Sian_WF1(_CP15_TLBIMVA, CP15_TLBIMVA(%0))		/* Invalidate unified TLB by MVA */
107276333Sian
108276333Sian_WF1(_CP15_TTB_SET, CP15_TTBR0(%0))
109276333Sian
110276333Sian/* Cache and Branch predictor */
111276333Sian
112276333Sian_WF0(_CP15_BPIALL, CP15_BPIALL)			/* Branch predictor invalidate all */
113276333Sian#if __ARM_ARCH >= 7 && defined SMP
114276333Sian_WF0(_CP15_BPIALLIS, CP15_BPIALLIS)		/* Branch predictor invalidate all IS */
115276333Sian#endif
116276333Sian_WF1(_CP15_BPIMVA, CP15_BPIMVA(%0))		/* Branch predictor invalidate by MVA */
117276333Sian_WF1(_CP15_DCCIMVAC, CP15_DCCIMVAC(%0))		/* Data cache clean and invalidate by MVA PoC */
118276333Sian_WF1(_CP15_DCCISW, CP15_DCCISW(%0))		/* Data cache clean and invalidate by set/way */
119276333Sian_WF1(_CP15_DCCMVAC, CP15_DCCMVAC(%0))		/* Data cache clean by MVA PoC */
120276333Sian#if __ARM_ARCH >= 7
121276333Sian_WF1(_CP15_DCCMVAU, CP15_DCCMVAU(%0))		/* Data cache clean by MVA PoU */
122276333Sian#endif
123276333Sian_WF1(_CP15_DCCSW, CP15_DCCSW(%0))		/* Data cache clean by set/way */
124276333Sian_WF1(_CP15_DCIMVAC, CP15_DCIMVAC(%0))		/* Data cache invalidate by MVA PoC */
125276333Sian_WF1(_CP15_DCISW, CP15_DCISW(%0))		/* Data cache invalidate by set/way */
126276333Sian_WF0(_CP15_ICIALLU, CP15_ICIALLU)		/* Instruction cache invalidate all PoU */
127276333Sian#if __ARM_ARCH >= 7 && defined SMP
128276333Sian_WF0(_CP15_ICIALLUIS, CP15_ICIALLUIS)		/* Instruction cache invalidate all PoU IS */
129276333Sian#endif
130276333Sian_WF1(_CP15_ICIMVAU, CP15_ICIMVAU(%0))		/* Instruction cache invalidate */
131276333Sian
132276333Sian/*
133276333Sian * Publicly accessible functions
134276333Sian */
135276333Sian
136276333Sian/* Various control registers */
137276333Sian
138276333Sian_RF0(cp15_dfsr_get, CP15_DFSR(%0))
139276333Sian_RF0(cp15_ifsr_get, CP15_IFSR(%0))
140276333Sian_WF1(cp15_prrr_set, CP15_PRRR(%0))
141276333Sian_WF1(cp15_nmrr_set, CP15_NMRR(%0))
142276333Sian_RF0(cp15_ttbr_get, CP15_TTBR0(%0))
143276333Sian_RF0(cp15_dfar_get, CP15_DFAR(%0))
144276333Sian#if __ARM_ARCH >= 7
145276333Sian_RF0(cp15_ifar_get, CP15_IFAR(%0))
146276333Sian#endif
147276333Sian
148276333Sian/*CPU id registers */
149276333Sian_RF0(cp15_midr_get, CP15_MIDR(%0))
150276333Sian_RF0(cp15_ctr_get, CP15_CTR(%0))
151276333Sian_RF0(cp15_tcmtr_get, CP15_TCMTR(%0))
152276333Sian_RF0(cp15_tlbtr_get, CP15_TLBTR(%0))
153276333Sian_RF0(cp15_mpidr_get, CP15_MPIDR(%0))
154276333Sian_RF0(cp15_revidr_get, CP15_REVIDR(%0))
155276333Sian_RF0(cp15_aidr_get, CP15_AIDR(%0))
156276333Sian_RF0(cp15_id_pfr0_get, CP15_ID_PFR0(%0))
157276333Sian_RF0(cp15_id_pfr1_get, CP15_ID_PFR1(%0))
158276333Sian_RF0(cp15_id_dfr0_get, CP15_ID_DFR0(%0))
159276333Sian_RF0(cp15_id_afr0_get, CP15_ID_AFR0(%0))
160276333Sian_RF0(cp15_id_mmfr0_get, CP15_ID_MMFR0(%0))
161276333Sian_RF0(cp15_id_mmfr1_get, CP15_ID_MMFR1(%0))
162276333Sian_RF0(cp15_id_mmfr2_get, CP15_ID_MMFR2(%0))
163276333Sian_RF0(cp15_id_mmfr3_get, CP15_ID_MMFR3(%0))
164276333Sian_RF0(cp15_id_isar0_get, CP15_ID_ISAR0(%0))
165276333Sian_RF0(cp15_id_isar1_get, CP15_ID_ISAR1(%0))
166276333Sian_RF0(cp15_id_isar2_get, CP15_ID_ISAR2(%0))
167276333Sian_RF0(cp15_id_isar3_get, CP15_ID_ISAR3(%0))
168276333Sian_RF0(cp15_id_isar4_get, CP15_ID_ISAR4(%0))
169276333Sian_RF0(cp15_id_isar5_get, CP15_ID_ISAR5(%0))
170276333Sian_RF0(cp15_cbar_get, CP15_CBAR(%0))
171276333Sian
172276803Sian/* Performance Monitor registers */
173276803Sian
174276803Sian#if __ARM_ARCH == 6 && defined(CPU_ARM1176)
175276803Sian_RF0(cp15_pmccntr_get, CP15_PMCCNTR(%0))
176276803Sian_WF1(cp15_pmccntr_set, CP15_PMCCNTR(%0))
177276803Sian#elif __ARM_ARCH > 6
178276803Sian_RF0(cp15_pmcr_get, CP15_PMCR(%0))
179276803Sian_WF1(cp15_pmcr_set, CP15_PMCR(%0))
180276803Sian_RF0(cp15_pmcnten_get, CP15_PMCNTENSET(%0))
181276803Sian_WF1(cp15_pmcnten_set, CP15_PMCNTENSET(%0))
182276803Sian_WF1(cp15_pmcnten_clr, CP15_PMCNTENCLR(%0))
183276803Sian_RF0(cp15_pmovsr_get, CP15_PMOVSR(%0))
184276803Sian_WF1(cp15_pmovsr_set, CP15_PMOVSR(%0))
185276803Sian_WF1(cp15_pmswinc_set, CP15_PMSWINC(%0))
186276803Sian_RF0(cp15_pmselr_get, CP15_PMSELR(%0))
187276803Sian_WF1(cp15_pmselr_set, CP15_PMSELR(%0))
188276803Sian_RF0(cp15_pmccntr_get, CP15_PMCCNTR(%0))
189276803Sian_WF1(cp15_pmccntr_set, CP15_PMCCNTR(%0))
190276803Sian_RF0(cp15_pmxevtyper_get, CP15_PMXEVTYPER(%0))
191276803Sian_WF1(cp15_pmxevtyper_set, CP15_PMXEVTYPER(%0))
192276803Sian_RF0(cp15_pmxevcntr_get, CP15_PMXEVCNTRR(%0))
193276803Sian_WF1(cp15_pmxevcntr_set, CP15_PMXEVCNTRR(%0))
194276803Sian_RF0(cp15_pmuserenr_get, CP15_PMUSERENR(%0))
195276803Sian_WF1(cp15_pmuserenr_set, CP15_PMUSERENR(%0))
196276803Sian_RF0(cp15_pminten_get, CP15_PMINTENSET(%0))
197276803Sian_WF1(cp15_pminten_set, CP15_PMINTENSET(%0))
198276803Sian_WF1(cp15_pminten_clr, CP15_PMINTENCLR(%0))
199276803Sian#endif
200276803Sian
201277415Sandrew_RF0(cp15_tpidrurw_get, CP15_TPIDRURW(%0))
202277415Sandrew_WF1(cp15_tpidrurw_set, CP15_TPIDRURW(%0))
203277415Sandrew_RF0(cp15_tpidruro_get, CP15_TPIDRURO(%0))
204277415Sandrew_WF1(cp15_tpidruro_set, CP15_TPIDRURO(%0))
205277415Sandrew_RF0(cp15_tpidrpwr_get, CP15_TPIDRPRW(%0))
206277415Sandrew_WF1(cp15_tpidrpwr_set, CP15_TPIDRPRW(%0))
207277415Sandrew
208280985Sandrew/* Generic Timer registers - only use when you know the hardware is available */
209280985Sandrew_RF0(cp15_cntfrq_get, CP15_CNTFRQ(%0))
210280985Sandrew_WF1(cp15_cntfrq_set, CP15_CNTFRQ(%0))
211280985Sandrew_RF0(cp15_cntkctl_get, CP15_CNTKCTL(%0))
212280985Sandrew_WF1(cp15_cntkctl_set, CP15_CNTKCTL(%0))
213280985Sandrew_RF0(cp15_cntp_tval_get, CP15_CNTP_TVAL(%0))
214280985Sandrew_WF1(cp15_cntp_tval_set, CP15_CNTP_TVAL(%0))
215280985Sandrew_RF0(cp15_cntp_ctl_get, CP15_CNTP_CTL(%0))
216280985Sandrew_WF1(cp15_cntp_ctl_set, CP15_CNTP_CTL(%0))
217280985Sandrew_RF0(cp15_cntv_tval_get, CP15_CNTV_TVAL(%0))
218280985Sandrew_WF1(cp15_cntv_tval_set, CP15_CNTV_TVAL(%0))
219280985Sandrew_RF0(cp15_cntv_ctl_get, CP15_CNTV_CTL(%0))
220280985Sandrew_WF1(cp15_cntv_ctl_set, CP15_CNTV_CTL(%0))
221280985Sandrew_RF0(cp15_cnthctl_get, CP15_CNTHCTL(%0))
222280985Sandrew_WF1(cp15_cnthctl_set, CP15_CNTHCTL(%0))
223280985Sandrew_RF0(cp15_cnthp_tval_get, CP15_CNTHP_TVAL(%0))
224280985Sandrew_WF1(cp15_cnthp_tval_set, CP15_CNTHP_TVAL(%0))
225280985Sandrew_RF0(cp15_cnthp_ctl_get, CP15_CNTHP_CTL(%0))
226280985Sandrew_WF1(cp15_cnthp_ctl_set, CP15_CNTHP_CTL(%0))
227280985Sandrew
228280985Sandrew_R64F0(cp15_cntpct_get, CP15_CNTPCT(%Q0, %R0))
229280985Sandrew_R64F0(cp15_cntvct_get, CP15_CNTVCT(%Q0, %R0))
230280985Sandrew_R64F0(cp15_cntp_cval_get, CP15_CNTP_CVAL(%Q0, %R0))
231280985Sandrew_W64F1(cp15_cntp_cval_set, CP15_CNTP_CVAL(%Q0, %R0))
232280985Sandrew_R64F0(cp15_cntv_cval_get, CP15_CNTV_CVAL(%Q0, %R0))
233280985Sandrew_W64F1(cp15_cntv_cval_set, CP15_CNTV_CVAL(%Q0, %R0))
234280985Sandrew_R64F0(cp15_cntvoff_get, CP15_CNTVOFF(%Q0, %R0))
235280985Sandrew_W64F1(cp15_cntvoff_set, CP15_CNTVOFF(%Q0, %R0))
236280985Sandrew_R64F0(cp15_cnthp_cval_get, CP15_CNTHP_CVAL(%Q0, %R0))
237280985Sandrew_W64F1(cp15_cnthp_cval_set, CP15_CNTHP_CVAL(%Q0, %R0))
238280985Sandrew
239276333Sian#undef	_FX
240276333Sian#undef	_RF0
241276333Sian#undef	_WF0
242276333Sian#undef	_WF1
243276333Sian
244276334Sian/*
245276334Sian * TLB maintenance operations.
246276334Sian */
247276334Sian
248276334Sian/* Local (i.e. not broadcasting ) operations.  */
249276334Sian
250276334Sian/* Flush all TLB entries (even global). */
251276334Sianstatic __inline void
252276334Siantlb_flush_all_local(void)
253276334Sian{
254276334Sian
255276334Sian	dsb();
256276334Sian	_CP15_TLBIALL();
257276334Sian	dsb();
258276334Sian}
259276334Sian
260276334Sian/* Flush all not global TLB entries. */
261276334Sianstatic __inline void
262276334Siantlb_flush_all_ng_local(void)
263276334Sian{
264276334Sian
265276334Sian	dsb();
266276334Sian	_CP15_TLBIASID(CPU_ASID_KERNEL);
267276334Sian	dsb();
268276334Sian}
269276334Sian
270276334Sian/* Flush single TLB entry (even global). */
271276334Sianstatic __inline void
272276334Siantlb_flush_local(vm_offset_t sva)
273276334Sian{
274276334Sian
275276334Sian	dsb();
276276334Sian	_CP15_TLBIMVA((sva & ~PAGE_MASK ) | CPU_ASID_KERNEL);
277276334Sian	dsb();
278276334Sian}
279276334Sian
280276334Sian/* Flush range of TLB entries (even global). */
281276334Sianstatic __inline void
282276334Siantlb_flush_range_local(vm_offset_t sva, vm_size_t size)
283276334Sian{
284276334Sian	vm_offset_t va;
285276334Sian	vm_offset_t eva = sva + size;
286276334Sian
287276334Sian	dsb();
288276334Sian	for (va = sva; va < eva; va += PAGE_SIZE)
289276334Sian		_CP15_TLBIMVA((va & ~PAGE_MASK ) | CPU_ASID_KERNEL);
290276334Sian	dsb();
291276334Sian}
292276334Sian
293276334Sian/* Broadcasting operations. */
294276803Sian#if __ARM_ARCH >= 7 && defined SMP
295276334Sian
296276334Sianstatic __inline void
297276334Siantlb_flush_all(void)
298276334Sian{
299276334Sian
300276334Sian	dsb();
301276334Sian	_CP15_TLBIALLIS();
302276334Sian	dsb();
303276334Sian}
304276334Sian
305276334Sianstatic __inline void
306276340Siantlb_flush_all_ng(void)
307276334Sian{
308276334Sian
309276334Sian	dsb();
310276334Sian	_CP15_TLBIASIDIS(CPU_ASID_KERNEL);
311276334Sian	dsb();
312276334Sian}
313276334Sian
314276334Sianstatic __inline void
315276334Siantlb_flush(vm_offset_t sva)
316276334Sian{
317276334Sian
318276334Sian	dsb();
319276334Sian	_CP15_TLBIMVAAIS(sva);
320276334Sian	dsb();
321276334Sian}
322276334Sian
323276334Sianstatic __inline void
324276334Siantlb_flush_range(vm_offset_t sva,  vm_size_t size)
325276334Sian{
326276334Sian	vm_offset_t va;
327276334Sian	vm_offset_t eva = sva + size;
328276334Sian
329276334Sian	dsb();
330276334Sian	for (va = sva; va < eva; va += PAGE_SIZE)
331276334Sian		_CP15_TLBIMVAAIS(va);
332276334Sian	dsb();
333276334Sian}
334276803Sian#else /* SMP */
335276803Sian
336276803Sian#define tlb_flush_all() 		tlb_flush_all_local()
337276803Sian#define tlb_flush_all_ng() 		tlb_flush_all_ng_local()
338276803Sian#define tlb_flush(sva) 			tlb_flush_local(sva)
339276803Sian#define tlb_flush_range(sva, size) 	tlb_flush_range_local(sva, size)
340276803Sian
341276334Sian#endif /* SMP */
342276334Sian
343276334Sian/*
344276334Sian * Cache maintenance operations.
345276334Sian */
346276334Sian
347276334Sian/*  Sync I and D caches to PoU */
348276334Sianstatic __inline void
349276334Sianicache_sync(vm_offset_t sva, vm_size_t size)
350276334Sian{
351276334Sian	vm_offset_t va;
352276334Sian	vm_offset_t eva = sva + size;
353276334Sian
354276334Sian	dsb();
355279811Sian	for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
356276803Sian#if __ARM_ARCH >= 7 && defined SMP
357276334Sian		_CP15_DCCMVAU(va);
358276334Sian#else
359276334Sian		_CP15_DCCMVAC(va);
360276334Sian#endif
361276334Sian	}
362276334Sian	dsb();
363276803Sian#if __ARM_ARCH >= 7 && defined SMP
364276334Sian	_CP15_ICIALLUIS();
365276334Sian#else
366276334Sian	_CP15_ICIALLU();
367276334Sian#endif
368276334Sian	dsb();
369276334Sian	isb();
370276334Sian}
371276334Sian
372276334Sian/*  Invalidate I cache */
373276334Sianstatic __inline void
374276334Sianicache_inv_all(void)
375276334Sian{
376276803Sian#if __ARM_ARCH >= 7 && defined SMP
377276334Sian	_CP15_ICIALLUIS();
378276334Sian#else
379276334Sian	_CP15_ICIALLU();
380276334Sian#endif
381276334Sian	dsb();
382276334Sian	isb();
383276334Sian}
384276334Sian
385279811Sian/* Invalidate branch predictor buffer */
386279811Sianstatic __inline void
387279811Sianbpb_inv_all(void)
388279811Sian{
389279811Sian#if __ARM_ARCH >= 7 && defined SMP
390279811Sian	_CP15_BPIALLIS();
391279811Sian#else
392279811Sian	_CP15_BPIALL();
393279811Sian#endif
394279811Sian	dsb();
395279811Sian	isb();
396279811Sian}
397279811Sian
398276334Sian/* Write back D-cache to PoU */
399276334Sianstatic __inline void
400276334Siandcache_wb_pou(vm_offset_t sva, vm_size_t size)
401276334Sian{
402276334Sian	vm_offset_t va;
403276334Sian	vm_offset_t eva = sva + size;
404276334Sian
405276334Sian	dsb();
406279811Sian	for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
407276803Sian#if __ARM_ARCH >= 7 && defined SMP
408276334Sian		_CP15_DCCMVAU(va);
409276334Sian#else
410276334Sian		_CP15_DCCMVAC(va);
411276334Sian#endif
412276334Sian	}
413276334Sian	dsb();
414276334Sian}
415276334Sian
416276334Sian/* Invalidate D-cache to PoC */
417276334Sianstatic __inline void
418276334Siandcache_inv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size)
419276334Sian{
420276334Sian	vm_offset_t va;
421276334Sian	vm_offset_t eva = sva + size;
422276334Sian
423276334Sian	/* invalidate L1 first */
424279811Sian	for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
425276334Sian		_CP15_DCIMVAC(va);
426276334Sian	}
427276334Sian	dsb();
428276334Sian
429276334Sian	/* then L2 */
430276334Sian 	cpu_l2cache_inv_range(pa, size);
431276334Sian	dsb();
432276334Sian
433276334Sian	/* then L1 again */
434279811Sian	for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
435276334Sian		_CP15_DCIMVAC(va);
436276334Sian	}
437276334Sian	dsb();
438276334Sian}
439276334Sian
440276334Sian/* Write back D-cache to PoC */
441276334Sianstatic __inline void
442276334Siandcache_wb_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size)
443276334Sian{
444276334Sian	vm_offset_t va;
445276334Sian	vm_offset_t eva = sva + size;
446276334Sian
447276334Sian	dsb();
448276334Sian
449279811Sian	for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
450276334Sian		_CP15_DCCMVAC(va);
451276334Sian	}
452276334Sian	dsb();
453276334Sian
454276334Sian	cpu_l2cache_wb_range(pa, size);
455276334Sian}
456276334Sian
457276334Sian/* Write back and invalidate D-cache to PoC */
458276334Sianstatic __inline void
459276334Siandcache_wbinv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size)
460276334Sian{
461276334Sian	vm_offset_t va;
462276334Sian	vm_offset_t eva = sva + size;
463276334Sian
464276334Sian	dsb();
465276334Sian
466276334Sian	/* write back L1 first */
467279811Sian	for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
468276334Sian		_CP15_DCCMVAC(va);
469276334Sian	}
470276334Sian	dsb();
471276334Sian
472276334Sian	/* then write back and invalidate L2 */
473276334Sian	cpu_l2cache_wbinv_range(pa, size);
474276334Sian
475276334Sian	/* then invalidate L1 */
476279811Sian	for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
477276334Sian		_CP15_DCIMVAC(va);
478276334Sian	}
479276334Sian	dsb();
480276334Sian}
481276334Sian
482276334Sian/* Set TTB0 register */
483276334Sianstatic __inline void
484276334Siancp15_ttbr_set(uint32_t reg)
485276334Sian{
486276334Sian	dsb();
487276334Sian	_CP15_TTB_SET(reg);
488276334Sian	dsb();
489276334Sian	_CP15_BPIALL();
490276334Sian	dsb();
491276334Sian	isb();
492276334Sian	tlb_flush_all_ng_local();
493276334Sian}
494276334Sian
495276333Sian#endif /* !MACHINE_CPU_V6_H */
496