From: Jonathan Cameron <jic23@kernel.org>
To: Fabrice Gasnier <fabrice.gasnier@st.com>
Cc: <linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>, <mcoquelin.stm32@gmail.com>,
<alexandre.torgue@st.com>, <linux-iio@vger.kernel.org>,
<lars@metafoo.de>, <knaack.h@gmx.de>, <pmeerw@pmeerw.net>,
<linux-stm32@st-md-mailman.stormreply.com>
Subject: Re: [PATCH 3/3] iio: adc: stm32-adc: switch off running adc when going to low power
Date: Sun, 25 Nov 2018 13:17:35 +0000 [thread overview]
Message-ID: <20181125131735.616d6cf9@archlinux> (raw)
In-Reply-To: <1542708752-26163-4-git-send-email-fabrice.gasnier@st.com>
On Tue, 20 Nov 2018 11:12:32 +0100
Fabrice Gasnier <fabrice.gasnier@st.com> wrote:
> Switch off ADC when going to low power mode, in case it has been left
> running in buffer mode. Then re-enable it when resuming.
>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
My suspicion is that we have other drivers not correctly handing this
case, but as far as I can see you have it well covered here.
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> drivers/iio/adc/stm32-adc.c | 79 ++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 63 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
> index 32c9c61..2a9891c 100644
> --- a/drivers/iio/adc/stm32-adc.c
> +++ b/drivers/iio/adc/stm32-adc.c
> @@ -1518,7 +1518,7 @@ static int stm32_adc_dma_start(struct iio_dev *indio_dev)
> return 0;
> }
>
> -static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> +static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> {
> struct stm32_adc *adc = iio_priv(indio_dev);
> struct device *dev = indio_dev->dev.parent;
> @@ -1542,10 +1542,6 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> goto err_clr_trig;
> }
>
> - ret = iio_triggered_buffer_postenable(indio_dev);
> - if (ret < 0)
> - goto err_stop_dma;
> -
> /* Reset adc buffer index */
> adc->bufi = 0;
>
> @@ -1556,9 +1552,6 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
>
> return 0;
>
> -err_stop_dma:
> - if (adc->dma_chan)
> - dmaengine_terminate_all(adc->dma_chan);
> err_clr_trig:
> stm32_adc_set_trig(indio_dev, NULL);
> err_pm_put:
> @@ -1568,20 +1561,30 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> return ret;
> }
>
> -static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
> +static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + int ret;
> +
> + ret = iio_triggered_buffer_postenable(indio_dev);
> + if (ret < 0)
> + return ret;
> +
> + ret = __stm32_adc_buffer_postenable(indio_dev);
> + if (ret < 0)
> + iio_triggered_buffer_predisable(indio_dev);
> +
> + return ret;
> +}
> +
> +static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
> {
> struct stm32_adc *adc = iio_priv(indio_dev);
> struct device *dev = indio_dev->dev.parent;
> - int ret;
>
> adc->cfg->stop_conv(adc);
> if (!adc->dma_chan)
> stm32_adc_conv_irq_disable(adc);
>
> - ret = iio_triggered_buffer_predisable(indio_dev);
> - if (ret < 0)
> - dev_err(&indio_dev->dev, "predisable failed\n");
> -
> if (adc->dma_chan)
> dmaengine_terminate_all(adc->dma_chan);
>
> @@ -1590,6 +1593,17 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
>
> pm_runtime_mark_last_busy(dev);
> pm_runtime_put_autosuspend(dev);
> +}
> +
> +static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
> +{
> + int ret;
> +
> + __stm32_adc_buffer_predisable(indio_dev);
> +
> + ret = iio_triggered_buffer_predisable(indio_dev);
> + if (ret < 0)
> + dev_err(&indio_dev->dev, "predisable failed\n");
>
> return ret;
> }
> @@ -2013,6 +2027,40 @@ static int stm32_adc_remove(struct platform_device *pdev)
> return 0;
> }
>
> +#if defined(CONFIG_PM_SLEEP)
> +static int stm32_adc_suspend(struct device *dev)
> +{
> + struct stm32_adc *adc = dev_get_drvdata(dev);
> + struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> +
> + if (iio_buffer_enabled(indio_dev))
> + __stm32_adc_buffer_predisable(indio_dev);
> +
> + return pm_runtime_force_suspend(dev);
> +}
> +
> +static int stm32_adc_resume(struct device *dev)
> +{
> + struct stm32_adc *adc = dev_get_drvdata(dev);
> + struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> + int ret;
> +
> + ret = pm_runtime_force_resume(dev);
> + if (ret < 0)
> + return ret;
> +
> + if (!iio_buffer_enabled(indio_dev))
> + return 0;
> +
> + ret = stm32_adc_update_scan_mode(indio_dev,
> + indio_dev->active_scan_mask);
> + if (ret < 0)
> + return ret;
> +
> + return __stm32_adc_buffer_postenable(indio_dev);
> +}
> +#endif
> +
> #if defined(CONFIG_PM)
> static int stm32_adc_runtime_suspend(struct device *dev)
> {
> @@ -2026,8 +2074,7 @@ static int stm32_adc_runtime_resume(struct device *dev)
> #endif
>
> static const struct dev_pm_ops stm32_adc_pm_ops = {
> - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> - pm_runtime_force_resume)
> + SET_SYSTEM_SLEEP_PM_OPS(stm32_adc_suspend, stm32_adc_resume)
> SET_RUNTIME_PM_OPS(stm32_adc_runtime_suspend, stm32_adc_runtime_resume,
> NULL)
> };
WARNING: multiple messages have this Message-ID (diff)
From: jic23@kernel.org (Jonathan Cameron)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/3] iio: adc: stm32-adc: switch off running adc when going to low power
Date: Sun, 25 Nov 2018 13:17:35 +0000 [thread overview]
Message-ID: <20181125131735.616d6cf9@archlinux> (raw)
In-Reply-To: <1542708752-26163-4-git-send-email-fabrice.gasnier@st.com>
On Tue, 20 Nov 2018 11:12:32 +0100
Fabrice Gasnier <fabrice.gasnier@st.com> wrote:
> Switch off ADC when going to low power mode, in case it has been left
> running in buffer mode. Then re-enable it when resuming.
>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
My suspicion is that we have other drivers not correctly handing this
case, but as far as I can see you have it well covered here.
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> drivers/iio/adc/stm32-adc.c | 79 ++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 63 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
> index 32c9c61..2a9891c 100644
> --- a/drivers/iio/adc/stm32-adc.c
> +++ b/drivers/iio/adc/stm32-adc.c
> @@ -1518,7 +1518,7 @@ static int stm32_adc_dma_start(struct iio_dev *indio_dev)
> return 0;
> }
>
> -static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> +static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> {
> struct stm32_adc *adc = iio_priv(indio_dev);
> struct device *dev = indio_dev->dev.parent;
> @@ -1542,10 +1542,6 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> goto err_clr_trig;
> }
>
> - ret = iio_triggered_buffer_postenable(indio_dev);
> - if (ret < 0)
> - goto err_stop_dma;
> -
> /* Reset adc buffer index */
> adc->bufi = 0;
>
> @@ -1556,9 +1552,6 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
>
> return 0;
>
> -err_stop_dma:
> - if (adc->dma_chan)
> - dmaengine_terminate_all(adc->dma_chan);
> err_clr_trig:
> stm32_adc_set_trig(indio_dev, NULL);
> err_pm_put:
> @@ -1568,20 +1561,30 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> return ret;
> }
>
> -static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
> +static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + int ret;
> +
> + ret = iio_triggered_buffer_postenable(indio_dev);
> + if (ret < 0)
> + return ret;
> +
> + ret = __stm32_adc_buffer_postenable(indio_dev);
> + if (ret < 0)
> + iio_triggered_buffer_predisable(indio_dev);
> +
> + return ret;
> +}
> +
> +static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
> {
> struct stm32_adc *adc = iio_priv(indio_dev);
> struct device *dev = indio_dev->dev.parent;
> - int ret;
>
> adc->cfg->stop_conv(adc);
> if (!adc->dma_chan)
> stm32_adc_conv_irq_disable(adc);
>
> - ret = iio_triggered_buffer_predisable(indio_dev);
> - if (ret < 0)
> - dev_err(&indio_dev->dev, "predisable failed\n");
> -
> if (adc->dma_chan)
> dmaengine_terminate_all(adc->dma_chan);
>
> @@ -1590,6 +1593,17 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
>
> pm_runtime_mark_last_busy(dev);
> pm_runtime_put_autosuspend(dev);
> +}
> +
> +static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
> +{
> + int ret;
> +
> + __stm32_adc_buffer_predisable(indio_dev);
> +
> + ret = iio_triggered_buffer_predisable(indio_dev);
> + if (ret < 0)
> + dev_err(&indio_dev->dev, "predisable failed\n");
>
> return ret;
> }
> @@ -2013,6 +2027,40 @@ static int stm32_adc_remove(struct platform_device *pdev)
> return 0;
> }
>
> +#if defined(CONFIG_PM_SLEEP)
> +static int stm32_adc_suspend(struct device *dev)
> +{
> + struct stm32_adc *adc = dev_get_drvdata(dev);
> + struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> +
> + if (iio_buffer_enabled(indio_dev))
> + __stm32_adc_buffer_predisable(indio_dev);
> +
> + return pm_runtime_force_suspend(dev);
> +}
> +
> +static int stm32_adc_resume(struct device *dev)
> +{
> + struct stm32_adc *adc = dev_get_drvdata(dev);
> + struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> + int ret;
> +
> + ret = pm_runtime_force_resume(dev);
> + if (ret < 0)
> + return ret;
> +
> + if (!iio_buffer_enabled(indio_dev))
> + return 0;
> +
> + ret = stm32_adc_update_scan_mode(indio_dev,
> + indio_dev->active_scan_mask);
> + if (ret < 0)
> + return ret;
> +
> + return __stm32_adc_buffer_postenable(indio_dev);
> +}
> +#endif
> +
> #if defined(CONFIG_PM)
> static int stm32_adc_runtime_suspend(struct device *dev)
> {
> @@ -2026,8 +2074,7 @@ static int stm32_adc_runtime_resume(struct device *dev)
> #endif
>
> static const struct dev_pm_ops stm32_adc_pm_ops = {
> - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> - pm_runtime_force_resume)
> + SET_SYSTEM_SLEEP_PM_OPS(stm32_adc_suspend, stm32_adc_resume)
> SET_RUNTIME_PM_OPS(stm32_adc_runtime_suspend, stm32_adc_runtime_resume,
> NULL)
> };
next prev parent reply other threads:[~2018-11-26 0:08 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-20 10:12 [PATCH 0/3] iio: stm32-adc: add PM support Fabrice Gasnier
2018-11-20 10:12 ` Fabrice Gasnier
2018-11-20 10:12 ` [PATCH 1/3] iio: adc: stm32-adc: move self-calibration to prepare routine Fabrice Gasnier
2018-11-20 10:12 ` Fabrice Gasnier
2018-11-25 13:03 ` Jonathan Cameron
2018-11-25 13:03 ` Jonathan Cameron
2018-11-25 13:14 ` Jonathan Cameron
2018-11-25 13:14 ` Jonathan Cameron
2018-11-26 10:41 ` Fabrice Gasnier
2018-11-26 10:41 ` Fabrice Gasnier
2018-11-20 10:12 ` [PATCH 2/3] iio: adc: stm32-adc: add power management support Fabrice Gasnier
2018-11-20 10:12 ` Fabrice Gasnier
2018-11-25 13:16 ` Jonathan Cameron
2018-11-25 13:16 ` Jonathan Cameron
2018-11-20 10:12 ` [PATCH 3/3] iio: adc: stm32-adc: switch off running adc when going to low power Fabrice Gasnier
2018-11-20 10:12 ` Fabrice Gasnier
2018-11-25 13:17 ` Jonathan Cameron [this message]
2018-11-25 13:17 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181125131735.616d6cf9@archlinux \
--to=jic23@kernel.org \
--cc=alexandre.torgue@st.com \
--cc=fabrice.gasnier@st.com \
--cc=knaack.h@gmx.de \
--cc=lars@metafoo.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=pmeerw@pmeerw.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.