diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 43729875b4ff2de0fa6d5d9b997b3e1e2b49431a..d4f9f5c506af862e5dd0da357d7a719af2975553 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -119,20 +119,6 @@ config RT_USING_MTD_NAND default n endif -config RT_USING_MTD - bool "Using Memory Technology Device (MTD)" - default n - - if RT_USING_MTD - config MTD_USING_NOR - bool "Using MTD Nor Flash device" - default n - - config MTD_USING_NAND - bool "Using MTD Nand Flash device" - default n - endif - config RT_USING_PM bool "Using Power Management device drivers" default n diff --git a/components/drivers/include/drivers/mtd.h b/components/drivers/include/drivers/mtd.h deleted file mode 100644 index fb7ea4389d603d1a578415f8cf0c0d8507bd197a..0000000000000000000000000000000000000000 --- a/components/drivers/include/drivers/mtd.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTD_H__ -#define __MTD_H__ - -#include -#include -#include - -#define MTD_TYPE_NOR 1 -#define MTD_TYPE_NAND 2 - - /** - * MTD operation modes - * - * @MTD_OPM_PLACE_OOB: OOB data are placed at the given offset (default) - * @MTD_OPM_AUTO_OOB: OOB data are automatically placed at the free areas - * @MTD_OPM_RAW: data are transferred as-is, with no error correction; - */ -enum mtd_opm -{ - MTD_OPM_PLACE_OOB = 0, - MTD_OPM_AUTO_OOB = 1, - MTD_OPM_RAW = 2, -}; - -#ifndef loff_t -typedef long loff_t; -#endif - -struct mtd_oob_region -{ - uint8_t offset; - uint8_t length; -}; - -typedef struct mtd_info -{ - struct rt_device parent; - - const struct mtd_ops *ops; - - uint16_t oob_size; - uint16_t sector_size; /* Minimal writable flash unit size */ - uint32_t block_size:28; /* Erase size for the device */ - uint32_t type:4; - - size_t size; /* Total size of the MTD */ - loff_t offset; /* At which this MTD starts, from the beginning of the MEMORY */ - struct mtd_info *master; - - void *priv; -}rt_mtd_t; - -struct mtd_io_desc -{ - uint8_t mode; /* operation mode(enum mtd_opm) */ - uint8_t ooblen; /* number of oob bytes to write/read */ - uint8_t oobretlen; /* number of oob bytes written/read */ - uint8_t ooboffs; /* offset in the oob area */ - uint8_t *oobbuf; - - size_t datlen; /* number of data bytes to write/read */ - size_t datretlen; /* number of data bytes written/read */ - uint8_t *datbuf; /* if NULL only oob are read/written */ -}; - -struct mtd_ops -{ - int(*erase)(rt_mtd_t *mtd, loff_t addr, size_t len); /* return 0 if success */ - int(*read) (rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *ops); /* return 0 if success */ - int(*write) (rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *ops); /* return 0 if success */ - int(*isbad) (rt_mtd_t *mtd, uint32_t block); /* return 1 if bad, 0 not bad */ - int(*markbad) (rt_mtd_t *mtd, uint32_t block); /* return 0 if success */ -}; - -struct mtd_part -{ - const char *name; /* name of the MTD partion */ - loff_t offset; /* start addr of partion */ - size_t size; /* size of partion */ -}; - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size); -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc); -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc); -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len); -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len); -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block); - -rt_mtd_t* rt_mtd_get(const char *name); -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np); - -#endif diff --git a/components/drivers/include/drivers/mtdnand.h b/components/drivers/include/drivers/mtdnand.h deleted file mode 100644 index 2e836cb2fb957ccf5e3e328ad402c9efe62eea59..0000000000000000000000000000000000000000 --- a/components/drivers/include/drivers/mtdnand.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef _MTDNAND_H_ -#define _MTDNAND_H_ - -#include "mtd.h" - - /* Status bits */ -#define NAND_STATUS_FAIL 0x01 -#define NAND_STATUS_FAIL_N1 0x02 -#define NAND_STATUS_WP 0x80 - -typedef enum -{ - NAND_CMD_PAGE_RD, /* read data to chip's page buffer,do WaitBusy after this cmd in low driver */ - NAND_CMD_PAGE_WR0, /* write data to chip's page buffer */ - NAND_CMD_PAGE_WR1, /* do flash programe */ - NAND_CMD_BLK_ERASE, /* erase block */ - NAND_CMD_ECC_EN, /* enable gen HWECC */ - NAND_CMD_ECC_DIS /* disable gen HWECC */ -} nand_cmd_t; - -typedef enum -{ - NAND_ECCM_NONE, - NAND_ECCM_HW, -} nand_eccmode_t; - -struct nand_chip; -struct nand_ops; - -/** -* struct nand_buffers - buffer structure for read/write -* @ecccalc: buffer pointer for calculated ECC, size is oobsize. -* @ecccode: buffer pointer for ECC read from flash, size is oobsize. -* -*/ -struct nand_buffers -{ - uint8_t *ecccalc; - uint8_t *ecccode; -}; - -struct nand_ecc -{ - uint8_t mode; /* nand_eccmode_t */ - uint8_t bytes; /* gen ecc bytes per ecc step(usually 3) */ - uint16_t stepsize:12; /* min 256 */ - uint16_t _step:4; /* */ - - /* driver must set the two interface if HWECC */ - void (*calculate)(struct nand_chip *chip, const uint8_t *dat, uint8_t *ecc_code); - /* return max bit flips if can't correct,return -1 ECC is error(0 success) */ - int(*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc); - /* ignore if NONECC */ - const struct mtd_oob_region *layout; -}; - -typedef struct nand_chip -{ - rt_mtd_t parent; - - /* driver must init these */ - const struct nand_ops *ops; - struct nand_ecc ecc; - const struct mtd_oob_region *freelayout; - - /* driver do not touch */ - struct nand_buffers buffers; - uint8_t *oob_poi; - uint8_t *pagebuf; - uint32_t size; - uint16_t oobsize; - uint8_t pages_pb; - uint16_t page_size; - int(*read_page)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page); - int(*write_page)(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page); -}rt_nand_t; - -struct nand_ops -{ - int(*cmdfunc)(rt_nand_t *nand, int cmd, int page, int offset); /* send nand operation cmd, return Status bits(0 success), - if nand is busy please wait in low driver */ - int(*read_buf)(rt_nand_t *nand, uint8_t *buf, int len); /* read data from nand chip's page buffer */ - int(*write_buf)(rt_nand_t *nand, const uint8_t *buf, int len);/* write data to nand chip's page buffer */ - int(*isbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(not 0xff is bad) */ - int(*markbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(set to 0x00) */ -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size); - -#endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtdnor.h b/components/drivers/include/drivers/mtdnor.h deleted file mode 100644 index ccb7466b4b4222b334086b5553ca6edadc0782c9..0000000000000000000000000000000000000000 --- a/components/drivers/include/drivers/mtdnor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTDNOR_H__ -#define __MTDNOR_H__ - -#include - -struct nor_ops; - -typedef struct -{ - rt_mtd_t parent; - - const struct nor_ops *ops; /* operations interface */ -}rt_nor_t; - -struct nor_ops -{ - int (*erase)(rt_nor_t *nor, loff_t addr, size_t len); /* return success erased len or error code */ - int (*read)(rt_nor_t *nor, loff_t addr, uint8_t *buf, size_t len); /* return success data size or error code */ - int (*write)(rt_nor_t *nor, loff_t addr, const uint8_t *buf, size_t len); /* return success data size or error code */ -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize); - -#endif diff --git a/components/drivers/mtd/mtd.c b/components/drivers/mtd/mtd.c deleted file mode 100644 index 3e7b4f2b54633b96ff3c937169aa73bd69851662..0000000000000000000000000000000000000000 --- a/components/drivers/mtd/mtd.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include - -static rt_mtd_t* mtd_part_alloc(rt_mtd_t *master, const struct mtd_part *part) -{ - rt_mtd_t *slave; - - slave = rt_malloc(sizeof(rt_mtd_t)); - if (slave == RT_NULL) - goto out; - - slave->master = master; - - *slave = *master; - slave->size = part->size; - slave->offset = part->offset; - -out: - - return slave; -} - -rt_mtd_t* rt_mtd_get(const char *name) -{ - rt_mtd_t *mtd; - - mtd = (rt_mtd_t *)rt_device_find(name); - if (mtd == RT_NULL) - return RT_NULL; - - if (mtd->parent.type != RT_Device_Class_MTD) - return RT_NULL; - - return mtd; -} - -/* - * Register MTD driver - * - * @parts partion description - * @np number of partitions - * @return number of unregistered partitions - * -*/ -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np) -{ - int ret; - rt_mtd_t *slave; - - master->master = master; - master->parent.type = RT_Device_Class_MTD; - - if (np > 0) - { - master->offset = parts->offset; - master->size = parts->size; - - ret = rt_device_register((rt_device_t)master, parts->name, 0); - if (ret != 0) - goto _out; - - np --; - parts ++; - } - - while (np > 0) - { - slave = mtd_part_alloc(master, parts); - if (!slave) - break; - ret = rt_device_register((rt_device_t)slave, parts->name, 0); - if (ret) - break; - parts ++; - np --; - } - -_out: - return np; -} - -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks; - loff_t addr; - - total_blks = mtd->size/mtd->block_size; - if (block >= total_blks) - return -EINVAL; - addr = mtd->offset + mtd->block_size * block; - - return mtd->ops->erase(mtd->master, addr, mtd->block_size); -} - -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->isbad) - return 0; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->isbad(mtd->master, block + offset_blk); -} - -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->markbad) - return -EOPNOTSUPP; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->markbad(mtd->master, block + offset_blk); -} - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - if (addr > mtd->size || (addr + size) > mtd->size) - return -EINVAL; - addr += mtd->offset; - - return mtd->ops->erase(mtd->master, addr, size); -} - -/* -* Read data only -* -* @from offset to read from -* @return success size or error code -*/ -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (from < 0 || from >= (loff_t)mtd->size || len > mtd->size - from) - return -EINVAL; - if (!len) - return 0; - - desc.datbuf = buf; - desc.datlen = len; - ret = mtd->ops->read(mtd->master, from + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Write data only -* -* @to offset to write from -* @return success size or error code -*/ -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (to < 0 || to >= (loff_t)mtd->size || len > mtd->size - to) - return -EINVAL; - if (!mtd->ops->write) - return -EROFS; - if (!len) - return 0; - - desc.datbuf = (uint8_t*)buf; - desc.datlen = len; - ret = mtd->ops->write(mtd->master, to + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Read data and/or out-of-band -* -* @from offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (from < 0 || from >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen > (mtd->size - from))) - return -EINVAL; - - return mtd->ops->read(mtd->master, from + mtd->offset, desc); -} - -/** -* Write data and/or out-of-band -* -* @to offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (to < 0 || to >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen >(mtd->size - to))) - return -EINVAL; - - return mtd->ops->write(mtd->master, to + mtd->offset, desc); -} diff --git a/components/drivers/mtd/mtdnand.c b/components/drivers/mtd/mtdnand.c deleted file mode 100644 index 50012219fbebf43f1d22549015b4ff486e6ff151..0000000000000000000000000000000000000000 --- a/components/drivers/mtd/mtdnand.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-09-10 heyuanjie87 first version - */ - -#include - -#define MTDTONAND(x) ((rt_nand_t*)(x)) -#define NOTALIGNED(x) ((x & (chip->page_size - 1)) != 0) -#ifndef min -#define min(a,b) (a>b? b:a) -#endif - -static uint8_t *nand_fill_oob(rt_nand_t *chip, uint8_t *oob, size_t len, struct mtd_io_desc *desc) -{ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(chip->oob_poi + desc->ooboffs, oob, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - const struct mtd_oob_region *free = chip->freelayout; - uint32_t boffs; - size_t bytes; - - bytes = min(len, free->length); - boffs = free->offset; - - rt_memcpy(chip->oob_poi + boffs, oob, bytes); - oob += bytes; - - return oob; - } - } - - return NULL; -} - -static uint8_t *nand_transfer_oob(rt_nand_t *chip, uint8_t *oob, struct mtd_io_desc *desc, size_t len) -{ - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(oob, chip->oob_poi + desc->ooboffs, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - struct mtd_oob_region *free = (struct mtd_oob_region *)chip->freelayout; - uint32_t boffs = 0, roffs = desc->ooboffs; - size_t bytes = 0; - - for (; free->length && len; free++, len -= bytes) - { - /* Read request not from offset 0? */ - if (roffs) - { - if (roffs >= free->length) - { - roffs -= free->length; - continue; - } - boffs = free->offset + roffs; - bytes = min(len, (free->length - roffs)); - roffs = 0; - } - else - { - bytes = min(len, free->length); - boffs = free->offset; - } - - rt_memcpy(oob, chip->oob_poi + boffs, bytes); - oob += bytes; - } - - return oob; - } - } - - return NULL; -} - -static int nand_read_page_raw(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - chip->ops->read_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_raw(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - chip->ops->write_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_hwecc(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t stepsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *ecc_calc = chip->buffers.ecccalc; - const uint8_t *p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += stepsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->write_buf(chip, p, stepsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - rt_memcpy(&chip->oob_poi[eccpos], ecc_calc, chip->ecc.layout->length); - - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_read_page_hwecc(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t eccsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *p = buf; - uint8_t *ecc_calc = chip->buffers.ecccalc; - uint8_t *ecc_code = chip->buffers.ecccode; - int ret = 0; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->read_buf(chip, p, eccsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - rt_memcpy(ecc_code, &chip->oob_poi[eccpos], chip->ecc.layout->length); - - eccsteps = chip->ecc._step; - p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - int stat; - - stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); - if (stat != 0) - ret = -1; - } - - return ret; -} - -static int nand_write_page(rt_nand_t *chip, const uint8_t *buf, - int oob_required, int page, int raw) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, 0x00); - - if (raw) - { - nand_write_page_raw(chip, buf, oob_required, page); - } - else - { - chip->write_page(chip, buf, oob_required, page); - } - - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status; -} - -static int nand_do_read_desc(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page, bytes; - char oob_required; - char ecc_fail = 0; - int ret = 0; - uint32_t readlen = desc->datlen; - uint16_t oobreadlen = desc->ooblen; - uint16_t max_oobsize = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob, *buf, *notalign = 0; - - /* Reject reads, which are not page aligned */ - if (NOTALIGNED(from)) - { - return -EINVAL; - } - - buf = desc->datbuf; - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - page = (int)(from / chip->page_size); - - oob = desc->oobbuf; - oob_required = oob ? 1 : 0; - - while (1) - { - bytes = min(chip->page_size, readlen); - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, 0x00); - if (NOTALIGNED(bytes)) - { - notalign = buf; - buf = chip->pagebuf; - } - /* - * Now read the page into the buffer. Absent an error, - * the read methods return max bitflips per ecc step. - */ - if (desc->mode == MTD_OPM_RAW) - { - ret = nand_read_page_raw(chip, buf, oob_required, page); - } - else - { - ret = chip->read_page(chip, buf, oob_required, page); - } - - if (ret != 0) - { - ret = -EBADMSG; - break; - } - - if (oob) - { - int toread = min(oobreadlen, max_oobsize); - - if (toread) - { - oob = nand_transfer_oob(chip, oob, desc, toread); - oobreadlen -= toread; - } - } - - if (notalign) - { - rt_memcpy(notalign, buf, bytes); - } - - buf += bytes; - readlen -= bytes; - - if (!readlen) - break; - - page++; - } - - desc->datretlen = desc->datlen - (size_t)readlen; - if (oob) - desc->oobretlen = desc->ooblen - oobreadlen; - - return ret; -} - -/* - * write with ECC - * -*/ -static int nand_do_write_desc(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page; - uint16_t writelen = desc->datlen; - uint16_t oob_required = desc->oobbuf ? 1 : 0; - uint16_t oobwritelen = desc->ooblen; - uint16_t oobmaxlen = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob = desc->oobbuf; - uint8_t *buf = desc->datbuf; - int ret; - - if (!writelen) - return 0; - - /* Reject writes, which are not page aligned */ - if (NOTALIGNED(to)) - { - return -EINVAL; - } - - page = (int)(to / chip->page_size); - - /* Don't allow multipage oob writes with offset */ - if (oob && desc->ooboffs && (desc->ooboffs + desc->ooblen > oobmaxlen)) - { - ret = -EINVAL; - goto err_out; - } - - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - while (1) - { - uint16_t bytes = min(chip->page_size, writelen); - - if (oob) - { - size_t len = min(oobwritelen, oobmaxlen); - oob = nand_fill_oob(chip, oob, len, desc); - oobwritelen -= len; - } - else - { - /* We still need to erase leftover OOB data */ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - } - - if (NOTALIGNED(bytes)) - { - uint8_t *dbtmp = buf; - buf = chip->pagebuf; - rt_memset(&buf[bytes], 0xff, chip->page_size - bytes); - rt_memcpy(buf, dbtmp, bytes); - } - ret = nand_write_page(chip, buf, oob_required, page, (desc->mode == MTD_OPM_RAW)); - if (ret) - break; - - writelen -= bytes; - if (!writelen) - break; - - buf += bytes; - page++; - } - - desc->datretlen = desc->datlen - writelen; - if (oob) - desc->oobretlen = desc->ooblen; - -err_out: - - return ret; -} - -static int nand_read_oob_std(rt_nand_t *chip, int page) -{ - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, chip->page_size); - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -/* - * read one page of OOB -*/ -static int nand_only_read_oob(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page; - int readlen = desc->ooblen; - int len; - uint8_t *buf = desc->oobbuf; - int ret = 0; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - if (desc->ooboffs >= len) //attempt to start read outside oob - { - return -EINVAL; - } - - page = (int)(from / chip->page_size); - - ret = nand_read_oob_std(chip, page); - if (ret == 0) - { - len = min(len, readlen); - buf = nand_transfer_oob(chip, buf, desc, len); - desc->oobretlen = len; - } - - return ret; -} - -static int nand_write_oob_std(rt_nand_t *chip, int page) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, chip->page_size); - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - /* Send command to program the OOB data */ - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status & NAND_STATUS_FAIL ? -EIO : 0; -} - -static int nand_only_write_oob(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page, ret, len; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - /* Do not allow write past end of page */ - if ((desc->ooboffs + desc->ooblen) > len) - { - return -EINVAL; - } - - if (desc->ooblen == 0) - { - return -EINVAL; - } - - /* get page */ - page = (int)(to / chip->page_size); - - nand_fill_oob(chip, desc->oobbuf, desc->ooblen, desc); - - ret = nand_write_oob_std(chip, page); - if (ret == 0) - desc->oobretlen = len; - - return ret; -} - -static int nand_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - rt_nand_t *chip; - int status; - int page; - uint32_t blksize; - - chip = MTDTONAND(mtd); - blksize = mtd->block_size; - page = addr / chip->page_size; - - while (size >= blksize) - { - status = chip->ops->cmdfunc(chip, NAND_CMD_BLK_ERASE, page, 0); - if (status & NAND_STATUS_FAIL) - { - break; - } - size -= blksize; - page += chip->pages_pb; - } - - return size; -} - -static int nand_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_read_oob(chip, from, desc); - else - ret = nand_do_read_desc(chip, from, desc); - -out: - - return ret; -} - -static int nand_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_write_oob(chip, to, desc); - else - ret = nand_do_write_desc(chip, to, desc); - -out: - - return ret; -} - -static int nand_block_isbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip = MTDTONAND(mtd); - - if (chip->ops->isbad) - { - ret = chip->ops->isbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - nand_read_oob_std(chip, page); - ret = chip->oob_poi[0] != 0xFF; - } - - return ret; -} - -static int nand_block_markbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - if (chip->ops->markbad) - { - ret = chip->ops->markbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - chip->oob_poi[0] = 0; - ret = nand_write_oob_std(chip, page); - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - nand_erase, - nand_read, - nand_write, - nand_block_isbad, - nand_block_markbad, -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size) -{ - uint8_t *buf; - - buf = rt_malloc(oob_size * 3); - if (buf == RT_NULL) - return -ENOMEM; - - nand->oob_poi = buf; - buf += oob_size; - nand->buffers.ecccalc = buf; - buf += oob_size; - nand->buffers.ecccode = buf; - nand->pagebuf = 0; /* alloc when unaligen access */ - - nand->pages_pb = blk_size / page_size; - nand->ecc._step = page_size / nand->ecc.stepsize; - nand->page_size = page_size; - nand->oobsize = oob_size; - - nand->parent.type = MTD_TYPE_NAND; - nand->parent.ops = &_ops; - nand->parent.sector_size = page_size; - nand->parent.block_size = blk_size; - nand->parent.oob_size = oob_size; - - switch (nand->ecc.mode) - { - case NAND_ECCM_NONE: - { - nand->read_page = nand_read_page_raw; - nand->write_page = nand_write_page_raw; - }break; - case NAND_ECCM_HW: - { - nand->read_page = nand_read_page_hwecc; - nand->write_page = nand_write_page_hwecc; - }break; - default: - { - rt_free(buf); - return -1; - } - } - - return 0; -} diff --git a/components/drivers/mtd/mtdnor.c b/components/drivers/mtd/mtdnor.c deleted file mode 100644 index 481d26167e736af3003dde7d2a9736aa33e62228..0000000000000000000000000000000000000000 --- a/components/drivers/mtd/mtdnor.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include - -#ifdef MTD_USING_NOR -static int _nor_erase(rt_mtd_t *mtd, loff_t addr, size_t len) -{ - rt_nor_t *nor; - - nor = (rt_nor_t *)mtd; - return nor->ops->erase(nor, addr, len); -} - -static int _nor_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->read(nor, from, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static int _nor_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->write(nor, to, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - _nor_erase, - _nor_read, - _nor_write, - 0, - 0 -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize) -{ - nor->parent.sector_size = 1; - nor->parent.block_size = blksize; - nor->parent.ops = &_ops; - nor->parent.type = MTD_TYPE_NOR; - nor->parent.oob_size = 0; - - return 0; -} -#endif