1 /**
2 * @file flc_me13.c
3 * @brief Flash Controler driver.
4 * @details This driver can be used to operate on the embedded flash memory.
5 */
6 /******************************************************************************
7 *
8 * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
9 * Analog Devices, Inc.),
10 * Copyright (C) 2023-2024 Analog Devices, Inc.
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 ******************************************************************************/
25
26 /* **** Includes **** */
27 #include <string.h>
28 #include "mxc_device.h"
29 #include "mxc_assert.h"
30 #include "mxc_sys.h"
31 #include "flc.h"
32 #include "flc_reva.h"
33 #include "flc_common.h"
34 #include "icc.h"
35 #include "mcr_regs.h" // For ECCEN registers.
36 #include "sfcc.h"
37
38 //******************************************************************************
MXC_FLC_ME13_Flash_Operation(void)39 void MXC_FLC_ME13_Flash_Operation(void)
40 {
41 /*
42 This function should be called after modifying the contents of flash memory.
43 It flushes the instruction caches and line fill buffer.
44
45 It should be called _afterwards_ because after flash is modified the cache
46 may contain instructions that may no longer be valid. _Before_ the
47 flash modifications the ICC may contain relevant cached instructions related to
48 the incoming flash instructions (especially relevant in the case of external memory),
49 and these instructions will be valid up until the point that the modifications are made.
50
51 The line fill buffer is a FLC-related buffer that also may no longer be valid.
52 It's flushed by reading 2 pages of flash.
53 */
54
55 /* Flush all instruction caches if cache is enabled */
56 if (MXC_ICC->cache_ctrl & MXC_F_ICC_CACHE_CTRL_EN) {
57 MXC_ICC_Flush();
58 }
59
60 if (MXC_SFCC->cache_ctrl & MXC_F_ICC_CACHE_CTRL_EN) {
61 MXC_SFCC_Enable();
62 }
63
64 // Clear the line fill buffer by reading 2 pages from flash
65 volatile uint32_t *line_addr;
66 volatile uint32_t __unused line; // __unused attribute removes warning
67 line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE);
68 line = *line_addr;
69 line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE + MXC_FLASH_PAGE_SIZE);
70 line = *line_addr;
71 }
72
73 //******************************************************************************
MXC_FLC_ME13_GetByAddress(mxc_flc_regs_t ** flc,uint32_t addr)74 int MXC_FLC_ME13_GetByAddress(mxc_flc_regs_t **flc, uint32_t addr)
75 {
76 if (addr < MXC_FLASH1_MEM_BASE && addr >= MXC_FLASH0_MEM_BASE) {
77 *flc = MXC_FLC0;
78 } else if (addr >= MXC_FLASH1_MEM_BASE && addr < (MXC_FLASH1_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
79 *flc = MXC_FLC1;
80 } else if (addr >= MXC_INFO0_MEM_BASE && addr < (MXC_INFO0_MEM_BASE + MXC_INFO_MEM_SIZE)) {
81 *flc = MXC_FLC0;
82 } else if (addr >= MXC_INFO1_MEM_BASE && addr < (MXC_INFO1_MEM_BASE + MXC_INFO_MEM_SIZE)) {
83 *flc = MXC_FLC1;
84 } else {
85 return E_BAD_PARAM;
86 }
87
88 return E_NO_ERROR;
89 }
90
91 //******************************************************************************
MXC_FLC_ME13_GetPhysicalAddress(uint32_t addr,uint32_t * result)92 int MXC_FLC_ME13_GetPhysicalAddress(uint32_t addr, uint32_t *result)
93 {
94 if (addr < MXC_FLASH1_MEM_BASE && addr >= MXC_FLASH0_MEM_BASE) {
95 *result = addr & (MXC_FLASH_MEM_SIZE - 1);
96 } else if (addr >= MXC_FLASH1_MEM_BASE && addr < (MXC_FLASH1_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
97 *result = (addr - MXC_FLASH_MEM_SIZE) & (MXC_FLASH_MEM_SIZE - 1);
98 } else if (addr >= MXC_INFO0_MEM_BASE && addr < (MXC_INFO0_MEM_BASE + MXC_INFO_MEM_SIZE)) {
99 *result = (addr & (MXC_INFO_MEM_SIZE - 1)) + MXC_FLASH_MEM_SIZE;
100 } else if (addr >= MXC_INFO1_MEM_BASE && addr < (MXC_INFO1_MEM_BASE + MXC_INFO_MEM_SIZE)) {
101 *result = ((addr - MXC_INFO_MEM_SIZE) & (MXC_INFO_MEM_SIZE - 1)) + MXC_FLASH_MEM_SIZE;
102 } else {
103 return E_BAD_PARAM;
104 }
105
106 return E_NO_ERROR;
107 }
108
109 //******************************************************************************
MXC_FLC_Init(void)110 int MXC_FLC_Init(void)
111 {
112 MXC_FLC_SetFLCInt(MXC_FLC0);
113 MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_ICACHEXIP);
114
115 return E_NO_ERROR;
116 }
117
118 //******************************************************************************
119 #if IAR_PRAGMAS
120 #pragma section = ".flashprog"
121 #else
122 __attribute__((section(".flashprog")))
123 #endif
MXC_FLC_Busy(void)124 int MXC_FLC_Busy(void)
125 {
126 return MXC_FLC_RevA_Busy();
127 }
128
129 //******************************************************************************
130 #if IAR_PRAGMAS
131 #pragma section = ".flashprog"
132 #else
133 __attribute__((section(".flashprog")))
134 #endif
MXC_FLC_PageErase(uint32_t address)135 int MXC_FLC_PageErase(uint32_t address)
136 {
137 int err;
138 uint32_t addr;
139 mxc_flc_regs_t *flc = NULL;
140
141 // Get FLC Instance
142 if ((err = MXC_FLC_ME13_GetByAddress(&flc, address)) != E_NO_ERROR) {
143 return err;
144 }
145
146 if ((err = MXC_FLC_ME13_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
147 return err;
148 }
149
150 err = MXC_FLC_RevA_PageErase((mxc_flc_reva_regs_t *)flc, addr);
151 // Flush the cache
152 MXC_FLC_ME13_Flash_Operation();
153
154 return err;
155 }
156
157 //******************************************************************************
MXC_FLC_MassErase(void)158 int MXC_FLC_MassErase(void)
159 {
160 int err, i;
161 mxc_flc_regs_t *flc;
162
163 for (i = 0; i < MXC_FLC_INSTANCES; i++) {
164 flc = MXC_FLC_GET_FLC(i);
165 err = MXC_FLC_RevA_MassErase((mxc_flc_reva_regs_t *)flc);
166
167 if (err != E_NO_ERROR) {
168 return err;
169 }
170
171 MXC_FLC_ME13_Flash_Operation();
172 }
173
174 return E_NO_ERROR;
175 }
176
177 //******************************************************************************
178 #if IAR_PRAGMAS
179 #pragma section = ".flashprog"
180 #else
181 __attribute__((section(".flashprog")))
182 #endif
183 // make sure to disable ICC with ICC_Disable(); before Running this function
MXC_FLC_Write128(uint32_t address,uint32_t * data)184 int MXC_FLC_Write128(uint32_t address, uint32_t *data)
185 {
186 int err;
187 mxc_flc_regs_t *flc = NULL;
188 uint32_t addr;
189
190 // Address checked if it is 128-bit aligned
191 if (address & 0xF) {
192 return E_BAD_PARAM;
193 }
194
195 // Get FLC Instance
196 if ((err = MXC_FLC_ME13_GetByAddress(&flc, address)) != E_NO_ERROR) {
197 return err;
198 }
199
200 if ((err = MXC_FLC_ME13_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
201 return err;
202 }
203
204 if ((err = MXC_FLC_RevA_Write128((mxc_flc_reva_regs_t *)flc, addr, data)) != E_NO_ERROR) {
205 return err;
206 }
207
208 // Flush the cache
209 MXC_FLC_ME13_Flash_Operation();
210
211 if ((err = MXC_FLC_Com_VerifyData(address, 4, data)) != E_NO_ERROR) {
212 return err;
213 }
214
215 return E_NO_ERROR;
216 }
217
218 //******************************************************************************
MXC_FLC_Write32(uint32_t address,uint32_t data)219 int MXC_FLC_Write32(uint32_t address, uint32_t data)
220 {
221 uint32_t addr, aligned;
222 int err;
223 mxc_flc_regs_t *flc = NULL;
224
225 // Address checked if it is byte addressable
226 if (address & 0x3) {
227 return E_BAD_PARAM;
228 }
229
230 // Align address to 128-bit word
231 aligned = address & 0xfffffff0;
232
233 // Get FLC Instance
234 if ((err = MXC_FLC_ME13_GetByAddress(&flc, address)) != E_NO_ERROR) {
235 return err;
236 }
237
238 if ((err = MXC_FLC_ME13_GetPhysicalAddress(aligned, &addr)) < E_NO_ERROR) {
239 return err;
240 }
241
242 if ((MXC_MCR->eccen & MXC_F_MCR_ECCEN_FL0ECCEN) ||
243 (MXC_MCR->eccen & MXC_F_MCR_ECCEN_FL1ECCEN)) {
244 return E_BAD_STATE;
245 }
246
247 err = MXC_FLC_RevA_Write32Using128((mxc_flc_reva_regs_t *)flc, address, data, addr);
248
249 // Flush the cache
250 MXC_FLC_ME13_Flash_Operation();
251
252 return err;
253 }
254
255 //******************************************************************************
MXC_FLC_Write(uint32_t address,uint32_t length,uint32_t * buffer)256 int MXC_FLC_Write(uint32_t address, uint32_t length, uint32_t *buffer)
257 {
258 return MXC_FLC_Com_Write(address, length, buffer);
259 }
260
261 //******************************************************************************
MXC_FLC_Read(int address,void * buffer,int len)262 void MXC_FLC_Read(int address, void *buffer, int len)
263 {
264 MXC_FLC_Com_Read(address, buffer, len);
265 }
266
267 //******************************************************************************
MXC_FLC_SetFLCInt(mxc_flc_regs_t * flc)268 void MXC_FLC_SetFLCInt(mxc_flc_regs_t *flc)
269 {
270 MXC_FLC_RevA_SetFLCInt((mxc_flc_reva_regs_t *)flc);
271 }
272
273 //******************************************************************************
MXC_FLC_GetFLCInt(void)274 mxc_flc_regs_t *MXC_FLC_GetFLCInt(void)
275 {
276 return ((mxc_flc_regs_t *)MXC_FLC_RevA_GetFLCInt());
277 }
278
279 //******************************************************************************
MXC_FLC_EnableInt(uint32_t flags)280 int MXC_FLC_EnableInt(uint32_t flags)
281 {
282 return MXC_FLC_RevA_EnableInt(flags);
283 }
284
285 //******************************************************************************
MXC_FLC_DisableInt(uint32_t flags)286 int MXC_FLC_DisableInt(uint32_t flags)
287 {
288 return MXC_FLC_RevA_DisableInt(flags);
289 }
290
291 //******************************************************************************
MXC_FLC_GetFlags(void)292 int MXC_FLC_GetFlags(void)
293 {
294 return MXC_FLC_RevA_GetFlags();
295 }
296
297 //******************************************************************************
MXC_FLC_ClearFlags(uint32_t flags)298 int MXC_FLC_ClearFlags(uint32_t flags)
299 {
300 return MXC_FLC_RevA_ClearFlags(flags);
301 }
302
303 //******************************************************************************
MXC_FLC_UnlockInfoBlock(uint32_t address)304 int MXC_FLC_UnlockInfoBlock(uint32_t address)
305 {
306 int err;
307 mxc_flc_regs_t *flc;
308
309 if ((err = MXC_FLC_ME13_GetByAddress(&flc, address)) != E_NO_ERROR) {
310 return err;
311 }
312
313 return MXC_FLC_RevA_UnlockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
314 }
315
316 //******************************************************************************
MXC_FLC_LockInfoBlock(uint32_t address)317 int MXC_FLC_LockInfoBlock(uint32_t address)
318 {
319 int err;
320 mxc_flc_regs_t *flc;
321
322 if ((err = MXC_FLC_ME13_GetByAddress(&flc, address)) != E_NO_ERROR) {
323 return err;
324 }
325
326 return MXC_FLC_RevA_LockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
327 }
328
329 //******************************************************************************
MXC_FLC_BlockPageWrite(uint32_t address)330 int MXC_FLC_BlockPageWrite(uint32_t address)
331 {
332 /* MAX32570 does not support flash page read and write locks */
333 return E_NOT_SUPPORTED;
334 }
335
336 //******************************************************************************
MXC_FLC_BlockPageRead(uint32_t address)337 int MXC_FLC_BlockPageRead(uint32_t address)
338 {
339 /* MAX32570 does not support flash page read and write locks */
340 return E_NOT_SUPPORTED;
341 }
342
343 //******************************************************************************
MXC_FLC_GetWELR(uint32_t address,uint32_t page_num)344 volatile uint32_t *MXC_FLC_GetWELR(uint32_t address, uint32_t page_num)
345 {
346 /* MAX32570 does not support flash page read and write locks */
347 return NULL;
348 }
349
350 //******************************************************************************
MXC_FLC_GetRLR(uint32_t address,uint32_t page_num)351 volatile uint32_t *MXC_FLC_GetRLR(uint32_t address, uint32_t page_num)
352 {
353 /* MAX32570 does not support flash page read and write locks */
354 return NULL;
355 }
356