hzyitc / openwrt-redmi-ax3000

Openwrt for Redmi AX3000 / Xiaomi CR880x / Xiaomi CR881x
Other
417 stars 87 forks source link

请教如何添加 SPI NAND 的支持? #79

Open sseseed opened 1 month ago

sseseed commented 1 month ago

看到你也在研究 IPQ5018,我最近也在搞这个,但我水平实在太业余,网上找到一些源码算是编译出来了,但因为试的机子是 PZ-L8,使用的是 ESMT F50D1G41LB 闪存,启动时就识别不正常,前一句还正常识别nand: device found, Manufacturer ID: 0xa1, Chip ID: 0xa5,后面就是nand: unknown nand 2gib 1,8v 8-bit这样的错误信息,原厂固件显示的正常的应该是nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 128。所以考虑到是不是源码不支持这个闪存。请问怎么添加这个闪存的支持?

hzyitc commented 1 month ago

F50D1G41LB 不是这个ID。

请拆机确认你板子上用的NAND芯片

sseseed commented 1 month ago

F50D1G41LB 不是这个ID。

请拆机确认你板子上用的NAND芯片

首先,谢谢你的回复。我对比过原厂固件启动信息,的确也是显示 nand: device found, Manufacturer ID: 0xa1, Chip ID: 0xa5,闪存型号我没认真拆开看,因为有散热片和屏蔽压着所以没拆到底,只是看网上别人的拆解图的确是F50D1G41LB 。

potatoigit commented 1 month ago

应该是0x11

sseseed commented 1 month ago

F50D1G41LB 不是这个ID。

请拆机确认你板子上用的NAND芯片

刚刚拆开看了,的确和网上拆机图不同,硬件版本和网上一样,但网上拆的是 21 年产的,我手上的是 23 年产的,我手上这个的 SPI NAND 型号是 复旦微 FM25LS01。

sseseed commented 1 month ago

F50D1G41LB 不是这个ID。

请拆机确认你板子上用的NAND芯片

经过一番的瞎探索,终于找到了添加 SPI NAND 的 patch 文件并添加了 FM25LS01 进去, {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) }, 但不懂这个结构体,应该有些参数设错了,特别是 ECC 那里,我在 https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 查到 FM25LS01 的 ECC 是 1bit,所以就填成 1,SZ_512,也不知道对不对。目前能成功到识别分区那里了,但后面读不到数据提示 ECC 错误。部分关键的 TTL 回显如下:

