[PATCH v3 07/12] rtc: rzn1: Replace remove callback with devm_add_action_or_reset()

From: Prabhakar

Date: Mon Jul 06 2026 - 15:25:18 EST


From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>

Simplify the driver teardown by registering a managed cleanup action with
devm_add_action_or_reset(). This eliminates the explicit probe error path
and allows the .remove() callback to be dropped.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v2->v3:
- New patch to replace the remove callback with devm_add_action_or_reset().
---
drivers/rtc/rtc-rzn1.c | 56 +++++++++++++++++-------------------------
1 file changed, 23 insertions(+), 33 deletions(-)

diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
index a5283e680e36..1e6d26a122b8 100644
--- a/drivers/rtc/rtc-rzn1.c
+++ b/drivers/rtc/rtc-rzn1.c
@@ -378,6 +378,17 @@ static const struct rtc_class_ops rzn1_rtc_ops_scmp = {
.alarm_irq_enable = rzn1_rtc_alarm_irq_enable,
};

+static void rzn1_rtc_disable_hardware(void *data)
+{
+ struct device *dev = data;
+ struct rzn1_rtc *rtc = dev_get_drvdata(dev);
+
+ /* Disable all interrupts */
+ writel(0, rtc->base + RZN1_RTC_CTL1);
+
+ pm_runtime_put(dev);
+}
+
static int rzn1_rtc_probe(struct platform_device *pdev)
{
struct rzn1_rtc *rtc;
@@ -415,18 +426,19 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
if (ret < 0)
return ret;

+ ret = devm_add_action_or_reset(&pdev->dev, rzn1_rtc_disable_hardware, &pdev->dev);
+ if (ret)
+ return ret;
+
/* Only switch to scmp if we have an xtal clock with a valid rate and != 32768 */
xtal = devm_clk_get_optional(&pdev->dev, "xtal");
if (IS_ERR(xtal)) {
- ret = PTR_ERR(xtal);
- goto dis_runtime_pm;
+ return PTR_ERR(xtal);
} else if (xtal) {
rate = clk_get_rate(xtal);

- if (rate < 32000 || rate > BIT(22)) {
- ret = -EOPNOTSUPP;
- goto dis_runtime_pm;
- }
+ if (rate < 32000 || rate > BIT(22))
+ return -EOPNOTSUPP;

if (rate != 32768)
scmp_val = RZN1_RTC_CTL0_SLSB_SCMP;
@@ -439,7 +451,7 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL0, val,
!(val & RZN1_RTC_CTL0_CEST), 62, 123);
if (ret)
- goto dis_runtime_pm;
+ return ret;

/* Set desired modes leaving the controller disabled */
writel(RZN1_RTC_CTL0_AMPM | scmp_val, rtc->base + RZN1_RTC_CTL0);
@@ -462,14 +474,12 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc);
if (ret) {
dev_err(&pdev->dev, "RTC alarm interrupt not available\n");
- goto dis_runtime_pm;
+ return ret;
}

irq = platform_get_irq_byname_optional(pdev, "pps");
- if (irq == -EPROBE_DEFER) {
- ret = irq;
- goto dis_runtime_pm;
- }
+ if (irq == -EPROBE_DEFER)
+ return irq;
if (irq >= 0)
ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc);

@@ -479,26 +489,7 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n");
}

- ret = devm_rtc_register_device(rtc->rtcdev);
- if (ret)
- goto dis_runtime_pm;
-
- return 0;
-
-dis_runtime_pm:
- pm_runtime_put(&pdev->dev);
-
- return ret;
-}
-
-static void rzn1_rtc_remove(struct platform_device *pdev)
-{
- struct rzn1_rtc *rtc = platform_get_drvdata(pdev);
-
- /* Disable all interrupts */
- writel(0, rtc->base + RZN1_RTC_CTL1);
-
- pm_runtime_put(&pdev->dev);
+ return devm_rtc_register_device(rtc->rtcdev);
}

static const struct of_device_id rzn1_rtc_of_match[] = {
@@ -509,7 +500,6 @@ MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match);

static struct platform_driver rzn1_rtc_driver = {
.probe = rzn1_rtc_probe,
- .remove = rzn1_rtc_remove,
.driver = {
.name = "rzn1-rtc",
.of_match_table = rzn1_rtc_of_match,
--
2.54.0