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_SST26VF064B_H__
18 #define __DRIVER_FLASH_SST26VF064B_H__
19 
20 #include "cmsis_compiler.h"
21 #include "Driver_Flash_Common.h"
22 #include "spi_sst26vf064b_flash_lib.h"
23 
24 /*
25  * ARM FLASH device structure
26  */
27 struct arm_flash_sst26vf064b_flash_dev_t {
28     struct spi_sst26vf064b_dev_t* dev;   /*!< FLASH memory device structure */
29     ARM_FLASH_INFO* data;                /*!< FLASH data */
30     int8_t (*setup_qspi)(struct arm_flash_sst26vf064b_flash_dev_t* dev);
31                                          /*!< Setup flash for QSPI access */
32     int8_t (*release_qspi)(struct arm_flash_sst26vf064b_flash_dev_t* dev);
33                                          /*!< Setup flash for XIP access */
34     const uint32_t memory_base_s;        /*!< FLASH memory base address in
35                                           *   XIP mode, secure alias */
36     const uint32_t memory_base_ns;       /*!< FLASH memory base address in
37                                           *   XIP mode, non-secure alias */
38 };
39 /* Driver Capabilities */
40 static const ARM_FLASH_CAPABILITIES SST26VF064BDriverCapabilities = {
41     0, /* event_ready */
42     0, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
43     1, /* erase_chip */
44     0, /* reserved */
45 };
46 
47 static ARM_FLASH_INFO SST26VF064B_DEV_DATA = {
48     .sector_info    = NULL,     /* Uniform sector layout */
49     .sector_count   = SST26VF064B_FLASH_TOTAL_SIZE /
50                         SST26VF064B_FLASH_SECTOR_SIZE,
51     .sector_size    = SST26VF064B_FLASH_SECTOR_SIZE,
52     .page_size      = SST26VF064B_FLASH_PAGE_SIZE,
53     .program_unit   = SST26VF064B_FLASH_PROGRAM_UNIT,
54     .erased_value   = ARM_FLASH_DRV_ERASE_VALUE
55 };
56 
SST26VF064B_Driver_GetCapabilities(void)57 __STATIC_INLINE ARM_FLASH_CAPABILITIES SST26VF064B_Driver_GetCapabilities(void)
58 {
59     return SST26VF064BDriverCapabilities;
60 }
61 
62 #define SETUP_QSPI(flash_dev)                                            \
63 do {                                                                     \
64     if(flash_dev.setup_qspi != NULL) {                                   \
65         if(flash_dev.setup_qspi(&flash_dev) != 0) {                      \
66             ret = SST26VF064B_ERR_QSPI_SETUP;                            \
67             goto cleanup;                                                \
68         }                                                                \
69     }                                                                    \
70 } while(0)
71 
72 #define RELEASE_QSPI(flash_dev)                                          \
73 do {                                                                     \
74     if(flash_dev.release_qspi != NULL) {                                 \
75         if(flash_dev.release_qspi(&flash_dev) != 0) {                    \
76             /* Should never get there */                                 \
77             __ASM("B .");                                                \
78         }                                                                \
79     }                                                                    \
80 } while(0)
81 
82 /*
83  * \brief Macro for SST26VF064B Flash Driver
84  *
85  * \param[in]  FLASH_DEV          Native driver device
86  *                                \ref arm_flash_sst26vf064b_flash_dev_t
87  * \param[out] FLASH_DRIVER_NAME  Resulting Driver name
88  */
89 #define ARM_FLASH_SST26VF064B(FLASH_DEV, FLASH_DRIVER_NAME)                   \
90 static int32_t FLASH_DRIVER_NAME##_Initialize(                                \
91                                             ARM_Flash_SignalEvent_t cb_event) \
92 {                                                                             \
93     ARG_UNUSED(cb_event);                                                     \
94     enum sst26vf064b_error_t ret = ARM_DRIVER_OK;                             \
95     struct spi_sst26vf064b_dev_t* dev = FLASH_DEV.dev;                        \
96     ARM_FLASH_INFO* data = FLASH_DEV.data;                                    \
97                                                                               \
98     dev->total_sector_cnt = data->sector_count;                               \
99     dev->page_size = data->page_size;                                         \
100     dev->sector_size = data->sector_size;                                     \
101     dev->program_unit = data->program_unit;                                   \
102                                                                               \
103     SETUP_QSPI(FLASH_DEV);                                                    \
104     ret = spi_sst26vf064b_initialize(FLASH_DEV.dev);                          \
105     if (ret != SST26VF064B_ERR_NONE) {                                        \
106         SPI_FLASH_LOG_MSG("%s: Initialization failed.\n\r", __func__);        \
107         goto cleanup;                                                         \
108     }                                                                         \
109                                                                               \
110 cleanup:                                                                      \
111     RELEASE_QSPI(FLASH_DEV);                                                  \
112     if (ret != SST26VF064B_ERR_NONE) {                                        \
113         return ARM_DRIVER_ERROR;                                              \
114     }                                                                         \
115     return ARM_DRIVER_OK;                                                     \
116 }                                                                             \
117                                                                               \
118 static int32_t FLASH_DRIVER_NAME##_ReadData(uint32_t addr,                    \
119                                             void *data,                       \
120                                             uint32_t cnt)                     \
121 {                                                                             \
122     enum sst26vf064b_error_t ret;                                             \
123                                                                               \
124     if (SST26VF064BDriverCapabilities.data_width > 2 ||                       \
125         SST26VF064BDriverCapabilities.data_width < 0)                         \
126     {                                                                         \
127         SPI_FLASH_LOG_MSG("%s: Incorrect data width selected: addr=0x%x\n\r", \
128                           __func__, addr);                                    \
129         ret = SST26VF064B_ERR_WRONG_ARGUMENT;                                 \
130         goto cleanup;                                                         \
131     }                                                                         \
132                                                                               \
133     cnt *= data_width_byte[SST26VF064BDriverCapabilities.data_width];         \
134                                                                               \
135     SETUP_QSPI(FLASH_DEV);                                                    \
136     ret = spi_sst26vf064b_read(FLASH_DEV.dev, addr, (uint8_t*) data, cnt);    \
137     if (ret != SST26VF064B_ERR_NONE) {                                        \
138         SPI_FLASH_LOG_MSG("%s: read failed: addr=0x%x, cnt=%u\n\r",           \
139                           __func__, addr, cnt);                               \
140         goto cleanup;                                                         \
141     }                                                                         \
142                                                                               \
143     cnt /= data_width_byte[SST26VF064BDriverCapabilities.data_width];         \
144                                                                               \
145 cleanup:                                                                      \
146     RELEASE_QSPI(FLASH_DEV);                                                  \
147     if (ret != SST26VF064B_ERR_NONE) {                                        \
148         return ARM_DRIVER_ERROR;                                              \
149     }                                                                         \
150     return cnt;                                                               \
151 }                                                                             \
152                                                                               \
153 static int32_t FLASH_DRIVER_NAME##_ProgramData(uint32_t addr,                 \
154                                                const void *data,              \
155                                                uint32_t cnt)                  \
156 {                                                                             \
157     enum sst26vf064b_error_t ret;                                             \
158                                                                               \
159     if (SST26VF064BDriverCapabilities.data_width > 2 ||                       \
160         SST26VF064BDriverCapabilities.data_width < 0)                         \
161     {                                                                         \
162         SPI_FLASH_LOG_MSG("%s: Incorrect data width selected: addr=0x%x\n\r", \
163                           __func__, addr);                                    \
164         ret = SST26VF064B_ERR_WRONG_ARGUMENT;                                 \
165         goto cleanup;                                                         \
166     }                                                                         \
167                                                                               \
168     cnt *= data_width_byte[SST26VF064BDriverCapabilities.data_width];         \
169                                                                               \
170     SETUP_QSPI(FLASH_DEV);                                                    \
171     ret = spi_sst26vf064b_program(FLASH_DEV.dev, addr, (uint8_t*) data, cnt); \
172     if (ret != SST26VF064B_ERR_NONE) {                                        \
173         SPI_FLASH_LOG_MSG("%s: program failed: addr=0x%x, cnt=%u\n\r",        \
174                           __func__, addr, cnt);                               \
175         goto cleanup;                                                         \
176     }                                                                         \
177                                                                               \
178     cnt /= data_width_byte[SST26VF064BDriverCapabilities.data_width];         \
179                                                                               \
180 cleanup:                                                                      \
181     RELEASE_QSPI(FLASH_DEV);                                                  \
182     if (ret != SST26VF064B_ERR_NONE) {                                        \
183         return ARM_DRIVER_ERROR;                                              \
184     }                                                                         \
185     return cnt;                                                               \
186 }                                                                             \
187                                                                               \
188 static int32_t FLASH_DRIVER_NAME##_EraseSector(uint32_t addr)                 \
189 {                                                                             \
190     enum sst26vf064b_error_t ret;                                             \
191                                                                               \
192     SETUP_QSPI(FLASH_DEV);                                                    \
193     ret = spi_sst26vf064b_erase_sector(FLASH_DEV.dev, addr);                  \
194     if (ret != SST26VF064B_ERR_NONE) {                                        \
195         SPI_FLASH_LOG_MSG("%s: erase failed: addr=0x%x\n\r", __func__, addr); \
196         goto cleanup;                                                         \
197     }                                                                         \
198                                                                               \
199 cleanup:                                                                      \
200     RELEASE_QSPI(FLASH_DEV);                                                  \
201     if (ret != SST26VF064B_ERR_NONE) {                                        \
202         return ARM_DRIVER_ERROR;                                              \
203     }                                                                         \
204     return ARM_DRIVER_OK;                                                     \
205 }                                                                             \
206                                                                               \
207 static int32_t FLASH_DRIVER_NAME##_EraseChip(void)                            \
208 {                                                                             \
209     enum sst26vf064b_error_t ret;                                             \
210                                                                               \
211     SETUP_QSPI(FLASH_DEV);                                                    \
212     ret = spi_sst26vf064b_erase_chip(FLASH_DEV.dev);                          \
213     if (ret != SST26VF064B_ERR_NONE) {                                        \
214         SPI_FLASH_LOG_MSG("%s: erase chip failed\n\r", __func__);             \
215         goto cleanup;                                                         \
216     }                                                                         \
217                                                                               \
218 cleanup:                                                                      \
219     RELEASE_QSPI(FLASH_DEV);                                                  \
220     if (ret != SST26VF064B_ERR_NONE) {                                        \
221         return ARM_DRIVER_ERROR;                                              \
222     }                                                                         \
223     return ARM_DRIVER_OK;                                                     \
224 }                                                                             \
225                                                                               \
226 static ARM_FLASH_INFO * FLASH_DRIVER_NAME##_GetInfo(void)                     \
227 {                                                                             \
228     return FLASH_DEV.data;                                                    \
229 }                                                                             \
230                                                                               \
231 ARM_DRIVER_FLASH FLASH_DRIVER_NAME = {                                        \
232     ARM_Flash_GetVersion,                                                     \
233     SST26VF064B_Driver_GetCapabilities,                                       \
234     FLASH_DRIVER_NAME##_Initialize,                                           \
235     ARM_Flash_Uninitialize,                                                   \
236     ARM_Flash_PowerControl,                                                   \
237     FLASH_DRIVER_NAME##_ReadData,                                             \
238     FLASH_DRIVER_NAME##_ProgramData,                                          \
239     FLASH_DRIVER_NAME##_EraseSector,                                          \
240     FLASH_DRIVER_NAME##_EraseChip,                                            \
241     ARM_Flash_GetStatus,                                                      \
242     FLASH_DRIVER_NAME##_GetInfo                                               \
243 }
244 
245 #endif /* __DRIVER_FLASH_SST26VF064B_H__ */
246