diff mbox series

[v2] Allow for riscv-clock to pick up mmio address.

Message ID 20250409143816.15802-1-aleksa.paunovic@htecgroup.com (mailing list archive)
State New
Headers show
Series [v2] Allow for riscv-clock to pick up mmio address. | expand

Checks

Context Check Description
bjorn/pre-ci_am fail Failed to apply series

Commit Message

Aleksa Paunovic April 9, 2025, 2:38 p.m. UTC
From: Dragan Mladjenovic <Dragan.Mladjenovic@syrmia.com>

Allows faster rdtime access via GCR.U mtime shadow register on p8700.

Signed-off-by: Aleksa Paunovic <aleksa.paunovic@htecgroup.com>
---
 arch/riscv/Kconfig                | 10 ++++++
 arch/riscv/include/asm/timex.h    | 59 ++++++++++++++++++++-----------
 drivers/clocksource/timer-riscv.c | 30 ++++++++++++++++
 3 files changed, 79 insertions(+), 20 deletions(-)

Comments

Conor Dooley April 10, 2025, 10:21 a.m. UTC | #1
On Wed, Apr 09, 2025 at 02:38:55PM +0000, Aleksa Paunovic wrote:
> From: Dragan Mladjenovic <Dragan.Mladjenovic@syrmia.com>
> 
> Allows faster rdtime access via GCR.U mtime shadow register on p8700.
> 
> Signed-off-by: Aleksa Paunovic <aleksa.paunovic@htecgroup.com>

> +#if defined(CONFIG_RISCV_TIME_MMIO)
> +	gcru = of_find_compatible_node(NULL, NULL, "mti,p8700-gcru");

Firstly, this is an undocumented compatible, so you'll need to create a
binding for it before you can use it. Not much to say on the use of the
compatible in the driver without more information on what the device
looks like.

Secondly, the option you have added is generically named and described,
yet only functions on this p8700 platform. At a minimum, it needs to
explain the platforms where it is relevant, and probably also should
depend on the kconfig option that enables building a dt etc for the
p8700 platform in the first place.

Cheers,
Conor.

> +	if (gcru) {
> +		if (!of_property_read_u64_index(gcru, "reg", 0, &mmio_addr)) {
> +			riscv_time_val = ioremap((long)mmio_addr, 8);
> +			if (riscv_time_val) {
> +				pr_info("Using mmio time register at 0x%llx\n",
> +					mmio_addr);
> +				static_branch_enable(
> +					&riscv_time_mmio_available);
> +			} else {
> +				pr_warn("Unable to use mmio time at 0x%llx\n",
> +					mmio_addr);
> +			}
> +			of_node_put(gcru);
> +		}
> +	}
> +#endif
diff mbox series

Patch

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6b296ebc8c61..3414d419a7cb 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -728,6 +728,16 @@  config RISCV_ISA_ZALRSC_ONLY
 
 	   If you don't know what to do here, say n.
 
+config RISCV_TIME_MMIO
+	bool "Time mmio support"
+	depends on !RISCV_M_MODE
+	default n
+	help
+	   Access time mmio instead of rdtime.
+	   Some CPUs trap on rdtime or reading the time CSR register.
+
+	   If you don't know what to do here, say n.
+
 config TOOLCHAIN_HAS_ZBB
 	bool
 	default y
diff --git a/arch/riscv/include/asm/timex.h b/arch/riscv/include/asm/timex.h
index a06697846e69..b1956c737513 100644
--- a/arch/riscv/include/asm/timex.h
+++ b/arch/riscv/include/asm/timex.h
@@ -7,31 +7,24 @@ 
 #define _ASM_RISCV_TIMEX_H
 
 #include <asm/csr.h>
+#include <asm/mmio.h>
+
+#include <linux/jump_label.h>
 
 typedef unsigned long cycles_t;
 
+extern u64 __iomem *riscv_time_val;
+DECLARE_STATIC_KEY_FALSE(riscv_time_mmio_available);
+
+#define riscv_time_val riscv_time_val
+
 #ifdef CONFIG_RISCV_M_MODE
 
 #include <asm/clint.h>
 
-#ifdef CONFIG_64BIT
-static inline cycles_t get_cycles(void)
-{
-	return readq_relaxed(clint_time_val);
-}
-#else /* !CONFIG_64BIT */
-static inline u32 get_cycles(void)
-{
-	return readl_relaxed(((u32 *)clint_time_val));
-}
-#define get_cycles get_cycles
+#undef riscv_time_val
 
