* [PATCH] rtc: Fix error handling in devm_rtc_allocate_device
From: Ma Ke @ 2025-11-09 6:08 UTC (permalink / raw)
To: alexandre.belloni; +Cc: linux-rtc, linux-kernel, akpm, Ma Ke, stable
In rtc_allocate_device(), device_initialize() sets the reference count
to 1. In rtc_allocate_device(), when devm_add_action_or_reset() or
dev_set_name() fails after successful device initialization via
device_initialize(), rtc_allocate_device() returns an error without
properly calling put_device() and releasing the reference count.
Add proper error handling that calls put_device() in all error paths
after device_initialize(), ensuring proper resource cleanup.
Found by code review.
Cc: stable@vger.kernel.org
Fixes: 3068a254d551 ("rtc: introduce new registration method")
Signed-off-by: Ma Ke <make24@iscas.ac.cn>
---
drivers/rtc/class.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index b1a2be1f9e3b..db5f33a22b14 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -379,13 +379,17 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev)
rtc->dev.parent = dev;
err = devm_add_action_or_reset(dev, devm_rtc_release_device, rtc);
if (err)
- return ERR_PTR(err);
+ goto err_put_device;
err = dev_set_name(&rtc->dev, "rtc%d", id);
if (err)
- return ERR_PTR(err);
+ goto err_put_device;
return rtc;
+
+err_put_device:
+ put_device(&rtc->dev);
+ return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(devm_rtc_allocate_device);
--
2.17.1
^ permalink raw reply related
* [PATCH] rtc: isl12026: Add id_table
From: Akhilesh Patil @ 2025-11-09 5:48 UTC (permalink / raw)
To: alexandre.belloni, ddaney, david.daney, pombredanne
Cc: linux-rtc, linux-kernel, akhileshpatilvnit, skhan
Add i2c id_table for isl12026 rtc.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
tested by instantiating isl12026 device as
echo "isl12026 0x6f" > new_device
Tested rtc on TI am62x sk board on i2c-2 using rtctest.
I am currently implementing alarm support for isl12026
this patch helps to instantiate device runtime without DT
for faster testing without reboots.
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);
--
2.34.1
^ permalink raw reply related
* Re: [GIT PULL] RTC fixes for 6.18
From: pr-tracker-bot @ 2025-11-09 0:08 UTC (permalink / raw)
To: Alexandre Belloni; +Cc: Linus Torvalds, linux-rtc, linux-kernel
In-Reply-To: <20251108203908b1400ce8@mail.local>
The pull request you sent on Sat, 8 Nov 2025 21:39:08 +0100:
> git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-6.18-fixes
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/41d318c47fa2090dbca7329037e5d63abeddebdf
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
^ permalink raw reply
* Re: [PATCH] rtc: rx8025: fix incorrect register reference
From: Alexandre Belloni @ 2025-11-08 20:39 UTC (permalink / raw)
To: linux-rtc, linux-kernel, Yuta Hayama; +Cc: Takao Miyasaka, Naokado OGISO
In-Reply-To: <eae5f479-5d28-4a37-859d-d54794e7628c@lineo.co.jp>
On Wed, 15 Oct 2025 12:07:05 +0900, Yuta Hayama wrote:
> This code is intended to operate on the CTRL1 register, but ctrl[1] is
> actually CTRL2. Correctly, ctrl[0] is CTRL1.
>
>
Applied, thanks!
[1/1] rtc: rx8025: fix incorrect register reference
https://git.kernel.org/abelloni/c/162f24cbb0f6
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* [GIT PULL] RTC fixes for 6.18
From: Alexandre Belloni @ 2025-11-08 20:39 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-rtc, linux-kernel
Hello Linus,
Here are some fixes for 6.18. The two reverts are for patches that I
shouldn't have applied. The rx8025 patch fixes an issue present since
2022.
The following changes since commit 3a8660878839faadb4f1a6dd72c3179c1df56787:
Linux 6.18-rc1 (2025-10-12 13:42:36 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-6.18-fixes
for you to fetch changes up to 162f24cbb0f6ec596e7e9f3e91610d79dc805229:
rtc: rx8025: fix incorrect register reference (2025-11-08 20:56:12 +0100)
----------------------------------------------------------------
RTC fixes for 6.18
Drivers:
- cpcap, tps6586x: revert incorrect irq enable/disable balance fix
- rx8025: fix incorrect register reference
----------------------------------------------------------------
Jon Hunter (2):
Revert "rtc: tps6586x: Fix initial enable_irq/disable_irq balance"
Revert "rtc: cpcap: Fix initial enable_irq/disable_irq balance"
Yuta Hayama (1):
rtc: rx8025: fix incorrect register reference
drivers/rtc/rtc-cpcap.c | 1 -
drivers/rtc/rtc-rx8025.c | 2 +-
drivers/rtc/rtc-tps6586x.c | 1 -
3 files changed, 1 insertion(+), 3 deletions(-)
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v4 2/4] rtc: renesas-rtca3: Add support for multiple reset lines
From: Claudiu Beznea @ 2025-11-08 9:46 UTC (permalink / raw)
To: Ovidiu Panait, claudiu.beznea.uj, alexandre.belloni, robh,
krzk+dt, conor+dt, geert+renesas, magnus.damm, p.zabel
Cc: linux-rtc, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20251107210706.45044-3-ovidiu.panait.rb@renesas.com>
On 11/7/25 23:07, Ovidiu Panait wrote:
> 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 <ovidiu.panait.rb@renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
> 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 ab816bdf0d77..3524053269ef 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);
>
^ permalink raw reply
* [PATCH v4 4/4] arm64: dts: renesas: r9a09g057h44-rzv2h-evk: Enable RTC
From: Ovidiu Panait @ 2025-11-07 21:07 UTC (permalink / raw)
To: claudiu.beznea.uj, alexandre.belloni, robh, krzk+dt, conor+dt,
geert+renesas, magnus.damm, p.zabel
Cc: linux-rtc, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20251107210706.45044-1-ovidiu.panait.rb@renesas.com>
Enable RTC.
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
---
arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts b/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts
index 7fff8bea9494..99dfb40b6ea8 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts
+++ b/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts
@@ -407,6 +407,10 @@ &qextal_clk {
clock-frequency = <24000000>;
};
+&rtc {
+ status = "okay";
+};
+
&rtxin_clk {
clock-frequency = <32768>;
};
--
2.51.0
^ permalink raw reply related
* [PATCH v4 2/4] rtc: renesas-rtca3: Add support for multiple reset lines
From: Ovidiu Panait @ 2025-11-07 21:07 UTC (permalink / raw)
To: claudiu.beznea.uj, alexandre.belloni, robh, krzk+dt, conor+dt,
geert+renesas, magnus.damm, p.zabel
Cc: linux-rtc, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20251107210706.45044-1-ovidiu.panait.rb@renesas.com>
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 <ovidiu.panait.rb@renesas.com>
---
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 ab816bdf0d77..3524053269ef 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);
--
2.51.0
^ permalink raw reply related
* [PATCH v4 3/4] arm64: dts: renesas: r9a09g057: Add RTC node
From: Ovidiu Panait @ 2025-11-07 21:07 UTC (permalink / raw)
To: claudiu.beznea.uj, alexandre.belloni, robh, krzk+dt, conor+dt,
geert+renesas, magnus.damm, p.zabel
Cc: linux-rtc, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20251107210706.45044-1-ovidiu.panait.rb@renesas.com>
Add RTC node to Renesas RZ/V2H ("R9A09G057") SoC DTSI.
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
---
arch/arm64/boot/dts/renesas/r9a09g057.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
index 40b15f1db930..8aad46c367ae 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
@@ -591,6 +591,21 @@ wdt3: watchdog@13000400 {
status = "disabled";
};
+ rtc: rtc@11c00800 {
+ compatible = "renesas,r9a09g057-rtca3", "renesas,rz-rtca3";
+ reg = <0 0x11c00800 0 0x400>;
+ interrupts = <GIC_SPI 524 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 525 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 526 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "alarm", "period", "carry";
+ clocks = <&cpg CPG_MOD 0x53>, <&rtxin_clk>;
+ clock-names = "bus", "counter";
+ power-domains = <&cpg>;
+ resets = <&cpg 0x79>, <&cpg 0x7a>;
+ reset-names = "rtc", "rtest";
+ status = "disabled";
+ };
+
scif: serial@11c01400 {
compatible = "renesas,scif-r9a09g057";
reg = <0 0x11c01400 0 0x400>;
--
2.51.0
^ permalink raw reply related
* [PATCH v4 1/4] dt-bindings: rtc: renesas,rz-rtca3: Add RZ/V2H support
From: Ovidiu Panait @ 2025-11-07 21:07 UTC (permalink / raw)
To: claudiu.beznea.uj, alexandre.belloni, robh, krzk+dt, conor+dt,
geert+renesas, magnus.damm, p.zabel
Cc: linux-rtc, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20251107210706.45044-1-ovidiu.panait.rb@renesas.com>
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 <ovidiu.panait.rb@renesas.com>
---
.../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 <claudiu.beznea.uj@bp.renesas.com>
-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";
};
--
2.51.0
^ permalink raw reply related
* [PATCH v4 0/4] Add RTC support for the Renesas RZ/V2H SoC
From: Ovidiu Panait @ 2025-11-07 21:07 UTC (permalink / raw)
To: claudiu.beznea.uj, alexandre.belloni, robh, krzk+dt, conor+dt,
geert+renesas, magnus.damm, p.zabel
Cc: linux-rtc, linux-renesas-soc, devicetree, linux-kernel
Hi,
This series adds RTC support for the Renesas RZ/V2H SoC.
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
Best regards,
Ovidiu
v4:
- Renamed reset "rtc_rtest" -> "rtest".
- Added "vbattb" reset name to example node.
v3:
- Dropped all changes related to "max_user_freq", as it was removed from
all drivers by:
https://lore.kernel.org/all/20251101-max_user_freq-v1-0-c9a274fd6883@bootlin.com/
v2:
- Updated bindings and RTC dts node with "reset-names" property.
Ovidiu Panait (4):
dt-bindings: rtc: renesas,rz-rtca3: Add RZ/V2H support
rtc: renesas-rtca3: Add support for multiple reset lines
arm64: dts: renesas: r9a09g057: Add RTC node
arm64: dts: renesas: r9a09g057h44-rzv2h-evk: Enable RTC
.../bindings/rtc/renesas,rz-rtca3.yaml | 46 +++++++++++++++++--
arch/arm64/boot/dts/renesas/r9a09g057.dtsi | 15 ++++++
.../dts/renesas/r9a09g057h44-rzv2h-evk.dts | 4 ++
drivers/rtc/rtc-renesas-rtca3.c | 2 +-
4 files changed, 61 insertions(+), 6 deletions(-)
--
2.51.0
^ permalink raw reply
* Re: [PATCH v5 1/2] dt-bindings: rtc: Add pcf85053 support
From: Conor Dooley @ 2025-11-07 18:01 UTC (permalink / raw)
To: Lakshay Piplani
Cc: alexandre.belloni, linux-rtc, linux-kernel, robh, krzk+dt,
conor+dt, devicetree, pankit.garg, vikash.bansal, priyanka.jain,
shashank.rebbapragada
In-Reply-To: <20251107132618.2246407-1-lakshay.piplani@nxp.com>
[-- Attachment #1: Type: text/plain, Size: 796 bytes --]
On Fri, Nov 07, 2025 at 06:56:17PM +0530, Lakshay Piplani wrote:
> + nxp,write-access:
> + type: boolean
> + description: |
> + Request the driver to claim write ownership at probe time by setting
> + CTRL.TWO=1. This property is only valid when nxp,interface="primary".
> + The driver will not modify any other CTRL bits (HF/DM/etc.) and will not
> + clear any status/interrupt flags at probe.
I'm sorry for not noticing this before, can you please remove the
commentary about linux driver specific stuff from here? Probably needs
to be something like "Indicates that write ownership of the RTC can be
should be claimed by setting CTRL.TWO. This property is only valid when
acting as the primary interface (nxp,interface = "primary")" or
something along those lines.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH v5 2/2] rtc: Add NXP PCF85053 driver support
From: Lakshay Piplani @ 2025-11-07 13:26 UTC (permalink / raw)
To: alexandre.belloni, linux-rtc, linux-kernel, robh, krzk+dt,
conor+dt, devicetree
Cc: pankit.garg, vikash.bansal, priyanka.jain, shashank.rebbapragada,
Lakshay Piplani, Daniel Aguirre
In-Reply-To: <20251107132618.2246407-1-lakshay.piplani@nxp.com>
PCF85053 is i2c based RTC which supports timer and calendar
functionality.
Features supported:
1. Read/Write time
2. Get/Set Alarm
3. Wakeup Source
4. Generate up to 32768Hz clock output
5. Primary/Secondary i2c bus
Signed-off-by: Daniel Aguirre <daniel.aguirre@nxp.com>
Signed-off-by: Pankit Garg <pankit.garg@nxp.com>
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>
---
V4 -> V5: no changes
V3 -> V4: - Handle multi-host ownership explicitly using primary/secondary bus hadling.
- Probe no longer changes any CTRL bits unconditionally and do not clear ST/AF/OF
avoiding lost interrupts or silent mode changes.
- Read/Set time & alarm now respect HF(12/24h) and DM(BCD/BIN) converting
hour fields correctly for all combinations.
- Minor changes: drop noisy warnings, tidy error paths/comments.
V2 -> V3: Add MAINTAINERS file changes to this patch
V1 -> V2: no changes
MAINTAINERS | 7 +
drivers/rtc/Kconfig | 10 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-pcf85053.c | 734 +++++++++++++++++++++++++++++++++++++
4 files changed, 752 insertions(+)
create mode 100644 drivers/rtc/rtc-pcf85053.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 6bbe4b4f8ec0..b835c2787e63 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18352,6 +18352,13 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
F: sound/soc/codecs/tfa989x.c
+NXP RTC PCF85053 DRIVER
+M: Pankit Gargi <pankit.garg@nxp.com>
+M: Lakshay Piplani <lakshay.piplani@nxp.com>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: drivers/rtc/rtc-pcf85053.c
+
NZXT-KRAKEN2 HARDWARE MONITORING DRIVER
M: Jonas Malaco <jonas@protocubo.io>
L: linux-hwmon@vger.kernel.org
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 64f6e9756aff..59ef0b6a53a7 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -974,6 +974,16 @@ config RTC_DRV_PCF85063
This driver can also be built as a module. If so, the module
will be called rtc-pcf85063.
+config RTC_DRV_PCF85053
+ tristate "NXP PCF85053"
+ depends on OF
+ help
+ If you say yes here you get support for the NXP PCF85053 I2C Bootable CPU RTC
+ chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-pcf85053.
+
config RTC_DRV_RV3029C2
tristate "Micro Crystal RV3029/3049"
depends on RTC_I2C_AND_SPI
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 789bddfea99d..7b2f379d10a9 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -128,6 +128,7 @@ obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o
obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o
obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
+obj-$(CONFIG_RTC_DRV_PCF85053) += rtc-pcf85053.o
obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o
obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
diff --git a/drivers/rtc/rtc-pcf85053.c b/drivers/rtc/rtc-pcf85053.c
new file mode 100644
index 000000000000..4eec1a661b6b
--- /dev/null
+++ b/drivers/rtc/rtc-pcf85053.c
@@ -0,0 +1,734 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2025 NXP
+
+#include <linux/bcd.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/regmap.h>
+
+#define PCF85053_REG_SC 0x00 /* seconds */
+#define PCF85053_REG_SCA 0x01 /* alarm */
+#define PCF85053_REG_MN 0x02 /* minutes */
+#define PCF85053_REG_MNA 0x03 /* alarm */
+#define PCF85053_REG_HR 0x04 /* hour */
+#define PCF85053_REG_HRA 0x05 /* alarm */
+#define PCF85053_REG_DW 0x06 /* day of week */
+#define PCF85053_REG_DM 0x07 /* day of month */
+#define PCF85053_REG_MO 0x08 /* month */
+#define PCF85053_REG_YR 0x09 /* year */
+#define PCF85053_REG_CTRL 0x0A /* timer control */
+#define PCF85053_REG_ST 0x0B /* status */
+#define PCF85053_REG_CLKO 0x0C /* clock out */
+#define PCF85053_REG_ACC 0x14 /* xclk access */
+
+#define PCF85053_BIT_AF BIT(7)
+#define PCF85053_BIT_ST BIT(7)
+#define PCF85053_BIT_DM BIT(6)
+#define PCF85053_BIT_HF BIT(5)
+#define PCF85053_BIT_DSM BIT(4)
+#define PCF85053_BIT_AIE BIT(3)
+#define PCF85053_BIT_OFIE BIT(2)
+#define PCF85053_BIT_CIE BIT(1)
+#define PCF85053_BIT_TWO BIT(0)
+#define PCF85053_BIT_XCLK BIT(7)
+
+#define PCF85053_REG_BAT_MASK 0x07 /* Battery mask */
+#define PCF85053A_BVL_MASK 0x07
+#define PCF85053A_BVL_LOW_THRESHOLD 0x02
+#define PCF85053_REG_CLKO_F_MASK 0x03 /* Frequenc mask */
+#define PCF85053_REG_CLKO_CKE 0x80 /* clock out enabled */
+#define PCF85053_BIT_OF BIT(6)
+
+#define PCF85053_HR_PM BIT(7)
+#define PCF85053_HR_24H_MASK GENMASK(5, 0)
+
+struct pcf85053_config {
+ const struct regmap_config regmap;
+ unsigned has_alarms:1;
+};
+
+struct pcf85053 {
+ struct rtc_device *rtc;
+ struct i2c_client *client;
+ struct regmap *regmap;
+#ifdef CONFIG_COMMON_CLK
+ struct clk_hw clkout_hw;
+#endif
+ bool is_primary;
+};
+
+static inline int pcf85053_read_two_bit(struct pcf85053 *pcf85053, bool *two)
+{
+ unsigned int ctrl;
+ int err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CTRL, &ctrl);
+ if (err)
+ return err;
+
+ *two = !!(ctrl & PCF85053_BIT_TWO);
+
+ return 0;
+}
+
+static inline bool pcf85053_time_write_access(struct pcf85053 *pcf85053)
+{
+ bool two;
+
+ if (pcf85053_read_two_bit(pcf85053, &two))
+ return false;
+
+ /* Primary writes iff TWO=1; secondary writes iff TWO=0 */
+ return pcf85053->is_primary ? two : !two;
+}
+
+static int pcf85053_set_alarm_mode(struct device *dev, bool on)
+{
+ struct pcf85053 *pcf85053 = dev_get_drvdata(dev);
+ unsigned int val;
+ int err;
+
+ val = on ? PCF85053_BIT_AIE : 0;
+ val &= ~(PCF85053_BIT_CIE | PCF85053_BIT_OFIE);
+
+ err = regmap_update_bits(pcf85053->regmap, PCF85053_REG_CTRL,
+ PCF85053_BIT_AIE | PCF85053_BIT_CIE | PCF85053_BIT_OFIE,
+ val);
+ if (err)
+ return err;
+
+ return regmap_update_bits(pcf85053->regmap, PCF85053_REG_ST,
+ PCF85053_BIT_AF, 0);
+}
+
+static int pcf85053_get_alarm_mode(struct device *dev,
+ unsigned char *alarm_enable, unsigned char *alarm_flag)
+{
+ struct pcf85053 *pcf85053 = dev_get_drvdata(dev);
+ unsigned int val;
+ int err;
+
+ if (alarm_enable) {
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CTRL, &val);
+ if (err)
+ return err;
+
+ *alarm_enable = val & PCF85053_BIT_AIE;
+ }
+
+ if (alarm_flag) {
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_ST, &val);
+ if (err)
+ return err;
+
+ *alarm_flag = val & PCF85053_BIT_AF;
+ }
+
+ return 0;
+}
+
+static irqreturn_t pcf85053_irq(int irq, void *dev_id)
+{
+ struct pcf85053 *pcf85053 = i2c_get_clientdata(dev_id);
+ unsigned char alarm_flag;
+ unsigned char alarm_enable;
+ int err;
+
+ err = pcf85053_get_alarm_mode(&pcf85053->client->dev, &alarm_enable, &alarm_flag);
+ if (err)
+ return IRQ_NONE;
+
+ if (!alarm_flag)
+ return IRQ_NONE;
+
+ rtc_update_irq(pcf85053->rtc, 1, RTC_IRQF | RTC_AF);
+ pcf85053_set_alarm_mode(&pcf85053->client->dev, false);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * In the routines that deal directly with the PCF85053 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf85053_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pcf85053 *pcf85053 = dev_get_drvdata(dev);
+ unsigned int ctrl, st, h12;
+ bool is_24h, is_bin;
+ u8 regs[10], hr;
+ int err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CTRL, &ctrl);
+ if (err)
+ return err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_ST, &st);
+ if (err)
+ return err;
+
+ if (ctrl & PCF85053_BIT_ST)
+ dev_warn(dev, "RTC is stopped; time may be invalid\n");
+
+ err = regmap_bulk_read(pcf85053->regmap, PCF85053_REG_SC, regs, sizeof(regs));
+ if (err)
+ return err;
+
+ if (ctrl & PCF85053_BIT_DM) {
+ tm->tm_sec = regs[PCF85053_REG_SC] & 0x7F;
+ tm->tm_min = regs[PCF85053_REG_MN] & 0x7F;
+ tm->tm_mday = regs[PCF85053_REG_DM] & 0x3F;
+ tm->tm_mon = (regs[PCF85053_REG_MO] & 0x1F) - 1;
+ tm->tm_year = regs[PCF85053_REG_YR] + 100;
+ } else {
+ tm->tm_sec = bcd2bin(regs[PCF85053_REG_SC] & 0x7F);
+ tm->tm_min = bcd2bin(regs[PCF85053_REG_MN] & 0x7F);
+ tm->tm_mday = bcd2bin(regs[PCF85053_REG_DM] & 0x3F);
+ tm->tm_mon = bcd2bin(regs[PCF85053_REG_MO] & 0x1F) - 1;
+ tm->tm_year = bcd2bin(regs[PCF85053_REG_YR]) + 100;
+ }
+ tm->tm_wday = regs[PCF85053_REG_DW] & 0x07;
+
+ hr = regs[PCF85053_REG_HR];
+ is_24h = ctrl & PCF85053_BIT_HF;
+ is_bin = ctrl & PCF85053_BIT_DM;
+
+ if (is_24h) {
+ tm->tm_hour = is_bin
+ ? (hr & PCF85053_HR_24H_MASK)
+ : bcd2bin(hr & PCF85053_HR_24H_MASK);
+ } else {
+ if (is_bin) {
+ h12 = hr & PCF85053_HR_24H_MASK;
+ } else {
+ h12 = is_bin ? (hr & PCF85053_HR_24H_MASK) :
+ bcd2bin(hr & PCF85053_HR_24H_MASK);
+
+ tm->tm_hour = (h12 == 12) ? ((hr & PCF85053_HR_PM) ? 12 : 0) :
+ ((hr & PCF85053_HR_PM) ? h12 + 12 : h12);
+ }
+ }
+
+ return 0;
+}
+
+static int pcf85053_rtc_set_time(struct device *dev, struct rtc_time *tm)
+
+{
+ struct pcf85053 *pcf85053 = dev_get_drvdata(dev);
+ unsigned int ctrl, h12;
+ int err, ret;
+ u8 buf[10];
+ bool pm;
+
+ /*
+ * By default, secondary have write access to time registers as TWO
+ * bit is 0 by default, if we set nxp,interface = "primary" and the
+ * nxp,write-access in device tree, then TWO bits gets set and primary
+ * gets write access to time registers.
+ */
+ if (!pcf85053_time_write_access(pcf85053))
+ return -EACCES;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CTRL, &ctrl);
+ if (err)
+ return err;
+
+ buf[0] = tm->tm_sec & 0x7F;
+ buf[1] = 0;
+ buf[2] = tm->tm_min & 0x7F;
+ buf[3] = 0;
+ buf[5] = 0;
+ buf[6] = tm->tm_wday & 0x07;
+ buf[7] = tm->tm_mday & 0x3F;
+ buf[8] = (tm->tm_mon + 1) & 0x1F;
+ buf[9] = (tm->tm_year - 100) & 0xFF;
+
+ if (ctrl & PCF85053_BIT_HF) {
+ buf[4] = tm->tm_hour & PCF85053_HR_24H_MASK;
+ } else {
+ pm = tm->tm_hour >= 12;
+ h12 = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12;
+ buf[4] = (h12 & PCF85053_HR_24H_MASK) | (pm << 7);
+ }
+
+ if (!(ctrl & PCF85053_BIT_DM)) {
+ buf[0] = bin2bcd(buf[0]);
+ buf[2] = bin2bcd(buf[2]);
+ buf[4] = bin2bcd(buf[4] & PCF85053_HR_24H_MASK) | (buf[4] & PCF85053_HR_PM);
+ buf[7] = bin2bcd(buf[7]);
+ buf[8] = bin2bcd(buf[8]);
+ buf[9] = bin2bcd(buf[9]);
+ }
+
+ if (pcf85053->is_primary) {
+ err = regmap_update_bits(pcf85053->regmap, PCF85053_REG_CTRL,
+ PCF85053_BIT_ST, PCF85053_BIT_ST);
+ if (err)
+ return err;
+
+ ret = regmap_bulk_write(pcf85053->regmap, PCF85053_REG_SC, buf, sizeof(buf));
+ err = regmap_update_bits(pcf85053->regmap, PCF85053_REG_CTRL,
+ PCF85053_BIT_ST, 0);
+ return ret ? ret : err;
+ }
+
+ return regmap_bulk_write(pcf85053->regmap, PCF85053_REG_SC, buf, sizeof(buf));
+}
+
+static int pcf85053_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+ struct pcf85053 *pcf85053 = dev_get_drvdata(dev);
+ unsigned int ctrl, h12;
+ bool is_24h, is_bin, pm;
+ u8 buf[5];
+ u8 hr;
+ int err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CTRL, &ctrl);
+ if (err)
+ return err;
+
+ err = regmap_bulk_read(pcf85053->regmap, PCF85053_REG_SCA, buf, sizeof(buf));
+ if (err)
+ return err;
+
+ if (ctrl & PCF85053_BIT_DM) {
+ tm->time.tm_sec = buf[0] & 0x7F; /* SCA */
+ tm->time.tm_min = buf[2] & 0x7F; /* MNA */
+ } else {
+ tm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
+ tm->time.tm_min = bcd2bin(buf[2] & 0x7F);
+ }
+
+ hr = buf[4];
+ is_24h = !!(ctrl & PCF85053_BIT_HF);
+ is_bin = !!(ctrl & PCF85053_BIT_DM);
+
+ if (is_24h) {
+ tm->time.tm_hour = is_bin
+ ? (hr & PCF85053_HR_24H_MASK)
+ : bcd2bin(hr & PCF85053_HR_24H_MASK);
+ } else {
+ pm = !!(hr & PCF85053_HR_PM);
+
+ if (is_bin)
+ h12 = (hr & PCF85053_HR_24H_MASK);
+ else
+ h12 = (bcd2bin(hr & PCF85053_HR_24H_MASK));
+
+ if (h12 == 12)
+ h12 = 0;
+ tm->time.tm_hour = pm ? (h12 + 12) : h12;
+ }
+
+ return pcf85053_get_alarm_mode(dev, &tm->enabled, &tm->pending);
+}
+
+static int pcf85053_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+ struct pcf85053 *pcf85053 = dev_get_drvdata(dev);
+ bool is_24h, is_bin, pm;
+ unsigned int ctrl, h12;
+ u8 sec, min, hra;
+ int err;
+
+ /*
+ * Only primary can set alarm, as secondary have read only access
+ * to alarm, control and status registers
+ */
+ if (!pcf85053->is_primary)
+ return -EACCES;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CTRL, &ctrl);
+ if (err)
+ return err;
+
+ err = regmap_update_bits(pcf85053->regmap, PCF85053_REG_ST,
+ PCF85053_BIT_AF, 0);
+ if (err)
+ return err;
+
+ is_24h = !!(ctrl & PCF85053_BIT_HF);
+ is_bin = !!(ctrl & PCF85053_BIT_DM);
+
+ sec = tm->time.tm_sec & 0x7F;
+ min = tm->time.tm_min & 0x7F;
+
+ if (is_24h) {
+ hra = tm->time.tm_hour & PCF85053_HR_24H_MASK;
+ if (!is_bin)
+ hra = bin2bcd(hra) & PCF85053_HR_24H_MASK;
+ } else {
+ h12 = tm->time.tm_hour % 12;
+ pm = tm->time.tm_hour >= 12;
+ if (h12 == 0)
+ h12 = 12;
+
+ if (is_bin)
+ hra = (h12 & PCF85053_HR_24H_MASK) | (pm << 7);
+ else
+ hra = (bin2bcd(h12) & PCF85053_HR_24H_MASK) | (pm << 7);
+ }
+
+ if (!is_bin) {
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ }
+
+ err = regmap_write(pcf85053->regmap, PCF85053_REG_SCA, sec);
+ if (err)
+ return err;
+
+ err = regmap_write(pcf85053->regmap, PCF85053_REG_MNA, min);
+ if (err)
+ return err;
+
+ err = regmap_write(pcf85053->regmap, PCF85053_REG_HRA, hra);
+ if (err)
+ return err;
+
+ return pcf85053_set_alarm_mode(dev, tm->enabled);
+}
+
+static int pcf85053_irq_enable(struct device *dev, unsigned int enabled)
+{
+ dev_dbg(dev, "%s: alarm enable=%d\n", __func__, enabled);
+
+ return pcf85053_set_alarm_mode(dev, enabled);
+}
+
+static int pcf85053_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct pcf85053 *pcf85053 = dev_get_drvdata(dev);
+ unsigned int val = 0, vl_status = 0;
+ unsigned int bvl;
+ int status;
+
+ switch (cmd) {
+ case RTC_VL_READ:
+ status = regmap_read(pcf85053->regmap, PCF85053_REG_ST, &val);
+ if (status)
+ return status;
+
+ if (val & PCF85053_BIT_OF)
+ vl_status |= RTC_VL_DATA_INVALID;
+
+ bvl = val & PCF85053A_BVL_MASK;
+
+ if (bvl == 0x00)
+ vl_status |= RTC_VL_BACKUP_EMPTY;
+ else if (bvl <= PCF85053A_BVL_LOW_THRESHOLD)
+ vl_status |= RTC_VL_BACKUP_LOW;
+
+ return put_user(vl_status, (unsigned int __user *)arg);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+#ifdef CONFIG_COMMON_CLK
+/*
+ * Handling of the clkout
+ */
+
+#define clkout_hw_to_pcf85053(_hw) container_of(_hw, struct pcf85053, clkout_hw)
+
+static const int clkout_rates[] = {
+ 32768,
+ 1024,
+ 32,
+ 1,
+};
+
+static unsigned long pcf85053_clkout_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct pcf85053 *pcf85053 = clkout_hw_to_pcf85053(hw);
+ unsigned int val = 0;
+ int err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CLKO, &val);
+ if (err)
+ return 0;
+
+ val &= PCF85053_REG_CLKO_F_MASK;
+ return clkout_rates[val];
+}
+
+static int pcf85053_clkout_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ int i;
+ unsigned long best = 0;
+
+ for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) {
+ if (clkout_rates[i] <= req->rate) {
+ best = clkout_rates[i];
+ break;
+ }
+ }
+ if (!best)
+ best = clkout_rates[ARRAY_SIZE(clkout_rates) - 1];
+
+ req->rate = best;
+ return 0;
+}
+
+static int pcf85053_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct pcf85053 *pcf85053 = clkout_hw_to_pcf85053(hw);
+ unsigned int val = 0;
+ int err, i;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CLKO, &val);
+ if (err)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+ if (clkout_rates[i] == rate) {
+ val &= ~PCF85053_REG_CLKO_F_MASK;
+ val |= i;
+ return regmap_write(pcf85053->regmap, PCF85053_REG_CLKO, val);
+ }
+
+ return -EINVAL;
+}
+
+static int pcf85053_clkout_control(struct clk_hw *hw, bool enable)
+{
+ struct pcf85053 *pcf85053 = clkout_hw_to_pcf85053(hw);
+ unsigned int val = 0;
+ int err;
+
+ if (!pcf85053->is_primary)
+ return -EACCES;
+
+ val = PCF85053_BIT_XCLK;
+ err = regmap_write(pcf85053->regmap, PCF85053_REG_ACC, val);
+ if (err)
+ return err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CLKO, &val);
+ if (err)
+ return err;
+
+ if (enable)
+ val |= PCF85053_REG_CLKO_CKE;
+ else
+ val &= ~PCF85053_REG_CLKO_CKE;
+
+ return regmap_write(pcf85053->regmap, PCF85053_REG_CLKO, val);
+}
+
+static int pcf85053_clkout_prepare(struct clk_hw *hw)
+{
+ return pcf85053_clkout_control(hw, 1);
+}
+
+static void pcf85053_clkout_unprepare(struct clk_hw *hw)
+{
+ pcf85053_clkout_control(hw, 0);
+}
+
+static int pcf85053_clkout_is_prepared(struct clk_hw *hw)
+{
+ struct pcf85053 *pcf85053 = clkout_hw_to_pcf85053(hw);
+ unsigned int val = 0;
+ int err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CLKO, &val);
+ if (err)
+ return err;
+
+ return val & PCF85053_REG_CLKO_CKE;
+}
+
+static const struct clk_ops pcf85053_clkout_ops = {
+ .prepare = pcf85053_clkout_prepare,
+ .unprepare = pcf85053_clkout_unprepare,
+ .is_prepared = pcf85053_clkout_is_prepared,
+ .recalc_rate = pcf85053_clkout_recalc_rate,
+ .determine_rate = pcf85053_clkout_determine_rate,
+ .set_rate = pcf85053_clkout_set_rate,
+};
+
+static struct clk *pcf85053_clkout_register_clk(struct pcf85053 *pcf85053)
+{
+ struct i2c_client *client = pcf85053->client;
+ struct device_node *node = client->dev.of_node;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ init.name = "pcf85053-clkout";
+ init.ops = &pcf85053_clkout_ops;
+ init.flags = 0;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ pcf85053->clkout_hw.init = &init;
+
+ /* optional override of the clockname */
+ of_property_read_string(node, "clock-output-names", &init.name);
+
+ /* register the clock */
+ clk = devm_clk_register(&client->dev, &pcf85053->clkout_hw);
+
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return clk;
+}
+#endif
+
+static const struct rtc_class_ops pcf85053_rtc_ops = {
+ .read_time = pcf85053_rtc_read_time,
+ .set_time = pcf85053_rtc_set_time,
+ .read_alarm = pcf85053_rtc_read_alarm,
+ .set_alarm = pcf85053_rtc_set_alarm,
+ .alarm_irq_enable = pcf85053_irq_enable,
+ .ioctl = pcf85053_ioctl,
+};
+
+static const struct pcf85053_config config_pcf85053 = {
+ .regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x1D,
+ },
+ .has_alarms = 1,
+};
+
+static int pcf85053_probe(struct i2c_client *client)
+{
+ struct pcf85053 *pcf85053;
+ const struct pcf85053_config *config;
+ const char *iface = NULL;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BLOCK_DATA))
+ return -ENODEV;
+
+ pcf85053 = devm_kzalloc(&client->dev, sizeof(struct pcf85053),
+ GFP_KERNEL);
+ if (!pcf85053)
+ return -ENOMEM;
+
+ config = i2c_get_match_data(client);
+ if (!config)
+ return -ENODEV;
+
+ pcf85053->regmap = devm_regmap_init_i2c(client, &config->regmap);
+ if (IS_ERR(pcf85053->regmap))
+ return PTR_ERR(pcf85053->regmap);
+
+ i2c_set_clientdata(client, pcf85053);
+
+ pcf85053->client = client;
+ device_set_wakeup_capable(&client->dev, 1);
+
+ pcf85053->is_primary = true;
+
+ if (of_property_read_string(client->dev.of_node, "nxp,interface", &iface))
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Missing mandatory property: nxp,interface\n");
+ if (!strcmp(iface, "primary"))
+ pcf85053->is_primary = true;
+ else if (!strcmp(iface, "secondary"))
+ pcf85053->is_primary = false;
+ else
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Invalid value for nxp,interface: %s\n", iface);
+
+ if (pcf85053->is_primary) {
+ unsigned int ctrl;
+ int err;
+
+ err = regmap_read(pcf85053->regmap, PCF85053_REG_CTRL, &ctrl);
+ if (err)
+ return err;
+
+ if (of_property_read_bool(client->dev.of_node, "nxp,write-access")) {
+ if (!(ctrl & PCF85053_BIT_TWO)) {
+ err = regmap_update_bits(pcf85053->regmap, PCF85053_REG_CTRL,
+ PCF85053_BIT_TWO, PCF85053_BIT_TWO);
+ if (err)
+ return err;
+ }
+ dev_dbg(&client->dev, "Ownership set: TWO=1 (primary writes)\n");
+ } else {
+ /* TWO (Time Write Ownership) bit defaults to 0 (Secondary) */
+ dev_dbg(&client->dev, "Default ownership set: TWO=0 (secondary writes)\n");
+ }
+ }
+
+ pcf85053->rtc = devm_rtc_allocate_device(&client->dev);
+ if (IS_ERR(pcf85053->rtc))
+ return PTR_ERR(pcf85053->rtc);
+
+ pcf85053->rtc->ops = &pcf85053_rtc_ops;
+ pcf85053->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ pcf85053->rtc->range_max = RTC_TIMESTAMP_END_2099;
+ clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, pcf85053->rtc->features);
+ clear_bit(RTC_FEATURE_ALARM, pcf85053->rtc->features);
+
+ if (config->has_alarms && client->irq > 0) {
+ err = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, pcf85053_irq,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+ "pcf85053", client);
+ if (err) {
+ dev_err(&client->dev, "unable to request IRQ %d\n", client->irq);
+ } else {
+ set_bit(RTC_FEATURE_ALARM, pcf85053->rtc->features);
+ device_init_wakeup(&client->dev, true);
+ err = dev_pm_set_wake_irq(&client->dev, client->irq);
+ if (err)
+ dev_err(&client->dev, "failed to enable irq wake\n");
+ }
+ }
+
+#ifdef CONFIG_COMMON_CLK
+ /* register clk in common clk framework */
+ pcf85053_clkout_register_clk(pcf85053);
+#endif
+
+ return devm_rtc_register_device(pcf85053->rtc);
+}
+
+static const struct i2c_device_id pcf85053_id[] = {
+ { "pcf85053", .driver_data = (kernel_ulong_t)&config_pcf85053 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf85053_id);
+
+static const struct of_device_id pcf85053_of_match[] = {
+ { .compatible = "nxp,pcf85053", .data = &config_pcf85053 },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pcf85053_of_match);
+
+static struct i2c_driver pcf85053_driver = {
+ .driver = {
+ .name = "rtc-pcf85053",
+ .of_match_table = of_match_ptr(pcf85053_of_match),
+ },
+ .probe = pcf85053_probe,
+ .id_table = pcf85053_id,
+};
+
+module_i2c_driver(pcf85053_driver);
+
+MODULE_AUTHOR("Pankit Garg <pankit.garg@nxp.com>");
+MODULE_AUTHOR("Lakshay Piplani <lakshay.piplani@nxp.com>");
+MODULE_DESCRIPTION("NXP pcf85053 RTC driver");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related
* [PATCH v5 1/2] dt-bindings: rtc: Add pcf85053 support
From: Lakshay Piplani @ 2025-11-07 13:26 UTC (permalink / raw)
To: alexandre.belloni, linux-rtc, linux-kernel, robh, krzk+dt,
conor+dt, devicetree
Cc: pankit.garg, vikash.bansal, priyanka.jain, shashank.rebbapragada,
Lakshay Piplani
Add device tree bindings for NXP PCF85053 RTC chip.
Signed-off-by: Pankit Garg <pankit.garg@nxp.com>
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>
---
V4 -> V5: - Updated schema validation logic to enforce correct combinations of
'nxp,interface' and 'nxp,write-access' using oneOf clauses.
- Refined property descriptions for clarity and hardware alignment.
V3 -> V4: Add dedicated nxp,pcf85053.yaml.
Remove entry from trivial-rtc.yaml.
V2 -> V3: Moved MAINTAINERS file changes to the driver patch
V1 -> V2: Handled dt-bindings by trivial-rtc.yaml
.../devicetree/bindings/rtc/nxp,pcf85053.yaml | 115 ++++++++++++++++++
1 file changed, 115 insertions(+)
create mode 100644 Documentation/devicetree/bindings/rtc/nxp,pcf85053.yaml
diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf85053.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf85053.yaml
new file mode 100644
index 000000000000..1b3fbde00001
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/nxp,pcf85053.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2025 NXP
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/nxp,pcf85053.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCF85053 Real Time Clock
+
+maintainers:
+ - Pankit Garg <pankit.garg@nxp.com>
+ - Lakshay Piplani <lakshay.piplani@nxp.com>
+
+properties:
+ compatible:
+ enum:
+ - nxp,pcf85053
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ nxp,interface:
+ $ref: /schemas/types.yaml#/definitions/string
+ enum: [ primary, secondary ]
+ description: |
+ Identifies this host's logical role in a multi-host topology for the
+ PCF85053 RTC. The device exposes a "TWO" ownership bit in the CTRL
+ register that gates which host may write time/alarm registers.
+ - "primary": Designated host that *may* claim write ownership (set
+ CTRL.TWO=1) **if** write-access is explicitly requested.
+ - "secondary": Peer host that writes only when CTRL.TWO=0 (default).
+
+ This property helps the driver determine whether it should attempt to
+ claim write-access.
+
+ The actual role depends on whether 'nxp,write-access' is also specified.
+ Supported configurations are:-
+ 1. Primary with 'nxp,write-access' -> primary claims write ownership.
+ 2. Primary without 'nxp,write-access' -> primary is ready only; secondary may write.
+ 3. Secondary (must not specify 'nxp,write-access') -> Secondary writes only
+ when no primary claims ownership.
+
+ nxp,write-access:
+ type: boolean
+ description: |
+ Request the driver to claim write ownership at probe time by setting
+ CTRL.TWO=1. This property is only valid when nxp,interface="primary".
+ The driver will not modify any other CTRL bits (HF/DM/etc.) and will not
+ clear any status/interrupt flags at probe.
+
+required:
+ - compatible
+ - reg
+ - nxp,interface
+
+additionalProperties: false
+
+allOf:
+ - $ref: rtc.yaml#
+ - if:
+ properties:
+ nxp,interface:
+ const: secondary
+ then:
+ not:
+ required: [ "nxp,write-access" ]
+
+examples:
+ # Single host example.
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@6f {
+ compatible = "nxp,pcf85053";
+ reg = <0x6f>;
+ nxp,interface = "primary";
+ nxp,write-access;
+ interrupt-parent = <&gpio2>;
+ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
+
+ # Dual-host example: one primary that claims writes; one secondary that never claims writes.
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@6f {
+ compatible = "nxp,pcf85053";
+ reg = <0x6f>;
+ nxp,interface = "primary";
+ nxp,write-access;
+ interrupt-parent = <&gpio2>;
+ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
+
+ i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@6f {
+ compatible = "nxp,pcf85053";
+ reg = <0x6f>;
+ nxp,interface = "secondary";
+ };
+ };
--
2.25.1
^ permalink raw reply related
* Re: PROBLEM: hwclock busted w/ M48T59 RTC (regression)
From: Nick Bowler @ 2025-11-07 3:06 UTC (permalink / raw)
To: Thorsten Leemhuis
Cc: Esben Haabendal, linux-kernel, regressions, linux-rtc, stable,
sparclinux
In-Reply-To: <35bd11bf-23fa-4ce9-96fb-d10ad6cd546e@leemhuis.info>
On Thu, Nov 06, 2025 at 11:25:55AM +0100, Thorsten Leemhuis wrote:
> Just wondering: was this fixed in between? Just asking, as I noticed the
> culprit was backported to various stable/longterm series recently
I am not aware of any fix. I just retested both 6.18-rc4 and 6.17.7 and
there is no change in behaviour.
Thanks,
Nick
^ permalink raw reply
* Re: (subset) [PATCH v2 1/4] mfd: simple-mfd-i2c: remove select I2C_K1
From: Troy Mitchell @ 2025-11-07 1:29 UTC (permalink / raw)
To: Lee Jones, Yixun Lan, Alex Elder, Andi Shyti, Alexandre Belloni,
Liam Girdwood, Mark Brown, Troy Mitchell
Cc: linux-kernel, linux-riscv, spacemit, linux-i2c, linux-rtc,
kernel test robot
In-Reply-To: <176244506110.1925720.10807118665958896958.b4-ty@kernel.org>
On Thu, Nov 06, 2025 at 04:04:21PM +0000, Lee Jones wrote:
> On Mon, 27 Oct 2025 13:48:05 +0800, Troy Mitchell wrote:
> > select will force a symbol to a specific value without considering
> > its dependencies. As a result, the i2c-k1 driver will fail to build
> > when OF or COMMON_CLK are disabled.
> >
> > The reason for removing I2C_K1 instead of adding a depends on condition
> > is to keep the possibility for other SoCs to use this PMIC.
> >
> > [...]
>
> Applied, thanks!
>
> [1/4] mfd: simple-mfd-i2c: remove select I2C_K1
> commit: ecf6bc474ae97c404e2125b413eb0ef3627b03c5
Hi Lee,
I think you didn't notice this reply [1]
(Maybe because he was replying to the cover letter).
As Aurelien mentioned, the current shutdown/reboot (and possibly the regulator
as well) intends to use the `default MFD_SPACEMIT_P1`.
So if there’s no `default m if ARCH_SPACEMIT`,
the default value in subdevices may not make much sense.
But don’t worry — to make things easier for you, I’ll send an additional
patch based on your branch (in this series).
How does that sound?
Link: https://lore.kernel.org/all/aP9IVckJT-k2_O4K@aurel32.net/ [1]
>
> --
> Lee Jones [李琼斯]
>
>
^ permalink raw reply
* Re: (subset) [PATCH v7 0/4] Add NVIDIA VRS RTC support
From: Alexandre Belloni @ 2025-11-06 22:56 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Catalin Marinas, Will Deacon, Jonathan Hunter, Shubhi Garg
Cc: devicetree, linux-arm-kernel, linux-rtc, linux-tegra
In-Reply-To: <20251007135738.487694-1-shgarg@nvidia.com>
On Tue, 07 Oct 2025 13:57:34 +0000, Shubhi Garg wrote:
> This patch series adds support for NVIDIA's Voltage Regulator Specification
> (VRS) RTC device. It provides following features:
> - read/set system time
> - 32kHz clock support with backup battery input to retain system time
> across boot
> - alarm functionality to wake system from suspend and shutdown state
>
> [...]
Applied, thanks!
[1/4] dt-bindings: rtc: Document NVIDIA VRS RTC
https://git.kernel.org/abelloni/c/4c03653f19ae
[3/4] rtc: nvvrs: add NVIDIA VRS RTC device driver
https://git.kernel.org/abelloni/c/9d6d6b06933c
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH V6 0/3] rtc: atcrtc100: Add Andes ATCRTC100 RTC driver
From: Alexandre Belloni @ 2025-11-06 22:47 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, CL Wang
Cc: devicetree, linux-kernel, linux-rtc, tim609
In-Reply-To: <20250915031439.2680364-1-cl634@andestech.com>
On Mon, 15 Sep 2025 11:14:36 +0800, CL Wang wrote:
> This patch series adds support for the Andes ATCRTC100 Real-Time Clock.
>
> The series is now based on the rtc-next branch from:
> git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git.
>
> This V6 patch series is built upon the V5 series and has been rebased
> exclusively onto the latest commit in the rtc-next branch, which
> corresponds to rtc-6.17."
>
> [...]
Applied, thanks!
[1/3] dt-bindings: rtc: Add support for ATCRTC100 RTC
https://git.kernel.org/abelloni/c/e1794c59730a
[2/3] MAINTAINERS: Add entry for ATCRTC100 RTC driver
https://git.kernel.org/abelloni/c/a603092d5be1
[3/3] rtc: atcrtc100: Add ATCRTC100 RTC driver
https://git.kernel.org/abelloni/c/7adca706fe16
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH 06/25] rtc: Add driver for RDA Micro SoC
From: Alexandre Belloni @ 2025-11-06 22:42 UTC (permalink / raw)
To: dang.huynh
Cc: Manivannan Sadhasivam, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski,
Michael Turquette, Stephen Boyd, Philipp Zabel, Sebastian Reichel,
Vinod Koul, Kees Cook, Gustavo A. R. Silva, Ulf Hansson,
linux-arm-kernel, linux-unisoc, devicetree, linux-kernel,
linux-gpio, linux-rtc, linux-clk, linux-pm, dmaengine,
linux-hardening, linux-mmc
In-Reply-To: <20250917-rda8810pl-drivers-v1-6-9ca9184ca977@mainlining.org>
Hello,
There are checkpatch --strict issues, please fix them.
On 17/09/2025 03:25:03+0700, Dang Huynh via B4 Relay wrote:
> MAINTAINERS | 6 +
> drivers/rtc/Kconfig | 11 ++
> drivers/rtc/Makefile | 1 +
> drivers/rtc/rtc-rda.c | 356 ++++++++++++++++++++++++++++++++++++++++++++++++++
Unless you can guarantee this driver will support all the future RDA
SoC RTCs, the filename needs to be SoC specific.
> +config RTC_DRV_RDA
> + tristate "RDA Micro RTC"
> + depends on ARCH_RDA || COMPILE_TEST
> + select REGMAP_MMIO
> + help
> + If you say yes here you get support for the built-in RTC on
> + RDA Micro SoC.
You probably also need to list which ones are supported.
> +static int rda_rtc_settime(struct device *dev, struct rtc_time *tm)
> +{
> + struct rda_rtc *rtc = dev_get_drvdata(dev);
> + u32 high, low;
> + int ret;
> +
> + ret = rtc_valid_tm(tm);
> + if (ret < 0)
> + return ret;
The RTC core will never pass an invalid rtc_tm, this check is useless.
> +
> + /*
> + * The number of years since 1900 in kernel,
> + * but it is defined since 2000 by HW.
> + * The number of mons' range is from 0 to 11 in kernel,
> + * but it is defined from 1 to 12 by HW.
This comment is not super useful as this is super common in the RTC
drivers,. If you want to keep it, please fix it.
> + */
> + low = FIELD_PREP(RDA_SEC_MASK, tm->tm_sec) |
> + FIELD_PREP(RDA_MIN_MASK, tm->tm_min) |
> + FIELD_PREP(RDA_HRS_MASK, tm->tm_hour);
> +
> + high = FIELD_PREP(RDA_MDAY_MASK, tm->tm_mday) |
> + FIELD_PREP(RDA_MON_MASK, tm->tm_mon + 1) |
> + FIELD_PREP(RDA_YEAR_MASK, tm->tm_year - 100) |
> + FIELD_PREP(RDA_WDAY_MASK, tm->tm_wday);
> +
> + ret = regmap_write(rtc->regmap, RDA_RTC_CAL_LOAD_LOW_REG, low);
> + if (ret < 0) {
> + dev_err(dev, "Failed to update RTC low register: %d\n", ret);
This needs to be a dev_dbg or removed.
> + return ret;
> + }
> +
> + ret = regmap_write(rtc->regmap, RDA_RTC_CAL_LOAD_HIGH_REG, high);
> + if (ret < 0) {
> + dev_err(dev, "Failed to update RTC low register: %d\n", ret);
Ditto
> + return ret;
> + }
> +
> + ret = regmap_update_bits(rtc->regmap, RDA_RTC_CMD_REG, RDA_RTC_CMD_CAL_LOAD, 1);
> + if (ret < 0) {
> + dev_err(dev, "Failed to update RTC cal load register: %d\n", ret);
Ditto
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int rda_rtc_readtime(struct device *dev, struct rtc_time *tm)
> +{
> + struct rda_rtc *rtc = dev_get_drvdata(dev);
> + unsigned int high, low;
> + int ret;
> +
> + /*
> + * Check if RTC data is valid.
> + *
> + * When this bit is set, it means the data in the RTC is invalid
> + * or not configured.
> + */
> + ret = regmap_test_bits(rtc->regmap, RDA_RTC_STA_REG, RDA_RTC_STA_NOT_PROG);
> + if (ret < 0) {
> + dev_err(dev, "Failed to read RTC status: %d\n", ret);
dev_dbg
> + return ret;
> + } else if (ret > 0)
> + return -EINVAL;
> +
> + ret = regmap_read(rtc->regmap, RDA_RTC_CUR_LOAD_HIGH_REG, &high);
> + if (ret) {
> + dev_err(dev, "Failed to read RTC high reg: %d\n", ret);
Ditto
> + return ret;
> + }
> +
> + ret = regmap_read(rtc->regmap, RDA_RTC_CUR_LOAD_LOW_REG, &low);
> + if (ret) {
> + dev_err(dev, "Failed to read RTC low reg: %d\n", ret);
Ditto
> + return ret;
> + }
> +
> + tm->tm_sec = FIELD_GET(RDA_SEC_MASK, low);
> + tm->tm_min = FIELD_GET(RDA_MIN_MASK, low);
> + tm->tm_hour = FIELD_GET(RDA_HRS_MASK, low);
> + tm->tm_mday = FIELD_GET(RDA_MDAY_MASK, high);
> + tm->tm_mon = FIELD_GET(RDA_MON_MASK, high);
> + tm->tm_year = FIELD_GET(RDA_YEAR_MASK, high);
> + tm->tm_wday = FIELD_GET(RDA_WDAY_MASK, high);
> +
> + /*
> + * The number of years since 1900 in kernel,
> + * but it is defined since 2000 by HW.
> + */
> + tm->tm_year += 100;
> + /*
> + * The number of mons' range is from 0 to 11 in kernel,
> + * but it is defined from 1 to 12 by HW.
> + */
You can probably drop both comments.
> + tm->tm_mon -= 1;
> +
> + return 0;
> +}
> +
> +static int rda_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> + struct rda_rtc *rtc = dev_get_drvdata(dev);
> + struct rtc_time *tm = &alrm->time;
> + unsigned int high, low;
> + int ret;
> +
> + ret = regmap_read(rtc->regmap, RDA_RTC_ALARM_HIGH_REG, &high);
> + if (ret) {
> + dev_err(dev, "Failed to read alarm low reg: %d\n", ret);
Just to be clear, the driver is super verbose with all those dev_err.
Strings are bloating the kernel and those string will probably never be
seen by any user and event if they are seen, the user doesn't have any
other action to do other than retrying. Please remove them of move them
to dev_dbg
> + return ret;
> + }
> +
> + ret = regmap_read(rtc->regmap, RDA_RTC_ALARM_LOW_REG, &low);
> + if (ret) {
> + dev_err(dev, "Failed to read alarm low reg: %d\n", ret);
> + return ret;
> + }
> +
> + tm->tm_sec = FIELD_GET(RDA_SEC_MASK, low);
> + tm->tm_min = FIELD_GET(RDA_MIN_MASK, low);
> + tm->tm_hour = FIELD_GET(RDA_HRS_MASK, low);
> + tm->tm_mday = FIELD_GET(RDA_MDAY_MASK, high);
> + tm->tm_mon = FIELD_GET(RDA_MON_MASK, high);
> + tm->tm_year = FIELD_GET(RDA_YEAR_MASK, high);
> + tm->tm_wday = FIELD_GET(RDA_WDAY_MASK, high);
> +
> + /*
> + * The number of years since 1900 in kernel,
> + * but it is defined since 2000 by HW.
> + */
> + tm->tm_year += 100;
> + /*
> + * The number of mons' range is from 0 to 11 in kernel,
> + * but it is defined from 1 to 12 by HW.
> + */
> + tm->tm_mon -= 1;
> +
> + return 0;
> +}
> +
> +static int rda_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
> +{
> + struct rda_rtc *rtc = dev_get_drvdata(dev);
> +
> + if (enabled)
> + return regmap_update_bits(rtc->regmap, RDA_RTC_CMD_REG,
> + RDA_RTC_CMD_ALARM_ENABLE, 1);
> +
> + return regmap_update_bits(rtc->regmap, RDA_RTC_CMD_REG,
> + RDA_RTC_CMD_ALARM_DISABLE, 1);
Wow, this is super weird, so you have one bit to enable and one to
disable the alarm. Is RDA_RTC_CMD_REG write only?
> +}
> +
> +static int rda_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> + struct rda_rtc *rtc = dev_get_drvdata(dev);
> + struct rtc_time *tm = &alrm->time;
> + u32 high, low;
> + int ret;
> +
> + ret = rtc_valid_tm(tm);
> + if (ret < 0)
> + return ret;
> +
tm will never be invalid
> + /* TODO: Check if it's necessary to disable IRQ first */
I'd say probably not ;)
> + rda_rtc_alarm_irq_enable(dev, 0);
> +
> + /*
> + * The number of years since 1900 in kernel,
> + * but it is defined since 2000 by HW.
> + * The number of mons' range is from 0 to 11 in kernel,
> + * but it is defined from 1 to 12 by HW.
> + */
This is still the same comment...
> + low = FIELD_PREP(RDA_SEC_MASK, tm->tm_sec) |
> + FIELD_PREP(RDA_MIN_MASK, tm->tm_min) |
> + FIELD_PREP(RDA_HRS_MASK, tm->tm_hour);
> +
> + high = FIELD_PREP(RDA_MDAY_MASK, tm->tm_mday) |
> + FIELD_PREP(RDA_MON_MASK, tm->tm_mon + 1) |
> + FIELD_PREP(RDA_YEAR_MASK, tm->tm_year - 100) |
> + FIELD_PREP(RDA_WDAY_MASK, tm->tm_wday);
> +
> +
> + ret = regmap_write(rtc->regmap, RDA_RTC_ALARM_LOW_REG, low);
> + if (ret < 0) {
> + dev_err(dev, "Failed to set low alarm register: %d\n", ret);
> + return ret;
> + }
> +
> + ret = regmap_write(rtc->regmap, RDA_RTC_ALARM_HIGH_REG, high);
> + if (ret < 0) {
> + dev_err(dev, "Failed to set low alarm register: %d\n", ret);
> + return ret;
> + }
> +
> + ret = regmap_update_bits(rtc->regmap, RDA_RTC_CMD_REG, RDA_RTC_CMD_ALARM_LOAD, 1);
> + if (ret < 0) {
> + dev_err(dev, "Failed to set alarm register: %d\n", ret);
> + return ret;
> + }
> +
> + dev_dbg(dev, "Alarm set: %4d-%02d-%02d %02d:%02d:%02d\n",
> + 2000 + (tm->tm_year - 100), tm->tm_mon + 1, tm->tm_mday,
> + tm->tm_hour, tm->tm_min, tm->tm_sec);
You probably want to use %ptR or drop this as we have a tracepoint just
after.
> +
> + return 0;
> +}
> +
> +static int rda_rtc_proc(struct device *dev, struct seq_file *seq)
> +{
> + struct rda_rtc *rtc = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = regmap_test_bits(rtc->regmap, RDA_RTC_STA_REG, RDA_RTC_STA_ALARM_ENABLE);
> + if (ret < 0) {
> + dev_err(dev, "Failed to read alarm status: %d\n", ret);
> + return ret;
> + }
> +
> + seq_printf(seq, "alarm enable\t: %s\n", (ret > 0) ? "yes" : "no");
> +
> + return 0;
> +}
Drop this function, this interface is obsolete
> +
> +static const struct rtc_class_ops rda_rtc_ops = {
> + .read_time = rda_rtc_readtime,
> + .set_time = rda_rtc_settime,
> + .read_alarm = rda_rtc_readalarm,
> + .set_alarm = rda_rtc_setalarm,
> + .proc = rda_rtc_proc,
> + .alarm_irq_enable = rda_rtc_alarm_irq_enable,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int rda_rtc_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + /* TODO: Check if it's okay to turn on alarm IRQ when it's not set */
> + return rda_rtc_alarm_irq_enable(&pdev->dev, 1);
> +}
> +
> +static int rda_rtc_resume(struct platform_device *pdev)
> +{
> + /* If alarms were left, we turn them off. */
> + return rda_rtc_alarm_irq_enable(&pdev->dev, 0);
> +}
Let userspace enabling/disabling alarm, the kernel must not decide to
enable or disable them which fixes your TODO
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(rda_rtc_pm_ops, rda_rtc_suspend, rda_rtc_resume);
> +
> +static const struct regmap_config regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +static int rda_rtc_probe(struct platform_device *pdev)
> +{
> + struct rda_rtc *rda_rtc;
> + void __iomem *base;
> +
> + rda_rtc = devm_kzalloc(&pdev->dev, sizeof(*rda_rtc), GFP_KERNEL);
> + if (!rda_rtc)
> + return -ENOMEM;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return dev_err_probe(&pdev->dev, PTR_ERR(base),
> + "failed to remap resource\n");
> +
> + rda_rtc->regmap = devm_regmap_init_mmio(&pdev->dev, base, ®map_config);
> + if (!rda_rtc->regmap)
> + return dev_err_probe(&pdev->dev, PTR_ERR(rda_rtc->regmap),
> + "can't find regmap\n");
> +
> + rda_rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
> + if (IS_ERR(rda_rtc->rtc_dev))
> + return dev_err_probe(&pdev->dev, PTR_ERR(rda_rtc->rtc_dev),
> + "failed to allocate rtc device\n");
> +
> + rda_rtc->rtc_dev->ops = &rda_rtc_ops;
> + rda_rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
> + rda_rtc->rtc_dev->range_max = RTC_TIMESTAMP_END_2127;
> +
> + platform_set_drvdata(pdev, rda_rtc);
> +
> + return devm_rtc_register_device(rda_rtc->rtc_dev);
> +}
> +
> +static const struct of_device_id rda_rtc_id_table[] = {
> + { .compatible = "rda,8810pl-rtc", },
> + { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, rda_rtc_id_table);
> +
> +static struct platform_driver rda_rtc_driver = {
> + .probe = rda_rtc_probe,
> + .driver = {
> + .name = "rtc-rda",
> + .pm = &rda_rtc_pm_ops,
> + .of_match_table = rda_rtc_id_table,
> + },
> +};
> +module_platform_driver(rda_rtc_driver);
> +
> +MODULE_AUTHOR("Dang Huynh <dang.huynh@mainlining.org>");
> +MODULE_DESCRIPTION("RDA Micro RTC driver");
> +MODULE_LICENSE("GPL");
>
> --
> 2.51.0
>
>
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: (subset) [PATCH v2 1/4] mfd: simple-mfd-i2c: remove select I2C_K1
From: Lee Jones @ 2025-11-06 16:04 UTC (permalink / raw)
To: Lee Jones, Yixun Lan, Alex Elder, Andi Shyti, Alexandre Belloni,
Liam Girdwood, Mark Brown, Troy Mitchell
Cc: linux-kernel, linux-riscv, spacemit, linux-i2c, linux-rtc,
kernel test robot
In-Reply-To: <20251027-p1-kconfig-fix-v2-1-49688f30bae8@linux.spacemit.com>
On Mon, 27 Oct 2025 13:48:05 +0800, Troy Mitchell wrote:
> select will force a symbol to a specific value without considering
> its dependencies. As a result, the i2c-k1 driver will fail to build
> when OF or COMMON_CLK are disabled.
>
> The reason for removing I2C_K1 instead of adding a depends on condition
> is to keep the possibility for other SoCs to use this PMIC.
>
> [...]
Applied, thanks!
[1/4] mfd: simple-mfd-i2c: remove select I2C_K1
commit: ecf6bc474ae97c404e2125b413eb0ef3627b03c5
--
Lee Jones [李琼斯]
^ permalink raw reply
* [GIT PULL] Immutable branch between MFD and HWMON due for the v6.19 merge window
From: Lee Jones @ 2025-11-06 14:00 UTC (permalink / raw)
To: James Calligeros
Cc: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Rob Herring, 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: <20251025-macsmc-subdevs-v4-6-374d5c9eba0e@gmail.com>
Whoever takes this driver will need to pull the following:
The following changes since commit 3a8660878839faadb4f1a6dd72c3179c1df56787:
Linux 6.18-rc1 (2025-10-12 13:42:36 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git ib-mfd-hwmon-v6.19
for you to fetch changes up to b340412a3b22b60b5e19cce8726940c7b5b14439:
mfd: macsmc: Add new __SMC_KEY macro (2025-11-06 13:58:42 +0000)
----------------------------------------------------------------
Immutable branch between MFD and HWMON due for the v6.19 merge window
----------------------------------------------------------------
James Calligeros (1):
mfd: macsmc: Add new __SMC_KEY macro
include/linux/mfd/macsmc.h | 1 +
1 file changed, 1 insertion(+)
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: (subset) [PATCH v4 05/11] mfd: macsmc: Add new __SMC_KEY macro
From: Lee Jones @ 2025-11-06 13:56 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251025-macsmc-subdevs-v4-5-374d5c9eba0e@gmail.com>
On Sat, 25 Oct 2025 10:24:36 +1000, James Calligeros wrote:
> When using the _SMC_KEY macro in switch/case statements, GCC 15.2.1 errors
> out with 'case label does not reduce to an integer constant'. Introduce
> a new __SMC_KEY macro that can be used instead.
>
>
Applied, thanks!
[05/11] mfd: macsmc: Add new __SMC_KEY macro
commit: 8c3290b4c975e35a01aecfb51e0e004b6f7c0480
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH v4 00/11] mfd: macsmc: add rtc, hwmon and hid subdevices
From: Lee Jones @ 2025-11-06 13:55 UTC (permalink / raw)
To: James Calligeros
Cc: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Rob Herring, 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, Mark Kettenis, Hector Martin
In-Reply-To: <20251025-macsmc-subdevs-v4-0-374d5c9eba0e@gmail.com>
On Sat, 25 Oct 2025, James Calligeros wrote:
> Hi all,
>
> This series adds support for the remaining SMC subdevices. These are the
> RTC, hwmon, and HID devices. They are being submitted together as the RTC
> and hwmon drivers both require changes to the SMC DT schema.
>
> The RTC driver is responsible for getting and setting the system clock,
> and requires an NVMEM cell. This series replaces Sven's original RTC driver
> submission [1].
>
> The hwmon function is an interesting one. While each Apple Silicon device
> exposes pretty similar sets of sensors, these all seem to be paired to
> different SMC keys in the firmware interface. This is true even when the
> sensors are on the SoC. For example, an M1 MacBook Pro will use different
> keys to access the LITTLE core temperature sensors to an M1 Mac mini. This
> necessitates describing which keys correspond to which sensors for each
> device individually, and populating the hwmon structs at runtime. We do
> this with a node in the device tree. This series includes only the keys
> for sensors which we know to be common to all devices. The SMC is also
> responsible for monitoring and controlling fan speeds on systems with fans,
> which we expose via the hwmon driver.
>
> The SMC also handles the hardware power button and lid switch. Power
> button presses and lid opening/closing are emitted as HID events, so we
> add an input subdevice to handle them.
>
> Since there are no real dependencies between the components of this series,
> it should be fine for each subsystem to take the relevant patches through
> their trees. The mfd one-liners should be taken in order to avoid trivial
> conflicts.
The MFD parts look okay. Let me know when the other drivers have been
accepted and I'll apply them all.
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH v4 03/11] rtc: Add new rtc-macsmc driver for Apple Silicon Macs
From: Lee Jones @ 2025-11-06 13:54 UTC (permalink / raw)
To: James Calligeros
Cc: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Rob Herring, 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, Hector Martin
In-Reply-To: <20251025-macsmc-subdevs-v4-3-374d5c9eba0e@gmail.com>
On Sat, 25 Oct 2025, James Calligeros wrote:
> From: Hector Martin <marcan@marcan.st>
>
> 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 <neal@gompa.dev>
> Signed-off-by: Hector Martin <marcan@marcan.st>
> Signed-off-by: Sven Peter <sven@kernel.org>
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
> MAINTAINERS | 1 +
> drivers/rtc/Kconfig | 11 ++
> drivers/rtc/Makefile | 1 +
> drivers/rtc/rtc-macsmc.c | 141 +++++++++++++++++++++++++
> 4 files changed, 154 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 10f4c0034b5e..3c6322872dd1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2460,6 +2460,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 4a8dc8d0a4b7..e165301d4abb 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -2078,6 +2078,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 610a9ee5fd33..32083bd5bb81 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -93,6 +93,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..05e360277f63
> --- /dev/null
> +++ b/drivers/rtc/rtc-macsmc.c
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +/*
> + * Apple SMC RTC driver
> + * Copyright The Asahi Linux Contributors
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/mfd/core.h>
Why is this here?
> +#include <linux/mfd/macsmc.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-consumer.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/rtc.h>
> +#include <linux/slab.h>
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH v4 08/11] input: macsmc-input: New driver to handle the Apple Mac SMC buttons/lid
From: Lee Jones @ 2025-11-06 13:53 UTC (permalink / raw)
To: James Calligeros
Cc: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Rob Herring, 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, Hector Martin
In-Reply-To: <20251025-macsmc-subdevs-v4-8-374d5c9eba0e@gmail.com>
On Sat, 25 Oct 2025, James Calligeros wrote:
> From: Hector Martin <marcan@marcan.st>
>
> This driver implements power button and lid switch support for Apple Mac
> devices using SMC controllers driven by the macsmc driver.
>
> In addition to basic input support, this also responds to the final
> shutdown warning (when the power button is held down long enough) by
> doing an emergency kernel poweroff. This allows the NVMe controller to
> be cleanly shut down, which prevents data loss for in-cache data.
>
> Reviewed-by: Neal Gompa <neal@gompa.dev>
> Signed-off-by: Hector Martin <marcan@marcan.st>
> Co-developed-by: Sven Peter <sven@kernel.org>
> Signed-off-by: Sven Peter <sven@kernel.org>
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
> MAINTAINERS | 1 +
> drivers/input/misc/Kconfig | 11 ++
> drivers/input/misc/Makefile | 1 +
> drivers/input/misc/macsmc-input.c | 208 +++++++++++++++++++++++++
> 4 files changed, 221 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 79b9f40224a9..e8283f127f11 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2451,6 +2451,7 @@ F: drivers/hwmon/macsmc-hwmon.c
> F: drivers/pmdomain/apple/
> F: drivers/i2c/busses/i2c-pasemi-core.c
> F: drivers/i2c/busses/i2c-pasemi-platform.c
> +F: drivers/input/misc/macsmc-input.c
> F: drivers/input/touchscreen/apple_z2.c
> F: drivers/iommu/apple-dart.c
> F: drivers/iommu/io-pgtable-dart.c
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index 0e6b49fb54bc..109660a1a5d2 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -981,4 +981,15 @@ config INPUT_STPMIC1_ONKEY
> To compile this driver as a module, choose M here: the
> module will be called stpmic1_onkey.
>
> +config INPUT_MACSMC
> + tristate "Apple Mac SMC lid/buttons"
> + depends on MFD_MACSMC
> + help
> + Say Y here if you want to use the input events delivered via the
> + SMC controller on Apple Mac machines using the macsmc driver.
> + This includes lid open/close and the power button.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called macsmc-input.
> +
> endif
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index ae857c24f48e..480a0d08d4ae 100644
> --- a/drivers/input/misc/Makefile
> +++ b/drivers/input/misc/Makefile
> @@ -51,6 +51,7 @@ obj-$(CONFIG_INPUT_IQS7222) += iqs7222.o
> obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
> obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
> obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
> +obj-$(CONFIG_INPUT_MACSMC_INPUT) += macsmc-input.o
> obj-$(CONFIG_INPUT_MAX7360_ROTARY) += max7360-rotary.o
> obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o
> obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
> diff --git a/drivers/input/misc/macsmc-input.c b/drivers/input/misc/macsmc-input.c
> new file mode 100644
> index 000000000000..d35322856526
> --- /dev/null
> +++ b/drivers/input/misc/macsmc-input.c
> @@ -0,0 +1,208 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +/*
> + * Apple SMC input event driver
> + * Copyright The Asahi Linux Contributors
> + *
> + * This driver exposes certain events from the SMC as an input device.
> + * This includes the lid open/close and power button notifications.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/input.h>
> +#include <linux/mfd/core.h>
This looks like it shouldn't be there.
> +#include <linux/mfd/macsmc.h>
> +#include <linux/module.h>
> +#include <linux/reboot.h>
--
Lee Jones [李琼斯]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox