openwrt/target/linux/airoha/patches-6.6/028-v6.13-spi-airoha-do-not...

436 lines
14 KiB
Diff

From 7a4b3ebf1d60349587fee21872536e7bd6a4cf39 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Sun, 22 Sep 2024 19:38:30 +0200
Subject: [PATCH] spi: airoha: do not keep {tx,rx} dma buffer always mapped
DMA map txrx_buf on demand in airoha_snand_dirmap_read and
airoha_snand_dirmap_write routines and do not keep it always mapped.
This patch is not fixing any bug or introducing any functional change
to the driver, it just simplifies the code and improve code readability
without introducing any performance degradation according to the results
obtained from the mtd_speedtest kernel module test.
root@OpenWrt:# insmod mtd_test.ko
root@OpenWrt:# insmod mtd_speedtest.ko dev=5
[ 49.849869] =================================================
[ 49.855659] mtd_speedtest: MTD device: 5
[ 49.859583] mtd_speedtest: MTD device size 8388608, eraseblock size 131072, page size 2048, count of eraseblocks 64, pages per eraseblock 64, OOB size 128
[ 49.874622] mtd_test: scanning for bad eraseblocks
[ 49.879433] mtd_test: scanned 64 eraseblocks, 0 are bad
[ 50.106372] mtd_speedtest: testing eraseblock write speed
[ 53.083380] mtd_speedtest: eraseblock write speed is 2756 KiB/s
[ 53.089322] mtd_speedtest: testing eraseblock read speed
[ 54.143360] mtd_speedtest: eraseblock read speed is 7811 KiB/s
[ 54.370365] mtd_speedtest: testing page write speed
[ 57.349480] mtd_speedtest: page write speed is 2754 KiB/s
[ 57.354895] mtd_speedtest: testing page read speed
[ 58.410431] mtd_speedtest: page read speed is 7796 KiB/s
[ 58.636805] mtd_speedtest: testing 2 page write speed
[ 61.612427] mtd_speedtest: 2 page write speed is 2757 KiB/s
[ 61.618021] mtd_speedtest: testing 2 page read speed
[ 62.672653] mtd_speedtest: 2 page read speed is 7804 KiB/s
[ 62.678159] mtd_speedtest: Testing erase speed
[ 62.903617] mtd_speedtest: erase speed is 37063 KiB/s
[ 62.908678] mtd_speedtest: Testing 2x multi-block erase speed
[ 63.134083] mtd_speedtest: 2x multi-block erase speed is 37292 KiB/s
[ 63.140442] mtd_speedtest: Testing 4x multi-block erase speed
[ 63.364262] mtd_speedtest: 4x multi-block erase speed is 37566 KiB/s
[ 63.370632] mtd_speedtest: Testing 8x multi-block erase speed
[ 63.595740] mtd_speedtest: 8x multi-block erase speed is 37344 KiB/s
[ 63.602089] mtd_speedtest: Testing 16x multi-block erase speed
[ 63.827426] mtd_speedtest: 16x multi-block erase speed is 37320 KiB/s
[ 63.833860] mtd_speedtest: Testing 32x multi-block erase speed
[ 64.059389] mtd_speedtest: 32x multi-block erase speed is 37288 KiB/s
[ 64.065833] mtd_speedtest: Testing 64x multi-block erase speed
[ 64.290609] mtd_speedtest: 64x multi-block erase speed is 37415 KiB/s
[ 64.297063] mtd_speedtest: finished
[ 64.300555] =================================================
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20240922-airoha-spi-fixes-v3-1-f958802b3d68@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/spi/spi-airoha-snfi.c | 154 ++++++++++++++++------------------
1 file changed, 71 insertions(+), 83 deletions(-)
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -206,13 +206,6 @@ enum airoha_snand_cs {
SPI_CHIP_SEL_LOW,
};
-struct airoha_snand_dev {
- size_t buf_len;
-
- u8 *txrx_buf;
- dma_addr_t dma_addr;
-};
-
struct airoha_snand_ctrl {
struct device *dev;
struct regmap *regmap_ctrl;
@@ -617,9 +610,9 @@ static bool airoha_snand_supports_op(str
static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
{
- struct airoha_snand_dev *as_dev = spi_get_ctldata(desc->mem->spi);
+ u8 *txrx_buf = spi_get_ctldata(desc->mem->spi);
- if (!as_dev->txrx_buf)
+ if (!txrx_buf)
return -EINVAL;
if (desc->info.offset + desc->info.length > U32_MAX)
@@ -634,10 +627,11 @@ 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_device *spi = desc->mem->spi;
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
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;
int err;
@@ -662,14 +656,17 @@ static ssize_t airoha_snand_dirmap_read(
if (err)
return err;
- dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
- as_dev->buf_len, DMA_BIDIRECTIONAL);
+ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
+ DMA_FROM_DEVICE);
+ err = dma_mapping_error(as_ctrl->dev, dma_addr);
+ if (err)
+ return err;
/* set dma addr */
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
- as_dev->dma_addr);
+ dma_addr);
if (err)
- return err;
+ goto error_dma_unmap;
/* set cust sec size */
val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
@@ -678,58 +675,58 @@ static ssize_t airoha_snand_dirmap_read(
REG_SPI_NFI_SNF_MISC_CTL2,
SPI_NFI_READ_DATA_BYTE_NUM, val);
if (err)
- return err;
+ goto error_dma_unmap;
/* set read command */
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
op->cmd.opcode);
if (err)
- return err;
+ goto error_dma_unmap;
/* set read mode */
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, rd_mode));
if (err)
- return err;
+ goto error_dma_unmap;
/* set read addr */
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
if (err)
- return 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)
- return 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)
- return err;
+ goto error_dma_unmap;
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
if (err)
- return err;
+ goto error_dma_unmap;
/* trigger dma start read */
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
SPI_NFI_RD_TRIG);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
SPI_NFI_RD_TRIG);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
REG_SPI_NFI_SNF_STA_CTL1, val,
(val & SPI_NFI_READ_FROM_CACHE_DONE),
0, 1 * USEC_PER_SEC);
if (err)
- return err;
+ goto error_dma_unmap;
/*
* SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
@@ -739,35 +736,41 @@ static ssize_t airoha_snand_dirmap_read(
SPI_NFI_READ_FROM_CACHE_DONE,
SPI_NFI_READ_FROM_CACHE_DONE);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
val, (val & SPI_NFI_AHB_DONE), 0,
1 * USEC_PER_SEC);
if (err)
- return err;
+ goto error_dma_unmap;
/* DMA read need delay for data ready from controller to DRAM */
udelay(1);
- dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
- as_dev->buf_len, DMA_BIDIRECTIONAL);
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
+ DMA_FROM_DEVICE);
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
if (err < 0)
return err;
- memcpy(buf, as_dev->txrx_buf + offs, len);
+ memcpy(buf, txrx_buf + offs, len);
return len;
+
+error_dma_unmap:
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
+ DMA_FROM_DEVICE);
+ return err;
}
static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
u64 offs, size_t len, const void *buf)
{
- struct spi_device *spi = desc->mem->spi;
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
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;
int err;
@@ -776,19 +779,20 @@ static ssize_t airoha_snand_dirmap_write
if (err < 0)
return err;
- dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
- as_dev->buf_len, DMA_BIDIRECTIONAL);
- memcpy(as_dev->txrx_buf + offs, buf, len);
- dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
- as_dev->buf_len, DMA_BIDIRECTIONAL);
+ 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)
- return err;
+ goto error_dma_unmap;
err = airoha_snand_nfi_config(as_ctrl);
if (err)
- return err;
+ goto error_dma_unmap;
if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
@@ -797,9 +801,9 @@ static ssize_t airoha_snand_dirmap_write
wr_mode = 0;
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
- as_dev->dma_addr);
+ dma_addr);
if (err)
- return 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);
@@ -807,65 +811,65 @@ static ssize_t airoha_snand_dirmap_write
REG_SPI_NFI_SNF_MISC_CTL2,
SPI_NFI_PROG_LOAD_BYTE_NUM, val);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
op->cmd.opcode));
if (err)
- return err;
+ goto error_dma_unmap;
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)
- return err;
+ goto error_dma_unmap;
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
SPI_NFI_READ_MODE);
if (err)
- return 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)
- return err;
+ goto error_dma_unmap;
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
SPI_NFI_DMA_MODE);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
SPI_NFI_WR_TRIG);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
SPI_NFI_WR_TRIG);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
val, (val & SPI_NFI_AHB_DONE), 0,
1 * USEC_PER_SEC);
if (err)
- return err;
+ goto error_dma_unmap;
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
REG_SPI_NFI_SNF_STA_CTL1, val,
(val & SPI_NFI_LOAD_TO_CACHE_DONE),
0, 1 * USEC_PER_SEC);
if (err)
- return err;
+ goto error_dma_unmap;
/*
* SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
@@ -875,13 +879,20 @@ static ssize_t airoha_snand_dirmap_write
SPI_NFI_LOAD_TO_CACHE_DONE,
SPI_NFI_LOAD_TO_CACHE_DONE);
if (err)
- return err;
+ goto error_dma_unmap;
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
+ DMA_TO_DEVICE);
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
if (err < 0)
return err;
return len;
+
+error_dma_unmap:
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
+ DMA_TO_DEVICE);
+ return err;
}
static int airoha_snand_exec_op(struct spi_mem *mem,
@@ -956,42 +967,20 @@ static const struct spi_controller_mem_o
static int airoha_snand_setup(struct spi_device *spi)
{
struct airoha_snand_ctrl *as_ctrl;
- struct airoha_snand_dev *as_dev;
-
- as_ctrl = spi_controller_get_devdata(spi->controller);
-
- as_dev = devm_kzalloc(as_ctrl->dev, sizeof(*as_dev), GFP_KERNEL);
- if (!as_dev)
- return -ENOMEM;
+ u8 *txrx_buf;
/* prepare device buffer */
- as_dev->buf_len = SPI_NAND_CACHE_SIZE;
- as_dev->txrx_buf = devm_kzalloc(as_ctrl->dev, as_dev->buf_len,
- GFP_KERNEL);
- if (!as_dev->txrx_buf)
- return -ENOMEM;
-
- as_dev->dma_addr = dma_map_single(as_ctrl->dev, as_dev->txrx_buf,
- as_dev->buf_len, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
+ as_ctrl = spi_controller_get_devdata(spi->controller);
+ txrx_buf = devm_kzalloc(as_ctrl->dev, SPI_NAND_CACHE_SIZE,
+ GFP_KERNEL);
+ if (!txrx_buf)
return -ENOMEM;
- spi_set_ctldata(spi, as_dev);
+ spi_set_ctldata(spi, txrx_buf);
return 0;
}
-static void airoha_snand_cleanup(struct spi_device *spi)
-{
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
- struct airoha_snand_ctrl *as_ctrl;
-
- as_ctrl = spi_controller_get_devdata(spi->controller);
- dma_unmap_single(as_ctrl->dev, as_dev->dma_addr,
- as_dev->buf_len, DMA_BIDIRECTIONAL);
- spi_set_ctldata(spi, NULL);
-}
-
static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
{
u32 val, sec_size, sec_num;
@@ -1093,7 +1082,6 @@ static int airoha_snand_probe(struct pla
ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
ctrl->mode_bits = SPI_RX_DUAL;
ctrl->setup = airoha_snand_setup;
- ctrl->cleanup = airoha_snand_cleanup;
device_set_node(&ctrl->dev, dev_fwnode(dev));
err = airoha_snand_nfi_setup(as_ctrl);