diff mbox series

[08/11] spi: dw: update buffer for enhanced spi mode

Message ID 20220802175755.6530-9-sudip.mukherjee@sifive.com (mailing list archive)
State New, archived
Headers show
Series Add support for enhanced SPI for Designware SPI controllers | expand

Commit Message

Sudip Mukherjee Aug. 2, 2022, 5:57 p.m. UTC
In enhanced spi mode we will be writing the address to a single FIFO
location instead of writing to multiple FIFOs in the standard SPI mode.
Save the cmd and address bytes in the buffer accordingly.

Signed-off-by: Sudip Mukherjee <sudip.mukherjee@sifive.com>
---
 drivers/spi/spi-dw-core.c | 55 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 7 deletions(-)

Comments

Serge Semin Aug. 26, 2022, 11:05 p.m. UTC | #1
On Tue, Aug 02, 2022 at 06:57:52PM +0100, Sudip Mukherjee wrote:
> In enhanced spi mode we will be writing the address to a single FIFO
> location instead of writing to multiple FIFOs in the standard SPI mode.
> Save the cmd and address bytes in the buffer accordingly.
> 
> Signed-off-by: Sudip Mukherjee <sudip.mukherjee@sifive.com>
> ---
>  drivers/spi/spi-dw-core.c | 55 ++++++++++++++++++++++++++++++++++-----
>  1 file changed, 48 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index 8cb30540ad5b..2564a2276572 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -520,7 +520,8 @@ static bool dw_spi_supports_mem_op(struct spi_mem *mem,
>  	return spi_mem_default_supports_op(mem, op);
>  }
> 
 
> -static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
> +static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op,
> +			       bool enhanced_spi)

There is no point in modifying this method. Since clock stretching is
available you won't need to collect all the data in a single buffer.
So just create a new method dw_spi_init_enh_mem_buf() which would set
dws->tx/rx pointers and tx_len/rx_len fields with the
spi_mem_op.data.buf.{in,out} and the corresponding lengths. The command
and address data shall be written to the Tx FIFO to initiate the SPI MEM
transfers, since in accordance with the HW manual the SPI-bus transfers
won't start before it is done.

-Sergey

>  {
>  	unsigned int i, j, len;
>  	u8 *out;
> @@ -548,17 +549,57 @@ static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
>  	 */
>  	for (i = 0; i < op->cmd.nbytes; ++i)
>  		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)
> -		out[i] = 0x0;
> +
> +	if (enhanced_spi) {
> +		/*
> +		 * Fill the remaining spaces of dws->reg_io_width bytes
> +		 * size register with zero for cmd.
> +		 */
> +		for (; i < dws->reg_io_width; ++i)
> +			out[i] = 0;
> +		/*
> +		 * Copy the address bytes in dws->reg_io_width bytes size
> +		 * register and fill remaining spaces with zero.
> +		 */
> +		for (j = op->addr.nbytes; j > 0; ++i, --j)
> +			out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j);
> +		for (j = op->addr.nbytes; j < dws->reg_io_width; ++i, ++j)
> +			out[i] = 0;
> +	} else {
> +		for (j = 0; j < op->addr.nbytes; ++i, ++j)
> +			out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1);
> +	}
> +
> +	if (!enhanced_spi) {
> +		/*
> +		 * dummy bytes are not needed in enhanced mode as
> +		 * wait_cycles specified as number of SPI clock cycles
> +		 * between control frames transmit and data reception
> +		 * will be mentioned in enhanced spi mode.
> +		 */
> +		for (j = 0; j < op->dummy.nbytes; ++i, ++j)
> +			out[i] = 0x0;
> +	}
>  
>  	if (op->data.dir == SPI_MEM_DATA_OUT)
>  		memcpy(&out[i], op->data.buf.out, op->data.nbytes);
>  
>  	dws->n_bytes = 1;
>  	dws->tx = out;
> -	dws->tx_len = len;
> +
> +	if (enhanced_spi) {
> +		/*
> +		 * In enhanced mode cmd will be one FIFO and address
> +		 * will be one more FIFO.
> +		 */
> +		dws->tx_len = 1;
> +		if (op->addr.nbytes)
> +			dws->tx_len += 1;
> +		if (op->data.dir == SPI_MEM_DATA_OUT)
> +			dws->tx_len += op->data.nbytes;
> +	} else {
> +		dws->tx_len = len;
> +	}
>  	if (op->data.dir == SPI_MEM_DATA_IN) {
>  		dws->rx = op->data.buf.in;
>  		dws->rx_len = op->data.nbytes;
> @@ -744,7 +785,7 @@ static int dw_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  	 * Collect the outbound data into a single buffer to speed the
>  	 * transmission up at least on the initial stage.
>  	 */
> -	ret = dw_spi_init_mem_buf(dws, op);
> +	ret = dw_spi_init_mem_buf(dws, op, enhanced_spi);
>  	if (ret)
>  		return ret;
>  
> -- 
> 2.30.2
>
diff mbox series

Patch

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 8cb30540ad5b..2564a2276572 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -520,7 +520,8 @@  static bool dw_spi_supports_mem_op(struct spi_mem *mem,
 	return spi_mem_default_supports_op(mem, op);
 }
 
-static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
+static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op,
+			       bool enhanced_spi)
 {
 	unsigned int i, j, len;
 	u8 *out;
@@ -548,17 +549,57 @@  static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
 	 */
 	for (i = 0; i < op->cmd.nbytes; ++i)
 		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)