[ 0.867862] nand: device found, Manufacturer ID: 0xa1, Chip ID: 0xa5 [ 0.867909] nand: Unknown FM25LS01 SPI NAND 1G 1.8V [ 0.873733] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 128 [ 0.878408] QPIC controller hw version Major:2, Minor:1 [ 0.886111] 17 fixed-partitions partitions found on MTD device qcom_nand.0 [ 0.891223] Creating 17 MTD partitions on "qcom_nand.0": [ 0.898153] 0x000000000000-0x000000080000 : "0:SBL1" [ 0.905109] 0x000000080000-0x000000100000 : "0:MIBIB" [ 0.910138] 0x000000100000-0x000000140000 : "0:BOOTCONFIG" [ 0.914616] 0x000000140000-0x000000180000 : "0:BOOTCONFIG1" [ 0.920055] 0x000000180000-0x000000280000 : "0:QSEE" [ 0.926815] 0x000000280000-0x000000380000 : "0:QSEE_1" [ 0.931764] 0x000000380000-0x0000003c0000 : "0:DEVCFG" [ 0.935535] 0x0000003c0000-0x000000400000 : "0:DEVCFG_1" [ 0.940821] 0x000000400000-0x000000440000 : "0:CDT" [ 0.946324] 0x000000440000-0x000000480000 : "0:CDT_1" [ 0.950828] 0x000000480000-0x000000500000 : "0:APPSBLENV" [ 0.956449] 0x000000500000-0x000000640000 : "0:APPSBL" [ 0.962891] 0x000000640000-0x000000780000 : "0:APPSBL_1" [ 0.968129] 0x000000780000-0x000000880000 : "0:ART" [ 0.972979] 0x000000880000-0x000000900000 : "0:TRAINING" [ 0.976980] 0x000000900000-0x000004300000 : "rootfs" [ 1.064560] mtd: setting mtd15 (rootfs) as root device [ 1.065941] mtdsplit: error occured while reading from "rootfs" [ 1.068709] 0x000004300000-0x000007d00000 : "rootfs_1" [ 1.557315] i2c_dev: i2c /dev entries driver [ 1.558363] cpufreq: cpufreq_online: CPU0: Running at unlisted initial frequency: 24000 KHz, changing to: 800000 KHz [ 1.561003] sdhci: Secure Digital Host Controller Interface driver [ 1.571225] sdhci: Copyright(c) Pierre Ossman [ 1.577194] sdhci-pltfm: SDHCI platform and OF driver helper [ 1.584402] remoteproc remoteproc0: releasing cd00000.remoteproc [ 1.588620] cs_system_cfg: CoreSight Configuration manager initialised [ 1.594946] NET: Registered PF_INET6 protocol family [ 1.601500] Segment Routing with IPv6 [ 1.604897] In-situ OAM (IOAM) with IPv6 [ 1.608569] NET: Registered PF_PACKET protocol family [ 1.612457] 8021q: 802.1Q VLAN Support v1.8 [ 1.617587] Registering SWP/SWPB emulation handler [ 1.642534] remoteproc remoteproc0: cd00000.remoteproc is available [ 1.643945] remoteproc remoteproc1: 4ab000.remoteproc_pd1 is available [ 1.649375] remoteproc remoteproc2: cd00000.remoteproc:remoteproc_pd2 is available [ 1.655250] ubi0: attaching mtd15 [ 1.663580] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read only 64 bytes, retry [ 1.666420] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read only 64 bytes, retry [ 1.677328] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read only 64 bytes, retry [ 1.688621] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read 64 bytes [ 1.698361] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.150 #0 [ 1.708375] Hardware name: Generic DT based system [ 1.714460] [<8030e0b0>] (unwind_backtrace) from [<80309bd8>] (show_stack+0x10/0x14) [ 1.719143] [<80309bd8>] (show_stack) from [<8067a780>] (dump_stack_lvl+0x40/0x4c) [ 1.727042] [<8067a780>] (dump_stack_lvl) from [<80791d88>] (ubi_io_read+0x138/0x33c) [ 1.734421] [<80791d88>] (ubi_io_read) from [<807921e0>] (ubi_io_read_ec_hdr+0x44/0x1f4) [ 1.742318] [<807921e0>] (ubi_io_read_ec_hdr) from [<807972f4>] (ubi_attach+0x428/0x1458) [ 1.750479] [<807972f4>] (ubi_attach) from [<8078c4e4>] (ubi_attach_mtd_dev+0x494/0xb34) [ 1.758552] [<8078c4e4>] (ubi_attach_mtd_dev) from [<80d1e7f0>] (ubi_init+0x124/0x354) [ 1.766712] [<80d1e7f0>] (ubi_init) from [<8030180c>] (do_one_initcall+0x54/0x1f4) [ 1.774436] [<8030180c>] (do_one_initcall) from [<80d013d8>] (kernel_init_freeable+0x218/0x26c) [ 1.781991] [<80d013d8>] (kernel_init_freeable) from [<809f9a1c>] (kernel_init+0x14/0x124) [ 1.790584] [<809f9a1c>] (kernel_init) from [<80300124>] (ret_from_fork+0x14/0x30) [ 1.798914] Exception stack(0x81029fb0 to 0x81029ff8) [ 1.806466] 9fa0: 00000000 00000000 00000000 00000000 [ 1.811592] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 1.819752] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 [ 1.830145] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read only 64 bytes, retry [ 1.835616] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read only 64 bytes, retry [ 1.846791] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read only 64 bytes, retry [ 1.857866] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read 64 bytes [ 1.867733] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.150 #0 [ 1.877732] Hardware name: Generic DT based system [ 1.883815] [<8030e0b0>] (unwind_backtrace) from [<80309bd8>] (show_stack+0x10/0x14) [ 1.888501] [<80309bd8>] (show_stack) from [<8067a780>] (dump_stack_lvl+0x40/0x4c) [ 1.896398] [<8067a780>] (dump_stack_lvl) from [<80791d88>] (ubi_io_read+0x138/0x33c) [ 1.903778] [<80791d88>] (ubi_io_read) from [<807921e0>] (ubi_io_read_ec_hdr+0x44/0x1f4) [ 1.911675] [<807921e0>] (ubi_io_read_ec_hdr) from [<807972f4>] (ubi_attach+0x428/0x1458) [ 1.919836] [<807972f4>] (ubi_attach) from [<8078c4e4>] (ubi_attach_mtd_dev+0x494/0xb34) [ 1.927909] [<8078c4e4>] (ubi_attach_mtd_dev) from [<80d1e7f0>] (ubi_init+0x124/0x354) [ 1.936069] [<80d1e7f0>] (ubi_init) from [<8030180c>] (do_one_initcall+0x54/0x1f4) [ 1.943795] [<8030180c>] (do_one_initcall) from [<80d013d8>] (kernel_init_freeable+0x218/0x26c) [ 1.951348] [<80d013d8>] (kernel_init_freeable) from [<809f9a1c>] (kernel_init+0x14/0x124) [ 1.959941] [<809f9a1c>] (kernel_init) from [<80300124>] (ret_from_fork+0x14/0x30) [ 1.968271] Exception stack(0x81029fb0 to 0x81029ff8) [ 1.975825] 9fa0: 00000000 00000000 00000000 00000000 [ 1.980951] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 1.989110] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 [ 1.999424] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 2:0, read only 64 bytes, retry

