diff options
author | Hou Zhiqiang <b48286@freescale.com> | 2013-12-12 08:53:52 +0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-12-12 15:50:02 +0400 |
commit | 714bb654e97535c4bed4a8da0628cbc842dc8e31 (patch) | |
tree | 3c086135837f1358dd8648f6e780e65fef07d376 | |
parent | 7227cd18934276eb6d7cf758f79f8c6feacdc421 (diff) | |
download | linux-714bb654e97535c4bed4a8da0628cbc842dc8e31.tar.xz |
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>
-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) return mpc8xxx_spi_remove(&dev->dev); } +#ifdef CONFIG_PM_SLEEP +static int of_fsl_espi_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct mpc8xxx_spi *mpc8xxx_spi; + struct fsl_espi_reg *reg_base; + u32 regval; + int ret; + + mpc8xxx_spi = spi_master_get_devdata(master); + reg_base = mpc8xxx_spi->reg_base; + + ret = spi_master_suspend(master); + if (ret) { + dev_warn(dev, "cannot suspend master\n"); + return ret; + } + + regval = mpc8xxx_spi_read_reg(®_base->mode); + regval &= ~SPMODE_ENABLE; + mpc8xxx_spi_write_reg(®_base->mode, regval); + + return 0; +} + +static int of_fsl_espi_resume(struct device *dev) +{ + struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); + struct spi_master *master = dev_get_drvdata(dev); + struct mpc8xxx_spi *mpc8xxx_spi; + struct fsl_espi_reg *reg_base; + u32 regval; + int i; + + mpc8xxx_spi = spi_master_get_devdata(master); + reg_base = mpc8xxx_spi->reg_base; + + /* SPI controller initializations */ + mpc8xxx_spi_write_reg(®_base->mode, 0); + mpc8xxx_spi_write_reg(®_base->mask, 0); + mpc8xxx_spi_write_reg(®_base->command, 0); + mpc8xxx_spi_write_reg(®_base->event, 0xffffffff); + + /* Init eSPI CS mode register */ + for (i = 0; i < pdata->max_chipselect; i++) + mpc8xxx_spi_write_reg(®_base->csmode[i], CSMODE_INIT_VAL); + + /* Enable SPI interface */ + regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; + + mpc8xxx_spi_write_reg(®_base->mode, regval); + + return spi_master_resume(master); +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops espi_pm = { + SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume) +}; + static const struct of_device_id of_fsl_espi_match[] = { { .compatible = "fsl,mpc8536-espi" }, {} @@ -738,6 +798,7 @@ static struct platform_driver fsl_espi_driver = { .name = "fsl_espi", .owner = THIS_MODULE, .of_match_table = of_fsl_espi_match, + .pm = &espi_pm, }, .probe = of_fsl_espi_probe, .remove = of_fsl_espi_remove, |