[PATCH] spi: Replace `dummy.nbytes` with `dummy.ncycles`

Patrice CHOTARD patrice.chotard at foss.st.com
Mon Sep 12 02:44:41 PDT 2022


Hi Sergiu

On 9/11/22 19:45, Sergiu Moga wrote:
> In order to properly represent the hardware functionality
> in the core, avoid reconverting the number of dummy cycles
> to the number of bytes and only work with the former.
> Instead, let the drivers that do need this conversion do
> it themselves.
> 
> Signed-off-by: Sergiu Moga <sergiu.moga at microchip.com>
> ---
>  drivers/mtd/spi-nor/core.c        | 22 ++++----------
>  drivers/mtd/spi-nor/micron-st.c   |  2 +-
>  drivers/spi/atmel-quadspi.c       |  6 ++--
>  drivers/spi/spi-aspeed-smc.c      | 32 ++++++++++++++-------
>  drivers/spi/spi-ath79.c           |  2 +-
>  drivers/spi/spi-bcm-qspi.c        | 12 +++++---
>  drivers/spi/spi-cadence-quadspi.c |  8 ++----
>  drivers/spi/spi-cadence-xspi.c    |  5 +++-
>  drivers/spi/spi-dw-core.c         | 10 +++++--
>  drivers/spi/spi-fsl-qspi.c        | 17 ++++++-----
>  drivers/spi/spi-hisi-sfc-v3xx.c   |  6 +++-
>  drivers/spi/spi-mem.c             | 27 +++++++++++------
>  drivers/spi/spi-mt65xx.c          | 33 ++++++++++++++-------
>  drivers/spi/spi-mtk-nor.c         | 48 +++++++++++++++++--------------
>  drivers/spi/spi-mtk-snfi.c        | 24 ++++++++++------
>  drivers/spi/spi-mxic.c            | 18 ++++++++----
>  drivers/spi/spi-npcm-fiu.c        | 17 ++++++++---
>  drivers/spi/spi-nxp-fspi.c        | 10 +++----
>  drivers/spi/spi-rockchip-sfc.c    | 27 +++++++++++------
>  drivers/spi/spi-rpc-if.c          |  5 ++--
>  drivers/spi/spi-stm32-qspi.c      |  5 ++--
>  drivers/spi/spi-ti-qspi.c         | 12 ++++++--
>  drivers/spi/spi-zynq-qspi.c       | 15 ++++++----
>  drivers/spi/spi-zynqmp-gqspi.c    |  8 ++++--
>  include/linux/spi/spi-mem.h       | 10 +++----
>  25 files changed, 234 insertions(+), 147 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index f2c64006f8d7..cc8ca824f912 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -88,7 +88,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
>  	if (op->addr.nbytes)
>  		op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto);
>  
> -	if (op->dummy.nbytes)
> +	if (op->dummy.ncycles)
>  		op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto);
>  
>  	if (op->data.nbytes)
> @@ -106,9 +106,6 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
>  		op->dummy.dtr = true;
>  		op->data.dtr = true;
>  
> -		/* 2 bytes per clock cycle in DTR mode. */
> -		op->dummy.nbytes *= 2;
> -

What is the benefit to remove dtr dummy.nbytes computation ? it leads to spray it in all drivers which support DTR.
It was simpler to let the framework to deal with it, have i missed something ?

Patrice

>  		ext = spi_nor_get_cmd_ext(nor, op);
>  		op->cmd.opcode = (op->cmd.opcode << 8) | ext;
>  		op->cmd.nbytes = 2;
> @@ -207,10 +204,7 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from,
>  
>  	spi_nor_spimem_setup_op(nor, &op, nor->read_proto);
>  
> -	/* convert the dummy cycles to the number of bytes */
> -	op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
> -	if (spi_nor_protocol_is_dtr(nor->read_proto))
> -		op.dummy.nbytes *= 2;
> +	op.dummy.ncycles = nor->read_dummy;
>  
>  	usebouncebuf = spi_nor_spimem_bounce(nor, &op);
>  
> @@ -455,7 +449,7 @@ int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
>  
>  		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
>  			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
> -			op.dummy.nbytes = nor->params->rdsr_dummy;
> +			op.dummy.ncycles = nor->params->rdsr_dummy;
>  			/*
>  			 * We don't want to read only one byte in DTR mode. So,
>  			 * read 2 and then discard the second byte.
> @@ -1913,10 +1907,7 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor,
>  
>  	spi_nor_spimem_setup_op(nor, &op, read->proto);
>  
> -	/* convert the dummy cycles to the number of bytes */
> -	op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
> -	if (spi_nor_protocol_is_dtr(nor->read_proto))
> -		op.dummy.nbytes *= 2;

the same here

> +	op.dummy.ncycles = nor->read_dummy;
>  
>  	return spi_nor_spimem_check_op(nor, &op);
>  }
> @@ -3034,10 +3025,7 @@ static int spi_nor_create_read_dirmap(struct spi_nor *nor)
>  
>  	spi_nor_spimem_setup_op(nor, op, nor->read_proto);
>  
> -	/* convert the dummy cycles to the number of bytes */
> -	op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8;
> -	if (spi_nor_protocol_is_dtr(nor->read_proto))
> -		op->dummy.nbytes *= 2;

ditto

