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