1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2017 Intel Corporation. All rights reserved.
4 *
5 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6 */
7
8 #ifdef __SOF_LIB_CACHE_H__
9
10 #ifndef __ARCH_LIB_CACHE_H__
11 #define __ARCH_LIB_CACHE_H__
12
13 #include <xtensa/config/core-isa.h>
14
15 #define DCACHE_LINE_SIZE XCHAL_DCACHE_LINESIZE
16
17 #if !defined(__ASSEMBLER__) && !defined(LINKER)
18
19 #include <xtensa/hal.h>
20 #include <stddef.h>
21 #include <stdint.h>
22
23 #ifdef CONFIG_COMPILER_WORKAROUND_CACHE_ATTR
24 #include <sof/drivers/cache_attr.h>
25 #endif
26
27 #define SRAM_UNCACHED_ALIAS 0x20000000
28
29 #ifdef CONFIG_IMX
30
31 #ifdef CONFIG_COMPILER_WORKAROUND_CACHE_ATTR
32 /*
33 * We want to avoid buggy compiler optimization (function inlining).
34 * So we replace the call to glb_addr_attr() from glb_is_cached()
35 * with a function pointer that is initialized in
36 * src/arch/xtensa/driver/cache_attr.c
37 */
38 #define is_cached(address) glb_is_cached(address)
39
40 #else /* CONFIG_COMPILER_WORKAROUND_CACHE_ATTR */
41 /*
42 * The _memmap_cacheattr_reset linker script variable has
43 * dedicate cache attribute for every 512M in 4GB space
44 * 1: write through
45 * 2: cache bypass
46 * 4: write back
47 * F: invalid access
48 */
49 extern uint32_t _memmap_cacheattr_reset;
50
51 /*
52 * Since each hex digit keeps the attributes for a 512MB region,
53 * we have the following address ranges:
54 * Address range - hex digit
55 * 0 - 1FFFFFFF - 0
56 * 20000000 - 3FFFFFFF - 1
57 * 40000000 - 5FFFFFFF - 2
58 * 60000000 - 7FFFFFFF - 3
59 * 80000000 - 9FFFFFFF - 4
60 * A0000000 - BFFFFFFF - 5
61 * C0000000 - DFFFFFFF - 6
62 * E0000000 - FFFFFFFF - 7
63 */
64
65 /*
66 * Based on the above information, get the address region id (0-7)
67 */
68 #define _addr_range(address) (((uintptr_t)(address) >> 29) & 0x7)
69 /*
70 * Get the position of the cache attribute for a certain memory region.
71 * There are 4 bits per hex digit.
72 */
73 #define _addr_shift(address) ((_addr_range(address)) << 2)
74 /*
75 * For the given address, get the corresponding hex digit
76 * from the linker script variable that contains the cache attributes
77 */
78 #define _addr_attr(address) ((((uint32_t)(&_memmap_cacheattr_reset)) >> \
79 (_addr_shift(address))) & 0xF)
80 /*
81 * Check if the address is cacheable or not, by verifying the _addr_attr,
82 * which for cacheable addresses might be 1 or 4
83 */
84 #define is_cached(address) ((_addr_attr(address) == 1) || \
85 (_addr_attr(address) == 4))
86 #endif /* CONFIG_COMPILER_WORKAROUND_CACHE_ATTR */
87
88 #else /* CONFIG_IMX */
89 #define is_cached(address) (!!((uintptr_t)(address) & SRAM_UNCACHED_ALIAS))
90 #endif
91
dcache_writeback_region(void * addr,size_t size)92 static inline void dcache_writeback_region(void *addr, size_t size)
93 {
94 #if XCHAL_DCACHE_SIZE > 0
95 if (is_cached(addr))
96 xthal_dcache_region_writeback(addr, size);
97 #endif
98 }
99
dcache_writeback_all(void)100 static inline void dcache_writeback_all(void)
101 {
102 #if XCHAL_DCACHE_SIZE > 0
103 xthal_dcache_all_writeback();
104 #endif
105 }
106
dcache_invalidate_region(void * addr,size_t size)107 static inline void dcache_invalidate_region(void *addr, size_t size)
108 {
109 #if XCHAL_DCACHE_SIZE > 0
110 if (is_cached(addr))
111 xthal_dcache_region_invalidate(addr, size);
112 #endif
113 }
114
dcache_invalidate_all(void)115 static inline void dcache_invalidate_all(void)
116 {
117 #if XCHAL_DCACHE_SIZE > 0
118 xthal_dcache_all_invalidate();
119 #endif
120 }
121
icache_invalidate_region(void * addr,size_t size)122 static inline void icache_invalidate_region(void *addr, size_t size)
123 {
124 #if XCHAL_ICACHE_SIZE > 0
125 xthal_icache_region_invalidate(addr, size);
126 #endif
127 }
128
icache_invalidate_all(void)129 static inline void icache_invalidate_all(void)
130 {
131 #if XCHAL_ICACHE_SIZE > 0
132 xthal_icache_all_invalidate();
133 #endif
134 }
135
dcache_writeback_invalidate_region(void * addr,size_t size)136 static inline void dcache_writeback_invalidate_region(void *addr, size_t size)
137 {
138 #if XCHAL_DCACHE_SIZE > 0
139 if (is_cached(addr))
140 xthal_dcache_region_writeback_inv(addr, size);
141 #endif
142 }
143
dcache_writeback_invalidate_all(void)144 static inline void dcache_writeback_invalidate_all(void)
145 {
146 #if XCHAL_DCACHE_SIZE > 0
147 xthal_dcache_all_writeback_inv();
148 #endif
149 }
150
151 #endif /* !defined(__ASSEMBLER__) && !defined(LINKER) */
152
153 #endif /* __ARCH_LIB_CACHE_H__ */
154
155 #else
156
157 #error "This file shouldn't be included from outside of sof/lib/cache.h"
158
159 #endif /* __SOF_LIB_CACHE_H__ */
160