1 /*
2 * Copyright (c) 2013-2018 Arm Limited. All rights reserved.
3 * Copyright (c) 2021 Laird Connectivity. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the License); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include <Driver_Flash.h>
21 #include <RTE_Device.h>
22 #include <flash_layout.h>
23 #include <string.h>
24 #include <nrfx_qspi.h>
25
26 #ifndef ARG_UNUSED
27 #define ARG_UNUSED(arg) (void)arg
28 #endif
29
30 #define ARM_FLASH_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0)
31 #define QSPI_MIN_READ_SIZE 4
32 #define QSPI_READ_SIZE_ALIGNMENT 4
33 #define QSPI_READ_BUFFER_SIZE 512
34
35 #if RTE_QSPI0
36
37 /**
38 * Data width values for ARM_FLASH_CAPABILITIES::data_width
39 * \ref ARM_FLASH_CAPABILITIES
40 */
41 enum {
42 DATA_WIDTH_8BIT = 0u,
43 DATA_WIDTH_16BIT,
44 DATA_WIDTH_32BIT,
45 DATA_WIDTH_ENUM_SIZE
46 };
47
48 static const uint32_t data_width_byte[DATA_WIDTH_ENUM_SIZE] = {
49 sizeof(uint8_t),
50 sizeof(uint16_t),
51 sizeof(uint32_t),
52 };
53
54 static const ARM_DRIVER_VERSION DriverVersion = {
55 ARM_FLASH_API_VERSION,
56 ARM_FLASH_DRV_VERSION
57 };
58
59 static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
60 .event_ready = 0,
61 .data_width = DATA_WIDTH_32BIT,
62 .erase_chip = 0
63 };
64
65 static ARM_FLASH_INFO FlashInfo = {
66 .sector_info = NULL, /* Uniform sector layout */
67 .sector_count = QSPI_FLASH_TOTAL_SIZE / QSPI_FLASH_AREA_IMAGE_SECTOR_SIZE,
68 .sector_size = QSPI_FLASH_AREA_IMAGE_SECTOR_SIZE,
69 .page_size = 256,
70 .program_unit = sizeof(uint32_t), /* 32-bit word = 4 bytes */
71 .erased_value = 0xFF
72 };
73
74 static const nrfx_qspi_config_t pQSPIConf = NRFX_QSPI_DEFAULT_CONFIG(RTE_QSPI0_SCL_PIN,
75 RTE_QSPI0_CSN_PIN,
76 RTE_QSPI0_IO0_PIN,
77 RTE_QSPI0_IO1_PIN,
78 RTE_QSPI0_IO2_PIN,
79 RTE_QSPI0_IO3_PIN);
80
81 static bool bQSPIInit = false;
82
83 __ALIGN(4) uint8_t baTmpRAMBuffer[QSPI_READ_BUFFER_SIZE];
84
is_range_valid(uint32_t addr,uint32_t cnt)85 static bool is_range_valid(uint32_t addr, uint32_t cnt)
86 {
87 if (addr > QSPI_FLASH_TOTAL_SIZE) {
88 return false;
89 }
90
91 if (cnt > (QSPI_FLASH_TOTAL_SIZE - addr)) {
92 return false;
93 }
94
95 return true;
96 }
97
ARM_QSPI_Flash_GetVersion(void)98 static ARM_DRIVER_VERSION ARM_QSPI_Flash_GetVersion(void)
99 {
100 return DriverVersion;
101 }
102
ARM_QSPI_Flash_GetCapabilities(void)103 static ARM_FLASH_CAPABILITIES ARM_QSPI_Flash_GetCapabilities(void)
104 {
105 return DriverCapabilities;
106 }
107
ARM_QSPI_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)108 static int32_t ARM_QSPI_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)
109 {
110 ARG_UNUSED(cb_event);
111
112 if (bQSPIInit == false)
113 {
114 if (nrfx_qspi_init(&pQSPIConf, NULL, NULL) != NRFX_SUCCESS)
115 {
116 return ARM_DRIVER_ERROR_PARAMETER;
117 }
118
119 bQSPIInit = true;
120 }
121
122 return ARM_DRIVER_OK;
123 }
124
ARM_QSPI_Flash_Uninitialize(void)125 static int32_t ARM_QSPI_Flash_Uninitialize(void)
126 {
127 if (bQSPIInit == true)
128 {
129 nrfx_qspi_uninit();
130 bQSPIInit = false;
131 }
132
133 /* Clear the QSPI read buffer to prevent information leakage */
134 memset(baTmpRAMBuffer, 0, sizeof(baTmpRAMBuffer));
135
136 return ARM_DRIVER_OK;
137 }
138
ARM_QSPI_Flash_PowerControl(ARM_POWER_STATE state)139 static int32_t ARM_QSPI_Flash_PowerControl(ARM_POWER_STATE state)
140 {
141 switch (state) {
142 case ARM_POWER_FULL:
143 /* Nothing to be done */
144 return ARM_DRIVER_OK;
145
146 case ARM_POWER_OFF:
147 case ARM_POWER_LOW:
148 default:
149 return ARM_DRIVER_ERROR_UNSUPPORTED;
150 }
151 }
152
ARM_QSPI_Flash_ReadData(uint32_t addr,void * data,uint32_t cnt)153 static int32_t ARM_QSPI_Flash_ReadData(uint32_t addr, void *data, uint32_t cnt)
154 {
155 uint32_t data_index = 0;
156 uint8_t *buffer = (uint8_t *)data;
157
158 /* Conversion between data items and bytes */
159 uint32_t bytes = cnt * data_width_byte[DriverCapabilities.data_width];
160
161 if ((addr % QSPI_READ_SIZE_ALIGNMENT) != 0)
162 {
163 /* Read beginning part prior to requested data which is before the word boundary */
164 uint8_t off_by = (addr % QSPI_READ_SIZE_ALIGNMENT);
165 uint8_t needed = QSPI_READ_SIZE_ALIGNMENT - off_by;
166 uint32_t read_pos = addr - off_by;
167
168 if (nrfx_qspi_read(baTmpRAMBuffer, QSPI_MIN_READ_SIZE, read_pos) != NRFX_SUCCESS)
169 {
170 return ARM_DRIVER_ERROR_PARAMETER;
171 }
172
173 memcpy(&buffer[data_index], &baTmpRAMBuffer[off_by], needed);
174 data_index += needed;
175 addr += needed;
176 bytes -= needed;
177 }
178
179 while (bytes > 0)
180 {
181 /* Read in chunks of data to the temporary buffer and copy to the supplied buffer */
182 uint32_t read_size = sizeof(baTmpRAMBuffer);
183 uint32_t save_size = read_size;
184 if (bytes < read_size)
185 {
186 read_size = bytes;
187 save_size = bytes;
188
189 if ((read_size % QSPI_READ_SIZE_ALIGNMENT) != 0)
190 {
191 /* Ensure read size is a multiple of the word size */
192 read_size += QSPI_READ_SIZE_ALIGNMENT - (read_size % QSPI_READ_SIZE_ALIGNMENT);
193 }
194 }
195
196 if (nrfx_qspi_read(baTmpRAMBuffer, read_size, addr) != NRFX_SUCCESS)
197 {
198 return ARM_DRIVER_ERROR_PARAMETER;
199 }
200
201 memcpy(&buffer[data_index], baTmpRAMBuffer, save_size);
202 data_index += save_size;
203 addr += save_size;
204 bytes -= save_size;
205 }
206
207 return cnt;
208 }
209
ARM_QSPI_Flash_ProgramData(uint32_t addr,const void * data,uint32_t cnt)210 static int32_t ARM_QSPI_Flash_ProgramData(uint32_t addr, const void *data,
211 uint32_t cnt)
212 {
213 uint32_t err;
214
215 /* Conversion between data items and bytes */
216 uint32_t bytes = cnt * data_width_byte[DriverCapabilities.data_width];
217
218 /* Only aligned writes of full 32-bit words are allowed. */
219 if (addr % sizeof(uint32_t)) {
220 return ARM_DRIVER_ERROR_PARAMETER;
221 }
222
223 if (!is_range_valid(addr, bytes)) {
224 return ARM_DRIVER_ERROR_PARAMETER;
225 }
226
227 if (!nrfx_is_in_ram(data))
228 {
229 /* Not in RAM, copy to RAM so it can be written to QSPI */
230 __ALIGN(4) uint8_t baRAMDataBuffer[bytes];
231 memcpy(baRAMDataBuffer, data, bytes);
232 err = nrfx_qspi_write(baRAMDataBuffer, bytes, addr);
233 }
234 else
235 {
236 err = nrfx_qspi_write(data, bytes, addr);
237 }
238
239 if (err != NRFX_SUCCESS)
240 {
241 return ARM_DRIVER_ERROR;
242 }
243
244 return cnt;
245 }
246
ARM_QSPI_Flash_EraseSector(uint32_t addr)247 static int32_t ARM_QSPI_Flash_EraseSector(uint32_t addr)
248 {
249 nrfx_err_t err_code;
250
251 if (!is_range_valid(addr, QSPI_FLASH_AREA_IMAGE_SECTOR_SIZE)) {
252 return ARM_DRIVER_ERROR_PARAMETER;
253 }
254
255 err_code = nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, addr);
256
257 if (err_code != NRFX_SUCCESS) {
258 return ARM_DRIVER_ERROR;
259 }
260
261 return ARM_DRIVER_OK;
262 }
263
ARM_QSPI_Flash_EraseChip(void)264 static int32_t ARM_QSPI_Flash_EraseChip(void)
265 {
266 return ARM_DRIVER_ERROR_UNSUPPORTED;
267 }
268
ARM_QSPI_Flash_GetStatus(void)269 static ARM_FLASH_STATUS ARM_QSPI_Flash_GetStatus(void)
270 {
271 ARM_FLASH_STATUS status = {
272 .busy = (nrfx_qspi_mem_busy_check() == NRFX_SUCCESS)
273 };
274
275 return status;
276 }
277
ARM_QSPI_Flash_GetInfo(void)278 static ARM_FLASH_INFO * ARM_QSPI_Flash_GetInfo(void)
279 {
280 return &FlashInfo;
281 }
282
283 ARM_DRIVER_FLASH Driver_FLASH1 = {
284 .GetVersion = ARM_QSPI_Flash_GetVersion,
285 .GetCapabilities = ARM_QSPI_Flash_GetCapabilities,
286 .Initialize = ARM_QSPI_Flash_Initialize,
287 .Uninitialize = ARM_QSPI_Flash_Uninitialize,
288 .PowerControl = ARM_QSPI_Flash_PowerControl,
289 .ReadData = ARM_QSPI_Flash_ReadData,
290 .ProgramData = ARM_QSPI_Flash_ProgramData,
291 .EraseSector = ARM_QSPI_Flash_EraseSector,
292 .EraseChip = ARM_QSPI_Flash_EraseChip,
293 .GetStatus = ARM_QSPI_Flash_GetStatus,
294 .GetInfo = ARM_QSPI_Flash_GetInfo
295 };
296
297 #endif /* RTE_QSPI0 */
298