1 /*
2  * Copyright (c) 2019 - 2020, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *    list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  *    contributors may be used to endorse or promote products derived from this
17  *    software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef NRF_CACHE_H__
33 #define NRF_CACHE_H__
34 
35 #include <nrfx.h>
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 /**
42  * @defgroup nrf_cache_hal CACHE HAL
43  * @{
44  * @ingroup nrf_cache
45  * @brief   The hardware access layer for managing the CACHE peripheral.
46  */
47 
48 /** @brief Cache regions. */
49 typedef enum
50 {
51     NRF_CACHE_REGION_FLASH = 0, ///< Cache region related to Flash access.
52     NRF_CACHE_REGION_XIP   = 1, ///< Cache region related to XIP access.
53 } nrf_cache_region_t;
54 
55 /**
56  * @brief Function for enabling the CACHE peripheral.
57  *
58  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
59  */
60 NRF_STATIC_INLINE void nrf_cache_enable(NRF_CACHE_Type * p_reg);
61 
62 /**
63  * @brief Function for disabling the CACHE peripheral.
64  *
65  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
66  */
67 NRF_STATIC_INLINE void nrf_cache_disable(NRF_CACHE_Type * p_reg);
68 
69 /**
70  * @brief Function for invalidating the cache content.
71  *
72  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
73  */
74 NRF_STATIC_INLINE void nrf_cache_invalidate(NRF_CACHE_Type * p_reg);
75 
76 /**
77  * @brief Function for erasing the cache content.
78  *
79  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
80  */
81 NRF_STATIC_INLINE void nrf_cache_erase(NRF_CACHE_Type * p_reg);
82 
83 /**
84  * @brief Function for checking the status of @ref nrf_cache_erase().
85  *
86  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
87  *
88  * @retval true  Erase is finished.
89  * @retval false Erase is not complete or has not started.
90  */
91 NRF_STATIC_INLINE bool nrf_cache_erase_status_check(NRF_CACHE_Type const * p_reg);
92 
93 /**
94  * @brief Function for clearing the status of the cache erase.
95  *
96  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
97  */
98 NRF_STATIC_INLINE void nrf_cache_erase_status_clear(NRF_CACHE_Type * p_reg);
99 
100 /**
101  * @brief Function for setting the cache profiling.
102  *
103  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
104  * @param[in] enable True if cache profiling is to be enabled, false otherwise.
105  */
106 NRF_STATIC_INLINE void nrf_cache_profiling_set(NRF_CACHE_Type * p_reg, bool enable);
107 
108 /**
109  * @brief Function for clearing the cache profiling counters.
110  *
111  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
112  */
113 NRF_STATIC_INLINE void nrf_cache_profiling_counters_clear(NRF_CACHE_Type * p_reg);
114 
115 /**
116  * @brief Function for getting the number of cache hits for instruction fetch from the specified
117  *        cache region.
118  *
119  * @note Separate counters are used for flash region and XIP region.
120  * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
121  *
122  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
123  * @param[in] region Cache region.
124  *
125  * @return Number of instruction fetch cache hits.
126  */
127 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_hit_counter_get(NRF_CACHE_Type const * p_reg,
128                                                                  nrf_cache_region_t     region);
129 
130 /**
131  * @brief Function for getting the number of cache misses for instruction fetch from the specified
132  *        cache region.
133  *
134  * @note Separate counters are used for flash region and XIP region.
135  * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
136  *
137  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
138  * @param[in] region Cache region.
139  *
140  * @return Number of instruction fetch cache misses.
141  */
142 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_miss_counter_get(NRF_CACHE_Type const * p_reg,
143                                                                   nrf_cache_region_t     region);
144 
145 /**
146  * @brief Function for getting the number of cache hits for data fetch from the specified
147  *        cache region.
148  *
149  * @note Separate counters are used for flash region and XIP region.
150  * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
151  *
152  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
153  * @param[in] region Cache region.
154  *
155  * @return Number of data fetch cache hits.
156  */
157 NRF_STATIC_INLINE uint32_t nrf_cache_data_hit_counter_get(NRF_CACHE_Type const * p_reg,
158                                                           nrf_cache_region_t     region);
159 
160 /**
161  * @brief Function for getting the number of cache misses for data fetch from the specified
162  *        cache region.
163  *
164  * @note Separate counters are used for flash region and XIP region.
165  * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
166  *
167  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
168  * @param[in] region Cache region.
169  *
170  * @return Number of data fetch cache misses.
171  */
172 NRF_STATIC_INLINE uint32_t nrf_cache_data_miss_counter_get(NRF_CACHE_Type const * p_reg,
173                                                            nrf_cache_region_t     region);
174 
175 /**
176  * @brief Function for setting the cache RAM mode.
177  *
178  * When configured in the RAM mode, the accesses to internal or external flash will not be cached.
179  * In this mode, the cache data contents can be used as the read/write RAM.
180  * Only the data content of the cache is available as RAM.
181  *
182  * @note -Enabling the RAM mode causes the RAM to be cleared.
183  * @note -Disabling the RAM mode causes the cache to be invalidated.
184  *
185  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
186  * @param[in] enable True if the cache RAM mode is to be enabled, false otherwise.
187  */
188 NRF_STATIC_INLINE void nrf_cache_ram_mode_set(NRF_CACHE_Type * p_reg, bool enable);
189 
190 /**
191  * @brief Function for blocking the cache content access.
192  *
193  * To unlock the cache content access, a reset has to be performed.
194  *
195  * @note Blocking is ignored in the RAM mode.
196  *
197  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
198  */
199 NRF_STATIC_INLINE void nrf_cache_read_lock_enable(NRF_CACHE_Type * p_reg);
200 
201 /**
202  * @brief Function for blocking the cache content updates.
203  *
204  * Blocking of updates prevents updating of cache content on cache misses,
205  * but the peripheral will continue to check for instruction/data fetches
206  * in the content already present in the cache.
207  *
208  * @note Blocking is ignored in the RAM mode.
209  *
210  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
211  * @param[in] enable True if cache content update lock is to be enabled, false otherwise.
212  */
213 NRF_STATIC_INLINE void nrf_cache_update_lock_set(NRF_CACHE_Type * p_reg, bool enable);
214 
215 /**
216  * @brief Function for getting the cache data word.
217  *
218  * @note When operating in the RAM mode, the cache data is accessible as a general purpose RAM.
219  *
220  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
221  * @param[in] set   Set that contains the data to get.
222  * @param[in] way   Way that contains the data to get.
223  * @param[in] word  Data word index to get.
224  *
225  * @return 32-bit data word.
226  */
227 NRF_STATIC_INLINE uint32_t nrf_cache_data_get(NRF_CACHEDATA_Type const * p_reg,
228                                               uint32_t                   set,
229                                               uint8_t                    way,
230                                               uint8_t                    word);
231 
232 /**
233  * @brief Function for getting the tag associated with the specified set and way.
234  *
235  * The tag is used to check if an entry in the cache matches the address that is being fetched.
236  *
237  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
238  * @param[in] set   Set that contains the tag to get.
239  * @param[in] way   Way that contains the tag to get.
240  *
241  * @return Tag value.
242  */
243 NRF_STATIC_INLINE uint32_t nrf_cache_tag_get(NRF_CACHEINFO_Type const * p_reg,
244                                              uint32_t                   set,
245                                              uint8_t                    way);
246 
247 /**
248  * @brief Function for checking the validity of a cache line associated with the specified set and way.
249  *
250  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
251  * @param[in] set   Set that contains the cache line to check.
252  * @param[in] way   Way that contains the cache line to check.
253  *
254  * @retval true  Cache line is valid.
255  * @retval false Cache line is invalid.
256  */
257 NRF_STATIC_INLINE bool nrf_cache_line_validity_check(NRF_CACHEINFO_Type const * p_reg,
258                                                      uint32_t                   set,
259                                                      uint8_t                    way);
260 
261 /**
262  * @brief Function for getting the most recently used way in the specified set.
263  *
264  * The most recently used way is updated on each fetch from the cache and is used for the cache replacement policy.
265  *
266  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
267  * @param[in] set   Specified set.
268  *
269  * @return The most recently used way in the specified set.
270  */
271 NRF_STATIC_INLINE uint8_t nrf_cache_mru_get(NRF_CACHEINFO_Type const * p_reg, uint32_t set);
272 
273 #ifndef NRF_DECLARE_ONLY
274 
nrf_cache_enable(NRF_CACHE_Type * p_reg)275 NRF_STATIC_INLINE void nrf_cache_enable(NRF_CACHE_Type * p_reg)
276 {
277     p_reg->ENABLE = CACHE_ENABLE_ENABLE_Enabled;
278 }
279 
nrf_cache_disable(NRF_CACHE_Type * p_reg)280 NRF_STATIC_INLINE void nrf_cache_disable(NRF_CACHE_Type * p_reg)
281 {
282     p_reg->ENABLE = CACHE_ENABLE_ENABLE_Disabled;
283 }
284 
nrf_cache_invalidate(NRF_CACHE_Type * p_reg)285 NRF_STATIC_INLINE void nrf_cache_invalidate(NRF_CACHE_Type * p_reg)
286 {
287     p_reg->INVALIDATE = CACHE_INVALIDATE_INVALIDATE_Invalidate;
288 }
289 
nrf_cache_erase(NRF_CACHE_Type * p_reg)290 NRF_STATIC_INLINE void nrf_cache_erase(NRF_CACHE_Type * p_reg)
291 {
292     p_reg->ERASE = CACHE_ERASE_ERASE_Erase;
293 }
294 
nrf_cache_erase_status_check(NRF_CACHE_Type const * p_reg)295 NRF_STATIC_INLINE bool nrf_cache_erase_status_check(NRF_CACHE_Type const * p_reg)
296 {
297     return (bool)(p_reg->ERASESTATUS & CACHE_ERASESTATUS_ERASESTATUS_Msk);
298 }
299 
nrf_cache_erase_status_clear(NRF_CACHE_Type * p_reg)300 NRF_STATIC_INLINE void nrf_cache_erase_status_clear(NRF_CACHE_Type * p_reg)
301 {
302     p_reg->ERASESTATUS = 0;
303 }
304 
nrf_cache_profiling_set(NRF_CACHE_Type * p_reg,bool enable)305 NRF_STATIC_INLINE void nrf_cache_profiling_set(NRF_CACHE_Type * p_reg, bool enable)
306 {
307     p_reg->PROFILINGENABLE =
308         (enable ? CACHE_PROFILINGENABLE_ENABLE_Enable : CACHE_PROFILINGENABLE_ENABLE_Disable);
309 }
310 
nrf_cache_profiling_counters_clear(NRF_CACHE_Type * p_reg)311 NRF_STATIC_INLINE void nrf_cache_profiling_counters_clear(NRF_CACHE_Type * p_reg)
312 {
313     p_reg->PROFILINGCLEAR = (CACHE_PROFILINGCLEAR_CLEAR_Clear << CACHE_PROFILINGCLEAR_CLEAR_Pos);
314 }
315 
nrf_cache_instruction_hit_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)316 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_hit_counter_get(NRF_CACHE_Type const * p_reg,
317                                                                  nrf_cache_region_t     region)
318 {
319     return p_reg->PROFILING[region].IHIT;
320 }
321 
nrf_cache_instruction_miss_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)322 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_miss_counter_get(NRF_CACHE_Type const * p_reg,
323                                                                   nrf_cache_region_t     region)
324 {
325     return p_reg->PROFILING[region].IMISS;
326 }
327 
nrf_cache_data_hit_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)328 NRF_STATIC_INLINE uint32_t nrf_cache_data_hit_counter_get(NRF_CACHE_Type const * p_reg,
329                                                           nrf_cache_region_t     region)
330 {
331     return p_reg->PROFILING[region].DHIT;
332 }
333 
nrf_cache_data_miss_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)334 NRF_STATIC_INLINE uint32_t nrf_cache_data_miss_counter_get(NRF_CACHE_Type const * p_reg,
335                                                            nrf_cache_region_t     region)
336 {
337     return p_reg->PROFILING[region].DMISS;
338 }
339 
nrf_cache_ram_mode_set(NRF_CACHE_Type * p_reg,bool enable)340 NRF_STATIC_INLINE void nrf_cache_ram_mode_set(NRF_CACHE_Type * p_reg, bool enable)
341 {
342     p_reg->MODE = (enable ? CACHE_MODE_MODE_Ram : CACHE_MODE_MODE_Cache);
343 }
344 
nrf_cache_read_lock_enable(NRF_CACHE_Type * p_reg)345 NRF_STATIC_INLINE void nrf_cache_read_lock_enable(NRF_CACHE_Type * p_reg)
346 {
347     p_reg->DEBUGLOCK = CACHE_DEBUGLOCK_DEBUGLOCK_Locked;
348 }
349 
nrf_cache_update_lock_set(NRF_CACHE_Type * p_reg,bool enable)350 NRF_STATIC_INLINE void nrf_cache_update_lock_set(NRF_CACHE_Type * p_reg, bool enable)
351 {
352     p_reg->WRITELOCK =
353         (enable ? CACHE_WRITELOCK_WRITELOCK_Locked : CACHE_WRITELOCK_WRITELOCK_Unlocked);
354 }
355 
nrf_cache_data_get(NRF_CACHEDATA_Type const * p_reg,uint32_t set,uint8_t way,uint8_t word)356 NRF_STATIC_INLINE uint32_t nrf_cache_data_get(NRF_CACHEDATA_Type const * p_reg,
357                                               uint32_t                   set,
358                                               uint8_t                    way,
359                                               uint8_t                    word)
360 {
361     volatile CACHEDATA_SET_WAY_Type const * reg = &p_reg->SET[set].WAY[way];
362     switch (word)
363     {
364         case 0: return reg->DATA0;
365         case 1: return reg->DATA1;
366         case 2: return reg->DATA2;
367         case 3: return reg->DATA3;
368         default:
369             NRFX_ASSERT(false);
370             return 0;
371     }
372 }
373 
nrf_cache_tag_get(NRF_CACHEINFO_Type const * p_reg,uint32_t set,uint8_t way)374 NRF_STATIC_INLINE uint32_t nrf_cache_tag_get(NRF_CACHEINFO_Type const * p_reg,
375                                              uint32_t                   set,
376                                              uint8_t                    way)
377 {
378     return (p_reg->SET[set].WAY[way] & CACHEINFO_SET_WAY_TAG_Msk);
379 }
380 
nrf_cache_line_validity_check(NRF_CACHEINFO_Type const * p_reg,uint32_t set,uint8_t way)381 NRF_STATIC_INLINE bool nrf_cache_line_validity_check(NRF_CACHEINFO_Type const * p_reg,
382                                                      uint32_t                   set,
383                                                      uint8_t                    way)
384 {
385     return (bool)(p_reg->SET[set].WAY[way] & CACHEINFO_SET_WAY_V_Msk);
386 }
387 
nrf_cache_mru_get(NRF_CACHEINFO_Type const * p_reg,uint32_t set)388 NRF_STATIC_INLINE uint8_t nrf_cache_mru_get(NRF_CACHEINFO_Type const * p_reg, uint32_t set)
389 {
390     return ((p_reg->SET[set].WAY[0] & CACHEINFO_SET_WAY_MRU_Msk) >> CACHEINFO_SET_WAY_MRU_Pos);
391 }
392 
393 #endif // NRF_DECLARE_ONLY
394 
395 /** @} */
396 
397 #ifdef __cplusplus
398 }
399 #endif
400 
401 #endif // NRF_CACHE_H__
402