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