Linux RTC
 help / color / mirror / Atom feed
* [PATCH] rtc: ds1343: replace symbolic permissions with octal
From: Jack Lee @ 2026-06-12 22:35 UTC (permalink / raw)
  To: alexandre.belloni; +Cc: linux-rtc, linux-kernel, Jack Lee

Symbolic permissions S_IRUGO and S_IWUSR are deprecated in favor of
octal permissions. Replace S_IRUGO|S_IWUSR with 0644 and S_IRUGO
with 0444.

Signed-off-by: Jack Lee <skunkolee@gmail.com>
---
 drivers/rtc/rtc-ds1343.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c
index aa9500791b7e..54f6af7886a8 100644
--- a/drivers/rtc/rtc-ds1343.c
+++ b/drivers/rtc/rtc-ds1343.c
@@ -120,7 +120,7 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev,
 	return count;
 }
 
-static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter,
+static DEVICE_ATTR(glitch_filter, 0644, ds1343_show_glitchfilter,
 			ds1343_store_glitchfilter);
 
 static int ds1343_nvram_write(void *priv, unsigned int off, void *val,
@@ -183,7 +183,7 @@ static ssize_t ds1343_show_tricklecharger(struct device *dev,
 	return sprintf(buf, "%s %s\n", diodes, resistors);
 }
 
-static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL);
+static DEVICE_ATTR(trickle_charger, 0444, ds1343_show_tricklecharger, NULL);
 
 static struct attribute *ds1343_attrs[] = {
 	&dev_attr_glitch_filter.attr,
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v6 1/7] dt-bindings: hwmon: Add Apple System Management Controller hwmon schema
From: Rob Herring @ 2026-06-12 22:07 UTC (permalink / raw)
  To: James Calligeros
  Cc: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
	Lee Jones, Krzysztof Kozlowski, Conor Dooley, Alexandre Belloni,
	Jean Delvare, Guenter Roeck, Dmitry Torokhov, Jonathan Corbet,
	asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
	linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251215-macsmc-subdevs-v6-1-0518cb5f28ae@gmail.com>

On Mon, Dec 15, 2025 at 07:37:45PM +1000, James Calligeros wrote:
> Apple Silicon devices integrate a vast array of sensors, monitoring
> current, power, temperature, and voltage across almost every part of
> the system. The sensors themselves are all connected to the System
> Management Controller (SMC). The SMC firmware exposes the data
> reported by these sensors via its standard FourCC-based key-value
> API. The SMC is also responsible for monitoring and controlling any
> fans connected to the system, exposing them in the same way.
> 
> For reasons known only to Apple, each device exposes its sensors with
> an almost totally unique set of keys. This is true even for devices
> which share an SoC. An M1 Mac mini, for example, will report its core
> temperatures on different keys to an M1 MacBook Pro. Worse still, the
> SMC does not provide a way to enumerate the available keys at runtime,
> nor do the keys follow any sort of reasonable or consistent naming
> rules that could be used to deduce their purpose. We must therefore
> know which keys are present on any given device, and which function
> they serve, ahead of time.
> 
> Add a schema so that we can describe the available sensors for a given
> Apple Silicon device in the Devicetree.
> 
> Reviewed-by: Neal Gompa <neal@gompa.dev>
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
>  .../bindings/hwmon/apple,smc-hwmon.yaml  | 86 +++++++++++++++++++++++++
>  .../bindings/mfd/apple,smc.yaml          | 36 +++++++++++
>  MAINTAINERS                              |  1 +
>  3 files changed, 123 insertions(+)

I fixed up the error and applied. Please ensure all your patches get 
applied.

Rob

^ permalink raw reply

* Re: [PATCH] rtc: meson: fix refcount leak in meson_rtc_get_bus
From: Philipp Zabel @ 2026-06-11  8:08 UTC (permalink / raw)
  To: WenTao Liang
  Cc: alexandre.belloni, neil.armstrong, khilman, jbrunet,
	martin.blumenstingl, ben.dooks, linux-rtc, linux-arm-kernel,
	linux-amlogic, linux-kernel, stable
In-Reply-To: <20260611035605.59906-1-vulab@iscas.ac.cn>

On Thu, Jun 11, 2026 at 11:56:05AM +0800, WenTao Liang wrote:
> In meson_rtc_get_bus(), reset_control_reset() is called to trigger
> a hardware reset when the serial bus is not ready. The function may
> retry up to three times, but neither the successful nor the failure
> path calls reset_control_rearm() to balance the reference count,
> leaking the triggered_count on shared reset controls.

Wrong, this driver uses exclusive reset control, which does not do any
refcounting. Arguably, it should request the reset control via
devm_regulator_get_exclusive() instead of devm_regulator_get() to
make this clear.

> Fix this by adding reset_control_rearm() after reset_control_reset()
> on both the error return path and the success path within the retry
> loop, ensuring the reset control can be re-triggered on subsequent
> bus acquisition attempts.

This doesn't fix anything, reset_control_rearm() does nothing and
should not be used with exclusive reset controls.

regards
Philipp

^ permalink raw reply

* [PATCH] rtc: meson: fix refcount leak in meson_rtc_get_bus
From: WenTao Liang @ 2026-06-11  3:56 UTC (permalink / raw)
  To: alexandre.belloni, neil.armstrong, khilman, p.zabel
  Cc: jbrunet, martin.blumenstingl, ben.dooks, linux-rtc,
	linux-arm-kernel, linux-amlogic, linux-kernel, WenTao Liang,
	stable

In meson_rtc_get_bus(), reset_control_reset() is called to trigger
a hardware reset when the serial bus is not ready. The function may
retry up to three times, but neither the successful nor the failure
path calls reset_control_rearm() to balance the reference count,
leaking the triggered_count on shared reset controls.

Fix this by adding reset_control_rearm() after reset_control_reset()
on both the error return path and the success path within the retry
loop, ensuring the reset control can be re-triggered on subsequent
bus acquisition attempts.

Cc: stable@vger.kernel.org
Fixes: d8fe6009aa3e ("rtc: support for the Amlogic Meson RTC")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
---
 drivers/rtc/rtc-meson.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c
index 21eceb9e2e13..729384dceb12 100644
--- a/drivers/rtc/rtc-meson.c
+++ b/drivers/rtc/rtc-meson.c
@@ -146,8 +146,12 @@ static int meson_rtc_get_bus(struct meson_rtc *rtc)
 		dev_warn(rtc->dev, "failed to get bus, resetting RTC\n");
 
 		ret = reset_control_reset(rtc->reset);
-		if (ret)
+		if (ret) {
+			reset_control_rearm(rtc->reset);
 			return ret;
+		}
+
+		reset_control_rearm(rtc->reset);
 	}
 
 	dev_err(rtc->dev, "bus is not ready\n");
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related

* [PATCH] rtc: meson: fix refcount leak in meson_rtc_get_bus
From: WenTao Liang @ 2026-06-11  3:40 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: neil.armstrong, khilman, jbrunet, martin.blumenstingl, p.zabel,
	ben.dooks, linux-rtc, linux-arm-kernel, linux-amlogic,
	linux-kernel, WenTao Liang, stable

In meson_rtc_get_bus(), reset_control_reset() is called to trigger
a hardware reset when the serial bus is not ready. The function may
retry up to three times, but neither the successful nor the failure
path calls reset_control_rearm() to balance the reference count,
leaking the triggered_count on shared reset controls.

Fix this by adding reset_control_rearm() after reset_control_reset()
on both the error return path and the success path within the retry
loop, ensuring the reset control can be re-triggered on subsequent
bus acquisition attempts.

Cc: stable@vger.kernel.org
Fixes: d8fe6009aa3e ("rtc: support for the Amlogic Meson RTC")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
---
 drivers/rtc/rtc-meson.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c
index 21eceb9e2e13..729384dceb12 100644
--- a/drivers/rtc/rtc-meson.c
+++ b/drivers/rtc/rtc-meson.c
@@ -146,8 +146,12 @@ static int meson_rtc_get_bus(struct meson_rtc *rtc)
 		dev_warn(rtc->dev, "failed to get bus, resetting RTC\n");
 
 		ret = reset_control_reset(rtc->reset);
-		if (ret)
+		if (ret) {
+			reset_control_rearm(rtc->reset);
 			return ret;
+		}
+
+		reset_control_rearm(rtc->reset);
 	}
 
 	dev_err(rtc->dev, "bus is not ready\n");
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related

* [PATCH] rtc: mv: add suspend/resume support for wakeup
From: Xue Lei @ 2026-06-11  2:33 UTC (permalink / raw)
  To: alexandre.belloni; +Cc: linux-rtc, linux-kernel, xue.lei

Add PM suspend/resume callbacks to enable/disable IRQ wake for the
RTC alarm interrupt. This allows the RTC alarm to wake the system
from STR (e.g. via rtcwake -m mem -s N).

