From c85012addd800d8fd135b9a871d5ce9b8e8c4081 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 21 Jun 2014 11:32:23 +0100 Subject: spi: spi-orion: check return value from clk_prepare()/clk_enable() clk_prepare()/clk_enable() can fail, and it's return value should be checked. Add the proper checking, and while we're here, convert to clk_prepare_enable(). Signed-off-by: Russell King Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi-orion.c') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index d018a4aac3a1..24844984ef36 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -382,8 +382,10 @@ static int orion_spi_probe(struct platform_device *pdev) goto out; } - clk_prepare(spi->clk); - clk_enable(spi->clk); + status = clk_prepare_enable(spi->clk); + if (status) + goto out; + tclk_hz = clk_get_rate(spi->clk); master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4); master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30); -- cgit v1.2.3 From 5c6786945b4e0434312572da6cf40f13f1763740 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 21 Jun 2014 12:22:37 +0100 Subject: spi: spi-orion: add runtime PM support Add trivial runtime PM support. This will only be of benefit on SoCs where the clock to the SPI interface can be shut down. Signed-off-by: Russell King Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 59 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 9 deletions(-) (limited to 'drivers/spi/spi-orion.c') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 24844984ef36..aa3ecfc6b466 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,9 @@ #define DRIVER_NAME "orion_spi" +/* Runtime PM autosuspend timeout: PM is fairly light on this driver */ +#define SPI_AUTOSUSPEND_TIMEOUT 200 + #define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/ #define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */ @@ -277,7 +281,6 @@ out: return xfer->len - count; } - static int orion_spi_transfer_one_message(struct spi_master *master, struct spi_message *m) { @@ -370,6 +373,7 @@ static int orion_spi_probe(struct platform_device *pdev) master->transfer_one_message = orion_spi_transfer_one_message; master->num_chipselect = ORION_NUM_CHIPSELECTS; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); + master->auto_runtime_pm = true; platform_set_drvdata(pdev, master); @@ -397,16 +401,26 @@ static int orion_spi_probe(struct platform_device *pdev) goto out_rel_clk; } + pm_runtime_set_active(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); + pm_runtime_enable(&pdev->dev); + if (orion_spi_reset(spi) < 0) - goto out_rel_clk; + goto out_rel_pm; + + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); master->dev.of_node = pdev->dev.of_node; - status = devm_spi_register_master(&pdev->dev, master); + status = spi_register_master(master); if (status < 0) - goto out_rel_clk; + goto out_rel_pm; return status; +out_rel_pm: + pm_runtime_disable(&pdev->dev); out_rel_clk: clk_disable_unprepare(spi->clk); out: @@ -417,19 +431,45 @@ out: static int orion_spi_remove(struct platform_device *pdev) { - struct spi_master *master; - struct orion_spi *spi; - - master = platform_get_drvdata(pdev); - spi = spi_master_get_devdata(master); + struct spi_master *master = platform_get_drvdata(pdev); + struct orion_spi *spi = spi_master_get_devdata(master); + pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(spi->clk); + spi_unregister_master(master); + pm_runtime_disable(&pdev->dev); + return 0; } MODULE_ALIAS("platform:" DRIVER_NAME); +#ifdef CONFIG_PM_RUNTIME +static int orion_spi_runtime_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct orion_spi *spi = spi_master_get_devdata(master); + + clk_disable_unprepare(spi->clk); + return 0; +} + +static int orion_spi_runtime_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct orion_spi *spi = spi_master_get_devdata(master); + + return clk_prepare_enable(spi->clk); +} +#endif + +static const struct dev_pm_ops orion_spi_pm_ops = { + SET_RUNTIME_PM_OPS(orion_spi_runtime_suspend, + orion_spi_runtime_resume, + NULL) +}; + static const struct of_device_id orion_spi_of_match_table[] = { { .compatible = "marvell,orion-spi", }, {} @@ -440,6 +480,7 @@ static struct platform_driver orion_spi_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .pm = &orion_spi_pm_ops, .of_match_table = of_match_ptr(orion_spi_of_match_table), }, .probe = orion_spi_probe, -- cgit v1.2.3 From 1403381638e03b361afde8f3e107ecc8e6c8f54f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 20 Jul 2014 22:03:14 +0800 Subject: spi: orion: Fix error return code in orion_spi_probe() Fix to return a negative error code from the error handling case of orion_spi_reset() instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/spi/spi-orion.c') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index aa3ecfc6b466..3a3170ae3b31 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -406,7 +406,8 @@ static int orion_spi_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_enable(&pdev->dev); - if (orion_spi_reset(spi) < 0) + status = orion_spi_reset(spi); + if (status < 0) goto out_rel_pm; pm_runtime_mark_last_busy(&pdev->dev); -- cgit v1.2.3