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