Prepare v2023.10
[platform/kernel/u-boot.git] / arch / arm / lib / cache.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2002
4  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5  */
6
7 /* for now: just dummy functions to satisfy the linker */
8
9 #include <common.h>
10 #include <cpu_func.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <asm/cache.h>
14 #include <asm/global_data.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 /*
19  * Flush range from all levels of d-cache/unified-cache.
20  * Affects the range [start, start + size - 1].
21  */
22 __weak void flush_cache(unsigned long start, unsigned long size)
23 {
24         flush_dcache_range(start, start + size);
25 }
26
27 /*
28  * Default implementation:
29  * do a range flush for the entire range
30  */
31 __weak void flush_dcache_all(void)
32 {
33         flush_cache(0, ~0);
34 }
35
36 /*
37  * Default implementation of enable_caches()
38  * Real implementation should be in platform code
39  */
40 __weak void enable_caches(void)
41 {
42         puts("WARNING: Caches not enabled\n");
43 }
44
45 __weak void invalidate_dcache_range(unsigned long start, unsigned long stop)
46 {
47         /* An empty stub, real implementation should be in platform code */
48 }
49 __weak void flush_dcache_range(unsigned long start, unsigned long stop)
50 {
51         /* An empty stub, real implementation should be in platform code */
52 }
53
54 int check_cache_range(unsigned long start, unsigned long stop)
55 {
56         int ok = 1;
57
58         if (start & (CONFIG_SYS_CACHELINE_SIZE - 1))
59                 ok = 0;
60
61         if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1))
62                 ok = 0;
63
64         if (!ok) {
65                 warn_non_spl("CACHE: Misaligned operation at range [%08lx, %08lx]\n",
66                              start, stop);
67         }
68
69         return ok;
70 }
71
72 #ifdef CONFIG_SYS_NONCACHED_MEMORY
73 /*
74  * Reserve one MMU section worth of address space below the malloc() area that
75  * will be mapped uncached.
76  */
77 static unsigned long noncached_start;
78 static unsigned long noncached_end;
79 static unsigned long noncached_next;
80
81 void noncached_set_region(void)
82 {
83 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
84         mmu_set_region_dcache_behaviour(noncached_start,
85                                         noncached_end - noncached_start,
86                                         DCACHE_OFF);
87 #endif
88 }
89
90 int noncached_init(void)
91 {
92         phys_addr_t start, end;
93         size_t size;
94
95         /* If this calculation changes, update board_f.c:reserve_noncached() */
96         end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE;
97         size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
98         start = end - size;
99
100         debug("mapping memory %pa-%pa non-cached\n", &start, &end);
101
102         noncached_start = start;
103         noncached_end = end;
104         noncached_next = start;
105
106         noncached_set_region();
107
108         return 0;
109 }
110
111 phys_addr_t noncached_alloc(size_t size, size_t align)
112 {
113         phys_addr_t next = ALIGN(noncached_next, align);
114
115         if (next >= noncached_end || (noncached_end - next) < size)
116                 return 0;
117
118         debug("allocated %zu bytes of uncached memory @%pa\n", size, &next);
119         noncached_next = next + size;
120
121         return next;
122 }
123 #endif /* CONFIG_SYS_NONCACHED_MEMORY */
124
125 #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
126 void invalidate_l2_cache(void)
127 {
128         unsigned int val = 0;
129
130         asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache"
131                 : : "r" (val) : "cc");
132         isb();
133 }
134 #endif
135
136 int arch_reserve_mmu(void)
137 {
138         return arm_reserve_mmu();
139 }
140
141 __weak int arm_reserve_mmu(void)
142 {
143 #if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
144         /* reserve TLB table */
145         gd->arch.tlb_size = PGTABLE_SIZE;
146         gd->relocaddr -= gd->arch.tlb_size;
147
148         /* round down to next 64 kB limit */
149         gd->relocaddr &= ~(0x10000 - 1);
150
151         gd->arch.tlb_addr = gd->relocaddr;
152         debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
153               gd->arch.tlb_addr + gd->arch.tlb_size);
154
155 #ifdef CFG_SYS_MEM_RESERVE_SECURE
156         /*
157          * Record allocated tlb_addr in case gd->tlb_addr to be overwritten
158          * with location within secure ram.
159          */
160         gd->arch.tlb_allocated = gd->arch.tlb_addr;
161 #endif
162
163         if (IS_ENABLED(CONFIG_CMO_BY_VA_ONLY)) {
164                 /*
165                  * As invalidate_dcache_all() will be called before
166                  * mmu_setup(), we should make sure that the PTs are
167                  * already in a valid state.
168                  */
169                 memset((void *)gd->arch.tlb_addr, 0, gd->arch.tlb_size);
170         }
171 #endif
172
173         return 0;
174 }