From a0f6931c32a3baae9affed76320812ad4fd9e867 Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Sun, 9 Nov 2025 10:06:55 +0300 Subject: [PATCH] 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. Signed-off-by: Mikhail Kshevetskiy --- drivers/spi/airoha_snfi_spi.c | 135 +++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 33 deletions(-) diff --git a/drivers/spi/airoha_snfi_spi.c b/drivers/spi/airoha_snfi_spi.c index b136f8b26d2..55194648d9c 100644 --- a/drivers/spi/airoha_snfi_spi.c +++ b/drivers/spi/airoha_snfi_spi.c @@ -645,7 +645,48 @@ 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 + */ + 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)); + if (err) + goto error_dma_mode_off; + + /* 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; @@ -658,7 +699,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, @@ -685,18 +733,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; @@ -791,7 +827,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; @@ -804,8 +881,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); @@ -830,22 +915,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.47.3