* [PATCH v2 0/4] rtc: Add StarFive JH7110 RTC support
@ 2026-11-08 21:28 Owen O'Hehir
2026-11-08 21:28 ` [PATCH v2 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC Owen O'Hehir
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Owen O'Hehir @ 2026-11-08 21:28 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
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 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
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 | 323 ++++++++++++++++++
6 files changed, 441 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] 11+ messages in thread* [PATCH v2 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC 2026-11-08 21:28 [PATCH v2 0/4] rtc: Add StarFive JH7110 RTC support Owen O'Hehir @ 2026-11-08 21:28 ` Owen O'Hehir 2026-11-08 22:56 ` Conor Dooley 2026-11-08 21:28 ` [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver Owen O'Hehir ` (2 subsequent siblings) 3 siblings, 1 reply; 11+ messages in thread From: Owen O'Hehir @ 2026-11-08 21:28 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 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..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 [flat|nested] 11+ messages in thread
* Re: [PATCH v2 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC 2026-11-08 21:28 ` [PATCH v2 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC Owen O'Hehir @ 2026-11-08 22:56 ` Conor Dooley 0 siblings, 0 replies; 11+ messages in thread From: Conor Dooley @ 2026-11-08 22:56 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, Uwe Kleine-König [-- Attachment #1: Type: text/plain, Size: 75 bytes --] Acked-by: Conor Dooley <conor.dooley@microchip.com> pw-bot: not-applicable [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver 2026-11-08 21:28 [PATCH v2 0/4] rtc: Add StarFive JH7110 RTC support Owen O'Hehir 2026-11-08 21:28 ` [PATCH v2 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC Owen O'Hehir @ 2026-11-08 21:28 ` Owen O'Hehir 2026-11-09 3:12 ` E Shattow 2026-11-08 21:28 ` [PATCH v2 3/4] MAINTAINERS: Add entry for the " Owen O'Hehir 2026-11-08 21:28 ` [PATCH v2 4/4] riscv: dts: starfive: jh7110: Add the RTC node Owen O'Hehir 3 siblings, 1 reply; 11+ messages in thread From: Owen O'Hehir @ 2026-11-08 21:28 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 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 | 323 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 335 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..d2d89cdd4 --- /dev/null +++ b/drivers/rtc/rtc-jh7110.c @@ -0,0 +1,323 @@ +// 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/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 [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver 2026-11-08 21:28 ` [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver Owen O'Hehir @ 2026-11-09 3:12 ` E Shattow 2026-11-09 15:44 ` Owen O'Hehir 2026-11-09 16:29 ` Alexandre Belloni 0 siblings, 2 replies; 11+ messages in thread From: E Shattow @ 2026-11-09 3:12 UTC (permalink / raw) To: Owen O'Hehir, 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 Hi Owen, On 11/8/26 13:28, Owen O'Hehir wrote: > 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 | 323 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 335 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..d2d89cdd4 > --- /dev/null > +++ b/drivers/rtc/rtc-jh7110.c > @@ -0,0 +1,323 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * RTC driver for the StarFive JH7110 SoC > + * > + * Copyright (C) 2021 StarFive Technology Co., Ltd. > + */ Is this copyrighted work from previous year 2021 being imported without modification? If there is modification then I would assume it needs appended your authorship and the current year 2026. > + > +#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 > + Align 8-char tab stops per Linux coding style, and then tidy up the extra junk clearspace on some of the defines > +#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); I note that JH7100 does not mention RTC in its datasheet. Does JH7110 RTC have any commonality with JHB100 and if so then would rtc-starfive be a more suitable name for the code filename and module? > + > +MODULE_AUTHOR("Samin Guo <samin.guo@starfivetech.com>"); > +MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>"); Review use of authorship macros as appropriate. This may be okay as-is. > +MODULE_DESCRIPTION("StarFive JH7110 RTC driver"); > +MODULE_LICENSE("GPL"); -E ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver 2026-11-09 3:12 ` E Shattow @ 2026-11-09 15:44 ` Owen O'Hehir 2026-11-09 16:29 ` Alexandre Belloni 1 sibling, 0 replies; 11+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 UTC (permalink / raw) To: E Shattow 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, Uwe Kleine-König Hi E, Thanks for the review. > Is this copyrighted work from previous year 2021 being imported without > modification? > > If there is modification then I would assume it needs appended your > authorship and the current year 2026. It is modified, so v3 adds my copyright line below StarFive's. > Align 8-char tab stops per Linux coding style, and then tidy up the > extra junk clearspace on some of the defines The values line up in the file; in the patch the leading '+' pushes a few of them (TIME, DATE, CFG_HOUR_24H, SW_CAL_VALUE, EVENT_UPDATE) one tab out. The extra space before some names marks them as bit fields of the register above; as it reads as noise, v3 drops it. > I note that JH7100 does not mention RTC in its datasheet. Does JH7110 > RTC have any commonality with JHB100 and if so then would rtc-starfive > be a more suitable name for the code filename and module? The JHB100 clock and reset bindings do name an RTC clock and reset, under its Peripheral-2 clock and reset generator alongside CAN and GMAC, whose inputs include no 32 kHz clock; the JH7110 RTC is in the always-on domain. I searched for JHB100 documentation but found nothing on its RTC beyond those names, so I cannot say whether the block is the same. I would keep the jh7110 name, after the first SoC supported; if the JHB100 turns out to use the same block, it can reuse the driver with its own compatible. That is what the pending JHB100 TRNG series does with jh7110-trng.c. I would appreciate advice from Hal or anyone who knows whether the JHB100 RTC is the same IP. > Review use of authorship macros as appropriate. This may be okay as-is. The driver is derived from the StarFive one, so I kept its authors and will leave these as they are. Owen ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver 2026-11-09 3:12 ` E Shattow 2026-11-09 15:44 ` Owen O'Hehir @ 2026-11-09 16:29 ` Alexandre Belloni 1 sibling, 0 replies; 11+ messages in thread From: Alexandre Belloni @ 2026-11-09 16:29 UTC (permalink / raw) To: E Shattow Cc: Owen O'Hehir, 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, Uwe Kleine-König On 08/11/2026 19:12:58-0800, E Shattow wrote: > > +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); > > I note that JH7100 does not mention RTC in its datasheet. Does JH7110 > RTC have any commonality with JHB100 and if so then would rtc-starfive > be a more suitable name for the code filename and module? > The filename has to be soc specific, else we will end up with rtc-starfive.c, rtc-starfive2.c, etc... when the vendor choose to change the IP. -- Alexandre Belloni, co-owner and COO, Bootlin Embedded Linux and Kernel engineering https://bootlin.com ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 3/4] MAINTAINERS: Add entry for the StarFive JH7110 RTC driver 2026-11-08 21:28 [PATCH v2 0/4] rtc: Add StarFive JH7110 RTC support Owen O'Hehir 2026-11-08 21:28 ` [PATCH v2 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC Owen O'Hehir 2026-11-08 21:28 ` [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver Owen O'Hehir @ 2026-11-08 21:28 ` Owen O'Hehir 2026-11-08 21:28 ` [PATCH v2 4/4] riscv: dts: starfive: jh7110: Add the RTC node Owen O'Hehir 3 siblings, 0 replies; 11+ messages in thread From: Owen O'Hehir @ 2026-11-08 21:28 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 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 [flat|nested] 11+ messages in thread
* [PATCH v2 4/4] riscv: dts: starfive: jh7110: Add the RTC node 2026-11-08 21:28 [PATCH v2 0/4] rtc: Add StarFive JH7110 RTC support Owen O'Hehir ` (2 preceding siblings ...) 2026-11-08 21:28 ` [PATCH v2 3/4] MAINTAINERS: Add entry for the " Owen O'Hehir @ 2026-11-08 21:28 ` Owen O'Hehir 2026-11-09 3:37 ` E Shattow 3 siblings, 1 reply; 11+ messages in thread From: Owen O'Hehir @ 2026-11-08 21:28 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 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 [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/4] riscv: dts: starfive: jh7110: Add the RTC node 2026-11-08 21:28 ` [PATCH v2 4/4] riscv: dts: starfive: jh7110: Add the RTC node Owen O'Hehir @ 2026-11-09 3:37 ` E Shattow 2026-11-09 15:44 ` Owen O'Hehir 0 siblings, 1 reply; 11+ messages in thread From: E Shattow @ 2026-11-09 3:37 UTC (permalink / raw) To: Owen O'Hehir, 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 Hi Owen, On 11/8/26 13:28, Owen O'Hehir wrote: > 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>; Is status property applicable to SoC rtc? If not, then is 'rtc' label appropriate when there's no status applicable? Note that Mars CM / CM-Lite System-on-Modules may be used commonly with board carriers which implement a battery-backed RTC on the I2C bus, and so another 'rtc' label may be applicable, something to consider. The initial Mars CM / CM-Lite dts ignores this because there is an inconvenient I2C bus device address conflict of the SoM EEPROM and some carrier boards' RTC, and the SoC RTC driver was not then present; problems for a future self. -E ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/4] riscv: dts: starfive: jh7110: Add the RTC node 2026-11-09 3:37 ` E Shattow @ 2026-11-09 15:44 ` Owen O'Hehir 0 siblings, 0 replies; 11+ messages in thread From: Owen O'Hehir @ 2026-11-09 15:44 UTC (permalink / raw) To: E Shattow 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, Uwe Kleine-König Hi E, > Is status property applicable to SoC rtc? If not, then is 'rtc' label > appropriate when there's no status applicable? The RTC is in the SoC always-on domain and its clocks come from aoncrg; the 32 kHz oscillator is set in jh7110-common.dtsi, which every JH7110 board includes, so no board needs to enable it. It is left enabled in the dtsi like the other always-on nodes (aoncrg, aongpio, pwrc). Other SoC RTCs do the same, e.g. Allwinner (including the D1), Sophgo CV180x and i.MX snvs_rtc; the ones disabled by default, such as STM32, depend on board parts that not every board has. An alias is only needed when a board has more than one RTC, and none of the JH7110 boards in the tree do. A board can still disable the node or alias it through the label. > Note that Mars CM / CM-Lite System-on-Modules may be used commonly with > board carriers which implement a battery-backed RTC on the I2C bus, and > so another 'rtc' label may be applicable, something to consider. Good point. v3 renames the label to soc_rtc, leaving rtc free for a carrier board's RTC. Owen ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-11-09 16:29 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-11-08 21:28 [PATCH v2 0/4] rtc: Add StarFive JH7110 RTC support Owen O'Hehir 2026-11-08 21:28 ` [PATCH v2 1/4] dt-bindings: rtc: Add StarFive JH7110 RTC Owen O'Hehir 2026-11-08 22:56 ` Conor Dooley 2026-11-08 21:28 ` [PATCH v2 2/4] rtc: Add StarFive JH7110 RTC driver Owen O'Hehir 2026-11-09 3:12 ` E Shattow 2026-11-09 15:44 ` Owen O'Hehir 2026-11-09 16:29 ` Alexandre Belloni 2026-11-08 21:28 ` [PATCH v2 3/4] MAINTAINERS: Add entry for the " Owen O'Hehir 2026-11-08 21:28 ` [PATCH v2 4/4] riscv: dts: starfive: jh7110: Add the RTC node Owen O'Hehir 2026-11-09 3:37 ` E Shattow 2026-11-09 15:44 ` Owen O'Hehir
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®