Without this, the RTC IRQ is masked during suspend by the MPIC's
IRQCHIP_MASK_ON_SUSPEND behavior, preventing alarm-based wakeup.

Signed-off-by: Xue Lei <Xue.Lei@windriver.com>
---
 drivers/rtc/rtc-mv.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index db31da56bfa7..55fa937f9f70 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -301,6 +301,28 @@ static const struct of_device_id rtc_mv_of_match_table[] = {
 MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table);
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+static int mv_rtc_suspend(struct device *dev)
+{
+	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev) && pdata->irq >= 0)
+		enable_irq_wake(pdata->irq);
+	return 0;
+}
+
+static int mv_rtc_resume(struct device *dev)
+{
+	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev) && pdata->irq >= 0)
+		disable_irq_wake(pdata->irq);
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mv_rtc_pm_ops, mv_rtc_suspend, mv_rtc_resume);
+
 /*
  * mv_rtc_remove() lives in .exit.text. For drivers registered via
  * module_platform_driver_probe() this is ok because they cannot get unbound at
@@ -312,6 +334,7 @@ static struct platform_driver mv_rtc_driver __refdata = {
 	.driver		= {
 		.name	= "rtc-mv",
 		.of_match_table = of_match_ptr(rtc_mv_of_match_table),
+		.pm	= &mv_rtc_pm_ops,
 	},
 };
 
-- 
2.49.1


^ permalink raw reply related

* Re: [PATCH] rtc: interface: Add rtc time jump debug in rtc_timer_do_work()
From: Jinjie Ruan @ 2026-06-11  2:01 UTC (permalink / raw)
  To: alexandre.belloni, linux-rtc, linux-kernel, tglx
In-Reply-To: <20260525130825.954214-1-ruanjinjie@huawei.com>

+cc Thomas Gleixner

On 5/25/2026 9:08 PM, Jinjie Ruan wrote:
> In virtualization environments like QEMU [1], or during hardware
> clocksource anomalies, an extreme time-warp event can occur. When
> the system time abruptly jumps forward, the rtc_timer_do_work() handler
> falls into a prolonged processing loop to clear accumulated historical
> timers via timerqueue_getnext(). Running this loop indefinitely under
> the rtc->ops_lock mutex triggers a kernel softlockup, stalling
> the system.
> 
> Introduce an adaptive telemetry and loop guard mechanism to enhance debug
> visibility and prevent softlockups:
> 
> 1. Record `start_jiffies` upon entry and leverage `time_after()` to
>    check if the loop has monopolized the CPU for more than 1s (HZ). If so,
>    the handler prints a telemetry warning, triggers a WARN stack dump, and
>    breaks the loop to safely yield the CPU.
> 
> 2. Track the execution via a `loop_count` metric. Printing this counter
>    in the warning log provides vital diagnostics to distinguish
>    an aggressive time-warp storm (high count) from a bogged-down callback
>    bug (low count).
> 
> 3. Utilize the kernel format specifier `%ptR` to convert the raw ktime
>    into a human-readable timestamp (YYYY-MM-DD HH:MM:SS), allowing
>    developers to instantly pinpoint the exact boundary of the time
>    jump in dmesg.
> 
> This non-destructive telemetry guard provides precise hardware/emulator
> diagnostic visibility while ensuring core kernel availability.
> 
> [1]: https://lore.kernel.org/all/20260114013257.3500578-1-ruanjinjie@huawei.com/
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> ---
>  drivers/rtc/interface.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
> index 1906f4884a83..f6c5fd16cc4e 100644
> --- a/drivers/rtc/interface.c
> +++ b/drivers/rtc/interface.c
> @@ -927,10 +927,12 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
>   */
>  void rtc_timer_do_work(struct work_struct *work)
>  {
> -	struct rtc_timer *timer;
> +	unsigned long start_jiffies = jiffies;
>  	struct timerqueue_node *next;
> -	ktime_t now;
> +	struct rtc_timer *timer;
>  	struct rtc_time tm;
> +	int loop_count = 0;
> +	ktime_t now;
>  	int err;
>  
>  	struct rtc_device *rtc =
> @@ -945,6 +947,15 @@ void rtc_timer_do_work(struct work_struct *work)
>  	}
>  	now = rtc_tm_to_ktime(tm);
>  	while ((next = timerqueue_getnext(&rtc->timerqueue))) {
> +		loop_count++;
> +
> +		if (unlikely(time_after(jiffies, start_jiffies + HZ))) {
> +			dev_warn(&rtc->dev, "RTC time jump (loop: %d) to %ptR.\n",
> +				 loop_count, &tm);
> +			WARN_ON_ONCE(1);
> +			break;
> +		}
> +
>  		if (next->expires > now)
>  			break;
>  


^ permalink raw reply

* Re: [PATCH] rtc: interface: Add rtc time jump debug in rtc_timer_do_work()
From: Jinjie Ruan @ 2026-06-11  1:40 UTC (permalink / raw)
  To: alexandre.belloni, linux-rtc, linux-kernel
In-Reply-To: <20260525130825.954214-1-ruanjinjie@huawei.com>

Gentle ping.

On 5/25/2026 9:08 PM, Jinjie Ruan wrote:
> In virtualization environments like QEMU [1], or during hardware
> clocksource anomalies, an extreme time-warp event can occur. When
> the system time abruptly jumps forward, the rtc_timer_do_work() handler
> falls into a prolonged processing loop to clear accumulated historical
> timers via timerqueue_getnext(). Running this loop indefinitely under
> the rtc->ops_lock mutex triggers a kernel softlockup, stalling
> the system.
> 
> Introduce an adaptive telemetry and loop guard mechanism to enhance debug
> visibility and prevent softlockups:
> 
> 1. Record `start_jiffies` upon entry and leverage `time_after()` to
>    check if the loop has monopolized the CPU for more than 1s (HZ). If so,
>    the handler prints a telemetry warning, triggers a WARN stack dump, and
>    breaks the loop to safely yield the CPU.
> 
> 2. Track the execution via a `loop_count` metric. Printing this counter
>    in the warning log provides vital diagnostics to distinguish
>    an aggressive time-warp storm (high count) from a bogged-down callback
>    bug (low count).
> 
> 3. Utilize the kernel format specifier `%ptR` to convert the raw ktime
>    into a human-readable timestamp (YYYY-MM-DD HH:MM:SS), allowing
>    developers to instantly pinpoint the exact boundary of the time
>    jump in dmesg.
> 
> This non-destructive telemetry guard provides precise hardware/emulator
> diagnostic visibility while ensuring core kernel availability.
> 
> [1]: https://lore.kernel.org/all/20260114013257.3500578-1-ruanjinjie@huawei.com/
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> ---
>  drivers/rtc/interface.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
> index 1906f4884a83..f6c5fd16cc4e 100644
> --- a/drivers/rtc/interface.c
> +++ b/drivers/rtc/interface.c
> @@ -927,10 +927,12 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
>   */
>  void rtc_timer_do_work(struct work_struct *work)
>  {
> -	struct rtc_timer *timer;
> +	unsigned long start_jiffies = jiffies;
>  	struct timerqueue_node *next;
> -	ktime_t now;
> +	struct rtc_timer *timer;
>  	struct rtc_time tm;
> +	int loop_count = 0;
> +	ktime_t now;
>  	int err;
>  
>  	struct rtc_device *rtc =
> @@ -945,6 +947,15 @@ void rtc_timer_do_work(struct work_struct *work)
>  	}
>  	now = rtc_tm_to_ktime(tm);
>  	while ((next = timerqueue_getnext(&rtc->timerqueue))) {
> +		loop_count++;
> +
> +		if (unlikely(time_after(jiffies, start_jiffies + HZ))) {
> +			dev_warn(&rtc->dev, "RTC time jump (loop: %d) to %ptR.\n",
> +				 loop_count, &tm);
> +			WARN_ON_ONCE(1);
> +			break;
> +		}
> +
>  		if (next->expires > now)
>  			break;
>  


^ permalink raw reply

* Re: [PATCH v1] rtc: Use named initializers for arrays of i2c_device_data
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-10 17:07 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Antoniu Miclaus, Andrew Jeffery, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Tóth János, Dianlong Li, linux-rtc, linux-kernel,
	openbmc
In-Reply-To: <20260515154720.406128-2-u.kleine-koenig@baylibre.com>

[-- Attachment #1: Type: text/plain, Size: 917 bytes --]

Hello Alexandre,

On Fri, May 15, 2026 at 05:47:20PM +0200, Uwe Kleine-König (The Capable Hub) wrote:
> While being less compact, using named initializers allows to more easily
> see which members of the structs are assigned which value without having
> to lookup the declaration of the struct. And it's also more robust
> against changes to the struct definition.
> 
> The mentioned robustness is relevant for a planned change to struct
> i2c_device_id that replaces .driver_data by an anonymous union.
> 
> While touching all these arrays, unify usage of whitespace and commas.
> 
> This patch doesn't modify the compiled arrays, only their representation
> in source form benefits. The former was confirmed with x86 and arm64
> builds.
> 
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>

Is there a chance to still get this into 7.2-rc1?

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH] rtc: ds1307: update reference to removed CONFIG_RTC_DRV_DS1307_HWMON
From: Ethan Nelson-Moore @ 2026-06-10  5:47 UTC (permalink / raw)
  To: linux-rtc; +Cc: Heiner Kallweit, Ethan Nelson-Moore, Alexandre Belloni

The CONFIG_RTC_DRV_DS1307_HWMON macro was removed in favor of
CONFIG_HWMON in commit 6b583a64fd1e ("rtc: ds1307: simplify hwmon
config"), but a reference to it remained in a comment. Correct this
reference.

Discovered while searching for CONFIG_* symbols referenced in code but
not defined in any Kconfig file.

Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
 drivers/rtc/rtc-ds1307.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 7205c59ff729..6dce01e3373a 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -1409,7 +1409,7 @@ static void ds1307_hwmon_register(struct ds1307 *ds1307)
 {
 }
 
-#endif /* CONFIG_RTC_DRV_DS1307_HWMON */
+#endif /* IS_REACHABLE(CONFIG_HWMON) */
 
 /*----------------------------------------------------------------------*/
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 2/2] m68k: coldfire/m5441x: register the on-chip RTC
From: Jean-Michel Hautbois @ 2026-06-07  9:00 UTC (permalink / raw)
  To: Alexandre Belloni, Greg Ungerer, Geert Uytterhoeven
  Cc: linux-kernel, linux-rtc, linux-m68k, Jean-Michel Hautbois
In-Reply-To: <20260607-jmh-upstream-coldfire-rtc-v2-0-948d2b1ed146@yoseli.org>

Register the MCF5441x on-chip RTC platform device from the SoC code so
every MCF5441x board gets the rtc-m5441x driver (time/calendar plus the
battery-backed standby RAM via nvmem) without a per-board file.

Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
---
 arch/m68k/coldfire/m5441x.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/arch/m68k/coldfire/m5441x.c b/arch/m68k/coldfire/m5441x.c
index 7a25cfc7ac07..b79aebdfd567 100644
--- a/arch/m68k/coldfire/m5441x.c
+++ b/arch/m68k/coldfire/m5441x.c
@@ -10,6 +10,7 @@
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -239,6 +240,34 @@ static void __init m5441x_fec_init(void)
 	__raw_writeb(0x03, MCFGPIO_PAR_FEC);
 }
 
+/*
+ * On-chip "robust" RTC. Exposes the time/calendar and the 2KB
+ * battery-backed standby RAM (rtc-m5441x driver).
+ */
+static struct resource m5441x_rtc_resource[] = {
+	{
+		.start	= MCFRTC_BASE,
+		.end	= MCFRTC_BASE + MCFRTC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MCF_IRQ_RTC,
+		.end	= MCF_IRQ_RTC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static int __init m5441x_rtc_init(void)
+{
+	struct platform_device *pdev;
+
+	pdev = platform_device_register_simple("rtc-m5441x", -1,
+					       m5441x_rtc_resource,
+					       ARRAY_SIZE(m5441x_rtc_resource));
+	return PTR_ERR_OR_ZERO(pdev);
+}
+arch_initcall(m5441x_rtc_init);
+
 void __init config_BSP(char *commandp, int size)
 {
 	m5441x_clk_init();

-- 
2.39.5


^ permalink raw reply related

* [PATCH v2 1/2] rtc: m5441x: add MCF5441x on-chip RTC driver
From: Jean-Michel Hautbois @ 2026-06-07  9:00 UTC (permalink / raw)
  To: Alexandre Belloni, Greg Ungerer, Geert Uytterhoeven
  Cc: linux-kernel, linux-rtc, linux-m68k, Jean-Michel Hautbois
In-Reply-To: <20260607-jmh-upstream-coldfire-rtc-v2-0-948d2b1ed146@yoseli.org>

Add an rtc-class driver for the Freescale MCF5441x on-chip "robust" RTC.
It provides the time/calendar and alarm, and exposes the 2KB
battery-backed standby RAM through the nvmem framework so userspace can
preserve data across a main-power loss (the RAM is retained while
VSTBY_RTC is supplied).

Register and standby-RAM writes go through the RTC_CR[WE] knock
sequence; the base-2112 year encoding and register map follow the
MCF54418 reference manual. Based on the out-of-tree Freescale 3.0.x
rtc-m5441x driver, rewritten for the current RTC and nvmem APIs.

Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
---
 MAINTAINERS              |   6 +
 drivers/rtc/Kconfig      |  12 +
 drivers/rtc/Makefile     |   1 +
 drivers/rtc/rtc-m5441x.c | 579 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 598 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e035a3be797c..44901a34499a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10196,6 +10196,12 @@ S:	Maintained
 F:	drivers/mmc/host/sdhci-esdhc-mcf.c
 F:	include/linux/platform_data/mmc-esdhc-mcf.h
 
+FREESCALE COLDFIRE M5441X RTC DRIVER
+M:	Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
+L:	linux-rtc@vger.kernel.org
+S:	Maintained
+F:	drivers/rtc/rtc-m5441x.c
+
 FREESCALE DIU FRAMEBUFFER DRIVER
 M:	Timur Tabi <timur@kernel.org>
 L:	linux-fbdev@vger.kernel.org
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 364afc73f8ab..45362247a56c 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1427,6 +1427,18 @@ config RTC_DRV_NTXEC
 
 comment "on-CPU RTC drivers"
 
+config RTC_DRV_M5441X
+	tristate "Freescale MCF5441x on-chip RTC"
+	depends on M5441x || COMPILE_TEST
+	help
+	  If you say yes here you get support for the on-chip "robust"
+	  real time clock found on Freescale MCF5441x ColdFire SoCs,
+	  including its 2KB battery-backed standby RAM exposed through the
+	  nvmem framework.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-m5441x.
+
 config RTC_DRV_ASM9260
 	tristate "Alphascale asm9260 RTC"
 	depends on MACH_ASM9260 || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6cf7e066314e..4c7cb67fbc3f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
 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_M5441X)	+= rtc-m5441x.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
diff --git a/drivers/rtc/rtc-m5441x.c b/drivers/rtc/rtc-m5441x.c
new file mode 100644
index 000000000000..4e4834b2c956
--- /dev/null
+++ b/drivers/rtc/rtc-m5441x.c
@@ -0,0 +1,579 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RTC driver for the Freescale MCF5441x on-chip "robust" RTC.
+ *
+ * Exposes the time/calendar and alarm, plus the 2KB battery-backed
+ * standby RAM as an nvmem device. The standby RAM survives main-power
+ * loss while VSTBY_RTC is supplied, which makes it usable to persist a
+ * reset/reboot counter across power cycles.
+ *
+ * Register layout and the base-2112 year encoding are taken from the
+ * MCF54418 reference manual (chapter "Robust Real Time Clock").
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2026 Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
+ *
+ * Based on the out-of-tree Freescale 3.0.x rtc-m5441x driver by
+ * Lanttor Guo <Lanttor.Guo@freescale.com>, rewritten for the current
+ * RTC and nvmem frameworks.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+
+/* Register offsets from the RTC base. */
+#define M5441X_RTC_YEARMON	0x00
+#define M5441X_RTC_DAYS		0x02
+#define M5441X_RTC_HOURMIN	0x04
+#define M5441X_RTC_SECONDS	0x06
+#define M5441X_RTC_ALM_YRMON	0x08
+#define M5441X_RTC_ALM_DAYS	0x0a
+#define M5441X_RTC_ALM_HM	0x0c
+#define M5441X_RTC_ALM_SEC	0x0e
+#define M5441X_RTC_CR		0x10
+#define M5441X_RTC_SR		0x12
+#define M5441X_RTC_ISR		0x14
+#define M5441X_RTC_IER		0x16
+#define M5441X_RTC_CFG_DATA	0x20
+
+/* RTC_CR bits. Only WE is freely writable; the rest need the WE knock. */
+#define M5441X_RTC_CR_RSVD	0x8000	/* bit 15, reserved, must be set */
+#define M5441X_RTC_CR_BCDEN	0x0080	/* 0 = binary, 1 = BCD time/date */
+#define M5441X_RTC_CR_DSTEN	0x0040	/* daylight-saving auto-adjust */
+#define M5441X_RTC_CR_AM_MASK	0x000c	/* alarm match field */
+#define M5441X_RTC_CR_AM_FULL	0x000c	/* match s,m,h,day,month,year */
+#define M5441X_RTC_CR_WE_MASK	0x0003	/* write-enable knock field */
+
+#define M5441X_RTC_SR_INVAL	0x0001	/* time invalid / changing */
+#define M5441X_RTC_SR_WPE	0x0010	/* write protection enabled */
+#define M5441X_RTC_ISR_ALM	0x0004	/* alarm interrupt status/enable */
+#define M5441X_RTC_IER_RSVD	0x0001	/* IER/ISR bit 0 reserved, must be set */
+#define M5441X_RTC_CFG_OSCEN	0x0008	/* oscillator enable */
+
+/* Battery-backed standby RAM: 2KB at this offset within the block. */
+#define M5441X_RTC_SRAM_OFFSET	0x40
+#define M5441X_RTC_SRAM_SIZE	2048
+#define M5441X_RTC_SRAM_CHUNK	64	/* lock-drop granularity for SRAM I/O */
+
+#define M5441X_RTC_YEAR_BASE	2112
+
+struct m5441x_rtc {
+	struct rtc_device *rtc;
+	void __iomem *base;
+	spinlock_t lock;	/* serialises register access + WP window */
+	bool osc_dead;		/* 32kHz oscillator never started; no timekeeping */
+};
+
+static inline u16 rtc_rd(struct m5441x_rtc *p, unsigned int reg)
+{
+	return ioread16be(p->base + reg);
+}
+
+static inline void rtc_wr(struct m5441x_rtc *p, unsigned int reg, u16 val)
+{
+	iowrite16be(val, p->base + reg);
+}
+
+/*
+ * Issue the RTC_CR[WE] knock (00 -> 01 -> 11 -> 10) that opens the
+ * write-protection window. Writes to the registers and the standby RAM
+ * are rejected unless this sequence has been issued; the space then
+ * stays writable for ~2 seconds. Caller holds p->lock.
+ */
+static void m5441x_rtc_knock(struct m5441x_rtc *p)
+{
+	rtc_wr(p, M5441X_RTC_CR, 0x0000);
+	rtc_wr(p, M5441X_RTC_CR, 0x0001);
+	rtc_wr(p, M5441X_RTC_CR, 0x0003);
+	rtc_wr(p, M5441X_RTC_CR, 0x0002);
+}
+
+/* Open the write window only if protection is currently enabled. */
+static void m5441x_rtc_unlock(struct m5441x_rtc *p)
+{
+	if (rtc_rd(p, M5441X_RTC_SR) & M5441X_RTC_SR_WPE)
+		m5441x_rtc_knock(p);
+}
+
+/*
+ * Write the data bits of RTC_CR (BCDEN/DSTEN/AM). Caller holds p->lock
+ * and must have opened the write window first. The reserved bit 15 is
+ * kept set and the WE field kept clear so the write updates the data
+ * bits without re-arming write protection (a lone WE=10 would).
+ */
+static void m5441x_rtc_write_cr(struct m5441x_rtc *p, u16 val)
+{
+	val &= ~M5441X_RTC_CR_WE_MASK;
+	val |= M5441X_RTC_CR_RSVD;
+	rtc_wr(p, M5441X_RTC_CR, val);
+}
+
+/*
+ * The time counters are unstable for an oscillator cycle either side of
+ * the one-second boundary. RTC_SR[INVAL] flags this; reads during the
+ * window return 0xffff and writes are nullified. Poll until it clears.
+ * The window is only a couple of 32kHz cycles (~60us), so bound the
+ * busy-wait tightly. This runs with the lock held and interrupts off, so
+ * poll atomically (no sleeping). Caller holds p->lock.
+ */
+static int m5441x_rtc_wait_valid(struct m5441x_rtc *p)
+{
+	u16 sr;
+	int ret;
+
+	ret = read_poll_timeout_atomic(rtc_rd, sr, !(sr & M5441X_RTC_SR_INVAL),
+				       10, 100, false, p, M5441X_RTC_SR);
+
+	return ret ? -EIO : 0;
+}
+
+static int m5441x_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct m5441x_rtc *p = dev_get_drvdata(dev);
+	u16 yearmon, days, hourmin, seconds;
+	unsigned int tries = 3;
+	unsigned long flags;
+	int ret;
+
+	/*
+	 * Without a running oscillator the counters are frozen; refuse the
+	 * read rather than hand userspace a stale time that hwclock --hctosys
+	 * would propagate into the system clock.
+	 */
+	if (p->osc_dead)
+		return -ENODATA;
+
+	/*
+	 * INVAL only guarantees the counters are stable at the moment it is
+	 * checked; it does not freeze them across the four reads. If a 1Hz
+	 * tick re-asserts INVAL mid-burst the fields can straddle a second
+	 * boundary (e.g. 23:59:59 -> 00:00:00), so re-check it afterwards and
+	 * retry the whole burst on observed re-entry.
+	 */
+	spin_lock_irqsave(&p->lock, flags);
+	do {
+		ret = m5441x_rtc_wait_valid(p);
+		if (ret)
+			break;
+		yearmon = rtc_rd(p, M5441X_RTC_YEARMON);
+		days    = rtc_rd(p, M5441X_RTC_DAYS);
+		hourmin = rtc_rd(p, M5441X_RTC_HOURMIN);
+		seconds = rtc_rd(p, M5441X_RTC_SECONDS);
+		/* Stable across the whole burst -> the snapshot is coherent. */
+		if (!(rtc_rd(p, M5441X_RTC_SR) & M5441X_RTC_SR_INVAL))
+			break;
+		ret = -EAGAIN;
+	} while (--tries);
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	if (ret)
+		return ret;
+
+	tm->tm_year = M5441X_RTC_YEAR_BASE + (s8)((yearmon >> 8) & 0xff) - 1900;
+	tm->tm_mon  = (yearmon & 0xff) - 1;
+	tm->tm_mday = days & 0xff;
+	tm->tm_wday = (days >> 8) & 0x7;
+	tm->tm_hour = (hourmin >> 8) & 0x1f;
+	tm->tm_min  = hourmin & 0x3f;
+	tm->tm_sec  = seconds & 0x3f;
+
+	return 0;
+}
+
+static int m5441x_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct m5441x_rtc *p = dev_get_drvdata(dev);
+	s8 yoff = (tm->tm_year + 1900) - M5441X_RTC_YEAR_BASE;
+	unsigned int tries = 3;
+	unsigned long flags;
+	int ret;
+
+	/* A frozen oscillator would never latch the new time; reject it. */
+	if (p->osc_dead)
+		return -ENODATA;
+
+	/*
+	 * Writes are nullified while INVAL is asserted. wait_valid() clears
+	 * the path before the burst, but the knock plus four writes can cross
+	 * a second boundary on a slow RTC bus, silently dropping fields.
+	 * Re-check INVAL afterwards and rewrite on observed re-entry.
+	 */
+	spin_lock_irqsave(&p->lock, flags);
+	do {
+		ret = m5441x_rtc_wait_valid(p);
+		if (ret)
+			break;
+		m5441x_rtc_unlock(p);
+		rtc_wr(p, M5441X_RTC_YEARMON,
+		       ((u16)((u8)yoff) << 8) | ((tm->tm_mon + 1) & 0xff));
+		rtc_wr(p, M5441X_RTC_DAYS,
+		       ((tm->tm_wday & 0x7) << 8) | (tm->tm_mday & 0x1f));
+		rtc_wr(p, M5441X_RTC_HOURMIN,
+		       ((tm->tm_hour & 0x1f) << 8) | (tm->tm_min & 0x3f));
+		rtc_wr(p, M5441X_RTC_SECONDS, tm->tm_sec & 0x3f);
+		/* No boundary crossed mid-burst -> the writes all took. */
+		if (!(rtc_rd(p, M5441X_RTC_SR) & M5441X_RTC_SR_INVAL))
+			break;
+		ret = -EAGAIN;
+	} while (--tries);
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	return ret;
+}
+
+static int m5441x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct m5441x_rtc *p = dev_get_drvdata(dev);
+	u16 yearmon, days, hourmin, seconds, ier, isr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->lock, flags);
+	yearmon = rtc_rd(p, M5441X_RTC_ALM_YRMON);
+	days    = rtc_rd(p, M5441X_RTC_ALM_DAYS);
+	hourmin = rtc_rd(p, M5441X_RTC_ALM_HM);
+	seconds = rtc_rd(p, M5441X_RTC_ALM_SEC);
+	ier     = rtc_rd(p, M5441X_RTC_IER);
+	isr     = rtc_rd(p, M5441X_RTC_ISR);
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	alrm->time.tm_year = M5441X_RTC_YEAR_BASE +
+			     (s8)((yearmon >> 8) & 0xff) - 1900;
+	alrm->time.tm_mon  = (yearmon & 0xff) - 1;
+	alrm->time.tm_mday = days & 0xff;
+	alrm->time.tm_hour = (hourmin >> 8) & 0x1f;
+	alrm->time.tm_min  = hourmin & 0x3f;
+	alrm->time.tm_sec  = seconds & 0x3f;
+	alrm->enabled = !!(ier & M5441X_RTC_ISR_ALM);
+	alrm->pending = !!(isr & M5441X_RTC_ISR_ALM);
+
+	return 0;
+}
+
+static int m5441x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct m5441x_rtc *p = dev_get_drvdata(dev);
+	unsigned long flags;
+	u16 ier;
+
+	spin_lock_irqsave(&p->lock, flags);
+	m5441x_rtc_unlock(p);
+	ier = rtc_rd(p, M5441X_RTC_IER);
+	if (enabled) {
+		/*
+		 * The comparator latches ISR_ALM even while IER masks delivery,
+		 * so a match from a previous arming (or one surviving a reboot)
+		 * would fire the moment IER is unmasked. Clear it first.
+		 */
+		rtc_wr(p, M5441X_RTC_ISR, M5441X_RTC_ISR_ALM);
+		ier |= M5441X_RTC_ISR_ALM;
+	} else {
+		ier &= ~M5441X_RTC_ISR_ALM;
+	}
+	rtc_wr(p, M5441X_RTC_IER, ier);
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	return 0;
+}
+
+static int m5441x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct m5441x_rtc *p = dev_get_drvdata(dev);
+	s8 yoff = (alrm->time.tm_year + 1900) - M5441X_RTC_YEAR_BASE;
+	unsigned long flags;
+	u16 ier, cr;
+
+	spin_lock_irqsave(&p->lock, flags);
+	m5441x_rtc_unlock(p);
+	/* acknowledge any pending alarm (write-1-to-clear) */
+	rtc_wr(p, M5441X_RTC_ISR, M5441X_RTC_ISR_ALM);
+
+	/*
+	 * Match the full date so the alarm is a one-shot rather than the
+	 * hardware default of a daily hour:minute:second match.
+	 */
+	cr = rtc_rd(p, M5441X_RTC_CR);
+	m5441x_rtc_write_cr(p, (cr & ~M5441X_RTC_CR_AM_MASK) |
+				M5441X_RTC_CR_AM_FULL);
+
+	rtc_wr(p, M5441X_RTC_ALM_YRMON,
+	       ((u16)((u8)yoff) << 8) | ((alrm->time.tm_mon + 1) & 0xff));
+	/* RTC_ALM_DAYS has no day-of-week field; bits [15:8] are reserved. */
+	rtc_wr(p, M5441X_RTC_ALM_DAYS, alrm->time.tm_mday & 0x1f);
+	rtc_wr(p, M5441X_RTC_ALM_HM,
+	       ((alrm->time.tm_hour & 0x1f) << 8) | (alrm->time.tm_min & 0x3f));
+	rtc_wr(p, M5441X_RTC_ALM_SEC, alrm->time.tm_sec & 0x3f);
+
+	ier = rtc_rd(p, M5441X_RTC_IER);
+	if (alrm->enabled)
+		ier |= M5441X_RTC_ISR_ALM;
+	else
+		ier &= ~M5441X_RTC_ISR_ALM;
+	rtc_wr(p, M5441X_RTC_IER, ier);
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	return 0;
+}
+
+static irqreturn_t m5441x_rtc_irq(int irq, void *dev_id)
+{
+	struct m5441x_rtc *p = dev_id;
+	u16 status;
+
+	spin_lock(&p->lock);
+	/*
+	 * Mask the reserved bit 0 (always reads set) so only a real source
+	 * can claim the interrupt.
+	 */
+	status = rtc_rd(p, M5441X_RTC_ISR) & rtc_rd(p, M5441X_RTC_IER) &
+		 ~M5441X_RTC_IER_RSVD;
+	if (status) {
+		m5441x_rtc_unlock(p);
+		rtc_wr(p, M5441X_RTC_ISR, status);	/* write-1-to-clear */
+	}
+	spin_unlock(&p->lock);
+
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & M5441X_RTC_ISR_ALM)
+		rtc_update_irq(p->rtc, 1, RTC_AF | RTC_IRQF);
+
+	/*
+	 * A hardware source was acknowledged above; claim the IRQ even when it
+	 * was not the alarm so genirq's spurious detector does not disable the
+	 * shared line.
+	 */
+	return IRQ_HANDLED;
+}
+
+static int m5441x_rtc_nvram_read(void *priv, unsigned int offset,
+				 void *val, size_t bytes)
+{
+	struct m5441x_rtc *p = priv;
+	u8 *buf = val;
+	size_t done;
+
+	/*
+	 * In-kernel nvmem_device_read() forwards offset/bytes verbatim, so
+	 * range-check here rather than trust the caller.
+	 */
+	if (offset >= M5441X_RTC_SRAM_SIZE ||
+	    bytes > M5441X_RTC_SRAM_SIZE - offset)
+		return -EINVAL;
+
+	/*
+	 * Process the transfer in chunks, releasing the lock between them, so
+	 * a full 2KB access does not keep hard interrupts disabled across
+	 * thousands of slow on-chip MMIO cycles and wreck IRQ latency.
+	 */
+	for (done = 0; done < bytes; done += M5441X_RTC_SRAM_CHUNK) {
+		unsigned int chunk = min_t(unsigned int, bytes - done,
+					   M5441X_RTC_SRAM_CHUNK);
+		unsigned int i;
+
+		scoped_guard(spinlock_irqsave, &p->lock)
+			for (i = 0; i < chunk; i++)
+				buf[done + i] = ioread8(p->base + M5441X_RTC_SRAM_OFFSET +
+							offset + done + i);
+	}
+
+	return 0;
+}
+
+static int m5441x_rtc_nvram_write(void *priv, unsigned int offset,
+				  void *val, size_t bytes)
+{
+	struct m5441x_rtc *p = priv;
+	u8 *buf = val;
+	size_t done;
+
+	/* See the read path: validate the range, the core does not. */
+	if (offset >= M5441X_RTC_SRAM_SIZE ||
+	    bytes > M5441X_RTC_SRAM_SIZE - offset)
+		return -EINVAL;
+
+	/*
+	 * Chunk the write and drop the lock between chunks (see the read
+	 * path). The write window stays open for ~2 seconds, far longer than
+	 * one chunk takes, so re-knock at the start of each chunk to keep it
+	 * open across the lock-drop.
+	 */
+	for (done = 0; done < bytes; done += M5441X_RTC_SRAM_CHUNK) {
+		unsigned int chunk = min_t(unsigned int, bytes - done,
+					   M5441X_RTC_SRAM_CHUNK);
+		unsigned int i;
+
+		scoped_guard(spinlock_irqsave, &p->lock) {
+			m5441x_rtc_knock(p);
+			for (i = 0; i < chunk; i++)
+				iowrite8(buf[done + i], p->base + M5441X_RTC_SRAM_OFFSET +
+					 offset + done + i);
+		}
+	}
+
+	return 0;
+}
+
+static const struct rtc_class_ops m5441x_rtc_ops = {
+	.read_time		= m5441x_rtc_read_time,
+	.set_time		= m5441x_rtc_set_time,
+	.read_alarm		= m5441x_rtc_read_alarm,
+	.set_alarm		= m5441x_rtc_set_alarm,
+	.alarm_irq_enable	= m5441x_rtc_alarm_irq_enable,
+};
+
+static int m5441x_rtc_probe(struct platform_device *pdev)
+{
+	struct nvmem_config nvmem_cfg = {
+		.name		= "m5441x_rtc_sram",
+		.type		= NVMEM_TYPE_BATTERY_BACKED,
+		.word_size	= 1,
+		.stride		= 1,
+		.size		= M5441X_RTC_SRAM_SIZE,
+		.reg_read	= m5441x_rtc_nvram_read,
+		.reg_write	= m5441x_rtc_nvram_write,
+	};
+	struct m5441x_rtc *p;
+	unsigned long flags;
+	bool osc_dead = false;
+	int irq, ret;
+	u16 cr, cfg;
+
+	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	spin_lock_init(&p->lock);
+
+	p->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(p->base))
+		return PTR_ERR(p->base);
+
+	platform_set_drvdata(pdev, p);
+
+	/* Enable the oscillator if needed and mask/clear stale interrupts. */
+	spin_lock_irqsave(&p->lock, flags);
+	m5441x_rtc_unlock(p);
+	/*
+	 * Force binary, DST-free time/date encoding. The driver does not
+	 * handle the BCD format, and Linux expects the RTC to keep monotonic
+	 * time with local-time/DST conversion done in userspace, so clear
+	 * BCDEN and DSTEN in case a bootloader or prior OS left them set. Also
+	 * default the alarm match field to a full one-shot match: the reset
+	 * value (AM=00) is a daily hh:mm:ss match, which would fire on the
+	 * wrong day if userspace enables the alarm via RTC_AIE_ON without
+	 * first programming it through set_alarm().
+	 */
+	cr = rtc_rd(p, M5441X_RTC_CR);
+	cr &= ~(M5441X_RTC_CR_BCDEN | M5441X_RTC_CR_DSTEN | M5441X_RTC_CR_AM_MASK);
+	cr |= M5441X_RTC_CR_AM_FULL;
+	m5441x_rtc_write_cr(p, cr);
+
+	/*
+	 * The alarm registers are battery-backed and survive a power cycle,
+	 * so a previously armed match could re-fire before set_alarm() runs.
+	 * Clear them now (the write window is open).
+	 */
+	rtc_wr(p, M5441X_RTC_ALM_YRMON, 0);
+	rtc_wr(p, M5441X_RTC_ALM_DAYS, 0);
+	rtc_wr(p, M5441X_RTC_ALM_HM, 0);
+	rtc_wr(p, M5441X_RTC_ALM_SEC, 0);
+
+	/*
+	 * Enable the 32kHz oscillator that drives the time counters. This only
+	 * checks that the OSCEN enable bit latches: when it reads back clear
+	 * the oscillator block rejected the enable, which in practice means no
+	 * RTC crystal is fitted and the counters will never advance. It cannot
+	 * tell a dead crystal from one still starting up, so it is a best-
+	 * effort hint, not a liveness guarantee. Warn but keep probing, since
+	 * the battery-backed standby RAM stays usable without the oscillator.
+	 */
+	cfg = rtc_rd(p, M5441X_RTC_CFG_DATA);
+	if (!(cfg & M5441X_RTC_CFG_OSCEN)) {
+		rtc_wr(p, M5441X_RTC_CFG_DATA, cfg | M5441X_RTC_CFG_OSCEN);
+		if (!(rtc_rd(p, M5441X_RTC_CFG_DATA) & M5441X_RTC_CFG_OSCEN))
+			osc_dead = true;
+	}
+
+	/* Mask every source but keep the reserved bit 0 set as required. */
+	rtc_wr(p, M5441X_RTC_IER, M5441X_RTC_IER_RSVD);
+	rtc_wr(p, M5441X_RTC_ISR, rtc_rd(p, M5441X_RTC_ISR));
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	/*
+	 * Keep the device (and its standby-RAM nvmem) usable, but record the
+	 * dead oscillator so read_time/set_time refuse to expose a clock that
+	 * cannot tick.
+	 */
+	p->osc_dead = osc_dead;
+	if (osc_dead)
+		dev_warn(&pdev->dev,
+			 "RTC oscillator enable did not latch; timekeeping unavailable (no 32kHz crystal?)\n");
+
+	p->rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(p->rtc))
+		return PTR_ERR(p->rtc);
+
+	p->rtc->ops = &m5441x_rtc_ops;
+	p->rtc->range_min = mktime64(1984, 1, 1, 0, 0, 0);
+	p->rtc->range_max = mktime64(2239, 12, 31, 23, 59, 59);
+
+	irq = platform_get_irq_optional(pdev, 0);
+	if (irq > 0) {
+		ret = devm_request_irq(&pdev->dev, irq, m5441x_rtc_irq, 0,
+				       dev_name(&pdev->dev), p);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to request IRQ %d: %d, alarm disabled\n",
+				irq, ret);
+			clear_bit(RTC_FEATURE_ALARM, p->rtc->features);
+		} else {
+			/*
+			 * The alarm comparator runs on standby power, so let it
+			 * wake a suspended system. The PM core keeps the IRQ
+			 * enabled across suspend once it is the device's wake
+			 * IRQ; both are device-managed.
+			 */
+			devm_device_init_wakeup(&pdev->dev);
+			devm_pm_set_wake_irq(&pdev->dev, irq);
+		}
+	} else {
+		clear_bit(RTC_FEATURE_ALARM, p->rtc->features);
+	}
+
+	/*
+	 * Register the RTC device before the nvmem provider:
+	 * devm_rtc_nvmem_register() copies rtc->owner into the nvmem config,
+	 * and that field is only assigned by devm_rtc_register_device().
+	 * Registering nvmem first would leave its owner NULL and fail to pin
+	 * this module while standby-RAM consumers hold references.
+	 */
+	ret = devm_rtc_register_device(p->rtc);
+	if (ret)
+		return ret;
+
+	nvmem_cfg.priv = p;
+	ret = devm_rtc_nvmem_register(p->rtc, &nvmem_cfg);
+	if (ret)
+		dev_warn(&pdev->dev, "standby RAM nvmem unavailable: %d\n", ret);
+
+	return 0;
+}
+
+static struct platform_driver m5441x_rtc_driver = {
+	.driver = {
+		.name = "rtc-m5441x",
+	},
+	.probe = m5441x_rtc_probe,
+};
+module_platform_driver(m5441x_rtc_driver);
+
+MODULE_DESCRIPTION("Freescale MCF5441x on-chip RTC driver");
+MODULE_AUTHOR("Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rtc-m5441x");