后面是不停地循环。。。

sseseed commented 1 month ago

应该是0x11

麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },

potatoigit commented 1 month ago

应该是0x11

麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },

请尝试NAND_ECC_INFO(4, SZ_512)

sseseed commented 1 month ago

应该是0x11

麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },

请尝试NAND_ECC_INFO(4, SZ_512)

这个试过了,也是不行,一开始就是用 4 ,然后用 8 都不行,最后才试 1 的。可能不只一个参数有问题,暂时只能乱试,现在把 0, 2, 128 那里改成 0,2,64 试,然后 ECC 那里就是 1、4、8 都轮着试。小白只能穷举了 :) 网上下载的别人说可以用的固件在我这里不可以,可能就是闪存不同的原因,别人的固件直接提示找不到 nand 然后就中断不动了。

sseseed commented 1 month ago

应该是0x11

麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },

请尝试NAND_ECC_INFO(4, SZ_512)

找到了另一个形式的对 FM25LS01 的结构体,但不会套过去... { .id = { 0xa1, 0xa5 }, .page_size = 2048, .erase_blk_size = 0x00020000, .pgs_per_blk = 64, .no_of_blocks = 1024, .spare_size = 64, .density = 0x08000000, .otp_region = 0x2000, .no_of_addr_cycle = 0x3, .num_bits_ecc_correctability = 4, .timing_mode_support = 0, .quad_mode = true, .check_quad_config = true, .name = "FM25LS01", },

JiaY-shi commented 3 weeks ago
From 6ee246291159ce8fa235aa4412941413e073c779 Mon Sep 17 00:00:00 2001
From: JiaY-shi <shi05275@163.com>
Date: Sun, 4 Aug 2024 13:19:32 +0800
Subject: mtd: nand: add ipq5018 spi nand support

---
 drivers/mtd/nand/raw/qcom_nandc.c | 191 ++++++++++++++++++++++++++++--
 1 file changed, 178 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index b8cff9240b28..9d0e690980b3 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -35,13 +35,22 @@
 #define    NAND_DEV_CMD0           0xa0
 #define    NAND_DEV_CMD1           0xa4
 #define    NAND_DEV_CMD2           0xa8
+#define    NAND_DEV_CMD3           0xd0
+#define    NAND_DEV_CMD4           0xd4
+#define    NAND_DEV_CMD5           0xd8
+#define    NAND_DEV_CMD6           0xdc
+#define    NAND_DEV_CMD7           0xb0
+#define    NAND_DEV_CMD8           0xb4
+#define    NAND_DEV_CMD9           0xb8
 #define    NAND_DEV_CMD_VLD        0xac
+#define    NAND_FLASH_SPI_CFG      0xc0
+#define    NAND_SPI_NUM_ADDR_CYCLES    0xc4
+#define    NAND_SPI_BUSY_CHECK_WAIT_CNT    0xc8
 #define    SFLASHC_BURST_CFG       0xe0
 #define    NAND_ERASED_CW_DETECT_CFG   0xe8
 #define    NAND_ERASED_CW_DETECT_STATUS    0xec
 #define    NAND_EBI2_ECC_BUF_CFG       0xf0
 #define    FLASH_BUF_ACC           0x100
