1 /**
2  * @file flc_es17.h
3  * @brief      Flash Controller 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 "ctb.h"
35 #include "mcr_regs.h" // For ECCEN registers.
36 #include "icc_regs.h"
37 
38 static void mxc_aes_init(void);
39 static int mxc_encrypt_sequence(const uint8_t *pt, uint8_t *ct, uint32_t addr, int len);
40 
41 //******************************************************************************
MXC_FLC_Flash_Operation(void)42 void MXC_FLC_Flash_Operation(void)
43 {
44     volatile uint32_t *line_addr;
45     volatile uint32_t __attribute__((unused)) line;
46 
47     // Clear the cache and leave the cache enable/disable state unchanged
48     MXC_ICC->cache_ctrl ^= MXC_F_ICC_CACHE_CTRL_CACHE_EN;
49     MXC_ICC->cache_ctrl ^= MXC_F_ICC_CACHE_CTRL_CACHE_EN;
50 
51     // Clear the line fill buffer
52     line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE);
53     line = *line_addr;
54     line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE + MXC_FLASH_PAGE_SIZE);
55     line = *line_addr;
56 }
57 
58 //******************************************************************************
MXC_FLC_GetByAddress(mxc_flc_regs_t ** flc,uint32_t addr)59 int MXC_FLC_GetByAddress(mxc_flc_regs_t **flc, uint32_t addr)
60 {
61     if (addr < MXC_FLASH1_MEM_BASE && addr >= MXC_FLASH0_MEM_BASE) {
62         *flc = MXC_FLC;
63     } else if (addr >= MXC_FLASH1_MEM_BASE && addr < (MXC_FLASH1_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
64         *flc = MXC_FLC;
65     } else if (addr >= MXC_INFO0_MEM_BASE && addr < (MXC_INFO0_MEM_BASE + MXC_INFO_MEM_SIZE)) {
66         *flc = MXC_FLC;
67     } else if (addr >= MXC_INFO1_MEM_BASE && addr < (MXC_INFO1_MEM_BASE + MXC_INFO_MEM_SIZE)) {
68         *flc = MXC_FLC;
69     } else {
70         return E_BAD_PARAM;
71     }
72 
73     return E_NO_ERROR;
74 }
75 
76 //******************************************************************************
MXC_FLC_GetPhysicalAddress(uint32_t addr,uint32_t * result)77 int MXC_FLC_GetPhysicalAddress(uint32_t addr, uint32_t *result)
78 {
79     if (addr < MXC_FLASH1_MEM_BASE && addr >= MXC_FLASH0_MEM_BASE) {
80         *result = addr & (MXC_FLASH_MEM_SIZE - 1);
81     } else if (addr >= MXC_FLASH1_MEM_BASE && addr < (MXC_FLASH1_MEM_BASE + MXC_FLASH_MEM_SIZE)) {
82         *result = (addr - MXC_FLASH_MEM_SIZE) & (MXC_FLASH_MEM_SIZE - 1);
83     } else if (addr >= MXC_INFO0_MEM_BASE && addr < (MXC_INFO0_MEM_BASE + MXC_INFO_MEM_SIZE)) {
84         *result = addr;
85     } else if (addr >= MXC_INFO1_MEM_BASE && addr < (MXC_INFO1_MEM_BASE + MXC_INFO_MEM_SIZE)) {
86         *result = addr;
87     } else {
88         return E_BAD_PARAM;
89     }
90 
91     return E_NO_ERROR;
92 }
93 
94 //******************************************************************************
MXC_FLC_Init(void)95 int MXC_FLC_Init(void)
96 {
97     return E_NO_ERROR;
98 }
99 
100 //******************************************************************************
101 #if IAR_PRAGMAS
102 #pragma section = ".flashprog"
103 #else
104 __attribute__((section(".flashprog")))
105 #endif
MXC_FLC_Busy(void)106 int MXC_FLC_Busy(void)
107 {
108     return MXC_FLC_RevA_Busy();
109 }
110 
111 //******************************************************************************
112 #if IAR_PRAGMAS
113 #pragma section = ".flashprog"
114 #else
115 __attribute__((section(".flashprog")))
116 #endif
MXC_FLC_PageErase(uint32_t address)117 int MXC_FLC_PageErase(uint32_t address)
118 {
119     int err;
120     uint32_t addr;
121     mxc_flc_regs_t *flc = NULL;
122 
123     // Get FLC Instance
124     if ((err = MXC_FLC_GetByAddress(&flc, address)) != E_NO_ERROR) {
125         return err;
126     }
127 
128     if ((err = MXC_FLC_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
129         return err;
130     }
131 
132     err = MXC_FLC_RevA_PageErase((mxc_flc_reva_regs_t *)flc, addr);
133     // Flush the cache
134     MXC_FLC_Flash_Operation();
135 
136     return err;
137 }
138 
139 //******************************************************************************
MXC_FLC_MassErase(void)140 int MXC_FLC_MassErase(void)
141 {
142     int err, i;
143     mxc_flc_regs_t *flc;
144 
145     for (i = 0; i < MXC_FLC_INSTANCES; i++) {
146         flc = MXC_FLC_GET_FLC(i);
147         err = MXC_FLC_RevA_MassErase((mxc_flc_reva_regs_t *)flc);
148 
149         if (err != E_NO_ERROR) {
150             return err;
151         }
152 
153         MXC_FLC_Flash_Operation();
154     }
155 
156     return E_NO_ERROR;
157 }
158 
159 //******************************************************************************
160 #if IAR_PRAGMAS
161 #pragma section = ".flashprog"
162 #else
163 __attribute__((section(".flashprog")))
164 #endif
165 // make sure to disable ICC with ICC_Disable(); before Running this function
MXC_FLC_Write128(uint32_t address,uint32_t * data)166 int MXC_FLC_Write128(uint32_t address, uint32_t *data)
167 {
168     int err;
169     mxc_flc_regs_t *flc = NULL;
170     uint32_t addr;
171 
172     // Address checked if it is 128-bit aligned
173     if (address & 0xF) {
174         return E_BAD_PARAM;
175     }
176 
177     // Get FLC Instance
178     if ((err = MXC_FLC_GetByAddress(&flc, address)) != E_NO_ERROR) {
179         return err;
180     }
181 
182     if ((err = MXC_FLC_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
183         return err;
184     }
185 
186     if ((err = MXC_FLC_RevA_Write128((mxc_flc_reva_regs_t *)flc, addr, data)) != E_NO_ERROR) {
187         return err;
188     }
189 
190     // Flush the cache
191     MXC_FLC_Flash_Operation();
192 
193     if ((err = MXC_FLC_Com_VerifyData(address, 4, data)) != E_NO_ERROR) {
194         return err;
195     }
196 
197     return E_NO_ERROR;
198 }
199 
200 //******************************************************************************
MXC_FLC_Write32(uint32_t address,uint32_t data)201 int MXC_FLC_Write32(uint32_t address, uint32_t data)
202 {
203     uint32_t addr;
204     int err;
205     mxc_flc_regs_t *flc = NULL;
206 
207     // Address checked if it is byte addressable
208     if (address & 0x3) {
209         return E_BAD_PARAM;
210     }
211 
212     // Get FLC Instance
213     if ((err = MXC_FLC_GetByAddress(&flc, address)) != E_NO_ERROR) {
214         return err;
215     }
216 
217     if ((err = MXC_FLC_GetPhysicalAddress(address, &addr)) < E_NO_ERROR) {
218         return err;
219     }
220 
221     /* Check if the flash controller is busy */
222     if (flc->flsh_cn & (MXC_F_FLC_FLSH_CN_WR | MXC_F_FLC_FLSH_CN_ME | MXC_F_FLC_FLSH_CN_PGE)) {
223         return E_BUSY;
224     }
225 
226     // Set flash clock divider to generate a 1MHz clock from the APB clock
227     flc->flsh_clkdiv = SystemCoreClock / 1000000;
228 
229     /* Clear stale errors */
230     if (flc->flsh_int & MXC_F_FLC_FLSH_INT_AF) {
231         flc->flsh_int &= ~MXC_F_FLC_FLSH_INT_AF;
232     }
233 
234     /* Unlock flash */
235     flc->flsh_cn = (flc->flsh_cn & ~MXC_F_FLC_FLSH_CN_UNLOCK) | MXC_S_FLC_FLSH_CN_UNLOCK_UNLOCKED;
236 
237     // write 32-bits
238     flc->flsh_cn |= MXC_F_FLC_REVA_CTRL_WDTH;
239     // write the data
240     flc->flsh_addr = addr;
241     flc->flsh_data[0] = data;
242     flc->flsh_cn |= MXC_F_FLC_FLSH_CN_WR;
243 
244     /* Wait until flash operation is complete */
245     while (flc->flsh_cn & (MXC_F_FLC_FLSH_CN_WR | MXC_F_FLC_FLSH_CN_ME | MXC_F_FLC_FLSH_CN_PGE)) {}
246 
247     /* Lock flash */
248     flc->flsh_cn &= ~MXC_F_FLC_FLSH_CN_UNLOCK;
249 
250     /* Check access violations */
251     if (flc->flsh_int & MXC_F_FLC_FLSH_INT_AF) {
252         flc->flsh_int &= ~MXC_F_FLC_FLSH_INT_AF;
253         return E_BAD_STATE;
254     }
255 
256     // Flush the cache
257     MXC_FLC_Flash_Operation();
258 
259     if ((err = MXC_FLC_Com_VerifyData(address, 1, &data)) != E_NO_ERROR) {
260         return err;
261     }
262 
263     return E_NO_ERROR;
264 }
265 
266 //******************************************************************************
MXC_FLC_Write(uint32_t address,uint32_t length,uint32_t * buffer)267 int MXC_FLC_Write(uint32_t address, uint32_t length, uint32_t *buffer)
268 {
269     return MXC_FLC_Com_Write(address, length, buffer);
270 }
271 
272 //******************************************************************************
MXC_FLC_Read(int address,void * buffer,int len)273 void MXC_FLC_Read(int address, void *buffer, int len)
274 {
275     MXC_FLC_Com_Read(address, buffer, len);
276 }
277 
278 //******************************************************************************
MXC_FLC_EnableInt(uint32_t flags)279 int MXC_FLC_EnableInt(uint32_t flags)
280 {
281     return MXC_FLC_RevA_EnableInt(flags);
282 }
283 
284 //******************************************************************************
MXC_FLC_DisableInt(uint32_t flags)285 int MXC_FLC_DisableInt(uint32_t flags)
286 {
287     return MXC_FLC_RevA_DisableInt(flags);
288 }
289 
290 //******************************************************************************
MXC_FLC_GetFlags(void)291 int MXC_FLC_GetFlags(void)
292 {
293     return MXC_FLC_RevA_GetFlags();
294 }
295 
296 //******************************************************************************
MXC_FLC_ClearFlags(uint32_t flags)297 int MXC_FLC_ClearFlags(uint32_t flags)
298 {
299     return MXC_FLC_RevA_ClearFlags(flags);
300 }
301 
302 //******************************************************************************
MXC_FLC_UnlockInfoBlock(uint32_t address)303 int MXC_FLC_UnlockInfoBlock(uint32_t address)
304 {
305     int err;
306     mxc_flc_regs_t *flc;
307 
308     if ((err = MXC_FLC_GetByAddress(&flc, address)) != E_NO_ERROR) {
309         return err;
310     }
311 
312     return MXC_FLC_RevA_UnlockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
313 }
314 
315 //******************************************************************************
MXC_FLC_LockInfoBlock(uint32_t address)316 int MXC_FLC_LockInfoBlock(uint32_t address)
317 {
318     int err;
319     mxc_flc_regs_t *flc;
320 
321     if ((err = MXC_FLC_GetByAddress(&flc, address)) != E_NO_ERROR) {
322         return err;
323     }
324 
325     return MXC_FLC_RevA_LockInfoBlock((mxc_flc_reva_regs_t *)flc, address);
326 }
327 
328 //******************************************************************************
329 #if IAR_PRAGMAS
330 #pragma section = ".flashprog"
331 #else
332 __attribute__((section(".flashprog")))
333 #endif
334 // make sure to disable ICC with ICC_Disable(); before Running this function
MXC_FLC_Write_Encrypted(uint32_t address,uint32_t length,uint32_t * buffer)335 int MXC_FLC_Write_Encrypted(uint32_t address, uint32_t length, uint32_t *buffer)
336 {
337     int err;
338     uint32_t encrypted_buffer[4];
339 
340     // Address checked if it is 128-bit aligned
341     if (address & 0xF) {
342         return E_BAD_PARAM;
343     }
344 
345     // Length checked if it is a multiple of 128-bits.
346     if (length & 0x3) {
347         return E_BAD_PARAM;
348     }
349 
350     // Initialize crypto and AES engine.
351     mxc_aes_init();
352 
353     while (length >= 16) {
354         // Encrypt 128-bits of buffer, output to encrypted_buffer
355         if ((err = mxc_encrypt_sequence((uint8_t *)buffer, (uint8_t *)encrypted_buffer, address,
356                                         16)) != E_NO_ERROR) {
357             return err;
358         }
359 
360         if ((err = MXC_FLC_Write128(address, encrypted_buffer)) != E_NO_ERROR) {
361             /* NOTE: FLC_Write128() does not know how to verify writes. */
362             /* Ignore E_BAD_STATE errors, we will do our own verify. */
363             if (err != E_BAD_STATE) {
364                 return err;
365             }
366         }
367 
368         /* Verify read data vs. plaintext buffer. */
369         if ((err = MXC_FLC_Com_VerifyData(address, 4, buffer)) != E_NO_ERROR) {
370             return err;
371         }
372 
373         address += 16;
374         length -= 16;
375         buffer += 4;
376     }
377 
378     return E_NO_ERROR;
379 }
380 
381 //******************************************************************************
382 #if IAR_PRAGMAS
383 #pragma section = ".flashprog"
384 #else
385 __attribute__((section(".flashprog")))
386 #endif
mxc_aes_init(void)387 static void mxc_aes_init(void)
388 {
389     // Make sure CTB clocks are enabled
390     MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_CTB);
391 
392     // Reset Crypto block and clear state
393     MXC_CTB->crypto_ctrl = MXC_F_CTB_CRYPTO_CTRL_RST;
394 
395     // Set the legacy bit
396     MXC_CTB->crypto_ctrl |= MXC_F_CTB_CRYPTO_CTRL_FLAG_MODE;
397 
398     // Byte swap the input and output
399     MXC_CTB->crypto_ctrl |= MXC_F_CTB_CRYPTO_CTRL_BSO;
400     MXC_CTB->crypto_ctrl |= MXC_F_CTB_CRYPTO_CTRL_BSI;
401 }
402 
403 //******************************************************************************
404 #if IAR_PRAGMAS
405 #pragma section = ".flashprog"
406 #else
407 __attribute__((section(".flashprog")))
408 #endif
mxc_encrypt_sequence(const uint8_t * pt,uint8_t * ct,uint32_t addr,int len)409 static int mxc_encrypt_sequence(const uint8_t *pt, uint8_t *ct, uint32_t addr, int len)
410 {
411     uint8_t pt_buf[16];
412     uint8_t ct_buf[16];
413 
414     int i, j;
415 
416     // Check input length for multiple of 16 bytes (one AES block size)
417     if (len & 0x0F) {
418         return E_BAD_PARAM;
419     }
420 
421     for (j = 0; j < len; j += 16) {
422         // XOR with the address
423         uint32_t xor_addr = addr + j;
424 
425         for (i = 0; i < 16; i += 4) {
426             pt_buf[i + 0] = pt[j + i + 0] ^ (((xor_addr + i) >> 0) & 0xFF);
427             pt_buf[i + 1] = pt[j + i + 1] ^ (((xor_addr + i) >> 8) & 0xFF);
428             pt_buf[i + 2] = pt[j + i + 2] ^ (((xor_addr + i) >> 16) & 0xFF);
429             pt_buf[i + 3] = pt[j + i + 3];
430         }
431 
432         // Clear interrupt flags
433         MXC_CTB->crypto_ctrl |= MXC_F_CTB_CRYPTO_CTRL_CPH_DONE;
434 
435         // ECB, AES-128, encrypt
436         MXC_CTB->cipher_ctrl =
437             ((0x0 << MXC_F_CTB_CIPHER_CTRL_MODE_POS) | (1 << MXC_F_CTB_CIPHER_CTRL_CIPHER_POS) |
438              (0 << MXC_F_CTB_CIPHER_CTRL_ENC_POS));
439 
440         // Set the key source
441         MXC_CTB->cipher_ctrl = ((MXC_CTB->cipher_ctrl & ~MXC_F_CTB_CIPHER_CTRL_SRC) |
442                                 (0x3 << MXC_F_CTB_CIPHER_CTRL_SRC_POS));
443 
444         // Copy data to start the operation
445         memcpy((void *)&MXC_CTB->crypto_din[0], (void *)(pt_buf), 16);
446 
447         // Wait until operation is complete
448         while (!(MXC_CTB->crypto_ctrl & MXC_F_CTB_CRYPTO_CTRL_CPH_DONE)) {}
449 
450         // Copy the data out
451         memcpy((void *)(ct_buf), (void *)&MXC_CTB->crypto_dout[0], 16);
452 
453         // Put the bytes in the ct buffer
454         for (i = 0; i < 16; i += 4) {
455             ct[j + i + 0] = ct_buf[i + 0];
456             ct[j + i + 1] = ct_buf[i + 1];
457             ct[j + i + 2] = ct_buf[i + 2];
458             ct[j + i + 3] = ct_buf[i + 3];
459         }
460     }
461 
462     return E_NO_ERROR;
463 }
464 
465 //******************************************************************************
MXC_FLC_BlockPageWrite(uint32_t address)466 int MXC_FLC_BlockPageWrite(uint32_t address)
467 {
468     /* MAX32520 does not support flash page read and write locks */
469     return E_NOT_SUPPORTED;
470 }
471 
472 //******************************************************************************
MXC_FLC_BlockPageRead(uint32_t address)473 int MXC_FLC_BlockPageRead(uint32_t address)
474 {
475     /* MAX32520 does not support flash page read and write locks */
476     return E_NOT_SUPPORTED;
477 }
478 
479 //******************************************************************************
MXC_FLC_GetWELR(uint32_t address,uint32_t page_num)480 volatile uint32_t *MXC_FLC_GetWELR(uint32_t address, uint32_t page_num)
481 {
482     /* MAX32520 does not support flash page read and write locks */
483     return NULL;
484 }
485 
486 //******************************************************************************
MXC_FLC_GetRLR(uint32_t address,uint32_t page_num)487 volatile uint32_t *MXC_FLC_GetRLR(uint32_t address, uint32_t page_num)
488 {
489     /* MAX32520 does not support flash page read and write locks */
490     return NULL;
491 }
492