[PATCH 2/5] spi: ma35d1-qspi: Move speed setting to bus configuration
Miquel Raynal
miquel.raynal at bootlin.com
Thu Aug 13 01:00:22 PDT 2026
The speed setting is wrongly placed inside the "setup transfer" helper,
since the bus configuration may require the speed to be correct. Indeed,
DTR mode (not yet available) divides by 2 the bus clock when enabled. As
a result, to remain at a constant clock speed (and improve the data
rate), we must double the bus clock when enabling DTR. In order to
prepare for this change, move all the bus configuration required for
each step of the operation inside a unique helper called
nuvoton_qspi_configure_bus().
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
drivers/spi/spi-ma35d1-qspi.c | 69 +++++++++++++++++++++++++++----------------
1 file changed, 44 insertions(+), 25 deletions(-)
diff --git a/drivers/spi/spi-ma35d1-qspi.c b/drivers/spi/spi-ma35d1-qspi.c
index 929546dbe38f..b4fd0ab4bd31 100644
--- a/drivers/spi/spi-ma35d1-qspi.c
+++ b/drivers/spi/spi-ma35d1-qspi.c
@@ -131,11 +131,15 @@ static int nuvoton_qspi_reset_fifo(struct nuvoton_qspi *qspi)
1, NUVOTON_QSPI_TIMEOUT_US);
}
-static int nuvoton_qspi_set_speed(struct nuvoton_qspi *qspi, u32 speed_hz)
+static int nuvoton_qspi_set_speed(struct spi_device *spi, u32 speed_hz)
{
+ struct nuvoton_qspi *qspi = spi_controller_get_devdata(spi->controller);
unsigned long clk_rate;
u32 div;
+ if (!speed_hz)
+ speed_hz = spi->max_speed_hz;
+
if (!speed_hz)
return -EINVAL;
@@ -174,24 +178,16 @@ static int nuvoton_qspi_set_bits_per_word(struct nuvoton_qspi *qspi, u8 bpw)
return 0;
}
-static int nuvoton_qspi_setup_transfer(struct spi_device *spi,
- u32 speed_hz, u8 bpw)
+static int nuvoton_qspi_setup_transfer(struct spi_device *spi, u8 bpw)
{
struct nuvoton_qspi *qspi = spi_controller_get_devdata(spi->controller);
u32 mode = spi->mode & SPI_MODE_X_MASK;
u32 ctl = 0;
int ret;
- if (!speed_hz)
- speed_hz = spi->max_speed_hz;
-
if (!bpw)
bpw = NUVOTON_QSPI_DEFAULT_BPW;
- ret = nuvoton_qspi_set_speed(qspi, speed_hz);
- if (ret)
- return ret;
-
ret = nuvoton_qspi_set_bits_per_word(qspi, bpw);
if (ret)
return ret;
@@ -216,11 +212,18 @@ static int nuvoton_qspi_setup_transfer(struct spi_device *spi,
return 0;
}
-static void nuvoton_qspi_set_bus_width(struct nuvoton_qspi *qspi,
- unsigned int buswidth,
- enum spi_mem_data_dir dir)
+static int nuvoton_qspi_configure_bus(struct spi_device *spi,
+ unsigned int buswidth,
+ enum spi_mem_data_dir dir,
+ u32 speed_hz)
{
+ struct nuvoton_qspi *qspi = spi_controller_get_devdata(spi->controller);
u32 ctl = 0;
+ int ret;
+
+ ret = nuvoton_qspi_set_speed(spi, speed_hz);
+ if (ret)
+ return ret;
if (buswidth == 4)
ctl |= NUVOTON_QSPI_CTL_QUADIOEN_MASK;
@@ -234,6 +237,8 @@ static void nuvoton_qspi_set_bus_width(struct nuvoton_qspi *qspi,
NUVOTON_QSPI_CTL_QUADIOEN_MASK |
NUVOTON_QSPI_CTL_DUALIOEN_MASK |
NUVOTON_QSPI_CTL_DATDIR_MASK, ctl);
+
+ return 0;
}
static u32 nuvoton_qspi_tx_byte(const void *txbuf, unsigned int idx)
@@ -459,14 +464,17 @@ static int nuvoton_qspi_mem_exec_op(struct spi_mem *mem,
int ret;
int i;
- ret = nuvoton_qspi_setup_transfer(spi, op->max_freq,
- NUVOTON_QSPI_DEFAULT_BPW);
+ ret = nuvoton_qspi_setup_transfer(spi, NUVOTON_QSPI_DEFAULT_BPW);
if (ret)
return ret;
nuvoton_qspi_mem_set_cs(spi, true);
- nuvoton_qspi_set_bus_width(qspi, op->cmd.buswidth, SPI_MEM_DATA_OUT);
+ ret = nuvoton_qspi_configure_bus(spi, op->cmd.buswidth, SPI_MEM_DATA_OUT,
+ op->max_freq);
+ if (ret)
+ goto out_deassert_cs;
+
ret = nuvoton_qspi_txrx(qspi, &opcode, NULL, 1);
if (ret)
goto out_deassert_cs;
@@ -475,24 +483,33 @@ static int nuvoton_qspi_mem_exec_op(struct spi_mem *mem,
for (i = 0; i < op->addr.nbytes; i++)
addr[i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
- nuvoton_qspi_set_bus_width(qspi, op->addr.buswidth,
- SPI_MEM_DATA_OUT);
+ ret = nuvoton_qspi_configure_bus(spi, op->addr.buswidth, SPI_MEM_DATA_OUT,
+ op->max_freq);
+ if (ret)
+ goto out_deassert_cs;
+
ret = nuvoton_qspi_txrx(qspi, addr, NULL, op->addr.nbytes);
if (ret)
goto out_deassert_cs;
}
if (op->dummy.nbytes) {
- nuvoton_qspi_set_bus_width(qspi, op->dummy.buswidth,
- SPI_MEM_DATA_OUT);
+ ret = nuvoton_qspi_configure_bus(spi, op->dummy.buswidth, SPI_MEM_DATA_OUT,
+ op->max_freq);
+ if (ret)
+ goto out_deassert_cs;
+
ret = nuvoton_qspi_txrx(qspi, NULL, NULL, op->dummy.nbytes);
if (ret)
goto out_deassert_cs;
}
if (op->data.nbytes) {
- nuvoton_qspi_set_bus_width(qspi, op->data.buswidth,
- op->data.dir);
+ ret = nuvoton_qspi_configure_bus(spi, op->data.buswidth, op->data.dir,
+ op->max_freq);
+ if (ret)
+ goto out_deassert_cs;
+
ret = nuvoton_qspi_txrx(qspi,
op->data.dir == SPI_MEM_DATA_OUT ?
op->data.buf.out : NULL,
@@ -528,8 +545,7 @@ static int nuvoton_qspi_transfer_one(struct spi_controller *ctlr,
unsigned int buswidth = 1;
int ret;
- ret = nuvoton_qspi_setup_transfer(spi, xfer->speed_hz,
- xfer->bits_per_word);
+ ret = nuvoton_qspi_setup_transfer(spi, xfer->bits_per_word);
if (ret)
return ret;
@@ -552,7 +568,10 @@ static int nuvoton_qspi_transfer_one(struct spi_controller *ctlr,
buswidth = 2;
}
- nuvoton_qspi_set_bus_width(qspi, buswidth, dir);
+ ret = nuvoton_qspi_configure_bus(spi, buswidth, dir, xfer->speed_hz);
+ if (ret)
+ return ret;
+
ret = nuvoton_qspi_txrx(qspi, xfer->tx_buf, xfer->rx_buf,
xfer->len);
--
2.54.0
More information about the linux-arm-kernel
mailing list