[PATCH 1/3] mtd: spi nor: add support for dual and quad bit transfers
Jean Pihet
jean.pihet at newoldbits.com
Tue Dec 1 20:03:05 CET 2020
Hi Pratyush,
On Mon, Nov 30, 2020 at 1:37 PM Pratyush Yadav <p.yadav at ti.com> wrote:
>
> Hi Jean,
>
> On 29/11/20 11:39AM, Jean Pihet wrote:
> > Use the flags field of the SPI slave struct to pass the dual and quad
> > read properties, from the SPI NOR layer to the low level driver.
> > Tested with TI QSPI in 1, 2 and 4 bits modes.
> >
> > Signed-off-by: Jean Pihet <jean.pihet at newoldbits.com>
> > ---
> > drivers/mtd/spi/spi-nor-core.c | 34 +++++++++++++++++++++++++++++++---
> > drivers/spi/spi-mem.c | 8 +++++++-
> > include/spi.h | 2 ++
> > 3 files changed, 40 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> > index e16b0e1462..54569b3cba 100644
> > --- a/drivers/mtd/spi/spi-nor-core.c
> > +++ b/drivers/mtd/spi/spi-nor-core.c
> > @@ -94,22 +94,50 @@ static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
> > /* convert the dummy cycles to the number of bytes */
> > op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
> >
> > + /* Check for dual and quad I/O read */
> > + switch (op.cmd.opcode) {
> > + case SPINOR_OP_READ_1_1_2:
> > + case SPINOR_OP_READ_1_2_2:
> > + case SPINOR_OP_READ_1_1_2_4B:
> > + case SPINOR_OP_READ_1_2_2_4B:
> > + case SPINOR_OP_READ_1_2_2_DTR:
> > + case SPINOR_OP_READ_1_2_2_DTR_4B:
> > + nor->spi->flags |= SPI_XFER_DUAL_READ;
> > + break;
> > + case SPINOR_OP_READ_1_1_4:
> > + case SPINOR_OP_READ_1_4_4:
> > + case SPINOR_OP_READ_1_1_4_4B:
> > + case SPINOR_OP_READ_1_4_4_4B:
> > + case SPINOR_OP_READ_1_4_4_DTR:
> > + case SPINOR_OP_READ_1_4_4_DTR_4B:
> > + nor->spi->flags |= SPI_XFER_QUAD_READ;
> > + break;
> > + default:
> > + break;
> > + }
> > +
>
> NACK. What if a flash uses some other opcode for dual or quad reads?
>
> Why not use op->data.buswidth in ti_qspi_exec_mem_op() to enable dual or
> quad mode? In fact, ti_qspi_setup_mmap_read() already checks this and
> enables dual or quad mode. What problem does this patch solve then?
Ok I will rework this that way.
The goal is to enable bigger flashes (>64MB) and to optimize the
transfer speed. I will add a cover letter to the patch series to
better describe the goals.
>
> > while (remaining) {
> > op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
> > ret = spi_mem_adjust_op_size(nor->spi, &op);
> > if (ret)
> > - return ret;
> > + goto out;
> >
> > ret = spi_mem_exec_op(nor->spi, &op);
> > if (ret)
> > - return ret;
> > + goto out;
> >
> > op.addr.val += op.data.nbytes;
> > remaining -= op.data.nbytes;
> > op.data.buf.in += op.data.nbytes;
> > }
> >
> > - return len;
> > + ret = len;
> > +
> > +out:
> > + /* Reset dual and quad I/O read flags for upcoming transactions */
> > + nor->spi->flags &= ~(SPI_XFER_DUAL_READ | SPI_XFER_QUAD_READ);
> > +
> > + return ret;
> > }
> >
> > static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
> > diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
> > index c095ae9505..24e38ea95e 100644
> > --- a/drivers/spi/spi-mem.c
> > +++ b/drivers/spi/spi-mem.c
> > @@ -387,9 +387,15 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
> > return ret;
> >
> > /* 2nd transfer: rx or tx data path */
> > + flag = SPI_XFER_END;
> > + /* Check for dual and quad I/O reads */
> > + if (slave->flags & SPI_XFER_DUAL_READ)
> > + flag |= SPI_XFER_DUAL_READ;
> > + if (slave->flags & SPI_XFER_QUAD_READ)
> > + flag |= SPI_XFER_QUAD_READ;
>
> Ah, so you are targeting the "legacy" path. Seeing that ti_qspi does
> support the SPI MEM path, this would be executed when the read exceeds
> priv->mmap_size, correct?
Yes exactly. The TI QSPI controller can only mmap 64MB.
>
> In any case, I don't see why you need slave->flags. Why can't you set
> these flags by checking op->data.buswidth and op->data.dir? This would
> make your fix transparent to SPI NOR, which IMO is a much better idea.
Ok let me rework this.
>
> > if (tx_buf || rx_buf) {
> > ret = spi_xfer(slave, op->data.nbytes * 8, tx_buf,
> > - rx_buf, SPI_XFER_END);
> > + rx_buf, flag);
> > if (ret)
> > return ret;
> > }
> > diff --git a/include/spi.h b/include/spi.h
> > index ef8c1f6692..cf5f05e526 100644
> > --- a/include/spi.h
> > +++ b/include/spi.h
> > @@ -146,6 +146,8 @@ struct spi_slave {
> > #define SPI_XFER_BEGIN BIT(0) /* Assert CS before transfer */
> > #define SPI_XFER_END BIT(1) /* Deassert CS after transfer */
> > #define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END)
> > +#define SPI_XFER_DUAL_READ BIT(2) /* Dual I/O read */
> > +#define SPI_XFER_QUAD_READ BIT(3) /* Quad I/O read */
> > };
> >
> > /**
> > --
> > 2.26.2
> >
>
> --
> Regards,
> Pratyush Yadav
> Texas Instruments India
Thanks for reviewing!
BR,
Jean
More information about the U-Boot
mailing list