xref: /openbmc/u-boot/arch/arm/cpu/armv8/cache_v8.c (revision 9e414032)
1 /*
2  * (C) Copyright 2013
3  * David Feng <fenghua@phytium.com.cn>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <asm/system.h>
10 #include <asm/armv8/mmu.h>
11 
12 DECLARE_GLOBAL_DATA_PTR;
13 
14 #ifndef CONFIG_SYS_DCACHE_OFF
15 
16 static void set_pgtable_section(u64 section, u64 memory_type)
17 {
18 	u64 *page_table = (u64 *)gd->arch.tlb_addr;
19 	u64 value;
20 
21 	value = (section << SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF;
22 	value |= PMD_ATTRINDX(memory_type);
23 	page_table[section] = value;
24 }
25 
26 /* to activate the MMU we need to set up virtual memory */
27 static void mmu_setup(void)
28 {
29 	int i, j, el;
30 	bd_t *bd = gd->bd;
31 
32 	/* Setup an identity-mapping for all spaces */
33 	for (i = 0; i < (PGTABLE_SIZE >> 3); i++)
34 		set_pgtable_section(i, MT_DEVICE_NGNRNE);
35 
36 	/* Setup an identity-mapping for all RAM space */
37 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
38 		ulong start = bd->bi_dram[i].start;
39 		ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size;
40 		for (j = start >> SECTION_SHIFT;
41 		     j < end >> SECTION_SHIFT; j++) {
42 			set_pgtable_section(j, MT_NORMAL);
43 		}
44 	}
45 
46 	/* load TTBR0 */
47 	el = current_el();
48 	if (el == 1)
49 		asm volatile("msr ttbr0_el1, %0"
50 			     : : "r" (gd->arch.tlb_addr) : "memory");
51 	else if (el == 2)
52 		asm volatile("msr ttbr0_el2, %0"
53 			     : : "r" (gd->arch.tlb_addr) : "memory");
54 	else
55 		asm volatile("msr ttbr0_el3, %0"
56 			     : : "r" (gd->arch.tlb_addr) : "memory");
57 
58 	/* enable the mmu */
59 	set_sctlr(get_sctlr() | CR_M);
60 }
61 
62 /*
63  * Performs a invalidation of the entire data cache at all levels
64  */
65 void invalidate_dcache_all(void)
66 {
67 	__asm_flush_dcache_all();
68 }
69 
70 /*
71  * Performs a clean & invalidation of the entire data cache at all levels
72  */
73 void flush_dcache_all(void)
74 {
75 	__asm_flush_dcache_all();
76 }
77 
78 /*
79  * Invalidates range in all levels of D-cache/unified cache
80  */
81 void invalidate_dcache_range(unsigned long start, unsigned long stop)
82 {
83 	__asm_flush_dcache_range(start, stop);
84 }
85 
86 /*
87  * Flush range(clean & invalidate) from all levels of D-cache/unified cache
88  */
89 void flush_dcache_range(unsigned long start, unsigned long stop)
90 {
91 	__asm_flush_dcache_range(start, stop);
92 }
93 
94 void dcache_enable(void)
95 {
96 	/* The data cache is not active unless the mmu is enabled */
97 	if (!(get_sctlr() & CR_M)) {
98 		invalidate_dcache_all();
99 		__asm_invalidate_tlb_all();
100 		mmu_setup();
101 	}
102 
103 	set_sctlr(get_sctlr() | CR_C);
104 }
105 
106 void dcache_disable(void)
107 {
108 	uint32_t sctlr;
109 
110 	sctlr = get_sctlr();
111 
112 	/* if cache isn't enabled no need to disable */
113 	if (!(sctlr & CR_C))
114 		return;
115 
116 	set_sctlr(sctlr & ~(CR_C|CR_M));
117 
118 	flush_dcache_all();
119 	__asm_invalidate_tlb_all();
120 }
121 
122 int dcache_status(void)
123 {
124 	return (get_sctlr() & CR_C) != 0;
125 }
126 
127 #else	/* CONFIG_SYS_DCACHE_OFF */
128 
129 void invalidate_dcache_all(void)
130 {
131 }
132 
133 void flush_dcache_all(void)
134 {
135 }
136 
137 void invalidate_dcache_range(unsigned long start, unsigned long stop)
138 {
139 }
140 
141 void flush_dcache_range(unsigned long start, unsigned long stop)
142 {
143 }
144 
145 void dcache_enable(void)
146 {
147 }
148 
149 void dcache_disable(void)
150 {
151 }
152 
153 int dcache_status(void)
154 {
155 	return 0;
156 }
157 
158 #endif	/* CONFIG_SYS_DCACHE_OFF */
159 
160 #ifndef CONFIG_SYS_ICACHE_OFF
161 
162 void icache_enable(void)
163 {
164 	set_sctlr(get_sctlr() | CR_I);
165 }
166 
167 void icache_disable(void)
168 {
169 	set_sctlr(get_sctlr() & ~CR_I);
170 }
171 
172 int icache_status(void)
173 {
174 	return (get_sctlr() & CR_I) != 0;
175 }
176 
177 void invalidate_icache_all(void)
178 {
179 	__asm_invalidate_icache_all();
180 }
181 
182 #else	/* CONFIG_SYS_ICACHE_OFF */
183 
184 void icache_enable(void)
185 {
186 }
187 
188 void icache_disable(void)
189 {
190 }
191 
192 int icache_status(void)
193 {
194 	return 0;
195 }
196 
197 void invalidate_icache_all(void)
198 {
199 }
200 
201 #endif	/* CONFIG_SYS_ICACHE_OFF */
202 
203 /*
204  * Enable dCache & iCache, whether cache is actually enabled
205  * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF
206  */
207 void enable_caches(void)
208 {
209 	icache_enable();
210 	dcache_enable();
211 }
212 
213 /*
214  * Flush range from all levels of d-cache/unified-cache
215  */
216 void flush_cache(unsigned long start, unsigned long size)
217 {
218 	flush_dcache_range(start, start + size);
219 }
220