-- 
2.39.5


^ permalink raw reply related

* [PATCH v2 0/2] rtc: add a driver for the Freescale MCF5441x on-chip RTC
From: Jean-Michel Hautbois @ 2026-06-07  9:00 UTC (permalink / raw)
  To: Alexandre Belloni, Greg Ungerer, Geert Uytterhoeven
  Cc: linux-kernel, linux-rtc, linux-m68k, Jean-Michel Hautbois

This series adds support for the "robust" real time clock found on the
Freescale MCF5441x family of ColdFire SoCs.

Patch 1 adds the rtc-class driver. Besides the usual time/calendar and a
one-shot alarm, the block contains 2KB of battery-backed standby RAM that
survives a main-power loss while VSTBY_RTC is supplied; the driver exposes
it through the nvmem framework so userspace can persist data (for example a
reset/reboot counter) across power cycles. Register and standby-RAM writes
go through the RTC_CR[WE] knock sequence, the time counters are read under
the RTC_SR[INVAL] guard described in the reference manual, and the time/date
encoding is forced to binary at probe.

Patch 2 registers the platform device from the m5441x ColdFire SoC support
code so that every MCF5441x board gets the RTC. The MCFRTC_BASE, MCFRTC_SIZE
and MCF_IRQ_RTC definitions it relies on already exist in
arch/m68k/include/asm/m5441xsim.h.

