From 9e8ac4fc7125795ac5e8834aaf454fd45b99c580 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Mon, 25 Jul 2022 10:53:03 +0800 Subject: [PATCH 46/71] mtd: mtk-snand: add NMBM support for SPL Add NMBM support for mtk-snand SPL loader Signed-off-by: Weijie Gao --- drivers/mtd/mtk-snand/mtk-snand-spl.c | 127 ++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) --- a/drivers/mtd/mtk-snand/mtk-snand-spl.c +++ b/drivers/mtd/mtk-snand/mtk-snand-spl.c @@ -13,12 +13,134 @@ #include #include +#include + #include "mtk-snand.h" static struct mtk_snand *snf; static struct mtk_snand_chip_info cinfo; static u32 oobavail; +#ifdef CONFIG_ENABLE_NAND_NMBM +static struct nmbm_instance *ni; + +static int nmbm_lower_read_page(void *arg, uint64_t addr, void *buf, void *oob, + enum nmbm_oob_mode mode) +{ + int ret; + bool raw = mode == NMBM_MODE_RAW ? true : false; + + if (mode == NMBM_MODE_AUTO_OOB) { + ret = mtk_snand_read_page_auto_oob(snf, addr, buf, oob, + oobavail, NULL, false); + } else { + ret = mtk_snand_read_page(snf, addr, buf, oob, raw); + } + + if (ret == -EBADMSG) + return 1; + else if (ret >= 0) + return 0; + + return ret; +} + +static int nmbm_lower_write_page(void *arg, uint64_t addr, const void *buf, + const void *oob, enum nmbm_oob_mode mode) +{ + bool raw = mode == NMBM_MODE_RAW ? true : false; + + if (mode == NMBM_MODE_AUTO_OOB) { + return mtk_snand_write_page_auto_oob(snf, addr, buf, oob, + oobavail, NULL, false); + } + + return mtk_snand_write_page(snf, addr, buf, oob, raw); +} + +static int nmbm_lower_erase_block(void *arg, uint64_t addr) +{ + return mtk_snand_erase_block(snf, addr); +} + +static int nmbm_lower_is_bad_block(void *arg, uint64_t addr) +{ + return mtk_snand_block_isbad(snf, addr); +} + +static int nmbm_lower_mark_bad_block(void *arg, uint64_t addr) +{ + return mtk_snand_block_markbad(snf, addr); +} + +static void nmbm_lower_log(void *arg, enum nmbm_log_category level, + const char *fmt, va_list ap) +{ + vprintf(fmt, ap); +} + +static int nmbm_init(void) +{ + struct nmbm_lower_device nld; + size_t ni_size; + int ret; + + memset(&nld, 0, sizeof(nld)); + + nld.flags = NMBM_F_CREATE; + nld.max_ratio = CONFIG_NMBM_MAX_RATIO; + nld.max_reserved_blocks = CONFIG_NMBM_MAX_BLOCKS; + + nld.size = cinfo.chipsize; + nld.erasesize = cinfo.blocksize; + nld.writesize = cinfo.pagesize; + nld.oobsize = cinfo.sparesize; + nld.oobavail = oobavail; + + nld.read_page = nmbm_lower_read_page; + nld.write_page = nmbm_lower_write_page; + nld.erase_block = nmbm_lower_erase_block; + nld.is_bad_block = nmbm_lower_is_bad_block; + nld.mark_bad_block = nmbm_lower_mark_bad_block; + + nld.logprint = nmbm_lower_log; + + ni_size = nmbm_calc_structure_size(&nld); + ni = malloc(ni_size); + if (!ni) { + printf("Failed to allocate memory (0x%u) for NMBM instance\n", + ni_size); + return -ENOMEM; + } + + memset(ni, 0, ni_size); + + printf("Initializing NMBM ...\n"); + + ret = nmbm_attach(&nld, ni); + if (ret) { + ni = NULL; + return ret; + } + + return 0; +} + +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) +{ + size_t retlen; + + if (!ni) + return -ENODEV; + + nmbm_read_range(ni, offs, size, dst, NMBM_MODE_PLACE_OOB, &retlen); + if (retlen != size) + return -EIO; + + return 0; +} + +#else static u8 *page_cache; int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) @@ -60,6 +182,7 @@ int nand_spl_load_image(uint32_t offs, u return ret; } +#endif void nand_init(void) { @@ -105,11 +228,15 @@ void nand_init(void) printf("SPI-NAND: %s (%uMB)\n", cinfo.model, (u32)(cinfo.chipsize >> 20)); +#ifdef CONFIG_ENABLE_NAND_NMBM + nmbm_init(); +#else page_cache = malloc(cinfo.pagesize + cinfo.sparesize); if (!page_cache) { mtk_snand_cleanup(snf); printf("mtk-snand-spl: failed to allocate page cache\n"); } +#endif } void nand_deselect(void)