diff mbox series

[V1,24/26] spi: tegra114: de-assert CS before SPI mode is reset to its default

Message ID 1553666207-11414-24-git-send-email-skomatineni@nvidia.com
State Changes Requested
Headers show
Series [V1,01/26] spi: tegra114: fix PIO transfer | expand

Commit Message

Sowjanya Komatineni March 27, 2019, 5:56 a.m. UTC
With SW CS, during transfer completion CS is de-asserted by writing the
default command1 register value to SPI_COMMAND1 register. With this both
mode and CS state are set at the same time and if current transfer mode
is different to default SPI mode and if mode change happens prior to CS
de-assert, clock polarity can change while CS is active before transfer
finishes.

This causes Slave to see spurious clock edges resulting in data mismatch.

This patch fixes this by de-asserting CS before writing SPI_COMMAND1 to
its default value so through out the transfer it will be in same SPI mode.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/spi/spi-tegra114.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

Comments

Mark Brown April 1, 2019, 7:49 a.m. UTC | #1
On Tue, Mar 26, 2019 at 10:56:45PM -0700, Sowjanya Komatineni wrote:
> With SW CS, during transfer completion CS is de-asserted by writing the
> default command1 register value to SPI_COMMAND1 register. With this both
> mode and CS state are set at the same time and if current transfer mode
> is different to default SPI mode and if mode change happens prior to CS
> de-assert, clock polarity can change while CS is active before transfer
> finishes.

This is a bug fix so I'd expect it to be much earlier in the series
before any of the new features.
Sowjanya Komatineni April 1, 2019, 6:07 p.m. UTC | #2
> On Tue, Mar 26, 2019 at 10:56:45PM -0700, Sowjanya Komatineni wrote:
> > With SW CS, during transfer completion CS is de-asserted by writing 
> > the default command1 register value to SPI_COMMAND1 register. With 
> > this both mode and CS state are set at the same time and if current 
> > transfer mode is different to default SPI mode and if mode change 
> > happens prior to CS de-assert, clock polarity can change while CS is 
> > active before transfer finishes.
>
> This is a bug fix so I'd expect it to be much earlier in the series before any of the new features.

Thanks Mark. Will change order as per your feedback in next version of patch series.

I see you have applied some patches in V1 series so should I re-send again those as well along with feedback changes in next version or just only the patches that are not applied.
Mark Brown April 2, 2019, 4:52 a.m. UTC | #3
On Mon, Apr 01, 2019 at 06:07:45PM +0000, Sowjanya Komatineni wrote:

> I see you have applied some patches in V1 series so should I re-send
> again those as well along with feedback changes in next version or
> just only the patches that are not applied.

Please don't resend already applied patches.
diff mbox series

Patch

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 9b216e9d6079..e1669ab3b0fe 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1147,6 +1147,12 @@  static int tegra_spi_transfer_one_message(struct spi_master *master,
 		if (ret < 0 || skip) {
 			if (cstate->cs_gpio_valid)
 				gpio_set_value(spi->cs_gpio, cs_val);
+			if (cs_val && !tspi->use_hw_based_cs)
+				tspi->command1_reg |= SPI_CS_SW_VAL;
+			else
+				tspi->command1_reg &= ~SPI_CS_SW_VAL;
+			tegra_spi_writel(tspi, tspi->command1_reg,
+					 SPI_COMMAND1);
 			tegra_spi_writel(tspi, tspi->def_command1_reg,
 					SPI_COMMAND1);
 			tegra_spi_transfer_delay(xfer->delay_usecs);
@@ -1158,6 +1164,12 @@  static int tegra_spi_transfer_one_message(struct spi_master *master,
 			else {
 				if (cstate->cs_gpio_valid)
 					gpio_set_value(spi->cs_gpio, cs_val);
+				if (cs_val && !tspi->use_hw_based_cs)
+					tspi->command1_reg |= SPI_CS_SW_VAL;
+				else
+					tspi->command1_reg &= ~SPI_CS_SW_VAL;
+				tegra_spi_writel(tspi, tspi->command1_reg,
+						 SPI_COMMAND1);
 				tegra_spi_writel(tspi, tspi->def_command1_reg,
 						SPI_COMMAND1);
 				tegra_spi_transfer_delay(xfer->delay_usecs);
@@ -1165,6 +1177,12 @@  static int tegra_spi_transfer_one_message(struct spi_master *master,
 		} else if (xfer->cs_change) {
 			if (cstate->cs_gpio_valid)
 				gpio_set_value(spi->cs_gpio, cs_val);
+			if (cs_val && !tspi->use_hw_based_cs)
+				tspi->command1_reg |= SPI_CS_SW_VAL;
+			else
+				tspi->command1_reg &= ~SPI_CS_SW_VAL;
+			tegra_spi_writel(tspi, tspi->command1_reg,
+					 SPI_COMMAND1);
 			tegra_spi_writel(tspi, tspi->def_command1_reg,
 					SPI_COMMAND1);
 			tegra_spi_transfer_delay(xfer->delay_usecs);