--- /dev/null
+From 073de6579cf8c7599d925852bb0fc7fa50378dd3 Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 18:00:32 +0300
+Subject: [PATCH 1/4] spi: airoha: avoid setting of page/oob sizes in
+ REG_SPI_NFI_PAGEFMT
+
+spi-airoha-snfi uses custom sector size in REG_SPI_NFI_SECCUS_SIZE
+register, so setting of page/oob sizes in REG_SPI_NFI_PAGEFMT is not
+required.
+
+---
+ drivers/spi/airoha_snfi_spi.c | 38 -----------------------------------
+ 1 file changed, 38 deletions(-)
+
+diff --git a/drivers/spi/airoha_snfi_spi.c b/drivers/spi/airoha_snfi_spi.c
+index 7cafa900bbc..71e4fc13924 100644
+--- a/drivers/spi/airoha_snfi_spi.c
++++ b/drivers/spi/airoha_snfi_spi.c
+@@ -514,44 +514,6 @@ static int airoha_snand_nfi_config(struct airoha_snand_priv *priv)
+ if (err)
+ return err;
+
+- /* page format */
+- switch (priv->nfi_cfg.spare_size) {
+- case 26:
+- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1);
+- break;
+- case 27:
+- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2);
+- break;
+- case 28:
+- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3);
+- break;
+- default:
+- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0);
+- break;
+- }
+-
+- err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_PAGEFMT,
+- SPI_NFI_SPARE_SIZE, val);
+- if (err)
+- return err;
+-
+- switch (priv->nfi_cfg.page_size) {
+- case 2048:
+- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1);
+- break;
+- case 4096:
+- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2);
+- break;
+- default:
+- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0);
+- break;
+- }
+-
+- err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_PAGEFMT,
+- SPI_NFI_PAGE_SIZE, val);
+- if (err)
+- return err;
+-
+ /* sec num */
+ val = FIELD_PREP(SPI_NFI_SEC_NUM, priv->nfi_cfg.sec_num);
+ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
+--
+2.51.0
+
--- /dev/null
+From 3bd6ca4ddaae4f0a667a9359c8092d2271006687 Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 18:49:34 +0300
+Subject: [PATCH 2/4] spi: airoha: reduce the number of modification of
+ REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers
+
+This just reduce the number of modification of REG_SPI_NFI_CNFG and
+REG_SPI_NFI_SECCUS_SIZE registers during dirmap operation.
+
+This patch is a necessary step to avoid usage of flash specific
+parameters.
+
+---
+ drivers/spi/airoha_snfi_spi.c | 134 +++++++++++++++++++++++++---------
+ 1 file changed, 101 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/spi/airoha_snfi_spi.c b/drivers/spi/airoha_snfi_spi.c
+index 71e4fc13924..1fcf5dd89e9 100644
+--- a/drivers/spi/airoha_snfi_spi.c
++++ b/drivers/spi/airoha_snfi_spi.c
+@@ -641,7 +641,47 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ if (err < 0)
+ return err;
+
+- err = airoha_snand_nfi_config(priv);
++ /* NFI reset */
++ err = regmap_write(priv->regmap_nfi, REG_SPI_NFI_CON,
++ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
++ if (err)
++ goto error_dma_mode_off;
++
++ /* NFI configure:
++ * - No AutoFDM (custom sector size (SECCUS) register will be used)
++ * - No SoC's hardware ECC (flash internal ECC will be used)
++ * - Use burst mode (faster, but requires 16 byte alignment for addresses)
++ * - Setup for reading (SPI_NFI_READ_MODE)
++ * - Setup reading command: FIELD_PREP(SPI_NFI_OPMODE, 6)
++ * - Use DMA instead of PIO for data reading
++ * - Use AHB bus for DMA transfer
++ */
++ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
++ SPI_NFI_DMA_MODE |
++ SPI_NFI_READ_MODE |
++ SPI_NFI_DMA_BURST_EN |
++ SPI_NFI_HW_ECC_EN |
++ SPI_NFI_AUTO_FDM_EN |
++ SPI_NFI_OPMODE,
++ SPI_NFI_DMA_MODE |
++ SPI_NFI_READ_MODE |
++ SPI_NFI_DMA_BURST_EN |
++ FIELD_PREP(SPI_NFI_OPMODE, 6));
++
++ /* Set number of sector will be read */
++ val = FIELD_PREP(SPI_NFI_SEC_NUM, priv->nfi_cfg.sec_num);
++ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
++ SPI_NFI_SEC_NUM, val);
++ if (err)
++ goto error_dma_mode_off;
++
++ /* Set custom sector size */
++ val = priv->nfi_cfg.sec_size;
++ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
++ SPI_NFI_CUS_SEC_SIZE |
++ SPI_NFI_CUS_SEC_SIZE_EN,
++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
++ SPI_NFI_CUS_SEC_SIZE_EN);
+ if (err)
+ goto error_dma_mode_off;
+
+@@ -654,7 +694,14 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ if (err)
+ goto error_dma_unmap;
+
+- /* set cust sec size */
++ /*
++ * Setup transfer length
++ * ---------------------
++ * The following rule MUST be met:
++ * transfer_length =
++ * = NFI_SNF_MISC_CTL2.read_data_byte_number =
++ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
++ */
+ val = priv->nfi_cfg.sec_size * priv->nfi_cfg.sec_num;
+ val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
+ err = regmap_update_bits(priv->regmap_nfi,
+@@ -681,18 +728,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ if (err)
+ goto error_dma_unmap;
+
+- /* set nfi read */
+- err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_OPMODE,
+- FIELD_PREP(SPI_NFI_OPMODE, 6));
+- if (err)
+- goto error_dma_unmap;
+-
+- err = regmap_set_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
+- if (err)
+- goto error_dma_unmap;
+-
+ err = regmap_write(priv->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
+ if (err)
+ goto error_dma_unmap;
+@@ -783,7 +818,48 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
+ if (err < 0)
+ return err;
+
+- err = airoha_snand_nfi_config(priv);
++ /* NFI reset */
++ err = regmap_write(priv->regmap_nfi, REG_SPI_NFI_CON,
++ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
++ if (err)
++ goto error_dma_mode_off;
++
++ /*
++ * NFI configure:
++ * - No AutoFDM (custom sector size (SECCUS) register will be used)
++ * - No SoC's hardware ECC (flash internal ECC will be used)
++ * - Use burst mode (faster, but requires 16 byte alignment for addresses)
++ * - Setup for writing (SPI_NFI_READ_MODE bit is cleared)
++ * - Setup writing command: FIELD_PREP(SPI_NFI_OPMODE, 3)
++ * - Use DMA instead of PIO for data writing
++ */
++ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
++ SPI_NFI_DMA_MODE |
++ SPI_NFI_READ_MODE |
++ SPI_NFI_DMA_BURST_EN |
++ SPI_NFI_HW_ECC_EN |
++ SPI_NFI_AUTO_FDM_EN |
++ SPI_NFI_OPMODE,
++ SPI_NFI_DMA_MODE |
++ SPI_NFI_DMA_BURST_EN |
++ FIELD_PREP(SPI_NFI_OPMODE, 3));
++ if (err)
++ goto error_dma_mode_off;
++
++ /* Set number of sector will be written */
++ val = FIELD_PREP(SPI_NFI_SEC_NUM, priv->nfi_cfg.sec_num);
++ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
++ SPI_NFI_SEC_NUM, val);
++ if (err)
++ goto error_dma_mode_off;
++
++ /* Set custom sector size */
++ val = priv->nfi_cfg.sec_size;
++ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
++ SPI_NFI_CUS_SEC_SIZE |
++ SPI_NFI_CUS_SEC_SIZE_EN,
++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
++ SPI_NFI_CUS_SEC_SIZE_EN);
+ if (err)
+ goto error_dma_mode_off;
+
+@@ -796,8 +872,16 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
+ if (err)
+ goto error_dma_unmap;
+
+- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
+- priv->nfi_cfg.sec_size * priv->nfi_cfg.sec_num);
++ /*
++ * Setup transfer length
++ * ---------------------
++ * The following rule MUST be met:
++ * transfer_length =
++ * = NFI_SNF_MISC_CTL2.write_data_byte_number =
++ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
++ */
++ val = priv->nfi_cfg.sec_size * priv->nfi_cfg.sec_num;
++ val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+ err = regmap_update_bits(priv->regmap_nfi,
+ REG_SPI_NFI_SNF_MISC_CTL2,
+ SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+@@ -822,22 +906,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
+ if (err)
+ goto error_dma_unmap;
+
+- err = regmap_clear_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_READ_MODE);
+- if (err)
+- goto error_dma_unmap;
+-
+- err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_OPMODE,
+- FIELD_PREP(SPI_NFI_OPMODE, 3));
+- if (err)
+- goto error_dma_unmap;
+-
+- err = regmap_set_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_DMA_MODE);
+- if (err)
+- goto error_dma_unmap;
+-
+ err = regmap_write(priv->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
+ if (err)
+ goto error_dma_unmap;
+--
+2.51.0
+
--- /dev/null
+From 8e6cba428ce48005b5b8be64c2a08c98d04865e9 Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 22:47:17 +0300
+Subject: [PATCH 3/4] spi: airoha: set custom sector size equal to flash page
+ size
+
+Set custom sector size equal to flash page size including oob. Thus we
+will always read a single sector. The maximum custom sector size is
+8187, so all possible flash sector sizes are supported.
+
+This patch is a necessary step to avoid usage of flash specific
+parameters.
+
+---
+ drivers/spi/airoha_snfi_spi.c | 35 +++++++++++++++++++----------------
+ 1 file changed, 19 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/spi/airoha_snfi_spi.c b/drivers/spi/airoha_snfi_spi.c
+index 1fcf5dd89e9..c9feef83f89 100644
+--- a/drivers/spi/airoha_snfi_spi.c
++++ b/drivers/spi/airoha_snfi_spi.c
+@@ -515,7 +515,7 @@ static int airoha_snand_nfi_config(struct airoha_snand_priv *priv)
+ return err;
+
+ /* sec num */
+- val = FIELD_PREP(SPI_NFI_SEC_NUM, priv->nfi_cfg.sec_num);
++ val = FIELD_PREP(SPI_NFI_SEC_NUM, 1);
+ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
+ SPI_NFI_SEC_NUM, val);
+ if (err)
+@@ -528,7 +528,8 @@ static int airoha_snand_nfi_config(struct airoha_snand_priv *priv)
+ return err;
+
+ /* set cust sec size */
+- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, priv->nfi_cfg.sec_size);
++ val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
++ priv->nfi_cfg.sec_size * priv->nfi_cfg.sec_num);
+ return regmap_update_bits(priv->regmap_nfi,
+ REG_SPI_NFI_SECCUS_SIZE,
+ SPI_NFI_CUS_SEC_SIZE, val);
+@@ -610,8 +611,11 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ u8 *txrx_buf = priv->txrx_buf;
+ dma_addr_t dma_addr;
+ u32 val, rd_mode, opcode;
++ size_t bytes;
+ int err;
+
++ bytes = priv->nfi_cfg.sec_num * priv->nfi_cfg.sec_size;
++
+ /*
+ * DUALIO and QUADIO opcodes are not supported by the spi controller,
+ * replace them with supported opcodes.
+@@ -669,18 +673,17 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ FIELD_PREP(SPI_NFI_OPMODE, 6));
+
+ /* Set number of sector will be read */
+- val = FIELD_PREP(SPI_NFI_SEC_NUM, priv->nfi_cfg.sec_num);
+ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
+- SPI_NFI_SEC_NUM, val);
++ SPI_NFI_SEC_NUM,
++ FIELD_PREP(SPI_NFI_SEC_NUM, 1));
+ if (err)
+ goto error_dma_mode_off;
+
+ /* Set custom sector size */
+- val = priv->nfi_cfg.sec_size;
+ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+ SPI_NFI_CUS_SEC_SIZE |
+ SPI_NFI_CUS_SEC_SIZE_EN,
+- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
+ SPI_NFI_CUS_SEC_SIZE_EN);
+ if (err)
+ goto error_dma_mode_off;
+@@ -702,11 +705,10 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ * = NFI_SNF_MISC_CTL2.read_data_byte_number =
+ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+ */
+- val = priv->nfi_cfg.sec_size * priv->nfi_cfg.sec_num;
+- val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
+ err = regmap_update_bits(priv->regmap_nfi,
+ REG_SPI_NFI_SNF_MISC_CTL2,
+- SPI_NFI_READ_DATA_BYTE_NUM, val);
++ SPI_NFI_READ_DATA_BYTE_NUM,
++ FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, bytes));
+ if (err)
+ goto error_dma_unmap;
+
+@@ -795,8 +797,11 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
+ u8 *txrx_buf = priv->txrx_buf;
+ dma_addr_t dma_addr;
+ u32 wr_mode, val, opcode;
++ size_t bytes;
+ int err;
+
++ bytes = priv->nfi_cfg.sec_num * priv->nfi_cfg.sec_size;
++
+ opcode = desc->info.op_tmpl.cmd.opcode;
+ switch (opcode) {
+ case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
+@@ -847,18 +852,17 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
+ goto error_dma_mode_off;
+
+ /* Set number of sector will be written */
+- val = FIELD_PREP(SPI_NFI_SEC_NUM, priv->nfi_cfg.sec_num);
+ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
+- SPI_NFI_SEC_NUM, val);
++ SPI_NFI_SEC_NUM,
++ FIELD_PREP(SPI_NFI_SEC_NUM, 1));
+ if (err)
+ goto error_dma_mode_off;
+
+ /* Set custom sector size */
+- val = priv->nfi_cfg.sec_size;
+ err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+ SPI_NFI_CUS_SEC_SIZE |
+ SPI_NFI_CUS_SEC_SIZE_EN,
+- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
+ SPI_NFI_CUS_SEC_SIZE_EN);
+ if (err)
+ goto error_dma_mode_off;
+@@ -880,11 +884,10 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
+ * = NFI_SNF_MISC_CTL2.write_data_byte_number =
+ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+ */
+- val = priv->nfi_cfg.sec_size * priv->nfi_cfg.sec_num;
+- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+ err = regmap_update_bits(priv->regmap_nfi,
+ REG_SPI_NFI_SNF_MISC_CTL2,
+- SPI_NFI_PROG_LOAD_BYTE_NUM, val);
++ SPI_NFI_PROG_LOAD_BYTE_NUM,
++ FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, bytes));
+ if (err)
+ goto error_dma_unmap;
+
+--
+2.51.0
+
--- /dev/null
+From f015b0211a36bf818023c82ab44644631987d23c Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 23:56:24 +0300
+Subject: [PATCH 4/4] spi: airoha: avoid usage of flash specific parameters
+
+The spinand driver do 3 type of dirmap requests:
+ * read/write whole flash page without oob
+ (offs = 0, len = page_size)
+ * read/write whole flash page including oob
+ (offs = 0, len = page_size + oob_size)
+ * read/write oob area only
+ (offs = page_size, len = oob_size)
+
+The trick is:
+ * read/write a single "sector"
+ * set a custom sector size equal to offs + len. It's a bit safer to
+ round up "sector size" value 64.
+ * set the transfer length equal to custom sector size
+
+And it works!
+
+Thus we can find all data directly from dirmap request, so flash specific
+parameters is not needed anymore. Also
+ * airoha_snand_nfi_config(),
+ * airoha_snand_nfi_setup()
+functions becomes unnecessary.
+
+---
+ drivers/spi/airoha_snfi_spi.c | 94 ++---------------------------------
+ 1 file changed, 4 insertions(+), 90 deletions(-)
+
+diff --git a/drivers/spi/airoha_snfi_spi.c b/drivers/spi/airoha_snfi_spi.c
+index c9feef83f89..37fee0c6655 100644
+--- a/drivers/spi/airoha_snfi_spi.c
++++ b/drivers/spi/airoha_snfi_spi.c
+@@ -218,13 +218,6 @@ struct airoha_snand_priv {
+ struct regmap *regmap_nfi;
+ struct clk *spi_clk;
+
+- struct {
+- size_t page_size;
+- size_t sec_size;
+- u8 sec_num;
+- u8 spare_size;
+- } nfi_cfg;
+-
+ u8 *txrx_buf;
+ };
+
+@@ -486,55 +479,6 @@ static int airoha_snand_nfi_init(struct airoha_snand_priv *priv)
+ SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN);
+ }
+
+-static int airoha_snand_nfi_config(struct airoha_snand_priv *priv)
+-{
+- int err;
+- u32 val;
+-
+- err = regmap_write(priv->regmap_nfi, REG_SPI_NFI_CON,
+- SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+- if (err)
+- return err;
+-
+- /* auto FDM */
+- err = regmap_clear_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_AUTO_FDM_EN);
+- if (err)
+- return err;
+-
+- /* HW ECC */
+- err = regmap_clear_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_HW_ECC_EN);
+- if (err)
+- return err;
+-
+- /* DMA Burst */
+- err = regmap_set_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_DMA_BURST_EN);
+- if (err)
+- return err;
+-
+- /* sec num */
+- val = FIELD_PREP(SPI_NFI_SEC_NUM, 1);
+- err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
+- SPI_NFI_SEC_NUM, val);
+- if (err)
+- return err;
+-
+- /* enable cust sec size */
+- err = regmap_set_bits(priv->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+- SPI_NFI_CUS_SEC_SIZE_EN);
+- if (err)
+- return err;
+-
+- /* set cust sec size */
+- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
+- priv->nfi_cfg.sec_size * priv->nfi_cfg.sec_num);
+- return regmap_update_bits(priv->regmap_nfi,
+- REG_SPI_NFI_SECCUS_SIZE,
+- SPI_NFI_CUS_SEC_SIZE, val);
+-}
+-
+ static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)
+ {
+ if (op->addr.nbytes != 2)
+@@ -614,7 +558,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ size_t bytes;
+ int err;
+
+- bytes = priv->nfi_cfg.sec_num * priv->nfi_cfg.sec_size;
++ /* minimum oob size is 64 */
++ bytes = round_up(offs + len, 64);
+
+ /*
+ * DUALIO and QUADIO opcodes are not supported by the spi controller,
+@@ -800,7 +745,8 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
+ size_t bytes;
+ int err;
+
+- bytes = priv->nfi_cfg.sec_num * priv->nfi_cfg.sec_size;
++ /* minimum oob size is 64 */
++ bytes = round_up(offs + len, 64);
+
+ opcode = desc->info.op_tmpl.cmd.opcode;
+ switch (opcode) {
+@@ -1089,37 +1035,6 @@ static int airoha_snand_nfi_set_mode(struct udevice *bus, uint mode)
+ return 0;
+ }
+
+-static int airoha_snand_nfi_setup(struct spi_slave *slave,
+- const struct spinand_info *spinand_info)
+-{
+- struct udevice *bus = slave->dev->parent;
+- struct airoha_snand_priv *priv;
+- u32 sec_size, sec_num;
+- int pagesize, oobsize;
+-
+- priv = dev_get_priv(bus);
+-
+- pagesize = spinand_info->memorg.pagesize;
+- oobsize = spinand_info->memorg.oobsize;
+-
+- if (pagesize == 2 * 1024)
+- sec_num = 4;
+- else if (pagesize == 4 * 1024)
+- sec_num = 8;
+- else
+- sec_num = 1;
+-
+- sec_size = (pagesize + oobsize) / sec_num;
+-
+- /* init default value */
+- priv->nfi_cfg.sec_size = sec_size;
+- priv->nfi_cfg.sec_num = sec_num;
+- priv->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024);
+- priv->nfi_cfg.spare_size = 16;
+-
+- return airoha_snand_nfi_config(priv);
+-}
+-
+ static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
+ .supports_op = airoha_snand_supports_op,
+ .exec_op = airoha_snand_exec_op,
+@@ -1132,7 +1047,6 @@ static const struct dm_spi_ops airoha_snfi_spi_ops = {
+ .mem_ops = &airoha_snand_mem_ops,
+ .set_speed = airoha_snand_nfi_set_speed,
+ .set_mode = airoha_snand_nfi_set_mode,
+- .setup_for_spinand = airoha_snand_nfi_setup,
+ };
+
+ static const struct udevice_id airoha_snand_ids[] = {
+--
+2.51.0
+