[3/3] spi: meson-spicc: Lower CS between bursts

Message ID 20221116-s905x_spi_ili9486-v1-3-630401cb62d5@baylibre.com
State New
Headers
Series Fix SPICC and ILI9486 drivers |

Commit Message

Carlo Caione Nov. 17, 2022, 8:47 a.m. UTC
  On some hardware (reproduced on S905X) when a large payload is
transmitted over SPI in bursts at the end of each burst, the clock line
briefly fluctuates creating spurious clock transitions that are being
recognised by the connected device as a genuine pulses, creating an
offset in the data being transmitted.

Lower the GPIO CS between bursts to avoid the clock being interpreted as
valid.

Signed-off-by: Carlo Caione <ccaione@baylibre.com>
---
 drivers/spi/spi-meson-spicc.c | 6 ++++++
 1 file changed, 6 insertions(+)
  

Comments

Neil Armstrong Nov. 17, 2022, 8:54 a.m. UTC | #1
Hi,

On 17/11/2022 09:47, Carlo Caione wrote:
> On some hardware (reproduced on S905X) when a large payload is
> transmitted over SPI in bursts at the end of each burst, the clock line
> briefly fluctuates creating spurious clock transitions that are being
> recognised by the connected device as a genuine pulses, creating an
> offset in the data being transmitted.
> 
> Lower the GPIO CS between bursts to avoid the clock being interpreted as
> valid.

I'm afraid this will actually break SPI NORs for example where CS actually splits
transactions.

Isn't Amjad change enough ? The CLK pull-up should avoid this.

If it's not the case, then it's an HW issue and the CLK line pull-up is too weak and an
external pull should then be added.

> 
> Signed-off-by: Carlo Caione <ccaione@baylibre.com>
> ---
>   drivers/spi/spi-meson-spicc.c | 6 ++++++
>   1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
> index d47f2623a60f..af8d74b53519 100644
> --- a/drivers/spi/spi-meson-spicc.c
> +++ b/drivers/spi/spi-meson-spicc.c
> @@ -291,6 +291,10 @@ static inline void meson_spicc_setup_burst(struct meson_spicc_device *spicc)
>   static irqreturn_t meson_spicc_irq(int irq, void *data)
>   {
>   	struct meson_spicc_device *spicc = (void *) data;
> +	struct spi_device *spi_dev;
> +
> +	spi_dev = spicc->message->spi;
> +	gpiod_set_value(spi_dev->cs_gpiod, 0);
>   
>   	writel_bits_relaxed(SPICC_TC, SPICC_TC, spicc->base + SPICC_STATREG);
>   
> @@ -309,6 +313,8 @@ static irqreturn_t meson_spicc_irq(int irq, void *data)
>   	/* Setup burst */
>   	meson_spicc_setup_burst(spicc);
>   
> +	gpiod_set_value(spi_dev->cs_gpiod, 1);
> +
>   	/* Start burst */
>   	writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG);
>   
>
  
Mark Brown Nov. 17, 2022, 10:59 a.m. UTC | #2
On Thu, Nov 17, 2022 at 09:47:41AM +0100, Carlo Caione wrote:
> On some hardware (reproduced on S905X) when a large payload is
> transmitted over SPI in bursts at the end of each burst, the clock line
> briefly fluctuates creating spurious clock transitions that are being
> recognised by the connected device as a genuine pulses, creating an
> offset in the data being transmitted.

> Lower the GPIO CS between bursts to avoid the clock being interpreted as
> valid.

This is just plain broken, *many* SPI devices attach meaning to
chip select edges - for example register writes will typically
have the register address followed by one or more register values
for sequential registers.  Bouncing chip select in the middle of
transfer will corrupt data.  If the device can't handle larger
transfers it needs to advertise this limit and refuse to handle
them.
  
Carlo Caione Nov. 17, 2022, 2:05 p.m. UTC | #3
On 17/11/2022 09:54, Neil Armstrong wrote:

> I'm afraid this will actually break SPI NORs for example where CS 
> actually splits transactions.
> 
> Isn't Amjad change enough ? The CLK pull-up should avoid this.

It looks like it is not enough unfortunately.

> If it's not the case, then it's an HW issue and the CLK line pull-up 
> is too weak and an external pull should then be added.
	
Alright, I'll drop this patch in the next respin if needed.

Thanks,

--
Carlo Caione
  

Patch

diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
index d47f2623a60f..af8d74b53519 100644
--- a/drivers/spi/spi-meson-spicc.c
+++ b/drivers/spi/spi-meson-spicc.c
@@ -291,6 +291,10 @@  static inline void meson_spicc_setup_burst(struct meson_spicc_device *spicc)
 static irqreturn_t meson_spicc_irq(int irq, void *data)
 {
 	struct meson_spicc_device *spicc = (void *) data;
+	struct spi_device *spi_dev;
+
+	spi_dev = spicc->message->spi;
+	gpiod_set_value(spi_dev->cs_gpiod, 0);
 
 	writel_bits_relaxed(SPICC_TC, SPICC_TC, spicc->base + SPICC_STATREG);
 
@@ -309,6 +313,8 @@  static irqreturn_t meson_spicc_irq(int irq, void *data)
 	/* Setup burst */
 	meson_spicc_setup_burst(spicc);
 
+	gpiod_set_value(spi_dev->cs_gpiod, 1);
+
 	/* Start burst */
 	writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG);