aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2015-08-26 15:21:55 -0400
committerMark Brown <broonie@kernel.org>2015-08-28 13:15:18 -0400
commite9abb4db8d108624c293f06dce06b2978e626a13 (patch)
tree04132b9da13d86f0df51dbb415cc0683d44850aa
parent3c5395b66ff69d8d568d0b9ff8b1077e044def5b (diff)
spi: fsl-espi: add runtime PM
Add runtime PM and use autosuspend instead of suspending the SPI controller after each transfer. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-fsl-espi.c71
1 files changed, 54 insertions, 17 deletions
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index fe54e5788245..db82c872c0f9 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -21,6 +21,7 @@
21#include <linux/of_platform.h> 21#include <linux/of_platform.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/spi/spi.h> 23#include <linux/spi/spi.h>
24#include <linux/pm_runtime.h>
24#include <sysdev/fsl_soc.h> 25#include <sysdev/fsl_soc.h>
25 26
26#include "spi-fsl-lib.h" 27#include "spi-fsl-lib.h"
@@ -85,6 +86,8 @@ struct fsl_espi_transfer {
85#define SPCOM_TRANLEN(x) ((x) << 0) 86#define SPCOM_TRANLEN(x) ((x) << 0)
86#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */ 87#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */
87 88
89#define AUTOSUSPEND_TIMEOUT 2000
90
88static void fsl_espi_change_mode(struct spi_device *spi) 91static void fsl_espi_change_mode(struct spi_device *spi)
89{ 92{
90 struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); 93 struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi)
485 mpc8xxx_spi = spi_master_get_devdata(spi->master); 488 mpc8xxx_spi = spi_master_get_devdata(spi->master);
486 reg_base = mpc8xxx_spi->reg_base; 489 reg_base = mpc8xxx_spi->reg_base;
487 490
491 pm_runtime_get_sync(mpc8xxx_spi->dev);
492
488 hw_mode = cs->hw_mode; /* Save original settings */ 493 hw_mode = cs->hw_mode; /* Save original settings */
489 cs->hw_mode = mpc8xxx_spi_read_reg( 494 cs->hw_mode = mpc8xxx_spi_read_reg(
490 &reg_base->csmode[spi->chip_select]); 495 &reg_base->csmode[spi->chip_select]);
@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi)
507 mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode); 512 mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
508 513
509 retval = fsl_espi_setup_transfer(spi, NULL); 514 retval = fsl_espi_setup_transfer(spi, NULL);
515
516 pm_runtime_mark_last_busy(mpc8xxx_spi->dev);
517 pm_runtime_put_autosuspend(mpc8xxx_spi->dev);
518
510 if (retval < 0) { 519 if (retval < 0) {
511 cs->hw_mode = hw_mode; /* Restore settings */ 520 cs->hw_mode = hw_mode; /* Restore settings */
512 return retval; 521 return retval;
@@ -604,15 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
604 return ret; 613 return ret;
605} 614}
606 615
607static int fsl_espi_suspend(struct spi_master *master) 616#ifdef CONFIG_PM
617static int fsl_espi_runtime_suspend(struct device *dev)
608{ 618{
609 struct mpc8xxx_spi *mpc8xxx_spi; 619 struct spi_master *master = dev_get_drvdata(dev);
610 struct fsl_espi_reg *reg_base; 620 struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
621 struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
611 u32 regval; 622 u32 regval;
612 623
613 mpc8xxx_spi = spi_master_get_devdata(master);
614 reg_base = mpc8xxx_spi->reg_base;
615
616 regval = mpc8xxx_spi_read_reg(&reg_base->mode); 624 regval = mpc8xxx_spi_read_reg(&reg_base->mode);
617 regval &= ~SPMODE_ENABLE; 625 regval &= ~SPMODE_ENABLE;
618 mpc8xxx_spi_write_reg(&reg_base->mode, regval); 626 mpc8xxx_spi_write_reg(&reg_base->mode, regval);
@@ -620,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master)
620 return 0; 628 return 0;
621} 629}
622 630
623static int fsl_espi_resume(struct spi_master *master) 631static int fsl_espi_runtime_resume(struct device *dev)
624{ 632{
625 struct mpc8xxx_spi *mpc8xxx_spi; 633 struct spi_master *master = dev_get_drvdata(dev);
626 struct fsl_espi_reg *reg_base; 634 struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
635 struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
627 u32 regval; 636 u32 regval;
628 637
629 mpc8xxx_spi = spi_master_get_devdata(master);
630 reg_base = mpc8xxx_spi->reg_base;
631
632 regval = mpc8xxx_spi_read_reg(&reg_base->mode); 638 regval = mpc8xxx_spi_read_reg(&reg_base->mode);
633 regval |= SPMODE_ENABLE; 639 regval |= SPMODE_ENABLE;
634 mpc8xxx_spi_write_reg(&reg_base->mode, regval); 640 mpc8xxx_spi_write_reg(&reg_base->mode, regval);
635 641
636 return 0; 642 return 0;
637} 643}
644#endif
638 645
639static struct spi_master * fsl_espi_probe(struct device *dev, 646static struct spi_master * fsl_espi_probe(struct device *dev,
640 struct resource *mem, unsigned int irq) 647 struct resource *mem, unsigned int irq)
@@ -662,8 +669,7 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
662 master->setup = fsl_espi_setup; 669 master->setup = fsl_espi_setup;
663 master->cleanup = fsl_espi_cleanup; 670 master->cleanup = fsl_espi_cleanup;
664 master->transfer_one_message = fsl_espi_do_one_msg; 671 master->transfer_one_message = fsl_espi_do_one_msg;
665 master->prepare_transfer_hardware = fsl_espi_resume; 672 master->auto_runtime_pm = true;
666 master->unprepare_transfer_hardware = fsl_espi_suspend;
667 673
668 mpc8xxx_spi = spi_master_get_devdata(master); 674 mpc8xxx_spi = spi_master_get_devdata(master);
669 675
@@ -725,14 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
725 731
726 mpc8xxx_spi_write_reg(&reg_base->mode, regval); 732 mpc8xxx_spi_write_reg(&reg_base->mode, regval);
727 733
734 pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT);
735 pm_runtime_use_autosuspend(dev);
736 pm_runtime_set_active(dev);
737 pm_runtime_enable(dev);
738 pm_runtime_get_sync(dev);
739
728 ret = devm_spi_register_master(dev, master); 740 ret = devm_spi_register_master(dev, master);
729 if (ret < 0) 741 if (ret < 0)
730 goto err_probe; 742 goto err_pm;
731 743
732 dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq); 744 dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
733 745
746 pm_runtime_mark_last_busy(dev);
747 pm_runtime_put_autosuspend(dev);
748
734 return master; 749 return master;
735 750
751err_pm:
752 pm_runtime_put_noidle(dev);
753 pm_runtime_disable(dev);
754 pm_runtime_set_suspended(dev);
736err_probe: 755err_probe:
737 spi_master_put(master); 756 spi_master_put(master);
738err: 757err:
@@ -797,6 +816,13 @@ err:
797 return ret; 816 return ret;
798} 817}
799 818
819static int of_fsl_espi_remove(struct platform_device *dev)
820{
821 pm_runtime_disable(&dev->dev);
822
823 return 0;
824}
825
800#ifdef CONFIG_PM_SLEEP 826#ifdef CONFIG_PM_SLEEP
801static int of_fsl_espi_suspend(struct device *dev) 827static int of_fsl_espi_suspend(struct device *dev)
802{ 828{
@@ -809,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev)
809 return ret; 835 return ret;
810 } 836 }
811 837
812 return fsl_espi_suspend(master); 838 ret = pm_runtime_force_suspend(dev);
839 if (ret < 0)
840 return ret;
841
842 return 0;
813} 843}
814 844
815static int of_fsl_espi_resume(struct device *dev) 845static int of_fsl_espi_resume(struct device *dev)
@@ -819,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev)
819 struct mpc8xxx_spi *mpc8xxx_spi; 849 struct mpc8xxx_spi *mpc8xxx_spi;
820 struct fsl_espi_reg *reg_base; 850 struct fsl_espi_reg *reg_base;
821 u32 regval; 851 u32 regval;
822 int i; 852 int i, ret;
823 853
824 mpc8xxx_spi = spi_master_get_devdata(master); 854 mpc8xxx_spi = spi_master_get_devdata(master);
825 reg_base = mpc8xxx_spi->reg_base; 855 reg_base = mpc8xxx_spi->reg_base;
@@ -839,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev)
839 869
840 mpc8xxx_spi_write_reg(&reg_base->mode, regval); 870 mpc8xxx_spi_write_reg(&reg_base->mode, regval);
841 871
872 ret = pm_runtime_force_resume(dev);
873 if (ret < 0)
874 return ret;
875
842 return spi_master_resume(master); 876 return spi_master_resume(master);
843} 877}
844#endif /* CONFIG_PM_SLEEP */ 878#endif /* CONFIG_PM_SLEEP */
845 879
846static const struct dev_pm_ops espi_pm = { 880static const struct dev_pm_ops espi_pm = {
881 SET_RUNTIME_PM_OPS(fsl_espi_runtime_suspend,
882 fsl_espi_runtime_resume, NULL)
847 SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume) 883 SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
848}; 884};
849 885
@@ -860,6 +896,7 @@ static struct platform_driver fsl_espi_driver = {
860 .pm = &espi_pm, 896 .pm = &espi_pm,
861 }, 897 },
862 .probe = of_fsl_espi_probe, 898 .probe = of_fsl_espi_probe,
899 .remove = of_fsl_espi_remove,
863}; 900};
864module_platform_driver(fsl_espi_driver); 901module_platform_driver(fsl_espi_driver);
865 902