diff options
author | Fabrice Gasnier <fabrice.gasnier@st.com> | 2019-03-25 15:49:28 +0100 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2019-04-04 20:21:12 +0100 |
commit | 6ec417d2f1a028705a1ae6f59d3e15344f6a4fbe (patch) | |
tree | 778a1127f07b5cd2d8646d64962b50c25582437f /drivers/iio/adc/stm32-dfsdm-adc.c | |
parent | 9f57110d2e3de5411730f2cdd160d60f4b59acc5 (diff) | |
download | linux-6ec417d2f1a028705a1ae6f59d3e15344f6a4fbe.tar.bz2 |
iio: adc: stm32-dfsdm: add PM support
Add PM and runtime PM support to STM32 DFSDM drivers:
- stm32-dfsdm-core: manage clocks.
- stm32-dfsdm-adc: restore channels configuration upon resume. Also stop
restart everything in case of buffer mode.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio/adc/stm32-dfsdm-adc.c')
-rw-r--r-- | drivers/iio/adc/stm32-dfsdm-adc.c | 75 |
1 files changed, 66 insertions, 9 deletions
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 051561c1357a..19adc2b23472 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -868,24 +868,18 @@ static int stm32_dfsdm_update_scan_mode(struct iio_dev *indio_dev, return 0; } -static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) +static int __stm32_dfsdm_postenable(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); int ret; - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret < 0) - return ret; - } - /* Reset adc buffer index */ adc->bufi = 0; if (adc->hwc) { ret = iio_hw_consumer_enable(adc->hwc); if (ret < 0) - goto err_predisable; + return ret; } ret = stm32_dfsdm_start_dfsdm(adc->dfsdm); @@ -913,6 +907,26 @@ stop_dfsdm: err_stop_hwc: if (adc->hwc) iio_hw_consumer_disable(adc->hwc); + + return ret; +} + +static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) +{ + int ret; + + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + ret = iio_triggered_buffer_postenable(indio_dev); + if (ret < 0) + return ret; + } + + ret = __stm32_dfsdm_postenable(indio_dev); + if (ret < 0) + goto err_predisable; + + return 0; + err_predisable: if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) iio_triggered_buffer_predisable(indio_dev); @@ -920,7 +934,7 @@ err_predisable: return ret; } -static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) +static void __stm32_dfsdm_predisable(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); @@ -932,6 +946,11 @@ static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) if (adc->hwc) iio_hw_consumer_disable(adc->hwc); +} + +static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) +{ + __stm32_dfsdm_predisable(indio_dev); if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) iio_triggered_buffer_predisable(indio_dev); @@ -1496,10 +1515,48 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev) return 0; } +static int __maybe_unused stm32_dfsdm_adc_suspend(struct device *dev) +{ + struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev); + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + + if (iio_buffer_enabled(indio_dev)) + __stm32_dfsdm_predisable(indio_dev); + + return 0; +} + +static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev) +{ + struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev); + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + const struct iio_chan_spec *chan; + struct stm32_dfsdm_channel *ch; + int i, ret; + + /* restore channels configuration */ + for (i = 0; i < indio_dev->num_channels; i++) { + chan = indio_dev->channels + i; + ch = &adc->dfsdm->ch_list[chan->channel]; + ret = stm32_dfsdm_chan_configure(adc->dfsdm, ch); + if (ret) + return ret; + } + + if (iio_buffer_enabled(indio_dev)) + __stm32_dfsdm_postenable(indio_dev); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(stm32_dfsdm_adc_pm_ops, + stm32_dfsdm_adc_suspend, stm32_dfsdm_adc_resume); + static struct platform_driver stm32_dfsdm_adc_driver = { .driver = { .name = "stm32-dfsdm-adc", .of_match_table = stm32_dfsdm_adc_match, + .pm = &stm32_dfsdm_adc_pm_ops, }, .probe = stm32_dfsdm_adc_probe, .remove = stm32_dfsdm_adc_remove, |