* [PATCH 0/3] rtc: Add StarFive JH7110 RTC support @ 2026-11-06 17:55 ` Owen O'Hehir 0 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:55 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley The JH7110 has an RTC in its always-on domain that mainline does not support. This series adds a binding, a driver and the SoC DT node. The driver is based on the StarFive vendor driver (rtc-starfive.c, commit ebac2b5 in the StarFive 6.12 tree), reworked for mainline: - hardware calibration and the default time set in probe are dropped - wakeup uses the generic wake IRQ helpers instead of the irq_desc hack - set_time waits for the counter to load the new time - read_time re-reads if the time rolls over between TIME and DATE - the offset rounds to the nearest step and follows the sysfs sign convention (positive = slower) - the 32.768 kHz counter clock is described in the binding and enabled Thanks to ziv.xu and Hal Feng at StarFive for the original driver. Tested on a VisionFive 2 v1.3B with next-20261105 and v7.3.1: setting and reading the time across the 2000-2099 range (out-of-range years refused), leap day and century rollover, the alarm interrupt with cancel, the offset, the rate over 60 s, and setting the system clock at boot. Not tested: suspend wakeup, drift over hours, and keeping time across a power-off, as the board has no RTC battery connector. Known behaviour: the RTC loses about the length of a reboot across a warm reboot; the counter appears to stop during reset. After the StarFive vendor kernel the first boot found an invalid time. I would appreciate an opinion on whether this is expected of the hardware or something the driver should handle. The binding lists the RTC maintainer, as no one at StarFive has taken it on; I'm happy to change it if someone from StarFive wants to. Owen O'Hehir (2): dt-bindings: rtc: Add StarFive JH7110 RTC riscv: dts: starfive: jh7110: Add the RTC node ziv.xu (1): rtc: Add StarFive JH7110 RTC driver .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++ arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 + drivers/rtc/Kconfig | 11 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-jh7110.c | 324 ++++++++++++++++++ 5 files changed, 435 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml create mode 100644 drivers/rtc/rtc-jh7110.c base-commit: ddfe51b0a0f5dc9e415cc2c8ad8db17532dd426b -- 2.43.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 0/3] rtc: Add StarFive JH7110 RTC support @ 2026-11-06 17:55 ` Owen O'Hehir 0 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:55 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley The JH7110 has an RTC in its always-on domain that mainline does not support. This series adds a binding, a driver and the SoC DT node. The driver is based on the StarFive vendor driver (rtc-starfive.c, commit ebac2b5 in the StarFive 6.12 tree), reworked for mainline: - hardware calibration and the default time set in probe are dropped - wakeup uses the generic wake IRQ helpers instead of the irq_desc hack - set_time waits for the counter to load the new time - read_time re-reads if the time rolls over between TIME and DATE - the offset rounds to the nearest step and follows the sysfs sign convention (positive = slower) - the 32.768 kHz counter clock is described in the binding and enabled Thanks to ziv.xu and Hal Feng at StarFive for the original driver. Tested on a VisionFive 2 v1.3B with next-20261105 and v7.3.1: setting and reading the time across the 2000-2099 range (out-of-range years refused), leap day and century rollover, the alarm interrupt with cancel, the offset, the rate over 60 s, and setting the system clock at boot. Not tested: suspend wakeup, drift over hours, and keeping time across a power-off, as the board has no RTC battery connector. Known behaviour: the RTC loses about the length of a reboot across a warm reboot; the counter appears to stop during reset. After the StarFive vendor kernel the first boot found an invalid time. I would appreciate an opinion on whether this is expected of the hardware or something the driver should handle. The binding lists the RTC maintainer, as no one at StarFive has taken it on; I'm happy to change it if someone from StarFive wants to. Owen O'Hehir (2): dt-bindings: rtc: Add StarFive JH7110 RTC riscv: dts: starfive: jh7110: Add the RTC node ziv.xu (1): rtc: Add StarFive JH7110 RTC driver .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++ arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 + drivers/rtc/Kconfig | 11 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-jh7110.c | 324 ++++++++++++++++++ 5 files changed, 435 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml create mode 100644 drivers/rtc/rtc-jh7110.c base-commit: ddfe51b0a0f5dc9e415cc2c8ad8db17532dd426b -- 2.43.0 _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/3] dt-bindings: rtc: Add StarFive JH7110 RTC 2026-11-06 17:55 ` Owen O'Hehir @ 2026-11-06 17:55 ` Owen O'Hehir -1 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:55 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley Describe the RTC in the always-on domain of the StarFive JH7110 SoC. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml diff --git a/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml new file mode 100644 index 000000000..95edddea1 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/starfive,jh7110-rtc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JH7110 Real Time Clock + +maintainers: + - Alexandre Belloni <alexandre.belloni@bootlin.com> + +description: + The RTC in the always-on domain of the StarFive JH7110 SoC. It counts BCD + time and date from a 32.768 kHz clock and has an alarm, a frequency offset + adjustment and millisecond and one-second pulse outputs. + +allOf: + - $ref: rtc.yaml# + +properties: + compatible: + const: starfive,jh7110-rtc + + reg: + maxItems: 1 + + interrupts: + items: + - description: Millisecond pulse + - description: One-second pulse + - description: Alarm and calibration events + + interrupt-names: + items: + - const: ms-pulse + - const: sec-pulse + - const: rtc + + clocks: + items: + - description: APB bus clock + - description: Calibration reference clock + - description: 32.768 kHz counter clock + + clock-names: + items: + - const: apb + - const: cal + - const: 32k + + resets: + items: + - description: 32.768 kHz counter domain reset + - description: APB bus reset + - description: Calibration reset + +required: + - compatible + - reg + - interrupts + - interrupt-names + - clocks + - clock-names + - resets + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/starfive,jh7110-crg.h> + #include <dt-bindings/reset/starfive,jh7110-crg.h> + + rtc@17040000 { + compatible = "starfive,jh7110-rtc"; + reg = <0x17040000 0x10000>; + interrupts = <10>, <11>, <12>; + interrupt-names = "ms-pulse", "sec-pulse", "rtc"; + clocks = <&aoncrg JH7110_AONCLK_RTC_APB>, + <&aoncrg JH7110_AONCLK_RTC_CAL>, + <&aoncrg JH7110_AONCLK_RTC_32K>; + clock-names = "apb", "cal", "32k"; + resets = <&aoncrg JH7110_AONRST_RTC_32K>, + <&aoncrg JH7110_AONRST_RTC_APB>, + <&aoncrg JH7110_AONRST_RTC_CAL>; + }; -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 1/3] dt-bindings: rtc: Add StarFive JH7110 RTC @ 2026-11-06 17:55 ` Owen O'Hehir 0 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:55 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley Describe the RTC in the always-on domain of the StarFive JH7110 SoC. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml diff --git a/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml new file mode 100644 index 000000000..95edddea1 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/starfive,jh7110-rtc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JH7110 Real Time Clock + +maintainers: + - Alexandre Belloni <alexandre.belloni@bootlin.com> + +description: + The RTC in the always-on domain of the StarFive JH7110 SoC. It counts BCD + time and date from a 32.768 kHz clock and has an alarm, a frequency offset + adjustment and millisecond and one-second pulse outputs. + +allOf: + - $ref: rtc.yaml# + +properties: + compatible: + const: starfive,jh7110-rtc + + reg: + maxItems: 1 + + interrupts: + items: + - description: Millisecond pulse + - description: One-second pulse + - description: Alarm and calibration events + + interrupt-names: + items: + - const: ms-pulse + - const: sec-pulse + - const: rtc + + clocks: + items: + - description: APB bus clock + - description: Calibration reference clock + - description: 32.768 kHz counter clock + + clock-names: + items: + - const: apb + - const: cal + - const: 32k + + resets: + items: + - description: 32.768 kHz counter domain reset + - description: APB bus reset + - description: Calibration reset + +required: + - compatible + - reg + - interrupts + - interrupt-names + - clocks + - clock-names + - resets + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/starfive,jh7110-crg.h> + #include <dt-bindings/reset/starfive,jh7110-crg.h> + + rtc@17040000 { + compatible = "starfive,jh7110-rtc"; + reg = <0x17040000 0x10000>; + interrupts = <10>, <11>, <12>; + interrupt-names = "ms-pulse", "sec-pulse", "rtc"; + clocks = <&aoncrg JH7110_AONCLK_RTC_APB>, + <&aoncrg JH7110_AONCLK_RTC_CAL>, + <&aoncrg JH7110_AONCLK_RTC_32K>; + clock-names = "apb", "cal", "32k"; + resets = <&aoncrg JH7110_AONRST_RTC_32K>, + <&aoncrg JH7110_AONRST_RTC_APB>, + <&aoncrg JH7110_AONRST_RTC_CAL>; + }; -- 2.43.0 _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/3] dt-bindings: rtc: Add StarFive JH7110 RTC 2026-11-06 17:55 ` Owen O'Hehir (?) @ 2026-11-06 17:59 ` sashiko-bot -1 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-11-06 17:59 UTC (permalink / raw) To: Owen O'Hehir, linux-rtc; +Cc: Alexandre Belloni > Describe the RTC in the always-on domain of the StarFive JH7110 SoC. > > Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> Sashiko has reviewed this patch and found no issues. -- Sashiko AI review · https://sashiko.dev/#/patchset/20261106175600.3877614-1-oo.hehir@gmail.com?part=1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/3] dt-bindings: rtc: Add StarFive JH7110 RTC 2026-11-06 17:55 ` Owen O'Hehir @ 2026-11-06 18:16 ` Conor Dooley -1 siblings, 0 replies; 15+ messages in thread From: Conor Dooley @ 2026-11-06 18:16 UTC (permalink / raw) To: Owen O'Hehir Cc: Alexandre Belloni, linux-rtc, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu [-- Attachment #1: Type: text/plain, Size: 3355 bytes --] On Fri, Nov 06, 2026 at 05:55:58PM +0000, Owen O'Hehir wrote: > Describe the RTC in the always-on domain of the StarFive JH7110 SoC. > > Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> > --- > .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++++++++++++++++ > 1 file changed, 85 insertions(+) > create mode 100644 Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml > > diff --git a/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml > new file mode 100644 > index 000000000..95edddea1 > --- /dev/null > +++ b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml > @@ -0,0 +1,85 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/rtc/starfive,jh7110-rtc.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: StarFive JH7110 Real Time Clock > + > +maintainers: > + - Alexandre Belloni <alexandre.belloni@bootlin.com> Really, this should be you or someone that actually cares about the rtc on this device, not the subsystem maintainer. pw-bot: changes-requested Otherwise, this looks fine. Cheers, Conor. > + > +description: > + The RTC in the always-on domain of the StarFive JH7110 SoC. It counts BCD > + time and date from a 32.768 kHz clock and has an alarm, a frequency offset > + adjustment and millisecond and one-second pulse outputs. > + > +allOf: > + - $ref: rtc.yaml# > + > +properties: > + compatible: > + const: starfive,jh7110-rtc > + > + reg: > + maxItems: 1 > + > + interrupts: > + items: > + - description: Millisecond pulse > + - description: One-second pulse > + - description: Alarm and calibration events > + > + interrupt-names: > + items: > + - const: ms-pulse > + - const: sec-pulse > + - const: rtc > + > + clocks: > + items: > + - description: APB bus clock > + - description: Calibration reference clock > + - description: 32.768 kHz counter clock > + > + clock-names: > + items: > + - const: apb > + - const: cal > + - const: 32k > + > + resets: > + items: > + - description: 32.768 kHz counter domain reset > + - description: APB bus reset > + - description: Calibration reset > + > +required: > + - compatible > + - reg > + - interrupts > + - interrupt-names > + - clocks > + - clock-names > + - resets > + > +unevaluatedProperties: false > + > +examples: > + - | > + #include <dt-bindings/clock/starfive,jh7110-crg.h> > + #include <dt-bindings/reset/starfive,jh7110-crg.h> > + > + rtc@17040000 { > + compatible = "starfive,jh7110-rtc"; > + reg = <0x17040000 0x10000>; > + interrupts = <10>, <11>, <12>; > + interrupt-names = "ms-pulse", "sec-pulse", "rtc"; > + clocks = <&aoncrg JH7110_AONCLK_RTC_APB>, > + <&aoncrg JH7110_AONCLK_RTC_CAL>, > + <&aoncrg JH7110_AONCLK_RTC_32K>; > + clock-names = "apb", "cal", "32k"; > + resets = <&aoncrg JH7110_AONRST_RTC_32K>, > + <&aoncrg JH7110_AONRST_RTC_APB>, > + <&aoncrg JH7110_AONRST_RTC_CAL>; > + }; > -- > 2.43.0 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/3] dt-bindings: rtc: Add StarFive JH7110 RTC @ 2026-11-06 18:16 ` Conor Dooley 0 siblings, 0 replies; 15+ messages in thread From: Conor Dooley @ 2026-11-06 18:16 UTC (permalink / raw) To: Owen O'Hehir Cc: Alexandre Belloni, linux-rtc, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu [-- Attachment #1.1: Type: text/plain, Size: 3355 bytes --] On Fri, Nov 06, 2026 at 05:55:58PM +0000, Owen O'Hehir wrote: > Describe the RTC in the always-on domain of the StarFive JH7110 SoC. > > Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> > --- > .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++++++++++++++++ > 1 file changed, 85 insertions(+) > create mode 100644 Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml > > diff --git a/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml > new file mode 100644 > index 000000000..95edddea1 > --- /dev/null > +++ b/Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml > @@ -0,0 +1,85 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/rtc/starfive,jh7110-rtc.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: StarFive JH7110 Real Time Clock > + > +maintainers: > + - Alexandre Belloni <alexandre.belloni@bootlin.com> Really, this should be you or someone that actually cares about the rtc on this device, not the subsystem maintainer. pw-bot: changes-requested Otherwise, this looks fine. Cheers, Conor. > + > +description: > + The RTC in the always-on domain of the StarFive JH7110 SoC. It counts BCD > + time and date from a 32.768 kHz clock and has an alarm, a frequency offset > + adjustment and millisecond and one-second pulse outputs. > + > +allOf: > + - $ref: rtc.yaml# > + > +properties: > + compatible: > + const: starfive,jh7110-rtc > + > + reg: > + maxItems: 1 > + > + interrupts: > + items: > + - description: Millisecond pulse > + - description: One-second pulse > + - description: Alarm and calibration events > + > + interrupt-names: > + items: > + - const: ms-pulse > + - const: sec-pulse > + - const: rtc > + > + clocks: > + items: > + - description: APB bus clock > + - description: Calibration reference clock > + - description: 32.768 kHz counter clock > + > + clock-names: > + items: > + - const: apb > + - const: cal > + - const: 32k > + > + resets: > + items: > + - description: 32.768 kHz counter domain reset > + - description: APB bus reset > + - description: Calibration reset > + > +required: > + - compatible > + - reg > + - interrupts > + - interrupt-names > + - clocks > + - clock-names > + - resets > + > +unevaluatedProperties: false > + > +examples: > + - | > + #include <dt-bindings/clock/starfive,jh7110-crg.h> > + #include <dt-bindings/reset/starfive,jh7110-crg.h> > + > + rtc@17040000 { > + compatible = "starfive,jh7110-rtc"; > + reg = <0x17040000 0x10000>; > + interrupts = <10>, <11>, <12>; > + interrupt-names = "ms-pulse", "sec-pulse", "rtc"; > + clocks = <&aoncrg JH7110_AONCLK_RTC_APB>, > + <&aoncrg JH7110_AONCLK_RTC_CAL>, > + <&aoncrg JH7110_AONCLK_RTC_32K>; > + clock-names = "apb", "cal", "32k"; > + resets = <&aoncrg JH7110_AONRST_RTC_32K>, > + <&aoncrg JH7110_AONRST_RTC_APB>, > + <&aoncrg JH7110_AONRST_RTC_CAL>; > + }; > -- > 2.43.0 > [-- Attachment #1.2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] [-- Attachment #2: Type: text/plain, Size: 161 bytes --] _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/3] rtc: Add StarFive JH7110 RTC driver 2026-11-06 17:55 ` Owen O'Hehir @ 2026-11-06 17:55 ` Owen O'Hehir -1 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:55 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley From: "ziv.xu" <ziv.xu@starfivetech.com> Add a driver for the RTC in the always-on domain of the StarFive JH7110 SoC. It supports time, alarm with wakeup, and the frequency offset. Signed-off-by: ziv.xu <ziv.xu@starfivetech.com> Signed-off-by: Hal Feng <hal.feng@starfivetech.com> [Owen: rework of the StarFive vendor driver for mainline: drop hardware calibration & the default time set in probe, use the generic wake IRQ helpers, wait for the update bit in set_time, re-read a time that rolls over during the read, round the offset to the nearest step & follow the sysfs offset sign, enable the 32k counter clock] Co-developed-by: Owen O'Hehir <oo.hehir@gmail.com> Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- drivers/rtc/Kconfig | 11 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-jh7110.c | 324 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 drivers/rtc/rtc-jh7110.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 73ec9230e..332f2e022 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1807,6 +1807,17 @@ config RTC_DRV_MPC5121 This driver can also be built as a module. If so, the module will be called rtc-mpc5121. +config RTC_DRV_JH7110 + tristate "StarFive JH7110 RTC" + depends on ARCH_STARFIVE || COMPILE_TEST + help + If you say yes here you get support for the RTC in the always-on + domain of StarFive JH7110 SoCs, with alarm and frequency offset + support. + + This driver can also be built as a module. If so, the module + will be called rtc-jh7110. + config RTC_DRV_JZ4740 tristate "Ingenic JZ4740 SoC" depends on MIPS || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 46f1a0fc2..a5cddb8d8 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_RTC_DRV_IMX_BBM_SCMI) += rtc-imx-sm-bbm.o obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o +obj-$(CONFIG_RTC_DRV_JH7110) += rtc-jh7110.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_LOONGSON) += rtc-loongson.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o diff --git a/drivers/rtc/rtc-jh7110.c b/drivers/rtc/rtc-jh7110.c new file mode 100644 index 000000000..f7129b7ac --- /dev/null +++ b/drivers/rtc/rtc-jh7110.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RTC driver for the StarFive JH7110 SoC + * + * Copyright (C) 2021 StarFive Technology Co., Ltd. + */ + +#include <linux/bcd.h> +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/math64.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm_wakeirq.h> +#include <linux/reset.h> +#include <linux/rtc.h> + +#define JH7110_RTC_CFG 0x00 +#define JH7110_RTC_CFG_ENABLE BIT(0) +#define JH7110_RTC_CFG_CAL_SEL_HW BIT(2) +#define JH7110_RTC_CFG_HOUR_24H BIT(3) +#define JH7110_RTC_SW_CAL_VALUE 0x04 +#define JH7110_RTC_IRQ_EN 0x10 +#define JH7110_RTC_IRQ_EVENT 0x14 +#define JH7110_RTC_IRQ_ALARM BIT(4) +#define JH7110_RTC_IRQ_ALL GENMASK(4, 0) +#define JH7110_RTC_EVENT_UPDATE BIT(31) +#define JH7110_RTC_CAL_VALUE 0x24 +#define JH7110_RTC_CFG_TIME 0x28 +#define JH7110_RTC_CFG_DATE 0x2c +#define JH7110_RTC_ACT_TIME 0x34 +#define JH7110_RTC_ACT_DATE 0x38 +#define JH7110_RTC_TIME 0x3c +#define JH7110_RTC_DATE 0x40 + +#define JH7110_RTC_TIME_SEC GENMASK(6, 0) +#define JH7110_RTC_TIME_MIN GENMASK(13, 7) +#define JH7110_RTC_TIME_HOUR GENMASK(20, 14) +#define JH7110_RTC_DATE_DAY GENMASK(5, 0) +#define JH7110_RTC_DATE_MON GENMASK(10, 6) +#define JH7110_RTC_DATE_YEAR GENMASK(18, 11) + +#define JH7110_RTC_CAL_MASK GENMASK(15, 0) +#define JH7110_RTC_TICKS_PER_SEC 32768 + +#define JH7110_RTC_SYNC_TIMEOUT_US 1000 + +struct jh7110_rtc { + struct rtc_device *rtc; + void __iomem *base; +}; + +static void jh7110_rtc_reg2tm(struct rtc_time *tm, u32 time, u32 date) +{ + tm->tm_sec = bcd2bin(FIELD_GET(JH7110_RTC_TIME_SEC, time)); + tm->tm_min = bcd2bin(FIELD_GET(JH7110_RTC_TIME_MIN, time)); + tm->tm_hour = bcd2bin(FIELD_GET(JH7110_RTC_TIME_HOUR, time)); + tm->tm_mday = bcd2bin(FIELD_GET(JH7110_RTC_DATE_DAY, date)); + tm->tm_mon = bcd2bin(FIELD_GET(JH7110_RTC_DATE_MON, date)) - 1; + tm->tm_year = bcd2bin(FIELD_GET(JH7110_RTC_DATE_YEAR, date)) + 100; +} + +static u32 jh7110_rtc_tm2time(struct rtc_time *tm) +{ + return FIELD_PREP(JH7110_RTC_TIME_SEC, bin2bcd(tm->tm_sec)) | + FIELD_PREP(JH7110_RTC_TIME_MIN, bin2bcd(tm->tm_min)) | + FIELD_PREP(JH7110_RTC_TIME_HOUR, bin2bcd(tm->tm_hour)); +} + +static u32 jh7110_rtc_tm2date(struct rtc_time *tm) +{ + return FIELD_PREP(JH7110_RTC_DATE_DAY, bin2bcd(tm->tm_mday)) | + FIELD_PREP(JH7110_RTC_DATE_MON, bin2bcd(tm->tm_mon + 1)) | + FIELD_PREP(JH7110_RTC_DATE_YEAR, bin2bcd(tm->tm_year - 100)); +} + +static int jh7110_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 time, date; + + /* + * re-read if the time rolled over between reading TIME & DATE, since + * that rollover can also change the date. + */ + do { + time = readl(jrtc->base + JH7110_RTC_TIME); + date = readl(jrtc->base + JH7110_RTC_DATE); + } while (time != readl(jrtc->base + JH7110_RTC_TIME)); + + jh7110_rtc_reg2tm(tm, time, date); + + return 0; +} + +static int jh7110_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 val; + + writel(jh7110_rtc_tm2time(tm), jrtc->base + JH7110_RTC_CFG_TIME); + writel(jh7110_rtc_tm2date(tm), jrtc->base + JH7110_RTC_CFG_DATE); + + /* + * The counter loads CFG_TIME & CFG_DATE on this pulse; the bit appears + * to read back as 1 until the load is done. + */ + writel(JH7110_RTC_EVENT_UPDATE, jrtc->base + JH7110_RTC_IRQ_EVENT); + + return readl_poll_timeout(jrtc->base + JH7110_RTC_IRQ_EVENT, val, + !(val & JH7110_RTC_EVENT_UPDATE), 10, + JH7110_RTC_SYNC_TIMEOUT_US); +} + +static int jh7110_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 val; + + val = readl(jrtc->base + JH7110_RTC_IRQ_EN); + if (enabled) + val |= JH7110_RTC_IRQ_ALARM; + else + val &= ~JH7110_RTC_IRQ_ALARM; + writel(val, jrtc->base + JH7110_RTC_IRQ_EN); + + return 0; +} + +static int jh7110_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + + jh7110_rtc_reg2tm(&alrm->time, readl(jrtc->base + JH7110_RTC_ACT_TIME), + readl(jrtc->base + JH7110_RTC_ACT_DATE)); + alrm->enabled = !!(readl(jrtc->base + JH7110_RTC_IRQ_EN) & JH7110_RTC_IRQ_ALARM); + + return 0; +} + +static int jh7110_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 val; + int ret; + + jh7110_rtc_alarm_irq_enable(dev, 0); + writel(jh7110_rtc_tm2time(&alrm->time), jrtc->base + JH7110_RTC_ACT_TIME); + writel(jh7110_rtc_tm2date(&alrm->time), jrtc->base + JH7110_RTC_ACT_DATE); + writel(JH7110_RTC_IRQ_ALARM, jrtc->base + JH7110_RTC_IRQ_EVENT); + + ret = readl_poll_timeout(jrtc->base + JH7110_RTC_IRQ_EVENT, val, + !(val & JH7110_RTC_IRQ_ALARM), 10, + JH7110_RTC_SYNC_TIMEOUT_US); + if (ret) + return ret; + + return jh7110_rtc_alarm_irq_enable(dev, alrm->enabled); +} + +/* + * 1 sec for the RTC = CAL_VALUE + 1 cycles of the 32.768 kHz clock. + * Default of 0x7fff = exactly one second. + * Each step of CAL_VALUE changes the rate by 1/32768, about 30.5 ppm. + */ +static int jh7110_rtc_read_offset(struct device *dev, long *offset) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + s64 ticks; + + ticks = (readl(jrtc->base + JH7110_RTC_CAL_VALUE) & JH7110_RTC_CAL_MASK) + 1; + *offset = DIV_S64_ROUND_CLOSEST((ticks - JH7110_RTC_TICKS_PER_SEC) * NSEC_PER_SEC, + JH7110_RTC_TICKS_PER_SEC); + + return 0; +} + +static int jh7110_rtc_set_offset(struct device *dev, long offset) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + s64 ticks; + u32 val; + + if (offset < -NSEC_PER_SEC || offset > NSEC_PER_SEC) + return -ERANGE; + + ticks = JH7110_RTC_TICKS_PER_SEC + + DIV_S64_ROUND_CLOSEST((s64)offset * JH7110_RTC_TICKS_PER_SEC, NSEC_PER_SEC); + if (ticks < 1 || ticks > JH7110_RTC_CAL_MASK + 1) + return -ERANGE; + + writel(ticks - 1, jrtc->base + JH7110_RTC_SW_CAL_VALUE); + val = readl(jrtc->base + JH7110_RTC_CFG); + writel(val & ~JH7110_RTC_CFG_CAL_SEL_HW, jrtc->base + JH7110_RTC_CFG); + + return 0; +} + +static irqreturn_t jh7110_rtc_irq(int irq, void *data) +{ + struct jh7110_rtc *jrtc = data; + u32 events, val; + + events = readl(jrtc->base + JH7110_RTC_IRQ_EVENT) & + readl(jrtc->base + JH7110_RTC_IRQ_EN) & JH7110_RTC_IRQ_ALL; + if (!events) + return IRQ_NONE; + + writel(events, jrtc->base + JH7110_RTC_IRQ_EVENT); + if (readl_poll_timeout_atomic(jrtc->base + JH7110_RTC_IRQ_EVENT, val, + !(val & events), 0, JH7110_RTC_SYNC_TIMEOUT_US)) + dev_warn_ratelimited(&jrtc->rtc->dev, "interrupt events 0x%x not cleared\n", + events); + + if (events & JH7110_RTC_IRQ_ALARM) + rtc_update_irq(jrtc->rtc, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; +} + +static const struct rtc_class_ops jh7110_rtc_ops = { + .read_time = jh7110_rtc_read_time, + .set_time = jh7110_rtc_set_time, + .read_alarm = jh7110_rtc_read_alarm, + .set_alarm = jh7110_rtc_set_alarm, + .alarm_irq_enable = jh7110_rtc_alarm_irq_enable, + .read_offset = jh7110_rtc_read_offset, + .set_offset = jh7110_rtc_set_offset, +}; + +static int jh7110_rtc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct reset_control *rst; + struct jh7110_rtc *jrtc; + struct clk *clk; + int irq, ret; + u32 val; + + jrtc = devm_kzalloc(dev, sizeof(*jrtc), GFP_KERNEL); + if (!jrtc) + return -ENOMEM; + + jrtc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(jrtc->base)) + return PTR_ERR(jrtc->base); + + clk = devm_clk_get_enabled(dev, "apb"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable apb clock\n"); + + clk = devm_clk_get_enabled(dev, "cal"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable cal clock\n"); + + clk = devm_clk_get_enabled(dev, "32k"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable 32k clock\n"); + + /* Never asserted again, as that would stop the clock & lose the time */ + rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(rst)) + return dev_err_probe(dev, PTR_ERR(rst), "failed to get resets\n"); + + ret = reset_control_deassert(rst); + if (ret) + return dev_err_probe(dev, ret, "failed to deassert resets\n"); + + irq = platform_get_irq_byname(pdev, "rtc"); + if (irq < 0) + return irq; + + jrtc->rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(jrtc->rtc)) + return PTR_ERR(jrtc->rtc); + + platform_set_drvdata(pdev, jrtc); + + jrtc->rtc->ops = &jh7110_rtc_ops; + jrtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + jrtc->rtc->range_max = RTC_TIMESTAMP_END_2099; + + val = readl(jrtc->base + JH7110_RTC_CFG); + writel(val | JH7110_RTC_CFG_HOUR_24H | JH7110_RTC_CFG_ENABLE, + jrtc->base + JH7110_RTC_CFG); + + ret = devm_request_irq(dev, irq, jh7110_rtc_irq, 0, dev_name(dev), jrtc); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq\n"); + + ret = devm_device_init_wakeup(dev); + if (ret) + return dev_err_probe(dev, ret, "failed to init wakeup\n"); + + ret = devm_pm_set_wake_irq(dev, irq); + if (ret) + return dev_err_probe(dev, ret, "failed to set wake irq\n"); + + return devm_rtc_register_device(jrtc->rtc); +} + +static const struct of_device_id jh7110_rtc_of_match[] = { + { .compatible = "starfive,jh7110-rtc" }, + { } +}; +MODULE_DEVICE_TABLE(of, jh7110_rtc_of_match); + +static struct platform_driver jh7110_rtc_driver = { + .driver = { + .name = "jh7110-rtc", + .of_match_table = jh7110_rtc_of_match, + }, + .probe = jh7110_rtc_probe, +}; +module_platform_driver(jh7110_rtc_driver); + +MODULE_AUTHOR("Samin Guo <samin.guo@starfivetech.com>"); +MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>"); +MODULE_DESCRIPTION("StarFive JH7110 RTC driver"); +MODULE_LICENSE("GPL"); -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/3] rtc: Add StarFive JH7110 RTC driver @ 2026-11-06 17:55 ` Owen O'Hehir 0 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:55 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley From: "ziv.xu" <ziv.xu@starfivetech.com> Add a driver for the RTC in the always-on domain of the StarFive JH7110 SoC. It supports time, alarm with wakeup, and the frequency offset. Signed-off-by: ziv.xu <ziv.xu@starfivetech.com> Signed-off-by: Hal Feng <hal.feng@starfivetech.com> [Owen: rework of the StarFive vendor driver for mainline: drop hardware calibration & the default time set in probe, use the generic wake IRQ helpers, wait for the update bit in set_time, re-read a time that rolls over during the read, round the offset to the nearest step & follow the sysfs offset sign, enable the 32k counter clock] Co-developed-by: Owen O'Hehir <oo.hehir@gmail.com> Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- drivers/rtc/Kconfig | 11 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-jh7110.c | 324 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 drivers/rtc/rtc-jh7110.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 73ec9230e..332f2e022 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1807,6 +1807,17 @@ config RTC_DRV_MPC5121 This driver can also be built as a module. If so, the module will be called rtc-mpc5121. +config RTC_DRV_JH7110 + tristate "StarFive JH7110 RTC" + depends on ARCH_STARFIVE || COMPILE_TEST + help + If you say yes here you get support for the RTC in the always-on + domain of StarFive JH7110 SoCs, with alarm and frequency offset + support. + + This driver can also be built as a module. If so, the module + will be called rtc-jh7110. + config RTC_DRV_JZ4740 tristate "Ingenic JZ4740 SoC" depends on MIPS || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 46f1a0fc2..a5cddb8d8 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_RTC_DRV_IMX_BBM_SCMI) += rtc-imx-sm-bbm.o obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o +obj-$(CONFIG_RTC_DRV_JH7110) += rtc-jh7110.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_LOONGSON) += rtc-loongson.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o diff --git a/drivers/rtc/rtc-jh7110.c b/drivers/rtc/rtc-jh7110.c new file mode 100644 index 000000000..f7129b7ac --- /dev/null +++ b/drivers/rtc/rtc-jh7110.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RTC driver for the StarFive JH7110 SoC + * + * Copyright (C) 2021 StarFive Technology Co., Ltd. + */ + +#include <linux/bcd.h> +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/math64.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm_wakeirq.h> +#include <linux/reset.h> +#include <linux/rtc.h> + +#define JH7110_RTC_CFG 0x00 +#define JH7110_RTC_CFG_ENABLE BIT(0) +#define JH7110_RTC_CFG_CAL_SEL_HW BIT(2) +#define JH7110_RTC_CFG_HOUR_24H BIT(3) +#define JH7110_RTC_SW_CAL_VALUE 0x04 +#define JH7110_RTC_IRQ_EN 0x10 +#define JH7110_RTC_IRQ_EVENT 0x14 +#define JH7110_RTC_IRQ_ALARM BIT(4) +#define JH7110_RTC_IRQ_ALL GENMASK(4, 0) +#define JH7110_RTC_EVENT_UPDATE BIT(31) +#define JH7110_RTC_CAL_VALUE 0x24 +#define JH7110_RTC_CFG_TIME 0x28 +#define JH7110_RTC_CFG_DATE 0x2c +#define JH7110_RTC_ACT_TIME 0x34 +#define JH7110_RTC_ACT_DATE 0x38 +#define JH7110_RTC_TIME 0x3c +#define JH7110_RTC_DATE 0x40 + +#define JH7110_RTC_TIME_SEC GENMASK(6, 0) +#define JH7110_RTC_TIME_MIN GENMASK(13, 7) +#define JH7110_RTC_TIME_HOUR GENMASK(20, 14) +#define JH7110_RTC_DATE_DAY GENMASK(5, 0) +#define JH7110_RTC_DATE_MON GENMASK(10, 6) +#define JH7110_RTC_DATE_YEAR GENMASK(18, 11) + +#define JH7110_RTC_CAL_MASK GENMASK(15, 0) +#define JH7110_RTC_TICKS_PER_SEC 32768 + +#define JH7110_RTC_SYNC_TIMEOUT_US 1000 + +struct jh7110_rtc { + struct rtc_device *rtc; + void __iomem *base; +}; + +static void jh7110_rtc_reg2tm(struct rtc_time *tm, u32 time, u32 date) +{ + tm->tm_sec = bcd2bin(FIELD_GET(JH7110_RTC_TIME_SEC, time)); + tm->tm_min = bcd2bin(FIELD_GET(JH7110_RTC_TIME_MIN, time)); + tm->tm_hour = bcd2bin(FIELD_GET(JH7110_RTC_TIME_HOUR, time)); + tm->tm_mday = bcd2bin(FIELD_GET(JH7110_RTC_DATE_DAY, date)); + tm->tm_mon = bcd2bin(FIELD_GET(JH7110_RTC_DATE_MON, date)) - 1; + tm->tm_year = bcd2bin(FIELD_GET(JH7110_RTC_DATE_YEAR, date)) + 100; +} + +static u32 jh7110_rtc_tm2time(struct rtc_time *tm) +{ + return FIELD_PREP(JH7110_RTC_TIME_SEC, bin2bcd(tm->tm_sec)) | + FIELD_PREP(JH7110_RTC_TIME_MIN, bin2bcd(tm->tm_min)) | + FIELD_PREP(JH7110_RTC_TIME_HOUR, bin2bcd(tm->tm_hour)); +} + +static u32 jh7110_rtc_tm2date(struct rtc_time *tm) +{ + return FIELD_PREP(JH7110_RTC_DATE_DAY, bin2bcd(tm->tm_mday)) | + FIELD_PREP(JH7110_RTC_DATE_MON, bin2bcd(tm->tm_mon + 1)) | + FIELD_PREP(JH7110_RTC_DATE_YEAR, bin2bcd(tm->tm_year - 100)); +} + +static int jh7110_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 time, date; + + /* + * re-read if the time rolled over between reading TIME & DATE, since + * that rollover can also change the date. + */ + do { + time = readl(jrtc->base + JH7110_RTC_TIME); + date = readl(jrtc->base + JH7110_RTC_DATE); + } while (time != readl(jrtc->base + JH7110_RTC_TIME)); + + jh7110_rtc_reg2tm(tm, time, date); + + return 0; +} + +static int jh7110_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 val; + + writel(jh7110_rtc_tm2time(tm), jrtc->base + JH7110_RTC_CFG_TIME); + writel(jh7110_rtc_tm2date(tm), jrtc->base + JH7110_RTC_CFG_DATE); + + /* + * The counter loads CFG_TIME & CFG_DATE on this pulse; the bit appears + * to read back as 1 until the load is done. + */ + writel(JH7110_RTC_EVENT_UPDATE, jrtc->base + JH7110_RTC_IRQ_EVENT); + + return readl_poll_timeout(jrtc->base + JH7110_RTC_IRQ_EVENT, val, + !(val & JH7110_RTC_EVENT_UPDATE), 10, + JH7110_RTC_SYNC_TIMEOUT_US); +} + +static int jh7110_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 val; + + val = readl(jrtc->base + JH7110_RTC_IRQ_EN); + if (enabled) + val |= JH7110_RTC_IRQ_ALARM; + else + val &= ~JH7110_RTC_IRQ_ALARM; + writel(val, jrtc->base + JH7110_RTC_IRQ_EN); + + return 0; +} + +static int jh7110_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + + jh7110_rtc_reg2tm(&alrm->time, readl(jrtc->base + JH7110_RTC_ACT_TIME), + readl(jrtc->base + JH7110_RTC_ACT_DATE)); + alrm->enabled = !!(readl(jrtc->base + JH7110_RTC_IRQ_EN) & JH7110_RTC_IRQ_ALARM); + + return 0; +} + +static int jh7110_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + u32 val; + int ret; + + jh7110_rtc_alarm_irq_enable(dev, 0); + writel(jh7110_rtc_tm2time(&alrm->time), jrtc->base + JH7110_RTC_ACT_TIME); + writel(jh7110_rtc_tm2date(&alrm->time), jrtc->base + JH7110_RTC_ACT_DATE); + writel(JH7110_RTC_IRQ_ALARM, jrtc->base + JH7110_RTC_IRQ_EVENT); + + ret = readl_poll_timeout(jrtc->base + JH7110_RTC_IRQ_EVENT, val, + !(val & JH7110_RTC_IRQ_ALARM), 10, + JH7110_RTC_SYNC_TIMEOUT_US); + if (ret) + return ret; + + return jh7110_rtc_alarm_irq_enable(dev, alrm->enabled); +} + +/* + * 1 sec for the RTC = CAL_VALUE + 1 cycles of the 32.768 kHz clock. + * Default of 0x7fff = exactly one second. + * Each step of CAL_VALUE changes the rate by 1/32768, about 30.5 ppm. + */ +static int jh7110_rtc_read_offset(struct device *dev, long *offset) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + s64 ticks; + + ticks = (readl(jrtc->base + JH7110_RTC_CAL_VALUE) & JH7110_RTC_CAL_MASK) + 1; + *offset = DIV_S64_ROUND_CLOSEST((ticks - JH7110_RTC_TICKS_PER_SEC) * NSEC_PER_SEC, + JH7110_RTC_TICKS_PER_SEC); + + return 0; +} + +static int jh7110_rtc_set_offset(struct device *dev, long offset) +{ + struct jh7110_rtc *jrtc = dev_get_drvdata(dev); + s64 ticks; + u32 val; + + if (offset < -NSEC_PER_SEC || offset > NSEC_PER_SEC) + return -ERANGE; + + ticks = JH7110_RTC_TICKS_PER_SEC + + DIV_S64_ROUND_CLOSEST((s64)offset * JH7110_RTC_TICKS_PER_SEC, NSEC_PER_SEC); + if (ticks < 1 || ticks > JH7110_RTC_CAL_MASK + 1) + return -ERANGE; + + writel(ticks - 1, jrtc->base + JH7110_RTC_SW_CAL_VALUE); + val = readl(jrtc->base + JH7110_RTC_CFG); + writel(val & ~JH7110_RTC_CFG_CAL_SEL_HW, jrtc->base + JH7110_RTC_CFG); + + return 0; +} + +static irqreturn_t jh7110_rtc_irq(int irq, void *data) +{ + struct jh7110_rtc *jrtc = data; + u32 events, val; + + events = readl(jrtc->base + JH7110_RTC_IRQ_EVENT) & + readl(jrtc->base + JH7110_RTC_IRQ_EN) & JH7110_RTC_IRQ_ALL; + if (!events) + return IRQ_NONE; + + writel(events, jrtc->base + JH7110_RTC_IRQ_EVENT); + if (readl_poll_timeout_atomic(jrtc->base + JH7110_RTC_IRQ_EVENT, val, + !(val & events), 0, JH7110_RTC_SYNC_TIMEOUT_US)) + dev_warn_ratelimited(&jrtc->rtc->dev, "interrupt events 0x%x not cleared\n", + events); + + if (events & JH7110_RTC_IRQ_ALARM) + rtc_update_irq(jrtc->rtc, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; +} + +static const struct rtc_class_ops jh7110_rtc_ops = { + .read_time = jh7110_rtc_read_time, + .set_time = jh7110_rtc_set_time, + .read_alarm = jh7110_rtc_read_alarm, + .set_alarm = jh7110_rtc_set_alarm, + .alarm_irq_enable = jh7110_rtc_alarm_irq_enable, + .read_offset = jh7110_rtc_read_offset, + .set_offset = jh7110_rtc_set_offset, +}; + +static int jh7110_rtc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct reset_control *rst; + struct jh7110_rtc *jrtc; + struct clk *clk; + int irq, ret; + u32 val; + + jrtc = devm_kzalloc(dev, sizeof(*jrtc), GFP_KERNEL); + if (!jrtc) + return -ENOMEM; + + jrtc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(jrtc->base)) + return PTR_ERR(jrtc->base); + + clk = devm_clk_get_enabled(dev, "apb"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable apb clock\n"); + + clk = devm_clk_get_enabled(dev, "cal"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable cal clock\n"); + + clk = devm_clk_get_enabled(dev, "32k"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable 32k clock\n"); + + /* Never asserted again, as that would stop the clock & lose the time */ + rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(rst)) + return dev_err_probe(dev, PTR_ERR(rst), "failed to get resets\n"); + + ret = reset_control_deassert(rst); + if (ret) + return dev_err_probe(dev, ret, "failed to deassert resets\n"); + + irq = platform_get_irq_byname(pdev, "rtc"); + if (irq < 0) + return irq; + + jrtc->rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(jrtc->rtc)) + return PTR_ERR(jrtc->rtc); + + platform_set_drvdata(pdev, jrtc); + + jrtc->rtc->ops = &jh7110_rtc_ops; + jrtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + jrtc->rtc->range_max = RTC_TIMESTAMP_END_2099; + + val = readl(jrtc->base + JH7110_RTC_CFG); + writel(val | JH7110_RTC_CFG_HOUR_24H | JH7110_RTC_CFG_ENABLE, + jrtc->base + JH7110_RTC_CFG); + + ret = devm_request_irq(dev, irq, jh7110_rtc_irq, 0, dev_name(dev), jrtc); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq\n"); + + ret = devm_device_init_wakeup(dev); + if (ret) + return dev_err_probe(dev, ret, "failed to init wakeup\n"); + + ret = devm_pm_set_wake_irq(dev, irq); + if (ret) + return dev_err_probe(dev, ret, "failed to set wake irq\n"); + + return devm_rtc_register_device(jrtc->rtc); +} + +static const struct of_device_id jh7110_rtc_of_match[] = { + { .compatible = "starfive,jh7110-rtc" }, + { } +}; +MODULE_DEVICE_TABLE(of, jh7110_rtc_of_match); + +static struct platform_driver jh7110_rtc_driver = { + .driver = { + .name = "jh7110-rtc", + .of_match_table = jh7110_rtc_of_match, + }, + .probe = jh7110_rtc_probe, +}; +module_platform_driver(jh7110_rtc_driver); + +MODULE_AUTHOR("Samin Guo <samin.guo@starfivetech.com>"); +MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>"); +MODULE_DESCRIPTION("StarFive JH7110 RTC driver"); +MODULE_LICENSE("GPL"); -- 2.43.0 _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/3] rtc: Add StarFive JH7110 RTC driver 2026-11-06 17:55 ` Owen O'Hehir (?) @ 2026-11-06 18:02 ` sashiko-bot -1 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-11-06 18:02 UTC (permalink / raw) To: Owen O'Hehir, linux-rtc; +Cc: Alexandre Belloni > From: "ziv.xu" <ziv.xu@starfivetech.com> > > Add a driver for the RTC in the always-on domain of the StarFive JH7110 > SoC. It supports time, alarm with wakeup, and the frequency offset. > > Signed-off-by: ziv.xu <ziv.xu@starfivetech.com> > Signed-off-by: Hal Feng <hal.feng@starfivetech.com> > [Owen: rework of the StarFive vendor driver for mainline: drop hardware > calibration & the default time set in probe, use the generic wake IRQ > helpers, wait for the update bit in set_time, re-read a time that rolls > over during the read, round the offset to the nearest step & follow the > sysfs offset sign, enable the 32k counter clock] > Co-developed-by: Owen O'Hehir <oo.hehir@gmail.com> > Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> Sashiko has reviewed this patch and found no issues. -- Sashiko AI review · https://sashiko.dev/#/patchset/20261106175600.3877614-1-oo.hehir@gmail.com?part=2 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/3] rtc: Add StarFive JH7110 RTC driver 2026-11-06 17:55 ` Owen O'Hehir @ 2026-11-08 8:37 ` Uwe Kleine-König -1 siblings, 0 replies; 15+ messages in thread From: Uwe Kleine-König @ 2026-11-08 8:37 UTC (permalink / raw) To: Owen O'Hehir Cc: Alexandre Belloni, linux-rtc, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley [-- Attachment #1: Type: text/plain, Size: 469 bytes --] Hello, On Fri, Nov 06, 2026 at 05:55:59PM +0000, Owen O'Hehir wrote: > +#include <linux/mod_devicetable.h> > [...] > +#include <linux/platform_device.h> Please don't include <linux/mod_devicetable.h>. You can (and IMHO should) assume that <linux/platform_device.h> does provide struct of_device_id and just drop <linux/mod_devicetable.h>. If you insist on IWYU, please use <linux/device-id/of.h> instead to not get a bunch of unneeded dependencies. Best regards Uwe [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/3] rtc: Add StarFive JH7110 RTC driver @ 2026-11-08 8:37 ` Uwe Kleine-König 0 siblings, 0 replies; 15+ messages in thread From: Uwe Kleine-König @ 2026-11-08 8:37 UTC (permalink / raw) To: Owen O'Hehir Cc: Alexandre Belloni, linux-rtc, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley [-- Attachment #1.1: Type: text/plain, Size: 469 bytes --] Hello, On Fri, Nov 06, 2026 at 05:55:59PM +0000, Owen O'Hehir wrote: > +#include <linux/mod_devicetable.h> > [...] > +#include <linux/platform_device.h> Please don't include <linux/mod_devicetable.h>. You can (and IMHO should) assume that <linux/platform_device.h> does provide struct of_device_id and just drop <linux/mod_devicetable.h>. If you insist on IWYU, please use <linux/device-id/of.h> instead to not get a bunch of unneeded dependencies. Best regards Uwe [-- Attachment #1.2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] [-- Attachment #2: Type: text/plain, Size: 161 bytes --] _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/3] riscv: dts: starfive: jh7110: Add the RTC node 2026-11-06 17:55 ` Owen O'Hehir @ 2026-11-06 17:56 ` Owen O'Hehir -1 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:56 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley Tested on a VisionFive 2 v1.3B. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index 82ea63f71..14f92b942 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -1206,6 +1206,20 @@ pwrc: power-controller@17030000 { #power-domain-cells = <1>; }; + rtc: rtc@17040000 { + compatible = "starfive,jh7110-rtc"; + reg = <0x0 0x17040000 0x0 0x10000>; + interrupts = <10>, <11>, <12>; + interrupt-names = "ms-pulse", "sec-pulse", "rtc"; + clocks = <&aoncrg JH7110_AONCLK_RTC_APB>, + <&aoncrg JH7110_AONCLK_RTC_CAL>, + <&aoncrg JH7110_AONCLK_RTC_32K>; + clock-names = "apb", "cal", "32k"; + resets = <&aoncrg JH7110_AONRST_RTC_32K>, + <&aoncrg JH7110_AONRST_RTC_APB>, + <&aoncrg JH7110_AONRST_RTC_CAL>; + }; + csi2rx: csi@19800000 { compatible = "starfive,jh7110-csi2rx", "cdns,csi2rx"; reg = <0x0 0x19800000 0x0 0x10000>; -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/3] riscv: dts: starfive: jh7110: Add the RTC node @ 2026-11-06 17:56 ` Owen O'Hehir 0 siblings, 0 replies; 15+ messages in thread From: Owen O'Hehir @ 2026-11-06 17:56 UTC (permalink / raw) To: Alexandre Belloni, linux-rtc Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Emil Renner Berthing, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Philipp Zabel, devicetree, linux-kernel, linux-riscv, Hal Feng, ziv.xu, Conor Dooley Tested on a VisionFive 2 v1.3B. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index 82ea63f71..14f92b942 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -1206,6 +1206,20 @@ pwrc: power-controller@17030000 { #power-domain-cells = <1>; }; + rtc: rtc@17040000 { + compatible = "starfive,jh7110-rtc"; + reg = <0x0 0x17040000 0x0 0x10000>; + interrupts = <10>, <11>, <12>; + interrupt-names = "ms-pulse", "sec-pulse", "rtc"; + clocks = <&aoncrg JH7110_AONCLK_RTC_APB>, + <&aoncrg JH7110_AONCLK_RTC_CAL>, + <&aoncrg JH7110_AONCLK_RTC_32K>; + clock-names = "apb", "cal", "32k"; + resets = <&aoncrg JH7110_AONRST_RTC_32K>, + <&aoncrg JH7110_AONRST_RTC_APB>, + <&aoncrg JH7110_AONRST_RTC_CAL>; + }; + csi2rx: csi@19800000 { compatible = "starfive,jh7110-csi2rx", "cdns,csi2rx"; reg = <0x0 0x19800000 0x0 0x10000>; -- 2.43.0 _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 3/3] riscv: dts: starfive: jh7110: Add the RTC node 2026-11-06 17:56 ` Owen O'Hehir (?) @ 2026-11-06 17:59 ` sashiko-bot -1 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-11-06 17:59 UTC (permalink / raw) To: Owen O'Hehir, linux-rtc; +Cc: Alexandre Belloni > Tested on a VisionFive 2 v1.3B. > > Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> Sashiko has reviewed this patch and found no issues. -- Sashiko AI review · https://sashiko.dev/#/patchset/20261106175600.3877614-1-oo.hehir@gmail.com?part=3 ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-11-08 8:37 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-06 17:55 [PATCH 0/3] rtc: Add StarFive JH7110 RTC support Owen O'Hehir 2026-11-06 17:55 ` Owen O'Hehir 2026-11-06 17:55 ` [PATCH 1/3] dt-bindings: rtc: Add StarFive JH7110 RTC Owen O'Hehir 2026-11-06 17:55 ` Owen O'Hehir 2026-11-06 17:59 ` sashiko-bot 2026-11-06 18:16 ` Conor Dooley 2026-11-06 18:16 ` Conor Dooley 2026-11-06 17:55 ` [PATCH 2/3] rtc: Add StarFive JH7110 RTC driver Owen O'Hehir 2026-11-06 17:55 ` Owen O'Hehir 2026-11-06 18:02 ` sashiko-bot 2026-11-08 8:37 ` Uwe Kleine-König 2026-11-08 8:37 ` Uwe Kleine-König 2026-11-06 17:56 ` [PATCH 3/3] riscv: dts: starfive: jh7110: Add the RTC node Owen O'Hehir 2026-11-06 17:56 ` Owen O'Hehir 2026-11-06 17:59 ` sashiko-bot
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.