1 /*
2  * Copyright (c) 2023 Arm Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef __DRIVER_FLASH_N25Q256A_H__
18 #define __DRIVER_FLASH_N25Q256A_H__
19 
20 #include "Driver_Flash_Common.h"
21 #include "spi_n25q256a_flash_lib.h"
22 
23 /*
24  * ARM FLASH device structure
25  */
26 struct arm_n25q256a_flash_dev_t {
27     struct spi_n25q256a_dev_t *dev;         /*!< FLASH memory device structure */
28     ARM_FLASH_INFO *data;                   /*!< FLASH data */
29 };
30 
31 /* Driver Capabilities */
32 static const ARM_FLASH_CAPABILITIES N25Q256ADriverCapabilities = {
33     0, /* event_ready */
34     0, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
35     1  /* erase_chip */
36 };
37 
38 static ARM_FLASH_INFO N25Q256A_DEV_DATA = {
39     .sector_info    = NULL,     /* Uniform sector layout */
40     .sector_count   = PMOD_SF3_FLASH_TOTAL_SIZE / PMOD_SF3_FLASH_SECTOR_SIZE,
41     .sector_size    = PMOD_SF3_FLASH_SECTOR_SIZE,
42     .page_size      = PMOD_SF3_FLASH_PAGE_SIZE,
43     .program_unit   = PMOD_SF3_FLASH_PROGRAM_UNIT,
44     .erased_value   = ARM_FLASH_DRV_ERASE_VALUE
45 };
46 
N25Q256A_Driver_GetCapabilities(void)47 static inline ARM_FLASH_CAPABILITIES N25Q256A_Driver_GetCapabilities(void)
48 {
49     return N25Q256ADriverCapabilities;
50 }
51 
52 /*
53  * \brief Macro for N25Q256A Flash Driver
54  *
55  * \param[in]  FLASH_DEV          Native driver device
56  *                                \ref arm_n25q256a_flash_dev_t
57  * \param[out] FLASH_DRIVER_NAME  Resulting Driver name
58  */
59 #define ARM_FLASH_N25Q256A(FLASH_DEV, FLASH_DRIVER_NAME)                      \
60 static int32_t FLASH_DRIVER_NAME##_Initialize(                                \
61                                             ARM_Flash_SignalEvent_t cb_event) \
62 {                                                                             \
63     ARG_UNUSED(cb_event);                                                     \
64     enum n25q256a_error_t ret;                                                \
65     struct spi_n25q256a_dev_t* dev = FLASH_DEV.dev;                           \
66     ARM_FLASH_INFO* data = FLASH_DEV.data;                                    \
67                                                                               \
68     dev->total_sector_cnt = data->sector_count;                               \
69     dev->page_size = data->page_size;                                         \
70     dev->sector_size = data->sector_size;                                     \
71     dev->program_unit = data->program_unit;                                   \
72                                                                               \
73     ret = spi_n25q256a_initialize(FLASH_DEV.dev);                             \
74     if (ret != N25Q256A_ERR_NONE) {                                           \
75         SPI_FLASH_LOG_MSG("%s: Initialization failed.\n\r", __func__);        \
76         return ARM_DRIVER_ERROR;                                              \
77     }                                                                         \
78                                                                               \
79     return ARM_DRIVER_OK;                                                     \
80 }                                                                             \
81                                                                               \
82 static int32_t FLASH_DRIVER_NAME##_Uninitialize(void)                         \
83 {                                                                             \
84     spi_n25q256a_uninitialize(FLASH_DEV.dev);                                 \
85     return ARM_DRIVER_OK;                                                     \
86 }                                                                             \
87                                                                               \
88 static int32_t FLASH_DRIVER_NAME##_ReadData(uint32_t addr,                    \
89                                             void *data,                       \
90                                             uint32_t cnt)                     \
91 {                                                                             \
92     enum n25q256a_error_t ret;                                                \
93                                                                               \
94     if (N25Q256ADriverCapabilities.data_width > 2 ||                          \
95         N25Q256ADriverCapabilities.data_width < 0)                            \
96     {                                                                         \
97         SPI_FLASH_LOG_MSG("%s: Incorrect data width selected: addr=0x%x\n\r", \
98                           __func__,                                           \
99                           addr);                                              \
100         return ARM_DRIVER_ERROR;                                              \
101     }                                                                         \
102                                                                               \
103     cnt *= data_width_byte[N25Q256ADriverCapabilities.data_width];            \
104                                                                               \
105     ret = spi_n25q256a_read(FLASH_DEV.dev, addr, (uint8_t*) data, cnt);       \
106     if (ret != N25Q256A_ERR_NONE) {                                           \
107         SPI_FLASH_LOG_MSG("%s: read failed: addr=0x%x, cnt=%u\n\r",           \
108                           __func__,                                           \
109                           addr,                                               \
110                           cnt);                                               \
111         return ARM_DRIVER_ERROR;                                              \
112     }                                                                         \
113                                                                               \
114     cnt /= data_width_byte[N25Q256ADriverCapabilities.data_width];            \
115                                                                               \
116     return cnt;                                                               \
117 }                                                                             \
118                                                                               \
119 static int32_t FLASH_DRIVER_NAME##_ProgramData(uint32_t addr,                 \
120                                                const void *data,              \
121                                                uint32_t cnt)                  \
122 {                                                                             \
123     enum n25q256a_error_t ret;                                                \
124                                                                               \
125     if (N25Q256ADriverCapabilities.data_width > 2 ||                          \
126         N25Q256ADriverCapabilities.data_width < 0)                            \
127     {                                                                         \
128         SPI_FLASH_LOG_MSG("%s: Incorrect data width selected: addr=0x%x\n\r", \
129                           __func__,                                           \
130                           addr);                                              \
131         return ARM_DRIVER_ERROR;                                              \
132     }                                                                         \
133                                                                               \
134     cnt *= data_width_byte[N25Q256ADriverCapabilities.data_width];            \
135                                                                               \
136     ret = spi_n25q256a_program(FLASH_DEV.dev, addr, (uint8_t*) data, cnt);    \
137     if (ret != N25Q256A_ERR_NONE) {                                           \
138         SPI_FLASH_LOG_MSG("%s: program failed: addr=0x%x, cnt=%u\n\r",        \
139                           __func__,                                           \
140                           addr,                                               \
141                           cnt);                                               \
142         return ARM_DRIVER_ERROR;                                              \
143     }                                                                         \
144                                                                               \
145     cnt /= data_width_byte[N25Q256ADriverCapabilities.data_width];            \
146                                                                               \
147     return cnt;                                                               \
148 }                                                                             \
149                                                                               \
150 static int32_t FLASH_DRIVER_NAME##_EraseSector(uint32_t addr)                 \
151 {                                                                             \
152     enum n25q256a_error_t ret;                                                \
153                                                                               \
154     ret = spi_n25q256a_erase(FLASH_DEV.dev, addr);                            \
155     if (ret != N25Q256A_ERR_NONE) {                                           \
156         SPI_FLASH_LOG_MSG("%s: erase failed: addr=0x%x\n\r", __func__, addr); \
157         return ARM_DRIVER_ERROR;                                              \
158     }                                                                         \
159                                                                               \
160     return ARM_DRIVER_OK;                                                     \
161 }                                                                             \
162                                                                               \
163 static int32_t FLASH_DRIVER_NAME##_EraseChip(void)                            \
164 {                                                                             \
165     enum n25q256a_error_t ret;                                                \
166                                                                               \
167     ret = spi_n25q256a_erase_chip(FLASH_DEV.dev);                             \
168     if (ret != N25Q256A_ERR_NONE) {                                           \
169         SPI_FLASH_LOG_MSG("%s: erase chip failed\n\r", __func__);             \
170         return ARM_DRIVER_ERROR;                                              \
171     }                                                                         \
172                                                                               \
173     return ARM_DRIVER_OK;                                                     \
174 }                                                                             \
175                                                                               \
176 static ARM_FLASH_INFO * FLASH_DRIVER_NAME##_GetInfo(void)                     \
177 {                                                                             \
178     return FLASH_DEV.data;                                                    \
179 }                                                                             \
180                                                                               \
181 ARM_DRIVER_FLASH FLASH_DRIVER_NAME = {                                        \
182     ARM_Flash_GetVersion,                                                     \
183     N25Q256A_Driver_GetCapabilities,                                          \
184     FLASH_DRIVER_NAME##_Initialize,                                           \
185     FLASH_DRIVER_NAME##_Uninitialize,                                         \
186     ARM_Flash_PowerControl,                                                   \
187     FLASH_DRIVER_NAME##_ReadData,                                             \
188     FLASH_DRIVER_NAME##_ProgramData,                                          \
189     FLASH_DRIVER_NAME##_EraseSector,                                          \
190     FLASH_DRIVER_NAME##_EraseChip,                                            \
191     ARM_Flash_GetStatus,                                                      \
192     FLASH_DRIVER_NAME##_GetInfo                                               \
193 }
194 
195 #endif /* __DRIVER_FLASH_N25Q256A_H__ */
196