From 008340a82dde33d195d6dc5e9f687ac30d6ab2a7 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Thu, 29 Oct 2020 18:45:17 +0800 Subject: [PATCH] drivers: rkflash: Change to use the api which the oob area available Fixes: 69f3c341d9df ("drivers: rkflash: Support spinand non aligned read") Change-Id: I3146cd574ac77c2d1a0b5b6563440d86766a0a9a Signed-off-by: Jon Lin --- drivers/rkflash/Makefile | 2 +- drivers/rkflash/sfc_nand.c | 2 +- drivers/rkflash/sfc_nand_mtd.c | 11 +++-- drivers/rkflash/sfc_nand_mtd.h | 6 +++ drivers/rkflash/sfc_nand_mtd_bbt.c | 70 +++++++++++++++++++++++------- 5 files changed, 69 insertions(+), 22 deletions(-) diff --git a/drivers/rkflash/Makefile b/drivers/rkflash/Makefile index d087638ce738..283a217eb6ca 100644 --- a/drivers/rkflash/Makefile +++ b/drivers/rkflash/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_RK_NANDC_NAND) += rkflash_blk.o rkflash_debug.o rksftl.o rknandc_base.o nand_boot.o flash.o nandc.o obj-$(CONFIG_RK_SFC_NAND) += rkflash_blk.o rkflash_debug.o rksftl.o rksfc_base.o sfc_nand_boot.o sfc_nand.o sfc.o -obj-$(CONFIG_RK_SFC_NAND_MTD) += sfc_nand_mtd.o +obj-$(CONFIG_RK_SFC_NAND_MTD) += sfc_nand_mtd.o sfc_nand_mtd_bbt.o obj-$(CONFIG_RK_SFC_NOR) += rkflash_blk.o rkflash_debug.o rksfc_base.o sfc_nor_boot.o sfc_nor.o sfc.o obj-$(CONFIG_RK_SFC_NOR_MTD) += sfc_nor_mtd.o diff --git a/drivers/rkflash/sfc_nand.c b/drivers/rkflash/sfc_nand.c index 9bc02fab7e9e..3a03acb13a57 100644 --- a/drivers/rkflash/sfc_nand.c +++ b/drivers/rkflash/sfc_nand.c @@ -697,7 +697,7 @@ u32 sfc_nand_read_page_raw(u8 cs, u32 addr, u32 *p_page_buf) { u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page; - return sfc_nand_read(addr, gp_page_buf, 0, page_size); + return sfc_nand_read(addr, p_page_buf, 0, page_size); } u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare) diff --git a/drivers/rkflash/sfc_nand_mtd.c b/drivers/rkflash/sfc_nand_mtd.c index 6d2cd7dc910d..1b4d306050cf 100644 --- a/drivers/rkflash/sfc_nand_mtd.c +++ b/drivers/rkflash/sfc_nand_mtd.c @@ -11,8 +11,11 @@ #include "rkflash_blk.h" #include "rkflash_debug.h" +#include "sfc_nand.h" #include "sfc_nand_mtd.h" +#ifdef CONFIG_RK_SFC_NAND_MTD + static struct mtd_partition nand_parts[MAX_PART_COUNT]; static inline struct snand_mtd_dev *mtd_to_priv(struct mtd_info *ptr_mtd) @@ -21,7 +24,7 @@ static inline struct snand_mtd_dev *mtd_to_priv(struct mtd_info *ptr_mtd) offsetof(struct snand_mtd_dev, mtd)); } -static int sfc_nand_erase_mtd(struct mtd_info *mtd, u32 addr) +int sfc_nand_erase_mtd(struct mtd_info *mtd, u32 addr) { int ret; @@ -127,7 +130,7 @@ static int sfc_nand_read_mtd(struct mtd_info *mtd, loff_t from, return ret ? ret : max_bitflips; } -static int sfc_nand_isbad_mtd(struct mtd_info *mtd, loff_t ofs) +int sfc_nand_isbad_mtd(struct mtd_info *mtd, loff_t ofs) { int ret; struct snand_mtd_dev *p_dev = mtd_to_priv(mtd); @@ -220,8 +223,6 @@ out: return ret; } -#include "sfc_nand_mtd_bbt.c" - static int sfc_erase_mtd(struct mtd_info *mtd, struct erase_info *instr) { struct snand_mtd_dev *p_dev = mtd_to_priv(mtd); @@ -418,3 +419,5 @@ error_out: return ret; } + +#endif diff --git a/drivers/rkflash/sfc_nand_mtd.h b/drivers/rkflash/sfc_nand_mtd.h index d32e7580bde1..0d49c74654ab 100644 --- a/drivers/rkflash/sfc_nand_mtd.h +++ b/drivers/rkflash/sfc_nand_mtd.h @@ -68,9 +68,15 @@ static inline struct snand_mtd_dev *mtd_to_snanddev(struct mtd_info *mtd) return mtd->priv; } +int snanddev_bbt_init(struct snand_mtd_dev *nand); +void snanddev_bbt_cleanup(struct snand_mtd_dev *nand); int snanddev_bbt_update(struct snand_mtd_dev *nand); int snanddev_bbt_get_block_status(const struct snand_mtd_dev *nand, unsigned int entry); int snanddev_bbt_set_block_status(struct snand_mtd_dev *nand, unsigned int entry, enum nand_bbt_block_status status); + +int sfc_nand_isbad_mtd(struct mtd_info *mtd, loff_t ofs); +int sfc_nand_erase_mtd(struct mtd_info *mtd, u32 addr); + #endif diff --git a/drivers/rkflash/sfc_nand_mtd_bbt.c b/drivers/rkflash/sfc_nand_mtd_bbt.c index efa9d95338b7..a6ca9da20154 100644 --- a/drivers/rkflash/sfc_nand_mtd_bbt.c +++ b/drivers/rkflash/sfc_nand_mtd_bbt.c @@ -7,8 +7,10 @@ * Peter Pan */ +#include #include +#include "sfc_nand.h" #include "sfc_nand_mtd.h" #ifdef CONFIG_MTD_NAND_BBT_USING_FLASH @@ -44,12 +46,13 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update) unsigned int nbytes = DIV_ROUND_UP(nblocks * bits_per_block, BITS_PER_LONG) * sizeof(*nand->bbt.cache); struct mtd_info *mtd = snanddev_to_mtd(nand); - u8 *data_buf, *oob_buf; + u8 *data_buf, *oob_buf, *temp_buf; struct nanddev_bbt_info *bbt_info; struct mtd_oob_ops ops; - int bbt_page_num; + u32 bbt_page_num; int ret = 0; unsigned int version = 0; + u32 page_addr, i; if (!nand->bbt.cache) return -ENOMEM; @@ -74,7 +77,7 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update) bbt_info = (struct nanddev_bbt_info *)(data_buf + nbytes); memset(&ops, 0, sizeof(struct mtd_oob_ops)); - ops.mode = MTD_OPS_RAW; + ops.mode = MTD_OPS_PLACE_OOB; ops.datbuf = data_buf; ops.len = bbt_page_num * mtd->writesize; ops.oobbuf = oob_buf; @@ -82,14 +85,27 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update) ops.ooboffs = 0; /* Store one entry for each block */ - ret = sfc_nand_read_mtd(mtd, block * mtd->erasesize, &ops); - if (ret < 0) { - pr_err("%s fail %d\n", __func__, ret); - ret = -EIO; - goto out; - } else { - ret = 0; + temp_buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); + if (!temp_buf) { + kfree(data_buf); + kfree(oob_buf); + + return -ENOMEM; } + page_addr = (u32)(block << (mtd->erasesize_shift - mtd->writesize_shift)); + for (i = 0; i < bbt_page_num; i++) { + ret = sfc_nand_read_page_raw(0, page_addr + i, (u32 *)temp_buf); + if (ret < 0) { + pr_err("%s fail %d\n", __func__, ret); + ret = -EIO; + kfree(temp_buf); + goto out; + } + + memcpy(ops.datbuf + i * mtd->writesize, temp_buf, mtd->writesize); + memcpy(ops.oobbuf + i * mtd->oobsize, temp_buf + mtd->writesize, mtd->oobsize); + } + kfree(temp_buf); if (oob_buf[0] != 0xff && !memcmp(bbt_pattern, bbt_info->pattern, 4)) version = bbt_info->version; @@ -114,11 +130,12 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block) unsigned int nbytes = DIV_ROUND_UP(nblocks * bits_per_block, BITS_PER_LONG) * sizeof(*nand->bbt.cache); struct mtd_info *mtd = snanddev_to_mtd(nand); - u8 *data_buf, *oob_buf; + u8 *data_buf, *oob_buf, *temp_buf; struct nanddev_bbt_info *bbt_info; struct mtd_oob_ops ops; - int bbt_page_num; + u32 bbt_page_num; int ret = 0; + u32 page_addr, i; BBT_DBG("write_bbt to blk=%d ver=%d\n", block, nand->bbt.version); if (!nand->bbt.cache) @@ -149,7 +166,7 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block) bbt_info->version = nand->bbt.version; /* Store one entry for each block */ - ret = sfc_nand_erase_mtd(mtd, block << mtd->erasesize_shift); + ret = sfc_nand_erase_mtd(mtd, block / mtd->erasesize); if (ret) goto out; @@ -159,7 +176,28 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block) ops.oobbuf = oob_buf; ops.ooblen = bbt_page_num * mtd->oobsize; ops.ooboffs = 0; - ret = sfc_nand_write_mtd(mtd, block * mtd->erasesize, &ops); + + temp_buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); + if (!temp_buf) { + kfree(data_buf); + kfree(oob_buf); + + return -ENOMEM; + } + page_addr = (u32)(block << (mtd->erasesize_shift - mtd->writesize_shift)); + for (i = 0; i < bbt_page_num; i++) { + memcpy(temp_buf, ops.datbuf + i * mtd->writesize, mtd->writesize); + memcpy(temp_buf + mtd->writesize, ops.oobbuf + i * mtd->oobsize, mtd->oobsize); + + ret = sfc_nand_prog_page_raw(0, page_addr + i, (u32 *)temp_buf); + if (ret < 0) { + pr_err("%s fail %d\n", __func__, ret); + ret = -EIO; + kfree(temp_buf); + goto out; + } + } + kfree(temp_buf); out: kfree(data_buf); @@ -196,7 +234,7 @@ static int nanddev_scan_bbt(struct snand_mtd_dev *nand) { unsigned int nblocks = snanddev_neraseblocks(nand); u32 start_block, block; - int ret; + int ret = 0; nand->bbt.version = 0; start_block = nblocks - NANDDEV_BBT_SCAN_MAXBLOCKS; @@ -213,7 +251,7 @@ static int nanddev_scan_bbt(struct snand_mtd_dev *nand) } } - return 0; + return ret; } #endif