From 0c857d4c9cd9dc8e8ebba18cf9e9b10513ccb35d Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 3 Mar 2021 08:57:29 +0800 Subject: [PATCH 15/21] mtd: mtk-snand: add support for SPL Add support to initialize SPI-NAND in SPL. Add implementation for SPL NAND loader. Signed-off-by: Weijie Gao --- drivers/mtd/mtk-snand/Kconfig | 6 ++ drivers/mtd/mtk-snand/Makefile | 4 + drivers/mtd/mtk-snand/mtk-snand-spl.c | 132 ++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 drivers/mtd/mtk-snand/mtk-snand-spl.c --- a/drivers/mtd/mtk-snand/Kconfig +++ b/drivers/mtd/mtk-snand/Kconfig @@ -19,3 +19,9 @@ config MTK_SPI_NAND_MTD help This option enables access to SPI-NAND flashes through the MTD interface of MediaTek SPI NAND Flash Controller + +config SPL_MTK_SPI_NAND + tristate "SPL support for MediaTek SPI NAND flash controller" + depends on MTK_SPI_NAND + help + This option enables access to SPI-NAND flashes in the SPL stage --- a/drivers/mtd/mtk-snand/Makefile +++ b/drivers/mtd/mtk-snand/Makefile @@ -8,4 +8,8 @@ obj-y += mtk-snand.o mtk-snand-ecc.o mtk-snand-ids.o mtk-snand-os.o obj-$(CONFIG_MTK_SPI_NAND_MTD) += mtk-snand-mtd.o +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_SPL_MTK_SPI_NAND) += mtk-snand-spl.o +endif + ccflags-y += -DPRIVATE_MTK_SNAND_HEADER --- /dev/null +++ b/drivers/mtd/mtk-snand/mtk-snand-spl.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. + * + * Author: Weijie Gao + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mtk-snand.h" + +static struct mtk_snand *snf; +static struct mtk_snand_chip_info cinfo; +static u32 oobavail; + +static u8 *page_cache; + +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) +{ + u32 sizeremain = size, chunksize, leading; + uint32_t off = offs, writesize_mask = cinfo.pagesize - 1; + uint8_t *ptr = dst; + int ret; + + if (!snf) + return -ENODEV; + + while (sizeremain) { + WATCHDOG_RESET(); + + leading = off & writesize_mask; + chunksize = cinfo.pagesize - leading; + if (chunksize > sizeremain) + chunksize = sizeremain; + + if (chunksize == cinfo.pagesize) { + ret = mtk_snand_read_page(snf, off - leading, ptr, + NULL, false); + if (ret) + break; + } else { + ret = mtk_snand_read_page(snf, off - leading, + page_cache, NULL, false); + if (ret) + break; + + memcpy(ptr, page_cache + leading, chunksize); + } + + off += chunksize; + ptr += chunksize; + sizeremain -= chunksize; + } + + return ret; +} + +void nand_init(void) +{ + struct mtk_snand_platdata mtk_snand_pdata = {}; + struct udevice *dev; + fdt_addr_t base; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(mtk_snand), + &dev); + if (ret) { + printf("mtk-snand-spl: Device instance not found!\n"); + return; + } + + base = dev_read_addr_name(dev, "nfi"); + if (base == FDT_ADDR_T_NONE) { + printf("mtk-snand-spl: NFI base not set\n"); + return; + } + mtk_snand_pdata.nfi_base = map_sysmem(base, 0); + + base = dev_read_addr_name(dev, "ecc"); + if (base == FDT_ADDR_T_NONE) { + printf("mtk-snand-spl: ECC base not set\n"); + return; + } + mtk_snand_pdata.ecc_base = map_sysmem(base, 0); + + mtk_snand_pdata.soc = dev_get_driver_data(dev); + mtk_snand_pdata.quad_spi = dev_read_bool(dev, "quad-spi"); + + ret = mtk_snand_init(NULL, &mtk_snand_pdata, &snf); + if (ret) { + printf("mtk-snand-spl: failed to initialize SPI-NAND\n"); + return; + } + + mtk_snand_get_chip_info(snf, &cinfo); + + oobavail = cinfo.num_sectors * (cinfo.fdm_size - 1); + + printf("SPI-NAND: %s (%uMB)\n", cinfo.model, + (u32)(cinfo.chipsize >> 20)); + + page_cache = malloc(cinfo.pagesize + cinfo.sparesize); + if (!page_cache) { + mtk_snand_cleanup(snf); + printf("mtk-snand-spl: failed to allocate page cache\n"); + } +} + +void nand_deselect(void) +{ + +} + +static const struct udevice_id mtk_snand_ids[] = { + { .compatible = "mediatek,mt7622-snand", .data = SNAND_SOC_MT7622 }, + { .compatible = "mediatek,mt7629-snand", .data = SNAND_SOC_MT7629 }, + { .compatible = "mediatek,mt7986-snand", .data = SNAND_SOC_MT7986 }, + { /* sentinel */ }, +}; + +U_BOOT_DRIVER(mtk_snand) = { + .name = "mtk-snand", + .id = UCLASS_MTD, + .of_match = mtk_snand_ids, + .flags = DM_FLAG_PRE_RELOC, +};