-		out[i] = 0x0;
+
+	if (enhanced_spi) {
+		/*
+		 * Fill the remaining spaces of dws->reg_io_width bytes
+		 * size register with zero for cmd.
+		 */
+		for (; i < dws->reg_io_width; ++i)
+			out[i] = 0;
+		/*
+		 * Copy the address bytes in dws->reg_io_width bytes size
+		 * register and fill remaining spaces with zero.
+		 */
+		for (j = op->addr.nbytes; j > 0; ++i, --j)
+			out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j);
+		for (j = op->addr.nbytes; j < dws->reg_io_width; ++i, ++j)
+			out[i] = 0;
+	} else {
+		for (j = 0; j < op->addr.nbytes; ++i, ++j)
+			out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1);
+	}
+
+	if (!enhanced_spi) {
+		/*
+		 * dummy bytes are not needed in enhanced mode as
+		 * wait_cycles specified as number of SPI clock cycles
+		 * between control frames transmit and data reception
+		 * will be mentioned in enhanced spi mode.
+		 */
+		for (j = 0; j < op->dummy.nbytes; ++i, ++j)
+			out[i] = 0x0;
+	}
 
 	if (op->data.dir == SPI_MEM_DATA_OUT)
 		memcpy(&out[i], op->data.buf.out, op->data.nbytes);
 
 	dws->n_bytes = 1;
 	dws->tx = out;
-	dws->tx_len = len;
+
+	if (enhanced_spi) {
+		/*
+		 * In enhanced mode cmd will be one FIFO and address
+		 * will be one more FIFO.
+		 */
+		dws->tx_len = 1;
+		if (op->addr.nbytes)
+			dws->tx_len += 1;
+		if (op->data.dir == SPI_MEM_DATA_OUT)
+			dws->tx_len += op->data.nbytes;
+	} else {
+		dws->tx_len = len;
+	}
 	if (op->data.dir == SPI_MEM_DATA_IN) {
 		dws->rx = op->data.buf.in;
 		dws->rx_len = op->data.nbytes;
@@ -744,7 +785,7 @@  static int dw_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
 	 * Collect the outbound data into a single buffer to speed the
 	 * transmission up at least on the initial stage.
 	 */
-	ret = dw_spi_init_mem_buf(dws, op);
+	ret = dw_spi_init_mem_buf(dws, op, enhanced_spi);
 	if (ret)
 		return ret;