1 /**
2   * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3   *
4   * SPDX-License-Identifier: Apache-2.0
5   ******************************************************************************
6   * @file    drv_cache.c
7   * @version V0.1
8   * @brief   cpu cache interface
9   *
10   * Change Logs:
11   * Date           Author          Notes
12   * 2019-04-01     Cliff.Chen      first implementation
13   *
14   ******************************************************************************
15   */
16 
17 /** @addtogroup RKBSP_Driver_Reference
18  *  @{
19  */
20 
21 /** @addtogroup Cache
22  *  @{
23  */
24 
25 /** @defgroup Cache_How_To_Use How To Use
26  *  @{
27 
28 The Cache driver use to keeping data coherent between cpu and device, it can be used in the following three scenarios:
29 
30 - **The cpu want to read the latest data that has been modified by device**:
31     - The device modify the data;
32     - The cpu invalidate the data by rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE,
33            addr, size);
34     - The cpu read the latest data;
35 
36 - **The device want to read the latest data that was modified by cpu**:
37     - The cpu modify the data;
38     - The device flush the data by rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, addr, size);
39     - The device read the latest data;
40 
41 - **The cpu want to execute two code section on the same memory**:
42     - Loading the code A in the memory from start address of ADDR;
43     - Executing the code A;
44     - Loading the code B in the memory from start address of ADDR;
45     - Invalidating by rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, ADDR, size);
46     - Executing the code B
47 
48  @} */
49 
50 #include <rthw.h>
51 #include "drv_cache.h"
52 #include "hal_base.h"
53 
54 #if defined(ARCH_ARM_CORTEX_M)
55 
56 #ifdef RT_USING_CMBACKTRACE
57 #include "cm_backtrace.h"
58 #endif
59 
60 /********************* Private MACRO Definition ******************************/
61 /** @defgroup CACHE_Private_Macro Private Macro
62  *  @{
63  */
64 
65 /** @} */  // CACHE_Private_Macro
66 
67 /********************* Private Structure Definition **************************/
68 /** @defgroup CACHE_Private_Structure Private Structure
69  *  @{
70  */
71 
72 /** @} */  // CACHE_Private_Structure
73 
74 /********************* Private Variable Definition ***************************/
75 /** @defgroup CACHE_Private_Variable Private Variable
76  *  @{
77  */
78 
79 /** @} */  // CACHE_Private_Variable
80 
81 /********************* Private Function Definition ***************************/
82 /** @defgroup CACHE_Private_Function Private Function
83  *  @{
84  */
85 
86 /** @} */  // CACHE_Private_Function
87 
88 /********************* Public Function Definition ****************************/
89 
90 /** @defgroup CACHE_Public_Functions Public Functions
91  *  @{
92  */
93 
94 /**
95  * @brief  Enable the icache of cpu.
96  * @attention The cache will be enabled when board initialization, do not dynamically switch cache
97  *      unless specifically required.
98  */
rt_hw_cpu_icache_enable(void)99 void rt_hw_cpu_icache_enable(void)
100 {
101     HAL_ICACHE_Enable();
102 }
103 
104 /**
105  * @brief  Disable the icache of cpu.
106  * @attention The cache will be enabled when board initialization, do not dynamically switch cache
107  *      unless specifically required.
108  */
rt_hw_cpu_icache_disable(void)109 void rt_hw_cpu_icache_disable(void)
110 {
111     HAL_ICACHE_Disable();
112 }
113 
114 /**
115  * @brief  Get icache status.
116  * @return 0
117  * @attention Not yet implemnted.
118  */
rt_hw_cpu_icache_status(void)119 rt_base_t rt_hw_cpu_icache_status(void)
120 {
121     return 0;
122 }
123 
124 /**
125  * @brief  Icache maintain operation.
126  * @param ops: RT_HW_CACHE_INVALIDATE for cache invalidate.
127  * @param addr: The start address of memory you want maintain.
128  * @param size: The length of memory you want maintain.
129  */
rt_hw_cpu_icache_ops(int ops,void * addr,int size)130 void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
131 {
132     if (ops & RT_HW_CACHE_INVALIDATE)
133     {
134         HAL_ICACHE_InvalidateByRange((uint32_t)addr, size);
135     }
136 }
137 
138 /**
139  * @brief  Enable the dcache of cpu.
140  * @attention The cache will be enabled when board initialization, do not dynamically switch cache
141  *      unless specifically required.
142  */
rt_hw_cpu_dcache_enable(void)143 void rt_hw_cpu_dcache_enable(void)
144 {
145     HAL_DCACHE_Enable();
146 }
147 
148 /**
149  * @brief  Disable the dcache of cpu.
150  * @attention The cache will be enabled when board initialization, do not dynamically switch cache
151  *      unless specifically required.
152  */
rt_hw_cpu_dcache_disable(void)153 void rt_hw_cpu_dcache_disable(void)
154 {
155     HAL_DCACHE_Disable();
156 }
157 
158 /**
159  * @brief  Get dcache status.
160  * @return 0
161  * @attention Not yet implemnted.
162  */
rt_hw_cpu_dcache_status(void)163 rt_base_t rt_hw_cpu_dcache_status(void)
164 {
165     return 0;
166 }
167 
168 /**
169  * @brief  Dcache maintain operation.
170  * @param ops: RT_HW_CACHE_INVALIDATE for cache invalidate,
171  *      RT_HW_CACHE_FLUSH for cache clean.
172  * @param addr: The start address of memory you want maintain.
173  * @param size: The length of memory you want maintain.
174  */
rt_hw_cpu_dcache_ops(int ops,void * addr,int size)175 void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
176 {
177     if ((ops & RT_HW_CACHE_FLUSH) && (ops & RT_HW_CACHE_INVALIDATE))
178     {
179         HAL_DCACHE_CleanInvalidateByRange((uint32_t)addr, size);
180     }
181     else if (ops & RT_HW_CACHE_FLUSH)
182     {
183         HAL_DCACHE_CleanByRange((uint32_t)addr, size);
184     }
185     else if (ops & RT_HW_CACHE_INVALIDATE)
186     {
187         HAL_DCACHE_InvalidateByRange((uint32_t)addr, size);
188     }
189     else
190     {
191         RT_ASSERT(0);
192     }
193 }
194 
195 /**
196  * @brief  Dump ahb error occur in icache & dcache, it called by cache interrupt.
197  * @param fault_handler_lr: The value of LR register.
198  * @param fault_handler_sp: The value of SP register.
199  */
cache_dump_ahb_error(uint32_t fault_handler_lr,uint32_t fault_handler_sp)200 void cache_dump_ahb_error(uint32_t fault_handler_lr, uint32_t fault_handler_sp)
201 {
202     uint32_t addr;
203 
204     if (HAL_ICACHE_GetInt())
205     {
206         addr = HAL_ICACHE_GetErrAddr();
207         rt_kprintf("a ahb bus error occur in icache, addr=%p\n", (void *)addr);
208         HAL_ICACHE_ClearInt();
209     }
210 
211     if (HAL_DCACHE_GetInt())
212     {
213         addr = HAL_DCACHE_GetErrAddr();
214         rt_kprintf("a ahb bus error occur in dcache, addr=%p\n", (void *)addr);
215         HAL_DCACHE_ClearInt();
216     }
217 
218 #ifdef RT_USING_CMBACKTRACE
219     cm_backtrace_fault(fault_handler_lr, fault_handler_sp);
220 #endif
221 }
222 
223 extern void CACHE_IRQHandler(void);
224 
225 /**
226  * @brief  Enable cache interrupt and register the handler, it called by board initialization.
227  * @return RT_EOK
228  */
rt_hw_cpu_cache_init(void)229 int rt_hw_cpu_cache_init(void)
230 {
231 #if defined(ICACHE) || defined(DCACHE)
232     HAL_ICACHE_EnableInt();
233     HAL_DCACHE_EnableInt();
234 #if defined(RKMCU_PISCES) || defined(RKMCU_RK2108)
235     rt_hw_interrupt_install(CACHE_IRQn, (rt_isr_handler_t)CACHE_IRQHandler, RT_NULL, RT_NULL);
236     rt_hw_interrupt_umask(CACHE_IRQn);
237 #elif defined(RKMCU_RK2206)
238     rt_hw_interrupt_install(CACHE0_I_IRQn, (rt_isr_handler_t)CACHE_IRQHandler, RT_NULL, RT_NULL);
239     rt_hw_interrupt_install(CACHE0_D_IRQn, (rt_isr_handler_t)CACHE_IRQHandler, RT_NULL, RT_NULL);
240     rt_hw_interrupt_umask(CACHE0_I_IRQn);
241     rt_hw_interrupt_umask(CACHE0_D_IRQn);
242 #endif
243 #endif
244     return RT_EOK;
245 }
246 
247 /** @} */  // CACHE_Public_Functions
248 
249 #else
250 
rt_hw_cpu_icache_enable(void)251 rt_weak void rt_hw_cpu_icache_enable(void)
252 {
253 }
254 
rt_hw_cpu_icache_disable(void)255 rt_weak void rt_hw_cpu_icache_disable(void)
256 {
257 }
258 
rt_hw_cpu_icache_status(void)259 rt_weak rt_base_t rt_hw_cpu_icache_status(void)
260 {
261     return 0;
262 }
263 
rt_hw_cpu_icache_ops(int ops,void * addr,int size)264 rt_weak void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
265 {
266 }
267 
rt_hw_cpu_dcache_enable(void)268 rt_weak void rt_hw_cpu_dcache_enable(void)
269 {
270 }
271 
rt_hw_cpu_dcache_disable(void)272 rt_weak void rt_hw_cpu_dcache_disable(void)
273 {
274 }
275 
rt_hw_cpu_dcache_status(void)276 rt_weak rt_base_t rt_hw_cpu_dcache_status(void)
277 {
278     return 0;
279 }
280 
rt_hw_cpu_dcache_ops(int ops,void * addr,int size)281 rt_weak void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
282 {
283 }
284 
285 #endif
286 
287 /** @} */  // Cache
288 
289 /** @} */  // RKBSP_Driver_Reference
290