The driver has been exercised on an MCF54418-based board: it registers
as an rtc device, exposes the standby RAM as an nvmem device, and a value
written to the standby RAM survives a mains power-cycle.

Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
---
Changes in v2:
- Patch 1: wait_valid() now uses read_poll_timeout_atomic() instead of an
  open-coded busy-wait. The atomic variant is required because it runs with
  p->lock held and interrupts off. (Geert Uytterhoeven)
- Patch 1: nvram_read()/nvram_write() use unsigned int rather than size_t
  for the chunk/index locals, and scoped_guard(spinlock_irqsave) instead of
  explicit spin_lock_irqsave()/spin_unlock_irqrestore(). (Geert Uytterhoeven)
- Link to v1: https://patch.msgid.link/20260602-jmh-upstream-coldfire-rtc-v1-0-1e129a177d2f@yoseli.org

---
Jean-Michel Hautbois (2):
      rtc: m5441x: add MCF5441x on-chip RTC driver
      m68k: coldfire/m5441x: register the on-chip RTC

 MAINTAINERS                 |   6 +
 arch/m68k/coldfire/m5441x.c |  29 +++
 drivers/rtc/Kconfig         |  12 +
 drivers/rtc/Makefile        |   1 +
 drivers/rtc/rtc-m5441x.c    | 579 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 627 insertions(+)