> +	op->dummy.ncycles = nor->read_dummy;
>  
>  	/*
>  	 * Since spi_nor_spimem_setup_op() only sets buswidth when the number
> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> index 3c9681a3f7a3..840a9fc0a888 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -337,7 +337,7 @@ static int micron_st_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
>  
>  		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
>  			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
> -			op.dummy.nbytes = nor->params->rdsr_dummy;
> +			op.dummy.ncycles = nor->params->rdsr_dummy;
>  			/*
>  			 * We don't want to read only one byte in DTR mode. So,
>  			 * read 2 and then discard the second byte.
> diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
> index 976a217e356d..9a86525e7a4a 100644
> --- a/drivers/spi/atmel-quadspi.c
> +++ b/drivers/spi/atmel-quadspi.c
> @@ -286,7 +286,7 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem,
>  
>  	/* special case not supported by hardware */
>  	if (op->addr.nbytes == 2 && op->cmd.buswidth != op->addr.buswidth &&
> -	    op->dummy.nbytes == 0)
> +	    op->dummy.ncycles == 0)
>  		return false;
>  
>  	return true;
> @@ -308,8 +308,8 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
>  		return mode;
>  	ifr |= atmel_qspi_modes[mode].config;
>  
> -	if (op->dummy.nbytes)
> -		dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
> +	if (op->dummy.ncycles)
> +		dummy_cycles = op->dummy.ncycles;
>  
>  	/*
>  	 * The controller allows 24 and 32-bit addressing while NAND-flash
> diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
> index 3e891bf22470..2d50d50a9303 100644
> --- a/drivers/spi/spi-aspeed-smc.c
> +++ b/drivers/spi/spi-aspeed-smc.c
> @@ -231,7 +231,7 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
>  				    u64 offset, size_t len, void *buf)
>  {
>  	int io_mode = aspeed_spi_get_io_mode(op);
> -	u8 dummy = 0xFF;
> +	u8 dummy = 0xFF, dummy_nbytes;
>  	int i;
>  	int ret;
>  
> @@ -241,8 +241,12 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
>  	if (ret < 0)
>  		return ret;
>  
> -	if (op->dummy.buswidth && op->dummy.nbytes) {
> -		for (i = 0; i < op->dummy.nbytes / op->dummy.buswidth; i++)
> +	if (op->dummy.buswidth && op->dummy.ncycles) {
> +		dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +		if (op->dummy.dtr)
> +			dummy_nbytes *= 2;
> +
> +		for (i = 0; i < dummy_nbytes / op->dummy.buswidth; i++)
>  			aspeed_spi_write_to_ahb(chip->ahb_base, &dummy,	sizeof(dummy));
>  	}
>  
> @@ -270,6 +274,8 @@ static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
>  /* support for 1-1-1, 1-1-2 or 1-1-4 */
>  static bool aspeed_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  {
> +	u8 dummy_nbytes;
> +
>  	if (op->cmd.buswidth > 1)
>  		return false;
>  
> @@ -280,8 +286,12 @@ static bool aspeed_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op
>  			return false;
>  	}
>  
> -	if (op->dummy.nbytes != 0) {
> -		if (op->dummy.buswidth > 1 || op->dummy.nbytes > 7)
> +	if (op->dummy.ncycles != 0) {
> +		dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +		if (op->dummy.dtr)
> +			dummy_nbytes *= 2;
> +
> +		if (op->dummy.buswidth > 1 || dummy_nbytes > 7)
>  			return false;
>  	}
>  
> @@ -306,7 +316,7 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
>  		chip->cs, op->data.dir == SPI_MEM_DATA_IN ? "read" : "write",
>  		op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
>  		op->dummy.buswidth, op->data.buswidth,
> -		op->addr.nbytes, op->dummy.nbytes, op->data.nbytes);
> +		op->addr.nbytes, op->dummy.ncycles, op->data.nbytes);
>  
>  	addr_mode = readl(aspi->regs + CE_CTRL_REG);
>  	addr_mode_backup = addr_mode;
> @@ -327,8 +337,8 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
>  			ctl_val |= CTRL_IO_ADDRESS_4B;
>  	}
>  
> -	if (op->dummy.nbytes)
> -		ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.nbytes / op->dummy.buswidth);
> +	if (op->dummy.ncycles)
> +		ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.ncycles / 8);
>  
>  	if (op->data.nbytes)
>  		ctl_val |= aspeed_spi_get_io_mode(op);
> @@ -564,7 +574,7 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
>  		desc->info.offset, desc->info.offset + desc->info.length,
>  		op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
>  		op->dummy.buswidth, op->data.buswidth,
> -		op->addr.nbytes, op->dummy.nbytes);
> +		op->addr.nbytes, op->dummy.ncycles);
>  
>  	chip->clk_freq = desc->mem->spi->max_speed_hz;
>  
> @@ -584,8 +594,8 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
>  		op->cmd.opcode << CTRL_COMMAND_SHIFT |
>  		CTRL_IO_MODE_READ;
>  
> -	if (op->dummy.nbytes)
> -		ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.nbytes / op->dummy.buswidth);
> +	if (op->dummy.ncycles)
> +		ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.ncycles / 8);
>  
>  	/* Tune 4BYTE address mode */
>  	if (op->addr.nbytes) {
> diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
> index 607e7a49fb89..70bdb1eb42a2 100644
> --- a/drivers/spi/spi-ath79.c
> +++ b/drivers/spi/spi-ath79.c
> @@ -145,7 +145,7 @@ static int ath79_exec_mem_op(struct spi_mem *mem,
>  
>  	/* Only use for fast-read op. */
>  	if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN ||
> -	    op->addr.nbytes != 3 || op->dummy.nbytes != 1)
> +	    op->addr.nbytes != 3 || op->dummy.ncycles != 8)
>  		return -ENOTSUPP;
>  
>  	/* disable GPIO mode */
> diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
> index cad2d55dcd3d..143e411c1523 100644
> --- a/drivers/spi/spi-bcm-qspi.c
> +++ b/drivers/spi/spi-bcm-qspi.c
> @@ -428,8 +428,8 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,
>  	if (addrlen == BSPI_ADDRLEN_4BYTES)
>  		bpp = BSPI_BPP_ADDR_SELECT_MASK;
>  
> -	if (op->dummy.nbytes)
> -		bpp |= (op->dummy.nbytes * 8) / op->dummy.buswidth;
> +	if (op->dummy.ncycles)
> +		bpp |= op->dummy.ncycles;
>  
>  	switch (width) {
>  	case SPI_NBITS_SINGLE:
> @@ -1153,12 +1153,16 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi,
>  	struct spi_master *master = spi->master;
>  	struct bcm_qspi *qspi = spi_master_get_devdata(master);
>  	struct spi_transfer t[2];
> -	u8 cmd[6] = { };
> +	u8 cmd[6] = { }, dummy_nbytes;
>  	int ret, i;
>  
>  	memset(cmd, 0, sizeof(cmd));
>  	memset(t, 0, sizeof(t));
>  
> +	dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +
>  	/* tx */
>  	/* opcode is in cmd[0] */
>  	cmd[0] = op->cmd.opcode;
> @@ -1166,7 +1170,7 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi,
>  		cmd[1 + i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
>  
>  	t[0].tx_buf = cmd;
> -	t[0].len = op->addr.nbytes + op->dummy.nbytes + 1;
> +	t[0].len = op->addr.nbytes + dummy_nbytes + 1;
>  	t[0].bits_per_word = spi->bits_per_word;
>  	t[0].tx_nbits = op->cmd.buswidth;
>  	/* lets mspi know that this is not last transfer */
> diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
> index 72b1a5a2298c..2af43ba4a2cb 100644
> --- a/drivers/spi/spi-cadence-quadspi.c
> +++ b/drivers/spi/spi-cadence-quadspi.c
> @@ -356,12 +356,10 @@ static unsigned int cqspi_calc_dummy(const struct spi_mem_op *op)
>  {
>  	unsigned int dummy_clk;
>  
> -	if (!op->dummy.nbytes)
> +	if (!op->dummy.ncycles)
>  		return 0;
>  
> -	dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth);
> -	if (op->cmd.dtr)
> -		dummy_clk /= 2;
> +	dummy_clk = op->dummy.ncycles;
>  
>  	return dummy_clk;
>  }
> @@ -1333,7 +1331,7 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem,
>  	 */
>  	all_true = op->cmd.dtr &&
>  		   (!op->addr.nbytes || op->addr.dtr) &&
> -		   (!op->dummy.nbytes || op->dummy.dtr) &&
> +		   (!op->dummy.ncycles || op->dummy.dtr) &&
>  		   (!op->data.nbytes || op->data.dtr);
>  
>  	all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
> diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
> index 3ab19be83095..8575e4c2ed7a 100644
> --- a/drivers/spi/spi-cadence-xspi.c
> +++ b/drivers/spi/spi-cadence-xspi.c
> @@ -177,7 +177,10 @@
>  #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op) ( \
>  	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_DCNT_H, \
>  		((op)->data.nbytes >> 16) & 0xffff) | \
> -	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, (op)->dummy.nbytes * 8))
> +	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, \
> +		((op)->dummy.dtr ? \
> +		((op)->dummy.ncycles * (op)->dummy.buswidth * 2) : \
> +		((op)->dummy.ncycles * (op)->dummy.buswidth))))
>  
>  #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op, chipsel) ( \
>  	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_BANK, chipsel) | \
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index f87d97ccd2d6..0ba5c7d0e66e 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -498,13 +498,17 @@ static bool dw_spi_supports_mem_op(struct spi_mem *mem,
>  static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
>  {
>  	unsigned int i, j, len;
> -	u8 *out;
> +	u8 *out, dummy_nbytes;
>  
>  	/*
>  	 * Calculate the total length of the EEPROM command transfer and
>  	 * either use the pre-allocated buffer or create a temporary one.
>  	 */
> -	len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
> +	dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +
> +	len = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes;
>  	if (op->data.dir == SPI_MEM_DATA_OUT)
>  		len += op->data.nbytes;
>  
> @@ -525,7 +529,7 @@ static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
>  		out[i] = DW_SPI_GET_BYTE(op->cmd.opcode, op->cmd.nbytes - i - 1);
>  	for (j = 0; j < op->addr.nbytes; ++i, ++j)
>  		out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1);
> -	for (j = 0; j < op->dummy.nbytes; ++i, ++j)
> +	for (j = 0; j < dummy_nbytes; ++i, ++j)
>  		out[i] = 0x0;
>  
>  	if (op->data.dir == SPI_MEM_DATA_OUT)
> diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
> index 46ae46a944c5..897e8f11ccd1 100644
> --- a/drivers/spi/spi-fsl-qspi.c
> +++ b/drivers/spi/spi-fsl-qspi.c
> @@ -369,6 +369,7 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem,
>  				 const struct spi_mem_op *op)
>  {
>  	struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
> +	u8 dummy_nbytes;
>  	int ret;
>  
>  	ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth);
> @@ -376,7 +377,7 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem,
>  	if (op->addr.nbytes)
>  		ret |= fsl_qspi_check_buswidth(q, op->addr.buswidth);
>  
> -	if (op->dummy.nbytes)
> +	if (op->dummy.ncycles)
>  		ret |= fsl_qspi_check_buswidth(q, op->dummy.buswidth);
>  
>  	if (op->data.nbytes)
> @@ -389,14 +390,17 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem,
>  	 * The number of instructions needed for the op, needs
>  	 * to fit into a single LUT entry.
>  	 */
> +	dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +
>  	if (op->addr.nbytes +
> -	   (op->dummy.nbytes ? 1:0) +
> +	   (dummy_nbytes ? 1:0) +
>  	   (op->data.nbytes ? 1:0) > 6)
>  		return false;
>  
>  	/* Max 64 dummy clock cycles supported */
> -	if (op->dummy.nbytes &&
> -	    (op->dummy.nbytes * 8 / op->dummy.buswidth > 64))
> +	if (op->dummy.ncycles && op->dummy.ncycles > 64)
>  		return false;
>  
>  	/* Max data length, check controller limits and alignment */
> @@ -437,11 +441,10 @@ static void fsl_qspi_prepare_lut(struct fsl_qspi *q,
>  		lutidx++;
>  	}
>  
> -	if (op->dummy.nbytes) {
> +	if (op->dummy.ncycles) {
>  		lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
>  					      LUT_PAD(op->dummy.buswidth),
> -					      op->dummy.nbytes * 8 /
> -					      op->dummy.buswidth);
> +					      op->dummy.ncycles);
>  		lutidx++;
>  	}
>  
> diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c
> index d3a23b1c2a4c..5b6994eb7c8b 100644
> --- a/drivers/spi/spi-hisi-sfc-v3xx.c
> +++ b/drivers/spi/spi-hisi-sfc-v3xx.c
> @@ -276,6 +276,7 @@ static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host *host,
>  {
>  	int len = op->data.nbytes, buswidth_mode;
>  	u32 config = 0;
> +	u8 dummy_nbytes;
>  
>  	if (op->addr.nbytes)
>  		config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK;
> @@ -302,7 +303,10 @@ static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host *host,
>  	if (op->data.dir == SPI_MEM_DATA_IN)
>  		config |= HISI_SFC_V3XX_CMD_CFG_RW_MSK;
>  
> -	config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF |
> +	dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +	config |= dummy_nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF |
>  		  chip_select << HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF |
>  		  HISI_SFC_V3XX_CMD_CFG_START_MSK;
>  
> diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
> index 0c79193d9697..7b204963bb62 100644
> --- a/drivers/spi/spi-mem.c
> +++ b/drivers/spi/spi-mem.c
> @@ -149,7 +149,7 @@ static bool spi_mem_check_buswidth(struct spi_mem *mem,
>  	    spi_check_buswidth_req(mem, op->addr.buswidth, true))
>  		return false;
>  
> -	if (op->dummy.nbytes &&
> +	if (op->dummy.ncycles &&
>  	    spi_check_buswidth_req(mem, op->dummy.buswidth, true))
>  		return false;
>  
> @@ -202,7 +202,7 @@ static int spi_mem_check_op(const struct spi_mem_op *op)
>  		return -EINVAL;
>  
>  	if ((op->addr.nbytes && !op->addr.buswidth) ||
> -	    (op->dummy.nbytes && !op->dummy.buswidth) ||
> +	    (op->dummy.ncycles && !op->dummy.buswidth) ||
>  	    (op->data.nbytes && !op->data.buswidth))
>  		return -EINVAL;
>  
> @@ -315,7 +315,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  	struct spi_controller *ctlr = mem->spi->controller;
>  	struct spi_transfer xfers[4] = { };
>  	struct spi_message msg;
> -	u8 *tmpbuf;
> +	u8 *tmpbuf, dummy_nbytes;
>  	int ret;
>  
>  	ret = spi_mem_check_op(op);
> @@ -343,7 +343,11 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  			return ret;
>  	}
>  
> -	tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
> +	dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +
> +	tmpbufsize = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes;
>  
>  	/*
>  	 * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so
> @@ -379,15 +383,15 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  		totalxferlen += op->addr.nbytes;
>  	}
>  
> -	if (op->dummy.nbytes) {
> -		memset(tmpbuf + op->addr.nbytes + 1, 0xff, op->dummy.nbytes);
> +	if (dummy_nbytes) {
> +		memset(tmpbuf + op->addr.nbytes + 1, 0xff, dummy_nbytes);
>  		xfers[xferpos].tx_buf = tmpbuf + op->addr.nbytes + 1;
> -		xfers[xferpos].len = op->dummy.nbytes;
> +		xfers[xferpos].len = dummy_nbytes;
>  		xfers[xferpos].tx_nbits = op->dummy.buswidth;
>  		xfers[xferpos].dummy_data = 1;
>  		spi_message_add_tail(&xfers[xferpos], &msg);
>  		xferpos++;
> -		totalxferlen += op->dummy.nbytes;
> +		totalxferlen += dummy_nbytes;
>  	}
>  
>  	if (op->data.nbytes) {
> @@ -456,12 +460,17 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
>  {
>  	struct spi_controller *ctlr = mem->spi->controller;
>  	size_t len;
> +	u8 dummy_nbytes;
>  
>  	if (ctlr->mem_ops && ctlr->mem_ops->adjust_op_size)
>  		return ctlr->mem_ops->adjust_op_size(mem, op);
>  
> +	dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +
>  	if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) {
> -		len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
> +		len = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes;
>  
>  		if (len > spi_max_transfer_size(mem->spi))
>  			return -EINVAL;
> diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
> index 0a3b9f7eed30..22d002acebe8 100644
> --- a/drivers/spi/spi-mt65xx.c
> +++ b/drivers/spi/spi-mt65xx.c
> @@ -845,9 +845,13 @@ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
>  				      struct spi_mem_op *op)
>  {
>  	int opcode_len;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	if (op->data.dir != SPI_MEM_NO_DATA) {
> -		opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
> +		opcode_len = 1 + op->addr.nbytes + dummy_nbytes;
>  		if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
>  			op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len;
>  			/* force data buffer dma-aligned. */
> @@ -861,14 +865,19 @@ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
>  static bool mtk_spi_mem_supports_op(struct spi_mem *mem,
>  				    const struct spi_mem_op *op)
>  {
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +
>  	if (!spi_mem_default_supports_op(mem, op))
>  		return false;
>  
> -	if (op->addr.nbytes && op->dummy.nbytes &&
> +	if (op->addr.nbytes && dummy_nbytes &&
>  	    op->addr.buswidth != op->dummy.buswidth)
>  		return false;
>  
> -	if (op->addr.nbytes + op->dummy.nbytes > 16)
> +	if (op->addr.nbytes + dummy_nbytes > 16)
>  		return false;
>  
>  	if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
> @@ -942,6 +951,10 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
>  	u32 reg_val, nio, tx_size;
>  	char *tx_tmp_buf, *rx_tmp_buf;
>  	int ret = 0;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	mdata->use_spimem = true;
>  	reinit_completion(&mdata->spimem_done);
> @@ -957,8 +970,8 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
>  
>  	/* addr & dummy byte len */
>  	reg_val &= ~SPI_CFG3_IPM_ADDR_BYTELEN_MASK;
> -	if (op->addr.nbytes || op->dummy.nbytes)
> -		reg_val |= (op->addr.nbytes + op->dummy.nbytes) <<
> +	if (op->addr.nbytes || dummy_nbytes)
> +		reg_val |= (op->addr.nbytes + dummy_nbytes) <<
>  			    SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET;
>  
>  	/* data byte len */
> @@ -971,7 +984,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
>  		mtk_spi_setup_packet(mem->spi->master);
>  	}
>  
> -	if (op->addr.nbytes || op->dummy.nbytes) {
> +	if (op->addr.nbytes || dummy_nbytes) {
>  		if (op->addr.buswidth == 1 || op->dummy.buswidth == 1)
>  			reg_val |= SPI_CFG3_IPM_XMODE_EN;
>  		else
> @@ -999,7 +1012,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
>  		reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR;
>  	writel(reg_val, mdata->base + SPI_CFG3_IPM_REG);
>  
> -	tx_size = 1 + op->addr.nbytes + op->dummy.nbytes;
> +	tx_size = 1 + op->addr.nbytes + dummy_nbytes;
>  	if (op->data.dir == SPI_MEM_DATA_OUT)
>  		tx_size += op->data.nbytes;
>  
> @@ -1021,13 +1034,13 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
>  					(8 * (op->addr.nbytes - i - 1));
>  	}
>  
> -	if (op->dummy.nbytes)
> +	if (dummy_nbytes)
>  		memset(tx_tmp_buf + op->addr.nbytes + 1,
>  		       0xff,
> -		       op->dummy.nbytes);
> +		       dummy_nbytes);
>  
>  	if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
> -		memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1,
> +		memcpy(tx_tmp_buf + dummy_nbytes + op->addr.nbytes + 1,
>  		       op->data.buf.out,
>  		       op->data.nbytes);
>  
> diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
> index d167699a1a96..f6870c6e911a 100644
> --- a/drivers/spi/spi-mtk-nor.c
> +++ b/drivers/spi/spi-mtk-nor.c
> @@ -171,23 +171,18 @@ static bool need_bounce(struct mtk_nor *sp, const struct spi_mem_op *op)
>  
>  static bool mtk_nor_match_read(const struct spi_mem_op *op)
>  {
> -	int dummy = 0;
> -
> -	if (op->dummy.nbytes)
> -		dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth;
> -
>  	if ((op->data.buswidth == 2) || (op->data.buswidth == 4)) {
>  		if (op->addr.buswidth == 1)
> -			return dummy == 8;
> +			return op->dummy.ncycles == 8;
>  		else if (op->addr.buswidth == 2)
> -			return dummy == 4;
> +			return op->dummy.ncycles == 4;
>  		else if (op->addr.buswidth == 4)
> -			return dummy == 6;
> +			return op->dummy.ncycles == 6;
>  	} else if ((op->addr.buswidth == 1) && (op->data.buswidth == 1)) {
>  		if (op->cmd.opcode == 0x03)
> -			return dummy == 0;
> +			return op->dummy.ncycles == 0;
>  		else if (op->cmd.opcode == 0x0b)
> -			return dummy == 8;
> +			return op->dummy.ncycles == 8;
>  	}
>  	return false;
>  }
> @@ -195,6 +190,10 @@ static bool mtk_nor_match_read(const struct spi_mem_op *op)
>  static bool mtk_nor_match_prg(const struct spi_mem_op *op)
>  {
>  	int tx_len, rx_len, prg_len, prg_left;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	// prg mode is spi-only.
>  	if ((op->cmd.buswidth > 1) || (op->addr.buswidth > 1) ||
> @@ -205,7 +204,7 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op)
>  
>  	if (op->data.dir == SPI_MEM_DATA_OUT) {
>  		// count dummy bytes only if we need to write data after it
> -		tx_len += op->dummy.nbytes;
> +		tx_len += dummy_nbytes;
>  
>  		// leave at least one byte for data
>  		if (tx_len > MTK_NOR_REG_PRGDATA_MAX)
> @@ -221,7 +220,7 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op)
>  			return false;
>  
>  		rx_len = op->data.nbytes;
> -		prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - op->dummy.nbytes;
> +		prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - dummy_nbytes;
>  		if (prg_left > MTK_NOR_REG_SHIFT_MAX + 1)
>  			prg_left = MTK_NOR_REG_SHIFT_MAX + 1;
>  		if (rx_len > prg_left) {
> @@ -230,11 +229,11 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op)
>  			rx_len = prg_left;
>  		}
>  
> -		prg_len = tx_len + op->dummy.nbytes + rx_len;
> +		prg_len = tx_len + dummy_nbytes + rx_len;
>  		if (prg_len > MTK_NOR_PRG_CNT_MAX / 8)
>  			return false;
>  	} else {
> -		prg_len = tx_len + op->dummy.nbytes;
> +		prg_len = tx_len + dummy_nbytes;
>  		if (prg_len > MTK_NOR_PRG_CNT_MAX / 8)
>  			return false;
>  	}
> @@ -244,15 +243,19 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op)
>  static void mtk_nor_adj_prg_size(struct spi_mem_op *op)
>  {
>  	int tx_len, tx_left, prg_left;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	tx_len = op->cmd.nbytes + op->addr.nbytes;
>  	if (op->data.dir == SPI_MEM_DATA_OUT) {
> -		tx_len += op->dummy.nbytes;
> +		tx_len += dummy_nbytes;
>  		tx_left = MTK_NOR_REG_PRGDATA_MAX + 1 - tx_len;
>  		if (op->data.nbytes > tx_left)
>  			op->data.nbytes = tx_left;
>  	} else if (op->data.dir == SPI_MEM_DATA_IN) {
> -		prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - op->dummy.nbytes;
> +		prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - dummy_nbytes;
>  		if (prg_left > MTK_NOR_REG_SHIFT_MAX + 1)
>  			prg_left = MTK_NOR_REG_SHIFT_MAX + 1;
>  		if (op->data.nbytes > prg_left)
> @@ -312,7 +315,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem,
>  			break;
>  		case SPI_MEM_DATA_OUT:
>  			if ((op->addr.buswidth == 1) &&
> -			    (op->dummy.nbytes == 0) &&
> +			    (op->dummy.ncycles == 0) &&
>  			    (op->data.buswidth == 1))
>  				return true;
>  			break;
> @@ -515,17 +518,20 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op)
>  	int tx_len, prg_len;
>  	int i, ret;
>  	void __iomem *reg;
> -	u8 bufbyte;
> +	u8 bufbyte, dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	tx_len = op->cmd.nbytes + op->addr.nbytes;
>  
>  	// count dummy bytes only if we need to write data after it
>  	if (op->data.dir == SPI_MEM_DATA_OUT)
> -		tx_len += op->dummy.nbytes + op->data.nbytes;
> +		tx_len += dummy_nbytes + op->data.nbytes;
>  	else if (op->data.dir == SPI_MEM_DATA_IN)
>  		rx_len = op->data.nbytes;
>  
> -	prg_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes +
> +	prg_len = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes +
>  		  op->data.nbytes;
>  
>  	// an invalid op may reach here if the caller calls exec_op without
> @@ -550,7 +556,7 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op)
>  	}
>  
>  	if (op->data.dir == SPI_MEM_DATA_OUT) {
> -		for (i = 0; i < op->dummy.nbytes; i++, reg_offset--) {
> +		for (i = 0; i < dummy_nbytes; i++, reg_offset--) {
>  			reg = sp->base + MTK_NOR_REG_PRGDATA(reg_offset);
>  			writeb(0, reg);
>  		}
> diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c
> index d66bf9762557..05d2f0a97feb 100644
> --- a/drivers/spi/spi-mtk-snfi.c
> +++ b/drivers/spi/spi-mtk-snfi.c
> @@ -434,7 +434,10 @@ static int mtk_snand_mac_io(struct mtk_snand *snf, const struct spi_mem_op *op)
>  	const u8 *tx_buf = NULL;
>  	u8 *rx_buf = NULL;
>  	int i, ret;
> -	u8 b;
> +	u8 b, dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	if (op->data.dir == SPI_MEM_DATA_IN) {
>  		rx_len = op->data.nbytes;
> @@ -463,7 +466,7 @@ static int mtk_snand_mac_io(struct mtk_snand *snf, const struct spi_mem_op *op)
>  		}
>  	}
>  
> -	for (i = 0; i < op->dummy.nbytes; i++, reg_offs++) {
> +	for (i = 0; i < dummy_nbytes; i++, reg_offs++) {
>  		if (reg_offs % 4 == 3) {
>  			nfi_write32(snf, SNF_GPRAM + reg_offs - 3, val);
>  			val = 0;
> @@ -836,7 +839,7 @@ static int mtk_snand_read_page_cache(struct mtk_snand *snf,
>  	u32 op_addr = op->addr.val;
>  	// where to start copying data from bounce buffer
>  	u32 rd_offset = 0;
> -	u32 dummy_clk = (op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth);
> +	u32 dummy_clk = op->dummy.ncycles;
>  	u32 op_mode = 0;
>  	u32 dma_len = snf->buf_len;
>  	int ret = 0;
> @@ -1178,8 +1181,7 @@ static bool mtk_snand_is_page_ops(const struct spi_mem_op *op)
>  	// match read from page instructions
>  	if (op->data.dir == SPI_MEM_DATA_IN) {
>  		// check dummy cycle first
> -		if (op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth >
> -		    DATA_READ_MAX_DUMMY)
> +		if (op->dummy.ncycles > DATA_READ_MAX_DUMMY)
>  			return false;
>  		// quad io / quad out
>  		if ((op->addr.buswidth == 4 || op->addr.buswidth == 1) &&
> @@ -1196,7 +1198,7 @@ static bool mtk_snand_is_page_ops(const struct spi_mem_op *op)
>  			return true;
>  	} else if (op->data.dir == SPI_MEM_DATA_OUT) {
>  		// check dummy cycle first
> -		if (op->dummy.nbytes)
> +		if (op->dummy.ncycles)
>  			return false;
>  		// program load quad out
>  		if (op->addr.buswidth == 1 && op->data.buswidth == 4)
> @@ -1218,7 +1220,7 @@ static bool mtk_snand_supports_op(struct spi_mem *mem,
>  	if (mtk_snand_is_page_ops(op))
>  		return true;
>  	return ((op->addr.nbytes == 0 || op->addr.buswidth == 1) &&
> -		(op->dummy.nbytes == 0 || op->dummy.buswidth == 1) &&
> +		(op->dummy.ncycles == 0 || op->dummy.buswidth == 1) &&
>  		(op->data.nbytes == 0 || op->data.buswidth == 1));
>  }
>  
> @@ -1239,7 +1241,13 @@ static int mtk_snand_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
>  		if (op->data.nbytes > l)
>  			op->data.nbytes = l;
>  	} else {
> -		size_t hl = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
> +		size_t hl;
> +		u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +		if (op->dummy.dtr)
> +			dummy_nbytes *= 2;
> +
> +		hl = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes;
>  
>  		if (hl >= SNF_GPRAM_SIZE)
>  			return -EOPNOTSUPP;
> diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
> index 65be8e085ab8..d940ee0e11a5 100644
> --- a/drivers/spi/spi-mxic.c
> +++ b/drivers/spi/spi-mxic.c
> @@ -316,14 +316,18 @@ static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op,
>  	u32 cfg = OP_CMD_BYTES(op->cmd.nbytes) |
>  		  OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) |
>  		  (op->cmd.dtr ? OP_CMD_DDR : 0);
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	if (op->addr.nbytes)
>  		cfg |= OP_ADDR_BYTES(op->addr.nbytes) |
>  		       OP_ADDR_BUSW(fls(op->addr.buswidth) - 1) |
>  		       (op->addr.dtr ? OP_ADDR_DDR : 0);
>  
> -	if (op->dummy.nbytes)
> -		cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
> +	if (dummy_nbytes)
> +		cfg |= OP_DUMMY_CYC(dummy_nbytes);
>  
>  	/* Direct mapping data.nbytes field is not populated */
>  	if (data_len) {
> @@ -481,7 +485,7 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
>  	    op->dummy.buswidth > 8 || op->cmd.buswidth > 8)
>  		return false;
>  
> -	if (op->data.nbytes && op->dummy.nbytes &&
> +	if (op->data.nbytes && op->dummy.ncycles &&
>  	    op->data.buswidth != op->dummy.buswidth)
>  		return false;
>  
> @@ -512,7 +516,11 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
>  {
>  	struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
>  	int i, ret;
> -	u8 addr[8], cmd[2];
> +	u8 addr[8], cmd[2], dummy_nbytes;
> +
> +	dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
>  	if (ret)
> @@ -543,7 +551,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
>  	if (ret)
>  		goto out;
>  
> -	ret = mxic_spi_data_xfer(mxic, NULL, NULL, op->dummy.nbytes);
> +	ret = mxic_spi_data_xfer(mxic, NULL, NULL, dummy_nbytes);
>  	if (ret)
>  		goto out;
>  
> diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c
> index 49f6424e35af..17493f668459 100644
> --- a/drivers/spi/spi-npcm-fiu.c
> +++ b/drivers/spi/spi-npcm-fiu.c
> @@ -265,6 +265,11 @@ static const struct regmap_config npcm_mtd_regmap_config = {
>  static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu,
>  			     const struct spi_mem_op *op)
>  {
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
> +
>  	regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
>  			   NPCM_FIU_DRD_CFG_ACCTYPE,
>  			   ilog2(op->addr.buswidth) <<
> @@ -272,8 +277,8 @@ static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu,
>  	fiu->drd_op.addr.buswidth = op->addr.buswidth;
>  	regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
>  			   NPCM_FIU_DRD_CFG_DBW,
> -			   op->dummy.nbytes << NPCM_FIU_DRD_DBW_SHIFT);
> -	fiu->drd_op.dummy.nbytes = op->dummy.nbytes;
> +			   dummy_nbytes << NPCM_FIU_DRD_DBW_SHIFT);
> +	fiu->drd_op.dummy.ncycles = op->dummy.ncycles;
>  	regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
>  			   NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode);
>  	fiu->drd_op.cmd.opcode = op->cmd.opcode;
> @@ -299,7 +304,7 @@ static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc,
>  			*(buf_rx + i) = ioread8(src + i);
>  	} else {
>  		if (desc->info.op_tmpl.addr.buswidth != fiu->drd_op.addr.buswidth ||
> -		    desc->info.op_tmpl.dummy.nbytes != fiu->drd_op.dummy.nbytes ||
> +		    desc->info.op_tmpl.dummy.ncycles != fiu->drd_op.dummy.ncycles ||
>  		    desc->info.op_tmpl.cmd.opcode != fiu->drd_op.cmd.opcode ||
>  		    desc->info.op_tmpl.addr.nbytes != fiu->drd_op.addr.nbytes)
>  			npcm_fiu_set_drd(fiu, &desc->info.op_tmpl);
> @@ -341,6 +346,10 @@ static int npcm_fiu_uma_read(struct spi_mem *mem,
>  	int ret;
>  	u32 val;
>  	u32 i;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
>  			   NPCM_FIU_UMA_CTS_DEV_NUM,
> @@ -357,7 +366,7 @@ static int npcm_fiu_uma_read(struct spi_mem *mem,
>  			<< NPCM_FIU_UMA_CFG_DBPCK_SHIFT;
>  		uma_cfg |= ilog2(op->data.buswidth)
>  			<< NPCM_FIU_UMA_CFG_RDBPCK_SHIFT;
> -		uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT;
> +		uma_cfg |= dummy_nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT;
>  		uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT;
>  		regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, addr);
>  	} else {
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index 2b0301fc971c..ccec9b726283 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -444,7 +444,7 @@ static bool nxp_fspi_supports_op(struct spi_mem *mem,
>  	if (op->addr.nbytes)
>  		ret |= nxp_fspi_check_buswidth(f, op->addr.buswidth);
>  
> -	if (op->dummy.nbytes)
> +	if (op->dummy.ncycles)
>  		ret |= nxp_fspi_check_buswidth(f, op->dummy.buswidth);
>  
>  	if (op->data.nbytes)
> @@ -468,8 +468,7 @@ static bool nxp_fspi_supports_op(struct spi_mem *mem,
>  		return false;
>  
>  	/* Max 64 dummy clock cycles supported */
> -	if (op->dummy.buswidth &&
> -	    (op->dummy.nbytes * 8 / op->dummy.buswidth > 64))
> +	if (op->dummy.ncycles > 64)
>  		return false;
>  
>  	/* Max data length, check controller limits and alignment */
> @@ -543,15 +542,14 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
>  	}
>  
>  	/* dummy bytes, if needed */
> -	if (op->dummy.nbytes) {
> +	if (op->dummy.ncycles) {
>  		lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
>  		/*
>  		 * Due to FlexSPI controller limitation number of PAD for dummy
>  		 * buswidth needs to be programmed as equal to data buswidth.
>  		 */
>  					      LUT_PAD(op->data.buswidth),
> -					      op->dummy.nbytes * 8 /
> -					      op->dummy.buswidth);
> +					      op->dummy.ncycles);
>  		lutidx++;
>  	}
>  
> diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c
> index bd87d3c92dd3..82f9e61b9036 100644
> --- a/drivers/spi/spi-rockchip-sfc.c
> +++ b/drivers/spi/spi-rockchip-sfc.c
> @@ -282,16 +282,21 @@ static int rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc *sfc, u32 timeout_
>  
>  static void rockchip_sfc_adjust_op_work(struct spi_mem_op *op)
>  {
> -	if (unlikely(op->dummy.nbytes && !op->addr.nbytes)) {
> +	if (unlikely(op->dummy.ncycles && !op->addr.nbytes)) {
> +		u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +		if (op->dummy.dtr)
> +			dummy_nbytes *= 2;
> +
>  		/*
>  		 * SFC not support output DUMMY cycles right after CMD cycles, so
>  		 * treat it as ADDR cycles.
>  		 */
> -		op->addr.nbytes = op->dummy.nbytes;
> +		op->addr.nbytes = dummy_nbytes;
>  		op->addr.buswidth = op->dummy.buswidth;
>  		op->addr.val = 0xFFFFFFFFF;
>  
> -		op->dummy.nbytes = 0;
> +		op->dummy.ncycles = 0;
>  	}
>  }
>  
> @@ -301,6 +306,10 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc,
>  				   u32 len)
>  {
>  	u32 ctrl = 0, cmd = 0;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	/* set CMD */
>  	cmd = op->cmd.opcode;
> @@ -321,13 +330,13 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc,
>  	}
>  
>  	/* set DUMMY */
> -	if (op->dummy.nbytes) {
> +	if (dummy_nbytes) {
>  		if (op->dummy.buswidth == 4)
> -			cmd |= op->dummy.nbytes * 2 << SFC_CMD_DUMMY_SHIFT;
> +			cmd |= dummy_nbytes * 2 << SFC_CMD_DUMMY_SHIFT;
>  		else if (op->dummy.buswidth == 2)
> -			cmd |= op->dummy.nbytes * 4 << SFC_CMD_DUMMY_SHIFT;
> +			cmd |= dummy_nbytes * 4 << SFC_CMD_DUMMY_SHIFT;
>  		else
> -			cmd |= op->dummy.nbytes * 8 << SFC_CMD_DUMMY_SHIFT;
> +			cmd |= dummy_nbytes * 8 << SFC_CMD_DUMMY_SHIFT;
>  	}
>  
>  	/* set DATA */
> @@ -348,9 +357,9 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc,
>  	ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE;
>  	cmd |= mem->spi->chip_select << SFC_CMD_CS_SHIFT;
>  
> -	dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n",
> +	dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.ncycles=%x(x%d)\n",
>  		op->addr.nbytes, op->addr.buswidth,
> -		op->dummy.nbytes, op->dummy.buswidth);
> +		op->dummy.ncycles, op->dummy.buswidth);
>  	dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n",
>  		ctrl, cmd, op->addr.val, len);
>  
> diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
> index 24ec1c83f379..fb317a80bef8 100644
> --- a/drivers/spi/spi-rpc-if.c
> +++ b/drivers/spi/spi-rpc-if.c
> @@ -32,10 +32,9 @@ static void rpcif_spi_mem_prepare(struct spi_device *spi_dev,
>  		rpc_op.addr.val = spi_op->addr.val;
>  	}
>  
> -	if (spi_op->dummy.nbytes) {
> +	if (spi_op->dummy.ncycles) {
>  		rpc_op.dummy.buswidth = spi_op->dummy.buswidth;
> -		rpc_op.dummy.ncycles  = spi_op->dummy.nbytes * 8 /
> -					spi_op->dummy.buswidth;
> +		rpc_op.dummy.ncycles  = spi_op->dummy.ncycles;
>  	}
>  
>  	if (spi_op->data.nbytes || (offs && len)) {
> diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c
> index f3fe92300639..9072345eddde 100644
> --- a/drivers/spi/spi-stm32-qspi.c
> +++ b/drivers/spi/spi-stm32-qspi.c
> @@ -388,9 +388,8 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op)
>  		ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1);
>  	}
>  
> -	if (op->dummy.nbytes)
> -		ccr |= FIELD_PREP(CCR_DCYC_MASK,
> -				  op->dummy.nbytes * 8 / op->dummy.buswidth);
> +	if (op->dummy.ncycles)
> +		ccr |= FIELD_PREP(CCR_DCYC_MASK, op->dummy.ncycles);
>  
>  	if (op->data.nbytes) {
>  		ccr |= FIELD_PREP(CCR_DMODE_MASK,
> diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
> index 60086869bcae..377bc119344f 100644
> --- a/drivers/spi/spi-ti-qspi.c
> +++ b/drivers/spi/spi-ti-qspi.c
> @@ -579,6 +579,10 @@ static int ti_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
>  {
>  	struct ti_qspi *qspi = spi_controller_get_devdata(mem->spi->master);
>  	size_t max_len;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	if (op->data.dir == SPI_MEM_DATA_IN) {
>  		if (op->addr.val < qspi->mmap_size) {
> @@ -595,7 +599,7 @@ static int ti_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
>  			 * Adjust size to comply with the QSPI max frame length.
>  			 */
>  			max_len = QSPI_FRAME;
> -			max_len -= 1 + op->addr.nbytes + op->dummy.nbytes;
> +			max_len -= 1 + op->addr.nbytes + dummy_nbytes;
>  			op->data.nbytes = min((size_t) op->data.nbytes,
>  					      max_len);
>  		}
> @@ -610,6 +614,10 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem,
>  	struct ti_qspi *qspi = spi_master_get_devdata(mem->spi->master);
>  	u32 from = 0;
>  	int ret = 0;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	/* Only optimize read path. */
>  	if (!op->data.nbytes || op->data.dir != SPI_MEM_DATA_IN ||
> @@ -628,7 +636,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem,
>  		ti_qspi_enable_memory_map(mem->spi);
>  	}
>  	ti_qspi_setup_mmap_read(mem->spi, op->cmd.opcode, op->data.buswidth,
> -				op->addr.nbytes, op->dummy.nbytes);
> +				op->addr.nbytes, dummy_nbytes);
>  
>  	if (qspi->rx_chan) {
>  		struct sg_table sgt;
> diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c
> index 78f31b61a2aa..84b7db85548c 100644
> --- a/drivers/spi/spi-zynq-qspi.c
> +++ b/drivers/spi/spi-zynq-qspi.c
> @@ -527,7 +527,10 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
>  {
>  	struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master);
>  	int err = 0, i;
> -	u8 *tmpbuf;
> +	u8 *tmpbuf, dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
>  		op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
> @@ -568,17 +571,17 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
>  			err = -ETIMEDOUT;
>  	}
>  
> -	if (op->dummy.nbytes) {
> -		tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL);
> +	if (dummy_nbytes) {
> +		tmpbuf = kzalloc(dummy_nbytes, GFP_KERNEL);
>  		if (!tmpbuf)
>  			return -ENOMEM;
>  
> -		memset(tmpbuf, 0xff, op->dummy.nbytes);
> +		memset(tmpbuf, 0xff, dummy_nbytes);
>  		reinit_completion(&xqspi->data_completion);
>  		xqspi->txbuf = tmpbuf;
>  		xqspi->rxbuf = NULL;
> -		xqspi->tx_bytes = op->dummy.nbytes;
> -		xqspi->rx_bytes = op->dummy.nbytes;
> +		xqspi->tx_bytes = dummy_nbytes;
> +		xqspi->rx_bytes = dummy_nbytes;
>  		zynq_qspi_write_op(xqspi, ZYNQ_QSPI_FIFO_DEPTH, true);
>  		zynq_qspi_write(xqspi, ZYNQ_QSPI_IEN_OFFSET,
>  				ZYNQ_QSPI_IXR_RXTX_MASK);
> diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
> index c760aac070e5..b41abadef9a6 100644
> --- a/drivers/spi/spi-zynqmp-gqspi.c
> +++ b/drivers/spi/spi-zynqmp-gqspi.c
> @@ -948,6 +948,10 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
>  	u32 genfifoentry = 0;
>  	u16 opcode = op->cmd.opcode;
>  	u64 opaddr;
> +	u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8;
> +
> +	if (op->dummy.dtr)
> +		dummy_nbytes *= 2;
>  
>  	dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
>  		op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
> @@ -1006,14 +1010,14 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
>  		}
>  	}
>  
> -	if (op->dummy.nbytes) {
> +	if (dummy_nbytes) {
>  		xqspi->txbuf = NULL;
>  		xqspi->rxbuf = NULL;
>  		/*
>  		 * xqspi->bytes_to_transfer here represents the dummy circles
>  		 * which need to be sent.
>  		 */
> -		xqspi->bytes_to_transfer = op->dummy.nbytes * 8 / op->dummy.buswidth;
> +		xqspi->bytes_to_transfer = dummy_nbytes;
>  		xqspi->bytes_to_receive = 0;
>  		/*
>  		 * Using op->data.buswidth instead of op->dummy.buswidth here because
> diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
> index 2ba044d0d5e5..5fd45800af03 100644
> --- a/include/linux/spi/spi-mem.h
> +++ b/include/linux/spi/spi-mem.h
> @@ -29,9 +29,9 @@
>  
>  #define SPI_MEM_OP_NO_ADDR	{ }
>  
> -#define SPI_MEM_OP_DUMMY(__nbytes, __buswidth)			\
> +#define SPI_MEM_OP_DUMMY(__ncycles, __buswidth)		\
>  	{							\
> -		.nbytes = __nbytes,				\
> +		.ncycles = __ncycles,				\
>  		.buswidth = __buswidth,				\
>  	}
>  
> @@ -83,8 +83,8 @@ enum spi_mem_data_dir {
>   *	      Note that only @addr.nbytes are taken into account in this
>   *	      address value, so users should make sure the value fits in the
>   *	      assigned number of bytes.
> - * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can
> - *		  be zero if the operation does not require dummy bytes
> + * @dummy.ncycles: number of dummy cycles after an opcode or address. Can
> + *		   be zero if the operation does not require dummy cycles
>   * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes
>   * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not
>   * @data.buswidth: number of IO lanes used to send/receive the data
> @@ -112,7 +112,7 @@ struct spi_mem_op {
>  	} addr;
>  
>  	struct {
> -		u8 nbytes;
> +		u8 ncycles;
>  		u8 buswidth;
>  		u8 dtr : 1;
>  	} dummy;



More information about the Linux-mediatek mailing list