2 * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 /******************************************************************************
18 * @brief CSI Source File for Embedded Flash Driver
21 ******************************************************************************/
26 #include "drv_eflash.h"
27 #include "ck_eflash.h"
30 #define ERR_EFLASH(errno) (CSI_DRV_ERRNO_EFLASH_BASE | errno)
31 #define EFLASH_NULL_PARAM_CHK(para) \
34 return ERR_EFLASH(EDRV_PARAMETER); \
40 eflash_info_t eflashinfo;
42 eflash_status_t status;
45 extern int32_t target_get_eflash_count(void);
46 extern int32_t target_get_eflash(int32_t idx, uint32_t *base, eflash_info_t *info);
48 static ck_eflash_priv_t eflash_handle[CONFIG_EFLASH_NUM];
49 /* Driver Capabilities */
50 static const eflash_capabilities_t driver_capabilities = {
51 .event_ready = 1, /* event_ready */
52 .data_width = 2, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
53 .erase_chip = 0 /* erase_chip */
60 static int32_t eflash_program_word(eflash_handle_t handle, uint32_t dstaddr, uint32_t *srcbuf, uint32_t len)
62 ck_eflash_priv_t *eflash_priv = handle;
63 uint32_t fbase = eflash_priv->base;
66 for (i = 0; i < len; i++) {
67 *(volatile uint32_t *)(fbase + 0x04) = dstaddr;
68 *(volatile uint32_t *)(fbase + 0x1c) = *srcbuf;
69 *(volatile uint32_t *)(fbase + 0x18) = 1;
78 #ifdef CONFIG_CHIP_CH2201
79 static uint32_t context[EFLASH_SECTOR_SIZE >> 2] = {0x0};
80 static int32_t eflash_verify(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt)
83 uint8_t error_flag = 1;
85 uint8_t *block_addr = (uint8_t *)(addr & ~(EFLASH_SECTOR_SIZE - 1));
86 uint32_t pre_offset = addr - (uint32_t)block_addr;
87 uint32_t pre_count = (cnt > (EFLASH_SECTOR_SIZE - pre_offset)) ? (EFLASH_SECTOR_SIZE - pre_offset) : cnt;
93 dst = (uint8_t *)addr;
95 volatile uint8_t verify_count = 100;
98 for (i = 0; i < pre_count; i++) {
99 if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
100 *(volatile uint32_t *) 0x50004000 = 'E'; /* for debug */
101 *(volatile uint32_t *) 0x50004000 = 'E';
102 *(volatile uint32_t *) 0x50004000 = 'E';
103 *(volatile uint32_t *) 0x50004000 = 'E';
104 *(volatile uint32_t *) 0x50004000 = '\n';
105 memcpy(context, block_addr, EFLASH_SECTOR_SIZE);
106 memcpy((uint8_t *)context + pre_offset, p, pre_count);
107 csi_eflash_erase_sector(handle, (uint32_t)dst);
108 eflash_program_word(handle, (uint32_t)block_addr, context, EFLASH_SECTOR_SIZE >> 2);
113 if (i == pre_count || !(verify_count--)) {
119 return ERR_EFLASH(EDRV_TIMEOUT);
128 while (len >= EFLASH_SECTOR_SIZE) {
130 for (i = 0; i < EFLASH_SECTOR_SIZE; i++) {
131 if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
132 *(volatile uint32_t *) 0x50004000 = 'E'; /* for debug */
133 *(volatile uint32_t *) 0x50004000 = 'E';
134 *(volatile uint32_t *) 0x50004000 = 'E';
135 *(volatile uint32_t *) 0x50004000 = 'E';
136 *(volatile uint32_t *) 0x50004000 = '\n';
137 memcpy((uint8_t *)context, p, EFLASH_SECTOR_SIZE);
138 csi_eflash_erase_sector(handle, (uint32_t)dst);
139 eflash_program_word(handle, (uint32_t)dst, context, EFLASH_SECTOR_SIZE >> 2);
144 if (i == EFLASH_SECTOR_SIZE || !(verify_count--)) {
150 return ERR_EFLASH(EDRV_TIMEOUT);
156 dst += EFLASH_SECTOR_SIZE;
157 p += EFLASH_SECTOR_SIZE;
158 len -= EFLASH_SECTOR_SIZE;
163 for (i = 0; i < len; i++) {
164 if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
165 *(volatile uint32_t *) 0x50004000 = 'E'; /* for debug */
166 *(volatile uint32_t *) 0x50004000 = 'E';
167 *(volatile uint32_t *) 0x50004000 = 'E';
168 *(volatile uint32_t *) 0x50004000 = 'E';
169 *(volatile uint32_t *) 0x50004000 = '\n';
170 memcpy(context, dst, EFLASH_SECTOR_SIZE);
171 memcpy((uint8_t *)context + i, p + i, len - i);
172 csi_eflash_erase_sector(handle, (uint32_t)dst);
173 eflash_program_word(handle, (uint32_t)dst, context, EFLASH_SECTOR_SIZE >> 2);
178 if (i == len || !(verify_count--)) {
184 return ERR_EFLASH(EDRV_TIMEOUT);
195 \brief Initialize EFLASH Interface. 1. Initializes the resources needed for the EFLASH interface 2.registers event callback function
196 \param[in] idx device id
197 \param[in] cb_event Pointer to \ref eflash_event_cb_t
198 \return pointer to eflash handle
200 eflash_handle_t csi_eflash_initialize(int32_t idx, eflash_event_cb_t cb_event)
202 if (idx < 0 || idx >= CONFIG_EFLASH_NUM) {
206 /* obtain the eflash information */
209 int32_t real_idx = target_get_eflash(idx, &base, &info);
211 if (real_idx != idx) {
215 ck_eflash_priv_t *eflash_priv = &eflash_handle[idx];
217 eflash_priv->base = base;
218 eflash_priv->eflashinfo.start = info.start;
219 eflash_priv->eflashinfo.end = info.end;
220 eflash_priv->eflashinfo.sector_count = info.sector_count;
222 /* initialize the eflash context */
223 eflash_priv->cb = cb_event;
224 eflash_priv->status.busy = 0;
225 eflash_priv->status.error = 0U;
226 eflash_priv->eflashinfo.sector_size = EFLASH_SECTOR_SIZE;
227 eflash_priv->eflashinfo.page_size = EFLASH_PAGE_SIZE;
228 eflash_priv->eflashinfo.program_unit = EFLASH_PROGRAM_UINT;
229 eflash_priv->eflashinfo.erased_value = EFLASH_ERASED_VALUE;
231 return (eflash_handle_t)eflash_priv;
235 \brief De-initialize EFLASH Interface. stops operation and releases the software resources used by the interface
236 \param[in] handle eflash handle to operate.
239 int32_t csi_eflash_uninitialize(eflash_handle_t handle)
241 EFLASH_NULL_PARAM_CHK(handle);
243 ck_eflash_priv_t *eflash_priv = handle;
244 eflash_priv->cb = NULL;
250 \brief Get driver capabilities.
251 \param[in] idx device id
252 \return \ref eflash_capabilities_t
254 eflash_capabilities_t csi_eflash_get_capabilities(eflash_handle_t handle)
256 return driver_capabilities;
260 \brief Read data from Flash.
261 \param[in] handle eflash handle to operate.
262 \param[in] addr Data address.
263 \param[out] data Pointer to a buffer storing the data read from Flash.
264 \param[in] cnt Number of data items to read.
265 \return number of data items read or error code
267 int32_t csi_eflash_read(eflash_handle_t handle, uint32_t addr, void *data, uint32_t cnt)
269 EFLASH_NULL_PARAM_CHK(handle);
270 EFLASH_NULL_PARAM_CHK(data);
271 EFLASH_NULL_PARAM_CHK(cnt);
273 volatile uint8_t *src_addr = (uint8_t *)addr;
274 ck_eflash_priv_t *eflash_priv = handle;
276 if (eflash_priv->eflashinfo.start > addr || eflash_priv->eflashinfo.end < addr || eflash_priv->eflashinfo.start > (addr + cnt - 1) || eflash_priv->eflashinfo.end < (addr + cnt - 1)) {
277 return ERR_EFLASH(EDRV_PARAMETER);
280 if (eflash_priv->status.busy) {
281 return ERR_EFLASH(EDRV_BUSY);
284 eflash_priv->status.error = 0U;
288 for (i = 0; i < cnt; i++) {
289 *((uint8_t *)data + i) = *(src_addr + i);
296 \brief Program data to Flash.
297 \param[in] handle eflash handle to operate.
298 \param[in] addr Data address.
299 \param[in] data Pointer to a buffer containing the data to be programmed to Flash..
300 \param[in] cnt Number of data items to program.
301 \return number of data items programmed or error code
303 int32_t csi_eflash_program(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt)
305 EFLASH_NULL_PARAM_CHK(handle);
306 EFLASH_NULL_PARAM_CHK(data);
307 EFLASH_NULL_PARAM_CHK(cnt);
309 ck_eflash_priv_t *eflash_priv = handle;
311 if (eflash_priv->eflashinfo.start > addr || eflash_priv->eflashinfo.end < addr || eflash_priv->eflashinfo.start > (addr + cnt - 1) || eflash_priv->eflashinfo.end < (addr + cnt - 1)) {
312 return ERR_EFLASH(EDRV_PARAMETER);
319 return ERR_EFLASH(EDRV_PARAMETER);
322 if (eflash_priv->status.busy) {
323 return ERR_EFLASH(EDRV_BUSY);
326 eflash_priv->status.busy = 1U;
327 eflash_priv->status.error = 0U;
329 if (((uint32_t)data & 0x3) == 0) {
330 cur = cnt - (cnt & 0x3);
331 eflash_program_word(handle, addr, (uint32_t *)data, cur >> 2);
333 uint8_t *buffer_b = (uint8_t *)data;
335 for (; cur < cnt - 3; cur += 4, buffer_b += 4) {
336 pad_buf = buffer_b[0] | (buffer_b[1] << 8) | (buffer_b[2] << 16) | (buffer_b[3] << 24);
337 eflash_program_word(handle, addr + cur, &pad_buf, 1);
342 pad_buf = *((volatile uint32_t *)(addr + cur));
343 uint8_t *pad = (uint8_t *)&pad_buf;
344 uint8_t *buff = (uint8_t *)data;
347 for (i = 0; i < (cnt - cur); i++) {
348 pad[i] = buff[cur + i];
351 eflash_program_word(handle, addr + cur, &pad_buf, 1);
355 eflash_priv->status.busy = 0U;
356 #ifdef CONFIG_CHIP_CH2201
357 eflash_verify(handle, addr, data, cnt);
364 \brief Erase Flash Sector.
365 \param[in] handle eflash handle to operate.
366 \param[in] addr Sector address
369 int32_t csi_eflash_erase_sector(eflash_handle_t handle, uint32_t addr)
371 EFLASH_NULL_PARAM_CHK(handle);
373 ck_eflash_priv_t *eflash_priv = handle;
375 if (eflash_priv->eflashinfo.start > addr || eflash_priv->eflashinfo.end < addr) {
376 return ERR_EFLASH(EDRV_PARAMETER);
380 addr = addr & ~(EFLASH_SECTOR_SIZE - 1);
381 uint32_t fbase = eflash_priv->base;
383 if (eflash_priv->status.busy) {
384 return ERR_EFLASH(EDRV_BUSY);
387 eflash_priv->status.busy = 1U;
388 eflash_priv->status.error = 0U;
389 *(volatile uint32_t *)(fbase + 0x4) = addr;
390 *(volatile uint32_t *)(fbase + 0x10) = 0x1;
391 eflash_priv->status.busy = 0U;
397 \brief Erase complete Flash.
398 \param[in] handle eflash handle to operate.
401 int32_t csi_eflash_erase_chip(eflash_handle_t handle)
403 EFLASH_NULL_PARAM_CHK(handle);
405 return ERR_EFLASH(EDRV_UNSUPPORTED);
409 \brief Get Flash information.
410 \param[in] handle eflash handle to operate.
411 \return Pointer to Flash information \ref eflash_info_t
413 eflash_info_t *csi_eflash_get_info(eflash_handle_t handle)
415 if (handle == NULL) {
419 ck_eflash_priv_t *eflash_priv = handle;
420 eflash_info_t *eflash_info = &(eflash_priv->eflashinfo);
426 \brief Get EFLASH status.
427 \param[in] handle eflash handle to operate.
428 \return EFLASH status \ref eflash_status_t
430 eflash_status_t csi_eflash_get_status(eflash_handle_t handle)
432 if (handle == NULL) {
434 memset(&ret, 0, sizeof(eflash_status_t));
438 ck_eflash_priv_t *eflash_priv = handle;
440 return eflash_priv->status;