-
 #define    NAND_CTRL           0xf00
 #define    NAND_VERSION            0xf08
 #define    NAND_READ_LOCATION_0        0xf20
@@ -52,6 +61,7 @@
 #define    NAND_READ_LOCATION_LAST_CW_1    0xf44
 #define    NAND_READ_LOCATION_LAST_CW_2    0xf48
 #define    NAND_READ_LOCATION_LAST_CW_3    0xf4c
+#define    NAND_QSPI_MSTR_CONFIG       0xf60

 /* dummy register offsets, used by write_reg_dma */
 #define    NAND_DEV_CMD1_RESTORE       0xdead
@@ -189,6 +199,28 @@
 #define    ECC_BCH_4BIT    BIT(2)
 #define    ECC_BCH_8BIT    BIT(3)

+/* QSPI NAND config reg bits */
+#define    LOAD_CLK_CNTR_INIT_EN   (1 << 28)
+#define    CLK_CNTR_INIT_VAL_VEC   0x924
+#define    FEA_STATUS_DEV_ADDR 0xc0
+#define    SPI_CFG (1 << 0)
+
+/* CMD register value for qspi nand */
+#define    CMD0_VAL    0x1080D8D8
+#define    CMD1_VAL    0xF00F3000
+#define    CMD2_VAL    0xF0FF709F
+#define    CMD3_VAL    0x3F310015
+#define    CMD7_VAL    0x04061F0F
+#define    CMD_VLD_VAL 0xd
+#define    SPI_NUM_ADDR    0xDA4DB
+#define    WAIT_CNT    0x10
+
+/* QSPI NAND CMD reg bits value */
+#define    SPI_WP      (1 << 28)
+#define    SPI_HOLD    (1 << 27)
+#define    SPI_TRANSFER_MODE_x1    (1 << 29)
+#define    SPI_TRANSFER_MODE_x4    (3 << 29)
+
 #define nandc_set_read_loc_first(chip, reg, cw_offset, read_size, is_last_read_loc)    \
 nandc_set_reg(chip, reg,           \
          ((cw_offset) << READ_LOCATION_OFFSET) |       \
@@ -336,6 +368,9 @@ struct nandc_regs {
    __le32 read_location_last1;
    __le32 read_location_last2;
    __le32 read_location_last3;
+   __le32 spi_cfg;
+   __le32 num_addr_cycle;
+   __le32 busy_wait_cnt;

    __le32 erased_cw_detect_cfg_clr;
    __le32 erased_cw_detect_cfg_set;
@@ -396,6 +431,7 @@ struct qcom_nand_controller {

    struct clk *core_clk;
    struct clk *aon_clk;
+   struct clk *iomacro_clk;

    struct nandc_regs *regs;
    struct bam_transaction *bam_txn;
@@ -439,6 +475,7 @@ struct qcom_nand_controller {

    u32 cmd1, vld;
    bool exec_opwrite;
+   u32 hw_version;
 };

 /*
@@ -553,6 +590,7 @@ struct qcom_nand_host {
  * @is_qpic - whether NAND CTRL is part of qpic IP
  * @qpic_v2 - flag to indicate QPIC IP version 2
  * @use_codeword_fixup - whether NAND has different layout for boot partitions
+ * @is_serial_nand - QSPI nand flag, whether QPIC support serial nand or not
  */
 struct qcom_nandc_props {
    u32 ecc_modes;
@@ -561,6 +599,7 @@ struct qcom_nandc_props {
    bool is_qpic;
    bool qpic_v2;
    bool use_codeword_fixup;
+   bool is_serial_nand;
 };

 /* Frees the BAM transaction memory */
@@ -743,6 +782,12 @@ static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset)
        return &regs->read_location_last2;
    case NAND_READ_LOCATION_LAST_CW_3:
        return &regs->read_location_last3;
+   case NAND_FLASH_SPI_CFG:
+       return &regs->spi_cfg;
+   case NAND_SPI_NUM_ADDR_CYCLES:
+       return &regs->num_addr_cycle;
+   case NAND_SPI_BUSY_CHECK_WAIT_CNT:
+       return &regs->busy_wait_cnt;
    default:
        return NULL;
    }
@@ -814,13 +859,18 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i
    u32 cmd, cfg0, cfg1, ecc_bch_cfg;
    struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);

+   cmd = (PAGE_ACC | LAST_PAGE);
+
+   if (nandc->props->is_serial_nand)
+       cmd |= (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD);
+
    if (read) {
        if (host->use_ecc)
-           cmd = OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE;
+           cmd |= OP_PAGE_READ_WITH_ECC;
        else
-           cmd = OP_PAGE_READ | PAGE_ACC | LAST_PAGE;
+           cmd |= OP_PAGE_READ;
    } else {
-       cmd = OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE;
+       cmd |= OP_PROGRAM_PAGE;
    }

    if (host->use_ecc) {
@@ -2371,12 +2421,32 @@ static int qcom_nand_attach_chip(struct nand_chip *chip)
    int cwperpage, bad_block_byte, ret;
    bool wide_bus;
    int ecc_mode = 1;
+   int num_addr_cycle = 5, dsbl_sts_aftr_write = 0;
+   int wr_rd_bsy_gap = 2, recovery_cycle = 7;
+   u32 version_reg;

    /* controller only supports 512 bytes data steps */
    ecc->size = NANDC_STEP_SIZE;
    wide_bus = chip->options & NAND_BUSWIDTH_16 ? true : false;
    cwperpage = mtd->writesize / NANDC_STEP_SIZE;

+   /*
+    * Read the required ecc strength from NAND device and overwrite the
+    * device tree ecc strength
+    */
+   if (chip->base.ecc.requirements.strength >= 8)
+       ecc->strength = 8;
+
+   /* Read QPIC version register */
+   version_reg = (NAND_VERSION + 0x4000);
+   nandc->hw_version = nandc_read(nandc, version_reg);
+   pr_info("QPIC controller hw version Major:%d, Minor:%d\n",
+           ((nandc->hw_version & NAND_VERSION_MAJOR_MASK)
+            >> NAND_VERSION_MAJOR_SHIFT),
+           ((nandc->hw_version & NAND_VERSION_MINOR_MASK)
+            >> NAND_VERSION_MINOR_SHIFT));
+   nandc->hw_version = ((nandc->hw_version & NAND_VERSION_MAJOR_MASK)
+           >> NAND_VERSION_MAJOR_SHIFT);
    /*
     * Each CW has 4 available OOB bytes which will be protected with ECC
     * so remaining bytes can be used for ECC.
@@ -2485,33 +2555,43 @@ static int qcom_nand_attach_chip(struct nand_chip *chip)
    host->cw_size = host->cw_data + ecc->bytes;
    bad_block_byte = mtd->writesize - host->cw_size * (cwperpage - 1) + 1;

+   /* For QSPI serial nand QPIC config register value got changed
+    * so configure the new value for qspi serial nand
+    */
+   if (nandc->props->is_serial_nand) {
+       num_addr_cycle = 3;
+       dsbl_sts_aftr_write = 1;
+       wr_rd_bsy_gap = 20;
+       recovery_cycle = 0;
+   }
+
    host->cfg0 = (cwperpage - 1) << CW_PER_PAGE
                | host->cw_data << UD_SIZE_BYTES
-               | 0 << DISABLE_STATUS_AFTER_WRITE
-               | 5 << NUM_ADDR_CYCLES
+               | dsbl_sts_aftr_write << DISABLE_STATUS_AFTER_WRITE
+               | num_addr_cycle << NUM_ADDR_CYCLES
                | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_RS
                | 0 << STATUS_BFR_READ
                | 1 << SET_RD_MODE_AFTER_STATUS
                | host->spare_bytes << SPARE_SIZE_BYTES;

-   host->cfg1 = 7 << NAND_RECOVERY_CYCLES
+   host->cfg1 = recovery_cycle << NAND_RECOVERY_CYCLES
                | 0 <<  CS_ACTIVE_BSY
                | bad_block_byte << BAD_BLOCK_BYTE_NUM
                | 0 << BAD_BLOCK_IN_SPARE_AREA
-               | 2 << WR_RD_BSY_GAP
+               | wr_rd_bsy_gap << WR_RD_BSY_GAP
                | wide_bus << WIDE_FLASH
                | host->bch_enabled << ENABLE_BCH_ECC;

    host->cfg0_raw = (cwperpage - 1) << CW_PER_PAGE
                | host->cw_size << UD_SIZE_BYTES
-               | 5 << NUM_ADDR_CYCLES
+               | num_addr_cycle << NUM_ADDR_CYCLES
                | 0 << SPARE_SIZE_BYTES;

-   host->cfg1_raw = 7 << NAND_RECOVERY_CYCLES
+   host->cfg1_raw = recovery_cycle << NAND_RECOVERY_CYCLES
                | 0 << CS_ACTIVE_BSY
                | 17 << BAD_BLOCK_BYTE_NUM
                | 1 << BAD_BLOCK_IN_SPARE_AREA
-               | 2 << WR_RD_BSY_GAP
+               | wr_rd_bsy_gap << WR_RD_BSY_GAP
                | wide_bus << WIDE_FLASH
                | 1 << DEV0_CFG1_ECC_DISABLE;

@@ -2551,6 +2631,8 @@ static int qcom_op_cmd_mapping(struct nand_chip *chip, u8 opcode,
    switch (opcode) {
    case NAND_CMD_RESET:
        cmd = OP_RESET_DEVICE;
+       if (nandc->props->is_serial_nand)
+           cmd |= (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1);
        break;
    case NAND_CMD_READID:
        cmd = OP_FETCH_ID;
@@ -2763,6 +2845,17 @@ static int qcom_read_id_type_exec(struct nand_chip *chip, const struct nand_subo
    clear_read_regs(nandc);
    clear_bam_transaction(nandc);

+   if (nandc->props->is_serial_nand) {
+       q_op.cmd_reg |= (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1);
+       /* For spi nand read 2-bytes id only
+        * else if nandc->buf_count == 4; then the id value
+        * will repeat and the SLC device will be detect as MLC.
+        * by nand base layer
+        * so overwrite the nandc->buf_count == 2;
+        */
+       nandc->buf_count = 2;
+   }
+
    nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
    nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
    nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
@@ -2785,6 +2878,15 @@ static int qcom_read_id_type_exec(struct nand_chip *chip, const struct nand_subo
    instr = q_op.data_instr;
    op_id = q_op.data_instr_idx;
    len = nand_subop_get_data_len(subop, op_id);
+   if (nandc->props->is_serial_nand) {
+       /* For spi nand read 2-bytes id only
+        * else if nandc->buf_count == 4; then the id value
+        * will repeat and the SLC device will be detect as MLC.
+        * by nand base layer
+        * so overwrite the nandc->buf_count == 2;
+        */
+       len = 2;
+   }

    nandc_read_buffer_sync(nandc, true);
    memcpy(instr->ctx.data.buf.in, nandc->reg_read_buf, len);
@@ -2809,6 +2911,11 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
        goto wait_rdy;
    } else if (q_op.cmd_reg == OP_BLOCK_ERASE) {
        q_op.cmd_reg |= PAGE_ACC | LAST_PAGE;
+       if (nandc->props->is_serial_nand) {
+           q_op.cmd_reg |= (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1);
+           q_op.addr2_reg = (q_op.addr1_reg >> 16) & 0xffff;
+           q_op.addr1_reg <<= 16;
+       }
        nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
        nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
        nandc_set_reg(chip, NAND_DEV0_CFG0,
@@ -2859,7 +2966,7 @@ static int qcom_param_page_type_exec(struct nand_chip *chip,  const struct nand_
    unsigned int op_id = 0;
    unsigned int len = 0;
    int ret;
-
+   printk(KERN_INFO "%s:%d %d\n", __func__,__LINE__, nandc->props->is_serial_nand);
    ret = qcom_parse_instructions(chip, subop, &q_op);
    if (ret)
        return ret;
@@ -3254,6 +3361,34 @@ static int qcom_nand_host_parse_boot_partitions(struct qcom_nand_controller *nan
    return 0;
 }

+static void qspi_nand_init(struct qcom_nand_controller *nandc)
+{
+   u32 spi_cfg_val = 0x0;
+   u32 reg = 0x0;
+
+   spi_cfg_val |= (LOAD_CLK_CNTR_INIT_EN | (CLK_CNTR_INIT_VAL_VEC << 16)
+           | (FEA_STATUS_DEV_ADDR << 8) | SPI_CFG);
+
+   reg = dev_cmd_reg_addr(nandc, NAND_FLASH_SPI_CFG);
+   nandc_write(nandc, reg, 0);
+   nandc_write(nandc, reg, spi_cfg_val);
+   spi_cfg_val &= ~LOAD_CLK_CNTR_INIT_EN;
+   nandc_write(nandc, reg, spi_cfg_val);
+
+   reg = dev_cmd_reg_addr(nandc, NAND_DEV_CMD0);
+   nandc_write(nandc, reg, CMD0_VAL);
+   nandc_write(nandc, reg + 4, CMD1_VAL);
+   nandc_write(nandc, reg + 8, CMD2_VAL);
+   nandc_write(nandc, reg + 12, CMD_VLD_VAL);
+   nandc_write(nandc, reg + 16, CMD7_VAL);
+   reg = dev_cmd_reg_addr(nandc, NAND_DEV_CMD3);
+   nandc_write(nandc, reg, CMD3_VAL);
+
+   reg = dev_cmd_reg_addr(nandc, NAND_SPI_NUM_ADDR_CYCLES);
+   nandc_write(nandc, reg, SPI_NUM_ADDR);
+   nandc_write(nandc, reg + 4, WAIT_CNT);
+}
+
 static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
                        struct qcom_nand_host *host,
                        struct device_node *dn)
@@ -3295,6 +3430,9 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
    /* set up initial status value */
    host->status = NAND_STATUS_READY | NAND_STATUS_WP;

+   if (nandc->props->is_serial_nand)
+       qspi_nand_init(nandc);
+
    ret = nand_scan(chip, 1);
    if (ret)
        return ret;
@@ -3399,6 +3537,12 @@ static int qcom_nandc_probe(struct platform_device *pdev)
    if (IS_ERR(nandc->aon_clk))
        return PTR_ERR(nandc->aon_clk);

+   if (nandc->props->is_serial_nand) {
+       nandc->iomacro_clk = devm_clk_get(dev, "io_macro");
+       if (IS_ERR(nandc->iomacro_clk))
+           return PTR_ERR(nandc->iomacro_clk);
+   }
+
    ret = qcom_nandc_parse_dt(pdev);
    if (ret)
        return ret;
@@ -3426,6 +3570,12 @@ static int qcom_nandc_probe(struct platform_device *pdev)
    if (ret)
        goto err_nandc_alloc;

+   if (nandc->props->is_serial_nand) {
+       ret = clk_prepare_enable(nandc->iomacro_clk);
+       if (ret)
+           goto err_setup;
+   }
+
    ret = qcom_nandc_setup(nandc);
    if (ret)
        goto err_setup;
@@ -3477,6 +3627,7 @@ static const struct qcom_nandc_props ipq806x_nandc_props = {
    .is_bam = false,
    .use_codeword_fixup = true,
    .dev_cmd_reg_start = 0x0,
+   .is_serial_nand = false,
 };

 static const struct qcom_nandc_props ipq4019_nandc_props = {
@@ -3484,6 +3635,7 @@ static const struct qcom_nandc_props ipq4019_nandc_props = {
    .is_bam = true,
    .is_qpic = true,
    .dev_cmd_reg_start = 0x0,
+   .is_serial_nand = false,
 };

 static const struct qcom_nandc_props ipq8074_nandc_props = {
@@ -3491,6 +3643,15 @@ static const struct qcom_nandc_props ipq8074_nandc_props = {
    .is_bam = true,
    .is_qpic = true,
    .dev_cmd_reg_start = 0x7000,
+   .is_serial_nand = false,
+};
+
+static const struct qcom_nandc_props ipq5018_nandc_props = {
+   .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
+   .is_bam = true,
+   .qpic_v2 = true,
+   .dev_cmd_reg_start = 0x7000,
+   .is_serial_nand = true,
 };

 static const struct qcom_nandc_props sdx55_nandc_props = {
@@ -3526,6 +3687,10 @@ static const struct of_device_id qcom_nandc_of_match[] = {
        .compatible = "qcom,sdx55-nand",
        .data = &sdx55_nandc_props,
    },
+   {
+       .compatible = "qcom,ipq5018-nand",
+       .data = &ipq5018_nandc_props,
+   },
    {}
 };
 MODULE_DEVICE_TABLE(of, qcom_nandc_of_match);
@@ -3542,4 +3707,4 @@ module_platform_driver(qcom_nandc_driver);

 MODULE_AUTHOR("Archit Taneja <architt@codeaurora.org>");
 MODULE_DESCRIPTION("Qualcomm NAND Controller driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL v2");
\ No newline at end of file
-- 
2.43.0

试试这个,测试过,基于linux-6.6内核