diff options
author | Hou Zhiqiang <b48286@freescale.com> | 2013-12-11 23:53:52 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-12-12 06:50:02 -0500 |
commit | 714bb654e97535c4bed4a8da0628cbc842dc8e31 (patch) | |
tree | 3c086135837f1358dd8648f6e780e65fef07d376 /drivers/spi/spi-fsl-espi.c | |
parent | 7227cd18934276eb6d7cf758f79f8c6feacdc421 (diff) |
spi/fsl-espi: Add Power Management support for eSPI controller
Add PM support for eSPI controller using callback function suspend
and resume in .driver.pm of platform_driver.
Signed-off-by: Hou Zhiqiang <b48286@freescale.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi-fsl-espi.c')
-rw-r--r-- | drivers/spi/spi-fsl-espi.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 8106006cdc39..428dc7a6b62e 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c | |||
@@ -727,6 +727,66 @@ static int of_fsl_espi_remove(struct platform_device *dev) | |||
727 | return mpc8xxx_spi_remove(&dev->dev); | 727 | return mpc8xxx_spi_remove(&dev->dev); |
728 | } | 728 | } |
729 | 729 | ||
730 | #ifdef CONFIG_PM_SLEEP | ||
731 | static int of_fsl_espi_suspend(struct device *dev) | ||
732 | { | ||
733 | struct spi_master *master = dev_get_drvdata(dev); | ||
734 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
735 | struct fsl_espi_reg *reg_base; | ||
736 | u32 regval; | ||
737 | int ret; | ||
738 | |||
739 | mpc8xxx_spi = spi_master_get_devdata(master); | ||
740 | reg_base = mpc8xxx_spi->reg_base; | ||
741 | |||
742 | ret = spi_master_suspend(master); | ||
743 | if (ret) { | ||
744 | dev_warn(dev, "cannot suspend master\n"); | ||
745 | return ret; | ||
746 | } | ||
747 | |||
748 | regval = mpc8xxx_spi_read_reg(®_base->mode); | ||
749 | regval &= ~SPMODE_ENABLE; | ||
750 | mpc8xxx_spi_write_reg(®_base->mode, regval); | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int of_fsl_espi_resume(struct device *dev) | ||
756 | { | ||
757 | struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); | ||
758 | struct spi_master *master = dev_get_drvdata(dev); | ||
759 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
760 | struct fsl_espi_reg *reg_base; | ||
761 | u32 regval; | ||
762 | int i; | ||
763 | |||
764 | mpc8xxx_spi = spi_master_get_devdata(master); | ||
765 | reg_base = mpc8xxx_spi->reg_base; | ||
766 | |||
767 | /* SPI controller initializations */ | ||
768 | mpc8xxx_spi_write_reg(®_base->mode, 0); | ||
769 | mpc8xxx_spi_write_reg(®_base->mask, 0); | ||
770 | mpc8xxx_spi_write_reg(®_base->command, 0); | ||
771 | mpc8xxx_spi_write_reg(®_base->event, 0xffffffff); | ||
772 | |||
773 | /* Init eSPI CS mode register */ | ||
774 | for (i = 0; i < pdata->max_chipselect; i++) | ||
775 | mpc8xxx_spi_write_reg(®_base->csmode[i], CSMODE_INIT_VAL); | ||
776 | |||
777 | /* Enable SPI interface */ | ||
778 | regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; | ||
779 | |||
780 | mpc8xxx_spi_write_reg(®_base->mode, regval); | ||
781 | |||
782 | return spi_master_resume(master); | ||
783 | } | ||
784 | #endif /* CONFIG_PM_SLEEP */ | ||
785 | |||
786 | static const struct dev_pm_ops espi_pm = { | ||
787 | SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume) | ||
788 | }; | ||
789 | |||
730 | static const struct of_device_id of_fsl_espi_match[] = { | 790 | static const struct of_device_id of_fsl_espi_match[] = { |
731 | { .compatible = "fsl,mpc8536-espi" }, | 791 | { .compatible = "fsl,mpc8536-espi" }, |
732 | {} | 792 | {} |
@@ -738,6 +798,7 @@ static struct platform_driver fsl_espi_driver = { | |||
738 | .name = "fsl_espi", | 798 | .name = "fsl_espi", |
739 | .owner = THIS_MODULE, | 799 | .owner = THIS_MODULE, |
740 | .of_match_table = of_fsl_espi_match, | 800 | .of_match_table = of_fsl_espi_match, |
801 | .pm = &espi_pm, | ||
741 | }, | 802 | }, |
742 | .probe = of_fsl_espi_probe, | 803 | .probe = of_fsl_espi_probe, |
743 | .remove = of_fsl_espi_remove, | 804 | .remove = of_fsl_espi_remove, |