1 /*
2  * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 // The LL layer for Cache register operations
8 
9 #pragma once
10 
11 #include <stdbool.h>
12 #include "soc/extmem_reg.h"
13 #include "soc/ext_mem_defs.h"
14 #include "hal/cache_types.h"
15 #include "hal/assert.h"
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 
22 #define CACHE_LL_DEFAULT_IBUS_MASK                  CACHE_BUS_IBUS0
23 #define CACHE_LL_DEFAULT_DBUS_MASK                  CACHE_BUS_DBUS0
24 
25 #define CACHE_LL_L1_ACCESS_EVENT_MASK               (0x3f)
26 #define CACHE_LL_L1_ACCESS_EVENT_DBUS_WR_IC         (1<<5)
27 #define CACHE_LL_L1_ACCESS_EVENT_DBUS_REJECT        (1<<4)
28 #define CACHE_LL_L1_ACCESS_EVENT_DBUS_ACS_MSK_IC    (1<<3)
29 #define CACHE_LL_L1_ACCESS_EVENT_IBUS_REJECT        (1<<2)
30 #define CACHE_LL_L1_ACCESS_EVENT_IBUS_WR_IC         (1<<1)
31 #define CACHE_LL_L1_ACCESS_EVENT_IBUS_ACS_MSK_IC    (1<<0)
32 
33 #define CACHE_LL_L1_ILG_EVENT_MASK                  (0x23)
34 #define CACHE_LL_L1_ILG_EVENT_MMU_ENTRY_FAULT       (1<<5)
35 #define CACHE_LL_L1_ILG_EVENT_PRELOAD_OP_FAULT      (1<<1)
36 #define CACHE_LL_L1_ILG_EVENT_SYNC_OP_FAULT         (1<<0)
37 
38 /**
39  * @brief Get the status of cache if it is enabled or not
40  *
41  * @param   cache_id    cache ID (when l1 cache is per core)
42  * @param   type        see `cache_type_t`
43  * @return  enabled or not
44  */
45 __attribute__((always_inline))
cache_ll_l1_is_cache_enabled(uint32_t cache_id,cache_type_t type)46 static inline bool cache_ll_l1_is_cache_enabled(uint32_t cache_id, cache_type_t type)
47 {
48     HAL_ASSERT(cache_id == 0);
49     (void) type; // On C2 there's only ICache
50     return REG_GET_BIT(EXTMEM_ICACHE_CTRL_REG, EXTMEM_ICACHE_ENABLE);
51 }
52 
53 /**
54  * @brief Get the buses of a particular cache that are mapped to a virtual address range
55  *
56  * External virtual address can only be accessed when the involved cache buses are enabled.
57  * This API is to get the cache buses where the memory region (from `vaddr_start` to `vaddr_start + len`) reside.
58  *
59  * @param cache_id          cache ID (when l1 cache is per core)
60  * @param vaddr_start       virtual address start
61  * @param len               vaddr length
62  */
63 #if !BOOTLOADER_BUILD
64 __attribute__((always_inline))
65 #endif
cache_ll_l1_get_bus(uint32_t cache_id,uint32_t vaddr_start,uint32_t len)66 static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len)
67 {
68     HAL_ASSERT(cache_id == 0);
69     cache_bus_mask_t mask = 0;
70 
71     uint32_t vaddr_end = vaddr_start + len - 1;
72     if (vaddr_start >= IRAM0_CACHE_ADDRESS_LOW && vaddr_end < IRAM0_CACHE_ADDRESS_HIGH) {
73         mask |= CACHE_BUS_IBUS0;
74     } else if (vaddr_start >= DRAM0_CACHE_ADDRESS_LOW && vaddr_end < DRAM0_CACHE_ADDRESS_HIGH) {
75         mask |= CACHE_BUS_DBUS0;
76     } else {
77         HAL_ASSERT(0);      //Out of region
78     }
79 
80     return mask;
81 }
82 
83 /**
84  * Enable the Cache Buses
85  *
86  * @param cache_id    cache ID (when l1 cache is per core)
87  * @param mask        To know which buses should be enabled
88  */
89 #if !BOOTLOADER_BUILD
90 __attribute__((always_inline))
91 #endif
cache_ll_l1_enable_bus(uint32_t cache_id,cache_bus_mask_t mask)92 static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask)
93 {
94     HAL_ASSERT(cache_id == 0);
95     //On esp32c2, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first
96     HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0);
97 
98     uint32_t ibus_mask = 0;
99     ibus_mask |= (mask & CACHE_BUS_IBUS0) ? EXTMEM_ICACHE_SHUT_IBUS : 0;
100     REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, ibus_mask);
101 
102     uint32_t dbus_mask = 0;
103     dbus_mask |= (mask & CACHE_BUS_DBUS0) ? EXTMEM_ICACHE_SHUT_DBUS : 0;
104     REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, dbus_mask);
105 }
106 
107 /**
108  * Disable the Cache Buses
109  *
110  * @param cache_id    cache ID (when l1 cache is per core)
111  * @param mask        To know which buses should be disabled
112  */
113 __attribute__((always_inline))
cache_ll_l1_disable_bus(uint32_t cache_id,cache_bus_mask_t mask)114 static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask)
115 {
116     HAL_ASSERT(cache_id == 0);
117     //On esp32c2, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first
118     HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0);
119 
120     uint32_t ibus_mask = 0;
121     ibus_mask |= (mask & CACHE_BUS_IBUS0) ? EXTMEM_ICACHE_SHUT_IBUS : 0;
122     REG_SET_BIT(EXTMEM_ICACHE_CTRL1_REG, ibus_mask);
123 
124     uint32_t dbus_mask = 0;
125     dbus_mask |= (mask & CACHE_BUS_DBUS0) ? EXTMEM_ICACHE_SHUT_DBUS : 0;
126     REG_SET_BIT(EXTMEM_ICACHE_CTRL1_REG, dbus_mask);
127 }
128 
129 /*------------------------------------------------------------------------------
130  * Interrupt
131  *----------------------------------------------------------------------------*/
132 /**
133  * @brief Enable Cache access error interrupt
134  *
135  * @param cache_id    Cache ID, not used on C2. For compabitlity
136  * @param mask        Interrupt mask
137  */
cache_ll_l1_enable_access_error_intr(uint32_t cache_id,uint32_t mask)138 static inline void cache_ll_l1_enable_access_error_intr(uint32_t cache_id, uint32_t mask)
139 {
140     SET_PERI_REG_MASK(EXTMEM_CORE0_ACS_CACHE_INT_ENA_REG, mask);
141 }
142 
143 /**
144  * @brief Clear Cache access error interrupt status
145  *
146  * @param cache_id    Cache ID, not used on C2. For compabitlity
147  * @param mask        Interrupt mask
148  */
cache_ll_l1_clear_access_error_intr(uint32_t cache_id,uint32_t mask)149 static inline void cache_ll_l1_clear_access_error_intr(uint32_t cache_id, uint32_t mask)
150 {
151     SET_PERI_REG_MASK(EXTMEM_CORE0_ACS_CACHE_INT_CLR_REG, mask);
152 }
153 
154 /**
155  * @brief Get Cache access error interrupt status
156  *
157  * @param cache_id    Cache ID, not used on C2. For compabitlity
158  * @param mask        Interrupt mask
159  *
160  * @return            Status mask
161  */
cache_ll_l1_get_access_error_intr_status(uint32_t cache_id,uint32_t mask)162 static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_id, uint32_t mask)
163 {
164     return GET_PERI_REG_MASK(EXTMEM_CORE0_ACS_CACHE_INT_ST_REG, mask);
165 }
166 
167 /**
168  * @brief Enable Cache illegal error interrupt
169  *
170  * @param cache_id    Cache ID, not used on C2. For compabitlity
171  * @param mask        Interrupt mask
172  */
cache_ll_l1_enable_illegal_error_intr(uint32_t cache_id,uint32_t mask)173 static inline void cache_ll_l1_enable_illegal_error_intr(uint32_t cache_id, uint32_t mask)
174 {
175     SET_PERI_REG_MASK(EXTMEM_CACHE_ILG_INT_ENA_REG, mask);
176 }
177 
178 /**
179  * @brief Clear Cache illegal error interrupt status
180  *
181  * @param cache_id    Cache ID, not used on C2. For compabitlity
182  * @param mask        Interrupt mask
183  */
cache_ll_l1_clear_illegal_error_intr(uint32_t cache_id,uint32_t mask)184 static inline void cache_ll_l1_clear_illegal_error_intr(uint32_t cache_id, uint32_t mask)
185 {
186     SET_PERI_REG_MASK(EXTMEM_CACHE_ILG_INT_CLR_REG, mask);
187 }
188 
189 /**
190  * @brief Get Cache illegal error interrupt status
191  *
192  * @param cache_id    Cache ID, not used on C2. For compabitlity
193  * @param mask        Interrupt mask
194  *
195  * @return            Status mask
196  */
cache_ll_l1_get_illegal_error_intr_status(uint32_t cache_id,uint32_t mask)197 static inline uint32_t cache_ll_l1_get_illegal_error_intr_status(uint32_t cache_id, uint32_t mask)
198 {
199     return GET_PERI_REG_MASK(EXTMEM_CACHE_ILG_INT_ST_REG, mask);
200 }
201 
202 #ifdef __cplusplus
203 }
204 #endif
205