
From: Stephen Warren swarren@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@hostmobility.com Signed-off-by: Stephen Warren swarren@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(®s->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, ®s->command); debug("%s: COMMAND = %08x\n", __func__, readl(®s->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(®s->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, ®s->command);
priv->mode = mode; debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);