All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] spi: cadence_qspi_apb: Use 32 bit indirect write transaction when possible
@ 2016-11-10  5:18 Vignesh R
  2016-11-12 21:43 ` Marek Vasut
  0 siblings, 1 reply; 4+ messages in thread
From: Vignesh R @ 2016-11-10  5:18 UTC (permalink / raw)
  To: u-boot

According to Section 11.15.4.9.2 Indirect Write Controller of K2G SoC
TRM SPRUHY8D[1], the external master is only permitted to issue 32-bit
data interface writes until the last word of an indirect transfer
otherwise indirect writes is known to fails sometimes. So, make sure
that QSPI indirect writes are 32 bit sized except for the last write.

[1]www.ti.com/lit/ug/spruhy8d/spruhy8d.pdf

Signed-off-by: Vignesh R <vigneshr@ti.com>
---
 drivers/spi/cadence_qspi_apb.c | 41 +++++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index e285d3c1e761..0115700ef6a7 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -739,23 +739,44 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 {
 	unsigned int page_size = plat->page_size;
 	unsigned int remaining = n_tx;
-	unsigned int write_bytes;
+	unsigned int write_bytes = 0;
 	int ret;
 
+	/* Handle non-4-byte aligned access to avoid data abort. */
+	if ((uintptr_t) txbuf % 4) {
+		write_bytes = n_tx > 3 ? 4 - ((uintptr_t)txbuf % 4) : n_tx;
+		/* Configure the indirect read transfer bytes */
+		writel(write_bytes, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
+		/* Start the indirect write transfer */
+		writel(CQSPI_REG_INDIRECTWR_START_MASK,
+		       plat->regbase + CQSPI_REG_INDIRECTWR);
+		writesb(plat->ahbbase, txbuf, write_bytes);
+		txbuf += write_bytes;
+		remaining -= write_bytes;
+		if (remaining > 0) {
+			u32 start_addr = readl(plat->regbase +
+					       CQSPI_REG_INDIRECTWRSTARTADDR);
+			start_addr += write_bytes;
+			writel(start_addr, plat->regbase +
+			       CQSPI_REG_INDIRECTWRSTARTADDR);
+		}
+	}
+
 	/* Configure the indirect read transfer bytes */
-	writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
+	writel(n_tx - write_bytes, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
 
-	/* Start the indirect write transfer */
-	writel(CQSPI_REG_INDIRECTWR_START_MASK,
-	       plat->regbase + CQSPI_REG_INDIRECTWR);
+	if (remaining > 0)
+		writel(CQSPI_REG_INDIRECTWR_START_MASK,
+		       plat->regbase + CQSPI_REG_INDIRECTWR);
 
 	while (remaining > 0) {
 		write_bytes = remaining > page_size ? page_size : remaining;
-		/* Handle non-4-byte aligned access to avoid data abort. */
-		if (((uintptr_t)txbuf % 4) || (write_bytes % 4))
-			writesb(plat->ahbbase, txbuf, write_bytes);
-		else
-			writesl(plat->ahbbase, txbuf, write_bytes >> 2);
+
+		writesl(plat->ahbbase, txbuf, write_bytes >> 2);
+		if (write_bytes % 4)
+			writesb(plat->ahbbase,
+				txbuf + rounddown(write_bytes, 4),
+				write_bytes % 4);
 
 		ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL,
 				   CQSPI_REG_SDRAMLEVEL_WR_MASK <<
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] spi: cadence_qspi_apb: Use 32 bit indirect write transaction when possible
  2016-11-10  5:18 [U-Boot] [PATCH] spi: cadence_qspi_apb: Use 32 bit indirect write transaction when possible Vignesh R
@ 2016-11-12 21:43 ` Marek Vasut
  2016-11-15  5:03   ` Vignesh R
  0 siblings, 1 reply; 4+ messages in thread
From: Marek Vasut @ 2016-11-12 21:43 UTC (permalink / raw)
  To: u-boot

On 11/10/2016 06:18 AM, Vignesh R wrote:
> According to Section 11.15.4.9.2 Indirect Write Controller of K2G SoC
> TRM SPRUHY8D[1], the external master is only permitted to issue 32-bit
> data interface writes until the last word of an indirect transfer
> otherwise indirect writes is known to fails sometimes. So, make sure
> that QSPI indirect writes are 32 bit sized except for the last write.
> 
> [1]www.ti.com/lit/ug/spruhy8d/spruhy8d.pdf
> 
> Signed-off-by: Vignesh R <vigneshr@ti.com>

I would if it wouldn't be better to use bounce buffer for the txbuf .
See common/bouncebuf.c

> ---
>  drivers/spi/cadence_qspi_apb.c | 41 +++++++++++++++++++++++++++++++----------
>  1 file changed, 31 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
> index e285d3c1e761..0115700ef6a7 100644
> --- a/drivers/spi/cadence_qspi_apb.c
> +++ b/drivers/spi/cadence_qspi_apb.c
> @@ -739,23 +739,44 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
>  {
>  	unsigned int page_size = plat->page_size;
>  	unsigned int remaining = n_tx;
> -	unsigned int write_bytes;
> +	unsigned int write_bytes = 0;
>  	int ret;
>  
> +	/* Handle non-4-byte aligned access to avoid data abort. */
> +	if ((uintptr_t) txbuf % 4) {
> +		write_bytes = n_tx > 3 ? 4 - ((uintptr_t)txbuf % 4) : n_tx;
> +		/* Configure the indirect read transfer bytes */
> +		writel(write_bytes, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
> +		/* Start the indirect write transfer */
> +		writel(CQSPI_REG_INDIRECTWR_START_MASK,
> +		       plat->regbase + CQSPI_REG_INDIRECTWR);
> +		writesb(plat->ahbbase, txbuf, write_bytes);
> +		txbuf += write_bytes;
> +		remaining -= write_bytes;
> +		if (remaining > 0) {
> +			u32 start_addr = readl(plat->regbase +
> +					       CQSPI_REG_INDIRECTWRSTARTADDR);
> +			start_addr += write_bytes;
> +			writel(start_addr, plat->regbase +
> +			       CQSPI_REG_INDIRECTWRSTARTADDR);
> +		}
> +	}
> +
>  	/* Configure the indirect read transfer bytes */
> -	writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
> +	writel(n_tx - write_bytes, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
>  
> -	/* Start the indirect write transfer */
> -	writel(CQSPI_REG_INDIRECTWR_START_MASK,
> -	       plat->regbase + CQSPI_REG_INDIRECTWR);
> +	if (remaining > 0)
> +		writel(CQSPI_REG_INDIRECTWR_START_MASK,
> +		       plat->regbase + CQSPI_REG_INDIRECTWR);
>  
>  	while (remaining > 0) {
>  		write_bytes = remaining > page_size ? page_size : remaining;
> -		/* Handle non-4-byte aligned access to avoid data abort. */
> -		if (((uintptr_t)txbuf % 4) || (write_bytes % 4))
> -			writesb(plat->ahbbase, txbuf, write_bytes);
> -		else
> -			writesl(plat->ahbbase, txbuf, write_bytes >> 2);
> +
> +		writesl(plat->ahbbase, txbuf, write_bytes >> 2);
> +		if (write_bytes % 4)
> +			writesb(plat->ahbbase,
> +				txbuf + rounddown(write_bytes, 4),
> +				write_bytes % 4);
>  
>  		ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL,
>  				   CQSPI_REG_SDRAMLEVEL_WR_MASK <<
> 


-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] spi: cadence_qspi_apb: Use 32 bit indirect write transaction when possible
  2016-11-12 21:43 ` Marek Vasut
