* [PATCH] SPI: spi-orion: add runtime PM support
@ 2014-06-21 10:32 Russell King
[not found] ` <E1WyIay-0008KP-Mm-eh5Bv4kxaXIANfyc6IWni62ZND6+EDdj@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: Russell King @ 2014-06-21 10:32 UTC (permalink / raw)
To: Mark Brown, Andrew Lunn, Jason Cooper; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA
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 <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
---
Patch generated against v3.15
drivers/spi/spi-orion.c | 71 +++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 63 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 24844984ef36..0c229f9fec9c 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/sizes.h>
@@ -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,6 +281,18 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
return xfer->len - count;
}
+static int orion_spi_prepare_transfer(struct spi_master *master)
+{
+ int ret = pm_runtime_get_sync(master->dev.parent);
+ return ret < 0 ? ret : 0;
+}
+
+static int orion_spi_unprepare_transfer(struct spi_master *master)
+{
+ pm_runtime_mark_last_busy(master->dev.parent);
+ pm_runtime_put_autosuspend(master->dev.parent);
+ return 0;
+}
static int orion_spi_transfer_one_message(struct spi_master *master,
struct spi_message *m)
@@ -367,6 +383,8 @@ static int orion_spi_probe(struct platform_device *pdev)
/* we support only mode 0, and no options */
master->mode_bits = SPI_CPHA | SPI_CPOL;
+ master->prepare_transfer_hardware = orion_spi_prepare_transfer;
+ master->unprepare_transfer_hardware = orion_spi_unprepare_transfer;
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);
@@ -397,16 +415,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 +445,45 @@ static int orion_spi_probe(struct platform_device *pdev)
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 +494,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,
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] SPI: spi-orion: add runtime PM support
[not found] ` <E1WyIay-0008KP-Mm-eh5Bv4kxaXIANfyc6IWni62ZND6+EDdj@public.gmane.org>
@ 2014-06-21 11:03 ` Mark Brown
[not found] ` <20140621110339.GG5099-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: Mark Brown @ 2014-06-21 11:03 UTC (permalink / raw)
To: Russell King; +Cc: Andrew Lunn, Jason Cooper, linux-spi-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 845 bytes --]
On Sat, Jun 21, 2014 at 11:32:28AM +0100, Russell King wrote:
> Add trivial runtime PM support. This will only be of benefit on SoCs
> where the clock to the SPI interface can be shut down.
This is good but...
> +static int orion_spi_prepare_transfer(struct spi_master *master)
> +{
> + int ret = pm_runtime_get_sync(master->dev.parent);
> + return ret < 0 ? ret : 0;
> +}
> +
> +static int orion_spi_unprepare_transfer(struct spi_master *master)
> +{
> + pm_runtime_mark_last_busy(master->dev.parent);
> + pm_runtime_put_autosuspend(master->dev.parent);
> + return 0;
> +}
...it should be possible to replace these by setting auto_runtime_pm in
the master struct. There were a lot of drivers cut'n'pasting the same
code so this got factored out to save a little code and make sure
everyone remembered to do their error checking and so on.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] SPI: spi-orion: add runtime PM support
[not found] ` <20140621110339.GG5099-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
@ 2014-06-21 11:22 ` Russell King
[not found] ` <E1WyJNV-0004DZ-Sb-eh5Bv4kxaXIANfyc6IWni62ZND6+EDdj@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: Russell King @ 2014-06-21 11:22 UTC (permalink / raw)
To: Mark Brown, Andrew Lunn, Jason Cooper; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA
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 <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
---
drivers/spi/spi-orion.c | 59 +++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 50 insertions(+), 9 deletions(-)
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 <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/sizes.h>
@@ -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 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
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 @@ static int orion_spi_probe(struct platform_device *pdev)
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,
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2] SPI: spi-orion: add runtime PM support
[not found] ` <E1WyJNV-0004DZ-Sb-eh5Bv4kxaXIANfyc6IWni62ZND6+EDdj@public.gmane.org>
@ 2014-06-21 15:31 ` Mark Brown
0 siblings, 0 replies; 4+ messages in thread
From: Mark Brown @ 2014-06-21 15:31 UTC (permalink / raw)
To: Russell King; +Cc: Andrew Lunn, Jason Cooper, linux-spi-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 209 bytes --]
On Sat, Jun 21, 2014 at 12:22:37PM +0100, Russell King wrote:
> Add trivial runtime PM support. This will only be of benefit on SoCs
> where the clock to the SPI interface can be shut down.
Applied, thanks.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-06-21 15:31 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-21 10:32 [PATCH] SPI: spi-orion: add runtime PM support Russell King
[not found] ` <E1WyIay-0008KP-Mm-eh5Bv4kxaXIANfyc6IWni62ZND6+EDdj@public.gmane.org>
2014-06-21 11:03 ` Mark Brown
[not found] ` <20140621110339.GG5099-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2014-06-21 11:22 ` [PATCH v2] " Russell King
[not found] ` <E1WyJNV-0004DZ-Sb-eh5Bv4kxaXIANfyc6IWni62ZND6+EDdj@public.gmane.org>
2014-06-21 15:31 ` Mark Brown
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.