[U-Boot] [PATCH] spi: tegra20: fix mode selection logic

Stephen Warren swarren at wwwdotorg.org
Fri Aug 12 23:06:10 CEST 2016


From: Stephen Warren <swarren at nvidia.com>

When the set_mode() function runs, the SPI bus is not active, and hence
the clocks to the SPI controller are not running. Any register read/write
at this time will hang the CPU. Remove the code from set_mode() that does
this, and move it to the correct place in claim_bus().

This essentially reverts and re-implements the patch mentioned in the
fixes tag below. I'm not sure how the original could ever have worked on
any Tegra platform; it certainly breaks the only Tegra board I have that
uses SPI.

Fixes: 5cb1b7b395c0 ("spi: tegra20: Add support for mode selection")
Cc: Mirza Krak <mirza.krak at hostmobility.com>
Signed-off-by: Stephen Warren <swarren at nvidia.com>
---
As far as I can tell, the fixed patch was never CC'd to any Tegra
maintainer:-(
---
 drivers/spi/tegra20_slink.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 238edec23ba5..0e167ccac053 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -151,6 +151,14 @@ static int tegra30_spi_claim_bus(struct udevice *dev)
 	/* Set master mode and sw controlled CS */
 	reg = readl(&regs->command);
 	reg |= SLINK_CMD_M_S | SLINK_CMD_CS_SOFT;
+	/* Set CPOL and CPHA */
+	reg &= ~(SLINK_CMD_IDLE_SCLK_MASK | SLINK_CMD_CK_SDA);
+	if (priv->mode & SPI_CPHA)
+		reg |= SLINK_CMD_CK_SDA;
+	if (priv->mode & SPI_CPOL)
+		reg |= SLINK_CMD_IDLE_SCLK_DRIVE_HIGH;
+	else
+		reg |= SLINK_CMD_IDLE_SCLK_DRIVE_LOW;
 	writel(reg, &regs->command);
 	debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
 
@@ -321,22 +329,6 @@ static int tegra30_spi_set_speed(struct udevice *bus, uint speed)
 static int tegra30_spi_set_mode(struct udevice *bus, uint mode)
 {
 	struct tegra30_spi_priv *priv = dev_get_priv(bus);
-	struct spi_regs *regs = priv->regs;
-	u32 reg;
-
-	reg = readl(&regs->command);
-
-	/* Set CPOL and CPHA */
-	reg &= ~(SLINK_CMD_IDLE_SCLK_MASK | SLINK_CMD_CK_SDA);
-	if (mode & SPI_CPHA)
-		reg |= SLINK_CMD_CK_SDA;
-
-	if (mode & SPI_CPOL)
-		reg |= SLINK_CMD_IDLE_SCLK_DRIVE_HIGH;
-	else
-		reg |= SLINK_CMD_IDLE_SCLK_DRIVE_LOW;
-
-	writel(reg, &regs->command);
 
 	priv->mode = mode;
 	debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
-- 
2.9.2



More information about the U-Boot mailing list