@ 2016-11-15  5:03   ` Vignesh R
  2016-11-15  9:42     ` Marek Vasut
  0 siblings, 1 reply; 4+ messages in thread
From: Vignesh R @ 2016-11-15  5:03 UTC (permalink / raw)
  To: u-boot



On Sunday 13 November 2016 03:13 AM, Marek Vasut wrote:
> On 11/10/2016 06:18 AM, Vignesh R wrote:
>> According to Section 11.15.4.9.2 Indirect Write Controller of K2G SoC
>> TRM SPRUHY8D[1], the external master is only permitted to issue 32-bit
>> data interface writes until the last word of an indirect transfer
>> otherwise indirect writes is known to fails sometimes. So, make sure
>> that QSPI indirect writes are 32 bit sized except for the last write.
>>
>> [1]www.ti.com/lit/ug/spruhy8d/spruhy8d.pdf
>>
>> Signed-off-by: Vignesh R <vigneshr@ti.com>
> 
> I would if it wouldn't be better to use bounce buffer for the txbuf .
> See common/bouncebuf.c
> 

Yeah, I guess that will also help in implementing DMA support. How about
having a generic implementation of bounce buffer support in
spi_flash_cmd_{read/write}_ops?


-- 
Regards
Vignesh

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] spi: cadence_qspi_apb: Use 32 bit indirect write transaction when possible
  2016-11-15  5:03   ` Vignesh R
@ 2016-11-15  9:42     ` Marek Vasut
  0 siblings, 0 replies; 4+ messages in thread
From: Marek Vasut @ 2016-11-15  9:42 UTC (permalink / raw)
  To: u-boot

On 11/15/2016 06:03 AM, Vignesh R wrote:
> 
> 
> On Sunday 13 November 2016 03:13 AM, Marek Vasut wrote:
>> On 11/10/2016 06:18 AM, Vignesh R wrote:
>>> According to Section 11.15.4.9.2 Indirect Write Controller of K2G SoC
>>> TRM SPRUHY8D[1], the external master is only permitted to issue 32-bit
>>> data interface writes until the last word of an indirect transfer
>>> otherwise indirect writes is known to fails sometimes. So, make sure
>>> that QSPI indirect writes are 32 bit sized except for the last write.
>>>
>>> [1]www.ti.com/lit/ug/spruhy8d/spruhy8d.pdf
>>>
>>> Signed-off-by: Vignesh R <vigneshr@ti.com>
>>
>> I would if it wouldn't be better to use bounce buffer for the txbuf .
>> See common/bouncebuf.c
>>
> 
> Yeah, I guess that will also help in implementing DMA support. How about
> having a generic implementation of bounce buffer support in
> spi_flash_cmd_{read/write}_ops?

We have generic implementation of bounce buffer in common/bouncebuf.c
and not everyone needs it.

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-11-15  9:42 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-10  5:18 [U-Boot] [PATCH] spi: cadence_qspi_apb: Use 32 bit indirect write transaction when possible Vignesh R
2016-11-12 21:43 ` Marek Vasut
2016-11-15  5:03   ` Vignesh R
2016-11-15  9:42     ` Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.