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