-static inline u32 get_cycles_hi(void)
-{
-	return readl_relaxed(((u32 *)clint_time_val) + 1);
-}
-#define get_cycles_hi get_cycles_hi
-#endif /* CONFIG_64BIT */
+#define riscv_time_val clint_time_val
 
 /*
  * Much like MIPS, we may not have a viable counter to use at an early point
@@ -46,22 +39,48 @@  static inline unsigned long random_get_entropy(void)
 }
 #define random_get_entropy()	random_get_entropy()
 
-#else /* CONFIG_RISCV_M_MODE */
+#endif
+
+static inline long use_riscv_time_mmio(void)
+{
+	return IS_ENABLED(CONFIG_RISCV_M_MODE) ||
+		(IS_ENABLED(CONFIG_RISCV_TIME_MMIO) &&
+		 static_branch_unlikely(&riscv_time_mmio_available));
+}
+
+#ifdef CONFIG_64BIT
+static inline cycles_t mmio_get_cycles(void)
+{
+	return readq_relaxed(riscv_time_val);
+}
+#else /* !CONFIG_64BIT */
+static inline cycles_t mmio_get_cycles(void)
+{
+	return readl_relaxed(((u32 *)riscv_time_val));
+}
+#endif /* CONFIG_64BIT */
+
+static inline u32 mmio_get_cycles_hi(void)
+{
+	return readl_relaxed(((u32 *)riscv_time_val) + 1);
+}
 
 static inline cycles_t get_cycles(void)
 {
+	if (use_riscv_time_mmio())
+		return mmio_get_cycles();
 	return csr_read(CSR_TIME);
 }
 #define get_cycles get_cycles
 
 static inline u32 get_cycles_hi(void)
 {
+	if (use_riscv_time_mmio())
+		return mmio_get_cycles_hi();
 	return csr_read(CSR_TIMEH);
 }
 #define get_cycles_hi get_cycles_hi
 
-#endif /* !CONFIG_RISCV_M_MODE */
-
 #ifdef CONFIG_64BIT
 static inline u64 get_cycles64(void)
 {
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index 48ce50c5f5e6..175fb82acb41 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -32,6 +32,13 @@ 
 static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available);
 static bool riscv_timer_cannot_wake_cpu;
 
+#if defined(CONFIG_RISCV_TIME_MMIO)
+DEFINE_STATIC_KEY_FALSE_RO(riscv_time_mmio_available);
+EXPORT_SYMBOL(riscv_time_mmio_available);
+u64 __iomem *riscv_time_val __ro_after_init;
+EXPORT_SYMBOL(riscv_time_val);
+#endif
+
 static void riscv_clock_event_stop(void)
 {
 	if (static_branch_likely(&riscv_sstc_available)) {
@@ -203,6 +210,10 @@  static int __init riscv_timer_init_dt(struct device_node *n)
 	int cpuid, error;
 	unsigned long hartid;
 	struct device_node *child;
+#if defined(CONFIG_RISCV_TIME_MMIO)
+	u64 mmio_addr;
+	struct device_node *gcru;
+#endif
 
 	error = riscv_of_processor_hartid(n, &hartid);
 	if (error < 0) {
@@ -220,6 +231,25 @@  static int __init riscv_timer_init_dt(struct device_node *n)
 	if (cpuid != smp_processor_id())
 		return 0;
 
+#if defined(CONFIG_RISCV_TIME_MMIO)
+	gcru = of_find_compatible_node(NULL, NULL, "mti,p8700-gcru");
+	if (gcru) {
+		if (!of_property_read_u64_index(gcru, "reg", 0, &mmio_addr)) {
+			riscv_time_val = ioremap((long)mmio_addr, 8);
+			if (riscv_time_val) {
+				pr_info("Using mmio time register at 0x%llx\n",
+					mmio_addr);
+				static_branch_enable(
+					&riscv_time_mmio_available);
+			} else {
+				pr_warn("Unable to use mmio time at 0x%llx\n",
+					mmio_addr);
+			}
+			of_node_put(gcru);
+		}
+	}
+#endif
+
 	child = of_find_compatible_node(NULL, NULL, "riscv,timer");
 	if (child) {
 		riscv_timer_cannot_wake_cpu = of_property_read_bool(child,