--- /dev/null
+From 4abbbc74306598159fe1dc545f929ae594bf4dd1 Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 18:00:32 +0300
+Subject: [PATCH v6 10/13] 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/spi-airoha-snfi.c | 38 -----------------------------------
+ 1 file changed, 38 deletions(-)
+
+--- a/drivers/spi/spi-airoha-snfi.c
++++ b/drivers/spi/spi-airoha-snfi.c
+@@ -518,44 +518,6 @@ static int airoha_snand_nfi_config(struc
+ if (err)
+ return err;
+
+- /* page format */
+- switch (as_ctrl->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(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
+- SPI_NFI_SPARE_SIZE, val);
+- if (err)
+- return err;
+-
+- switch (as_ctrl->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(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
+- SPI_NFI_PAGE_SIZE, val);
+- if (err)
+- return err;
+-
+ /* sec num */
+ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
--- /dev/null
+From 0d8f58869192df0acdba286d233b57a4feeaf94b Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 18:49:34 +0300
+Subject: [PATCH v6 11/13] 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 reading flash page settings
+from SNFI registers during driver startup.
+
+---
+ drivers/spi/spi-airoha-snfi.c | 135 +++++++++++++++++++++++++---------
+ 1 file changed, 102 insertions(+), 33 deletions(-)
+
+--- a/drivers/spi/spi-airoha-snfi.c
++++ b/drivers/spi/spi-airoha-snfi.c
+@@ -668,7 +668,48 @@ static ssize_t airoha_snand_dirmap_read(
+ if (err < 0)
+ return err;
+
+- err = airoha_snand_nfi_config(as_ctrl);
++ /* NFI reset */
++ err = regmap_write(as_ctrl->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
++ */
++ err = regmap_update_bits(as_ctrl->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));
++ if (err)
++ goto error_dma_mode_off;
++
++ /* Set number of sector will be read */
++ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
++ SPI_NFI_SEC_NUM, val);
++ if (err)
++ goto error_dma_mode_off;
++
++ /* Set custom sector size */
++ val = as_ctrl->nfi_cfg.sec_size;
++ err = regmap_update_bits(as_ctrl->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;
+
+@@ -684,7 +725,14 @@ static ssize_t airoha_snand_dirmap_read(
+ 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 = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
+ val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
+ err = regmap_update_bits(as_ctrl->regmap_nfi,
+@@ -711,18 +759,6 @@ static ssize_t airoha_snand_dirmap_read(
+ if (err)
+ goto error_dma_unmap;
+
+- /* set nfi read */
+- err = regmap_update_bits(as_ctrl->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(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
+- if (err)
+- goto error_dma_unmap;
+-
+ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
+ if (err)
+ goto error_dma_unmap;
+@@ -819,7 +855,48 @@ static ssize_t airoha_snand_dirmap_write
+ if (err < 0)
+ return err;
+
+- err = airoha_snand_nfi_config(as_ctrl);
++ /* NFI reset */
++ err = regmap_write(as_ctrl->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(as_ctrl->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, as_ctrl->nfi_cfg.sec_num);
++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
++ SPI_NFI_SEC_NUM, val);
++ if (err)
++ goto error_dma_mode_off;
++
++ /* Set custom sector size */
++ val = as_ctrl->nfi_cfg.sec_size;
++ err = regmap_update_bits(as_ctrl->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;
+
+@@ -835,8 +912,16 @@ static ssize_t airoha_snand_dirmap_write
+ if (err)
+ goto error_dma_unmap;
+
+- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
+- as_ctrl->nfi_cfg.sec_size * as_ctrl->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 = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
++ val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+ err = regmap_update_bits(as_ctrl->regmap_nfi,
+ REG_SPI_NFI_SNF_MISC_CTL2,
+ SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+@@ -861,22 +946,6 @@ static ssize_t airoha_snand_dirmap_write
+ if (err)
+ goto error_dma_unmap;
+
+- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_READ_MODE);
+- if (err)
+- goto error_dma_unmap;
+-
+- err = regmap_update_bits(as_ctrl->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(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_DMA_MODE);
+- if (err)
+- goto error_dma_unmap;
+-
+ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
+ if (err)
+ goto error_dma_unmap;
--- /dev/null
+From 893ee23d650ca9ee36541b9a5ae0bc18be01a11f Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 22:47:17 +0300
+Subject: [PATCH v6 12/13] 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 reading flash page settings
+from SNFI registers during driver startup.
+
+---
+ drivers/spi/spi-airoha-snfi.c | 35 +++++++++++++++++++----------------
+ 1 file changed, 19 insertions(+), 16 deletions(-)
+
+--- a/drivers/spi/spi-airoha-snfi.c
++++ b/drivers/spi/spi-airoha-snfi.c
+@@ -519,7 +519,7 @@ static int airoha_snand_nfi_config(struc
+ return err;
+
+ /* sec num */
+- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
++ val = FIELD_PREP(SPI_NFI_SEC_NUM, 1);
+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+ SPI_NFI_SEC_NUM, val);
+ if (err)
+@@ -532,7 +532,8 @@ static int airoha_snand_nfi_config(struc
+ return err;
+
+ /* set cust sec size */
+- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size);
++ val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
++ as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
+ return regmap_update_bits(as_ctrl->regmap_nfi,
+ REG_SPI_NFI_SECCUS_SIZE,
+ SPI_NFI_CUS_SEC_SIZE, val);
+@@ -635,10 +636,13 @@ static ssize_t airoha_snand_dirmap_read(
+ u8 *txrx_buf = spi_get_ctldata(spi);
+ dma_addr_t dma_addr;
+ u32 val, rd_mode, opcode;
++ size_t bytes;
+ int err;
+
+ as_ctrl = spi_controller_get_devdata(spi->controller);
+
++ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
++
+ /*
+ * DUALIO and QUADIO opcodes are not supported by the spi controller,
+ * replace them with supported opcodes.
+@@ -697,18 +701,17 @@ static ssize_t airoha_snand_dirmap_read(
+ goto error_dma_mode_off;
+
+ /* Set number of sector will be read */
+- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+ err = regmap_update_bits(as_ctrl->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 = as_ctrl->nfi_cfg.sec_size;
+ err = regmap_update_bits(as_ctrl->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;
+@@ -733,11 +736,10 @@ static ssize_t airoha_snand_dirmap_read(
+ * = NFI_SNF_MISC_CTL2.read_data_byte_number =
+ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+ */
+- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
+- val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
+ err = regmap_update_bits(as_ctrl->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;
+
+@@ -826,10 +828,13 @@ static ssize_t airoha_snand_dirmap_write
+ struct airoha_snand_ctrl *as_ctrl;
+ dma_addr_t dma_addr;
+ u32 wr_mode, val, opcode;
++ size_t bytes;
+ int err;
+
+ as_ctrl = spi_controller_get_devdata(spi->controller);
+
++ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
++
+ opcode = desc->info.op_tmpl.cmd.opcode;
+ switch (opcode) {
+ case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
+@@ -884,18 +889,17 @@ static ssize_t airoha_snand_dirmap_write
+ goto error_dma_mode_off;
+
+ /* Set number of sector will be written */
+- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+ err = regmap_update_bits(as_ctrl->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 = as_ctrl->nfi_cfg.sec_size;
+ err = regmap_update_bits(as_ctrl->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;
+@@ -920,11 +924,10 @@ static ssize_t airoha_snand_dirmap_write
+ * = NFI_SNF_MISC_CTL2.write_data_byte_number =
+ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+ */
+- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
+- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+ err = regmap_update_bits(as_ctrl->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;
+
--- /dev/null
+From 64a4d6e84145227211485067022cd4e5cf052e04 Mon Sep 17 00:00:00 2001
+Date: Thu, 14 Aug 2025 23:56:24 +0300
+Subject: [PATCH v6 13/13] spi: airoha: avoid reading flash page settings from
+ SNFI registers during driver startup
+
+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
+ rounded up "sector size" value 64.
+ * set the transfer length equal to custom sector size
+
+And it works!
+
+Thus we can remove a dirty hack that reads flash page settings from
+SNFI registers during driver startup. Also airoha_snand_adjust_op_size()
+function becomes unnecessary.
+
+---
+ drivers/spi/spi-airoha-snfi.c | 115 ++--------------------------------
+ 1 file changed, 5 insertions(+), 110 deletions(-)
+
+--- a/drivers/spi/spi-airoha-snfi.c
++++ b/drivers/spi/spi-airoha-snfi.c
+@@ -223,13 +223,6 @@ struct airoha_snand_ctrl {
+ struct regmap *regmap_ctrl;
+ 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;
+ };
+
+ static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl,
+@@ -490,55 +483,6 @@ static int airoha_snand_nfi_init(struct
+ SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN);
+ }
+
+-static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
+-{
+- int err;
+- u32 val;
+-
+- err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+- SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+- if (err)
+- return err;
+-
+- /* auto FDM */
+- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_AUTO_FDM_EN);
+- if (err)
+- return err;
+-
+- /* HW ECC */
+- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+- SPI_NFI_HW_ECC_EN);
+- if (err)
+- return err;
+-
+- /* DMA Burst */
+- err = regmap_set_bits(as_ctrl->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(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+- SPI_NFI_SEC_NUM, val);
+- if (err)
+- return err;
+-
+- /* enable cust sec size */
+- err = regmap_set_bits(as_ctrl->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,
+- as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
+- return regmap_update_bits(as_ctrl->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)
+@@ -571,26 +515,6 @@ static bool airoha_snand_is_page_ops(con
+ }
+ }
+
+-static int airoha_snand_adjust_op_size(struct spi_mem *mem,
+- struct spi_mem_op *op)
+-{
+- size_t max_len;
+-
+- if (airoha_snand_is_page_ops(op)) {
+- struct airoha_snand_ctrl *as_ctrl;
+-
+- as_ctrl = spi_controller_get_devdata(mem->spi->controller);
+- max_len = as_ctrl->nfi_cfg.sec_size;
+- max_len += as_ctrl->nfi_cfg.spare_size;
+- max_len *= as_ctrl->nfi_cfg.sec_num;
+-
+- if (op->data.nbytes > max_len)
+- op->data.nbytes = max_len;
+- }
+-
+- return 0;
+-}
+-
+ static bool airoha_snand_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+ {
+@@ -641,7 +565,8 @@ static ssize_t airoha_snand_dirmap_read(
+
+ as_ctrl = spi_controller_get_devdata(spi->controller);
+
+- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->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,
+@@ -833,7 +758,8 @@ static ssize_t airoha_snand_dirmap_write
+
+ as_ctrl = spi_controller_get_devdata(spi->controller);
+
+- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
++ /* minimum oob size is 64 */
++ bytes = round_up(offs + len, 64);
+
+ opcode = desc->info.op_tmpl.cmd.opcode;
+ switch (opcode) {
+@@ -1080,7 +1006,6 @@ static int airoha_snand_exec_op(struct s
+ }
+
+ static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
+- .adjust_op_size = airoha_snand_adjust_op_size,
+ .supports_op = airoha_snand_supports_op,
+ .exec_op = airoha_snand_exec_op,
+ .dirmap_create = airoha_snand_dirmap_create,
+@@ -1105,36 +1030,6 @@ static int airoha_snand_setup(struct spi
+ return 0;
+ }
+
+-static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
+-{
+- u32 val, sec_size, sec_num;
+- int err;
+-
+- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val);
+- if (err)
+- return err;
+-
+- sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val);
+-
+- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val);
+- if (err)
+- return err;
+-
+- sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val);
+-
+- /* init default value */
+- as_ctrl->nfi_cfg.sec_size = sec_size;
+- as_ctrl->nfi_cfg.sec_num = sec_num;
+- as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024);
+- as_ctrl->nfi_cfg.spare_size = 16;
+-
+- err = airoha_snand_nfi_init(as_ctrl);
+- if (err)
+- return err;
+-
+- return airoha_snand_nfi_config(as_ctrl);
+-}
+-
+ static const struct regmap_config spi_ctrl_regmap_config = {
+ .name = "ctrl",
+ .reg_bits = 32,
+@@ -1208,7 +1103,7 @@ static int airoha_snand_probe(struct pla
+ ctrl->setup = airoha_snand_setup;
+ device_set_node(&ctrl->dev, dev_fwnode(dev));
+
+- err = airoha_snand_nfi_setup(as_ctrl);
++ err = airoha_snand_nfi_init(as_ctrl);
+ if (err)
+ return err;
+