mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-03-14 23:09:45 +01:00
econet: spi: sync spi-airoha-snfi patches from airoha target
Copy upstream v6.19 spi-airoha-snfi driver patches from target/linux/airoha/patches-6.12 for the EN7528 subtarget. Signed-off-by: Ahmed Naseef <naseefkm@gmail.com> Link: https://github.com/openwrt/openwrt/pull/21326 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
parent
fab098cb61
commit
0b035903fb
9 changed files with 937 additions and 0 deletions
|
|
@ -0,0 +1,33 @@
|
|||
From 661856ca131c8bf6724905966e02149805660abe Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:16:53 +0300
|
||||
Subject: [PATCH 05/14] spi: airoha: remove unnecessary restriction length
|
||||
|
||||
The "length < 160" restriction is not needed because airoha_snand_write_data()
|
||||
and airoha_snand_read_data() will properly handle data transfers above
|
||||
SPI_MAX_TRANSFER_SIZE.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-3-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -619,13 +619,6 @@ static int airoha_snand_adjust_op_size(s
|
||||
|
||||
if (op->data.nbytes > max_len)
|
||||
op->data.nbytes = max_len;
|
||||
- } else {
|
||||
- max_len = 1 + op->addr.nbytes + op->dummy.nbytes;
|
||||
- if (max_len >= 160)
|
||||
- return -EOPNOTSUPP;
|
||||
-
|
||||
- if (op->data.nbytes > 160 - max_len)
|
||||
- op->data.nbytes = 160 - max_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
From 7350f8dc15bfbb7abf1ce4babea6fcace1c574c5 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:16:55 +0300
|
||||
Subject: [PATCH 06/14] spi: airoha: remove unnecessary switch to non-dma mode
|
||||
|
||||
The code switches to dma at the start of dirmap operation and returns
|
||||
to non-dma at the end of dirmap operation, so an additional switch to
|
||||
non-dma at the start of dirmap write is not required.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-5-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -815,9 +815,6 @@ static ssize_t airoha_snand_dirmap_write
|
||||
int err;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
- err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
- if (err < 0)
|
||||
- return err;
|
||||
|
||||
memcpy(txrx_buf + offs, buf, len);
|
||||
dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
From 233a22687411ea053a4b169c07324ee6aa33bf38 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:16:58 +0300
|
||||
Subject: [PATCH 07/14] spi: airoha: unify dirmap read/write code
|
||||
|
||||
Makes dirmap writing looks similar to dirmap reading. Just a minor
|
||||
refactoring, no behavior change is expected.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-8-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 50 ++++++++++++++++++++++-------------
|
||||
1 file changed, 32 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -672,6 +672,8 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
u32 val, rd_mode;
|
||||
int err;
|
||||
|
||||
+ as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
+
|
||||
switch (op->cmd.opcode) {
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
|
||||
rd_mode = 1;
|
||||
@@ -684,7 +686,6 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
break;
|
||||
}
|
||||
|
||||
- as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -748,7 +749,7 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
- /* trigger dma start read */
|
||||
+ /* trigger dma reading */
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_RD_TRIG);
|
||||
if (err)
|
||||
@@ -806,37 +807,47 @@ error_dma_mode_off:
|
||||
static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, const void *buf)
|
||||
{
|
||||
- struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
struct spi_device *spi = desc->mem->spi;
|
||||
u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
dma_addr_t dma_addr;
|
||||
- u32 wr_mode, val;
|
||||
+ u32 wr_mode, val, opcode;
|
||||
int err;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
+ opcode = desc->info.op_tmpl.cmd.opcode;
|
||||
+ switch (opcode) {
|
||||
+ case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
|
||||
+ case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE:
|
||||
+ wr_mode = 0;
|
||||
+ break;
|
||||
+ case SPI_NAND_OP_PROGRAM_LOAD_QUAD:
|
||||
+ case SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD:
|
||||
+ wr_mode = 2;
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* unknown opcode */
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
memcpy(txrx_buf + offs, buf, len);
|
||||
- dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
- DMA_TO_DEVICE);
|
||||
- err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
- if (err)
|
||||
- return err;
|
||||
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
|
||||
if (err < 0)
|
||||
- goto error_dma_unmap;
|
||||
+ return err;
|
||||
|
||||
err = airoha_snand_nfi_config(as_ctrl);
|
||||
if (err)
|
||||
- goto error_dma_unmap;
|
||||
+ goto error_dma_mode_off;
|
||||
|
||||
- if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
|
||||
- op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
|
||||
- wr_mode = BIT(1);
|
||||
- else
|
||||
- wr_mode = 0;
|
||||
+ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_TO_DEVICE);
|
||||
+ err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
+ if (err)
|
||||
+ goto error_dma_mode_off;
|
||||
|
||||
+ /* set dma addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
dma_addr);
|
||||
if (err)
|
||||
@@ -850,12 +861,13 @@ static ssize_t airoha_snand_dirmap_write
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
+ /* set write command */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
|
||||
- FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
|
||||
- op->cmd.opcode));
|
||||
+ FIELD_PREP(SPI_NFI_PG_LOAD_CMD, opcode));
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
+ /* set write mode */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
|
||||
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));
|
||||
if (err)
|
||||
@@ -887,6 +899,7 @@ static ssize_t airoha_snand_dirmap_write
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
+ /* trigger dma writing */
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_WR_TRIG);
|
||||
if (err)
|
||||
@@ -931,6 +944,7 @@ static ssize_t airoha_snand_dirmap_write
|
||||
error_dma_unmap:
|
||||
dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
+error_dma_mode_off:
|
||||
airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
From 80b09137aeab27e59004383058f8cc696a9ee048 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:16:59 +0300
|
||||
Subject: [PATCH 08/14] spi: airoha: support of dualio/quadio flash reading
|
||||
commands
|
||||
|
||||
Airoha snfi spi controller supports acceleration of DUAL/QUAD
|
||||
operations, but does not supports DUAL_IO/QUAD_IO operations.
|
||||
Luckily DUAL/QUAD operations do the same as DUAL_IO/QUAD_IO ones,
|
||||
so we can issue corresponding DUAL/QUAD operation instead of
|
||||
DUAL_IO/QUAD_IO one.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-9-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 28 ++++++++++++++++++++++------
|
||||
1 file changed, 22 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -147,6 +147,8 @@
|
||||
#define SPI_NFI_CUS_SEC_SIZE_EN BIT(16)
|
||||
|
||||
#define REG_SPI_NFI_RD_CTL2 0x0510
|
||||
+#define SPI_NFI_DATA_READ_CMD GENMASK(7, 0)
|
||||
+
|
||||
#define REG_SPI_NFI_RD_CTL3 0x0514
|
||||
|
||||
#define REG_SPI_NFI_PG_CTL1 0x0524
|
||||
@@ -179,7 +181,9 @@
|
||||
#define SPI_NAND_OP_READ_FROM_CACHE_SINGLE 0x03
|
||||
#define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST 0x0b
|
||||
#define SPI_NAND_OP_READ_FROM_CACHE_DUAL 0x3b
|
||||
+#define SPI_NAND_OP_READ_FROM_CACHE_DUALIO 0xbb
|
||||
#define SPI_NAND_OP_READ_FROM_CACHE_QUAD 0x6b
|
||||
+#define SPI_NAND_OP_READ_FROM_CACHE_QUADIO 0xeb
|
||||
#define SPI_NAND_OP_WRITE_ENABLE 0x06
|
||||
#define SPI_NAND_OP_WRITE_DISABLE 0x04
|
||||
#define SPI_NAND_OP_PROGRAM_LOAD_SINGLE 0x02
|
||||
@@ -664,26 +668,38 @@ static int airoha_snand_dirmap_create(st
|
||||
static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, void *buf)
|
||||
{
|
||||
- struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
struct spi_device *spi = desc->mem->spi;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
dma_addr_t dma_addr;
|
||||
- u32 val, rd_mode;
|
||||
+ u32 val, rd_mode, opcode;
|
||||
int err;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
- switch (op->cmd.opcode) {
|
||||
+ /*
|
||||
+ * DUALIO and QUADIO opcodes are not supported by the spi controller,
|
||||
+ * replace them with supported opcodes.
|
||||
+ */
|
||||
+ opcode = desc->info.op_tmpl.cmd.opcode;
|
||||
+ switch (opcode) {
|
||||
+ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE:
|
||||
+ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST:
|
||||
+ rd_mode = 0;
|
||||
+ break;
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
|
||||
+ case SPI_NAND_OP_READ_FROM_CACHE_DUALIO:
|
||||
+ opcode = SPI_NAND_OP_READ_FROM_CACHE_DUAL;
|
||||
rd_mode = 1;
|
||||
break;
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_QUAD:
|
||||
+ case SPI_NAND_OP_READ_FROM_CACHE_QUADIO:
|
||||
+ opcode = SPI_NAND_OP_READ_FROM_CACHE_QUAD;
|
||||
rd_mode = 2;
|
||||
break;
|
||||
default:
|
||||
- rd_mode = 0;
|
||||
- break;
|
||||
+ /* unknown opcode */
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
|
||||
@@ -717,7 +733,7 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
|
||||
/* set read command */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
|
||||
- op->cmd.opcode);
|
||||
+ FIELD_PREP(SPI_NFI_DATA_READ_CMD, opcode));
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
From 70eec454f2d6cdfab547c262781acd38328e11a1 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:17:00 +0300
|
||||
Subject: [PATCH 09/14] 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.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-10-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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,
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
From d1ff30df1d9a4eb4c067795abb5e2a66910fd108 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:17:01 +0300
|
||||
Subject: [PATCH 10/14] 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.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-11-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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;
|
||||
@@ -815,7 +851,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;
|
||||
|
||||
@@ -831,8 +908,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);
|
||||
@@ -857,22 +942,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;
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
From fb81b5cecb8553e3ca2b45288cf340d43c9c2991 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:17:02 +0300
|
||||
Subject: [PATCH 11/14] 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.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-12-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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:
|
||||
@@ -880,18 +885,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;
|
||||
@@ -916,11 +920,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;
|
||||
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
From 902c0ea18a97b1a6eeee5799cb1fd9a79ef9208e Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:17:03 +0300
|
||||
Subject: [PATCH 12/14] 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.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-13-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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) {
|
||||
@@ -1076,7 +1002,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,
|
||||
@@ -1101,36 +1026,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,
|
||||
@@ -1204,7 +1099,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;
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 0743acf746a81e0460a56fd5ff847d97fa7eb370 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Date: Sun, 12 Oct 2025 15:17:04 +0300
|
||||
Subject: [PATCH 13/14] spi: airoha: buffer must be 0xff-ed before writing
|
||||
|
||||
During writing, the entire flash page (including OOB) will be updated
|
||||
with the values from the temporary buffer, so we need to fill the
|
||||
untouched areas of the buffer with 0xff value to prevent accidental
|
||||
data overwriting.
|
||||
|
||||
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://patch.msgid.link/20251012121707.2296160-14-mikhail.kshevetskiy@iopsys.eu
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -776,7 +776,11 @@ static ssize_t airoha_snand_dirmap_write
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
+ if (offs > 0)
|
||||
+ memset(txrx_buf, 0xff, offs);
|
||||
memcpy(txrx_buf + offs, buf, len);
|
||||
+ if (bytes > offs + len)
|
||||
+ memset(txrx_buf + offs + len, 0xff, bytes - offs - len);
|
||||
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
|
||||
if (err < 0)
|
||||
Loading…
Add table
Reference in a new issue