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