mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-06 21:14:18 +00:00
iio: adc: rzg2l_adc: Add suspend/resume support
The Renesas RZ/G3S SoC features a power-saving mode where power to most of the SoC components is turned off, including the ADC IP. Suspend/resume support has been added to the rzg2l_adc driver to restore functionality after resuming from this power-saving mode. During suspend, the ADC resets are asserted, and the ADC is powered down. On resume, the ADC resets are de-asserted, the hardware is re-initialized, and the ADC power is restored using the runtime PM APIs. Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Link: https://patch.msgid.link/20241206111337.726244-12-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
6dd8a77125
commit
563cf94f93
@ -88,6 +88,7 @@ struct rzg2l_adc {
|
||||
struct completion completion;
|
||||
struct mutex lock;
|
||||
u16 last_val[RZG2L_ADC_MAX_CHANNELS];
|
||||
bool was_rpm_active;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -529,8 +530,77 @@ static int rzg2l_adc_pm_runtime_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct rzg2l_adc *adc = iio_priv(indio_dev);
|
||||
struct reset_control_bulk_data resets[] = {
|
||||
{ .rstc = adc->presetn },
|
||||
{ .rstc = adc->adrstn },
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
adc->was_rpm_active = false;
|
||||
} else {
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
adc->was_rpm_active = true;
|
||||
}
|
||||
|
||||
ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
|
||||
if (ret)
|
||||
goto rpm_restore;
|
||||
|
||||
return 0;
|
||||
|
||||
rpm_restore:
|
||||
if (adc->was_rpm_active)
|
||||
pm_runtime_force_resume(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct rzg2l_adc *adc = iio_priv(indio_dev);
|
||||
struct reset_control_bulk_data resets[] = {
|
||||
{ .rstc = adc->adrstn },
|
||||
{ .rstc = adc->presetn },
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adc->was_rpm_active) {
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
goto resets_restore;
|
||||
}
|
||||
|
||||
ret = rzg2l_adc_hw_init(dev, adc);
|
||||
if (ret)
|
||||
goto rpm_restore;
|
||||
|
||||
return 0;
|
||||
|
||||
rpm_restore:
|
||||
if (adc->was_rpm_active) {
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
resets_restore:
|
||||
reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rzg2l_adc_pm_ops = {
|
||||
RUNTIME_PM_OPS(rzg2l_adc_pm_runtime_suspend, rzg2l_adc_pm_runtime_resume, NULL)
|
||||
SYSTEM_SLEEP_PM_OPS(rzg2l_adc_suspend, rzg2l_adc_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver rzg2l_adc_driver = {
|
||||
|
Loading…
Reference in New Issue
Block a user