Skip to content

Commit 563cf94

Browse files
claudiubezneajic23
authored andcommitted
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>
1 parent 6dd8a77 commit 563cf94

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

drivers/iio/adc/rzg2l_adc.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct rzg2l_adc {
8888
struct completion completion;
8989
struct mutex lock;
9090
u16 last_val[RZG2L_ADC_MAX_CHANNELS];
91+
bool was_rpm_active;
9192
};
9293

9394
/**
@@ -529,8 +530,77 @@ static int rzg2l_adc_pm_runtime_resume(struct device *dev)
529530
return 0;
530531
}
531532

533+
static int rzg2l_adc_suspend(struct device *dev)
534+
{
535+
struct iio_dev *indio_dev = dev_get_drvdata(dev);
536+
struct rzg2l_adc *adc = iio_priv(indio_dev);
537+
struct reset_control_bulk_data resets[] = {
538+
{ .rstc = adc->presetn },
539+
{ .rstc = adc->adrstn },
540+
};
541+
int ret;
542+
543+
if (pm_runtime_suspended(dev)) {
544+
adc->was_rpm_active = false;
545+
} else {
546+
ret = pm_runtime_force_suspend(dev);
547+
if (ret)
548+
return ret;
549+
adc->was_rpm_active = true;
550+
}
551+
552+
ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
553+
if (ret)
554+
goto rpm_restore;
555+
556+
return 0;
557+
558+
rpm_restore:
559+
if (adc->was_rpm_active)
560+
pm_runtime_force_resume(dev);
561+
562+
return ret;
563+
}
564+
565+
static int rzg2l_adc_resume(struct device *dev)
566+
{
567+
struct iio_dev *indio_dev = dev_get_drvdata(dev);
568+
struct rzg2l_adc *adc = iio_priv(indio_dev);
569+
struct reset_control_bulk_data resets[] = {
570+
{ .rstc = adc->adrstn },
571+
{ .rstc = adc->presetn },
572+
};
573+
int ret;
574+
575+
ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
576+
if (ret)
577+
return ret;
578+
579+
if (adc->was_rpm_active) {
580+
ret = pm_runtime_force_resume(dev);
581+
if (ret)
582+
goto resets_restore;
583+
}
584+
585+
ret = rzg2l_adc_hw_init(dev, adc);
586+
if (ret)
587+
goto rpm_restore;
588+
589+
return 0;
590+
591+
rpm_restore:
592+
if (adc->was_rpm_active) {
593+
pm_runtime_mark_last_busy(dev);
594+
pm_runtime_put_autosuspend(dev);
595+
}
596+
resets_restore:
597+
reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
598+
return ret;
599+
}
600+
532601
static const struct dev_pm_ops rzg2l_adc_pm_ops = {
533602
RUNTIME_PM_OPS(rzg2l_adc_pm_runtime_suspend, rzg2l_adc_pm_runtime_resume, NULL)
603+
SYSTEM_SLEEP_PM_OPS(rzg2l_adc_suspend, rzg2l_adc_resume)
534604
};
535605

536606
static struct platform_driver rzg2l_adc_driver = {

0 commit comments

Comments
 (0)