* [PATCH v3 0/4] rtc: Add StarFive JH7110 RTC support @ 2026-11-09 15:44 ` Owen O'Hehir 0 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 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, Uwe Kleine-König, E Shattow The JH7110 has an RTC in its always-on domain that mainline does not support. This series adds a binding, a driver, a MAINTAINERS entry 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. Changes in v3: - dt-bindings: add Conor's Acked-by - driver: add my copyright line; drop the extra space before the register bit field defines (as requested by E Shattow) - dts: rename the node label from rtc to soc_rtc, leaving rtc free for a carrier board's RTC (as requested by E Shattow) Changes in v2: - dt-bindings: list myself as maintainer instead of the RTC subsystem maintainer (as requested by Conor) - MAINTAINERS: new patch adding an entry for the driver & binding - driver: drop the <linux/mod_devicetable.h> include (as requested by Uwe) v1: https://lore.kernel.org/r/20261106175600.3877614-0-oo.hehir@gmail.com v2: https://lore.kernel.org/r/20261108212826.15890-1-oo.hehir@gmail.com Owen O'Hehir (3): dt-bindings: rtc: Add StarFive JH7110 RTC MAINTAINERS: Add entry for the StarFive JH7110 RTC driver riscv: dts: starfive: jh7110: Add the RTC node ziv.xu (1): rtc: Add StarFive JH7110 RTC driver .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++ MAINTAINERS | 7 + arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 + drivers/rtc/Kconfig | 11 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-jh7110.c | 324 ++++++++++++++++++ 6 files changed, 442 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] 13+ messages in thread
* [PATCH v3 0/4] rtc: Add StarFive JH7110 RTC support @ 2026-11-09 15:44 ` Owen O'Hehir 0 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 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, Uwe Kleine-König, E Shattow The JH7110 has an RTC in its always-on domain that mainline does not support. This series adds a binding, a driver, a MAINTAINERS entry 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. Changes in v3: - dt-bindings: add Conor's Acked-by - driver: add my copyright line; drop the extra space before the register bit field defines (as requested by E Shattow) - dts: rename the node label from rtc to soc_rtc, leaving rtc free for a carrier board's RTC (as requested by E Shattow) Changes in v2: - dt-bindings: list myself as maintainer instead of the RTC subsystem maintainer (as requested by Conor) - MAINTAINERS: new patch adding an entry for the driver & binding - driver: drop the <linux/mod_devicetable.h> include (as requested by Uwe) v1: https://lore.kernel.org/r/20261106175600.3877614-0-oo.hehir@gmail.com v2: https://lore.kernel.org/r/20261108212826.15890-1-oo.hehir@gmail.com Owen O'Hehir (3): dt-bindings: rtc: Add StarFive JH7110 RTC MAINTAINERS: Add entry for the StarFive JH7110 RTC driver riscv: dts: starfive: jh7110: Add the RTC node ziv.xu (1): rtc: Add StarFive JH7110 RTC driver .../bindings/rtc/starfive,jh7110-rtc.yaml | 85 +++++ MAINTAINERS | 7 + arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 + drivers/rtc/Kconfig | 11 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-jh7110.c | 324 ++++++++++++++++++ 6 files changed, 442 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] 13+ messages in thread
* [PATCH v3 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC 2026-11-09 15:44 ` Owen O'Hehir @ 2026-11-09 15:44 ` Owen O'Hehir -1 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 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, Uwe Kleine-König, E Shattow Describe the RTC in the always-on domain of the StarFive JH7110 SoC. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> Acked-by: Conor Dooley <conor.dooley@microchip.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..a88ab91ab --- /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: + - Owen O'Hehir <oo.hehir@gmail.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] 13+ messages in thread
* [PATCH v3 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC @ 2026-11-09 15:44 ` Owen O'Hehir 0 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 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, Uwe Kleine-König, E Shattow Describe the RTC in the always-on domain of the StarFive JH7110 SoC. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> Acked-by: Conor Dooley <conor.dooley@microchip.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..a88ab91ab --- /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: + - Owen O'Hehir <oo.hehir@gmail.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] 13+ messages in thread
* Re: [PATCH v3 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC 2026-11-09 15:44 ` Owen O'Hehir (?) @ 2026-11-09 15:47 ` sashiko-bot -1 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-11-09 15:47 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/20261109154501.63762-1-oo.hehir@gmail.com?part=1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 2/4] rtc: Add StarFive JH7110 RTC driver 2026-11-09 15:44 ` Owen O'Hehir @ 2026-11-09 15:44 ` Owen O'Hehir -1 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 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, Uwe Kleine-König, E Shattow 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..2dc9f64b1 --- /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. + * Copyright (C) 2026 Owen O'Hehir <oo.hehir@gmail.com> + */ + +#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/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] 13+ messages in thread
* [PATCH v3 2/4] rtc: Add StarFive JH7110 RTC driver @ 2026-11-09 15:44 ` Owen O'Hehir 0 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 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, Uwe Kleine-König, E Shattow 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..2dc9f64b1 --- /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. + * Copyright (C) 2026 Owen O'Hehir <oo.hehir@gmail.com> + */ + +#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/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] 13+ messages in thread
* Re: [PATCH v3 2/4] rtc: Add StarFive JH7110 RTC driver 2026-11-09 15:44 ` Owen O'Hehir (?) @ 2026-11-09 15:51 ` sashiko-bot -1 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-11-09 15:51 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/20261109154501.63762-1-oo.hehir@gmail.com?part=2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 3/4] MAINTAINERS: Add entry for the StarFive JH7110 RTC driver 2026-11-09 15:44 ` Owen O'Hehir @ 2026-11-09 15:45 ` Owen O'Hehir -1 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:45 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, Uwe Kleine-König, E Shattow Add myself as maintainer of the StarFive JH7110 RTC driver and its binding. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index aa647f5d3..2ee86a46c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -26877,6 +26877,13 @@ S: Supported F: Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml F: sound/soc/starfive/jh7110_pwmdac.c +STARFIVE JH7110 RTC DRIVER +M: Owen O'Hehir <oo.hehir@gmail.com> +L: linux-rtc@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml +F: drivers/rtc/rtc-jh7110.c + STARFIVE JH7110 SYSCON M: William Qiu <william.qiu@starfivetech.com> M: Xingyu Wu <xingyu.wu@starfivetech.com> -- 2.43.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 3/4] MAINTAINERS: Add entry for the StarFive JH7110 RTC driver @ 2026-11-09 15:45 ` Owen O'Hehir 0 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:45 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, Uwe Kleine-König, E Shattow Add myself as maintainer of the StarFive JH7110 RTC driver and its binding. Signed-off-by: Owen O'Hehir <oo.hehir@gmail.com> --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index aa647f5d3..2ee86a46c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -26877,6 +26877,13 @@ S: Supported F: Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml F: sound/soc/starfive/jh7110_pwmdac.c +STARFIVE JH7110 RTC DRIVER +M: Owen O'Hehir <oo.hehir@gmail.com> +L: linux-rtc@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/rtc/starfive,jh7110-rtc.yaml +F: drivers/rtc/rtc-jh7110.c + STARFIVE JH7110 SYSCON M: William Qiu <william.qiu@starfivetech.com> M: Xingyu Wu <xingyu.wu@starfivetech.com> -- 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] 13+ messages in thread
* [PATCH v3 4/4] riscv: dts: starfive: jh7110: Add the RTC node 2026-11-09 15:44 ` Owen O'Hehir @ 2026-11-09 15:45 ` Owen O'Hehir -1 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:45 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, Uwe Kleine-König, E Shattow 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..817898eab 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>; }; + soc_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] 13+ messages in thread
* [PATCH v3 4/4] riscv: dts: starfive: jh7110: Add the RTC node @ 2026-11-09 15:45 ` Owen O'Hehir 0 siblings, 0 replies; 13+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:45 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, Uwe Kleine-König, E Shattow 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..817898eab 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>; }; + soc_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] 13+ messages in thread
* Re: [PATCH v3 4/4] riscv: dts: starfive: jh7110: Add the RTC node 2026-11-09 15:45 ` Owen O'Hehir (?) @ 2026-11-09 15:48 ` sashiko-bot -1 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-11-09 15:48 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/20261109154501.63762-1-oo.hehir@gmail.com?part=4 ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-11-09 15:51 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-09 15:44 [PATCH v3 0/4] rtc: Add StarFive JH7110 RTC support Owen O'Hehir 2026-11-09 15:44 ` Owen O'Hehir 2026-11-09 15:44 ` [PATCH v3 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC Owen O'Hehir 2026-11-09 15:44 ` Owen O'Hehir 2026-11-09 15:47 ` sashiko-bot 2026-11-09 15:44 ` [PATCH v3 2/4] rtc: Add StarFive JH7110 RTC driver Owen O'Hehir 2026-11-09 15:44 ` Owen O'Hehir 2026-11-09 15:51 ` sashiko-bot 2026-11-09 15:45 ` [PATCH v3 3/4] MAINTAINERS: Add entry for the " Owen O'Hehir 2026-11-09 15:45 ` Owen O'Hehir 2026-11-09 15:45 ` [PATCH v3 4/4] riscv: dts: starfive: jh7110: Add the RTC node Owen O'Hehir 2026-11-09 15:45 ` Owen O'Hehir 2026-11-09 15:48 ` 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.