diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 1a6381de6f33d7018eb00842fa9ee8cd8f1f01f7..4c34ef9d5220f4c7e9d7c1af78501126994dcfed 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -379,6 +379,26 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static void rockchip_spi_poll_completion(struct rockchip_spi *rs, + struct spi_controller *ctlr, + unsigned int timeout_ms) +{ + ktime_t ktime = ktime_get(); + ktime_t ktimeout = ktime_add_ms(ktime, timeout_ms); + + do { + rockchip_spi_isr(0, ctlr); + + if (completion_done(&ctlr->xfer_completion)) + return; + + ktime = ktime_get(); + + } while (ktime_before(ktime, ktimeout)); + + dev_err(rs->dev, "atomic transfer timeout\n"); +} + static int rockchip_spi_prepare_irq(struct rockchip_spi *rs, struct spi_controller *ctlr, struct spi_transfer *xfer) @@ -400,6 +420,11 @@ static int rockchip_spi_prepare_irq(struct rockchip_spi *rs, else writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR); + if (ctlr->atomic_xfer) { + rockchip_spi_poll_completion(rs, ctlr, 1000); + return 0; + } + /* 1 means the transfer is in progress */ return 1; } @@ -677,7 +702,7 @@ static int rockchip_spi_transfer_one( { struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); int ret; - bool use_dma; + bool use_dma = false; /* Zero length transfers won't trigger an interrupt on completion */ if (!xfer->len) { @@ -700,7 +725,9 @@ static int rockchip_spi_transfer_one( rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2; rs->xfer = xfer; - use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false; + + if (!ctlr->atomic_xfer) + use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false; ret = rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->target); if (ret) @@ -1015,6 +1042,11 @@ static int rockchip_spi_runtime_resume(struct device *dev) } #endif /* CONFIG_PM */ +static void rockchip_spi_shutdown(struct platform_device *pdev) +{ + pm_runtime_get_sync(&pdev->dev); +} + static const struct dev_pm_ops rockchip_spi_pm = { SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume) SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend, @@ -1046,6 +1078,7 @@ static struct platform_driver rockchip_spi_driver = { }, .probe = rockchip_spi_probe, .remove = rockchip_spi_remove, + .shutdown = rockchip_spi_shutdown, }; module_platform_driver(rockchip_spi_driver);