---
base-commit: 979c294509f9248fe1e7c358d582fb37dd5ca12d
change-id: 20260529-jmh-upstream-coldfire-rtc-88b095b2cf28

Best regards,
--  
Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>


^ permalink raw reply

* Re: [PATCH v5] dt-bindings: clock: via,vt8500: Convert to DT Schema
From: Uday Kiran @ 2026-06-06 18:10 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: alchark, robh, krzk+dt, conor+dt, skhan, me, linux-rtc,
	devicetree, linux-kernel
In-Reply-To: <20260601-zealous-loutish-termite-ccfc8f@quoll>

> > Convert the VIA/Wondermedia VT8500 and Wondermedia WM8xxx series SoCs clock
> > controller binding from the legacy text format to DT schema.
> >
> > Signed-off-by: Udaya Kiran Challa <challauday369@gmail.com>
> > ---
> > Changelog:
> > Changes since v4:
>
> My comments from v2 still apply. Almost all of them.
>
> You a PMC binding and preferrably all this goes to that binding.

Understood, Krzysztof!

The current separation between the PMC binding and the clock binding may not
reflect the hardware correctly, since the clock controller functionality is
implemented as part of the PMC and all clock-specific registers are offsets
within the PMC register space.

Request you to please confirm on the below points to proceed for next revision
of YAML conversion.

