| From: Marcel Ziswiler <marcel.ziswiler@toradex.com> |
| Date: Wed, 29 Aug 2018 08:47:57 +0200 |
| Subject: spi: tegra20-slink: explicitly enable/disable clock |
| |
| commit 7001cab1dabc0b72b2b672ef58a90ab64f5e2343 upstream. |
| |
| Depending on the SPI instance one may get an interrupt storm upon |
| requesting resp. interrupt unless the clock is explicitly enabled |
| beforehand. This has been observed trying to bring up instance 4 on |
| T20. |
| |
| Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com> |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/spi/spi-tegra20-slink.c | 31 +++++++++++++++++++++++-------- |
| 1 file changed, 23 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/spi/spi-tegra20-slink.c |
| +++ b/drivers/spi/spi-tegra20-slink.c |
| @@ -1063,6 +1063,24 @@ static int tegra_slink_probe(struct plat |
| goto exit_free_master; |
| } |
| |
| + /* disabled clock may cause interrupt storm upon request */ |
| + tspi->clk = devm_clk_get(&pdev->dev, NULL); |
| + if (IS_ERR(tspi->clk)) { |
| + ret = PTR_ERR(tspi->clk); |
| + dev_err(&pdev->dev, "Can not get clock %d\n", ret); |
| + goto exit_free_master; |
| + } |
| + ret = clk_prepare(tspi->clk); |
| + if (ret < 0) { |
| + dev_err(&pdev->dev, "Clock prepare failed %d\n", ret); |
| + goto exit_free_master; |
| + } |
| + ret = clk_enable(tspi->clk); |
| + if (ret < 0) { |
| + dev_err(&pdev->dev, "Clock enable failed %d\n", ret); |
| + goto exit_free_master; |
| + } |
| + |
| spi_irq = platform_get_irq(pdev, 0); |
| tspi->irq = spi_irq; |
| ret = request_threaded_irq(tspi->irq, tegra_slink_isr, |
| @@ -1071,14 +1089,7 @@ static int tegra_slink_probe(struct plat |
| if (ret < 0) { |
| dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", |
| tspi->irq); |
| - goto exit_free_master; |
| - } |
| - |
| - tspi->clk = devm_clk_get(&pdev->dev, NULL); |
| - if (IS_ERR(tspi->clk)) { |
| - dev_err(&pdev->dev, "can not get clock\n"); |
| - ret = PTR_ERR(tspi->clk); |
| - goto exit_free_irq; |
| + goto exit_clk_disable; |
| } |
| |
| tspi->rst = devm_reset_control_get(&pdev->dev, "spi"); |
| @@ -1138,6 +1149,8 @@ exit_rx_dma_free: |
| tegra_slink_deinit_dma_param(tspi, true); |
| exit_free_irq: |
| free_irq(spi_irq, tspi); |
| +exit_clk_disable: |
| + clk_disable(tspi->clk); |
| exit_free_master: |
| spi_master_put(master); |
| return ret; |
| @@ -1150,6 +1163,8 @@ static int tegra_slink_remove(struct pla |
| |
| free_irq(tspi->irq, tspi); |
| |
| + clk_disable(tspi->clk); |
| + |
| if (tspi->tx_dma_chan) |
| tegra_slink_deinit_dma_param(tspi, false); |
| |