[PATCH v7 5/7] spi: mxic: Add support for swapping byte
Michael Walle
mwalle at kernel.org
Fri Jan 5 04:37:23 PST 2024
Hi,
> Some SPI-NOR flash swap the bytes on a 16-bit boundary when
> configured in Octal DTR mode. It means data format D0 D1 D2 D3
> would be swapped to D1 D0 D3 D2. So that whether controller
> support swapping bytes should be checked before enable Octal
> DTR mode. Add swap byte support on a 16-bit boundary when
> configured in Octal DTR mode for Macronix xSPI host controller
> dirver.
>
> According dtr_swab in operation to enable/disable Macronix
> xSPI host controller swap byte feature.
>
> To make sure swap byte feature is working well, program data in
> 1S-1S-1S mode then read back and compare read data in 8D-8D-8D
> mode.
>
> This feature have been validated on byte-swap flash and
> non-byte-swap flash.
>
> Macronix xSPI host controller bit "HC_CFG_DATA_PASS" determine
> the byte swap feature disabled/enabled and swap byte feature is
> working on 8D-8D-8D mode only.
>
> Signed-off-by: JaimeLiao <jaimeliao at mxic.com.tw>
> ---
> drivers/spi/spi-mxic.c | 19 +++++++++++++++----
> 1 file changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
> index 60c9f3048ac9..8dc83adaaa88 100644
> --- a/drivers/spi/spi-mxic.c
> +++ b/drivers/spi/spi-mxic.c
> @@ -294,7 +294,8 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
> mxic->regs + HC_CFG);
> }
>
> -static u32 mxic_spi_prep_hc_cfg(struct spi_device *spi, u32 flags)
> +static u32 mxic_spi_prep_hc_cfg(const struct spi_mem_op *op,
> + struct spi_device *spi, u32 flags)
Not my driver, but because it caught my eye: I wouldn't pass
spi_mem_op. Maybe just "bool swap16"?
> {
> int nio = 1;
>
> @@ -305,6 +306,13 @@ static u32 mxic_spi_prep_hc_cfg(struct spi_device
> *spi, u32 flags)
> else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
> nio = 2;
>
> + if (op->data.dtr) {
Checking this seems to be redundant with checking dtr_swab16.
> + if (op->data.dtr_swab16)
> + flags &= ~HC_CFG_DATA_PASS;
> + else
> + flags |= HC_CFG_DATA_PASS;
Mhh, this is strange. Given that dtr_swap16 is a new flag means
that you are now setting the HC_CFG_DATA_PASS bit by default.
Something to keep in mind if you have any users which already use
8d8d8d mode nowadays.
Also clearing the flag seems superfluous.
-michael
> + }
> +
> return flags | HC_CFG_NIO(nio) |
> HC_CFG_TYPE(spi_get_chipselect(spi, 0), HC_CFG_TYPE_SPI_NOR) |
> HC_CFG_SLV_ACT(spi_get_chipselect(spi, 0)) |
> HC_CFG_IDLE_SIO_LVL(1);
> @@ -397,7 +405,8 @@ static ssize_t mxic_spi_mem_dirmap_read(struct
> spi_mem_dirmap_desc *desc,
> if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
> return -EINVAL;
>
> - writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0), mxic->regs + HC_CFG);
> + writel(mxic_spi_prep_hc_cfg(&desc->info.op_tmpl,
> + desc->mem->spi, 0), mxic->regs + HC_CFG);
>
> writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
> mxic->regs + LRD_CFG);
> @@ -441,7 +450,8 @@ static ssize_t mxic_spi_mem_dirmap_write(struct
> spi_mem_dirmap_desc *desc,
> if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
> return -EINVAL;
>
> - writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0), mxic->regs + HC_CFG);
> + writel(mxic_spi_prep_hc_cfg(&desc->info.op_tmpl,
> + desc->mem->spi, 0), mxic->regs + HC_CFG);
>
> writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
> mxic->regs + LWR_CFG);
> @@ -518,7 +528,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem
> *mem,
> if (ret)
> return ret;
>
> - writel(mxic_spi_prep_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN),
> + writel(mxic_spi_prep_hc_cfg(op, mem->spi, HC_CFG_MAN_CS_EN),
> mxic->regs + HC_CFG);
>
> writel(HC_EN_BIT, mxic->regs + HC_EN);
> @@ -572,6 +582,7 @@ static const struct spi_controller_mem_ops
> mxic_spi_mem_ops = {
>
> static const struct spi_controller_mem_caps mxic_spi_mem_caps = {
> .dtr = true,
> + .dtr_swab16 = true,
> .ecc = true,
> };
More information about the linux-mtd
mailing list