mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2025-11-01 19:39:26 +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>
205 lines
5.6 KiB
Diff
205 lines
5.6 KiB
Diff
From 64a4d6e84145227211485067022cd4e5cf052e04 Mon Sep 17 00:00:00 2001
|
|
From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
|
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.
|
|
|
|
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
|
|
---
|
|
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;
|
|
|