1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
4  */
5 
6 /** @addtogroup RK_HAL_Driver
7  *  @{
8  */
9 
10 /** @addtogroup CACHE
11  *  @{
12  */
13 #include "hal_base.h"
14 #include "hal_cache.h"
15 
16 /** @defgroup CACHE_Exported_Definition_Group1 Basic Definition
17  *  @{
18  */
19 
20 /***************************** MACRO Definition ******************************/
21 
22 /***************************** Structure Definition **************************/
23 
24 /********************* Private Function Definition ***************************/
25 
26 #if defined(__CORTEX_M)
HAL_SYS_EnterCriticalSection(void)27 __STATIC_INLINE unsigned long HAL_SYS_EnterCriticalSection(void)
28 {
29     unsigned long flags;
30 
31     flags = __get_PRIMASK();
32     __disable_irq();
33 
34     return flags;
35 }
36 
HAL_SYS_ExitCriticalSection(unsigned long flags)37 __STATIC_INLINE void HAL_SYS_ExitCriticalSection(unsigned long flags)
38 {
39     __set_PRIMASK(flags);
40 }
41 #else
HAL_SYS_EnterCriticalSection(void)42 __STATIC_INLINE unsigned long HAL_SYS_EnterCriticalSection(void)
43 {
44     return 0;
45 }
46 
HAL_SYS_ExitCriticalSection(unsigned long flags)47 __STATIC_INLINE void HAL_SYS_ExitCriticalSection(unsigned long flags)
48 {
49 }
50 #endif
51 
52 /** @} */
53 /********************* Public Function Definition ****************************/
54 /** @defgroup CACHE_Exported_Functions_Group5 Other Functions
55  *  @attention these APIs allow direct use in the HAL layer
56  *  @{
57  */
58 
59 /**
60  * @brief  translate the cpuAddr to sramAddr
61  * @param cpuAddr: the address mapping to sram, only can be accessed by cpu
62  * @return sramAddr: the real address of sram, it can be accessed by cpu & device
63  */
HAL_CpuAddrToDmaAddr(uint32_t cpuAddr)64 uint32_t HAL_CpuAddrToDmaAddr(uint32_t cpuAddr)
65 {
66     uint32_t sramAddr = cpuAddr;
67 
68 #ifdef SRAM_IADDR_TO_DADDR_OFFSET
69 
70     if (cpuAddr >= SRAM_IADDR_START
71         && cpuAddr < (SRAM_IADDR_START + SRAM_SIZE)) {
72         sramAddr = cpuAddr + SRAM_IADDR_TO_DADDR_OFFSET;
73     }
74 
75 #endif
76 
77 #ifdef XIP_NOR_IADDR_TO_DADDR_OFFSET
78 
79     if (cpuAddr >= XIP_NOR_IADDR_START
80         && cpuAddr < (XIP_NOR_IADDR_START + XIP_NOR_SIZE)) {
81         sramAddr = cpuAddr + XIP_NOR_IADDR_TO_DADDR_OFFSET;
82     }
83 
84 #endif
85 
86 #ifdef XIP_PSRAM_IADDR_TO_DADDR_OFFSET
87 
88     if (cpuAddr >= XIP_PSRAM_IADDR_START
89         && cpuAddr < (XIP_PSRAM_IADDR_START + XIP_PSRAM_SIZE)) {
90         sramAddr = cpuAddr + XIP_PSRAM_IADDR_TO_DADDR_OFFSET;
91     }
92 
93 #endif
94 
95     return sramAddr;
96 }
97 
98 #ifdef MPU
99 /**
100  * @brief  check mpu is enable.
101  * @return HAL_ENABLE if mpu enable.
102  */
HAL_MPU_IsEnable(void)103 __STATIC_INLINE HAL_FuncStatus HAL_MPU_IsEnable(void)
104 {
105     HAL_FuncStatus ret = HAL_DISABLE;
106 
107     if (MPU->CTRL & MPU_CTRL_ENABLE_Msk) {
108         ret = HAL_ENABLE;
109     }
110 
111     return ret;
112 }
113 #endif
114 
115 /**
116  * @brief  enable icache.
117  * @return HAL_OK if success.
118  * @attention The MPU must be configured before cache if you need the function.
119  */
HAL_ICACHE_Enable(void)120 HAL_Status HAL_ICACHE_Enable(void)
121 {
122 #if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
123 
124 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
125     uint32_t status;
126     unsigned long flags;
127 
128     flags = HAL_SYS_EnterCriticalSection();
129 
130     /* config icache: mpu disable, stb disable, write through, hot buffer enable,
131        prefetch enable */
132     ICACHE->CACHE_CTRL |=
133         (ICACHE_CACHE_CTRL_CACHE_EN_MASK | ICACHE_CACHE_CTRL_CACHE_WT_EN_MASK);
134     ICACHE->CACHE_CTRL &= (~ICACHE_CACHE_CTRL_CACHE_STB_EN_MASK);
135 
136     /* if mpu has been enable, we will enable cache mpu function */
137 #ifdef MPU
138     if (HAL_MPU_IsEnable()) {
139         ICACHE->CACHE_CTRL |= ICACHE_CACHE_CTRL_CACHE_MPU_MODE_MASK;
140     }
141 #endif
142 
143     do {
144         status =
145             ICACHE->CACHE_STATUS & ICACHE_CACHE_STATUS_CACHE_INIT_FINISH_MASK;
146     } while (status == 0);
147 
148     ICACHE->CACHE_CTRL &= ~ICACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
149 
150     HAL_SYS_ExitCriticalSection(flags);
151 #endif
152 
153 #endif
154 
155     return HAL_OK;
156 }
157 
158 /**
159  * @brief  disable icache.
160  * @return HAL_OK if success.
161  */
HAL_ICACHE_Disable(void)162 HAL_Status HAL_ICACHE_Disable(void)
163 {
164 #if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
165 
166 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
167     unsigned long flags;
168 
169     flags = HAL_SYS_EnterCriticalSection();
170 
171     ICACHE->CACHE_CTRL |= ICACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
172 
173     HAL_SYS_ExitCriticalSection(flags);
174 #endif
175 
176 #endif
177 
178     return HAL_OK;
179 }
180 
181 /**
182  * @brief  invalidate all of the icache.
183  * @return HAL_OK if success.
184  */
HAL_ICACHE_Invalidate(void)185 HAL_Status HAL_ICACHE_Invalidate(void)
186 {
187 #if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
188 
189 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
190     uint32_t status = 0;
191     unsigned long flags;
192 
193     if ((uint32_t)DCACHE == (uint32_t)ICACHE) {
194         if (DCACHE->CACHE_CTRL & DCACHE_CACHE_CTRL_CACHE_WT_EN_MASK) {
195             return HAL_OK;
196         } else {
197             return HAL_INVAL;
198         }
199     }
200 
201     flags = HAL_SYS_EnterCriticalSection();
202 
203     ICACHE->CACHE_MAINTAIN[0] =
204         CACHE_M_INVALID_ALL | ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
205 
206     do {
207         status = ICACHE->CACHE_MAINTAIN[0] &
208                  ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
209     } while (status);
210 
211     HAL_SYS_ExitCriticalSection(flags);
212 #endif
213 
214 #endif
215 
216     return HAL_OK;
217 }
218 
219 /**
220  * @brief  invalidate the specified region of the icache.
221  * @param  address: the start address of specified region which you want invalidate.
222  * @param  sizeByte: the length in bytes of invalidate range.
223  * @return HAL_OK if success.
224  */
HAL_ICACHE_InvalidateByRange(uint32_t address,uint32_t sizeByte)225 HAL_Status HAL_ICACHE_InvalidateByRange(uint32_t address,
226                                         uint32_t sizeByte)
227 {
228 #if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
229 
230 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
231     uint32_t value = 0;
232     uint32_t offset = 0;
233     uint32_t status = 0;
234     unsigned long flags;
235 
236     if (sizeByte == 0) {
237         return HAL_OK;
238     }
239 
240     address = HAL_CpuAddrToDmaAddr(address);
241 
242     offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
243     value = (address & ICACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
244             CACHE_M_INVALID | ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
245 
246     flags = HAL_SYS_EnterCriticalSection();
247 
248     ICACHE->CACHE_MAINTAIN[1] = offset;
249     ICACHE->CACHE_MAINTAIN[0] = value;
250 
251     do {
252         status = ICACHE->CACHE_MAINTAIN[0] &
253                  ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
254     } while (status);
255 
256     HAL_SYS_ExitCriticalSection(flags);
257 #endif
258 
259 #endif
260 
261     return HAL_OK;
262 }
263 
264 /**
265  * @brief  enable performance measurement unit of icache.
266  * @return HAL_OK if success.
267  */
HAL_ICACHE_EnablePMU(void)268 HAL_Status HAL_ICACHE_EnablePMU(void)
269 {
270 #if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
271 
272 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
273     unsigned long flags;
274 
275     flags = HAL_SYS_EnterCriticalSection();
276 
277     ICACHE->CACHE_CTRL |= ICACHE_CACHE_CTRL_CACHE_PMU_EN_MASK;
278 
279     HAL_SYS_ExitCriticalSection(flags);
280 #endif
281 
282 #endif
283 
284     return HAL_OK;
285 }
286 
287 /**
288  * @brief  disable performance measurement unit of icache.
289  * @return HAL_OK if success.
290  */
HAL_ICACHE_DisablePMU(void)291 HAL_Status HAL_ICACHE_DisablePMU(void)
292 {
293 #if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
294 
295 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
296     unsigned long flags;
297 
298     flags = HAL_SYS_EnterCriticalSection();
299 
300     ICACHE->CACHE_CTRL &= (~ICACHE_CACHE_CTRL_CACHE_PMU_EN_MASK);
301 
302     HAL_SYS_ExitCriticalSection(flags);
303 #endif
304 
305 #endif
306 
307     return HAL_OK;
308 }
309 
310 /**
311  * @brief  get current state of performance measurement unit in icache.
312  * @param  stat: return the current state if success.
313  * @return HAL_OK if success.
314  */
HAL_ICACHE_GetPMU(struct CACHE_PMU_CNT * stat)315 HAL_Status HAL_ICACHE_GetPMU(struct CACHE_PMU_CNT *stat)
316 {
317 #if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
318 
319 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
320     unsigned long flags;
321 
322     HAL_ASSERT(stat != NULL);
323 
324     flags = HAL_SYS_EnterCriticalSection();
325 
326     stat->rdNum = ICACHE->PMU_RD_NUM_CNT;
327     stat->wrNum = ICACHE->PMU_WR_NUM_CNT;
328     stat->sramRdHit = ICACHE->PMU_SRAM_RD_HIT_CNT;
329     stat->hbRdHit = ICACHE->PMU_HB_RD_HIT_CNT;
330     stat->stbRdHit = ICACHE->PMU_STB_RD_HIT_CNT;
331     stat->rdHit = ICACHE->PMU_RD_HIT_CNT;
332     stat->wrHit = ICACHE->PMU_WR_HIT_CNT;
333     stat->rdMissPenalty = ICACHE->PMU_RD_MISS_PENALTY_CNT;
334     stat->wrMissPenalty = ICACHE->PMU_WR_MISS_PENALTY_CNT;
335     stat->rdLat = ICACHE->PMU_RD_LAT_CNT;
336     stat->wrLat = ICACHE->PMU_WR_LAT_CNT;
337 
338     HAL_SYS_ExitCriticalSection(flags);
339 #endif
340 
341 #endif
342 
343     return HAL_OK;
344 }
345 
346 /**
347  * @brief  Enable the interrupt of icache.
348  * @return HAL_OK if success.
349  */
HAL_ICACHE_EnableInt(void)350 HAL_Status HAL_ICACHE_EnableInt(void)
351 {
352 #if defined(ICACHE)
353 
354 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
355     unsigned long flags;
356 
357     flags = HAL_SYS_EnterCriticalSection();
358 
359     ICACHE->CACHE_INT_EN |= ICACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
360 
361     HAL_SYS_ExitCriticalSection(flags);
362 #endif
363 
364 #endif
365 
366     return HAL_OK;
367 }
368 
369 /**
370  * @brief  Disable the interrupt of icache.
371  * @return HAL_OK if success.
372  */
HAL_ICACHE_DisableInt(void)373 HAL_Status HAL_ICACHE_DisableInt(void)
374 {
375 #if defined(ICACHE)
376 
377 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
378     unsigned long flags;
379 
380     flags = HAL_SYS_EnterCriticalSection();
381 
382     ICACHE->CACHE_INT_EN &= ~ICACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
383 
384     HAL_SYS_ExitCriticalSection(flags);
385 #endif
386 
387 #endif
388 
389     return HAL_OK;
390 }
391 
392 /**
393  * @brief  Get the interrupt status of icache.
394  * @return HAL_TRUE if ahb error occur.
395  */
HAL_ICACHE_GetInt(void)396 HAL_Check HAL_ICACHE_GetInt(void)
397 {
398     uint32_t status = 0;
399 
400 #if defined(ICACHE)
401 
402 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
403 
404     status = ICACHE->CACHE_INT_ST & ICACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
405 
406 #endif
407 
408 #endif
409 
410     return status ? HAL_TRUE : HAL_FALSE;
411 }
412 
413 /**
414  * @brief  Get the ahb bus error address of icache.
415  * @return ahb buss error address if success.
416  * @attention The return value is only valid if you get a ahb error from CACHE_INT_ST
417  */
HAL_ICACHE_GetErrAddr(void)418 uint32_t HAL_ICACHE_GetErrAddr(void)
419 {
420     uint32_t address = -1;
421 
422 #if defined(ICACHE)
423 
424 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
425 
426     address = ICACHE->CACHE_ERR_HADDR;
427 
428 #endif
429 
430 #endif
431 
432     return address;
433 }
434 
435 /**
436  * @brief  Clear the interrupt status of icache.
437  * @return HAL_OK if success.
438  */
HAL_ICACHE_ClearInt(void)439 HAL_Status HAL_ICACHE_ClearInt(void)
440 {
441 #if defined(ICACHE)
442 
443 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
444     unsigned long flags;
445 
446     flags = HAL_SYS_EnterCriticalSection();
447 
448     ICACHE->CACHE_INT_ST |= ICACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
449 
450     HAL_SYS_ExitCriticalSection(flags);
451 #endif
452 
453 #endif
454 
455     return HAL_OK;
456 }
457 
458 /**
459  * @brief     enable dcache.
460  * @return    HAL_OK if success.
461  * @attention The MPU must be configured before cache if you need the feature.
462  * @attention Dynamically disable and enable dcache is not allowed.
463  */
HAL_DCACHE_Enable(void)464 HAL_Status HAL_DCACHE_Enable(void)
465 {
466 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
467 
468 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
469     uint32_t status;
470     unsigned long flags;
471 
472     flags = HAL_SYS_EnterCriticalSection();
473 
474     /* stb enable, stb_entry=7, stb_timeout enable, write back, prefetch enable */
475     DCACHE->CACHE_CTRL |=
476         DCACHE_CACHE_CTRL_CACHE_EN_MASK
477         | (7U << DCACHE_CACHE_CTRL_CACHE_ENTRY_THRESH_SHIFT)
478         | DCACHE_CACHE_CTRL_STB_TIMEOUT_EN_MASK;
479     DCACHE->STB_TIMEOUT_CTRL = 1;
480 
481     /* if mpu has been enable, we will enable cache mpu function */
482 #ifdef MPU
483     if (HAL_MPU_IsEnable()) {
484         DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_MPU_MODE_MASK;
485     }
486 #endif
487 
488     do {
489         status =
490             DCACHE->CACHE_STATUS & DCACHE_CACHE_STATUS_CACHE_INIT_FINISH_MASK;
491     } while (status == 0);
492 
493     DCACHE->CACHE_CTRL &= ~DCACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
494 
495     HAL_SYS_ExitCriticalSection(flags);
496 #endif
497 
498 #endif
499 
500     return HAL_OK;
501 }
502 
503 /**
504  * @brief  disable dcache.
505  * @return HAL_OK if success.
506  */
HAL_DCACHE_Disable(void)507 HAL_Status HAL_DCACHE_Disable(void)
508 {
509 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
510 
511 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
512     unsigned long flags;
513 
514     flags = HAL_SYS_EnterCriticalSection();
515 
516     DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
517 
518     HAL_SYS_ExitCriticalSection(flags);
519 #endif
520 
521 #endif
522 
523     return HAL_OK;
524 }
525 
526 /**
527  * @brief  invalidate all of the dcache.
528  * @return HAL_OK if success.
529  */
HAL_DCACHE_Invalidate(void)530 HAL_Status HAL_DCACHE_Invalidate(void)
531 {
532 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
533 
534 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
535     uint32_t status = 0;
536     unsigned long flags;
537 
538     if ((uint32_t)DCACHE == (uint32_t)ICACHE) {
539         if (DCACHE->CACHE_CTRL & DCACHE_CACHE_CTRL_CACHE_WT_EN_MASK) {
540             return HAL_OK;
541         } else {
542             return HAL_INVAL;
543         }
544     }
545 
546     flags = HAL_SYS_EnterCriticalSection();
547 
548     DCACHE->CACHE_MAINTAIN[0] =
549         CACHE_M_INVALID_ALL | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
550 
551     do {
552         status = DCACHE->CACHE_MAINTAIN[0] &
553                  DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
554     } while (status);
555 
556     HAL_SYS_ExitCriticalSection(flags);
557 #endif
558 
559 #endif
560 
561     return HAL_OK;
562 }
563 
564 /**
565  * @brief  invalidate the specified region of the dcache.
566  * @param  address: the start address of specified region which you want invalidate.
567  * @param  sizeByte: the length in bytes of invalidate range.
568  * @return HAL_OK if success.
569  */
HAL_DCACHE_InvalidateByRange(uint32_t address,uint32_t sizeByte)570 HAL_Status HAL_DCACHE_InvalidateByRange(uint32_t address,
571                                         uint32_t sizeByte)
572 {
573 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
574 
575 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
576     uint32_t value = 0;
577     uint32_t offset = 0;
578     uint32_t status = 0;
579     unsigned long flags;
580 
581     if (sizeByte == 0) {
582         return HAL_OK;
583     }
584 
585     offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
586     value = (address & DCACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
587             CACHE_M_INVALID | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
588 
589     flags = HAL_SYS_EnterCriticalSection();
590 
591     DCACHE->CACHE_MAINTAIN[1] = offset;
592     DCACHE->CACHE_MAINTAIN[0] = value;
593 
594     do {
595         status = DCACHE->CACHE_MAINTAIN[0] &
596                  DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
597     } while (status);
598 
599     HAL_SYS_ExitCriticalSection(flags);
600 #endif
601 
602 #endif
603 
604     return HAL_OK;
605 }
606 
607 /**
608  * @brief  clean the specified region of the dcache, it will flush the dirty cache in
609  *         the specified region.
610  * @param  address: the start address of specified region which you want invalidate.
611  * @param  sizeByte: the length in bytes of invalidate range.
612  * @return HAL_OK if success.
613  */
HAL_DCACHE_CleanByRange(uint32_t address,uint32_t sizeByte)614 HAL_Status HAL_DCACHE_CleanByRange(uint32_t address,
615                                    uint32_t sizeByte)
616 {
617 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
618 
619 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
620     uint32_t value = 0;
621     uint32_t offset = 0;
622     uint32_t status = 0;
623     unsigned long flags;
624 
625     if (sizeByte == 0) {
626         return HAL_OK;
627     }
628 
629     offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
630     value = (address & DCACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
631             CACHE_M_CLEAN | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
632 
633     flags = HAL_SYS_EnterCriticalSection();
634 
635     DCACHE->CACHE_MAINTAIN[1] = offset;
636     DCACHE->CACHE_MAINTAIN[0] = value;
637 
638     do {
639         status = DCACHE->CACHE_MAINTAIN[0] &
640                  DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
641     } while (status);
642 
643     HAL_SYS_ExitCriticalSection(flags);
644 #endif
645 
646 #endif
647 
648     return HAL_OK;
649 }
650 
651 /**
652  * @brief  clean and invalidate the specified region of the dcache, it will flush the dirty
653  *         cache in the specified region, and set the cache line to invalid state.
654  * @param  address: the start address of specified region which you want invalidate.
655  * @param  sizeByte: the length in bytes of invalidate range.
656  * @return HAL_OK if success.
657  */
658 HAL_Status
HAL_DCACHE_CleanInvalidateByRange(uint32_t address,uint32_t sizeByte)659 HAL_DCACHE_CleanInvalidateByRange(uint32_t address, uint32_t sizeByte)
660 {
661 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
662 
663 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
664     uint32_t value = 0;
665     uint32_t offset = 0;
666     uint32_t status = 0;
667     unsigned long flags;
668 
669     if (sizeByte == 0) {
670         return HAL_OK;
671     }
672 
673     offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
674     value = (address & DCACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
675             CACHE_M_CLEAN_INVALID | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
676 
677     flags = HAL_SYS_EnterCriticalSection();
678 
679     DCACHE->CACHE_MAINTAIN[1] = offset;
680     DCACHE->CACHE_MAINTAIN[0] = value;
681 
682     do {
683         status = DCACHE->CACHE_MAINTAIN[0] &
684                  DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
685     } while (status);
686 
687     HAL_SYS_ExitCriticalSection(flags);
688 #endif
689 
690 #endif
691 
692     return HAL_OK;
693 }
694 
695 /**
696  * @brief  clean and invalidate all of the dcache, the dirty cache line will be flush
697  *         to external memory, and all of the cache line will be set invalid.
698  * @return HAL_OK if success.
699  */
HAL_DCACHE_CleanInvalidate(void)700 HAL_Status HAL_DCACHE_CleanInvalidate(void)
701 {
702 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
703 
704 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
705     uint32_t status = 0;
706     unsigned long flags;
707 
708     flags = HAL_SYS_EnterCriticalSection();
709 
710     DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_FLUSH_MASK;
711 
712     do {
713         status =
714             DCACHE->CACHE_STATUS & DCACHE_CACHE_STATUS_CACHE_FLUSH_DONE_MASK;
715     } while (!status);
716 
717     DCACHE->CACHE_CTRL &= ~DCACHE_CACHE_CTRL_CACHE_FLUSH_MASK;
718 
719     HAL_SYS_ExitCriticalSection(flags);
720 #endif
721 
722 #endif
723 
724     return HAL_OK;
725 }
726 
727 /**
728  * @brief  enable performance measurement unit of dcache.
729  * @return HAL_OK if success.
730  */
HAL_DCACHE_EnablePMU(void)731 HAL_Status HAL_DCACHE_EnablePMU(void)
732 {
733 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
734 
735 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
736     unsigned long flags;
737 
738     flags = HAL_SYS_EnterCriticalSection();
739 
740     DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_PMU_EN_MASK;
741 
742     HAL_SYS_ExitCriticalSection(flags);
743 #endif
744 
745 #endif
746 
747     return HAL_OK;
748 }
749 
750 /**
751  * @brief  disable performance measurement unit of dcache.
752  * @return HAL_OK if success.
753  */
HAL_DCACHE_DisablePMU(void)754 HAL_Status HAL_DCACHE_DisablePMU(void)
755 {
756 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
757 
758 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
759     unsigned long flags;
760 
761     flags = HAL_SYS_EnterCriticalSection();
762 
763     DCACHE->CACHE_CTRL &= (~DCACHE_CACHE_CTRL_CACHE_PMU_EN_MASK);
764 
765     HAL_SYS_ExitCriticalSection(flags);
766 #endif
767 
768 #endif
769 
770     return HAL_OK;
771 }
772 
773 /**
774  * @brief  get current state of performance measurement unit in icache.
775  * @param  stat: return the current state if success.
776  * @return HAL_OK if success.
777  */
HAL_DCACHE_GetPMU(struct CACHE_PMU_CNT * stat)778 HAL_Status HAL_DCACHE_GetPMU(struct CACHE_PMU_CNT *stat)
779 {
780 #if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
781 
782 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
783     unsigned long flags;
784 
785     HAL_ASSERT(stat != NULL);
786 
787     flags = HAL_SYS_EnterCriticalSection();
788 
789     stat->rdNum = DCACHE->PMU_RD_NUM_CNT;
790     stat->wrNum = DCACHE->PMU_WR_NUM_CNT;
791     stat->sramRdHit = DCACHE->PMU_SRAM_RD_HIT_CNT;
792     stat->hbRdHit = DCACHE->PMU_HB_RD_HIT_CNT;
793     stat->stbRdHit = DCACHE->PMU_STB_RD_HIT_CNT;
794     stat->rdHit = DCACHE->PMU_RD_HIT_CNT;
795     stat->wrHit = DCACHE->PMU_WR_HIT_CNT;
796     stat->rdMissPenalty = DCACHE->PMU_RD_MISS_PENALTY_CNT;
797     stat->wrMissPenalty = DCACHE->PMU_WR_MISS_PENALTY_CNT;
798     stat->rdLat = DCACHE->PMU_RD_LAT_CNT;
799     stat->wrLat = DCACHE->PMU_WR_LAT_CNT;
800 
801     HAL_SYS_ExitCriticalSection(flags);
802 #endif
803 
804 #endif
805 
806     return HAL_OK;
807 }
808 
809 /**
810  * @brief  Enable the interrupt of dcache.
811  * @return HAL_OK if success.
812  */
HAL_DCACHE_EnableInt(void)813 HAL_Status HAL_DCACHE_EnableInt(void)
814 {
815 #if defined(DCACHE)
816 
817 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
818     unsigned long flags;
819 
820     flags = HAL_SYS_EnterCriticalSection();
821 
822     DCACHE->CACHE_INT_EN |= DCACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
823 
824     HAL_SYS_ExitCriticalSection(flags);
825 #endif
826 
827 #endif
828 
829     return HAL_OK;
830 }
831 
832 /**
833  * @brief  Disable the interrupt of dcache.
834  * @return HAL_OK if success.
835  */
HAL_DCACHE_DisableInt(void)836 HAL_Status HAL_DCACHE_DisableInt(void)
837 {
838 #if defined(DCACHE)
839 
840 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
841     unsigned long flags;
842 
843     flags = HAL_SYS_EnterCriticalSection();
844 
845     DCACHE->CACHE_INT_EN &= ~DCACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
846 
847     HAL_SYS_ExitCriticalSection(flags);
848 #endif
849 
850 #endif
851 
852     return HAL_OK;
853 }
854 
855 /**
856  * @brief  Get the interrupt status of dcache.
857  * @return HAL_TRUE if ahb error occur.
858  */
HAL_DCACHE_GetInt(void)859 HAL_Check HAL_DCACHE_GetInt(void)
860 {
861     uint32_t status = 0;
862 
863 #if defined(DCACHE)
864 
865 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
866 
867     status = DCACHE->CACHE_INT_ST & DCACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
868 
869 #endif
870 
871 #endif
872 
873     return status ? HAL_TRUE : HAL_FALSE;
874 }
875 
876 /**
877  * @brief  Clear the interrupt status of dcache.
878  * @return HAL_OK if success.
879  */
HAL_DCACHE_ClearInt(void)880 HAL_Status HAL_DCACHE_ClearInt(void)
881 {
882 #if defined(DCACHE)
883 
884 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
885     unsigned long flags;
886 
887     flags = HAL_SYS_EnterCriticalSection();
888 
889     DCACHE->CACHE_INT_ST |= DCACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
890 
891     HAL_SYS_ExitCriticalSection(flags);
892 #endif
893 
894 #endif
895 
896     return HAL_OK;
897 }
898 
899 /**
900  * @brief  Get the ahb bus error address of dcache.
901  * @return ahb buss error address if success.
902  * @attention The return value is only valid if you get a ahb error from CACHE_INT_ST
903  */
HAL_DCACHE_GetErrAddr(void)904 uint32_t HAL_DCACHE_GetErrAddr(void)
905 {
906     uint32_t address = -1;
907 
908 #if defined(DCACHE)
909 
910 #if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
911 
912     address = DCACHE->CACHE_ERR_HADDR;
913 
914 #endif
915 
916 #endif
917 
918     return address;
919 }
920 
921 /** @} */
922 
923 /** @} */
924 
925 /** @} */
926