1 /**
2 * @file flc_me15.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 "ecc_regs.h" // For ECCEN registers.
35 #include "mcr_regs.h" // For ECCEN registers.
36
37 //******************************************************************************
MXC_FLC_ME15_Flash_Operation(void)38 void MXC_FLC_ME15_Flash_Operation(void)
39 {
40 /* Flush all instruction caches */
41 MXC_GCR->sysctrl |= MXC_F_GCR_SYSCTRL_ICC0_FLUSH;
42
43 /* Wait for flush to complete */
44 while (MXC_GCR->sysctrl & MXC_F_GCR_SYSCTRL_ICC0_FLUSH) {}
45 }
46
47 //******************************************************************************
MXC_FLC_ME15_GetByAddress(mxc_flc_regs_t ** flc,uint32_t addr)48 int MXC_FLC_ME15_GetByAddress(mxc_flc_regs_t **flc, uint32_t addr)
49 {
50 if ((addr >= MXC_FLASH_MEM_BASE) && (addr < (MXC_FLASH_MEM_BASE + MXC_FLASH_MEM_SIZE))) {
51 *flc = MXC_FLC0;
52 } else if ((addr >= MXC_INFO_MEM_BASE) && (addr < (MXC_INFO_MEM_BASE + MXC_INFO_MEM_SIZE))) {
53 *flc = MXC_FLC0;
54 } else {
55 return E_BAD_PARAM;
56 }
57
58 return E_NO_ERROR;
59 }
60
61 //******************************************************************************
MXC_FLC_ME15_GetPhysicalAddress(uint32_t addr,uint32_t * result)62 int MXC_FLC_ME15_GetPhysicalAddress(uint32_t addr, uint32_t *result)
63 {
64 if ((addr >= MXC_FLASH_MEM_BASE) && (addr < (MXC_FLASH_MEM_BASE + MXC_FLASH_MEM_SIZE))) {
65 *result = addr - MXC_FLASH_MEM_BASE;
66 } else if ((addr >= MXC_INFO_MEM_BASE) && (addr < (MXC_INFO_MEM_BASE + MXC_INFO_MEM_SIZE))) {
67 /* For ME15, the info block base was located at the next power of 2 address beyond the main flash.
68 The ME15 ends at 0x5FFFF, so the info block starts at 0x80000. */
69 *result = (addr & (MXC_INFO_MEM_SIZE - 1)) + 0x80000;
70 } else {
71 return E_BAD_PARAM;
72 }
73
74 return E_NO_ERROR;
75 }
76
77 //******************************************************************************
MXC_FLC_Init(void)78 int MXC_FLC_Init(void)
79 {
80 return E_NO_ERROR;
81 }
82
83 //******************************************************************************
84 #if IAR_PRAGMAS
85 #pragma section = ".flashprog"
86 #else
87 __attribute__((section(".flashprog")))
88 #endif
MXC_FLC_Busy(void)89 int MXC_FLC_Busy(void)
90 {
91 return MXC_FLC_RevA_Busy();
92 }
93
94 //******************************************************************************
95 #if IAR_PRAGMAS
96 #pragma section = ".flashprog"
97 #else
98 __attribute__((section(".flashprog")))
99 #endif
MXC_FLC_PageErase(uint32_t address)100 int MXC_FLC_PageErase(uint32_t address)
101 {
102 int err;
103 uint32_t addr;
104 mxc_flc_regs_t *flc = NULL;
105
106 // Get FLC Instance
107 if ((err = MXC_FLC_ME15_GetByAddress(&flc, address)) != E_NO_ERROR) {
108 return err;
109 }
110
111 if ((err = MXC_FLC_ME15_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
112 return err;
113 }
114
115 err = MXC_FLC_RevA_PageErase((mxc_flc_reva_regs_t *)flc, addr);
116 // Flush the cache
117 MXC_FLC_ME15_Flash_Operation();
118
119 return err;
120 }
121
122 //******************************************************************************
123 #if IAR_PRAGMAS
124 #pragma section = ".flashprog"
125 #else
126 __attribute__((section(".flashprog")))
127 #endif
128 // make sure to disable ICC with ICC_Disable(); before Running this function
MXC_FLC_Write128(uint32_t address,uint32_t * data)129 int MXC_FLC_Write128(uint32_t address, uint32_t *data)
130 {
131 int err;
132 mxc_flc_regs_t *flc = NULL;
133 uint32_t addr;
134
135 // Address checked if it is 128-bit aligned
136 if (address & 0xF) {
137 return E_BAD_PARAM;
138 }
139
140 // Get FLC Instance
141 if ((err = MXC_FLC_ME15_GetByAddress(&flc, address)) != E_NO_ERROR) {
142 return err;
143 }
144
145 if ((err = MXC_FLC_ME15_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
146 return err;
147 }
148
149 if ((err = MXC_FLC_RevA_Write128((mxc_flc_reva_regs_t *)flc, addr, data)) != E_NO_ERROR) {
150 return err;
151 }
152
153 // Flush the cache
154 MXC_FLC_ME15_Flash_Operation();
155
156 if ((err = MXC_FLC_Com_VerifyData(address, 4, data)) != E_NO_ERROR) {
157 return err;
158 }
159
160 return E_NO_ERROR;
161 }
162
163 //******************************************************************************
MXC_FLC_Write32(uint32_t address,uint32_t data)164 int MXC_FLC_Write32(uint32_t address, uint32_t data)
165 {
166 uint32_t addr, aligned;
167 int err;
168 mxc_flc_regs_t *flc = NULL;
169
170 // Address checked if it is byte addressable
171 if (address & 0x3) {
172 return E_BAD_PARAM;
173 }
174
175 // Align address to 128-bit word
176 aligned = address & 0xfffffff0;
177
178 // Get FLC Instance
179 if ((err = MXC_FLC_ME15_GetByAddress(&flc, address)) != E_NO_ERROR) {
180 return err;
181 }
182
183 if ((err = MXC_FLC_ME15_GetPhysicalAddress(aligned, &addr)) < E_NO_ERROR) {
184 return err;
185 }
186
187 if (MXC_ECC->en & MXC_F_ECC_EN_FLASH) {
188 return E_BAD_STATE;
189 }
190
191 return MXC_FLC_RevA_Write32Using128((mxc_flc_reva_regs_t *)flc, address, data, addr);
192 }
193
194 //******************************************************************************
MXC_FLC_MassErase(void)195 int MXC_FLC_MassErase(void)
196 {
197 int err, i;
198 mxc_flc_regs_t *flc;
199
200 for (i = 0; i < MXC_FLC_INSTANCES; i++) {
201 flc = MXC_FLC_GET_FLC(i);
202 err = MXC_FLC_RevA_MassErase((mxc_flc_reva_regs_t *)flc);
203
204 if (err != E_NO_ERROR) {
205 return err;
206 }
207
208 MXC_FLC_ME15_Flash_Operation();
209 }
210
211 return E_NO_ERROR;
212 }
213
214 //******************************************************************************
MXC_FLC_UnlockInfoBlock(uint32_t address)215 int MXC_FLC_UnlockInfoBlock(uint32_t address)
216 {
217 int err;
218 mxc_flc_regs_t *flc;
219
220 if ((err = MXC_FLC_ME15_GetByAddress(&flc, address)) != E_NO_ERROR) {
221 return err;
222 }
223
224 return MXC_FLC_RevA_UnlockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
225 }
226
227 //******************************************************************************
MXC_FLC_LockInfoBlock(uint32_t address)228 int MXC_FLC_LockInfoBlock(uint32_t address)
229 {
230 int err;
231 mxc_flc_regs_t *flc;
232
233 if ((err = MXC_FLC_ME15_GetByAddress(&flc, address)) != E_NO_ERROR) {
234 return err;
235 }
236
237 return MXC_FLC_RevA_LockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
238 }
239
240 //******************************************************************************
MXC_FLC_Write(uint32_t address,uint32_t length,uint32_t * buffer)241 int MXC_FLC_Write(uint32_t address, uint32_t length, uint32_t *buffer)
242 {
243 return MXC_FLC_Com_Write(address, length, buffer);
244 }
245
246 //******************************************************************************
MXC_FLC_Read(int address,void * buffer,int len)247 void MXC_FLC_Read(int address, void *buffer, int len)
248 {
249 MXC_FLC_Com_Read(address, buffer, len);
250 }
251
252 //******************************************************************************
MXC_FLC_EnableInt(uint32_t flags)253 int MXC_FLC_EnableInt(uint32_t flags)
254 {
255 return MXC_FLC_RevA_EnableInt(flags);
256 }
257
258 //******************************************************************************
MXC_FLC_DisableInt(uint32_t flags)259 int MXC_FLC_DisableInt(uint32_t flags)
260 {
261 return MXC_FLC_RevA_DisableInt(flags);
262 }
263
264 //******************************************************************************
MXC_FLC_GetFlags(void)265 int MXC_FLC_GetFlags(void)
266 {
267 return MXC_FLC_RevA_GetFlags();
268 }
269
270 //******************************************************************************
MXC_FLC_ClearFlags(uint32_t flags)271 int MXC_FLC_ClearFlags(uint32_t flags)
272 {
273 return MXC_FLC_RevA_ClearFlags(flags);
274 }
275
276 //******************************************************************************
MXC_FLC_BlockPageWrite(uint32_t address)277 int MXC_FLC_BlockPageWrite(uint32_t address)
278 {
279 if (address < MXC_FLASH_MEM_BASE || address > (MXC_FLASH_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
280 return E_INVALID;
281 }
282
283 return MXC_FLC_RevA_BlockPageWrite(address, MXC_FLASH_MEM_BASE);
284 }
285
286 //******************************************************************************
MXC_FLC_BlockPageRead(uint32_t address)287 int MXC_FLC_BlockPageRead(uint32_t address)
288 {
289 if (address < MXC_FLASH_MEM_BASE || address > (MXC_FLASH_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
290 return E_INVALID;
291 }
292
293 return MXC_FLC_RevA_BlockPageRead(address, MXC_FLASH_MEM_BASE);
294 }
295
296 //******************************************************************************
MXC_FLC_GetWELR(uint32_t address,uint32_t page_num)297 volatile uint32_t *MXC_FLC_GetWELR(uint32_t address, uint32_t page_num)
298 {
299 uint32_t reg_num;
300 reg_num = page_num >>
301 5; // Divide by 32 to get WELR register number containing the page lock bit
302
303 if (address < MXC_FLASH_MEM_BASE || address > (MXC_FLASH_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
304 return NULL;
305 }
306
307 switch (reg_num) {
308 case 0:
309 return &(MXC_FLC0->welr0);
310 case 1:
311 return &(MXC_FLC0->welr1);
312 }
313
314 return NULL;
315 }
316
317 //******************************************************************************
MXC_FLC_GetRLR(uint32_t address,uint32_t page_num)318 volatile uint32_t *MXC_FLC_GetRLR(uint32_t address, uint32_t page_num)
319 {
320 uint32_t reg_num;
321 reg_num = page_num >> 5; // Divide by 32 to get RLR register number containing the page lock bit
322
323 if (address < MXC_FLASH_MEM_BASE || address > (MXC_FLASH_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
324 return NULL;
325 }
326
327 switch (reg_num) {
328 case 0:
329 return &(MXC_FLC0->rlr0);
330 case 1:
331 return &(MXC_FLC0->rlr1);
332 }
333
334 return NULL;
335 }
336