]>
Commit | Line | Data |
---|---|---|
0ae76531 DF |
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 | |
22932ffc YS |
15 | void set_pgtable_section(u64 *page_table, u64 index, u64 section, |
16 | u64 memory_type) | |
0ae76531 | 17 | { |
0ae76531 DF |
18 | u64 value; |
19 | ||
22932ffc | 20 | value = section | PMD_TYPE_SECT | PMD_SECT_AF; |
0ae76531 | 21 | value |= PMD_ATTRINDX(memory_type); |
22932ffc | 22 | page_table[index] = value; |
0ae76531 DF |
23 | } |
24 | ||
25 | /* to activate the MMU we need to set up virtual memory */ | |
26 | static void mmu_setup(void) | |
27 | { | |
0ae76531 | 28 | bd_t *bd = gd->bd; |
8b19dff5 TR |
29 | u64 *page_table = (u64 *)gd->arch.tlb_addr, i, j; |
30 | int el; | |
0ae76531 DF |
31 | |
32 | /* Setup an identity-mapping for all spaces */ | |
22932ffc YS |
33 | for (i = 0; i < (PGTABLE_SIZE >> 3); i++) { |
34 | set_pgtable_section(page_table, i, i << SECTION_SHIFT, | |
35 | MT_DEVICE_NGNRNE); | |
36 | } | |
0ae76531 DF |
37 | |
38 | /* Setup an identity-mapping for all RAM space */ | |
39 | for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { | |
40 | ulong start = bd->bi_dram[i].start; | |
41 | ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size; | |
42 | for (j = start >> SECTION_SHIFT; | |
43 | j < end >> SECTION_SHIFT; j++) { | |
22932ffc YS |
44 | set_pgtable_section(page_table, j, j << SECTION_SHIFT, |
45 | MT_NORMAL); | |
0ae76531 DF |
46 | } |
47 | } | |
48 | ||
49 | /* load TTBR0 */ | |
50 | el = current_el(); | |
f5222cfd | 51 | if (el == 1) { |
22932ffc YS |
52 | set_ttbr_tcr_mair(el, gd->arch.tlb_addr, |
53 | TCR_FLAGS | TCR_EL1_IPS_BITS, | |
54 | MEMORY_ATTRIBUTES); | |
f5222cfd | 55 | } else if (el == 2) { |
22932ffc YS |
56 | set_ttbr_tcr_mair(el, gd->arch.tlb_addr, |
57 | TCR_FLAGS | TCR_EL2_IPS_BITS, | |
58 | MEMORY_ATTRIBUTES); | |
f5222cfd | 59 | } else { |
22932ffc YS |
60 | set_ttbr_tcr_mair(el, gd->arch.tlb_addr, |
61 | TCR_FLAGS | TCR_EL3_IPS_BITS, | |
62 | MEMORY_ATTRIBUTES); | |
f5222cfd | 63 | } |
0ae76531 DF |
64 | /* enable the mmu */ |
65 | set_sctlr(get_sctlr() | CR_M); | |
66 | } | |
67 | ||
68 | /* | |
69 | * Performs a invalidation of the entire data cache at all levels | |
70 | */ | |
71 | void invalidate_dcache_all(void) | |
72 | { | |
1e6ad55c | 73 | __asm_invalidate_dcache_all(); |
0ae76531 DF |
74 | } |
75 | ||
76 | /* | |
dcd468b8 YS |
77 | * Performs a clean & invalidation of the entire data cache at all levels. |
78 | * This function needs to be inline to avoid using stack. | |
79 | * __asm_flush_l3_cache return status of timeout | |
0ae76531 | 80 | */ |
dcd468b8 | 81 | inline void flush_dcache_all(void) |
0ae76531 | 82 | { |
dcd468b8 YS |
83 | int ret; |
84 | ||
0ae76531 | 85 | __asm_flush_dcache_all(); |
dcd468b8 YS |
86 | ret = __asm_flush_l3_cache(); |
87 | if (ret) | |
88 | debug("flushing dcache returns 0x%x\n", ret); | |
89 | else | |
90 | debug("flushing dcache successfully.\n"); | |
0ae76531 DF |
91 | } |
92 | ||
93 | /* | |
94 | * Invalidates range in all levels of D-cache/unified cache | |
95 | */ | |
96 | void invalidate_dcache_range(unsigned long start, unsigned long stop) | |
97 | { | |
98 | __asm_flush_dcache_range(start, stop); | |
99 | } | |
100 | ||
101 | /* | |
102 | * Flush range(clean & invalidate) from all levels of D-cache/unified cache | |
103 | */ | |
104 | void flush_dcache_range(unsigned long start, unsigned long stop) | |
105 | { | |
106 | __asm_flush_dcache_range(start, stop); | |
107 | } | |
108 | ||
109 | void dcache_enable(void) | |
110 | { | |
111 | /* The data cache is not active unless the mmu is enabled */ | |
112 | if (!(get_sctlr() & CR_M)) { | |
113 | invalidate_dcache_all(); | |
114 | __asm_invalidate_tlb_all(); | |
115 | mmu_setup(); | |
116 | } | |
117 | ||
118 | set_sctlr(get_sctlr() | CR_C); | |
119 | } | |
120 | ||
121 | void dcache_disable(void) | |
122 | { | |
123 | uint32_t sctlr; | |
124 | ||
125 | sctlr = get_sctlr(); | |
126 | ||
127 | /* if cache isn't enabled no need to disable */ | |
128 | if (!(sctlr & CR_C)) | |
129 | return; | |
130 | ||
131 | set_sctlr(sctlr & ~(CR_C|CR_M)); | |
132 | ||
133 | flush_dcache_all(); | |
134 | __asm_invalidate_tlb_all(); | |
135 | } | |
136 | ||
137 | int dcache_status(void) | |
138 | { | |
139 | return (get_sctlr() & CR_C) != 0; | |
140 | } | |
141 | ||
142 | #else /* CONFIG_SYS_DCACHE_OFF */ | |
143 | ||
144 | void invalidate_dcache_all(void) | |
145 | { | |
146 | } | |
147 | ||
148 | void flush_dcache_all(void) | |
149 | { | |
150 | } | |
151 | ||
152 | void invalidate_dcache_range(unsigned long start, unsigned long stop) | |
153 | { | |
154 | } | |
155 | ||
156 | void flush_dcache_range(unsigned long start, unsigned long stop) | |
157 | { | |
158 | } | |
159 | ||
160 | void dcache_enable(void) | |
161 | { | |
162 | } | |
163 | ||
164 | void dcache_disable(void) | |
165 | { | |
166 | } | |
167 | ||
168 | int dcache_status(void) | |
169 | { | |
170 | return 0; | |
171 | } | |
172 | ||
173 | #endif /* CONFIG_SYS_DCACHE_OFF */ | |
174 | ||
175 | #ifndef CONFIG_SYS_ICACHE_OFF | |
176 | ||
177 | void icache_enable(void) | |
178 | { | |
1e6ad55c | 179 | __asm_invalidate_icache_all(); |
0ae76531 DF |
180 | set_sctlr(get_sctlr() | CR_I); |
181 | } | |
182 | ||
183 | void icache_disable(void) | |
184 | { | |
185 | set_sctlr(get_sctlr() & ~CR_I); | |
186 | } | |
187 | ||
188 | int icache_status(void) | |
189 | { | |
190 | return (get_sctlr() & CR_I) != 0; | |
191 | } | |
192 | ||
193 | void invalidate_icache_all(void) | |
194 | { | |
195 | __asm_invalidate_icache_all(); | |
196 | } | |
197 | ||
198 | #else /* CONFIG_SYS_ICACHE_OFF */ | |
199 | ||
200 | void icache_enable(void) | |
201 | { | |
202 | } | |
203 | ||
204 | void icache_disable(void) | |
205 | { | |
206 | } | |
207 | ||
208 | int icache_status(void) | |
209 | { | |
210 | return 0; | |
211 | } | |
212 | ||
213 | void invalidate_icache_all(void) | |
214 | { | |
215 | } | |
216 | ||
217 | #endif /* CONFIG_SYS_ICACHE_OFF */ | |
218 | ||
219 | /* | |
220 | * Enable dCache & iCache, whether cache is actually enabled | |
221 | * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF | |
222 | */ | |
2f78eae5 | 223 | void __weak enable_caches(void) |
0ae76531 DF |
224 | { |
225 | icache_enable(); | |
226 | dcache_enable(); | |
227 | } | |
228 | ||
229 | /* | |
230 | * Flush range from all levels of d-cache/unified-cache | |
231 | */ | |
232 | void flush_cache(unsigned long start, unsigned long size) | |
233 | { | |
234 | flush_dcache_range(start, start + size); | |
235 | } |