[RFC] riscv: (visionfive2:) device tree binding for riscv_timer

Torsten Duwe duwe at lst.de
Fri Jul 7 15:53:33 CEST 2023


Hi,

following the existing device tree binding[1], here is a draft to use it
in drivers/timer/riscv_timer.c. This would also fix the regression we see
with commit 55171aedda8 ("dm: Emit the arch_cpu_init_dm() even only
before relocation"), at least on the VisionFive2, as sketched out below.
The device tree addition suits the Linux kernel dirver

| riscv-timer: riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [3]

The of_match, along with the "timebase-frequency" property, provides
a working timer (again) on the VF2.

If this is the way to go, I'll turn this into a nicer patch series.
Comments welcome!

	Torsten

[1] linux/Documentation/devicetree/bindings/timer/riscv,timer.yaml
---
 arch/riscv/dts/jh7110.dtsi             |   10 ++++++++++
 configs/starfive_visionfive2_defconfig |    1 -
 drivers/timer/riscv_timer.c            |   21 ++++++++++++++++++---
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
index 3627ed79b8..03dda12f73 100644
--- a/drivers/timer/riscv_timer.c
+++ b/drivers/timer/riscv_timer.c
@@ -13,6 +13,7 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
+#include <fdt_support.h>
 #include <timer.h>
 #include <asm/csr.h>
 
@@ -53,9 +54,18 @@ u64 notrace timer_early_get_count(void)
 static int riscv_timer_probe(struct udevice *dev)
 {
 	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-
 	/* clock frequency was passed from the cpu driver as driver data */
-	uc_priv->clock_rate = dev->driver_data;
+	u32 rate = dev->driver_data;
+
+	if (!rate && gd->fdt_blob) {		/* not called from CPU driver? */
+		rate = fdt_getprop_u32_default(gd->fdt_blob,
+					       "/cpus", "timebase-frequency", 0);
+	}
+	uc_priv->clock_rate = rate;
+
+	/* timer uclass post_probe will later fail with -EINVAL. Hint at the cause! */
+	if (!rate)
+		log_err("riscv_timer_probe with clock rate 0\n");
 
 	return 0;
 }
@@ -64,10 +74,15 @@ static const struct timer_ops riscv_timer_ops = {
 	.get_count = riscv_timer_get_count,
 };
 
+static const struct udevice_id riscv_timer_ids[] = {
+        { .compatible = "riscv,timer", },
+        { }
+};
+
 U_BOOT_DRIVER(riscv_timer) = {
 	.name = "riscv_timer",
 	.id = UCLASS_TIMER,
+	.of_match = of_match_ptr(riscv_timer_ids),
 	.probe = riscv_timer_probe,
 	.ops = &riscv_timer_ops,
-	.flags = DM_FLAG_PRE_RELOC,
 };
diff --git a/arch/riscv/dts/jh7110.dtsi b/arch/riscv/dts/jh7110.dtsi
index c61730e8d1..9944f261b3 100644
--- a/arch/riscv/dts/jh7110.dtsi
+++ b/arch/riscv/dts/jh7110.dtsi
@@ -6,6 +6,7 @@
 /dts-v1/;
 #include <dt-bindings/clock/starfive,jh7110-crg.h>
 #include <dt-bindings/reset/starfive,jh7110-crg.h>
+#include <dt-bindings/interrupt-controller/riscv-hart.h>
 
 / {
 	compatible = "starfive,jh7110";
@@ -204,6 +205,15 @@
 			};
 	};
 
+	timer {
+		compatible = "riscv,timer";
+		interrupts-extended = <&cpu0_intc HART_INT_S_TIMER>,
+				      <&cpu1_intc HART_INT_S_TIMER>,
+				      <&cpu2_intc HART_INT_S_TIMER>,
+				      <&cpu3_intc HART_INT_S_TIMER>,
+				      <&cpu4_intc HART_INT_S_TIMER>;
+	};
+
 	osc: oscillator {
 		compatible = "fixed-clock";
 		clock-output-names = "osc";
diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig
index 570a1f53a1..3a213b2601 100644
--- a/configs/starfive_visionfive2_defconfig
+++ b/configs/starfive_visionfive2_defconfig
@@ -102,4 +102,3 @@ CONFIG_PINCTRL_STARFIVE=y
 # CONFIG_RAM_SIFIVE is not set
 CONFIG_SYS_NS16550=y
 CONFIG_CADENCE_QSPI=y
-CONFIG_TIMER_EARLY=y


More information about the U-Boot mailing list