1 /*
2  * Copyright 2017-2020 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdint.h>
8 #include <string.h>
9 
10 #include "mflash_drv.h"
11 #include "fsl_iap.h"
12 #include "pin_mux.h"
13 
14 static flash_config_t g_flash_instance = {0};
15 
16 static uint32_t g_pflashBlockBase  = 0;
17 static uint32_t g_pflashTotalSize  = 0;
18 static uint32_t g_pflashSectorSize = 0;
19 static uint32_t g_pflashPageSize   = 0;
20 
21 /* API - initialize 'mflash' */
mflash_drv_init(void)22 int32_t mflash_drv_init(void)
23 {
24     status_t result;
25 
26     result = FLASH_Init(&g_flash_instance);
27     if (result != kStatus_Success)
28         return result;
29 
30     result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashBlockBaseAddr, &g_pflashBlockBase);
31     if (result != kStatus_Success)
32         return result;
33 
34     result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashSectorSize, &g_pflashSectorSize);
35     if (result != kStatus_Success)
36         return result;
37 
38     result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashTotalSize, &g_pflashTotalSize);
39     if (result != kStatus_Success)
40         return result;
41 
42     result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashPageSize, &g_pflashPageSize);
43 
44     return result;
45 }
46 
47 /* API - Erase single sector */
mflash_drv_sector_erase(uint32_t sector_addr)48 int32_t mflash_drv_sector_erase(uint32_t sector_addr)
49 {
50     if (0 == mflash_drv_is_sector_aligned(sector_addr))
51         return kStatus_InvalidArgument;
52 
53     return FLASH_Erase(&g_flash_instance, sector_addr, MFLASH_SECTOR_SIZE, kFLASH_ApiEraseKey);
54 }
55 
56 /* API - Page program */
mflash_drv_page_program(uint32_t page_addr,uint32_t * data)57 int32_t mflash_drv_page_program(uint32_t page_addr, uint32_t *data)
58 {
59     if (0 == mflash_drv_is_page_aligned(page_addr))
60         return kStatus_InvalidArgument;
61 
62     return FLASH_Program(&g_flash_instance, page_addr, (uint8_t *)data, MFLASH_PAGE_SIZE);
63 }
64 
65 /* Internal - check FLASH status to avoid hardfault */
mflash_drv_is_readable(uint32_t addr)66 int32_t mflash_drv_is_readable(uint32_t addr)
67 {
68 #define FLASH_READMODE_ECC_MASK     (0x4U)
69 #define FLASH_READMODE_ECC_SHIFT    (2U)
70 #define FLASH_READMODE_ECC(x)       (((uint32_t)(((uint32_t)(x)) << FLASH_READMODE_ECC_SHIFT)) & FLASH_READMODE_ECC_MASK)
71 #define FLASH_READMODE_MARGIN_MASK  (0xC00U)
72 #define FLASH_READMODE_MARGIN_SHIFT (10U)
73 #define FLASH_READMODE_MARGIN(x) \
74     (((uint32_t)(((uint32_t)(x)) << FLASH_READMODE_MARGIN_SHIFT)) & FLASH_READMODE_MARGIN_MASK)
75 #define FLASH_READMODE_DMACC_MASK  (0x8000U)
76 #define FLASH_READMODE_DMACC_SHIFT (15U)
77 #define FLASH_READMODE_DMACC(x) \
78     (((uint32_t)(((uint32_t)(x)) << FLASH_READMODE_DMACC_SHIFT)) & FLASH_READMODE_DMACC_MASK)
79 
80     uint32_t result = 0, result_mask = 0;
81 
82     FLASH->INT_CLR_STATUS = FLASH_INT_CLR_STATUS_FAIL_MASK | FLASH_INT_CLR_STATUS_ERR_MASK |
83                             FLASH_INT_CLR_STATUS_DONE_MASK | FLASH_INT_CLR_STATUS_ECC_ERR_MASK;
84     FLASH->STARTA   = addr >> 4;
85     FLASH->DATAW[0] = FLASH_READMODE_ECC(g_flash_instance.modeConfig.readSingleWord.readWithEccOff) |
86                       FLASH_READMODE_MARGIN(g_flash_instance.modeConfig.readSingleWord.readMarginLevel) |
87                       FLASH_READMODE_DMACC(g_flash_instance.modeConfig.readSingleWord.readDmaccWord);
88     FLASH->CMD = 3;
89     while (!(FLASH->INT_STATUS & FLASH_INT_STATUS_DONE_MASK))
90         ;
91     result = FLASH->INT_STATUS;
92 
93     /* Report failure in case of errors */
94     result_mask = FLASH_INT_STATUS_FAIL_MASK | FLASH_INT_STATUS_ERR_MASK | FLASH_INT_STATUS_ECC_ERR_MASK;
95     if (result_mask & result)
96         return kStatus_Fail;
97 
98     return kStatus_Success;
99 }
100 
101 /* API - Read data */
mflash_drv_read(uint32_t addr,uint32_t * buffer,uint32_t len)102 int32_t mflash_drv_read(uint32_t addr, uint32_t *buffer, uint32_t len)
103 {
104     if (mflash_drv_is_readable(addr) != 0)
105         return kStatus_Fail;
106 
107     memcpy(buffer, (void *)addr, len);
108 
109     return kStatus_Success;
110 }
111 
112 /* API - Get pointer to FLASH region */
mflash_drv_phys2log(uint32_t addr,uint32_t len)113 void *mflash_drv_phys2log(uint32_t addr, uint32_t len)
114 {
115 #if 0
116     if (mflash_drv_is_readable(addr) != 0)
117         return NULL;
118 #endif
119 
120     /* FLASH is directly mapped in the address space */
121     return (void *)(addr);
122 }
123 
124 /* API - Get pointer to FLASH region */
mflash_drv_log2phys(void * ptr,uint32_t len)125 uint32_t mflash_drv_log2phys(void *ptr, uint32_t len)
126 {
127     /* FLASH is directly mapped in the address space */
128     return ((uint32_t)ptr);
129 }
130