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. -----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAluuOnETHGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0AhkB/9ahKdmxdxu0uuzzvS5qmdGD+98dTaV M+7+Bq6CJfBz0YTc9dxTiynbJot15vo5mKDZkDaJrgOoLCWWDGWa/DjRif2qS2o9 QxjWlBPzfOhKb81/HMJ+MaIHYDtAxvCu4iZExUZPxZzypX8Q9U3+9a/u0+JnRug2 guQ/4vYdxTGbR/taFsKLzf28DRqQb74KuDRAHaN44UYBxA1begy5gFOc7cEQTRu0 WACGM8jNL2eWWLXDNnQQTfb2t1v7LbbMorazyCn2e5ujamE4+DSaYWJF5axZiaQN ZcRVATw0SPiQlsQW/G014SSFJT0waybxWLOynWS9MSgjx84/GRYWvxRv =3ATM -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
2f19e7a7e6
|
@ -300,8 +300,8 @@ static int spi_gpio_request(struct device *dev,
|
|||
*mflags |= SPI_MASTER_NO_RX;
|
||||
|
||||
spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(spi_gpio->mosi))
|
||||
return PTR_ERR(spi_gpio->mosi);
|
||||
if (IS_ERR(spi_gpio->sck))
|
||||
return PTR_ERR(spi_gpio->sck);
|
||||
|
||||
for (i = 0; i < num_chipselects; i++) {
|
||||
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,
|
|||
|
||||
ret = wait_event_interruptible_timeout(rspi->wait,
|
||||
rspi->dma_callbacked, HZ);
|
||||
if (ret > 0 && rspi->dma_callbacked)
|
||||
if (ret > 0 && rspi->dma_callbacked) {
|
||||
ret = 0;
|
||||
else if (!ret) {
|
||||
dev_err(&rspi->master->dev, "DMA timeout\n");
|
||||
ret = -ETIMEDOUT;
|
||||
} else {
|
||||
if (!ret) {
|
||||
dev_err(&rspi->master->dev, "DMA timeout\n");
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
if (tx)
|
||||
dmaengine_terminate_all(rspi->master->dma_tx);
|
||||
if (rx)
|
||||
|
@ -1350,12 +1352,36 @@ static const struct platform_device_id 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 = {
|
||||
.probe = rspi_probe,
|
||||
.remove = rspi_remove,
|
||||
.id_table = spi_driver_ids,
|
||||
.driver = {
|
||||
.name = "renesas_spi",
|
||||
.pm = DEV_PM_OPS,
|
||||
.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,
|
|||
|
||||
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,
|
||||
|
@ -1426,12 +1427,37 @@ static const struct platform_device_id 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 = {
|
||||
.probe = sh_msiof_spi_probe,
|
||||
.remove = sh_msiof_spi_remove,
|
||||
.id_table = spi_driver_ids,
|
||||
.driver = {
|
||||
.name = "spi_sh_msiof",
|
||||
.pm = DEV_PM_OPS,
|
||||
.of_match_table = of_match_ptr(sh_msiof_match),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1063,6 +1063,24 @@ static int tegra_slink_probe(struct platform_device *pdev)
|
|||
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 platform_device *pdev)
|
|||
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_exclusive(&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 platform_device *pdev)
|
|||
|
||||
free_irq(tspi->irq, tspi);
|
||||
|
||||
clk_disable(tspi->clk);
|
||||
|
||||
if (tspi->tx_dma_chan)
|
||||
tegra_slink_deinit_dma_param(tspi, false);
|
||||
|
||||
|
|
|
@ -81,8 +81,10 @@ enum spi_mem_data_dir {
|
|||
* @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.dir: direction of the transfer
|
||||
* @data.buf.in: input buffer
|
||||
* @data.buf.out: output buffer
|
||||
* @data.nbytes: number of data bytes to send/receive. Can be zero if the
|
||||
* 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 {
|
||||
|
@ -105,7 +107,6 @@ struct spi_mem_op {
|
|||
u8 buswidth;
|
||||
enum spi_mem_data_dir dir;
|
||||
unsigned int nbytes;
|
||||
/* buf.{in,out} must be DMA-able. */
|
||||
union {
|
||||
void *in;
|
||||
const void *out;
|
||||
|
|
Loading…
Reference in New Issue