Commit 2f19e7a7 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'spi-fix-v4.19-rc5' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Mark writes:
  "spi: Fixes for v4.19

   Quite a few fixes for the Renesas drivers in here, plus a fix for the
   Tegra driver and some documentation fixes for the recently added
   spi-mem code.  The Tegra fix is relatively large but fairly
   straightforward and mechanical, it runs on probe so it's been
   reasonably well covered in -next testing."

* tag 'spi-fix-v4.19-rc5' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: spi-mem: Move the DMA-able constraint doc to the kerneldoc header
  spi: spi-mem: Add missing description for data.nbytes field
  spi: rspi: Fix interrupted DMA transfers
  spi: rspi: Fix invalid SPI use during system suspend
  spi: sh-msiof: Fix handling of write value for SISTR register
  spi: sh-msiof: Fix invalid SPI use during system suspend
  spi: gpio: Fix copy-and-paste error
  spi: tegra20-slink: explicitly enable/disable clock
parents 8f056611 c949a8e8
...@@ -300,8 +300,8 @@ static int spi_gpio_request(struct device *dev, ...@@ -300,8 +300,8 @@ static int spi_gpio_request(struct device *dev,
*mflags |= SPI_MASTER_NO_RX; *mflags |= SPI_MASTER_NO_RX;
spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW); spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
if (IS_ERR(spi_gpio->mosi)) if (IS_ERR(spi_gpio->sck))
return PTR_ERR(spi_gpio->mosi); return PTR_ERR(spi_gpio->sck);
for (i = 0; i < num_chipselects; i++) { for (i = 0; i < num_chipselects; i++) {
spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs",
......
...@@ -598,11 +598,13 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ...@@ -598,11 +598,13 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
ret = wait_event_interruptible_timeout(rspi->wait, ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ); rspi->dma_callbacked, HZ);
if (ret > 0 && rspi->dma_callbacked) if (ret > 0 && rspi->dma_callbacked) {
ret = 0; ret = 0;
else if (!ret) { } else {
dev_err(&rspi->master->dev, "DMA timeout\n"); if (!ret) {
ret = -ETIMEDOUT; dev_err(&rspi->master->dev, "DMA timeout\n");
ret = -ETIMEDOUT;
}
if (tx) if (tx)
dmaengine_terminate_all(rspi->master->dma_tx); dmaengine_terminate_all(rspi->master->dma_tx);
if (rx) if (rx)
...@@ -1350,12 +1352,36 @@ static const struct platform_device_id spi_driver_ids[] = { ...@@ -1350,12 +1352,36 @@ static const struct platform_device_id spi_driver_ids[] = {
MODULE_DEVICE_TABLE(platform, spi_driver_ids); MODULE_DEVICE_TABLE(platform, spi_driver_ids);
#ifdef CONFIG_PM_SLEEP
static int rspi_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct rspi_data *rspi = platform_get_drvdata(pdev);
return spi_master_suspend(rspi->master);
}
static int rspi_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct rspi_data *rspi = platform_get_drvdata(pdev);
return spi_master_resume(rspi->master);
}
static SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume);
#define DEV_PM_OPS &rspi_pm_ops
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
static struct platform_driver rspi_driver = { static struct platform_driver rspi_driver = {
.probe = rspi_probe, .probe = rspi_probe,
.remove = rspi_remove, .remove = rspi_remove,
.id_table = spi_driver_ids, .id_table = spi_driver_ids,
.driver = { .driver = {
.name = "renesas_spi", .name = "renesas_spi",
.pm = DEV_PM_OPS,
.of_match_table = of_match_ptr(rspi_of_match), .of_match_table = of_match_ptr(rspi_of_match),
}, },
}; };
......
...@@ -397,7 +397,8 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, ...@@ -397,7 +397,8 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p) static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
{ {
sh_msiof_write(p, STR, sh_msiof_read(p, STR)); sh_msiof_write(p, STR,
sh_msiof_read(p, STR) & ~(STR_TDREQ | STR_RDREQ));
} }
static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
...@@ -1426,12 +1427,37 @@ static const struct platform_device_id spi_driver_ids[] = { ...@@ -1426,12 +1427,37 @@ static const struct platform_device_id spi_driver_ids[] = {
}; };
MODULE_DEVICE_TABLE(platform, spi_driver_ids); MODULE_DEVICE_TABLE(platform, spi_driver_ids);
#ifdef CONFIG_PM_SLEEP
static int sh_msiof_spi_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
return spi_master_suspend(p->master);
}
static int sh_msiof_spi_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
return spi_master_resume(p->master);
}
static SIMPLE_DEV_PM_OPS(sh_msiof_spi_pm_ops, sh_msiof_spi_suspend,
sh_msiof_spi_resume);
#define DEV_PM_OPS &sh_msiof_spi_pm_ops
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
static struct platform_driver sh_msiof_spi_drv = { static struct platform_driver sh_msiof_spi_drv = {
.probe = sh_msiof_spi_probe, .probe = sh_msiof_spi_probe,
.remove = sh_msiof_spi_remove, .remove = sh_msiof_spi_remove,
.id_table = spi_driver_ids, .id_table = spi_driver_ids,
.driver = { .driver = {
.name = "spi_sh_msiof", .name = "spi_sh_msiof",
.pm = DEV_PM_OPS,
.of_match_table = of_match_ptr(sh_msiof_match), .of_match_table = of_match_ptr(sh_msiof_match),
}, },
}; };
......
...@@ -1063,6 +1063,24 @@ static int tegra_slink_probe(struct platform_device *pdev) ...@@ -1063,6 +1063,24 @@ static int tegra_slink_probe(struct platform_device *pdev)
goto exit_free_master; 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); spi_irq = platform_get_irq(pdev, 0);
tspi->irq = spi_irq; tspi->irq = spi_irq;
ret = request_threaded_irq(tspi->irq, tegra_slink_isr, ret = request_threaded_irq(tspi->irq, tegra_slink_isr,
...@@ -1071,14 +1089,7 @@ static int tegra_slink_probe(struct platform_device *pdev) ...@@ -1071,14 +1089,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
tspi->irq); tspi->irq);
goto exit_free_master; goto exit_clk_disable;
}
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;
} }
tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
...@@ -1138,6 +1149,8 @@ static int tegra_slink_probe(struct platform_device *pdev) ...@@ -1138,6 +1149,8 @@ static int tegra_slink_probe(struct platform_device *pdev)
tegra_slink_deinit_dma_param(tspi, true); tegra_slink_deinit_dma_param(tspi, true);
exit_free_irq: exit_free_irq:
free_irq(spi_irq, tspi); free_irq(spi_irq, tspi);
exit_clk_disable:
clk_disable(tspi->clk);
exit_free_master: exit_free_master:
spi_master_put(master); spi_master_put(master);
return ret; return ret;
...@@ -1150,6 +1163,8 @@ static int tegra_slink_remove(struct platform_device *pdev) ...@@ -1150,6 +1163,8 @@ static int tegra_slink_remove(struct platform_device *pdev)
free_irq(tspi->irq, tspi); free_irq(tspi->irq, tspi);
clk_disable(tspi->clk);
if (tspi->tx_dma_chan) if (tspi->tx_dma_chan)
tegra_slink_deinit_dma_param(tspi, false); tegra_slink_deinit_dma_param(tspi, false);
......
...@@ -81,8 +81,10 @@ enum spi_mem_data_dir { ...@@ -81,8 +81,10 @@ enum spi_mem_data_dir {
* @dummy.buswidth: number of IO lanes used to transmit the dummy bytes * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes
* @data.buswidth: number of IO lanes used to send/receive the data * @data.buswidth: number of IO lanes used to send/receive the data
* @data.dir: direction of the transfer * @data.dir: direction of the transfer
* @data.buf.in: input buffer * @data.nbytes: number of data bytes to send/receive. Can be zero if the
* @data.buf.out: output buffer * operation does not involve transferring data
* @data.buf.in: input buffer (must be DMA-able)
* @data.buf.out: output buffer (must be DMA-able)
*/ */
struct spi_mem_op { struct spi_mem_op {
struct { struct {
...@@ -105,7 +107,6 @@ struct spi_mem_op { ...@@ -105,7 +107,6 @@ struct spi_mem_op {
u8 buswidth; u8 buswidth;
enum spi_mem_data_dir dir; enum spi_mem_data_dir dir;
unsigned int nbytes; unsigned int nbytes;
/* buf.{in,out} must be DMA-able. */
union { union {
void *in; void *in;
const void *out; const void *out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment