From 633f8126a68fb9cc84173eec74a451b7f2795ecc Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Sun, 9 Mar 2025 02:02:24 +0800 Subject: [PATCH] atf: add support for dosilicon fmsh gsto spi nand Signed-off-by: Tianling Shen --- .../drivers/mtd/nand/spi_nand.c | 34 +++++++++++++------ .../drivers/spi_nand/mtk_spi_nand.c | 28 +++++++++++---- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/atf-20220606-637ba581b/drivers/mtd/nand/spi_nand.c b/atf-20220606-637ba581b/drivers/mtd/nand/spi_nand.c index 4688cea88..f4d600f1f 100644 --- a/atf-20220606-637ba581b/drivers/mtd/nand/spi_nand.c +++ b/atf-20220606-637ba581b/drivers/mtd/nand/spi_nand.c @@ -19,8 +19,11 @@ #define SPI_NAND_MAX_ID_LEN 4U #define DELAY_US_400MS 400000U +#define DOSILICON_ID 0xE5U #define ETRON_ID 0xD5U +#define FMSH_ID 0xA1U #define GIGADEVICE_ID 0xC8U +#define GSTO_ID 0x52U #define MACRONIX_ID 0xC2U #define MICRON_ID 0x2CU #define TOSHIBA_ID 0x98U @@ -48,12 +51,12 @@ static struct spinand_device spinand_dev; .quad_mode = (_quad_mode), .need_qe = (_need_qe)} static const struct spi_nand_info spi_nand_flash[] = { - /*SPI_NAND_INFO("W25N01GV", + SPI_NAND_INFO("W25N01GV", SPI_NAND_ID(true, 3, 0xef, 0xaa, 0x21, 0x00), SPI_NAND_MEMORG_1G_2K_64, true, false), SPI_NAND_INFO("MX35LF1GE4AB", SPI_NAND_ID(true, 2, 0xc2, 0x12, 0x00, 0x00), - SPI_NAND_MEMORG_1G_2K_64, true, true)*/ + SPI_NAND_MEMORG_1G_2K_64, true, true) }; static int spi_nand_reg(bool read_reg, uint8_t reg, uint8_t *val, @@ -122,7 +125,10 @@ static int spi_nand_quad_enable(uint8_t manufacturer_id) if (manufacturer_id != MACRONIX_ID && manufacturer_id != GIGADEVICE_ID && - manufacturer_id != ETRON_ID) { + manufacturer_id != GSTO_ID && + manufacturer_id != DOSILICON_ID && + manufacturer_id != ETRON_ID && + manufacturer_id != FMSH_ID) { return 0; } @@ -356,6 +362,10 @@ static int spi_nand_check_pp(struct parameter_page *pp, uint8_t *sel) INFO("PP COPY %d CRC read: 0x%x, compute: 0x%x\n", i, crc, crc_compute); + // Integrity CRC (bytes 254-255) on FMSH was reversed + if (crc != crc_compute) + crc = htobe16(pp->integrity_crc); + if (crc != crc_compute) { ret = -EBADMSG; continue; @@ -392,8 +402,9 @@ static int spi_nand_check_pp(struct parameter_page *pp, uint8_t *sel) return ret; } -static int spi_nand_read_pp(struct parameter_page *pp, uint8_t *sel) +static int spi_nand_read_pp(uint8_t *id, struct parameter_page *pp, uint8_t *sel) { + const bool is_dosilicon = (id[1] == DOSILICON_ID); uint8_t status; uint8_t cfg_reg; int ret, op_ret; @@ -405,7 +416,7 @@ static int spi_nand_read_pp(struct parameter_page *pp, uint8_t *sel) return ret; } - ret = spi_nand_write_reg(SPI_NAND_REG_CFG, cfg_reg | BIT(6)); + ret = spi_nand_write_reg(SPI_NAND_REG_CFG, is_dosilicon ? BIT(6) : (cfg_reg | BIT(6))); if (ret != 0) { return ret; } @@ -441,7 +452,7 @@ out: ERROR("Parameter page read failed\n"); } - ret = spi_nand_write_reg(SPI_NAND_REG_CFG, cfg_reg); + ret = spi_nand_write_reg(SPI_NAND_REG_CFG, is_dosilicon ? 0x10 : cfg_reg); if (ret != 0) { return ret; } @@ -578,12 +589,15 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size) return ret; } - ret = spi_nand_read_pp(pp, &sel); + ret = spi_nand_read_id(id); + if (ret != 0) { + ERROR("SPI_NAND Read ID failed.\n"); + return ret; + } + + ret = spi_nand_read_pp(id, pp, &sel); if (ret != 0) { ERROR("Parameter page read fail, fallback to read ID.\n"); - ret = spi_nand_read_id(id); - if (ret != 0) - return ret; spi_nand_set_data_via_id(&spinand_dev, id, &vendor_id); } else { vendor_id = pp[sel].manufactuere_id; diff --git a/atf-20240117-bacca82a8/plat/mediatek/apsoc_common/drivers/spi_nand/mtk_spi_nand.c b/atf-20240117-bacca82a8/plat/mediatek/apsoc_common/drivers/spi_nand/mtk_spi_nand.c index 33474e098..dde9ed78a 100644 --- a/atf-20240117-bacca82a8/plat/mediatek/apsoc_common/drivers/spi_nand/mtk_spi_nand.c +++ b/atf-20240117-bacca82a8/plat/mediatek/apsoc_common/drivers/spi_nand/mtk_spi_nand.c @@ -19,8 +19,11 @@ #define SPI_NAND_MAX_ID_LEN 4U #define DELAY_US_400MS 400000U +#define DOSILICON_ID 0xE5U #define ETRON_ID 0xD5U +#define FMSH_ID 0xA1U #define GIGADEVICE_ID 0xC8U +#define GSTO_ID 0x52U #define MACRONIX_ID 0xC2U #define MICRON_ID 0x2CU #define TOSHIBA_ID 0x98U @@ -129,7 +132,10 @@ static int spi_nand_quad_enable(uint8_t manufacturer_id) if (manufacturer_id != MACRONIX_ID && manufacturer_id != GIGADEVICE_ID && + manufacturer_id != GSTO_ID && + manufacturer_id != DOSILICON_ID && manufacturer_id != ETRON_ID && + manufacturer_id != FMSH_ID && manufacturer_id != FORESEE_ID) { return 0; } @@ -364,6 +370,10 @@ static int spi_nand_check_pp(struct parameter_page *pp, uint8_t *sel) INFO("PP COPY %d CRC read: 0x%x, compute: 0x%x\n", i, crc, crc_compute); + // Integrity CRC (bytes 254-255) on FMSH was reversed + if (crc != crc_compute) + crc = htobe16(pp->integrity_crc); + if (crc != crc_compute) { ret = -EBADMSG; continue; @@ -400,8 +410,9 @@ static int spi_nand_check_pp(struct parameter_page *pp, uint8_t *sel) return ret; } -static int spi_nand_read_pp(struct parameter_page *pp, uint8_t *sel) +static int spi_nand_read_pp(uint8_t *id, struct parameter_page *pp, uint8_t *sel) { + const bool is_dosilicon = (id[1] == DOSILICON_ID); uint8_t status; uint8_t cfg_reg; int ret, op_ret; @@ -413,7 +424,7 @@ static int spi_nand_read_pp(struct parameter_page *pp, uint8_t *sel) return ret; } - ret = spi_nand_write_reg(SPI_NAND_REG_CFG, cfg_reg | BIT(6)); + ret = spi_nand_write_reg(SPI_NAND_REG_CFG, is_dosilicon ? BIT(6) : (cfg_reg | BIT(6))); if (ret != 0) { return ret; } @@ -449,7 +460,7 @@ out: ERROR("Parameter page read failed\n"); } - ret = spi_nand_write_reg(SPI_NAND_REG_CFG, cfg_reg); + ret = spi_nand_write_reg(SPI_NAND_REG_CFG, is_dosilicon ? 0x10 : cfg_reg); if (ret != 0) { return ret; } @@ -589,12 +600,15 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size) return ret; } - ret = spi_nand_read_pp(pp, &sel); + ret = spi_nand_read_id(id); + if (ret != 0) { + ERROR("SPI_NAND Read ID failed.\n"); + return ret; + } + + ret = spi_nand_read_pp(id, pp, &sel); if (ret != 0) { ERROR("Parameter page read fail, fallback to read ID.\n"); - ret = spi_nand_read_id(id); - if (ret != 0) - return ret; spi_nand_set_data_via_id(&spinand_dev, id, &vendor_id); } else { vendor_id = pp[sel].manufactuere_id;