Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / arch / arm / cpu / armv8 / cache_v8.c
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 }