-
Notifications
You must be signed in to change notification settings - Fork 7.1k
/
cache_ll.h
251 lines (221 loc) · 8.02 KB
/
cache_ll.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for Cache register operations
#pragma once
#include "soc/extmem_reg.h"
#include "soc/ext_mem_defs.h"
#include "hal/cache_types.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CACHE_LL_DEFAULT_IBUS_MASK CACHE_BUS_IBUS0
#define CACHE_LL_DEFAULT_DBUS_MASK CACHE_BUS_DBUS0
#define CACHE_LL_L1_ACCESS_EVENT_MASK (0x1f)
#define CACHE_LL_L1_ACCESS_EVENT_DBUS_REJECT (1<<4)
#define CACHE_LL_L1_ACCESS_EVENT_DBUS_ACS_MSK_DC_INT (1<<3)
#define CACHE_LL_L1_ACCESS_EVENT_IBUS_REJECT (1<<2)
#define CACHE_LL_L1_ACCESS_EVENT_IBUS_WR_IC (1<<1)
#define CACHE_LL_L1_ACCESS_EVENT_IBUS_ACS_MSK_IC (1<<0)
#define CACHE_LL_L1_ILG_EVENT_MASK (0x3f)
#define CACHE_LL_L1_ILG_EVENT_MMU_ENTRY_FAULT (1<<5)
#define CACHE_LL_L1_ILG_EVENT_DCACHE_WRITE_FLASH (1<<4)
#define CACHE_LL_L1_ILG_EVENT_DCACHE_PRELOAD_OP_FAULT (1<<3)
#define CACHE_LL_L1_ILG_EVENT_DCACHE_SYNC_OP_FAULT (1<<2)
#define CACHE_LL_L1_ILG_EVENT_ICACHE_PRELOAD_OP_FAULT (1<<1)
#define CACHE_LL_L1_ILG_EVENT_ICACHE_SYNC_OP_FAULT (1<<0)
/**
* @brief Get the buses of a particular cache that are mapped to a virtual address range
*
* External virtual address can only be accessed when the involved cache buses are enabled.
* This API is to get the cache buses where the memory region (from `vaddr_start` to `vaddr_start + len`) reside.
*
* @param cache_id cache ID (when l1 cache is per core)
* @param vaddr_start virtual address start
* @param len vaddr length
*/
#if !BOOTLOADER_BUILD
__attribute__((always_inline))
#endif
static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len)
{
HAL_ASSERT(cache_id == 0 || cache_id == 1);
cache_bus_mask_t mask = 0;
uint32_t vaddr_end = vaddr_start + len - 1;
if (vaddr_start >= IRAM0_CACHE_ADDRESS_LOW && vaddr_end < IRAM0_CACHE_ADDRESS_HIGH) {
mask |= CACHE_BUS_IBUS0; //Both cores have their own IBUS0
} else if (vaddr_start >= DRAM0_CACHE_ADDRESS_LOW && vaddr_end < DRAM0_CACHE_ADDRESS_HIGH) {
mask |= CACHE_BUS_DBUS0; //Both cores have their own DBUS0
} else {
HAL_ASSERT(0); //Out of region
}
return mask;
}
/**
* Enable the Cache Buses
*
* @param cache_id cache ID (when l1 cache is per core)
* @param mask To know which buses should be enabled
*/
#if !BOOTLOADER_BUILD
__attribute__((always_inline))
#endif
static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask)
{
HAL_ASSERT(cache_id == 0 || cache_id == 1);
//On esp32s3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first
HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0);
uint32_t ibus_mask = 0;
if (cache_id == 0) {
ibus_mask |= (mask & CACHE_BUS_IBUS0) ? EXTMEM_ICACHE_SHUT_CORE0_BUS : 0;
} else {
ibus_mask |= (mask & CACHE_BUS_IBUS0) ? EXTMEM_ICACHE_SHUT_CORE1_BUS : 0;
}
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, ibus_mask);
uint32_t dbus_mask = 0;
if (cache_id == 1) {
dbus_mask |= (mask & CACHE_BUS_DBUS0) ? EXTMEM_DCACHE_SHUT_CORE0_BUS : 0;
} else {
dbus_mask |= (mask & CACHE_BUS_DBUS0) ? EXTMEM_DCACHE_SHUT_CORE1_BUS : 0;
}
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, dbus_mask);
}
/**
* Returns enabled buses for a given core
*
* @param cache_id cache ID (when l1 cache is per core)
*
* @return State of enabled buses
*/
__attribute__((always_inline))
static inline cache_bus_mask_t cache_ll_l1_get_enabled_bus(uint32_t cache_id)
{
cache_bus_mask_t mask = 0;
HAL_ASSERT(cache_id == 0 || cache_id == 1);
//On esp32s3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first
uint32_t ibus_mask = REG_READ(EXTMEM_ICACHE_CTRL1_REG);
if (cache_id == 0) {
mask |= (!(ibus_mask & EXTMEM_ICACHE_SHUT_CORE0_BUS)) ? CACHE_BUS_IBUS0 : 0;
} else {
mask |= (!(ibus_mask & EXTMEM_ICACHE_SHUT_CORE1_BUS)) ? CACHE_BUS_IBUS0 : 0;
}
uint32_t dbus_mask = REG_READ(EXTMEM_DCACHE_CTRL1_REG);
if (cache_id == 1) {
mask |= (!(dbus_mask & EXTMEM_DCACHE_SHUT_CORE0_BUS)) ? CACHE_BUS_DBUS0 : 0;
} else {
mask |= (!(dbus_mask & EXTMEM_DCACHE_SHUT_CORE1_BUS)) ? CACHE_BUS_DBUS0 : 0;
}
return mask;
}
/**
* Disable the Cache Buses
*
* @param cache_id cache ID (when l1 cache is per core)
* @param mask To know which buses should be disabled
*/
__attribute__((always_inline))
static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask)
{
HAL_ASSERT(cache_id == 0 || cache_id == 1);
//On esp32s3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first
HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0);
uint32_t ibus_mask = 0;
if (cache_id == 0) {
ibus_mask |= (mask & CACHE_BUS_IBUS0) ? EXTMEM_ICACHE_SHUT_CORE0_BUS : 0;
} else {
ibus_mask |= (mask & CACHE_BUS_IBUS0) ? EXTMEM_ICACHE_SHUT_CORE1_BUS : 0;
}
REG_SET_BIT(EXTMEM_ICACHE_CTRL1_REG, ibus_mask);
uint32_t dbus_mask = 0;
if (cache_id == 1) {
dbus_mask |= (mask & CACHE_BUS_DBUS0) ? EXTMEM_DCACHE_SHUT_CORE0_BUS : 0;
} else {
dbus_mask |= (mask & CACHE_BUS_DBUS0) ? EXTMEM_DCACHE_SHUT_CORE1_BUS : 0;
}
REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, dbus_mask);
}
/*------------------------------------------------------------------------------
* Interrupt
*----------------------------------------------------------------------------*/
/**
* @brief Enable Cache access error interrupt
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l1_enable_access_error_intr(uint32_t cache_id, uint32_t mask)
{
if (cache_id == 0) {
SET_PERI_REG_MASK(EXTMEM_CORE0_ACS_CACHE_INT_ENA_REG, mask);
} else {
SET_PERI_REG_MASK(EXTMEM_CORE1_ACS_CACHE_INT_ENA_REG, mask);
}
}
/**
* @brief Clear Cache access error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l1_clear_access_error_intr(uint32_t cache_id, uint32_t mask)
{
if (cache_id == 0) {
SET_PERI_REG_MASK(EXTMEM_CORE0_ACS_CACHE_INT_CLR_REG, mask);
} else {
SET_PERI_REG_MASK(EXTMEM_CORE1_ACS_CACHE_INT_CLR_REG, mask);
}
}
/**
* @brief Get Cache access error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*
* @return Status mask
*/
static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_id, uint32_t mask)
{
if (cache_id == 0) {
return GET_PERI_REG_MASK(EXTMEM_CORE0_ACS_CACHE_INT_ST_REG, mask);
} else {
return GET_PERI_REG_MASK(EXTMEM_CORE1_ACS_CACHE_INT_ST_REG, mask);
}
}
/**
* @brief Enable Cache illegal error interrupt
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l1_enable_illegal_error_intr(uint32_t cache_id, uint32_t mask)
{
SET_PERI_REG_MASK(EXTMEM_CACHE_ILG_INT_ENA_REG, mask);
}
/**
* @brief Clear Cache illegal error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l1_clear_illegal_error_intr(uint32_t cache_id, uint32_t mask)
{
SET_PERI_REG_MASK(EXTMEM_CACHE_ILG_INT_CLR_REG, mask);
}
/**
* @brief Get Cache illegal error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*
* @return Status mask
*/
static inline uint32_t cache_ll_l1_get_illegal_error_intr_status(uint32_t cache_id, uint32_t mask)
{
return GET_PERI_REG_MASK(EXTMEM_CACHE_ILG_INT_ST_REG, mask);
}
#ifdef __cplusplus
}
#endif