1. It will be a standalone PMC schema (`via,vt8500-pmc.yaml`) which also
describes the clock-related child nodes and replaces both legacy text bindings
(clock.txt & pmc.txt) , or
2. As per Alexey, PMC compatibles should be expanded to per-SoC values.

If it has to be expanded to per-SoC values, can it be taken as separate DT-ABI
change or should be done in the same series now?

Regards,
Udaya Kiran Challa

^ permalink raw reply

* Re: (subset) [PATCH v7 00/10] Support for Samsung S2MU005 PMIC and its sub-devices
From: Sebastian Reichel @ 2026-06-04 16:05 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński, Yassine Oudjana,
	Kaustabh Chakraborty
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Conor Dooley, Krzysztof Kozlowski
In-Reply-To: <20260516-s2mu005-pmic-v7-0-73f9702fb461@disroot.org>


On Sat, 16 May 2026 03:08:32 +0530, Kaustabh Chakraborty wrote:
> S2MU005 is an MFD chip manufactured by Samsung Electronics. This is
> found in various devices manufactured by Samsung and others, including
> all Exynos 7870 devices. It is known to have the following features:
> 
> 1. Two LED channels with adjustable brightness for use as a torch, or a
>    flash strobe.
> 2. An RGB LED with 8-bit channels. Usually programmed as a notification
>    indicator.
> 3. An MUIC, which works with USB micro-B (and USB-C?). For the micro-B
>    variant though, it measures the ID-GND resistance using an internal
>    ADC.
> 4. A charger device, which reports if charger is online, voltage,
>    resistance, etc.
> 
> [...]

