| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- /**
- * @file wm_fls.c
- *
- * @brief flash Driver Module
- *
- * @author dave
- *
- * Copyright (c) 2015 Winner Microelectronics Co., Ltd.
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "list.h"
- #include "wm_hostspi.h"
- #include "wm_flash.h"
- #include "wm_dbg.h"
- #include "wm_mem.h"
- #include "wm_fls_gd25qxx.h"
- static struct tls_fls *spi_fls = NULL;
- static int tls_spifls_read_id(u32 * id)
- {
- u32 cmd;
- int err;
- cmd = FLS_CMD_READ_DEV_ID;
- *id = 0;
- err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, (u8 *) id, 3);
- if (err != TLS_SPI_STATUS_OK)
- {
- TLS_DBGPRT_ERR("flash read ID fail(%d)!\n", err);
- return TLS_FLS_STATUS_EIO;
- }
- TLS_DBGPRT_FLASH_INFO("flash ID - 0x%x.\n", *id);
- return TLS_FLS_STATUS_OK;
- }
- /**
- * @brief This function is used to read data from the flash.
- *
- * @param[in] addr is byte offset addr for read from the flash.
- * @param[in] buf is user for data buffer of flash read
- * @param[in] len is byte length for read.
- *
- * @retval TLS_FLS_STATUS_OK if read sucsess
- * @retval TLS_FLS_STATUS_EIO if read fail
- *
- * @note None
- */
- int tls_spifls_read(u32 addr, u8 * buf, u32 len)
- {
- int err;
- u32 read_bytes;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
- || (buf == NULL))
- {
- return TLS_FLS_STATUS_EINVAL;
- }
- tls_os_sem_acquire(spi_fls->fls_lock, 0);
- drv = spi_fls->current_drv;
- read_bytes =
- ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
- err = TLS_FLS_STATUS_OK;
- err = drv->read(addr, buf, read_bytes);
- tls_os_sem_release(spi_fls->fls_lock);
- return err;
- }
- int tls_spifls_fast_read(u32 addr, u8 * buf, u32 len)
- {
- int err;
- u32 read_bytes;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
- || (buf == NULL))
- {
- return TLS_FLS_STATUS_EINVAL;
- }
- if ((spi_fls->current_drv->flags & TLS_FLS_FLAG_FAST_READ) !=
- TLS_FLS_FLAG_FAST_READ)
- {
- return TLS_FLS_STATUS_ENOSUPPORT;
- }
- drv = spi_fls->current_drv;
- read_bytes =
- ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
- err = TLS_FLS_STATUS_OK;
- err = drv->fast_read(addr, buf, read_bytes);
- return err;
- }
- int tls_spifls_page_write(u32 page, u8 * buf, u32 page_cnt)
- {
- int err;
- u32 write_pages;
- u32 i;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- if ((page >= (spi_fls->current_drv->total_size / spi_fls->current_drv->page_size))
- || (page_cnt == 0) || (buf == NULL))
- {
- return TLS_FLS_STATUS_EINVAL;
- }
- drv = spi_fls->current_drv;
- write_pages = ((page + page_cnt) > (drv->total_size / drv->page_size)) ?
- ((drv->total_size / drv->page_size) -page) : page_cnt;
- err = TLS_FLS_STATUS_OK;
- for (i = 0; i < write_pages; i++)
- {
- err = drv->page_write(page + i, buf + i * drv->page_size);
- if (err != TLS_FLS_STATUS_OK)
- {
- TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", (page + i));
- break;
- }
- }
- return err;
- }
- /**
- * @brief This function is used to write data to the flash.
- *
- * @param[in] addr is byte offset addr for write to the flash
- * @param[in] buf is the data buffer want to write to flash
- * @param[in] len is the byte length want to write
- *
- * @retval TLS_FLS_STATUS_OK if write flash success
- * @retval TLS_FLS_STATUS_EPERM if flash struct point is null
- * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed
- * @retval TLS_FLS_STATUS_EINVAL if argument is invalid
- * @retval TLS_FLS_STATUS_EIO if io error
- *
- * @note None
- */
- int tls_spifls_write(u32 addr, u8 * buf, u32 len)
- {
- u8 *cache;
- int err;
- u32 sector_addr;
- u32 sector_num;
- u32 write_bytes;
- u32 i;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
- || (buf == NULL))
- {
- return TLS_FLS_STATUS_EINVAL;
- }
- tls_os_sem_acquire(spi_fls->fls_lock, 0);
- drv = spi_fls->current_drv;
- write_bytes =
- ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
- sector_addr = addr / drv->sector_size;
- sector_num = (addr + write_bytes - 1) / drv->sector_size - sector_addr + 1;
- TLS_DBGPRT_FLASH_INFO
- ("write to flash: sector address - %d, sectors - %d.\n", sector_addr,
- sector_num);
- err = TLS_FLS_STATUS_OK;
- cache = tls_mem_alloc(drv->sector_size);
- if (cache == NULL)
- {
- tls_os_sem_release(spi_fls->fls_lock);
- TLS_DBGPRT_ERR("allocate sector cache memory(%dB) fail!\n",
- drv->sector_size);
- return TLS_FLS_STATUS_ENOMEM;
- }
- for (i = 0; i < sector_num; i++)
- {
- TLS_DBGPRT_FLASH_INFO("firstly, read the sector - %d to cache.\n",
- sector_addr + i);
- err = drv->read((sector_addr + i) * drv->sector_size, cache, drv->sector_size);
- if (err != TLS_FLS_STATUS_OK)
- {
- tls_os_sem_release(spi_fls->fls_lock);
- TLS_DBGPRT_ERR("flash read fail(sector %d)!\n", (sector_addr + i));
- break;
- }
- if (1 == sector_num){/*flash write only in one sector*/
- MEMCPY(cache + (addr%drv->sector_size), buf, write_bytes);
- buf += write_bytes;
- write_bytes = 0;
- }else{/*flash write through some sectors*/
- if (0 == i) {
- MEMCPY(cache+(addr%drv->sector_size), buf, drv->sector_size - (addr%drv->sector_size));
- buf += drv->sector_size - (addr%drv->sector_size);
- write_bytes -= drv->sector_size - (addr%drv->sector_size);
- } else if (i == (sector_num - 1)) {
- MEMCPY(cache, buf, write_bytes);
- buf += write_bytes;
- write_bytes = 0;
- } else {
- MEMCPY(cache, buf, drv->sector_size);
- buf += drv->sector_size;
- write_bytes -= drv->sector_size;
- }
- }
- TLS_DBGPRT_FLASH_INFO("second, erase the sector - %d.\n",
- sector_addr + i);
- err = drv->erase(sector_addr + i);
- if (err != TLS_FLS_STATUS_OK)
- {
- tls_os_sem_release(spi_fls->fls_lock);
- TLS_DBGPRT_ERR("flash erase fail(sector %d)!\n", (sector_addr + i));
- break;
- }
- TLS_DBGPRT_FLASH_INFO
- ("finnaly, write the data in cache to the sector - %d.\n",
- sector_addr + i);
- err = tls_spifls_page_write((sector_addr +i) * (drv->sector_size / drv->page_size),
- cache, drv->sector_size / drv->page_size);
- if (err != TLS_FLS_STATUS_OK)
- {
- tls_os_sem_release(spi_fls->fls_lock);
- TLS_DBGPRT_ERR("flash write fail(sector %d)!\n", (sector_addr + i));
- break;
- }
- }
- tls_mem_free(cache);
- tls_os_sem_release(spi_fls->fls_lock);
- return err;
- }
- int tls_spifls_erase(u32 sector)
- {
- int err;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- if (sector >= (spi_fls->current_drv->total_size / spi_fls->current_drv->sector_size))
- {
- TLS_DBGPRT_ERR("the sector to be erase overflow!\n");
- return TLS_FLS_STATUS_EINVAL;
- }
- tls_os_sem_acquire(spi_fls->fls_lock, 0);
- drv = spi_fls->current_drv;
- err = TLS_FLS_STATUS_OK;
- err = drv->erase(sector);
- tls_os_sem_release(spi_fls->fls_lock);
- return err;
- }
- int tls_spifls_chip_erase(void)
- {
- int err;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- drv = spi_fls->current_drv;
- err = TLS_FLS_STATUS_OK;
- err = drv->chip_erase();
- return err;
- }
- int tls_spifls_get_param(u8 type, void *param)
- {
- int err;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- if (param == NULL)
- {
- return TLS_FLS_STATUS_EINVAL;
- }
- tls_os_sem_acquire(spi_fls->fls_lock, 0);
- drv = spi_fls->current_drv;
- err = TLS_FLS_STATUS_OK;
- switch (type)
- {
- case TLS_FLS_PARAM_TYPE_ID:
- *((u32 *) param) = drv->id;
- break;
- case TLS_FLS_PARAM_TYPE_SIZE:
- *((u32 *) param) = drv->total_size;
- break;
- case TLS_FLS_PARAM_TYPE_PAGE_SIZE:
- *((u32 *) param) = drv->page_size;
- break;
- case TLS_FLS_PARAM_TYPE_PROG_SIZE:
- *((u32 *) param) = drv->program_size;
- break;
- case TLS_FLS_PARAM_TYPE_SECTOR_SIZE:
- *((u32 *) param) = drv->sector_size;
- break;
- default:
- TLS_DBGPRT_WARNING("invalid parameter ID!\n");
- err = TLS_FLS_STATUS_EINVAL;
- break;
- }
- tls_os_sem_release(spi_fls->fls_lock);
- return err;
- }
- int tls_spifls_drv_register(struct tls_fls_drv *fls_drv)
- {
- u32 cpu_sr;
- struct tls_fls_drv *drv;
- if (fls_drv == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EINVAL;
- }
- dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
- {
- if (drv->id == fls_drv->id)
- {
- TLS_DBGPRT_WARNING
- ("corresponding spi flash driver has registered!\n");
- return TLS_FLS_STATUS_EEXIST;
- }
- }
- cpu_sr = tls_os_set_critical();
- dl_list_add_tail((struct dl_list *) &spi_fls->fls_drvs,
- (struct dl_list *) &fls_drv->drv_list);
- tls_os_release_critical(cpu_sr);
- TLS_DBGPRT_FLASH_INFO("the spi flash driver is registered successfully!\n");
- return TLS_FLS_STATUS_OK;
- }
- int tls_spifls_drv_unregister(struct tls_fls_drv *fls_drv)
- {
- TLS_DBGPRT_WARNING
- ("unregister spi flash driver operation is not supported!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- int tls_spifls_probe(void)
- {
- int err;
- u32 id;
- struct tls_fls_drv *drv;
- if (spi_fls == NULL)
- {
- TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
- return TLS_FLS_STATUS_EPERM;
- }
- if (spi_fls->current_drv != NULL)
- {
- TLS_DBGPRT_ERR("the current spi flash has fount the matched driver!\n");
- return TLS_FLS_STATUS_EBUSY;
- }
- TLS_DBGPRT_FLASH_INFO("try to read the current spi flash ID.\n");
- err = tls_spifls_read_id(&id);
- if (err != TLS_FLS_STATUS_OK)
- {
- return err;
- }
- TLS_DBGPRT_FLASH_INFO("current spi flash ID - 0x%x.\n", id);
- dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
- {
- err = drv->probe(id);
- if (err != TLS_FLS_STATUS_OK)
- {
- return err;
- }
- tls_spi_setup(drv->mode, drv->cs_active, drv->clock);
- TLS_DBGPRT_FLASH_INFO("matched the spi flash driver.\n");
- spi_fls->current_drv = drv;
- break;
- }
- if (spi_fls->current_drv == NULL)
- {
- TLS_DBGPRT_WARNING("not found the matched spi flash driver!\n");
- return TLS_FLS_STATUS_ENODRV;
- }
- return TLS_FLS_STATUS_OK;
- }
- int tls_spifls_init(void)
- {
- struct tls_fls *fls;
- int err;
- if (spi_fls != NULL)
- {
- TLS_DBGPRT_ERR("flash driver module has been installed!\n");
- return TLS_FLS_STATUS_EBUSY;
- }
- fls = (struct tls_fls *) tls_mem_alloc(sizeof(struct tls_fls));
- if (fls == NULL)
- {
- TLS_DBGPRT_ERR("allocate @spi_fls fail!\n");
- return TLS_FLS_STATUS_ENOMEM;
- }
- memset(fls, 0, sizeof(*fls));
- dl_list_init((struct dl_list *) &fls->fls_drvs);
- err = tls_os_sem_create(&fls->fls_lock, 1);
- if (err != TLS_OS_SUCCESS)
- {
- tls_mem_free(fls);
- TLS_DBGPRT_ERR("create semaphore @fls_lock fail!\n");
- return TLS_FLS_STATUS_ENOMEM;
- }
- spi_fls = fls;
- tls_spifls_drv_install();
- return TLS_FLS_STATUS_OK;
- }
- int tls_spifls_exit(void)
- {
- TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n");
- return TLS_FLS_STATUS_EPERM;
- }
|