blob: bddf0e1f0c13f4eec10dec6e03e1150f343eb155 [file] [log] [blame]
Kévin Redon69b92d92019-01-24 16:39:20 +01001/**
2 * \file
3 *
4 * \brief Generic CMCC(Cortex M Cache Controller) related functionality.
5 *
6 * Copyright (c)2018 Microchip Technology Inc. and its subsidiaries.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Subject to your compliance with these terms, you may use Microchip
13 * software and any derivatives exclusively with Microchip products.
14 * It is your responsibility to comply with third party license terms applicable
15 * to your use of third party software (including open source software) that
16 * may accompany Microchip software.
17 *
18 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
19 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
20 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
21 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
22 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
23 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
24 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
25 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
26 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
27 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
28 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
29 *
30 * \asf_license_stop
31 *
32 */
33/*
34 * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
35 */
36
37#include <compiler.h>
38#include <hpl_cmcc.h>
39#include <hpl_cmcc_config.h>
40
41/**
42 * \brief Initialize Cache Module
43 *
44 * This function does low level cache configuration.
45 *
46 * \return initialize status
47 */
48int32_t _cmcc_init(void)
49{
50 int32_t return_value;
51
52 _cmcc_disable(CMCC);
53
54 if (_is_cache_disabled(CMCC)) {
55 hri_cmcc_write_CFG_reg(
56 CMCC,
57 (CMCC_CFG_CSIZESW(CONF_CMCC_CACHE_SIZE) | (CONF_CMCC_DATA_CACHE_DISABLE << CMCC_CFG_DCDIS_Pos)
58 | (CONF_CMCC_INST_CACHE_DISABLE << CMCC_CFG_ICDIS_Pos) | (CONF_CMCC_CLK_GATING_DISABLE)));
59
60 _cmcc_enable(CMCC);
61 return_value = _is_cache_enabled(CMCC) == true ? ERR_NONE : ERR_FAILURE;
62 } else {
63 return_value = ERR_NOT_INITIALIZED;
64 }
65
66 return return_value;
67}
68
69/**
70 * \brief Configure CMCC module
71 *
72 * \param[in] pointer pointing to the starting address of CMCC module
73 * \param[in] cache configuration structure pointer
74 *
75 * \return status of operation
76 */
77int32_t _cmcc_configure(const void *hw, struct _cache_cfg *cache_ctrl)
78{
79 int32_t return_value;
80
81 _cmcc_disable(hw);
82
83 if (_is_cache_disabled(hw)) {
84 hri_cmcc_write_CFG_reg(
85 hw,
86 (CMCC_CFG_CSIZESW(cache_ctrl->cache_size) | (cache_ctrl->data_cache_disable << CMCC_CFG_DCDIS_Pos)
87 | (cache_ctrl->inst_cache_disable << CMCC_CFG_ICDIS_Pos) | (cache_ctrl->gclk_gate_disable)));
88
89 return_value = ERR_NONE;
90 } else {
91 return_value = ERR_NOT_INITIALIZED;
92 }
93
94 return return_value;
95}
96
97/**
98 * \brief Enable data cache in CMCC module
99 *
100 * \param[in] pointer pointing to the starting address of CMCC module
101 * \param[in] boolean 1 -> Enable the data cache, 0 -> disable the data cache
102 *
103 * \return status of operation
104 */
105int32_t _cmcc_enable_data_cache(const void *hw, bool value)
106{
107 uint32_t tmp;
108 int32_t ret;
109
110 tmp = hri_cmcc_read_CFG_reg(hw);
111 tmp &= ~CMCC_CFG_DCDIS;
112 tmp |= ((!value) << CMCC_CFG_DCDIS_Pos);
113
114 ret = _cmcc_disable(hw);
115 hri_cmcc_write_CFG_reg(hw, tmp);
116 ret = _cmcc_enable(hw);
117
118 return ret;
119}
120
121/**
122 * \brief Enable instruction cache in CMCC module
123 *
124 * \param[in] pointer pointing to the starting address of CMCC module
125 * \param[in] boolean 1 -> Enable the inst cache, 0 -> disable the inst cache
126 *
127 * \return status of operation
128 */
129int32_t _cmcc_enable_inst_cache(const void *hw, bool value)
130{
131 uint32_t tmp;
132 int32_t ret;
133
134 tmp = hri_cmcc_read_CFG_reg(hw);
135 tmp &= ~CMCC_CFG_ICDIS;
136 tmp |= ((!value) << CMCC_CFG_ICDIS_Pos);
137
138 ret = _cmcc_disable(hw);
139 hri_cmcc_write_CFG_reg(hw, tmp);
140 ret = _cmcc_enable(hw);
141
142 return ret;
143}
144
145/**
146 * \brief Enable clock gating in CMCC module
147 *
148 * \param[in] pointer pointing to the starting address of CMCC module
149 * \param[in] boolean 1 -> Enable the clock gate, 0 -> disable the clock gate
150 *
151 * \return status of operation
152 */
153int32_t _cmcc_enable_clock_gating(const void *hw, bool value)
154{
155 uint32_t tmp;
156 int32_t ret;
157
158 tmp = hri_cmcc_read_CFG_reg(hw);
159 tmp |= value;
160
161 ret = _cmcc_disable(hw);
162 hri_cmcc_write_CFG_reg(hw, tmp);
163 ret = _cmcc_enable(hw);
164
165 return ret;
166}
167
168/**
169 * \brief Configure the cache size in CMCC module
170 *
171 * \param[in] pointer pointing to the starting address of CMCC module
172 * \param[in] element from cache size configuration enumerator
173 * 0->1K, 1->2K, 2->4K(default)
174 *
175 * \return status of operation
176 */
177int32_t _cmcc_configure_cache_size(const void *hw, enum conf_cache_size size)
178{
179 uint32_t tmp;
180 int32_t ret;
181
182 tmp = hri_cmcc_read_CFG_reg(hw);
183 tmp &= (~CMCC_CFG_CSIZESW_Msk);
184 tmp |= (size << CMCC_CFG_CSIZESW_Pos);
185
186 ret = _cmcc_disable(hw);
187 hri_cmcc_write_CFG_reg(hw, tmp);
188 ret = _cmcc_enable(hw);
189
190 return ret;
191}
192
193/**
194 * \brief Lock the mentioned WAY in CMCC module
195 *
196 * \param[in] pointer pointing to the starting address of CMCC module
197 * \param[in] element from "way_num_index" enumerator
198 *
199 * \return status of operation
200 */
201int32_t _cmcc_lock_way(const void *hw, enum way_num_index num)
202{
203 uint32_t tmp;
204 int32_t ret;
205
206 tmp = hri_cmcc_read_LCKWAY_reg(hw);
207 tmp |= CMCC_LCKWAY_LCKWAY(num);
208
209 ret = _cmcc_disable(hw);
210 hri_cmcc_write_LCKWAY_reg(hw, tmp);
211 ret = _cmcc_enable(hw);
212
213 return ret;
214}
215
216/**
217 * \brief Unlock the mentioned WAY in CMCC module
218 *
219 * \param[in] pointer pointing to the starting address of CMCC module
220 * \param[in] element from "way_num_index" enumerator
221 *
222 * \return status of operation
223 */
224int32_t _cmcc_unlock_way(const void *hw, enum way_num_index num)
225{
226 uint32_t tmp;
227 int32_t ret;
228
229 tmp = hri_cmcc_read_LCKWAY_reg(hw);
230 tmp &= (~CMCC_LCKWAY_LCKWAY(num));
231
232 ret = _cmcc_disable(hw);
233 hri_cmcc_write_LCKWAY_reg(hw, tmp);
234 ret = _cmcc_enable(hw);
235
236 return ret;
237}
238
239/**
240 * \brief Invalidate the mentioned cache line in CMCC module
241 *
242 * \param[in] pointer pointing to the starting address of CMCC module
243 * \param[in] element from "way_num" enumerator (valid arg is 0-3)
244 * \param[in] line number (valid arg is 0-63 as each way will have 64 lines)
245 *
246 * \return status of operation
247 */
248int32_t _cmcc_invalidate_by_line(const void *hw, uint8_t way_num, uint8_t line_num)
249{
250 int32_t return_value;
251
252 if ((way_num < CMCC_WAY_NOS) && (line_num < CMCC_LINE_NOS)) {
253 _cmcc_disable(hw);
254 while (!(_is_cache_disabled(hw)))
255 ;
256 hri_cmcc_write_MAINT1_reg(hw, (CMCC_MAINT1_INDEX(line_num) | CMCC_MAINT1_WAY(way_num)));
257 return_value = ERR_NONE;
258 } else {
259 return_value = ERR_INVALID_ARG;
260 }
261
262 return return_value;
263}
264
265/**
266 * \brief Invalidate entire cache entries in CMCC module
267 *
268 * \param[in] pointer pointing to the starting address of CMCC module
269 *
270 * \return status of operation
271 */
272int32_t _cmcc_invalidate_all(const void *hw)
273{
274 int32_t return_value;
275
276 _cmcc_disable(hw);
277 if (_is_cache_disabled(hw)) {
278 hri_cmcc_write_MAINT0_reg(hw, CMCC_MAINT0_INVALL);
279 return_value = ERR_NONE;
280 } else {
281 return_value = ERR_FAILURE;
282 }
283
284 return return_value;
285}
286
287/**
288 * \brief Configure cache monitor in CMCC module
289 *
290 * \param[in] pointer pointing to the starting address of CMCC module
291 * \param[in] element from cache monitor configurations enumerator
292 *
293 * \return status of operation
294 */
295int32_t _cmcc_configure_monitor(const void *hw, enum conf_cache_monitor monitor_cfg)
296{
297 hri_cmcc_write_MCFG_reg(hw, CMCC_MCFG_MODE(monitor_cfg));
298
299 return ERR_NONE;
300}
301
302/**
303 * \brief Enable cache monitor in CMCC module
304 *
305 * \param[in] pointer pointing to the starting address of CMCC module
306 *
307 * \return status of operation
308 */
309int32_t _cmcc_enable_monitor(const void *hw)
310{
311 hri_cmcc_write_MEN_reg(hw, CMCC_MEN_MENABLE);
312
313 return ERR_NONE;
314}
315
316/**
317 * \brief Disable cache monitor in CMCC module
318 *
319 * \param[in] pointer pointing to the starting address of CMCC module
320 *
321 * \return status of operation
322 */
323int32_t _cmcc_disable_monitor(const void *hw)
324{
325 hri_cmcc_write_MEN_reg(hw, (CMCC_MONITOR_DISABLE << CMCC_MEN_MENABLE_Pos));
326
327 return ERR_NONE;
328}
329
330/**
331 * \brief Reset cache monitor in CMCC module
332 *
333 * \param[in] pointer pointing to the starting address of CMCC module
334 *
335 * \return status of operation
336 */
337int32_t _cmcc_reset_monitor(const void *hw)
338{
339 hri_cmcc_write_MCTRL_reg(hw, CMCC_MCTRL_SWRST);
340
341 return ERR_NONE;
342}
343
344/**
345 * \brief Get cache monitor event counter value from CMCC module
346 *
347 * \param[in] pointer pointing to the starting address of CMCC module
348 *
349 * \return event counter value
350 */
351uint32_t _cmcc_get_monitor_event_count(const void *hw)
352{
353 return hri_cmcc_read_MSR_reg(hw);
354}