Applied, thanks!

[10/10] power: supply: add support for Samsung S2M series PMIC charger device
        commit: 7e541f6dbd05921d0bbb99646028cb9982535707

Best regards,
-- 
Sebastian Reichel <sebastian.reichel@collabora.com>


^ permalink raw reply

* Re: [PATCH v7 02/10] dt-bindings: extcon: document Samsung S2M series PMIC extcon device
From: Rob Herring @ 2026-06-02 19:46 UTC (permalink / raw)
  To: Kaustabh Chakraborty
  Cc: Lee Jones, Pavel Machek, Krzysztof Kozlowski, Conor Dooley,
	MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński, Yassine Oudjana, linux-leds,
	devicetree, linux-kernel, linux-pm, linux-samsung-soc, linux-rtc,
	linux-doc, Conor Dooley, Krzysztof Kozlowski
In-Reply-To: <20260516-s2mu005-pmic-v7-2-73f9702fb461@disroot.org>

On Sat, May 16, 2026 at 03:08:34AM +0530, Kaustabh Chakraborty wrote:
> Certain Samsung S2M series PMICs have a MUIC device which reports
> various cable states by measuring the ID-GND resistance with an internal
> ADC. Document the devicetree schema for this device.
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
> ---
>  .../bindings/extcon/samsung,s2mu005-muic.yaml      | 40 ++++++++++++++++++++++
>  1 file changed, 40 insertions(+)

As the rest of the series was applied without this, I've applied it to 
fix errors in dt_binding_check.

Rob

^ permalink raw reply

* [PATCH v2 5/5] rtc: renesas-rtca3: Factor out year decoding helper
From: Prabhakar @ 2026-06-02 19:25 UTC (permalink / raw)
  To: Alexandre Belloni, Claudiu Beznea, Geert Uytterhoeven, linux-rtc
  Cc: linux-renesas-soc, linux-kernel, Prabhakar, Biju Das,
	Fabrizio Castro, Lad Prabhakar
In-Reply-To: <20260602192559.1791344-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

The logic to decode the year value from the hardware registers is
duplicated in both rtca3_read_time() and rtca3_read_alarm().

Introduce a helper rtca3_decode_year() to centralize this conversion.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> # on RZ/G3S
---
 drivers/rtc/rtc-renesas-rtca3.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c
index 97e7e65f59a5..b3875d041de5 100644
--- a/drivers/rtc/rtc-renesas-rtca3.c
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -228,12 +228,19 @@ static void rtca3_prepare_cntalrm_regs_for_read(struct rtca3_priv *priv, bool cn
 	}
 }
 
+static u32 rtca3_decode_year(u8 mask, u16 year)
+{
+	u8 y = FIELD_GET(mask, year);
+	u32 century = bcd2bin((y == 0x99) ? 0x19 : 0x20);
+
+	return (century * 100 + bcd2bin(y)) - 1900;
+}
+
 static int rtca3_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct rtca3_priv *priv = dev_get_drvdata(dev);
 	u8 sec, min, hour, wday, mday, month, tmp;
 	u8 trials = 0;
-	u32 year100;
 	u16 year;
 
 	guard(spinlock_irqsave)(&priv->lock);
@@ -274,9 +281,7 @@ static int rtca3_read_time(struct device *dev, struct rtc_time *tm)
 	tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKCNT_WK, wday));
 	tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYCNT_DAY, mday));
 	tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONCNT_MONTH, month)) - 1;
-	year = FIELD_GET(RTCA3_RYRCNT_YEAR, year);
-	year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
-	tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+	tm->tm_year = rtca3_decode_year(RTCA3_RYRCNT_YEAR, year);
 
 	return 0;
 }
@@ -354,7 +359,6 @@ static int rtca3_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	struct rtca3_priv *priv = dev_get_drvdata(dev);
 	u8 sec, min, hour, wday, mday, month;
 	struct rtc_time *tm = &wkalrm->time;
-	u32 year100;
 	u16 year;
 
 	guard(spinlock_irqsave)(&priv->lock);
@@ -373,9 +377,7 @@ static int rtca3_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKAR_DAYW, wday));
 	tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYAR_DATE, mday));
 	tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONAR_MON, month)) - 1;
-	year = FIELD_GET(RTCA3_RYRAR_YR, year);
-	year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
-	tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+	tm->tm_year = rtca3_decode_year(RTCA3_RYRAR_YR, year);
 
 	wkalrm->enabled = !!(readb(priv->base + RTCA3_RCR1) & RTCA3_RCR1_AIE);
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 4/5] rtc: renesas-rtca3: Fix typo in rtca3_ppb_per_cycle documentation
From: Prabhakar @ 2026-06-02 19:25 UTC (permalink / raw)
  To: Alexandre Belloni, Claudiu Beznea, Geert Uytterhoeven, linux-rtc
  Cc: linux-renesas-soc, linux-kernel, Prabhakar, Biju Das,
	Fabrizio Castro, Lad Prabhakar
In-Reply-To: <20260602192559.1791344-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

Correct a typo in the kernel-doc comment for struct
rtca3_ppb_per_cycle by fixing "adjutment" to "adjustment".

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> # on RZ/G3S
---
 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 8763745b9172..97e7e65f59a5 100644
--- a/drivers/rtc/rtc-renesas-rtca3.c
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -103,7 +103,7 @@ enum rtca3_alrm_set_step {
 
 /**
  * struct rtca3_ppb_per_cycle - PPB per cycle
- * @ten_sec: PPB per cycle in 10 seconds adjutment mode
+ * @ten_sec: PPB per cycle in 10 seconds adjustment mode
  * @sixty_sec: PPB per cycle in 60 seconds adjustment mode
  */
 struct rtca3_ppb_per_cycle {
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 3/5] rtc: renesas-rtca3: Fix incorrect error message for reset assert
From: Prabhakar @ 2026-06-02 19:25 UTC (permalink / raw)
  To: Alexandre Belloni, Claudiu Beznea, Geert Uytterhoeven, linux-rtc
  Cc: linux-renesas-soc, linux-kernel, Prabhakar, Biju Das,
	Fabrizio Castro, Lad Prabhakar
In-Reply-To: <20260602192559.1791344-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

Update the message to "assert reset" to accurately reflect the
operation being performed.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> # on RZ/G3S
---
 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 af2a3878289e..8763745b9172 100644
--- a/drivers/rtc/rtc-renesas-rtca3.c
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -702,7 +702,7 @@ static void rtca3_action(void *data)
 
 	ret = reset_control_assert(priv->rstc);
 	if (ret)
-		dev_err(dev, "Failed to de-assert reset!");
+		dev_err(dev, "Failed to assert reset!");
 
 	ret = pm_runtime_put_sync(dev);
 	if (ret < 0)
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 2/5] rtc: renesas-rtca3: Check RADJ poll result during initial setup
From: Prabhakar @ 2026-06-02 19:25 UTC (permalink / raw)
  To: Alexandre Belloni, Claudiu Beznea, Geert Uytterhoeven, linux-rtc
  Cc: linux-renesas-soc, linux-kernel, Prabhakar, Biju Das,
	Fabrizio Castro, Lad Prabhakar
In-Reply-To: <20260602192559.1791344-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

In rtca3_initial_setup(), the driver clears the RTCA3_RADJ register and
waits for it to reach zero using readb_poll_timeout(). Check the return
value of readb_poll_timeout() and propagate the error if the poll fails.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> # on RZ/G3S
---
 drivers/rtc/rtc-renesas-rtca3.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c
