From 384150d7a5b60c1086790a8ee07b0629f906cca2 Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Tue, 21 Oct 2025 18:35:59 +0800 Subject: [PATCH 01/34] rtc: amlogic-a4: fix double free caused by devm The clock obtained via devm_clk_get_enabled() is automatically managed by devres and will be disabled and freed on driver detach. Manually calling clk_disable_unprepare() in error path and remove function causes double free. Remove the redundant clk_disable_unprepare() calls from the probe error path and aml_rtc_remove(), allowing the devm framework to automatically manage the clock lifecycle. Fixes: c89ac9182ee2 ("rtc: support for the Amlogic on-chip RTC") Signed-off-by: Haotian Zhang Reviewed-by: Xianwei Zhao Link: https://patch.msgid.link/20251021103559.1903-1-vulab@iscas.ac.cn Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-amlogic-a4.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c index 1928b29c1045..a993d35e1d6b 100644 --- a/drivers/rtc/rtc-amlogic-a4.c +++ b/drivers/rtc/rtc-amlogic-a4.c @@ -390,7 +390,6 @@ static int aml_rtc_probe(struct platform_device *pdev) return 0; err_clk: - clk_disable_unprepare(rtc->sys_clk); device_init_wakeup(dev, false); return ret; @@ -423,9 +422,6 @@ static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops, static void aml_rtc_remove(struct platform_device *pdev) { - struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev); - - clk_disable_unprepare(rtc->sys_clk); device_init_wakeup(&pdev->dev, false); } From ed14c9c68b407c320310159d0057a79e024a1b63 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 31 Oct 2025 21:47:23 +0100 Subject: [PATCH 02/34] rtc: amlogic-a4: simplify probe Use devm_device_init_wakeup to simplify probe and remove .remove as it is now empty. Also remove the unnecessary error string as there are no error path without an error message in devm_rtc_register_device. Reviewed-by: Xianwei Zhao Link: https://patch.msgid.link/20251031204724.756857-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-amlogic-a4.c | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c index a993d35e1d6b..123fb372fc9f 100644 --- a/drivers/rtc/rtc-amlogic-a4.c +++ b/drivers/rtc/rtc-amlogic-a4.c @@ -361,38 +361,26 @@ static int aml_rtc_probe(struct platform_device *pdev) "failed to get_enable rtc sys clk\n"); aml_rtc_init(rtc); - device_init_wakeup(dev, true); + devm_device_init_wakeup(dev); platform_set_drvdata(pdev, rtc); rtc->rtc_dev = devm_rtc_allocate_device(dev); - if (IS_ERR(rtc->rtc_dev)) { - ret = PTR_ERR(rtc->rtc_dev); - goto err_clk; - } + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler, IRQF_ONESHOT, "aml-rtc alarm", rtc); if (ret) { dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n", rtc->irq, ret); - goto err_clk; + return ret; } rtc->rtc_dev->ops = &aml_rtc_ops; rtc->rtc_dev->range_min = 0; rtc->rtc_dev->range_max = U32_MAX; - ret = devm_rtc_register_device(rtc->rtc_dev); - if (ret) { - dev_err_probe(&pdev->dev, ret, "Failed to register RTC device: %d\n", ret); - goto err_clk; - } - - return 0; -err_clk: - device_init_wakeup(dev, false); - - return ret; + return devm_rtc_register_device(rtc->rtc_dev); } #ifdef CONFIG_PM_SLEEP @@ -420,11 +408,6 @@ static int aml_rtc_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops, aml_rtc_suspend, aml_rtc_resume); -static void aml_rtc_remove(struct platform_device *pdev) -{ - device_init_wakeup(&pdev->dev, false); -} - static const struct aml_rtc_config a5_rtc_config = { }; @@ -447,7 +430,6 @@ MODULE_DEVICE_TABLE(of, aml_rtc_device_id); static struct platform_driver aml_rtc_driver = { .probe = aml_rtc_probe, - .remove = aml_rtc_remove, .driver = { .name = "aml-rtc", .pm = &aml_rtc_pm_ops, From ea57f047985370e9e172013ac8b56f585b3082cf Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:03 +0100 Subject: [PATCH 03/34] rtc: sa1100: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-1-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sa1100.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 1ad93648d69c..26b2f4184ecc 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -40,8 +40,6 @@ #define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_TRIM 0 -#define RTC_FREQ 1024 - static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) { @@ -202,7 +200,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info) } info->rtc->ops = &sa1100_rtc_ops; - info->rtc->max_user_freq = RTC_FREQ; info->rtc->range_max = U32_MAX; ret = devm_rtc_register_device(info->rtc); From 56d9df41ef1847ed0523f57ec6117649d581401d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:04 +0100 Subject: [PATCH 04/34] rtc: ds1685: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Acked-by: Joshua Kinard Link: https://patch.msgid.link/20251101-max_user_freq-v1-2-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1685.c | 3 --- include/linux/rtc/ds1685.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 97423f1d0361..5fc8e36b1abf 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -1268,9 +1268,6 @@ ds1685_rtc_probe(struct platform_device *pdev) rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc_dev->range_max = RTC_TIMESTAMP_END_2099; - /* Maximum periodic rate is 8192Hz (0.122070ms). */ - rtc_dev->max_user_freq = RTC_MAX_USER_FREQ; - /* See if the platform doesn't support UIE. */ if (pdata->uie_unsupported) clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc_dev->features); diff --git a/include/linux/rtc/ds1685.h b/include/linux/rtc/ds1685.h index 01da4582db6d..8ec0ebfaef04 100644 --- a/include/linux/rtc/ds1685.h +++ b/include/linux/rtc/ds1685.h @@ -324,7 +324,6 @@ struct ds1685_rtc_platform_data { #define RTC_SQW_2HZ 0x0f /* 0 1 1 1 1 */ #define RTC_SQW_0HZ 0x00 /* 0 0 0 0 0 */ #define RTC_SQW_32768HZ 32768 /* 1 - - - - */ -#define RTC_MAX_USER_FREQ 8192 /* From 90b033290dd3c8a404abea84e75a8d6597ca00c3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:05 +0100 Subject: [PATCH 05/34] rtc: pic32: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-3-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pic32.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c index 2812da2c50c5..52c11532bc3a 100644 --- a/drivers/rtc/rtc-pic32.c +++ b/drivers/rtc/rtc-pic32.c @@ -340,8 +340,6 @@ static int pic32_rtc_probe(struct platform_device *pdev) if (ret) goto err_nortc; - pdata->rtc->max_user_freq = 128; - pic32_rtc_setfreq(&pdev->dev, 1); ret = devm_request_irq(&pdev->dev, pdata->alarm_irq, pic32_rtc_alarmirq, 0, From 358867b551660ac7d0987fe5fad8518cbfd5e415 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:06 +0100 Subject: [PATCH 06/34] rtc: renesas-rtca3: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Reviewed-by: Claudiu Beznea Link: https://patch.msgid.link/20251101-max_user_freq-v1-4-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-renesas-rtca3.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c index ab816bdf0d77..a238ead6cf1a 100644 --- a/drivers/rtc/rtc-renesas-rtca3.c +++ b/drivers/rtc/rtc-renesas-rtca3.c @@ -772,7 +772,6 @@ static int rtca3_probe(struct platform_device *pdev) return PTR_ERR(priv->rtc_dev); priv->rtc_dev->ops = &rtca3_ops; - priv->rtc_dev->max_user_freq = 256; priv->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; priv->rtc_dev->range_max = RTC_TIMESTAMP_END_2099; From 80101193ff6c2cb3a332e12653c585d806890194 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:07 +0100 Subject: [PATCH 07/34] rtc: rv3028: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-5-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv3028.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index c2a531f0e125..d96f6bb68850 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -1023,8 +1023,6 @@ static int rv3028_probe(struct i2c_client *client) eeprom_cfg.priv = rv3028; devm_rtc_nvmem_register(rv3028->rtc, &eeprom_cfg); - rv3028->rtc->max_user_freq = 1; - #ifdef CONFIG_COMMON_CLK rv3028_clkout_register_clk(rv3028, client); #endif From 893a59632647c432d52697fadc6e56143cd6bec6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:08 +0100 Subject: [PATCH 08/34] rtc: rv3032: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-6-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv3032.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c index b8376bd1d905..6c09da7738e1 100644 --- a/drivers/rtc/rtc-rv3032.c +++ b/drivers/rtc/rtc-rv3032.c @@ -968,8 +968,6 @@ static int rv3032_probe(struct i2c_client *client) eeprom_cfg.priv = rv3032; devm_rtc_nvmem_register(rv3032->rtc, &eeprom_cfg); - rv3032->rtc->max_user_freq = 1; - #ifdef CONFIG_COMMON_CLK rv3032_clkout_register_clk(rv3032, client); #endif From b1d53c187e21feef86d89f077440684e17a7176a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:09 +0100 Subject: [PATCH 09/34] rtc: rv8803: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-7-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv8803.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 1327251e527c..4e9e04cbec89 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -738,8 +738,6 @@ static int rv8803_probe(struct i2c_client *client) devm_rtc_nvmem_register(rv8803->rtc, &nvmem_cfg); - rv8803->rtc->max_user_freq = 1; - return 0; } From 69dd36c2009fc3f898d3373728d99f8c4f7dcfb3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:10 +0100 Subject: [PATCH 10/34] rtc: rx6110: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-8-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx6110.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c index 7c423d672adb..07bf35ac8d79 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -324,8 +324,6 @@ static int rx6110_probe(struct rx6110_data *rx6110, struct device *dev) if (err) return err; - rx6110->rtc->max_user_freq = 1; - return 0; } From 48eca7ec00e6032fd463c3ecfcca8c159c77cc17 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:11 +0100 Subject: [PATCH 11/34] rtc: rx8010: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-9-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8010.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index 2b6198d1cf81..171240e50f48 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -412,7 +412,6 @@ static int rx8010_probe(struct i2c_client *client) } rx8010->rtc->ops = &rx8010_rtc_ops; - rx8010->rtc->max_user_freq = 1; rx8010->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rx8010->rtc->range_max = RTC_TIMESTAMP_END_2099; From 9115815afbc3815391a82d192f9b12aaff1e4ce8 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:12 +0100 Subject: [PATCH 12/34] rtc: rx8025: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Link: https://patch.msgid.link/20251101-max_user_freq-v1-10-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8025.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index aabe62c283a1..07119985fa83 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -565,8 +565,6 @@ static int rx8025_probe(struct i2c_client *client) clear_bit(RTC_FEATURE_ALARM, rx8025->rtc->features); } - rx8025->rtc->max_user_freq = 1; - set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rx8025->rtc->features); clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rx8025->rtc->features); From 1fd7078f0c69e0f9a33172c64232d97b790f72ac Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 1 Nov 2025 01:45:13 +0100 Subject: [PATCH 13/34] rtc: sh: stop setting max_user_freq max_user_freq has not been related to the hardware RTC since commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events"). Stop setting it from individual driver to avoid confusing new contributors. Reviewed-by: Wolfram Sang Link: https://patch.msgid.link/20251101-max_user_freq-v1-11-c9a274fd6883@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sh.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 619800a00479..0510dc64c3e2 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -423,7 +423,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev) writeb(tmp, rtc->regbase + RCR1); rtc->rtc_dev->ops = &sh_rtc_ops; - rtc->rtc_dev->max_user_freq = 256; if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) { rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900; From e1794c59730a68d6ece55430766cc51720ac653a Mon Sep 17 00:00:00 2001 From: CL Wang Date: Mon, 15 Sep 2025 11:14:37 +0800 Subject: [PATCH 14/34] dt-bindings: rtc: Add support for ATCRTC100 RTC Document Device Tree bindings for the Andes ATCRTC100 Real-Time Clock. Signed-off-by: CL Wang Reviewed-by: Conor Dooley Link: https://patch.msgid.link/20250915031439.2680364-2-cl634@andestech.com Signed-off-by: Alexandre Belloni --- .../bindings/rtc/andestech,atcrtc100.yaml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/andestech,atcrtc100.yaml diff --git a/Documentation/devicetree/bindings/rtc/andestech,atcrtc100.yaml b/Documentation/devicetree/bindings/rtc/andestech,atcrtc100.yaml new file mode 100644 index 000000000000..ec0a736793c7 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/andestech,atcrtc100.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/andestech,atcrtc100.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Andes ATCRTC100 Real-Time Clock + +maintainers: + - CL Wang + +allOf: + - $ref: rtc.yaml# + +properties: + compatible: + enum: + - andestech,atcrtc100 + + reg: + maxItems: 1 + + interrupts: + items: + - description: Periodic timekeeping interrupt + - description: RTC alarm interrupt + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + + rtc@f0300000 { + compatible = "andestech,atcrtc100"; + reg = <0xf0300000 0x100>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH>, <2 IRQ_TYPE_LEVEL_HIGH>; + }; From a603092d5be1b24af19676ad8a4a7974d426b7f8 Mon Sep 17 00:00:00 2001 From: CL Wang Date: Mon, 15 Sep 2025 11:14:38 +0800 Subject: [PATCH 15/34] MAINTAINERS: Add entry for ATCRTC100 RTC driver Add support entry for the Andes ATCRTC100 RTC driver in the MAINTAINERS file. Signed-off-by: CL Wang Link: https://patch.msgid.link/20250915031439.2680364-3-cl634@andestech.com Signed-off-by: Alexandre Belloni --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 46126ce2f968..da1e75d4cb9e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3946,6 +3946,12 @@ F: drivers/power/reset/atc260x-poweroff.c F: drivers/regulator/atc260x-regulator.c F: include/linux/mfd/atc260x/* +ATCRTC100 RTC DRIVER +M: CL Wang +S: Supported +F: Documentation/devicetree/bindings/rtc/andestech,atcrtc100.yaml +F: drivers/rtc/rtc-atcrtc100.c + ATHEROS 71XX/9XXX GPIO DRIVER M: Alban Bedel S: Maintained From 7adca706fe16581c899317196f5f40d3ad5ccc84 Mon Sep 17 00:00:00 2001 From: CL Wang Date: Mon, 15 Sep 2025 11:14:39 +0800 Subject: [PATCH 16/34] rtc: atcrtc100: Add ATCRTC100 RTC driver RTC driver for Andes ATCRTC100 Real-Time Clock. Signed-off-by: CL Wang Link: https://patch.msgid.link/20250915031439.2680364-4-cl634@andestech.com Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 15 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-atcrtc100.c | 379 ++++++++++++++++++++++++++++++++++++ 3 files changed, 395 insertions(+) create mode 100644 drivers/rtc/rtc-atcrtc100.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2933c41c77c8..5d509254824e 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1063,6 +1063,21 @@ config RTC_DRV_ALPHA Direct support for the real-time clock found on every Alpha system, specifically MC146818 compatibles. If in doubt, say Y. +config RTC_DRV_ATCRTC100 + tristate "Andes ATCRTC100" + depends on ARCH_ANDES || COMPILE_TEST + select REGMAP_MMIO + help + If you say yes here you will get support for the Andes ATCRTC100 + RTC driver. + + This driver provides support for the Andes ATCRTC100 real-time clock + device. It allows setting and retrieving the time and date, as well + as setting alarms. + + To compile this driver as a module, choose M here: the module will + be called rtc-atcrtc100. + config RTC_DRV_DS1216 tristate "Dallas DS1216" depends on SNI_RM diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 8221bda6e6dc..f1b5c3d123c0 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o +obj-$(CONFIG_RTC_DRV_ATCRTC100) += rtc-atcrtc100.o obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o obj-$(CONFIG_RTC_DRV_BBNSM) += rtc-nxp-bbnsm.o obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o diff --git a/drivers/rtc/rtc-atcrtc100.c b/drivers/rtc/rtc-atcrtc100.c new file mode 100644 index 000000000000..51933ae1a2fa --- /dev/null +++ b/drivers/rtc/rtc-atcrtc100.c @@ -0,0 +1,379 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Andes ATCRTC100 real time clock. + * + * Copyright (C) 2025 Andes Technology Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register Offsets */ +#define RTC_ID 0x00 /* ID and Revision Register */ +#define RTC_RSV 0x04 /* Reserved Register */ +#define RTC_CNT 0x10 /* Counter Register */ +#define RTC_ALM 0x14 /* Alarm Register */ +#define RTC_CR 0x18 /* Control Register */ +#define RTC_STA 0x1C /* Status Register */ +#define RTC_TRIM 0x20 /* Digital Trimming Register */ + +/* RTC_ID Register */ +#define ID_MSK GENMASK(31, 8) +#define ID_ATCRTC100 0x030110 + +/* RTC_CNT and RTC_ALM Register Fields */ +#define SEC_MSK GENMASK(5, 0) +#define MIN_MSK GENMASK(11, 6) +#define HOUR_MSK GENMASK(16, 12) +#define DAY_MSK GENMASK(31, 17) +#define RTC_SEC_GET(x) FIELD_GET(SEC_MSK, x) +#define RTC_MIN_GET(x) FIELD_GET(MIN_MSK, x) +#define RTC_HOUR_GET(x) FIELD_GET(HOUR_MSK, x) +#define RTC_DAY_GET(x) FIELD_GET(DAY_MSK, x) +#define RTC_SEC_SET(x) FIELD_PREP(SEC_MSK, x) +#define RTC_MIN_SET(x) FIELD_PREP(MIN_MSK, x) +#define RTC_HOUR_SET(x) FIELD_PREP(HOUR_MSK, x) +#define RTC_DAY_SET(x) FIELD_PREP(DAY_MSK, x) + +/* RTC_CR Register Bits */ +#define RTC_EN BIT(0) /* RTC Enable */ +#define ALARM_WAKEUP BIT(1) /* Alarm Wakeup Enable */ +#define ALARM_INT BIT(2) /* Alarm Interrupt Enable */ +#define DAY_INT BIT(3) /* Day Interrupt Enable */ +#define HOUR_INT BIT(4) /* Hour Interrupt Enable */ +#define MIN_INT BIT(5) /* Minute Interrupt Enable */ +#define SEC_INT BIT(6) /* Second Periodic Interrupt Enable */ +#define HSEC_INT BIT(7) /* Half-Second Periodic Interrupt Enable */ + +/* RTC_STA Register Bits */ +#define WRITE_DONE BIT(16) /* Register write completion status */ + +/* Time conversion macro */ +#define ATCRTC_TIME_TO_SEC(D, H, M, S) \ + ((time64_t)(D) * 86400 + (H) * 3600 + (M) * 60 + (S)) + +/* Timeout for waiting for the write_done bit */ +#define ATCRTC_TIMEOUT_US 1000000 +#define ATCRTC_TIMEOUT_USLEEP_MIN 20 +#define ATCRTC_TIMEOUT_USLEEP_MAX 30 + +struct atcrtc_dev { + struct rtc_device *rtc_dev; + struct regmap *regmap; + struct work_struct rtc_work; + unsigned int alarm_irq; + bool alarm_en; +}; + +static const struct regmap_config atcrtc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = RTC_TRIM, + .cache_type = REGCACHE_NONE, +}; + +/** + * atcrtc_check_write_done - Wait for RTC registers to be synchronized. + * @rtc: Pointer to the atcrtc_dev structure. + * + * The WriteDone bit in the status register indicates the synchronization + * progress of RTC register updates. This bit is cleared to zero whenever + * any RTC control register (Counter, Alarm, Control, etc.) is written. + * It returns to one only after all previous updates have been fully + * synchronized to the RTC clock domain. This function polls the WriteDone + * bit with a timeout to ensure the device is ready for the next operation. + * + * Return: 0 on success, or -EBUSY on timeout. + */ +static int atcrtc_check_write_done(struct atcrtc_dev *rtc) +{ + unsigned int val; + + /* + * Using read_poll_timeout is more efficient than a manual loop + * with usleep_range. + */ + return regmap_read_poll_timeout(rtc->regmap, RTC_STA, val, + val & WRITE_DONE, + ATCRTC_TIMEOUT_USLEEP_MIN, + ATCRTC_TIMEOUT_US); +} + +static irqreturn_t atcrtc_alarm_isr(int irq, void *dev) +{ + struct atcrtc_dev *rtc = dev; + unsigned int status; + + regmap_read(rtc->regmap, RTC_STA, &status); + if (status & ALARM_INT) { + regmap_write(rtc->regmap, RTC_STA, ALARM_INT); + rtc->alarm_en = false; + schedule_work(&rtc->rtc_work); + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static int atcrtc_alarm_irq_enable(struct device *dev, unsigned int enable) +{ + struct atcrtc_dev *rtc = dev_get_drvdata(dev); + unsigned int mask; + int ret; + + ret = atcrtc_check_write_done(rtc); + if (ret) + return ret; + + mask = ALARM_WAKEUP | ALARM_INT; + regmap_update_bits(rtc->regmap, RTC_CR, mask, enable ? mask : 0); + + return 0; +} + +static void atcrtc_alarm_clear(struct work_struct *work) +{ + struct atcrtc_dev *rtc = + container_of(work, struct atcrtc_dev, rtc_work); + int ret; + + rtc_lock(rtc->rtc_dev); + + if (!rtc->alarm_en) { + ret = atcrtc_check_write_done(rtc); + if (ret) + dev_info(&rtc->rtc_dev->dev, + "failed to sync before clearing alarm: %d\n", + ret); + else + regmap_update_bits(rtc->regmap, RTC_CR, + ALARM_WAKEUP | ALARM_INT, 0); + } + rtc_unlock(rtc->rtc_dev); +} + +static int atcrtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct atcrtc_dev *rtc = dev_get_drvdata(dev); + time64_t time; + unsigned int rtc_cnt; + + if (!regmap_test_bits(rtc->regmap, RTC_CR, RTC_EN)) + return -EIO; + + regmap_read(rtc->regmap, RTC_CNT, &rtc_cnt); + time = ATCRTC_TIME_TO_SEC(RTC_DAY_GET(rtc_cnt), + RTC_HOUR_GET(rtc_cnt), + RTC_MIN_GET(rtc_cnt), + RTC_SEC_GET(rtc_cnt)); + rtc_time64_to_tm(time, tm); + + return 0; +} + +static int atcrtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct atcrtc_dev *rtc = dev_get_drvdata(dev); + time64_t time; + unsigned int counter; + unsigned int day; + int ret; + + time = rtc_tm_to_time64(tm); + day = div_s64(time, 86400); + counter = RTC_DAY_SET(day) | + RTC_HOUR_SET(tm->tm_hour) | + RTC_MIN_SET(tm->tm_min) | + RTC_SEC_SET(tm->tm_sec); + ret = atcrtc_check_write_done(rtc); + if (ret) + return ret; + regmap_write(rtc->regmap, RTC_CNT, counter); + + ret = atcrtc_check_write_done(rtc); + if (ret) + return ret; + regmap_update_bits(rtc->regmap, RTC_CR, RTC_EN, RTC_EN); + + return 0; +} + +static int atcrtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct atcrtc_dev *rtc = dev_get_drvdata(dev); + struct rtc_time *tm = &wkalrm->time; + unsigned int rtc_alarm; + + wkalrm->enabled = regmap_test_bits(rtc->regmap, RTC_CR, ALARM_INT); + regmap_read(rtc->regmap, RTC_ALM, &rtc_alarm); + tm->tm_hour = RTC_HOUR_GET(rtc_alarm); + tm->tm_min = RTC_MIN_GET(rtc_alarm); + tm->tm_sec = RTC_SEC_GET(rtc_alarm); + + /* The RTC alarm does not support day/month/year fields */ + tm->tm_mday = -1; + tm->tm_mon = -1; + tm->tm_year = -1; + + return 0; +} + +static int atcrtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct atcrtc_dev *rtc = dev_get_drvdata(dev); + struct rtc_time *tm = &wkalrm->time; + unsigned int rtc_alarm; + int ret; + + /* Disable alarm first before setting a new one */ + ret = atcrtc_alarm_irq_enable(dev, 0); + if (ret) + return ret; + + rtc->alarm_en = false; + + rtc_alarm = RTC_SEC_SET(tm->tm_sec) | + RTC_MIN_SET(tm->tm_min) | + RTC_HOUR_SET(tm->tm_hour); + + ret = atcrtc_check_write_done(rtc); + if (ret) + return ret; + + regmap_write(rtc->regmap, RTC_ALM, rtc_alarm); + + rtc->alarm_en = wkalrm->enabled; + ret = atcrtc_alarm_irq_enable(dev, wkalrm->enabled); + + return ret; +} + +static const struct rtc_class_ops rtc_ops = { + .read_time = atcrtc_read_time, + .set_time = atcrtc_set_time, + .read_alarm = atcrtc_read_alarm, + .set_alarm = atcrtc_set_alarm, + .alarm_irq_enable = atcrtc_alarm_irq_enable, +}; + +static int atcrtc_probe(struct platform_device *pdev) +{ + struct atcrtc_dev *atcrtc_dev; + void __iomem *reg_base; + unsigned int rtc_id; + int ret; + + atcrtc_dev = devm_kzalloc(&pdev->dev, sizeof(*atcrtc_dev), GFP_KERNEL); + if (!atcrtc_dev) + return -ENOMEM; + platform_set_drvdata(pdev, atcrtc_dev); + + reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg_base)) + return dev_err_probe(&pdev->dev, PTR_ERR(reg_base), + "Failed to map I/O space\n"); + + atcrtc_dev->regmap = devm_regmap_init_mmio(&pdev->dev, + reg_base, + &atcrtc_regmap_config); + if (IS_ERR(atcrtc_dev->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->regmap), + "Failed to initialize regmap\n"); + + regmap_read(atcrtc_dev->regmap, RTC_ID, &rtc_id); + if (FIELD_GET(ID_MSK, rtc_id) != ID_ATCRTC100) + return dev_err_probe(&pdev->dev, -ENODEV, + "Failed to initialize RTC: unsupported hardware ID 0x%x\n", + rtc_id); + + atcrtc_dev->alarm_irq = platform_get_irq(pdev, 1); + if (atcrtc_dev->alarm_irq < 0) + return dev_err_probe(&pdev->dev, atcrtc_dev->alarm_irq, + "Failed to get IRQ for alarm\n"); + ret = devm_request_irq(&pdev->dev, + atcrtc_dev->alarm_irq, + atcrtc_alarm_isr, + 0, + "atcrtc_alarm", + atcrtc_dev); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "Failed to request IRQ %d for alarm\n", + atcrtc_dev->alarm_irq); + + atcrtc_dev->rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(atcrtc_dev->rtc_dev)) + return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->rtc_dev), + "Failed to allocate RTC device\n"); + + set_bit(RTC_FEATURE_ALARM, atcrtc_dev->rtc_dev->features); + ret = device_init_wakeup(&pdev->dev, true); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "Failed to initialize wake capability\n"); + + ret = dev_pm_set_wake_irq(&pdev->dev, atcrtc_dev->alarm_irq); + if (ret) { + device_init_wakeup(&pdev->dev, false); + return dev_err_probe(&pdev->dev, ret, + "Failed to set wake IRQ\n"); + } + + atcrtc_dev->rtc_dev->ops = &rtc_ops; + + INIT_WORK(&atcrtc_dev->rtc_work, atcrtc_alarm_clear); + return devm_rtc_register_device(atcrtc_dev->rtc_dev); +} + +static int atcrtc_resume(struct device *dev) +{ + struct atcrtc_dev *rtc = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(rtc->alarm_irq); + + return 0; +} + +static int atcrtc_suspend(struct device *dev) +{ + struct atcrtc_dev *rtc = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(rtc->alarm_irq); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(atcrtc_pm_ops, atcrtc_suspend, atcrtc_resume); + +static const struct of_device_id atcrtc_dt_match[] = { + { .compatible = "andestech,atcrtc100" }, + { }, +}; +MODULE_DEVICE_TABLE(of, atcrtc_dt_match); + +static struct platform_driver atcrtc_platform_driver = { + .driver = { + .name = "atcrtc100", + .of_match_table = atcrtc_dt_match, + .pm = pm_sleep_ptr(&atcrtc_pm_ops), + }, + .probe = atcrtc_probe, +}; + +module_platform_driver(atcrtc_platform_driver); + +MODULE_AUTHOR("CL Wang "); +MODULE_DESCRIPTION("Andes ATCRTC100 driver"); +MODULE_LICENSE("GPL"); From 4c03653f19ae9b57e84cfe2d625b13bd1dfd449e Mon Sep 17 00:00:00 2001 From: Shubhi Garg Date: Tue, 7 Oct 2025 13:57:35 +0000 Subject: [PATCH 17/34] dt-bindings: rtc: Document NVIDIA VRS RTC Add device tree bindings for NVIDIA VRS (Voltage Regulator Specification) RTC device. NVIDIA VRS is a Power Management IC (PMIC) that implements a power sequencing solution with I2C interface. The device includes RTC which provides functionality to get/set system time, retain system time across boot, wake system from suspend and shutdown state. Supported platforms: - NVIDIA Jetson AGX Orin Developer Kit - NVIDIA IGX Orin Development Kit - NVIDIA Jetson Orin NX Developer Kit - NVIDIA Jetson Orin Nano Developer Kit Signed-off-by: Shubhi Garg Reviewed-by: Rob Herring (Arm) Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20251007135738.487694-2-shgarg@nvidia.com Signed-off-by: Alexandre Belloni --- .../bindings/rtc/nvidia,vrs-10.yaml | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml diff --git a/Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml b/Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml new file mode 100644 index 000000000000..c7dbc8b83c00 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/nvidia,vrs-10.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Voltage Regulator Specification Real Time Clock + +maintainers: + - Shubhi Garg + +description: + NVIDIA VRS-10 (Voltage Regulator Specification) is a Power Management IC + (PMIC) that implements a power sequencing solution with I2C interface. + The device includes a real-time clock (RTC) with 32kHz clock output and + backup battery support, alarm functionality for system wake-up from + suspend and shutdown states, OTP memory for power sequencing configuration, + and an interrupt controller for managing VRS events. + +properties: + compatible: + const: nvidia,vrs-10 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - '#interrupt-cells' + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@3c { + compatible = "nvidia,vrs-10"; + reg = <0x3c>; + interrupt-parent = <&pmc>; + interrupts = <24 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; From 9d6d6b06933c86849e8e12f1cb9c1afb9c048536 Mon Sep 17 00:00:00 2001 From: Shubhi Garg Date: Tue, 7 Oct 2025 13:57:37 +0000 Subject: [PATCH 18/34] rtc: nvvrs: add NVIDIA VRS RTC device driver Add support for NVIDIA VRS (Voltage Regulator Specification) RTC device driver. NVIDIA VRS is a Power Management IC (PMIC) that implements a power sequencing solution with I2C interface. The device includes RTC which provides functionality to get/set system time, retain system time across boot, wake system from suspend and shutdown state. Supported platforms: - NVIDIA Jetson AGX Orin Developer Kit - NVIDIA IGX Orin Development Kit - NVIDIA Jetson Orin NX Developer Kit - NVIDIA Jetson Orin Nano Developer Kit Signed-off-by: Shubhi Garg Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20251007135738.487694-4-shgarg@nvidia.com Signed-off-by: Alexandre Belloni --- MAINTAINERS | 8 + drivers/rtc/Kconfig | 9 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-nvidia-vrs10.c | 542 +++++++++++++++++++++++++++++++++ 4 files changed, 560 insertions(+) create mode 100644 drivers/rtc/rtc-nvidia-vrs10.c diff --git a/MAINTAINERS b/MAINTAINERS index da1e75d4cb9e..a3b87f2c9eb6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18428,6 +18428,14 @@ S: Maintained F: drivers/video/fbdev/nvidia/ F: drivers/video/fbdev/riva/ +NVIDIA VRS RTC DRIVER +M: Shubhi Garg +L: linux-tegra@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml +F: drivers/rtc/rtc-nvidia-vrs10.c +F: include/linux/rtc/rtc-nvidia-vrs10.h + NVIDIA WMI EC BACKLIGHT DRIVER M: Daniel Dadap L: platform-driver-x86@vger.kernel.org diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5d509254824e..8154fd251c9f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -416,6 +416,15 @@ config RTC_DRV_SPACEMIT_P1 This driver can also be built as a module, which will be called "spacemit-p1-rtc". +config RTC_DRV_NVIDIA_VRS10 + tristate "NVIDIA VRS10 RTC device" + help + If you say yes here you will get support for the battery backed RTC device + of NVIDIA VRS (Voltage Regulator Specification). The RTC is connected via + I2C interface and supports alarm functionality. + This driver can also be built as a module. If so, the module will be called + rtc-nvidia-vrs10. + config RTC_DRV_NCT3018Y tristate "Nuvoton NCT3018Y" depends on OF diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index f1b5c3d123c0..e464a90be323 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -122,6 +122,7 @@ obj-$(CONFIG_RTC_DRV_GAMECUBE) += rtc-gamecube.o obj-$(CONFIG_RTC_DRV_NCT3018Y) += rtc-nct3018y.o obj-$(CONFIG_RTC_DRV_NCT6694) += rtc-nct6694.o obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o +obj-$(CONFIG_RTC_DRV_NVIDIA_VRS10)+= rtc-nvidia-vrs10.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o obj-$(CONFIG_RTC_DRV_OPTEE) += rtc-optee.o diff --git a/drivers/rtc/rtc-nvidia-vrs10.c b/drivers/rtc/rtc-nvidia-vrs10.c new file mode 100644 index 000000000000..b15796698558 --- /dev/null +++ b/drivers/rtc/rtc-nvidia-vrs10.c @@ -0,0 +1,542 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NVIDIA Voltage Regulator Specification RTC + * + * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#define NVVRS_REG_VENDOR_ID 0x00 +#define NVVRS_REG_MODEL_REV 0x01 + +/* Interrupts registers */ +#define NVVRS_REG_INT_SRC1 0x10 +#define NVVRS_REG_INT_SRC2 0x11 +#define NVVRS_REG_INT_VENDOR 0x12 + +/* Control Registers */ +#define NVVRS_REG_CTL_1 0x28 +#define NVVRS_REG_CTL_2 0x29 + +/* RTC Registers */ +#define NVVRS_REG_RTC_T3 0x70 +#define NVVRS_REG_RTC_T2 0x71 +#define NVVRS_REG_RTC_T1 0x72 +#define NVVRS_REG_RTC_T0 0x73 +#define NVVRS_REG_RTC_A3 0x74 +#define NVVRS_REG_RTC_A2 0x75 +#define NVVRS_REG_RTC_A1 0x76 +#define NVVRS_REG_RTC_A0 0x77 + +/* Interrupt Mask */ +#define NVVRS_INT_SRC1_RSTIRQ_MASK BIT(0) +#define NVVRS_INT_SRC1_OSC_MASK BIT(1) +#define NVVRS_INT_SRC1_EN_MASK BIT(2) +#define NVVRS_INT_SRC1_RTC_MASK BIT(3) +#define NVVRS_INT_SRC1_PEC_MASK BIT(4) +#define NVVRS_INT_SRC1_WDT_MASK BIT(5) +#define NVVRS_INT_SRC1_EM_PD_MASK BIT(6) +#define NVVRS_INT_SRC1_INTERNAL_MASK BIT(7) +#define NVVRS_INT_SRC2_PBSP_MASK BIT(0) +#define NVVRS_INT_SRC2_ECC_DED_MASK BIT(1) +#define NVVRS_INT_SRC2_TSD_MASK BIT(2) +#define NVVRS_INT_SRC2_LDO_MASK BIT(3) +#define NVVRS_INT_SRC2_BIST_MASK BIT(4) +#define NVVRS_INT_SRC2_RT_CRC_MASK BIT(5) +#define NVVRS_INT_SRC2_VENDOR_MASK BIT(7) +#define NVVRS_INT_VENDOR0_MASK BIT(0) +#define NVVRS_INT_VENDOR1_MASK BIT(1) +#define NVVRS_INT_VENDOR2_MASK BIT(2) +#define NVVRS_INT_VENDOR3_MASK BIT(3) +#define NVVRS_INT_VENDOR4_MASK BIT(4) +#define NVVRS_INT_VENDOR5_MASK BIT(5) +#define NVVRS_INT_VENDOR6_MASK BIT(6) +#define NVVRS_INT_VENDOR7_MASK BIT(7) + +/* Controller Register Mask */ +#define NVVRS_REG_CTL_1_FORCE_SHDN (BIT(0) | BIT(1)) +#define NVVRS_REG_CTL_1_FORCE_ACT BIT(2) +#define NVVRS_REG_CTL_1_FORCE_INT BIT(3) +#define NVVRS_REG_CTL_2_EN_PEC BIT(0) +#define NVVRS_REG_CTL_2_REQ_PEC BIT(1) +#define NVVRS_REG_CTL_2_RTC_PU BIT(2) +#define NVVRS_REG_CTL_2_RTC_WAKE BIT(3) +#define NVVRS_REG_CTL_2_RST_DLY 0xF0 + +#define ALARM_RESET_VAL 0xffffffff +#define NVVRS_MIN_MODEL_REV 0x40 + +enum nvvrs_irq_regs { + NVVRS_IRQ_REG_INT_SRC1 = 0, + NVVRS_IRQ_REG_INT_SRC2 = 1, + NVVRS_IRQ_REG_INT_VENDOR = 2, + NVVRS_IRQ_REG_COUNT = 3, +}; + +struct nvvrs_rtc_info { + struct device *dev; + struct i2c_client *client; + struct rtc_device *rtc; + unsigned int irq; +}; + +static int nvvrs_update_bits(struct nvvrs_rtc_info *info, u8 reg, + u8 mask, u8 value) +{ + int ret; + u8 val; + + ret = i2c_smbus_read_byte_data(info->client, reg); + if (ret < 0) + return ret; + + val = (u8)ret; + val &= ~mask; + val |= (value & mask); + + return i2c_smbus_write_byte_data(info->client, reg, val); +} + +static int nvvrs_rtc_write_alarm(struct i2c_client *client, u8 *time) +{ + int ret; + + ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A3, time[3]); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A2, time[2]); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A1, time[1]); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A0, time[0]); +} + +static int nvvrs_rtc_enable_alarm(struct nvvrs_rtc_info *info) +{ + int ret; + + /* Set RTC_WAKE bit for autonomous wake from sleep */ + ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE, + NVVRS_REG_CTL_2_RTC_WAKE); + if (ret < 0) + return ret; + + /* Set RTC_PU bit for autonomous wake from shutdown */ + ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU, + NVVRS_REG_CTL_2_RTC_PU); + if (ret < 0) + return ret; + + return 0; +} + +static int nvvrs_rtc_disable_alarm(struct nvvrs_rtc_info *info) +{ + struct i2c_client *client = info->client; + u8 val[4]; + int ret; + + /* Clear RTC_WAKE bit */ + ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE, + 0); + if (ret < 0) + return ret; + + /* Clear RTC_PU bit */ + ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU, + 0); + if (ret < 0) + return ret; + + /* Write ALARM_RESET_VAL in RTC Alarm register to disable alarm */ + val[0] = 0xff; + val[1] = 0xff; + val[2] = 0xff; + val[3] = 0xff; + + ret = nvvrs_rtc_write_alarm(client, val); + if (ret < 0) + return ret; + + return 0; +} + +static int nvvrs_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct nvvrs_rtc_info *info = dev_get_drvdata(dev); + time64_t secs = 0; + int ret; + u8 val; + + /* + * Multi-byte transfers are not supported with PEC enabled + * Read MSB first to avoid coherency issues + */ + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T3); + if (ret < 0) + return ret; + + val = (u8)ret; + secs |= (time64_t)val << 24; + + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T2); + if (ret < 0) + return ret; + + val = (u8)ret; + secs |= (time64_t)val << 16; + + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T1); + if (ret < 0) + return ret; + + val = (u8)ret; + secs |= (time64_t)val << 8; + + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T0); + if (ret < 0) + return ret; + + val = (u8)ret; + secs |= val; + + rtc_time64_to_tm(secs, tm); + + return 0; +} + +static int nvvrs_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct nvvrs_rtc_info *info = dev_get_drvdata(dev); + time64_t secs; + u8 time[4]; + int ret; + + secs = rtc_tm_to_time64(tm); + time[0] = secs & 0xff; + time[1] = (secs >> 8) & 0xff; + time[2] = (secs >> 16) & 0xff; + time[3] = (secs >> 24) & 0xff; + + ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T3, time[3]); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T2, time[2]); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T1, time[1]); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T0, time[0]); + + return ret; +} + +static int nvvrs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct nvvrs_rtc_info *info = dev_get_drvdata(dev); + time64_t alarm_val = 0; + int ret; + u8 val; + + /* Multi-byte transfers are not supported with PEC enabled */ + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A3); + if (ret < 0) + return ret; + + val = (u8)ret; + alarm_val |= (time64_t)val << 24; + + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A2); + if (ret < 0) + return ret; + + val = (u8)ret; + alarm_val |= (time64_t)val << 16; + + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A1); + if (ret < 0) + return ret; + + val = (u8)ret; + alarm_val |= (time64_t)val << 8; + + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A0); + if (ret < 0) + return ret; + + val = (u8)ret; + alarm_val |= val; + + if (alarm_val == ALARM_RESET_VAL) + alrm->enabled = 0; + else + alrm->enabled = 1; + + rtc_time64_to_tm(alarm_val, &alrm->time); + + return 0; +} + +static int nvvrs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct nvvrs_rtc_info *info = dev_get_drvdata(dev); + time64_t secs; + u8 time[4]; + int ret; + + if (!alrm->enabled) { + ret = nvvrs_rtc_disable_alarm(info); + if (ret < 0) + return ret; + } + + ret = nvvrs_rtc_enable_alarm(info); + if (ret < 0) + return ret; + + secs = rtc_tm_to_time64(&alrm->time); + time[0] = secs & 0xff; + time[1] = (secs >> 8) & 0xff; + time[2] = (secs >> 16) & 0xff; + time[3] = (secs >> 24) & 0xff; + + ret = nvvrs_rtc_write_alarm(info->client, time); + + return ret; +} + +static int nvvrs_pseq_irq_clear(struct nvvrs_rtc_info *info) +{ + unsigned int i; + int ret; + + for (i = 0; i < NVVRS_IRQ_REG_COUNT; i++) { + ret = i2c_smbus_read_byte_data(info->client, + NVVRS_REG_INT_SRC1 + i); + if (ret < 0) { + dev_err(info->dev, "Failed to read INT_SRC%d : %d\n", + i + 1, ret); + return ret; + } + + ret = i2c_smbus_write_byte_data(info->client, + NVVRS_REG_INT_SRC1 + i, + (u8)ret); + if (ret < 0) { + dev_err(info->dev, "Failed to clear INT_SRC%d : %d\n", + i + 1, ret); + return ret; + } + } + + return 0; +} + +static irqreturn_t nvvrs_rtc_irq_handler(int irq, void *data) +{ + struct nvvrs_rtc_info *info = data; + int ret; + + /* Check for RTC alarm interrupt */ + ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_INT_SRC1); + if (ret < 0) + return IRQ_NONE; + + if (ret & NVVRS_INT_SRC1_RTC_MASK) { + rtc_lock(info->rtc); + rtc_update_irq(info->rtc, 1, RTC_IRQF | RTC_AF); + rtc_unlock(info->rtc); + } + + /* Clear all interrupts */ + if (nvvrs_pseq_irq_clear(info) < 0) + return IRQ_NONE; + + return IRQ_HANDLED; +} + +static int nvvrs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + /* + * This hardware does not support enabling/disabling the alarm IRQ + * independently. The alarm is disabled by clearing the alarm time + * via set_alarm(). + */ + return 0; +} + +static const struct rtc_class_ops nvvrs_rtc_ops = { + .read_time = nvvrs_rtc_read_time, + .set_time = nvvrs_rtc_set_time, + .read_alarm = nvvrs_rtc_read_alarm, + .set_alarm = nvvrs_rtc_set_alarm, + .alarm_irq_enable = nvvrs_rtc_alarm_irq_enable, +}; + +static int nvvrs_pseq_vendor_info(struct nvvrs_rtc_info *info) +{ + struct i2c_client *client = info->client; + u8 vendor_id, model_rev; + int ret; + + ret = i2c_smbus_read_byte_data(client, NVVRS_REG_VENDOR_ID); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to read Vendor ID\n"); + + vendor_id = (u8)ret; + + ret = i2c_smbus_read_byte_data(client, NVVRS_REG_MODEL_REV); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to read Model Revision\n"); + + model_rev = (u8)ret; + + if (model_rev < NVVRS_MIN_MODEL_REV) { + return dev_err_probe(&client->dev, -ENODEV, + "Chip revision 0x%02x is not supported!\n", + model_rev); + } + + dev_dbg(&client->dev, "NVVRS Vendor ID: 0x%02x, Model Rev: 0x%02x\n", + vendor_id, model_rev); + + return 0; +} + +static int nvvrs_rtc_probe(struct i2c_client *client) +{ + struct nvvrs_rtc_info *info; + int ret; + + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + if (client->irq <= 0) + return dev_err_probe(&client->dev, -EINVAL, "No IRQ specified\n"); + + info->irq = client->irq; + info->dev = &client->dev; + client->flags |= I2C_CLIENT_PEC; + i2c_set_clientdata(client, info); + info->client = client; + + /* Check vendor info */ + if (nvvrs_pseq_vendor_info(info) < 0) + return dev_err_probe(&client->dev, -EINVAL, + "Failed to get vendor info\n"); + + /* Clear any pending IRQs before requesting IRQ handler */ + if (nvvrs_pseq_irq_clear(info) < 0) + return dev_err_probe(&client->dev, -EINVAL, + "Failed to clear interrupts\n"); + + /* Allocate RTC device */ + info->rtc = devm_rtc_allocate_device(info->dev); + if (IS_ERR(info->rtc)) + return PTR_ERR(info->rtc); + + info->rtc->ops = &nvvrs_rtc_ops; + info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + info->rtc->range_max = RTC_TIMESTAMP_END_2099; + + /* Request RTC IRQ */ + ret = devm_request_threaded_irq(info->dev, info->irq, NULL, + nvvrs_rtc_irq_handler, IRQF_ONESHOT, + "nvvrs-rtc", info); + if (ret < 0) { + dev_err_probe(info->dev, ret, "Failed to request RTC IRQ\n"); + return ret; + } + + /* RTC as a wakeup source */ + devm_device_init_wakeup(info->dev); + + return devm_rtc_register_device(info->rtc); +} + +#ifdef CONFIG_PM_SLEEP +static int nvvrs_rtc_suspend(struct device *dev) +{ + struct nvvrs_rtc_info *info = dev_get_drvdata(dev); + int ret; + + if (device_may_wakeup(dev)) { + /* Set RTC_WAKE bit for auto wake system from suspend state */ + ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, + NVVRS_REG_CTL_2_RTC_WAKE, + NVVRS_REG_CTL_2_RTC_WAKE); + if (ret < 0) { + dev_err(info->dev, "Failed to set RTC_WAKE bit (%d)\n", + ret); + return ret; + } + + return enable_irq_wake(info->irq); + } + + return 0; +} + +static int nvvrs_rtc_resume(struct device *dev) +{ + struct nvvrs_rtc_info *info = dev_get_drvdata(dev); + int ret; + + if (device_may_wakeup(dev)) { + /* Clear FORCE_ACT bit */ + ret = nvvrs_update_bits(info, NVVRS_REG_CTL_1, + NVVRS_REG_CTL_1_FORCE_ACT, 0); + if (ret < 0) { + dev_err(info->dev, "Failed to clear FORCE_ACT bit (%d)\n", + ret); + return ret; + } + + return disable_irq_wake(info->irq); + } + + return 0; +} + +#endif +static SIMPLE_DEV_PM_OPS(nvvrs_rtc_pm_ops, nvvrs_rtc_suspend, nvvrs_rtc_resume); + +static const struct of_device_id nvvrs_rtc_of_match[] = { + { .compatible = "nvidia,vrs-10" }, + { }, +}; +MODULE_DEVICE_TABLE(of, nvvrs_rtc_of_match); + +static struct i2c_driver nvvrs_rtc_driver = { + .driver = { + .name = "rtc-nvidia-vrs10", + .pm = &nvvrs_rtc_pm_ops, + .of_match_table = nvvrs_rtc_of_match, + }, + .probe = nvvrs_rtc_probe, +}; + +module_i2c_driver(nvvrs_rtc_driver); + +MODULE_AUTHOR("Shubhi Garg "); +MODULE_DESCRIPTION("NVIDIA Voltage Regulator Specification RTC driver"); +MODULE_LICENSE("GPL"); From 73c4638a2864e69ff2251080ce874d360fd13056 Mon Sep 17 00:00:00 2001 From: Nick Huang Date: Sun, 21 Sep 2025 01:42:23 +0800 Subject: [PATCH 19/34] rtc: s35390a: use u8 instead of char for register buffer The register buffer in s35390a_get_reg() was previously defined as `char *buf`. This is not ideal since register data represents raw binary values rather than textual data. Switch the type to `u8 *buf` to better reflect its intended usage and to avoid potential issues with sign extension when handling register values on platforms where `char` is signed by default. This change improves type safety and makes the code consistent with other RTC drivers that operate on raw register data. Signed-off-by: Nick Huang Link: https://patch.msgid.link/20250920174224.108795-1-sef1548@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s35390a.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 3408d2ab2741..07bd983b5692 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -66,7 +66,7 @@ struct s35390a { int twentyfourhour; }; -static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len) +static int s35390a_set_reg(struct s35390a *s35390a, int reg, u8 *buf, int len) { struct i2c_client *client = s35390a->client[reg]; struct i2c_msg msg[] = { @@ -83,7 +83,7 @@ static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len) return 0; } -static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) +static int s35390a_get_reg(struct s35390a *s35390a, int reg, u8 *buf, int len) { struct i2c_client *client = s35390a->client[reg]; struct i2c_msg msg[] = { @@ -168,7 +168,7 @@ static int s35390a_read_status(struct s35390a *s35390a, char *status1) static int s35390a_disable_test_mode(struct s35390a *s35390a) { - char buf[1]; + u8 buf[1]; if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0) return -EIO; @@ -210,7 +210,7 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); int i; - char buf[7], status; + u8 buf[7], status; dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, " "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, @@ -239,7 +239,7 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); - char buf[7], status; + u8 buf[7], status; int i, err; if (s35390a_read_status(s35390a, &status) == 1) @@ -273,7 +273,7 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); - char buf[3], sts = 0; + u8 buf[3], sts = 0; int err, i; dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\ @@ -326,7 +326,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); - char buf[3], sts; + u8 buf[3], sts; int i, err; err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); @@ -383,7 +383,7 @@ static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd, { struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); - char sts; + u8 sts; int err; switch (cmd) { @@ -422,7 +422,7 @@ static int s35390a_probe(struct i2c_client *client) unsigned int i; struct s35390a *s35390a; struct rtc_device *rtc; - char buf, status1; + u8 buf, status1; struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) From 53e71c177cd84982138457b617342f68511e0b64 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Sat, 11 Oct 2025 06:26:05 +0000 Subject: [PATCH 20/34] rtc: Kconfig: add MC34708 to mc13xxx help text MC34708 is one of the three mfd devices supported by DRV_MC13XXX. Update Kconfig accordingly. Signed-off-by: Alexander Kurz Link: https://patch.msgid.link/20251011062605.13591-1-akurz@blala.de Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8154fd251c9f..fc2154d6e413 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1773,7 +1773,7 @@ config RTC_DRV_MC13XXX tristate "Freescale MC13xxx RTC" help This enables support for the RTCs found on Freescale's PMICs - MC13783 and MC13892. + MC13783, MC13892 and MC34708. config RTC_DRV_MPC5121 tristate "Freescale MPC5121 built-in RTC" From b665c1b620e75e85ea85215735130fd4597bc47f Mon Sep 17 00:00:00 2001 From: Kartik Rajput Date: Fri, 24 Oct 2025 12:19:50 +0530 Subject: [PATCH 21/34] rtc: tegra: Use devm_clk_get_enabled() in probe Simplify clock management by replacing devm_clk_get() and manual clock enable/disable with devm_clk_get_enabled(). This also simplifies the error handling logic. Also remove tegra_rtc_remove() as the clock will automatically be disabled when the device is unbound from the bus. Suggested-by: Andy Shevchenko Signed-off-by: Kartik Rajput Reviewed-by: Andy Shevchenko Reviewed-by: Jon Hunter Link: https://patch.msgid.link/20251024064952.775883-1-kkartik@nvidia.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tegra.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 46788db89953..e8c83a6a96b3 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -300,14 +300,10 @@ static int tegra_rtc_probe(struct platform_device *pdev) info->rtc->ops = &tegra_rtc_ops; info->rtc->range_max = U32_MAX; - info->clk = devm_clk_get(&pdev->dev, NULL); + info->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(info->clk)) return PTR_ERR(info->clk); - ret = clk_prepare_enable(info->clk); - if (ret < 0) - return ret; - /* set context info */ info->pdev = pdev; spin_lock_init(&info->lock); @@ -324,29 +320,16 @@ static int tegra_rtc_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "failed to request interrupt: %d\n", ret); - goto disable_clk; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to request interrupt\n"); ret = devm_rtc_register_device(info->rtc); if (ret) - goto disable_clk; + return ret; dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); return 0; - -disable_clk: - clk_disable_unprepare(info->clk); - return ret; -} - -static void tegra_rtc_remove(struct platform_device *pdev) -{ - struct tegra_rtc_info *info = platform_get_drvdata(pdev); - - clk_disable_unprepare(info->clk); } #ifdef CONFIG_PM_SLEEP @@ -399,7 +382,6 @@ static void tegra_rtc_shutdown(struct platform_device *pdev) static struct platform_driver tegra_rtc_driver = { .probe = tegra_rtc_probe, - .remove = tegra_rtc_remove, .shutdown = tegra_rtc_shutdown, .driver = { .name = "tegra_rtc", From 0a293451030b4ad69026b77c7d6b6bdf5cafd7e4 Mon Sep 17 00:00:00 2001 From: Kartik Rajput Date: Fri, 24 Oct 2025 12:19:51 +0530 Subject: [PATCH 22/34] rtc: tegra: Add ACPI support Add ACPI support for Tegra RTC, which is available on Tegra241 and Tegra410. Both Tegra241 and Tegra410 use the same ACPI ID 'NVDA0280'. When ACPI boot is used, the RTC clock is configured by UEFI before the kernel boots. On device-tree boot, the probe must fail if clocks are not provided in the device-tree. Signed-off-by: Kartik Rajput Reviewed-by: Andy Shevchenko Reviewed-by: Jon Hunter Link: https://patch.msgid.link/20251024064952.775883-2-kkartik@nvidia.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tegra.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index e8c83a6a96b3..9e4e9c88178f 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -274,6 +274,12 @@ static const struct of_device_id tegra_rtc_dt_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match); +static const struct acpi_device_id tegra_rtc_acpi_match[] = { + { "NVDA0280" }, + { } +}; +MODULE_DEVICE_TABLE(acpi, tegra_rtc_acpi_match); + static int tegra_rtc_probe(struct platform_device *pdev) { struct tegra_rtc_info *info; @@ -300,9 +306,11 @@ static int tegra_rtc_probe(struct platform_device *pdev) info->rtc->ops = &tegra_rtc_ops; info->rtc->range_max = U32_MAX; - info->clk = devm_clk_get_enabled(&pdev->dev, NULL); - if (IS_ERR(info->clk)) - return PTR_ERR(info->clk); + if (dev_of_node(&pdev->dev)) { + info->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(info->clk)) + return PTR_ERR(info->clk); + } /* set context info */ info->pdev = pdev; @@ -386,6 +394,7 @@ static struct platform_driver tegra_rtc_driver = { .driver = { .name = "tegra_rtc", .of_match_table = tegra_rtc_dt_match, + .acpi_match_table = tegra_rtc_acpi_match, .pm = &tegra_rtc_pm_ops, }, }; From bf5ef3ce42da98c59d820dfdd9513ff210622f32 Mon Sep 17 00:00:00 2001 From: Kartik Rajput Date: Fri, 24 Oct 2025 12:19:52 +0530 Subject: [PATCH 23/34] rtc: tegra: Replace deprecated SIMPLE_DEV_PM_OPS Replace deprecated SIMPLE_DEV_PM_OPS with DEFINE_SIMPLE_DEV_PM_OPS macro and use pm_sleep_ptr() to initialize pm_ops. This also allows us to drop the checks for CONFIG_PM_SLEEP. Suggested-by: Andy Shevchenko Signed-off-by: Kartik Rajput Reviewed-by: Andy Shevchenko Reviewed-by: Jon Hunter Link: https://patch.msgid.link/20251024064952.775883-3-kkartik@nvidia.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tegra.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 9e4e9c88178f..528e32b7d101 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -340,7 +340,6 @@ static int tegra_rtc_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int tegra_rtc_suspend(struct device *dev) { struct tegra_rtc_info *info = dev_get_drvdata(dev); @@ -378,9 +377,8 @@ static int tegra_rtc_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume); static void tegra_rtc_shutdown(struct platform_device *pdev) { @@ -395,7 +393,7 @@ static struct platform_driver tegra_rtc_driver = { .name = "tegra_rtc", .of_match_table = tegra_rtc_dt_match, .acpi_match_table = tegra_rtc_acpi_match, - .pm = &tegra_rtc_pm_ops, + .pm = pm_sleep_ptr(&tegra_rtc_pm_ops), }, }; module_platform_driver(tegra_rtc_driver); From 4800046b56a5b240ab280f55165484a9dbdf7092 Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Fri, 7 Nov 2025 21:07:03 +0000 Subject: [PATCH 24/34] dt-bindings: rtc: renesas,rz-rtca3: Add RZ/V2H support The Renesas RZ/V2H RTC IP is based on the same RTCA3 IP as RZ/G3S (r9a08g045), with the following differences: - It lacks the time capture functionality - The maximum supported periodic interrupt frequency is 128Hz instead of 256Hz - It requires two reset lines instead of one Add new compatible string "renesas,r9a09g057-rtca3" for RZ/V2H and update the binding accordingly: - Allow "resets" to contain one or two entries depending on the SoC. - Add "reset-names" property, but make it required only for RZ/V2H. Signed-off-by: Ovidiu Panait Acked-by: Conor Dooley Link: https://patch.msgid.link/20251107210706.45044-2-ovidiu.panait.rb@renesas.com Signed-off-by: Alexandre Belloni --- .../bindings/rtc/renesas,rz-rtca3.yaml | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml b/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml index e70eeb66aa64..ccb1638c35b9 100644 --- a/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml +++ b/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml @@ -9,14 +9,12 @@ title: Renesas RTCA-3 Real Time Clock maintainers: - Claudiu Beznea -allOf: - - $ref: rtc.yaml# - properties: compatible: items: - enum: - renesas,r9a08g045-rtca3 # RZ/G3S + - renesas,r9a09g057-rtca3 # RZ/V2H - const: renesas,rz-rtca3 reg: @@ -48,8 +46,12 @@ properties: maxItems: 1 resets: - items: - - description: VBATTB module reset + minItems: 1 + maxItems: 2 + + reset-names: + minItems: 1 + maxItems: 2 required: - compatible @@ -61,6 +63,39 @@ required: - power-domains - resets +allOf: + - $ref: rtc.yaml# + + - if: + properties: + compatible: + contains: + const: renesas,r9a08g045-rtca3 + then: + properties: + resets: + items: + - description: VBATTB module reset + reset-names: + const: vbattb + - if: + properties: + compatible: + contains: + const: renesas,r9a09g057-rtca3 + then: + properties: + resets: + items: + - description: RTC reset + - description: Reset for the RTEST registers + reset-names: + items: + - const: rtc + - const: rtest + required: + - reset-names + additionalProperties: false examples: @@ -81,4 +116,5 @@ examples: clock-names = "bus", "counter"; power-domains = <&cpg>; resets = <&cpg R9A08G045_VBAT_BRESETN>; + reset-names = "vbattb"; }; From 6ada8e24238dd57b38faca503b09757e17819b05 Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Fri, 7 Nov 2025 21:07:04 +0000 Subject: [PATCH 25/34] rtc: renesas-rtca3: Add support for multiple reset lines Switch from devm_reset_control_get_shared() to devm_reset_control_array_get_shared() when retrieving resets. The RZ/V2H SoC requires two resets for the RTC block instead of one, so this will allow to handle multiple resets without additional changes. Signed-off-by: Ovidiu Panait Reviewed-by: Claudiu Beznea Link: https://patch.msgid.link/20251107210706.45044-3-ovidiu.panait.rb@renesas.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-renesas-rtca3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c index a238ead6cf1a..cbabaa4dc96a 100644 --- a/drivers/rtc/rtc-renesas-rtca3.c +++ b/drivers/rtc/rtc-renesas-rtca3.c @@ -726,7 +726,7 @@ static int rtca3_probe(struct platform_device *pdev) if (ret) return ret; - priv->rstc = devm_reset_control_get_shared(dev, NULL); + priv->rstc = devm_reset_control_array_get_shared(dev); if (IS_ERR(priv->rstc)) return PTR_ERR(priv->rstc); From e0784949c65b1d961d101325b11e43eb306ad04b Mon Sep 17 00:00:00 2001 From: Akhilesh Patil Date: Sun, 9 Nov 2025 11:18:59 +0530 Subject: [PATCH 26/34] rtc: isl12026: Add id_table Add i2c id_table for isl12026 rtc. Signed-off-by: Akhilesh Patil Link: https://patch.msgid.link/2025119-54859-2010914@bhairav-test.ee.iitb.ac.in Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl12026.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c index 2aabb9151d4c..45a2c9f676c5 100644 --- a/drivers/rtc/rtc-isl12026.c +++ b/drivers/rtc/rtc-isl12026.c @@ -484,6 +484,12 @@ static const struct of_device_id isl12026_dt_match[] = { }; MODULE_DEVICE_TABLE(of, isl12026_dt_match); +static const struct i2c_device_id isl12026_id[] = { + { "isl12026" }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, isl12026_id); + static struct i2c_driver isl12026_driver = { .driver = { .name = "rtc-isl12026", @@ -491,6 +497,7 @@ static struct i2c_driver isl12026_driver = { }, .probe = isl12026_probe, .remove = isl12026_remove, + .id_table = isl12026_id, }; module_i2c_driver(isl12026_driver); From 40d8123ff7492d014d9396a458b344d59cec3c6b Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Mon, 10 Nov 2025 08:35:44 +0100 Subject: [PATCH 27/34] MAINTAINERS: drop unneeded file entry in NVIDIA VRS RTC DRIVER Commit 9d6d6b06933c ("rtc: nvvrs: add NVIDIA VRS RTC device driver") adds the section NVIDIA VRS RTC DRIVER in MAINTAINERS, which refers to the non-existing file include/linux/rtc/rtc-nvidia-vrs10.h Note, with the changes of v6 to v7 of the patch series adding the driver, the content of this include file was moved into the driver file, and the include file was dropped from that patch. It was simply missed to adjust the section in MAINTAINERS that was newly added with that patch. Drop the file entry to this non-existing file accordingly now. Signed-off-by: Lukas Bulwahn Acked-by: Thierry Reding Reviewed-by: Jon Hunter Reviewed-by: Shubhi Garg Link: https://patch.msgid.link/20251110073544.443816-1-lukas.bulwahn@redhat.com Signed-off-by: Alexandre Belloni --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a3b87f2c9eb6..0a19e3171ad4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18434,7 +18434,6 @@ L: linux-tegra@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml F: drivers/rtc/rtc-nvidia-vrs10.c -F: include/linux/rtc/rtc-nvidia-vrs10.h NVIDIA WMI EC BACKLIGHT DRIVER M: Daniel Dadap From 07049187e83072e187d7a9f3386286e59c83e8ee Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Wed, 12 Nov 2025 21:16:47 +1000 Subject: [PATCH 28/34] dt-bindings: rtc: Add Apple SMC RTC Apple Silicon Macs (M1, etc.) have an RTC that is part of the PMU IC, but most of the PMU functionality is abstracted out by the SMC. An additional RTC offset stored inside NVMEM is required to compute the current date/time. Reviewed-by: Mark Kettenis Reviewed-by: Neal Gompa Reviewed-by: Rob Herring (Arm) Signed-off-by: Sven Peter Signed-off-by: James Calligeros Reviewd-by: Mark Kettenis Link: https://patch.msgid.link/20251112-macsmc-subdevs-v5-1-728e4b91fe81@gmail.com Signed-off-by: Alexandre Belloni --- .../devicetree/bindings/mfd/apple,smc.yaml | 9 +++++ .../bindings/rtc/apple,smc-rtc.yaml | 35 +++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml diff --git a/Documentation/devicetree/bindings/mfd/apple,smc.yaml b/Documentation/devicetree/bindings/mfd/apple,smc.yaml index 5429538f7e2e..0410e712c900 100644 --- a/Documentation/devicetree/bindings/mfd/apple,smc.yaml +++ b/Documentation/devicetree/bindings/mfd/apple,smc.yaml @@ -46,6 +46,9 @@ properties: reboot: $ref: /schemas/power/reset/apple,smc-reboot.yaml + rtc: + $ref: /schemas/rtc/apple,smc-rtc.yaml + additionalProperties: false required: @@ -80,5 +83,11 @@ examples: nvmem-cell-names = "shutdown_flag", "boot_stage", "boot_error_count", "panic_count"; }; + + rtc { + compatible = "apple,smc-rtc"; + nvmem-cells = <&rtc_offset>; + nvmem-cell-names = "rtc_offset"; + }; }; }; diff --git a/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml b/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml new file mode 100644 index 000000000000..607b610665a2 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/apple,smc-rtc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Apple SMC RTC + +description: + Apple Silicon Macs (M1, etc.) have an RTC that is part of the PMU IC, + but most of the PMU functionality is abstracted out by the SMC. + An additional RTC offset stored inside NVMEM is required to compute + the current date/time. + +maintainers: + - Sven Peter + +properties: + compatible: + const: apple,smc-rtc + + nvmem-cells: + items: + - description: 48bit RTC offset, specified in 32768 (2^15) Hz clock ticks + + nvmem-cell-names: + items: + - const: rtc_offset + +required: + - compatible + - nvmem-cells + - nvmem-cell-names + +additionalProperties: false diff --git a/MAINTAINERS b/MAINTAINERS index 0a19e3171ad4..b93d26e60e99 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2435,6 +2435,7 @@ F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml F: Documentation/devicetree/bindings/power/apple* F: Documentation/devicetree/bindings/power/reset/apple,smc-reboot.yaml F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml +F: Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml F: Documentation/devicetree/bindings/spi/apple,spi.yaml F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml From 49a51df427dbb5bab9b3341a3a59c248bab79d50 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Wed, 12 Nov 2025 21:16:49 +1000 Subject: [PATCH 29/34] rtc: Add new rtc-macsmc driver for Apple Silicon Macs Apple Silicon Macs (M1, etc.) have an RTC that is part of the PMU IC, but most of the PMU functionality is abstracted out by the SMC. On T600x machines, the RTC counter must be accessed via the SMC to get full functionality, and it seems likely that future machines will move towards making SMC handle all RTC functionality. The SMC RTC counter access is implemented on all current machines as of the time of this writing, on firmware 12.x. However, the RTC offset (needed to set the time) is still only accessible via direct PMU access. To handle this, we expose the RTC offset as an NVMEM cell from the SPMI PMU device node, and this driver consumes that cell and uses it to compute/set the current time. Reviewed-by: Neal Gompa Signed-off-by: Hector Martin Signed-off-by: Sven Peter Signed-off-by: James Calligeros Link: https://patch.msgid.link/20251112-macsmc-subdevs-v5-3-728e4b91fe81@gmail.com Signed-off-by: Alexandre Belloni --- MAINTAINERS | 1 + drivers/rtc/Kconfig | 11 +++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-macsmc.c | 140 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 drivers/rtc/rtc-macsmc.c diff --git a/MAINTAINERS b/MAINTAINERS index b93d26e60e99..051abbe5953c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2459,6 +2459,7 @@ F: drivers/nvmem/apple-spmi-nvmem.c F: drivers/pinctrl/pinctrl-apple-gpio.c F: drivers/power/reset/macsmc-reboot.c F: drivers/pwm/pwm-apple.c +F: drivers/rtc/rtc-macsmc.c F: drivers/soc/apple/* F: drivers/spi/spi-apple.c F: drivers/spmi/spmi-apple-controller.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index fc2154d6e413..9906cddd5a8b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -2098,6 +2098,17 @@ config RTC_DRV_WILCO_EC This can also be built as a module. If so, the module will be named "rtc_wilco_ec". +config RTC_DRV_MACSMC + tristate "Apple Mac System Management Controller RTC" + depends on MFD_MACSMC + help + If you say yes here you get support for RTC functions + inside Apple SPMI PMUs accessed through the SoC's + System Management Controller + + To compile this driver as a module, choose M here: the + module will be called rtc-macsmc. + config RTC_DRV_MSC313 tristate "MStar MSC313 RTC" depends on ARCH_MSTARV7 || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e464a90be323..6cf7e066314e 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -94,6 +94,7 @@ obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o obj-$(CONFIG_RTC_DRV_MA35D1) += rtc-ma35d1.o +obj-$(CONFIG_RTC_DRV_MACSMC) += rtc-macsmc.o obj-$(CONFIG_RTC_DRV_MAX31335) += rtc-max31335.o obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o diff --git a/drivers/rtc/rtc-macsmc.c b/drivers/rtc/rtc-macsmc.c new file mode 100644 index 000000000000..8fe883066956 --- /dev/null +++ b/drivers/rtc/rtc-macsmc.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Apple SMC RTC driver + * Copyright The Asahi Linux Contributors + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 48-bit RTC */ +#define RTC_BYTES 6 +#define RTC_BITS (8 * RTC_BYTES) + +/* 32768 Hz clock */ +#define RTC_SEC_SHIFT 15 + +struct macsmc_rtc { + struct device *dev; + struct apple_smc *smc; + struct rtc_device *rtc_dev; + struct nvmem_cell *rtc_offset; +}; + +static int macsmc_rtc_get_time(struct device *dev, struct rtc_time *tm) +{ + struct macsmc_rtc *rtc = dev_get_drvdata(dev); + u64 ctr = 0, off = 0; + time64_t now; + void *p_off; + size_t len; + int ret; + + ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES); + if (ret < 0) + return ret; + if (ret != RTC_BYTES) + return -EIO; + + p_off = nvmem_cell_read(rtc->rtc_offset, &len); + if (IS_ERR(p_off)) + return PTR_ERR(p_off); + if (len < RTC_BYTES) { + kfree(p_off); + return -EIO; + } + + memcpy(&off, p_off, RTC_BYTES); + kfree(p_off); + + /* Sign extend from 48 to 64 bits, then arithmetic shift right 15 bits to get seconds */ + now = sign_extend64(ctr + off, RTC_BITS - 1) >> RTC_SEC_SHIFT; + rtc_time64_to_tm(now, tm); + + return ret; +} + +static int macsmc_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct macsmc_rtc *rtc = dev_get_drvdata(dev); + u64 ctr = 0, off = 0; + int ret; + + ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES); + if (ret < 0) + return ret; + if (ret != RTC_BYTES) + return -EIO; + + /* This sets the offset such that the set second begins now */ + off = (rtc_tm_to_time64(tm) << RTC_SEC_SHIFT) - ctr; + return nvmem_cell_write(rtc->rtc_offset, &off, RTC_BYTES); +} + +static const struct rtc_class_ops macsmc_rtc_ops = { + .read_time = macsmc_rtc_get_time, + .set_time = macsmc_rtc_set_time, +}; + +static int macsmc_rtc_probe(struct platform_device *pdev) +{ + struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent); + struct macsmc_rtc *rtc; + + /* + * MFD will probe this device even without a node in the device tree, + * thus bail out early if the SMC on the current machines does not + * support RTC and has no node in the device tree. + */ + if (!pdev->dev.of_node) + return -ENODEV; + + rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + rtc->dev = &pdev->dev; + rtc->smc = smc; + + rtc->rtc_offset = devm_nvmem_cell_get(&pdev->dev, "rtc_offset"); + if (IS_ERR(rtc->rtc_offset)) + return dev_err_probe(&pdev->dev, PTR_ERR(rtc->rtc_offset), + "Failed to get rtc_offset NVMEM cell\n"); + + rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + + rtc->rtc_dev->ops = &macsmc_rtc_ops; + rtc->rtc_dev->range_min = S64_MIN >> (RTC_SEC_SHIFT + (64 - RTC_BITS)); + rtc->rtc_dev->range_max = S64_MAX >> (RTC_SEC_SHIFT + (64 - RTC_BITS)); + + platform_set_drvdata(pdev, rtc); + + return devm_rtc_register_device(rtc->rtc_dev); +} + +static const struct of_device_id macsmc_rtc_of_table[] = { + { .compatible = "apple,smc-rtc", }, + {} +}; +MODULE_DEVICE_TABLE(of, macsmc_rtc_of_table); + +static struct platform_driver macsmc_rtc_driver = { + .driver = { + .name = "macsmc-rtc", + .of_match_table = macsmc_rtc_of_table, + }, + .probe = macsmc_rtc_probe, +}; +module_platform_driver(macsmc_rtc_driver); + +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_DESCRIPTION("Apple SMC RTC driver"); +MODULE_AUTHOR("Hector Martin "); From 22a6db42253744f0f54ab632da0140b690feb44d Mon Sep 17 00:00:00 2001 From: Akiyoshi Kurita Date: Wed, 12 Nov 2025 20:37:59 +0900 Subject: [PATCH 30/34] Documentation: ABI: testing: Fix "upto" typo in rtc-cdev The word "upto" is a common typo for "up to". Correct this. Signed-off-by: Akiyoshi Kurita Link: https://patch.msgid.link/20251112113759.2953758-1-weibu@redadmin.org Signed-off-by: Alexandre Belloni --- Documentation/ABI/testing/rtc-cdev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/rtc-cdev b/Documentation/ABI/testing/rtc-cdev index 25910c3c3d7e..cec099a27c6d 100644 --- a/Documentation/ABI/testing/rtc-cdev +++ b/Documentation/ABI/testing/rtc-cdev @@ -14,7 +14,7 @@ Description: for RTCs that support alarms * RTC_ALM_READ, RTC_ALM_SET: Read or set the alarm time for - RTCs that support alarms. Can be set upto 24 hours in the + RTCs that support alarms. Can be set up to 24 hours in the future. Requires a separate RTC_AIE_ON call to enable the alarm interrupt. (Prefer to use RTC_WKALM_*) From d1220e47e4bd2be8b84bc158f4dea44f2f88b226 Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Wed, 26 Nov 2025 16:06:25 +0800 Subject: [PATCH 31/34] rtc: gamecube: Check the return value of ioremap() The function ioremap() in gamecube_rtc_read_offset_from_sram() can fail and return NULL, which is dereferenced without checking, leading to a NULL pointer dereference. Add a check for the return value of ioremap() and return -ENOMEM on failure. Fixes: 86559400b3ef ("rtc: gamecube: Add a RTC driver for the GameCube, Wii and Wii U") Signed-off-by: Haotian Zhang Reviewed-by: Link Mauve Link: https://patch.msgid.link/20251126080625.1752-1-vulab@iscas.ac.cn Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-gamecube.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/rtc/rtc-gamecube.c b/drivers/rtc/rtc-gamecube.c index c828bc8e05b9..045d5d45ab4b 100644 --- a/drivers/rtc/rtc-gamecube.c +++ b/drivers/rtc/rtc-gamecube.c @@ -242,6 +242,10 @@ static int gamecube_rtc_read_offset_from_sram(struct priv *d) } hw_srnprot = ioremap(res.start, resource_size(&res)); + if (!hw_srnprot) { + pr_err("failed to ioremap hw_srnprot\n"); + return -ENOMEM; + } old = ioread32be(hw_srnprot); /* TODO: figure out why we use this magic constant. I obtained it by From f07640f9fb8df2158199da1da1f8282948385a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Fri, 28 Nov 2025 16:36:38 +0000 Subject: [PATCH 32/34] rtc: max31335: Fix ignored return value in set_alarm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return the result from regmap_update_bits() instead of ignoring it and always returning 0. Fixes: dedaf03b99d6 ("rtc: max31335: add driver support") Signed-off-by: Nuno Sá Link: https://patch.msgid.link/20251128-max31335-handler-error-v1-1-6b6f7f78dbda@analog.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max31335.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c index dfb5bad3a369..23b7bf16b4cd 100644 --- a/drivers/rtc/rtc-max31335.c +++ b/drivers/rtc/rtc-max31335.c @@ -391,10 +391,8 @@ static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (ret) return ret; - ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg, - MAX31335_STATUS1_A1F, 0); - - return 0; + return regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg, + MAX31335_STATUS1_A1F, 0); } static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled) From 159a740c768e4e8fe3c63d20055bf54de29c0c02 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Nov 2025 13:48:56 +0300 Subject: [PATCH 33/34] rtc: atcrtc100: Fix signedness bug in probe() The "atcrtc_dev->alarm_irq" variable is an unsigned int but it needs to be signed for the error handling to work. Use the "ret" variable instead. Fixes: 7adca706fe16 ("rtc: atcrtc100: Add ATCRTC100 RTC driver") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/aRxPGBEX8hbY6sjV@stanley.mountain Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-atcrtc100.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-atcrtc100.c b/drivers/rtc/rtc-atcrtc100.c index 51933ae1a2fa..9808fc2c5a49 100644 --- a/drivers/rtc/rtc-atcrtc100.c +++ b/drivers/rtc/rtc-atcrtc100.c @@ -296,10 +296,12 @@ static int atcrtc_probe(struct platform_device *pdev) "Failed to initialize RTC: unsupported hardware ID 0x%x\n", rtc_id); - atcrtc_dev->alarm_irq = platform_get_irq(pdev, 1); - if (atcrtc_dev->alarm_irq < 0) - return dev_err_probe(&pdev->dev, atcrtc_dev->alarm_irq, + ret = platform_get_irq(pdev, 1); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Failed to get IRQ for alarm\n"); + atcrtc_dev->alarm_irq = ret; + ret = devm_request_irq(&pdev->dev, atcrtc_dev->alarm_irq, atcrtc_alarm_isr, From 16bd954c93360145bc77cc601e350913fc28182d Mon Sep 17 00:00:00 2001 From: Troy Mitchell Date: Tue, 18 Nov 2025 14:08:06 +0800 Subject: [PATCH 34/34] rtc: spacemit: MFD_SPACEMIT_P1 as dependencies RTC_DRV_SPACEMIT_P1 is a subdevice of P1 and should depend on MFD_SPACEMIT_P1 rather than selecting it directly. Using 'select' does not always respect the parent's dependencies, so 'depends on' is the safer and more correct choice. Additionally, the default value depends on MFD_SPACEMIT_P1 rather than ARCH_SPACEMIT. Signed-off-by: Troy Mitchell Acked-by: Alex Elder Link: https://patch.msgid.link/20251118-p1-kconfig-fix-v3-2-8839c5ac5db3@linux.spacemit.com Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9906cddd5a8b..50dc779f7f98 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -409,8 +409,8 @@ config RTC_DRV_MAX77686 config RTC_DRV_SPACEMIT_P1 tristate "SpacemiT P1 RTC" depends on ARCH_SPACEMIT || COMPILE_TEST - select MFD_SPACEMIT_P1 - default ARCH_SPACEMIT + depends on MFD_SPACEMIT_P1 + default MFD_SPACEMIT_P1 help Enable support for the RTC function in the SpacemiT P1 PMIC. This driver can also be built as a module, which will be called