From: Stephen Warren <swar...@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.k...@hostmobility.com>
Signed-off-by: Stephen Warren <swar...@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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to