diff options
author | Mark Brown <broonie@kernel.org> | 2023-03-17 20:43:18 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-03-17 20:43:18 +0300 |
commit | 864f0513a377184e12aa650089c9af71ba36c6e9 (patch) | |
tree | 9595a463e93ff09c14beeefc5fdf08fa86e098a6 | |
parent | 1e4929112507f145951f4c356161ab80ad9c1f0e (diff) | |
parent | 4d70dd0a25081bc4e6378d0da4a7c367389df707 (diff) | |
download | linux-864f0513a377184e12aa650089c9af71ba36c6e9.tar.xz |
spi: atmel-quadspi: Convert to platform remove
Merge series from Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
This series converts the atmel-quadspi driver to use the .remove_new()
callback that doesn't return an int but void. The motivation is to not
give driver authors a reason to (wrongly) believe that returning an
error code was sensible error handling. In fact the spi core only emits
a warning message in this case and otherwise continues as if the return
value was zero. This usually yields resource leaks that sometimes can
lead to exceptions later on.
The atmel-quadspi driver is one of these drivers that got error handling
wrong, this is fixed here and in the last patch the driver is converted
to .remove_new() with the eventual goal to change .remove() to return
void once all drivers are converted this way.
-rw-r--r-- | drivers/spi/atmel-quadspi.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index f4632cb07495..3d1252566134 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -700,25 +700,33 @@ disable_pclk: return err; } -static int atmel_qspi_remove(struct platform_device *pdev) +static void atmel_qspi_remove(struct platform_device *pdev) { struct spi_controller *ctrl = platform_get_drvdata(pdev); struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); int ret; - ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret < 0) - return ret; - spi_unregister_controller(ctrl); - atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR); + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret >= 0) { + atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR); + clk_disable(aq->qspick); + clk_disable(aq->pclk); + } else { + /* + * atmel_qspi_runtime_{suspend,resume} just disable and enable + * the two clks respectively. So after resume failed these are + * off, and we skip hardware access and disabling these clks again. + */ + dev_warn(&pdev->dev, "Failed to resume device on remove\n"); + } + + clk_unprepare(aq->qspick); + clk_unprepare(aq->pclk); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - - clk_disable_unprepare(aq->qspick); - clk_disable_unprepare(aq->pclk); - return 0; } static int __maybe_unused atmel_qspi_suspend(struct device *dev) @@ -786,7 +794,11 @@ static int __maybe_unused atmel_qspi_runtime_resume(struct device *dev) if (ret) return ret; - return clk_enable(aq->qspick); + ret = clk_enable(aq->qspick); + if (ret) + clk_disable(aq->pclk); + + return ret; } static const struct dev_pm_ops __maybe_unused atmel_qspi_pm_ops = { @@ -823,7 +835,7 @@ static struct platform_driver atmel_qspi_driver = { .pm = pm_ptr(&atmel_qspi_pm_ops), }, .probe = atmel_qspi_probe, - .remove = atmel_qspi_remove, + .remove_new = atmel_qspi_remove, }; module_platform_driver(atmel_qspi_driver); |