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