1 /*
2 * Copyright (c) 2013-2021 ARM Limited. All rights reserved.
3 * Copyright (c) 2019, Cypress Semiconductor Corporation. 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 /* This is a modified copy of the ref_twincpu version at
21 * platform/ext/target/ref_twincpu/CMSIS_Driver/Driver_Flash.c
22 */
23
24 #include <string.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include "Driver_Flash.h"
28 #include "RTE_Device.h"
29 #include "flash_layout.h"
30 #include "region_defs.h"
31
32 #include "cycfg.h"
33 #include "cy_device.h"
34 #include "cy_flash.h"
35
36 #ifndef ARG_UNUSED
37 #define ARG_UNUSED(arg) ((void)arg)
38 #endif
39
40 /* Driver version */
41 #define ARM_FLASH_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 1)
42 #define ARM_FLASH_DRV_ERASE_VALUE 0xFF
43
44 #define FLASH0_BASE CY_FLASH_BASE // User Flash start address for both CM0+ & CM4
45 #define FLASH0_SIZE CY_FLASH_SIZE // 1 MB
46 #define FLASH0_SECTOR_SIZE CY_FLASH_SIZEOF_ROW // 512 B
47 #define FLASH0_PAGE_SIZE CY_FLASH_SIZEOF_ROW // 512 B
48
49 struct arm_flash_dev_t {
50 const uint32_t memory_base; /*!< FLASH memory base address */
51 ARM_FLASH_INFO *data; /*!< FLASH data */
52 };
53
54 /* Flash Status */
55 static ARM_FLASH_STATUS FlashStatus = {0, 0, 0};
56
57 /* Driver Version */
58 static const ARM_DRIVER_VERSION DriverVersion = {
59 ARM_FLASH_API_VERSION,
60 ARM_FLASH_DRV_VERSION
61 };
62
63 /**
64 * Data width values for ARM_FLASH_CAPABILITIES::data_width
65 * \ref ARM_FLASH_CAPABILITIES
66 */
67 enum {
68 DATA_WIDTH_8BIT = 0u,
69 DATA_WIDTH_16BIT,
70 DATA_WIDTH_32BIT,
71 DATA_WIDTH_ENUM_SIZE
72 };
73
74 /* Driver Capabilities */
75 static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
76 0, /* event_ready */
77 DATA_WIDTH_8BIT,
78 1 /* erase_chip */
79 };
80
81 static const uint32_t data_width_byte[DATA_WIDTH_ENUM_SIZE] = {
82 sizeof(uint8_t),
83 sizeof(uint16_t),
84 sizeof(uint32_t),
85 };
86
87 #if (RTE_FLASH0)
88
89 static ARM_FLASH_INFO ARM_FLASH0_DEV_DATA = {
90 .sector_info = NULL, /* Uniform sector layout */
91 .sector_count = FLASH0_SIZE / FLASH0_SECTOR_SIZE,
92 .sector_size = FLASH0_SECTOR_SIZE,
93 .page_size = FLASH0_PAGE_SIZE,
94 .program_unit = TFM_HAL_PS_PROGRAM_UNIT,
95 .erased_value = ARM_FLASH_DRV_ERASE_VALUE
96 };
97
98 static struct arm_flash_dev_t ARM_FLASH0_DEV = {
99 .memory_base = FLASH0_BASE,
100 .data = &(ARM_FLASH0_DEV_DATA)
101 };
102
103 struct arm_flash_dev_t *FLASH0_DEV = &ARM_FLASH0_DEV;
104
105 /*
106 * Functions
107 */
108
ARM_Flash_GetVersion(void)109 static ARM_DRIVER_VERSION ARM_Flash_GetVersion(void)
110 {
111 return DriverVersion;
112 }
113
ARM_Flash_GetCapabilities(void)114 static ARM_FLASH_CAPABILITIES ARM_Flash_GetCapabilities(void)
115 {
116 return DriverCapabilities;
117 }
118
ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)119 static int32_t ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)
120 {
121 ARG_UNUSED(cb_event);
122
123 if (DriverCapabilities.data_width >= DATA_WIDTH_ENUM_SIZE) {
124 return ARM_DRIVER_ERROR;
125 }
126
127 return ARM_DRIVER_OK;
128 }
129
ARM_Flash_Uninitialize(void)130 static int32_t ARM_Flash_Uninitialize(void)
131 {
132 /* Nothing to be done */
133 return ARM_DRIVER_OK;
134 }
135
ARM_Flash_PowerControl(ARM_POWER_STATE state)136 static int32_t ARM_Flash_PowerControl(ARM_POWER_STATE state)
137 {
138 switch (state) {
139 case ARM_POWER_FULL:
140 /* Nothing to be done */
141 return ARM_DRIVER_OK;
142 break;
143
144 case ARM_POWER_OFF:
145 case ARM_POWER_LOW:
146 default:
147 return ARM_DRIVER_ERROR_UNSUPPORTED;
148 }
149 }
150
ARM_Flash_ReadData(uint32_t addr,void * data,uint32_t cnt)151 static int32_t ARM_Flash_ReadData(uint32_t addr, void *data, uint32_t cnt)
152 {
153 if ( (data == NULL) || (cnt == 0) ) {
154 return ARM_DRIVER_OK;
155 }
156 /* Conversion between data items and bytes */
157 cnt *= data_width_byte[DriverCapabilities.data_width];
158
159 // Wraparound check (before adding FLASH0_DEV->memory_base + addr)
160 if (FLASH0_DEV->memory_base >= UINT32_MAX - addr) {
161 return ARM_DRIVER_ERROR_PARAMETER;
162 }
163
164 uint32_t start_addr = FLASH0_DEV->memory_base + addr;
165
166 if (start_addr >= FLASH0_DEV->memory_base + FLASH0_SIZE) {
167 return ARM_DRIVER_ERROR_PARAMETER;
168 }
169
170 // Wraparound check (before adding start_addr + cnt)
171 if (start_addr >= UINT32_MAX - cnt) {
172 return ARM_DRIVER_ERROR_PARAMETER;
173 }
174
175 if ( (start_addr + cnt < FLASH0_DEV->memory_base) ||
176 (start_addr + cnt > FLASH0_DEV->memory_base + FLASH0_SIZE)
177 ) {
178 return ARM_DRIVER_ERROR_PARAMETER;
179 }
180
181 // Using memcpy for reading
182 memcpy(data, (void *)start_addr, cnt);
183
184 cnt /= data_width_byte[DriverCapabilities.data_width];
185 return cnt;
186 }
187
ARM_Flash_ProgramData(uint32_t addr,const void * data,uint32_t cnt)188 static int32_t ARM_Flash_ProgramData(uint32_t addr, const void *data,
189 uint32_t cnt)
190 {
191 __attribute__ ((aligned(4))) static uint8_t prog_buf[CY_FLASH_SIZEOF_ROW];
192 uint8_t *data_ptr = (uint8_t *) data;
193 uint32_t address = FLASH0_DEV->memory_base + addr;
194 cy_en_flashdrv_status_t cy_status = CY_FLASH_DRV_ERR_UNC;
195
196 // Address checks can be omitted here as they are done by Cypress API
197
198 if ( (data == NULL) || (cnt == 0) ) {
199 return ARM_DRIVER_ERROR_PARAMETER;
200 }
201
202 /* Conversion between data items and bytes */
203 cnt *= data_width_byte[DriverCapabilities.data_width];
204
205 // Make sure cnt argument is aligned to program_unit size
206 if (cnt % FLASH0_DEV->data->program_unit) {
207 return ARM_DRIVER_ERROR_PARAMETER;
208 }
209
210 // Wraparound check (before adding FLASH0_DEV->memory_base + addr)
211 if (FLASH0_DEV->memory_base >= UINT32_MAX - addr) {
212 return ARM_DRIVER_ERROR_PARAMETER;
213 }
214
215 while (cnt)
216 {
217 uint32_t offset = address % CY_FLASH_SIZEOF_ROW;
218 uint32_t chunk_size;
219 if (offset + cnt > CY_FLASH_SIZEOF_ROW) {
220 chunk_size = CY_FLASH_SIZEOF_ROW - offset;
221 } else {
222 chunk_size = cnt;
223 }
224 uint32_t row_address = address / CY_FLASH_SIZEOF_ROW * CY_FLASH_SIZEOF_ROW;
225 memcpy(prog_buf, (const void *)row_address, CY_FLASH_SIZEOF_ROW);
226 memcpy(prog_buf + offset, data_ptr, chunk_size);
227
228 cy_status = Cy_Flash_ProgramRow(row_address, (const uint32_t *)prog_buf);
229 if (cy_status != CY_FLASH_DRV_SUCCESS) {
230 break;
231 }
232 data_ptr += chunk_size;
233 address += chunk_size;
234 cnt -= chunk_size;
235 }
236
237 switch (cy_status)
238 {
239 case CY_FLASH_DRV_SUCCESS:
240 cnt /= data_width_byte[DriverCapabilities.data_width];
241 return cnt;
242
243 case CY_FLASH_DRV_IPC_BUSY:
244 return ARM_DRIVER_ERROR_BUSY;
245
246 case CY_FLASH_DRV_INVALID_INPUT_PARAMETERS:
247 return ARM_DRIVER_ERROR_PARAMETER;
248
249 default:
250 return ARM_DRIVER_ERROR;
251 }
252 }
253
ARM_Flash_EraseSector(uint32_t addr)254 static int32_t ARM_Flash_EraseSector(uint32_t addr)
255 {
256 // Wraparound check (before adding FLASH0_DEV->memory_base + addr)
257 if (FLASH0_DEV->memory_base >= UINT32_MAX - addr) {
258 return ARM_DRIVER_ERROR_PARAMETER;
259 }
260
261 uint32_t start_addr = FLASH0_DEV->memory_base + addr;
262
263 // Address checks can be omitted here as they are done by Cypress API
264
265 cy_en_flashdrv_status_t cy_status = Cy_Flash_EraseRow(start_addr);
266
267 switch (cy_status)
268 {
269 case CY_FLASH_DRV_SUCCESS:
270 return ARM_DRIVER_OK;
271
272 case CY_FLASH_DRV_IPC_BUSY:
273 return ARM_DRIVER_ERROR_BUSY;
274
275 case CY_FLASH_DRV_INVALID_INPUT_PARAMETERS:
276 return ARM_DRIVER_ERROR_PARAMETER;
277
278 default:
279 return ARM_DRIVER_ERROR;
280 }
281 }
282
ARM_Flash_EraseChip(void)283 static int32_t ARM_Flash_EraseChip(void)
284 {
285 uint32_t addr = FLASH0_DEV->memory_base;
286
287 cy_en_flashdrv_status_t cy_status = CY_FLASH_DRV_ERR_UNC;
288
289
290 if (DriverCapabilities.erase_chip != 1) {
291 return ARM_DRIVER_ERROR_UNSUPPORTED;
292 }
293
294 for (uint32_t i = 0; i < FLASH0_DEV->data->sector_count; i++) {
295
296 cy_status = Cy_Flash_EraseRow(addr);
297
298 if (cy_status != CY_FLASH_DRV_SUCCESS) {
299 break;
300 }
301
302 addr += FLASH0_DEV->data->sector_size;
303 }
304
305 switch (cy_status)
306 {
307 case CY_FLASH_DRV_SUCCESS:
308 return ARM_DRIVER_OK;
309
310 case CY_FLASH_DRV_IPC_BUSY:
311 return ARM_DRIVER_ERROR_BUSY;
312
313 case CY_FLASH_DRV_INVALID_INPUT_PARAMETERS:
314 return ARM_DRIVER_ERROR_PARAMETER;
315
316 default:
317 return ARM_DRIVER_ERROR;
318 }
319 }
320
ARM_Flash_GetStatus(void)321 static ARM_FLASH_STATUS ARM_Flash_GetStatus(void)
322 {
323 return FlashStatus;
324 }
325
ARM_Flash_GetInfo(void)326 static ARM_FLASH_INFO * ARM_Flash_GetInfo(void)
327 {
328 return FLASH0_DEV->data;
329 }
330
331 ARM_DRIVER_FLASH Driver_FLASH0 = {
332 ARM_Flash_GetVersion,
333 ARM_Flash_GetCapabilities,
334 ARM_Flash_Initialize,
335 ARM_Flash_Uninitialize,
336 ARM_Flash_PowerControl,
337 ARM_Flash_ReadData,
338 ARM_Flash_ProgramData,
339 ARM_Flash_EraseSector,
340 ARM_Flash_EraseChip,
341 ARM_Flash_GetStatus,
342 ARM_Flash_GetInfo
343 };
344
345 #endif /* RTE_FLASH0 */
346