1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /**
17 * @file wm_fls.c
18 *
19 * @brief flash Driver Module
20 *
21 * @author dave
22 *
23 * Copyright (c) 2015 Winner Microelectronics Co., Ltd.
24 */
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include "list.h"
30 #include "wm_hostspi.h"
31 #include "wm_flash.h"
32 #include "wm_dbg.h"
33 #include "wm_mem.h"
34 #include "wm_fls_gd25qxx.h"
35
36 static struct tls_fls *spi_fls = NULL;
37
tls_spifls_read_id(u32 * id)38 static int tls_spifls_read_id(u32 * id)
39 {
40 u32 cmd;
41 int err;
42
43 cmd = FLS_CMD_READ_DEV_ID;
44 *id = 0;
45
46 err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, (u8 *) id, 3);
47 if (err != TLS_SPI_STATUS_OK) {
48 TLS_DBGPRT_ERR("flash read ID fail(%d)!\n", err);
49 return TLS_FLS_STATUS_EIO;
50 }
51
52 TLS_DBGPRT_FLASH_INFO("flash ID - 0x%x.\n", *id);
53
54 return TLS_FLS_STATUS_OK;
55 }
56
57 /**
58 * @brief This function is used to read data from the flash.
59 *
60 * @param[in] addr is byte offset addr for read from the flash.
61 * @param[in] buf is user for data buffer of flash read
62 * @param[in] len is byte length for read.
63 *
64 * @retval TLS_FLS_STATUS_OK if read sucsess
65 * @retval TLS_FLS_STATUS_EIO if read fail
66 *
67 * @note None
68 */
tls_spifls_read(u32 addr,u8 * buf,u32 len)69 int tls_spifls_read(u32 addr, u8 * buf, u32 len)
70 {
71 int err;
72 u32 read_bytes;
73 struct tls_fls_drv *drv;
74
75 if (spi_fls == NULL) {
76 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
77 return TLS_FLS_STATUS_EPERM;
78 }
79
80 if (spi_fls->current_drv == NULL) {
81 TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
82 return TLS_FLS_STATUS_ENODRV;
83 }
84
85 if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
86 || (buf == NULL)) {
87 return TLS_FLS_STATUS_EINVAL;
88 }
89 tls_os_sem_acquire(spi_fls->fls_lock, 0);
90 drv = spi_fls->current_drv;
91 read_bytes =
92 ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
93
94 err = drv->read(addr, buf, read_bytes);
95 tls_os_sem_release(spi_fls->fls_lock);
96 return err;
97 }
98
tls_spifls_fast_read(u32 addr,u8 * buf,u32 len)99 int tls_spifls_fast_read(u32 addr, u8 * buf, u32 len)
100 {
101 int err;
102 u32 read_bytes;
103 struct tls_fls_drv *drv;
104
105 if (spi_fls == NULL) {
106 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
107 return TLS_FLS_STATUS_EPERM;
108 }
109
110 if (spi_fls->current_drv == NULL) {
111 TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
112 return TLS_FLS_STATUS_ENODRV;
113 }
114
115 if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
116 || (buf == NULL)) {
117 return TLS_FLS_STATUS_EINVAL;
118 }
119 if ((spi_fls->current_drv->flags & TLS_FLS_FLAG_FAST_READ) !=
120 TLS_FLS_FLAG_FAST_READ) {
121 return TLS_FLS_STATUS_ENOSUPPORT;
122 }
123
124 drv = spi_fls->current_drv;
125 read_bytes =
126 ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
127
128 err = drv->fast_read(addr, buf, read_bytes);
129
130 return err;
131 }
132
tls_spifls_page_write(u32 page,u8 * buf,u32 page_cnt)133 int tls_spifls_page_write(u32 page, u8 * buf, u32 page_cnt)
134 {
135 int err;
136 u32 write_pages;
137 u32 i;
138 struct tls_fls_drv *drv;
139
140 if (spi_fls == NULL) {
141 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
142 return TLS_FLS_STATUS_EPERM;
143 }
144
145 if (spi_fls->current_drv == NULL) {
146 TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
147 return TLS_FLS_STATUS_ENODRV;
148 }
149
150 if ((page >= (spi_fls->current_drv->total_size / spi_fls->current_drv->page_size))
151 || (page_cnt == 0) || (buf == NULL)) {
152 return TLS_FLS_STATUS_EINVAL;
153 }
154
155 drv = spi_fls->current_drv;
156 write_pages = ((page + page_cnt) > (drv->total_size / drv->page_size)) ?
157 ((drv->total_size / drv->page_size) -page) : page_cnt;
158
159 err = TLS_FLS_STATUS_OK;
160
161 for (i = 0; i < write_pages; i++) {
162 err = drv->page_write(page + i, buf + i * drv->page_size);
163 if (err != TLS_FLS_STATUS_OK) {
164 TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", (page + i));
165 break;
166 }
167 }
168
169 return err;
170 }
171
172 /**
173 * @brief This function is used to write data to the flash.
174 *
175 * @param[in] addr is byte offset addr for write to the flash
176 * @param[in] buf is the data buffer want to write to flash
177 * @param[in] len is the byte length want to write
178 *
179 * @retval TLS_FLS_STATUS_OK if write flash success
180 * @retval TLS_FLS_STATUS_EPERM if flash struct point is null
181 * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed
182 * @retval TLS_FLS_STATUS_EINVAL if argument is invalid
183 * @retval TLS_FLS_STATUS_EIO if io error
184 *
185 * @note None
186 */
tls_spifls_write(u32 addr,u8 * buf,u32 len)187 int tls_spifls_write(u32 addr, u8 * buf, u32 len)
188 {
189 u8 *cache;
190 int err;
191 u32 sector_addr;
192 u32 sector_num;
193 u32 write_bytes;
194 u32 i;
195 struct tls_fls_drv *drv;
196
197 if (spi_fls == NULL) {
198 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
199 return TLS_FLS_STATUS_EPERM;
200 }
201
202 if (spi_fls->current_drv == NULL) {
203 TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
204 return TLS_FLS_STATUS_ENODRV;
205 }
206
207 if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
208 || (buf == NULL)) {
209 return TLS_FLS_STATUS_EINVAL;
210 }
211 tls_os_sem_acquire(spi_fls->fls_lock, 0);
212 drv = spi_fls->current_drv;
213 write_bytes =
214 ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
215 sector_addr = addr / drv->sector_size;
216 sector_num = (addr + write_bytes - 1) / drv->sector_size - sector_addr + 1;
217
218 TLS_DBGPRT_FLASH_INFO("write to flash: sector address - %d, sectors - %d.\n", sector_addr, sector_num);
219
220 err = TLS_FLS_STATUS_OK;
221
222 cache = tls_mem_alloc(drv->sector_size);
223 if (cache == NULL) {
224 tls_os_sem_release(spi_fls->fls_lock);
225 TLS_DBGPRT_ERR("allocate sector cache memory(%dB) fail!\n",
226 drv->sector_size);
227 return TLS_FLS_STATUS_ENOMEM;
228 }
229
230 for (i = 0; i < sector_num; i++) {
231 TLS_DBGPRT_FLASH_INFO("firstly, read the sector - %d to cache.\n",
232 sector_addr + i);
233 err = drv->read((sector_addr + i) * drv->sector_size, cache, drv->sector_size);
234 if (err != TLS_FLS_STATUS_OK) {
235 tls_os_sem_release(spi_fls->fls_lock);
236 TLS_DBGPRT_ERR("flash read fail(sector %d)!\n", (sector_addr + i));
237 break;
238 }
239
240 if (sector_num == 1) { /* flash write only in one sector */
241 MEMCPY(cache + (addr%drv->sector_size), buf, write_bytes);
242 buf += write_bytes;
243 write_bytes = 0;
244 } else { /* flash write through some sectors */
245 if (i == 0) {
246 MEMCPY(cache+(addr%drv->sector_size), buf, drv->sector_size - (addr%drv->sector_size));
247 buf += drv->sector_size - (addr%drv->sector_size);
248 write_bytes -= drv->sector_size - (addr%drv->sector_size);
249 } else if (i == (sector_num - 1)) {
250 MEMCPY(cache, buf, write_bytes);
251 buf += write_bytes;
252 write_bytes = 0;
253 } else {
254 MEMCPY(cache, buf, drv->sector_size);
255 buf += drv->sector_size;
256 write_bytes -= drv->sector_size;
257 }
258 }
259
260 TLS_DBGPRT_FLASH_INFO("second, erase the sector - %d.\n",
261 sector_addr + i);
262 err = drv->erase(sector_addr + i);
263 if (err != TLS_FLS_STATUS_OK) {
264 tls_os_sem_release(spi_fls->fls_lock);
265 TLS_DBGPRT_ERR("flash erase fail(sector %d)!\n", (sector_addr + i));
266 break;
267 }
268
269 TLS_DBGPRT_FLASH_INFO("finnaly, write the data in cache to the sector - %d.\n", sector_addr + i);
270 err = tls_spifls_page_write((sector_addr +i) * (drv->sector_size / drv->page_size),
271 cache, drv->sector_size / drv->page_size);
272 if (err != TLS_FLS_STATUS_OK) {
273 tls_os_sem_release(spi_fls->fls_lock);
274 TLS_DBGPRT_ERR("flash write fail(sector %d)!\n", (sector_addr + i));
275 break;
276 }
277 }
278
279 tls_mem_free(cache);
280 tls_os_sem_release(spi_fls->fls_lock);
281 return err;
282 }
283
tls_spifls_erase(u32 sector)284 int tls_spifls_erase(u32 sector)
285 {
286 int err;
287 struct tls_fls_drv *drv;
288
289 if (spi_fls == NULL) {
290 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
291 return TLS_FLS_STATUS_EPERM;
292 }
293
294 if (spi_fls->current_drv == NULL) {
295 TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
296 return TLS_FLS_STATUS_ENODRV;
297 }
298
299 if (sector >= (spi_fls->current_drv->total_size / spi_fls->current_drv->sector_size)) {
300 TLS_DBGPRT_ERR("the sector to be erase overflow!\n");
301 return TLS_FLS_STATUS_EINVAL;
302 }
303 tls_os_sem_acquire(spi_fls->fls_lock, 0);
304 drv = spi_fls->current_drv;
305
306 err = drv->erase(sector);
307 tls_os_sem_release(spi_fls->fls_lock);
308 return err;
309 }
310
tls_spifls_chip_erase(void)311 int tls_spifls_chip_erase(void)
312 {
313 int err;
314 struct tls_fls_drv *drv;
315
316 if (spi_fls == NULL) {
317 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
318 return TLS_FLS_STATUS_EPERM;
319 }
320
321 if (spi_fls->current_drv == NULL) {
322 TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
323 return TLS_FLS_STATUS_ENODRV;
324 }
325
326 drv = spi_fls->current_drv;
327
328 err = drv->chip_erase();
329
330 return err;
331 }
332
tls_spifls_get_param(u8 type,void * param)333 int tls_spifls_get_param(u8 type, void *param)
334 {
335 int err;
336 struct tls_fls_drv *drv;
337
338 if (spi_fls == NULL) {
339 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
340 return TLS_FLS_STATUS_EPERM;
341 }
342
343 if (spi_fls->current_drv == NULL) {
344 TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
345 return TLS_FLS_STATUS_ENODRV;
346 }
347
348 if (param == NULL) {
349 return TLS_FLS_STATUS_EINVAL;
350 }
351 tls_os_sem_acquire(spi_fls->fls_lock, 0);
352 drv = spi_fls->current_drv;
353 err = TLS_FLS_STATUS_OK;
354 switch (type) {
355 case TLS_FLS_PARAM_TYPE_ID:
356 *((u32 *) param) = drv->id;
357 break;
358
359 case TLS_FLS_PARAM_TYPE_SIZE:
360 *((u32 *) param) = drv->total_size;
361 break;
362
363 case TLS_FLS_PARAM_TYPE_PAGE_SIZE:
364 *((u32 *) param) = drv->page_size;
365 break;
366
367 case TLS_FLS_PARAM_TYPE_PROG_SIZE:
368 *((u32 *) param) = drv->program_size;
369 break;
370
371 case TLS_FLS_PARAM_TYPE_SECTOR_SIZE:
372 *((u32 *) param) = drv->sector_size;
373 break;
374
375 default:
376 TLS_DBGPRT_WARNING("invalid parameter ID!\n");
377 err = TLS_FLS_STATUS_EINVAL;
378 break;
379 }
380 tls_os_sem_release(spi_fls->fls_lock);
381 return err;
382 }
383
tls_spifls_drv_register(struct tls_fls_drv * fls_drv)384 int tls_spifls_drv_register(struct tls_fls_drv *fls_drv)
385 {
386 u32 cpu_sr;
387 struct tls_fls_drv *drv;
388
389 if (fls_drv == NULL) {
390 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
391 return TLS_FLS_STATUS_EINVAL;
392 }
393
394 dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
395 {
396 if (drv->id == fls_drv->id) {
397 TLS_DBGPRT_WARNING
398 ("corresponding spi flash driver has registered!\n");
399 return TLS_FLS_STATUS_EEXIST;
400 }
401 }
402
403 cpu_sr = tls_os_set_critical();
404 dl_list_add_tail((struct dl_list *) &spi_fls->fls_drvs,
405 (struct dl_list *) &fls_drv->drv_list);
406 tls_os_release_critical(cpu_sr);
407
408 TLS_DBGPRT_FLASH_INFO("the spi flash driver is registered successfully!\n");
409
410 return TLS_FLS_STATUS_OK;
411 }
412
tls_spifls_drv_unregister(struct tls_fls_drv * fls_drv)413 int tls_spifls_drv_unregister(struct tls_fls_drv *fls_drv)
414 {
415 TLS_DBGPRT_WARNING("unregister spi flash driver operation is not supported!\n");
416 return TLS_FLS_STATUS_EPERM;
417 }
418
tls_spifls_probe(void)419 int tls_spifls_probe(void)
420 {
421 int err;
422 u32 id;
423 struct tls_fls_drv *drv;
424
425 if (spi_fls == NULL) {
426 TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
427 return TLS_FLS_STATUS_EPERM;
428 }
429 if (spi_fls->current_drv != NULL) {
430 TLS_DBGPRT_ERR("the current spi flash has fount the matched driver!\n");
431 return TLS_FLS_STATUS_EBUSY;
432 }
433
434 TLS_DBGPRT_FLASH_INFO("try to read the current spi flash ID.\n");
435 err = tls_spifls_read_id(&id);
436 if (err != TLS_FLS_STATUS_OK) {
437 return err;
438 }
439
440 TLS_DBGPRT_FLASH_INFO("current spi flash ID - 0x%x.\n", id);
441
442 dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
443 {
444 err = drv->probe(id);
445 if (err != TLS_FLS_STATUS_OK) {
446 return err;
447 }
448
449 tls_spi_setup(drv->mode, drv->cs_active, drv->clock);
450
451 TLS_DBGPRT_FLASH_INFO("matched the spi flash driver.\n");
452 spi_fls->current_drv = drv;
453 break;
454 }
455
456 if (spi_fls->current_drv == NULL) {
457 TLS_DBGPRT_WARNING("not found the matched spi flash driver!\n");
458 return TLS_FLS_STATUS_ENODRV;
459 }
460
461 return TLS_FLS_STATUS_OK;
462 }
463
tls_spifls_init(void)464 int tls_spifls_init(void)
465 {
466 struct tls_fls *fls;
467 int err;
468
469 if (spi_fls != NULL) {
470 TLS_DBGPRT_ERR("flash driver module has been installed!\n");
471 return TLS_FLS_STATUS_EBUSY;
472 }
473
474 fls = (struct tls_fls *) tls_mem_alloc(sizeof(struct tls_fls));
475 if (fls == NULL) {
476 TLS_DBGPRT_ERR("allocate @spi_fls fail!\n");
477 return TLS_FLS_STATUS_ENOMEM;
478 }
479
480 memset_s(fls, sizeof(fls), 0, sizeof(*fls));
481 dl_list_init((struct dl_list *) &fls->fls_drvs);
482 err = tls_os_sem_create(&fls->fls_lock, 1);
483 if (err != TLS_OS_SUCCESS) {
484 tls_mem_free(fls);
485 TLS_DBGPRT_ERR("create semaphore @fls_lock fail!\n");
486 return TLS_FLS_STATUS_ENOMEM;
487 }
488 spi_fls = fls;
489
490 tls_spifls_drv_install();
491
492 return TLS_FLS_STATUS_OK;
493 }
494
tls_spifls_exit(void)495 int tls_spifls_exit(void)
496 {
497 TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n");
498 return TLS_FLS_STATUS_EPERM;
499 }