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