index 2dc080d0eb6c..af2a3878289e 100644
--- a/drivers/rtc/rtc-renesas-rtca3.c
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -634,6 +634,8 @@ static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv)
 	writeb(0, priv->base + RTCA3_RADJ);
 	ret = readb_poll_timeout(priv->base + RTCA3_RADJ, tmp, !tmp, 10,
 				 RTCA3_DEFAULT_TIMEOUT_US);
+	if (ret)
+		return ret;
 
 	/* Start the RTC and enable automatic time error adjustment. */
 	mask = RTCA3_RCR2_START | RTCA3_RCR2_AADJE;
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 1/5] rtc: renesas-rtca3: Fix PIE clear polling condition in alarm setup error path
From: Prabhakar @ 2026-06-02 19:25 UTC (permalink / raw)
  To: Alexandre Belloni, Claudiu Beznea, Geert Uytterhoeven, linux-rtc
  Cc: linux-renesas-soc, linux-kernel, Prabhakar, Biju Das,
	Fabrizio Castro, Lad Prabhakar, stable
In-Reply-To: <20260602192559.1791344-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

In rtca3_set_alarm(), the setup_failed path attempts to disable the
Periodic Interrupt Enable (PIE) bit and wait until it is cleared.
However, the polling condition passed to readb_poll_timeout_atomic()
uses an incorrect expression:

    !(tmp & ~RTCA3_RCR1_PIE)

As ~RTCA3_RCR1_PIE evaluates to a mask of all bits except PIE, the
condition effectively waits for all non-PIE bits to become zero, which
is unrelated to the intended operation and is unlikely to ever be true.
This causes the poll to time out unnecessarily.

Fix the condition to check for the PIE bit itself being cleared:

    !(tmp & RTCA3_RCR1_PIE)

This correctly waits until PIE is deasserted after being cleared.

Fixes: d4488377609e3 ("rtc: renesas-rtca3: Add driver for RTCA-3 available on Renesas RZ/G3S SoC")
Cc: stable@vger.kernel.org
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> # on RZ/G3S
---
 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 cbabaa4dc96a..2dc080d0eb6c 100644
--- a/drivers/rtc/rtc-renesas-rtca3.c
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -455,7 +455,7 @@ static int rtca3_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 		 * specified timeout for setup.
 		 */
 		writeb(rcr1 & ~RTCA3_RCR1_PIE, priv->base + RTCA3_RCR1);
-		readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & ~RTCA3_RCR1_PIE),
+		readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & RTCA3_RCR1_PIE),
 					  10, RTCA3_DEFAULT_TIMEOUT_US);
 		atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
 	}
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 0/5] rtc: renesas-rtca3: Various fixes and improvements
From: Prabhakar @ 2026-06-02 19:25 UTC (permalink / raw)
  To: Alexandre Belloni, Claudiu Beznea, Geert Uytterhoeven, linux-rtc
  Cc: linux-renesas-soc, linux-kernel, Prabhakar, Biju Das,
	Fabrizio Castro, Lad Prabhakar

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

Hi all,

This patch series includes various fixes and improvements for the
Renesas RTCA-3 RTC driver, including:
- Fixing the polling condition when clearing the PIE bit during alarm
  setup error handling.
- Checking the result of the RADJ polling during initial setup and
  propagating errors.
- Correcting an error message related to reset control.
- Fixing a typo in the documentation for the rtca3_ppb_per_cycle struct.
- Refactoring year decoding logic into a helper function for better
  readability.

v1->v2:
- Added Fixes tag for patch #1
- Added RB/TB tags from Claudiu
- Rebased the patches on top of next-20260602

Cheers,
Prabhakar

Lad Prabhakar (5):
  rtc: renesas-rtca3: Fix PIE clear polling condition in alarm setup
    error path
  rtc: renesas-rtca3: Check RADJ poll result during initial setup
  rtc: renesas-rtca3: Fix incorrect error message for reset assert
  rtc: renesas-rtca3: Fix typo in rtca3_ppb_per_cycle documentation
  rtc: renesas-rtca3: Factor out year decoding helper

 drivers/rtc/rtc-renesas-rtca3.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

-- 
2.54.0


^ permalink raw reply

* Re: [PATCH 1/5] rtc: renesas-rtca3: Fix PIE clear polling condition in alarm setup error path
From: Lad, Prabhakar @ 2026-06-02 19:16 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: Alexandre Belloni, Claudiu Beznea, Geert Uytterhoeven, linux-rtc,
	linux-renesas-soc, linux-kernel, Biju Das, Fabrizio Castro,
	Lad Prabhakar
In-Reply-To: <7f6fe294-582d-4668-aa77-ad9ab47cce2e@tuxon.dev>

Hi Claudiu,

Thank you for the review.

On Tue, Jun 2, 2026 at 9:31 AM Claudiu Beznea <claudiu.beznea@tuxon.dev> wrote:
>
> Hi, Prabhakar,
>
> On 5/6/26 19:49, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > In rtca3_set_alarm(), the setup_failed path attempts to disable the
> > Periodic Interrupt Enable (PIE) bit and wait until it is cleared.
> > However, the polling condition passed to readb_poll_timeout_atomic()
> > uses an incorrect expression:
> >
> >      !(tmp & ~RTCA3_RCR1_PIE)
> >
> > As ~RTCA3_RCR1_PIE evaluates to a mask of all bits except PIE, the
> > condition effectively waits for all non-PIE bits to become zero, which
> > is unrelated to the intended operation and is unlikely to ever be true.
> > This causes the poll to time out unnecessarily.
> >
> > Fix the condition to check for the PIE bit itself being cleared:
> >
> >      !(tmp & RTCA3_RCR1_PIE)
> >
> > This correctly waits until PIE is deasserted after being cleared.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> # on RZ/G3S
>
> I think it also deserves a Fixes tag?
>
Ok, I will add (and also CC to stable).

Cheers,
Prabhakar

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: rtc: add ASPEED AST2700 compatible
From: Conor Dooley @ 2026-06-02 16:59 UTC (permalink / raw)
  To: Tommy Huang
  Cc: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, linux-rtc, devicetree, linux-kernel,
	linux-arm-kernel, linux-aspeed
In-Reply-To: <20260601-ast2700-rtc-v1-1-15d4ca46500a@aspeedtech.com>

[-- Attachment #1: Type: text/plain, Size: 75 bytes --]

Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH v1] rtc: mpfs: fix counter upload completion condition
From: Valentina.FernandezAlanis @ 2026-06-02 13:14 UTC (permalink / raw)
  To: conor, linux-riscv
  Cc: Conor.Dooley, stable, Daire.McNamara, alexandre.belloni,
	linux-rtc, linux-kernel, Valentina.FernandezAlanis
In-Reply-To: <20260513-panhandle-ashy-70c6abf84d59@spud>

On 13/05/2026 18:55, Conor Dooley wrote:
> From: Conor Dooley <conor.dooley@microchip.com>
>
> The condition that needs to be checked for upload completion is the
> UPLOAD bit in the completion register going low. The original iterations
> of this driver used a do-while and this was converted to a
> read_poll_timeout() during upstreaming without the condition being
> inverted as it should have been.
>
> I suspect that this went unnoticed until now because a) the first read
> was done when the bit was still set, immediately completing the
> read_poll_timeout() and b) because the RTC doesn't hold time when power
> is removed from the SoC reducing its utility (I for one keep it
> disabled). If my first suspicion was true when the driver was
> upstreamed, it's not true any longer though, hence the detection of the
> problem.
>
> Fixes: 0b31d703598dc ("rtc: Add driver for Microchip PolarFire SoC")
> CC: stable@vger.kernel.org
> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Tested-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
> ---
> CC: Valentina.FernandezAlanis@microchip.com
> CC: Conor Dooley <conor.dooley@microchip.com>
> CC: Daire McNamara <daire.mcnamara@microchip.com>
> CC: Alexandre Belloni <alexandre.belloni@bootlin.com>
> CC: linux-riscv@lists.infradead.org
> CC: linux-rtc@vger.kernel.org
> CC: linux-kernel@vger.kernel.org
> ---
>   drivers/rtc/rtc-mpfs.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c
> index 6aa3eae575d2a..ece6de4a6adbd 100644
> --- a/drivers/rtc/rtc-mpfs.c
> +++ b/drivers/rtc/rtc-mpfs.c
> @@ -112,7 +112,7 @@ static int mpfs_rtc_settime(struct device *dev, struct rtc_time *tm)
>   	ctrl |= CONTROL_UPLOAD_BIT;
>   	writel(ctrl, rtcdev->base + CONTROL_REG);
>   
> -	ret = read_poll_timeout(readl, prog, prog & CONTROL_UPLOAD_BIT, 0, UPLOAD_TIMEOUT_US,
> +	ret = read_poll_timeout(readl, prog, !(prog & CONTROL_UPLOAD_BIT), 0, UPLOAD_TIMEOUT_US,
>   				false, rtcdev->base + CONTROL_REG);
>   	if (ret) {
>   		dev_err(dev, "timed out uploading time to rtc");



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox