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