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