1 /**
2 * @file flc_me14.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 "mcr_regs.h"
35
36 //******************************************************************************
MXC_FLC_ME14_Flash_Operation(void)37 void MXC_FLC_ME14_Flash_Operation(void)
38 {
39 /*
40 This function should be called after modifying the contents of flash memory.
41 It flushes the instruction caches and line fill buffer.
42
43 It should be called _afterwards_ because after flash is modified the cache
44 may contain instructions that may no longer be valid. _Before_ the
45 flash modifications the ICC may contain relevant cached instructions related to
46 the incoming flash instructions (especially relevant in the case of external memory),
47 and these instructions will be valid up until the point that the modifications are made.
48
49 The line fill buffer is a FLC-related buffer that also may no longer be valid.
50 It's flushed by reading 2 pages of flash.
51 */
52
53 /* Flush all instruction caches */
54 MXC_GCR->scon |= MXC_F_GCR_SCON_CCACHE_FLUSH;
55
56 /* Wait for flush to complete */
57 while (MXC_GCR->scon & MXC_F_GCR_SCON_CCACHE_FLUSH) {}
58
59 // Clear the line fill buffer by reading 2 pages from flash
60 volatile uint32_t *line_addr;
61 volatile uint32_t __unused line; // __unused attribute removes warning
62 line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE);
63 line = *line_addr;
64 line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE + MXC_FLASH_PAGE_SIZE);
65 line = *line_addr;
66 }
67
68 //******************************************************************************
MXC_FLC_ME14_GetByAddress(mxc_flc_regs_t ** flc,uint32_t addr)69 int MXC_FLC_ME14_GetByAddress(mxc_flc_regs_t **flc, uint32_t addr)
70 {
71 if (addr < MXC_FLASH1_MEM_BASE && addr >= MXC_FLASH0_MEM_BASE) {
72 *flc = MXC_FLC0;
73 } else if (addr >= MXC_FLASH1_MEM_BASE && addr < (MXC_FLASH1_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
74 *flc = MXC_FLC1;
75 } else if (addr >= MXC_INFO0_MEM_BASE && addr < (MXC_INFO0_MEM_BASE + MXC_INFO_MEM_SIZE)) {
76 *flc = MXC_FLC0;
77 } else if (addr >= MXC_INFO1_MEM_BASE && addr < (MXC_INFO1_MEM_BASE + MXC_INFO_MEM_SIZE)) {
78 *flc = MXC_FLC1;
79 } else {
80 return E_BAD_PARAM;
81 }
82
83 return E_NO_ERROR;
84 }
85
86 //******************************************************************************
MXC_FLC_ME14_GetPhysicalAddress(uint32_t addr,uint32_t * result)87 int MXC_FLC_ME14_GetPhysicalAddress(uint32_t addr, uint32_t *result)
88 {
89 if (addr < MXC_FLASH1_MEM_BASE && addr >= MXC_FLASH0_MEM_BASE) {
90 *result = addr & (MXC_FLASH_MEM_SIZE - 1);
91 } else if (addr >= MXC_FLASH1_MEM_BASE && addr < (MXC_FLASH1_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
92 *result = (addr - MXC_FLASH_MEM_SIZE) & (MXC_FLASH_MEM_SIZE - 1);
93 } else if (addr >= MXC_INFO0_MEM_BASE && addr < (MXC_INFO0_MEM_BASE + MXC_INFO_MEM_SIZE)) {
94 *result = (addr & (MXC_INFO_MEM_SIZE - 1)) + MXC_FLASH_MEM_SIZE;
95 } else if (addr >= MXC_INFO1_MEM_BASE && addr < (MXC_INFO1_MEM_BASE + MXC_INFO_MEM_SIZE)) {
96 *result = ((addr - MXC_INFO_MEM_SIZE) & (MXC_INFO_MEM_SIZE - 1)) + MXC_FLASH_MEM_SIZE;
97 } else {
98 return E_BAD_PARAM;
99 }
100
101 return E_NO_ERROR;
102 }
103
104 /* ****************************************************************************** */
MXC_FLC_Init(void)105 int MXC_FLC_Init(void)
106 {
107 MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_ICACHEXIP);
108
109 return E_NO_ERROR;
110 }
111
112 //******************************************************************************
113 #if IAR_PRAGMAS
114 #pragma section = ".flashprog"
115 #else
116 __attribute__((section(".flashprog")))
117 #endif
MXC_FLC_Busy(void)118 int MXC_FLC_Busy(void)
119 {
120 return MXC_FLC_RevA_Busy();
121 }
122
123 //******************************************************************************
124 #if IAR_PRAGMAS
125 #pragma section = ".flashprog"
126 #else
127 __attribute__((section(".flashprog")))
128 #endif
MXC_FLC_PageErase(uint32_t address)129 int MXC_FLC_PageErase(uint32_t address)
130 {
131 int err;
132 uint32_t addr;
133 mxc_flc_regs_t *flc = NULL;
134
135 // Get FLC Instance
136 if ((err = MXC_FLC_ME14_GetByAddress(&flc, address)) != E_NO_ERROR) {
137 return err;
138 }
139
140 if ((err = MXC_FLC_ME14_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
141 return err;
142 }
143
144 if ((err = MXC_FLC_RevA_PageErase((mxc_flc_reva_regs_t *)flc, addr)) != E_NO_ERROR) {
145 return err;
146 }
147
148 // Flush the cache
149 MXC_FLC_ME14_Flash_Operation();
150
151 return err;
152 }
153
154 //******************************************************************************
MXC_FLC_MassErase(void)155 int MXC_FLC_MassErase(void)
156 {
157 int err, i;
158 mxc_flc_regs_t *flc;
159
160 for (i = 0; i < MXC_FLC_INSTANCES; i++) {
161 flc = MXC_FLC_GET_FLC(i);
162 err = MXC_FLC_RevA_MassErase((mxc_flc_reva_regs_t *)flc);
163
164 if (err != E_NO_ERROR) {
165 return err;
166 }
167
168 MXC_FLC_ME14_Flash_Operation();
169 }
170
171 return E_NO_ERROR;
172 }
173
174 //******************************************************************************
175 #if IAR_PRAGMAS
176 #pragma section = ".flashprog"
177 #else
178 __attribute__((section(".flashprog")))
179 #endif
180 // make sure to disable ICC with ICC_Disable(); before Running this function
MXC_FLC_Write128(uint32_t address,uint32_t * data)181 int MXC_FLC_Write128(uint32_t address, uint32_t *data)
182 {
183 int err;
184 mxc_flc_regs_t *flc = NULL;
185 uint32_t addr;
186
187 // Address checked if it is 128-bit aligned
188 if (address & 0xF) {
189 return E_BAD_PARAM;
190 }
191
192 // Get FLC Instance
193 if ((err = MXC_FLC_ME14_GetByAddress(&flc, address)) != E_NO_ERROR) {
194 return err;
195 }
196
197 if ((err = MXC_FLC_ME14_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
198 return err;
199 }
200
201 err = MXC_FLC_RevA_Write128((mxc_flc_reva_regs_t *)flc, addr, data);
202
203 // Flush the cache
204 MXC_FLC_ME14_Flash_Operation();
205
206 if ((err = MXC_FLC_Com_VerifyData(address, 4, data)) != E_NO_ERROR) {
207 return err;
208 }
209
210 return E_NO_ERROR;
211 }
212
213 //******************************************************************************
MXC_FLC_Write32(uint32_t address,uint32_t data)214 int MXC_FLC_Write32(uint32_t address, uint32_t data)
215 {
216 uint32_t addr, aligned;
217 int err;
218 mxc_flc_regs_t *flc = NULL;
219
220 // Address checked if it is byte addressable
221 if (address & 0x3) {
222 return E_BAD_PARAM;
223 }
224
225 // Align address to 128-bit word
226 aligned = address & 0xfffffff0;
227
228 // Get FLC Instance
229 if ((err = MXC_FLC_ME14_GetByAddress(&flc, address)) != E_NO_ERROR) {
230 return err;
231 }
232
233 if ((err = MXC_FLC_ME14_GetPhysicalAddress(aligned, &addr)) < E_NO_ERROR) {
234 return err;
235 }
236
237 if ((MXC_MCR->eccen & MXC_F_MCR_ECCEN_FL0ECCEN) ||
238 (MXC_MCR->eccen & MXC_F_MCR_ECCEN_FL1ECCEN)) {
239 return E_BAD_STATE;
240 }
241
242 err = MXC_FLC_RevA_Write32Using128((mxc_flc_reva_regs_t *)flc, address, data, addr);
243
244 // Flush the cache
245 MXC_FLC_ME14_Flash_Operation();
246
247 return err;
248 }
249
250 //******************************************************************************
MXC_FLC_Write(uint32_t address,uint32_t length,uint32_t * buffer)251 int MXC_FLC_Write(uint32_t address, uint32_t length, uint32_t *buffer)
252 {
253 return MXC_FLC_Com_Write(address, length, buffer);
254 }
255
256 //******************************************************************************
MXC_FLC_Read(int address,void * buffer,int len)257 void MXC_FLC_Read(int address, void *buffer, int len)
258 {
259 MXC_FLC_Com_Read(address, buffer, len);
260 }
261
262 //******************************************************************************
MXC_FLC_SetFLCInt(mxc_flc_regs_t * flc)263 void MXC_FLC_SetFLCInt(mxc_flc_regs_t *flc)
264 {
265 MXC_FLC_RevA_SetFLCInt((mxc_flc_reva_regs_t *)flc);
266 }
267
268 //******************************************************************************
MXC_FLC_GetFLCInt(void)269 mxc_flc_regs_t *MXC_FLC_GetFLCInt(void)
270 {
271 return ((mxc_flc_regs_t *)MXC_FLC_RevA_GetFLCInt());
272 }
273
274 //******************************************************************************
MXC_FLC_EnableInt(uint32_t flags)275 int MXC_FLC_EnableInt(uint32_t flags)
276 {
277 return MXC_FLC_RevA_EnableInt(flags);
278 }
279
280 //******************************************************************************
MXC_FLC_DisableInt(uint32_t flags)281 int MXC_FLC_DisableInt(uint32_t flags)
282 {
283 return MXC_FLC_RevA_DisableInt(flags);
284 }
285
286 //******************************************************************************
MXC_FLC_GetFlags(void)287 int MXC_FLC_GetFlags(void)
288 {
289 return MXC_FLC_RevA_GetFlags();
290 }
291
292 //******************************************************************************
MXC_FLC_ClearFlags(uint32_t flags)293 int MXC_FLC_ClearFlags(uint32_t flags)
294 {
295 return MXC_FLC_RevA_ClearFlags(flags);
296 }
297
298 //******************************************************************************
MXC_FLC_UnlockInfoBlock(uint32_t address)299 int MXC_FLC_UnlockInfoBlock(uint32_t address)
300 {
301 int err;
302 mxc_flc_regs_t *flc;
303
304 if ((err = MXC_FLC_ME14_GetByAddress(&flc, address)) != E_NO_ERROR) {
305 return err;
306 }
307
308 return MXC_FLC_RevA_UnlockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
309 }
310
311 //******************************************************************************
MXC_FLC_LockInfoBlock(uint32_t address)312 int MXC_FLC_LockInfoBlock(uint32_t address)
313 {
314 int err;
315 mxc_flc_regs_t *flc;
316
317 if ((err = MXC_FLC_ME14_GetByAddress(&flc, address)) != E_NO_ERROR) {
318 return err;
319 }
320
321 return MXC_FLC_RevA_LockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
322 }
323
324 //******************************************************************************
MXC_FLC_BlockPageWrite(uint32_t address)325 int MXC_FLC_BlockPageWrite(uint32_t address)
326 {
327 /* MAX32520 does not support flash page read and write locks */
328 return E_NOT_SUPPORTED;
329 }
330
331 //******************************************************************************
MXC_FLC_BlockPageRead(uint32_t address)332 int MXC_FLC_BlockPageRead(uint32_t address)
333 {
334 /* MAX32520 does not support flash page read and write locks */
335 return E_NOT_SUPPORTED;
336 }
337
338 //******************************************************************************
MXC_FLC_GetWELR(uint32_t address,uint32_t page_num)339 volatile uint32_t *MXC_FLC_GetWELR(uint32_t address, uint32_t page_num)
340 {
341 /* MAX32665 does not support flash page read and write locks */
342 return NULL;
343 }
344
345 //******************************************************************************
MXC_FLC_GetRLR(uint32_t address,uint32_t page_num)346 volatile uint32_t *MXC_FLC_GetRLR(uint32_t address, uint32_t page_num)
347 {
348 /* MAX32665 does not support flash page read and write locks */
349 return NULL;
350 }
351