1 /*
2 * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
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 * @file ck_eflash.c
18 * @brief CSI Source File for Embedded Flash Driver
19 * @version V1.0
20 * @date 02. June 2017
21 ******************************************************************************/
22 #include <stdio.h>
23 #include "drv_eflash.h"
24 #include "ck_eflash.h"
25
26
27 #define ERR_EFLASH(errno) (CSI_DRV_ERRNO_EFLASH_BASE | errno)
28 #define EFLASH_NULL_PARAM_CHK(para) \
29 do { \
30 if (para == NULL) { \
31 return ERR_EFLASH(EDRV_PARAMETER); \
32 } \
33 } while (0)
34
35 typedef struct {
36 uint32_t base;
37 eflash_info eflashinfo;
38 eflash_event_cb_t cb;
39 eflash_status_t status;
40 } ck_eflash_priv_t;
41
42 static ck_eflash_priv_t eflash_handle[CONFIG_EFLASH_NUM];
43 /* Driver Capabilities */
44 static const eflash_capabilities_t driver_capabilities = {
45 .event_ready = 1, /* event_ready */
46 .data_width = 2, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
47 .erase_chip = 0 /* erase_chip */
48 };
49
50 //
51 // Functions
52 //
53
eflash_program_word(eflash_handle_t handle,uint32_t dstaddr,uint32_t * srcbuf,uint32_t len)54 static int32_t eflash_program_word(eflash_handle_t handle, uint32_t dstaddr, uint32_t *srcbuf, uint32_t len)
55 {
56 ck_eflash_priv_t *eflash_priv = handle;
57 uint32_t fbase = eflash_priv->base;
58 uint32_t i;
59
60 for (i = 0; i < len; i++) {
61 *(volatile uint32_t *)(fbase + 0x04) = dstaddr;
62 *(volatile uint32_t *)(fbase + 0x1c) = *srcbuf;
63 *(volatile uint32_t *)(fbase + 0x18) = 1;
64 srcbuf++;
65 dstaddr += 4;
66 }
67
68 return (i << 2);
69 }
70
target_get_eflash_count(void)71 int32_t __attribute__((weak)) target_get_eflash_count(void)
72 {
73 return 0;
74 }
75
target_get_eflash(int32_t idx,uint32_t * base,eflash_info * info)76 int32_t __attribute__((weak)) target_get_eflash(int32_t idx, uint32_t *base, eflash_info *info)
77 {
78 return NULL;
79 }
80 /**
81 \brief get eflash handle count.
82 \return eflash handle count
83 */
csi_eflash_get_instance_count(void)84 int32_t csi_eflash_get_instance_count(void)
85 {
86 return target_get_eflash_count();
87 }
88
89 /**
90 \brief Initialize EFLASH Interface. 1. Initializes the resources needed for the EFLASH interface 2.registers event callback function
91 \param[in] idx must not exceed return value of csi_eflash_get_instance_count()
92 \param[in] cb_event Pointer to \ref eflash_event_cb_t
93 \return pointer to eflash handle
94 */
csi_eflash_initialize(int32_t idx,eflash_event_cb_t cb_event)95 eflash_handle_t csi_eflash_initialize(int32_t idx, eflash_event_cb_t cb_event)
96 {
97 if (idx < 0 || idx >= CONFIG_EFLASH_NUM) {
98 return NULL;
99 }
100
101 /* obtain the eflash information */
102 uint32_t base = 0u;
103 eflash_info info;
104 int32_t real_idx = target_get_eflash(idx, &base, &info);
105
106 if (real_idx != idx) {
107 return NULL;
108 }
109
110 ck_eflash_priv_t *eflash_priv = &eflash_handle[idx];
111
112 eflash_priv->base = base;
113 eflash_priv->eflashinfo.start = info.start;
114 eflash_priv->eflashinfo.end = info.end;
115 eflash_priv->eflashinfo.sector_count = info.sector_count;
116
117 /* initialize the eflash context */
118 eflash_priv->cb = cb_event;
119 eflash_priv->status.busy = 0;
120 eflash_priv->status.error = 0U;
121 eflash_priv->eflashinfo.sector_size = EFLASH_SECTOR_SIZE;
122 eflash_priv->eflashinfo.page_size = EFLASH_PAGE_SIZE;
123 eflash_priv->eflashinfo.program_unit = EFLASH_PROGRAM_UINT;
124 eflash_priv->eflashinfo.erased_value = EFLASH_ERASED_VALUE;
125
126 return (eflash_handle_t)eflash_priv;
127 }
128
129 /**
130 \brief De-initialize EFLASH Interface. stops operation and releases the software resources used by the interface
131 \param[in] handle eflash handle to operate.
132 \return error code
133 */
csi_eflash_uninitialize(eflash_handle_t handle)134 int32_t csi_eflash_uninitialize(eflash_handle_t handle)
135 {
136 EFLASH_NULL_PARAM_CHK(handle);
137
138 ck_eflash_priv_t *eflash_priv = handle;
139 eflash_priv->cb = NULL;
140
141 return 0;
142 }
143
144 /**
145 \brief Get driver capabilities.
146 \param[in] eflash handle to operate.
147 \return \ref eflash_capabilities_t
148 */
csi_eflash_get_capabilities(eflash_handle_t handle)149 eflash_capabilities_t csi_eflash_get_capabilities(eflash_handle_t handle)
150 {
151 return driver_capabilities;
152 }
153
154 /**
155 \brief Read data from Flash.
156 \param[in] handle eflash handle to operate.
157 \param[in] addr Data address.
158 \param[out] data Pointer to a buffer storing the data read from Flash.
159 \param[in] cnt Number of data items to read.
160 \return number of data items read or error code
161 */
csi_eflash_read(eflash_handle_t handle,uint32_t addr,void * data,uint32_t cnt)162 int32_t csi_eflash_read(eflash_handle_t handle, uint32_t addr, void *data, uint32_t cnt)
163 {
164 EFLASH_NULL_PARAM_CHK(handle);
165 EFLASH_NULL_PARAM_CHK(data);
166 EFLASH_NULL_PARAM_CHK(cnt);
167 if (!IS_EFLASH_ADDR(addr) || !(IS_EFLASH_ADDR(addr + cnt -1))) {
168 return ERR_EFLASH(EDRV_PARAMETER);
169 }
170
171 volatile uint8_t *src_addr = (uint8_t *)addr;
172 ck_eflash_priv_t *eflash_priv = handle;
173
174 if (eflash_priv->status.busy) {
175 return ERR_EFLASH(EDRV_BUSY);
176 }
177
178 eflash_priv->status.error = 0U;
179
180 int i;
181 for (i = 0; i < cnt; i++) {
182 *((uint8_t *)data + i) = *(src_addr + i);
183 }
184
185 return i;
186 }
187
188 /**
189 \brief Program data to Flash.
190 \param[in] handle eflash handle to operate.
191 \param[in] addr Data address.
192 \param[in] data Pointer to a buffer containing the data to be programmed to Flash..
193 \param[in] cnt Number of data items to program.
194 \return number of data items programmed or error code
195 */
csi_eflash_program(eflash_handle_t handle,uint32_t addr,const void * data,uint32_t cnt)196 int32_t csi_eflash_program(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt)
197 {
198 EFLASH_NULL_PARAM_CHK(handle);
199 EFLASH_NULL_PARAM_CHK(data);
200 EFLASH_NULL_PARAM_CHK(cnt);
201 if (!IS_EFLASH_ADDR(addr) || !(IS_EFLASH_ADDR(addr + cnt -1))) {
202 return ERR_EFLASH(EDRV_PARAMETER);
203 }
204
205 ck_eflash_priv_t *eflash_priv = handle;
206
207 if ((addr & 0x3) || ((uint32_t)data & 0x3) || (cnt & 0x3)) {
208 return ERR_EFLASH(EDRV_PARAMETER);
209 }
210
211 if (eflash_priv->status.busy) {
212 return ERR_EFLASH(EDRV_BUSY);
213 }
214
215 eflash_priv->status.busy = 1U;
216 eflash_priv->status.error = 0U;
217 uint32_t ret = eflash_program_word(handle, addr, (uint32_t *)data, cnt >> 2);
218 eflash_priv->status.busy = 0U;
219
220 return ret;
221 }
222
223 /**
224 \brief Erase Flash Sector.
225 \param[in] handle eflash handle to operate.
226 \param[in] addr Sector address
227 \return error code
228 */
csi_eflash_erase_sector(eflash_handle_t handle,uint32_t addr)229 int32_t csi_eflash_erase_sector(eflash_handle_t handle, uint32_t addr)
230 {
231 EFLASH_NULL_PARAM_CHK(handle);
232 if (!IS_EFLASH_ADDR(addr)) {
233 return ERR_EFLASH(EDRV_PARAMETER);
234 }
235
236 addr = addr & ~(EFLASH_SECTOR_SIZE - 1);
237 ck_eflash_priv_t *eflash_priv = handle;
238 uint32_t fbase = eflash_priv->base;
239
240 if (eflash_priv->status.busy) {
241 return ERR_EFLASH(EDRV_BUSY);
242 }
243
244 eflash_priv->status.busy = 1U;
245 eflash_priv->status.error = 0U;
246 *(volatile uint32_t *)(fbase + 0x4) = addr;
247 *(volatile uint32_t *)(fbase + 0x10) = 0x1;
248 eflash_priv->status.busy = 0U;
249
250 return 0;
251 }
252
253 /**
254 \brief Erase complete Flash.
255 \param[in] handle eflash handle to operate.
256 \return error code
257 */
csi_eflash_erase_chip(eflash_handle_t handle)258 int32_t csi_eflash_erase_chip(eflash_handle_t handle)
259 {
260 EFLASH_NULL_PARAM_CHK(handle);
261
262 return ERR_EFLASH(EDRV_UNSUPPORTED);
263 }
264
265 /**
266 \brief Get Flash information.
267 \param[in] handle eflash handle to operate.
268 \return Pointer to Flash information \ref eflash_info
269 */
csi_eflash_get_info(eflash_handle_t handle)270 eflash_info *csi_eflash_get_info(eflash_handle_t handle)
271 {
272 ck_eflash_priv_t *eflash_priv = handle;
273 eflash_info *eflash_info = &(eflash_priv->eflashinfo);
274
275 return eflash_info;
276 }
277
278 /**
279 \brief Get EFLASH status.
280 \param[in] handle eflash handle to operate.
281 \return EFLASH status \ref eflash_status_t
282 */
csi_eflash_get_status(eflash_handle_t handle)283 eflash_status_t csi_eflash_get_status(eflash_handle_t handle)
284 {
285 ck_eflash_priv_t *eflash_priv = handle;
286
287 return eflash_priv->status;
288 }
289