mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2025-11-01 00:28:52 +00:00
This patch series removes dirty hack that reads flash page settings from SNFI registers during driver startup. Before these patches the airoha spi snfi driver needs to know spinand flash page size. The driver can't get it from spinand subsystem, so the following approach was implemented: * bootloader know the flash page size (and some other parameters) * to operate properly the bootloader writes flash page size (and some other parameters) to SNFI registers * bootloader starts linux * after linux start SNFI registers keeps the values stored by bootloader * linux snfi driver reads flash parameters from SNFI registers. This works, but we can do better. It has been proven that flash page size is actually unnecessary. We can get all required data from dirmap requests. This patch series drops the hack and do things properly. Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu> Link: https://github.com/openwrt/openwrt/pull/20295 Signed-off-by: Robert Marko <robimarko@gmail.com>
198 lines
6.4 KiB
Diff
198 lines
6.4 KiB
Diff
From 0d8f58869192df0acdba286d233b57a4feeaf94b Mon Sep 17 00:00:00 2001
|
|
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
|
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.
|
|
|
|
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
|
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
|
---
|
|
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;
|