1 /*
2  * Copyright 2017-2020, 2024 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_flash.h"
12 #include "fsl_cache.h"
13 #include "fsl_flexspi_nor_flash.h"
14 #include "pin_mux.h"
15 
16 #define FLASH_BASE_ADDR 0x80000000UL
17 
18 #if FLASH_USE_CUSTOM_FCB
19 /* fcb for w45q64 */
20 const uint8_t CUSTOM_FCB[] = {
21     0x46, 0x43, 0x46, 0x42, 0x00, 0x04, 0x01, 0x56, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
22     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
25     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x04, 0x18, 0x0a, 0x06,
28     0x32, 0x04, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00,
29     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30     0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
32     0x04, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x04, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x18, 0x08, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37     0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
45     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
48 
49 #endif
50 
51 static flexspi_nor_config_t flashConfig;
52 
53 /* API - initialize 'mflash' */
mflash_drv_init(void)54 int32_t mflash_drv_init(void)
55 {
56     status_t result;
57 
58 #if FLASH_USE_CUSTOM_FCB
59     memcpy(&flashConfig, CUSTOM_FCB, sizeof(flexspi_nor_config_t));
60 #else
61     serial_nor_config_option_t option;
62     option.option0.U = 0xc0000001U;
63     option.option1.U = 0x00000000;
64 
65     result = FLEXSPI_NorFlash_GetConfig(0, &flashConfig, &option);
66     if (result != kStatus_Success)
67     {
68         return result;
69     }
70 #endif
71 
72     result = FLEXSPI_NorFlash_Init(0, &flashConfig);
73     if (result != kStatus_Success)
74     {
75         return result;
76     }
77 
78     return result;
79 }
80 
81 /* API - Erase single sector */
mflash_drv_sector_erase(uint32_t sector_addr)82 int32_t mflash_drv_sector_erase(uint32_t sector_addr)
83 {
84     status_t status;
85     uint32_t primask = __get_PRIMASK();
86 
87     if (0 == mflash_drv_is_sector_aligned(sector_addr))
88         return kStatus_InvalidArgument;
89 
90     __disable_irq();
91 
92     status = FLEXSPI_NorFlash_Erase(0, (flexspi_nor_config_t *)&flashConfig, sector_addr,
93                                   flashConfig.sectorSize);
94 
95     DCACHE_InvalidateByRange(MFLASH_BASE_ADDRESS + sector_addr, MFLASH_SECTOR_SIZE);
96 
97 
98     if (primask == 0U)
99     {
100         __enable_irq();
101     }
102 
103     /* Flush pipeline to allow pending interrupts take place
104      * before starting next loop */
105     __ISB();
106 
107     return status;
108 }
109 
110 /* API - Page program */
mflash_drv_page_program(uint32_t page_addr,uint32_t * data)111 int32_t mflash_drv_page_program(uint32_t page_addr, uint32_t *data)
112 {
113     status_t status;
114     uint32_t primask = __get_PRIMASK();
115 
116     if (0 == mflash_drv_is_page_aligned(page_addr))
117         return kStatus_InvalidArgument;
118 
119     __disable_irq();
120 
121     status = FLEXSPI_NorFlash_ProgramPage(0, &flashConfig, page_addr, (uint32_t *)data);
122 
123     DCACHE_InvalidateByRange(MFLASH_BASE_ADDRESS + page_addr, MFLASH_PAGE_SIZE);
124 
125 
126     if (primask == 0)
127     {
128         __enable_irq();
129     }
130 
131     /* Flush pipeline to allow pending interrupts take place
132      * before starting next loop */
133     __ISB();
134 
135     return status;
136 }
137 
138 /* API - Read data */
mflash_drv_read(uint32_t addr,uint32_t * buffer,uint32_t len)139 int32_t mflash_drv_read(uint32_t addr, uint32_t *buffer, uint32_t len)
140 {
141     memcpy(buffer, (void *)(addr + MFLASH_BASE_ADDRESS), len);
142 
143     return kStatus_Success;
144 }
145 
146 /* API - Get pointer to FLASH region */
mflash_drv_phys2log(uint32_t addr,uint32_t len)147 void *mflash_drv_phys2log(uint32_t addr, uint32_t len)
148 {
149     return (void *)(addr + MFLASH_BASE_ADDRESS);
150 }
151 
152 /* API - Get pointer to FLASH region */
mflash_drv_log2phys(void * ptr,uint32_t len)153 uint32_t mflash_drv_log2phys(void *ptr, uint32_t len)
154 {
155     if ((uint32_t)ptr < MFLASH_BASE_ADDRESS)
156         return kStatus_InvalidArgument;
157 
158     return ((uint32_t)ptr - MFLASH_BASE_ADDRESS);
159 }
160