Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Claudiu Beznea and committed by
Jonathan Cameron
563cf94f 6dd8a771

+70
+70
drivers/iio/adc/rzg2l_adc.c
··· 88 88 struct completion completion; 89 89 struct mutex lock; 90 90 u16 last_val[RZG2L_ADC_MAX_CHANNELS]; 91 + bool was_rpm_active; 91 92 }; 92 93 93 94 /** ··· 530 529 return 0; 531 530 } 532 531 532 + static int rzg2l_adc_suspend(struct device *dev) 533 + { 534 + struct iio_dev *indio_dev = dev_get_drvdata(dev); 535 + struct rzg2l_adc *adc = iio_priv(indio_dev); 536 + struct reset_control_bulk_data resets[] = { 537 + { .rstc = adc->presetn }, 538 + { .rstc = adc->adrstn }, 539 + }; 540 + int ret; 541 + 542 + if (pm_runtime_suspended(dev)) { 543 + adc->was_rpm_active = false; 544 + } else { 545 + ret = pm_runtime_force_suspend(dev); 546 + if (ret) 547 + return ret; 548 + adc->was_rpm_active = true; 549 + } 550 + 551 + ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets); 552 + if (ret) 553 + goto rpm_restore; 554 + 555 + return 0; 556 + 557 + rpm_restore: 558 + if (adc->was_rpm_active) 559 + pm_runtime_force_resume(dev); 560 + 561 + return ret; 562 + } 563 + 564 + static int rzg2l_adc_resume(struct device *dev) 565 + { 566 + struct iio_dev *indio_dev = dev_get_drvdata(dev); 567 + struct rzg2l_adc *adc = iio_priv(indio_dev); 568 + struct reset_control_bulk_data resets[] = { 569 + { .rstc = adc->adrstn }, 570 + { .rstc = adc->presetn }, 571 + }; 572 + int ret; 573 + 574 + ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets); 575 + if (ret) 576 + return ret; 577 + 578 + if (adc->was_rpm_active) { 579 + ret = pm_runtime_force_resume(dev); 580 + if (ret) 581 + goto resets_restore; 582 + } 583 + 584 + ret = rzg2l_adc_hw_init(dev, adc); 585 + if (ret) 586 + goto rpm_restore; 587 + 588 + return 0; 589 + 590 + rpm_restore: 591 + if (adc->was_rpm_active) { 592 + pm_runtime_mark_last_busy(dev); 593 + pm_runtime_put_autosuspend(dev); 594 + } 595 + resets_restore: 596 + reset_control_bulk_assert(ARRAY_SIZE(resets), resets); 597 + return ret; 598 + } 599 + 533 600 static const struct dev_pm_ops rzg2l_adc_pm_ops = { 534 601 RUNTIME_PM_OPS(rzg2l_adc_pm_runtime_suspend, rzg2l_adc_pm_runtime_resume, NULL) 602 + SYSTEM_SLEEP_PM_OPS(rzg2l_adc_suspend, rzg2l_adc_resume) 535 603 }; 536 604 537 605 static struct platform_driver rzg2l_adc_driver = {