1 /*
2 * Copyright 2022, 2024 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7 #include <string.h>
8 #include "board.h"
9 #include "fsl_lpspi_nor_flash.h"
10 #include "fsl_nor_flash.h"
11 #include "fsl_lpspi_mem_adapter.h"
12
13 /*******************************************************************************
14 * Definitions
15 ******************************************************************************/
16
17 /*******************************************************************************
18 * Prototypes
19 ******************************************************************************/
20 extern uint32_t BOARD_GetLpspiClock(void);
21 extern uint32_t BOARD_GetNorFlashBaudrate(void);
22 extern LPSPI_Type *BOARD_GetLpspiForNorFlash(void);
23 /*******************************************************************************
24 * Variables
25 ******************************************************************************/
26
27 /*******************************************************************************
28 * Code
29 ******************************************************************************/
30 /*!
31 * @brief Initialize NOR FLASH devices.
32 *
33 * This function initialize NOR Flash controller and NOR Flash.
34 *
35 * @param config NOR flash configuration.
36 * The "memControlConfig" and "driverBaseAddr" are controller specific structure.
37 * please set those two parameter with your Nand controller configuration structure type pointer.
38 * such as for SEMC:
39 *
40 * spifi_mem_nor_config_t spifiNorconfig =
41 * {
42 * .....
43 * }
44 * nor_config_t config =
45 * {
46 * .memControlConfig = (void *)\&spifiNorconfig;
47 * .driverBaseAddr = (void *)SPIFI0;
48 * }
49 * @param handle The NOR Flash handler.
50 * @retval execution status
51 */
Nor_Flash_Init(nor_config_t * config,nor_handle_t * handle)52 status_t Nor_Flash_Init(nor_config_t *config, nor_handle_t *handle)
53 {
54 assert(config);
55 assert(handle);
56
57 uint32_t baudRate = BOARD_GetNorFlashBaudrate();
58 status_t initStatus = kStatus_Fail;
59 lpspi_memory_config_t *memConfig = (lpspi_memory_config_t *)(config->memControlConfig);
60
61 handle->bytesInSectorSize = memConfig->bytesInSectorSize;
62 handle->bytesInPageSize = memConfig->bytesInPageSize;
63 handle->driverBaseAddr = BOARD_GetLpspiForNorFlash();
64
65 do
66 {
67 uint32_t spiClock_Hz = BOARD_GetLpspiClock();
68
69 spi_master_config_t spiMasterCfg;
70 spiMasterCfg.baudRate = baudRate;
71 spiMasterCfg.clockFreq = spiClock_Hz;
72 spiMasterCfg.whichPcs = 0;
73 status_t status = LPSPI_MemInit(&spiMasterCfg, handle->driverBaseAddr);
74 if (status != kStatus_Success)
75 {
76 break;
77 }
78
79 flash_id_t flashId;
80
81 status = LPSPI_MemReadId(&flashId, handle->driverBaseAddr);
82 if (status != kStatus_Success)
83 {
84 break;
85 }
86
87 initStatus = kStatus_Success;
88 } while (false);
89
90 return initStatus;
91 }
92
93 /*!
94 * @brief Read page data from NOR Flash.
95 *
96 * @param handle The NOR Flash handler.
97 * @param address NOR flash start address to read data from.
98 * @param buffer NOR flash buffer to read data to.
99 * @param length NOR flash read length.
100 * @retval execution status
101 */
Nor_Flash_Read(nor_handle_t * handle,uint32_t address,uint8_t * buffer,uint32_t length)102 status_t Nor_Flash_Read(nor_handle_t *handle, uint32_t address, uint8_t *buffer, uint32_t length)
103 {
104 assert(handle);
105
106 status_t readStatus = kStatus_Fail;
107
108 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
109
110 assert(base);
111
112 readStatus = LPSPI_MemRead(address, buffer, length, true, base);
113
114 return readStatus;
115 }
116
117 /*!
118 * @brief Initialize NOR FLASH devices.
119 *
120 * This function initialize NOR Flash controller and NOR Flash.
121 *
122 * @param config NOR flash configuration.
123 * @param handle The NOR Flash handler.
124 * @retval execution status
125 */
Nor_Flash_Initialization(nor_config_t * config,nor_handle_t * handle)126 status_t Nor_Flash_Initialization(nor_config_t *config, nor_handle_t *handle)
127 {
128 return Nor_Flash_Init(config, handle);
129 }
130
131 /*!
132 * @brief Program page data to NOR Flash.
133 *
134 * @param handle The NOR Flash handler.
135 * @param address The address to be programed.
136 * @param buffer The buffer to be programed to the page.
137 * @retval execution status
138 */
Nor_Flash_Page_Program(nor_handle_t * handle,uint32_t address,uint8_t * buffer)139 status_t Nor_Flash_Page_Program(nor_handle_t *handle, uint32_t address, uint8_t *buffer)
140 {
141 assert(handle);
142
143 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
144
145 assert(base);
146
147 status_t status = kStatus_Fail;
148
149 bool blocking = true;
150
151 if (handle->deviceSpecific != NULL)
152 {
153 blocking = (*(bool *)(handle->deviceSpecific));
154 }
155
156 status = LPSPI_MemWritePage(address, buffer, handle->bytesInPageSize, blocking, base);
157
158 return status;
159 }
160
161 /*!
162 * @brief Program data to NOR Flash.
163 *
164 * @param handle The NOR Flash handler.
165 * @param address The address to be programed.
166 * @param buffer The buffer to be programed to the page.
167 * @param length The data length to be programed to the page.
168 * @retval execution status
169 */
Nor_Flash_Program(nor_handle_t * handle,uint32_t address,uint8_t * buffer,uint32_t length)170 status_t Nor_Flash_Program(nor_handle_t *handle, uint32_t address, uint8_t *buffer, uint32_t length)
171 {
172 assert(handle);
173
174 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
175
176 assert(base);
177
178 status_t writeStatus = kStatus_Fail;
179
180 bool blocking = true;
181
182 if (handle->deviceSpecific != NULL)
183 {
184 blocking = (*(bool *)(handle->deviceSpecific));
185 }
186
187 do
188 {
189 while ((address & 0xFFu) + length > 0xFFu)
190 {
191 uint32_t bytes = 0x100u - (address & 0xFFu);
192
193 writeStatus = LPSPI_MemWritePage(address, buffer, bytes, blocking, base);
194 length -= bytes;
195 address += bytes;
196 buffer += bytes;
197
198 if (writeStatus != kStatus_Success)
199 {
200 break;
201 }
202 }
203
204 writeStatus = LPSPI_MemWritePage(address, buffer, length, blocking, base);
205 if (writeStatus != kStatus_Success)
206 {
207 break;
208 }
209 writeStatus = kStatus_Success;
210
211 } while (false);
212
213 return writeStatus;
214 }
215
216 /*!
217 * @brief Erase page.
218 *
219 * @note Not all device support to erase page.
220
221 * @param handle The NOR Flash handler.
222 * @param address The start address to be erased.
223 * @retval execution status
224 */
Nor_Flash_Erase_Page(nor_handle_t * handle,uint32_t address)225 status_t Nor_Flash_Erase_Page(nor_handle_t *handle, uint32_t address)
226 {
227 assert(handle);
228
229 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
230
231 assert(base);
232
233 status_t status = kStatus_Fail;
234
235 bool blocking = true;
236
237 if (handle->deviceSpecific != NULL)
238 {
239 blocking = (*(bool *)(handle->deviceSpecific));
240 }
241
242 status = LPSPI_MemErase(address, kSize_ErasePage, blocking, base);
243
244 return status;
245 }
246
247 /*!
248 * @brief Erase sector.
249 *
250 * @param handle The NOR Flash handler.
251 * @param address The start address to be erased.
252 * @retval execution status
253 */
Nor_Flash_Erase_Sector(nor_handle_t * handle,uint32_t address)254 status_t Nor_Flash_Erase_Sector(nor_handle_t *handle, uint32_t address)
255 {
256 assert(handle);
257
258 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
259
260 assert(base);
261
262 eraseOptions_t tmpEraseOption = kSize_Erase4K;
263 status_t status = kStatus_Fail;
264
265 bool blocking = true;
266
267 if (handle->deviceSpecific != NULL)
268 {
269 blocking = (*(bool *)(handle->deviceSpecific));
270 }
271
272 switch (handle->bytesInSectorSize)
273 {
274 case 4096UL:
275 {
276 tmpEraseOption = kSize_Erase4K;
277 break;
278 }
279 case 32768UL:
280 {
281 tmpEraseOption = kSize_Erase32K;
282 break;
283 }
284 case 65536UL:
285 {
286 tmpEraseOption = kSize_Erase64K;
287 break;
288 }
289 default:
290 {
291 return kStatus_OutOfRange;
292 }
293 }
294 status = LPSPI_MemErase(address, tmpEraseOption, blocking, base);
295
296 return status;
297 }
298
299 /*!
300 * @brief Erase 4K block.
301 *
302 * @param handle The NOR Flash handler.
303 * @param address The start address to be erased.
304 * @retval execution status
305 */
Nor_Flash_Erase_Block_4K(nor_handle_t * handle,uint32_t address)306 status_t Nor_Flash_Erase_Block_4K(nor_handle_t *handle, uint32_t address)
307 {
308 assert(handle);
309
310 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
311
312 assert(base);
313
314 status_t status = kStatus_Fail;
315
316 bool blocking = true;
317
318 if (handle->deviceSpecific != NULL)
319 {
320 blocking = (*(bool *)(handle->deviceSpecific));
321 }
322
323 status = LPSPI_MemErase(address, kSize_Erase4K, blocking, base);
324
325 return status;
326 }
327
328 /*!
329 * @brief Erase 32K block.
330 *
331 * @param handle The NOR Flash handler.
332 * @param address The start address to be erased.
333 * @retval execution status
334 */
Nor_Flash_Erase_Block_32K(nor_handle_t * handle,uint32_t address)335 status_t Nor_Flash_Erase_Block_32K(nor_handle_t *handle, uint32_t address)
336 {
337 assert(handle);
338
339 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
340
341 assert(base);
342
343 status_t status = kStatus_Fail;
344
345 bool blocking = true;
346
347 if (handle->deviceSpecific != NULL)
348 {
349 blocking = (*(bool *)(handle->deviceSpecific));
350 }
351
352 status = LPSPI_MemErase(address, kSize_Erase32K, blocking, base);
353
354 return status;
355 }
356
357 /*!
358 * @brief Erase 64K block.
359 *
360 * @param handle The NOR Flash handler.
361 * @param address The start address to be erased.
362 * @retval execution status
363 */
Nor_Flash_Erase_Block_64K(nor_handle_t * handle,uint32_t address)364 status_t Nor_Flash_Erase_Block_64K(nor_handle_t *handle, uint32_t address)
365 {
366 assert(handle);
367
368 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
369
370 assert(base);
371
372 status_t status = kStatus_Fail;
373
374 bool blocking = true;
375
376 if (handle->deviceSpecific != NULL)
377 {
378 blocking = (*(bool *)(handle->deviceSpecific));
379 }
380
381 status = LPSPI_MemErase(address, kSize_Erase64K, blocking, base);
382
383 return status;
384 }
385
386 /*!
387 * @brief Erase block.
388 *
389 * @param handle The NOR Flash handler.
390 * @param address The start address to be erased.
391 * @retval execution status
392 */
Nor_Flash_Erase_Block(nor_handle_t * handle,uint32_t address)393 status_t Nor_Flash_Erase_Block(nor_handle_t *handle, uint32_t address)
394 {
395 assert(handle);
396
397 status_t status = kStatus_Fail;
398
399 status = Nor_Flash_Erase_Block_4K(handle, address);
400
401 return status;
402 }
403
404 /*!
405 * @brief Erase flash.
406 *
407 * @param handle The NOR Flash handler.
408 * @param address The start address to be erased.
409 * @param size_Byte The size to be erased.
410 * @retval execution status
411 */
Nor_Flash_Erase(nor_handle_t * handle,uint32_t address,uint32_t size_Byte)412 status_t Nor_Flash_Erase(nor_handle_t *handle, uint32_t address, uint32_t size_Byte)
413 {
414 assert(handle);
415
416 status_t status = kStatus_Fail;
417 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
418
419 assert((size_Byte == 256U) || (size_Byte == 4096U) || (size_Byte == 32768U) || (size_Byte == 65536U));
420 assert(base);
421
422 bool blocking = true;
423
424 if (handle->deviceSpecific != NULL)
425 {
426 blocking = (*(bool *)(handle->deviceSpecific));
427 }
428
429 switch (size_Byte)
430 {
431 case 256U:
432 status = LPSPI_MemErase(address, kSize_ErasePage, blocking, base);
433 break;
434 case 4096U:
435 status = LPSPI_MemErase(address, kSize_Erase4K, blocking, base);
436 break;
437 case 32768U:
438 status = LPSPI_MemErase(address, kSize_Erase32K, blocking, base);
439 break;
440 case 65536U:
441 status = LPSPI_MemErase(address, kSize_Erase64K, blocking, base);
442 break;
443 default:
444 /* All the cases have been listed above, the default clause should not be reached. */
445 assert(false);
446 break;
447 }
448
449 return status;
450 }
451
452 /*!
453 * @brief Erase Chip NOR Flash .
454 *
455 * @param handle The NOR Flash handler.
456 * @retval execution status
457 */
Nor_Flash_Erase_Chip(nor_handle_t * handle)458 status_t Nor_Flash_Erase_Chip(nor_handle_t *handle)
459 {
460 assert(handle);
461
462 status_t status = kStatus_Fail;
463
464 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
465
466 assert(base);
467
468 bool blocking = true;
469
470 if (handle->deviceSpecific != NULL)
471 {
472 blocking = (*(bool *)(handle->deviceSpecific));
473 }
474
475 status = LPSPI_MemErase(0x0, kSize_EraseAll, blocking, base);
476
477 return status;
478 }
479
480 /*!
481 * @brief Deinitialize NOR FLASH devices.
482 *
483 * @param handle The NOR Flash handler.
484 * @retval execution status
485 */
Nor_Flash_DeInit(nor_handle_t * handle)486 status_t Nor_Flash_DeInit(nor_handle_t *handle)
487 {
488 assert(handle);
489
490 status_t status = kStatus_Fail;
491
492 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
493
494 assert(base);
495
496 status = LPSPI_MemDeinit(base);
497
498 return status;
499 }
500
501 /*!
502 * @brief Get the busy status of the NOR Flash.
503 *
504 * @param handle The NOR Flash handler.
505 * @retval execution status
506 */
Nor_Flash_Is_Busy(nor_handle_t * handle,bool * isBusy)507 status_t Nor_Flash_Is_Busy(nor_handle_t *handle, bool *isBusy)
508 {
509 assert(handle);
510
511 status_t status = kStatus_Fail;
512
513 LPSPI_Type *base = (LPSPI_Type *)handle->driverBaseAddr;
514
515 assert(base);
516
517 status = LPSPI_MemIsBusy(base, isBusy);
518
519 return status;
520 }
521
Nor_Flash_Enter_Lowpower(nor_handle_t * handle)522 status_t Nor_Flash_Enter_Lowpower(nor_handle_t *handle)
523 {
524 status_t status = kStatus_Fail;
525 bool busy;
526
527 assert(handle);
528
529 do
530 {
531 /* Make sure the flash is not busy */
532 (void)Nor_Flash_Is_Busy(handle, &busy);
533 } while (busy == true);
534
535 status = Nor_Flash_DeInit(handle);
536
537 return status;
538 }
539
Nor_Flash_Exit_Lowpower(nor_handle_t * handle)540 status_t Nor_Flash_Exit_Lowpower(nor_handle_t *handle)
541 {
542 assert(handle);
543
544 uint32_t baudRate = BOARD_GetNorFlashBaudrate();
545 status_t initStatus = kStatus_Fail;
546
547 handle->bytesInSectorSize = 256U;
548 handle->bytesInPageSize = 256U;
549 handle->driverBaseAddr = BOARD_GetLpspiForNorFlash();
550
551 do
552 {
553 uint32_t spiClock_Hz = BOARD_GetLpspiClock();
554
555 spi_master_config_t spiMasterCfg;
556 spiMasterCfg.baudRate = baudRate;
557 spiMasterCfg.clockFreq = spiClock_Hz;
558 spiMasterCfg.whichPcs = 0;
559 status_t status = LPSPI_MemInit(&spiMasterCfg, handle->driverBaseAddr);
560 if (status != kStatus_Success)
561 {
562 break;
563 }
564
565 initStatus = kStatus_Success;
566 } while (false);
567
568 return initStatus;
569 }
570