The generic RISC-V timer driver currently defines
timer_early_get_count() only when CONFIG_IS_ENABLED(RISCV_SMODE),
even though reading the TIME CSR is not inherently limited
to S‑mode; it works in M‑mode as well when the CSR is implemented
in hardware (e.g., with the Zicntr extension).

Moreover, timer_early_get_rate() is missing entirely for M‑mode,
causing early timer functions to be unavailable on such systems.

Fix this by:
- Moving timer_early_get_count() out of the RISCV_SMODE guard
  so it is always available when CONFIG_TIMER_EARLY is set.
- Adding M‑mode support to timer_early_get_rate(), returning
  RISCV_MMODE_TIMER_FREQ when running in M‑mode
  and RISCV_SMODE_TIMER_FREQ   in S‑mode.

This is also necessary because several functions
(e.g., net_random_ethaddr() via get_ticks()) rely on
timer_early_get_count() even if CONFIG_TIMER_EARLY is not
enabled.

Signed-off-by: Nikita Shubin <[email protected]>
---
 drivers/timer/Kconfig       | 13 +++++++++++--
 drivers/timer/riscv_timer.c | 12 +++++++++---
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 500a25638a9..12c194ff74a 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -227,8 +227,17 @@ config RISCV_TIMER
        bool "RISC-V timer support"
        depends on TIMER && RISCV
        help
-         Select this to enable support for a generic RISC-V S-Mode timer
-         driver.
+         Enable support for the generic RISC-V timer driver using the TIME CSR.
+
+         This driver works in S-mode and also in M-mode if the TIME CSR is
+         implemented in hardware (e.g., when the Zicntr extension is present).
+         In M-mode, the timer frequency must be provided via the macro
+         RISCV_MMODE_TIMER_FREQ; in S-mode, use RISCV_SMODE_TIMER_FREQ.
+
+         On platforms that also enable CLINT/ACLINT MTIMER, both drivers
+         may provide early timer functions and cause linking conflicts. Ensure
+         that only one of them is selected, or adjust the configuration to 
avoid
+         duplicate symbols.
 
 config ROCKCHIP_TIMER
        bool "Rockchip timer support"
diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
index 1f4980ceb38..c2e617317aa 100644
--- a/drivers/timer/riscv_timer.c
+++ b/drivers/timer/riscv_timer.c
@@ -7,7 +7,9 @@
  *
  * RISC-V architecturally-defined generic timer driver
  *
- * This driver provides generic timer support for S-mode U-Boot.
+ * This driver provides generic timer support for S-mode
+ * and M-Mode U-Boot if the TIME CSR is implemented in hardware
+ * (e.g., when the Zicntr extension is present).
  */
 
 #include <config.h>
@@ -33,14 +35,19 @@ static u64 notrace riscv_timer_get_count(struct udevice 
*dev)
        return ((u64)hi << 32) | lo;
 }
 
-#if CONFIG_IS_ENABLED(RISCV_SMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
 /**
  * timer_early_get_rate() - Get the timer rate before driver model
  */
+#if IS_ENABLED(CONFIG_TIMER_EARLY)
 unsigned long notrace timer_early_get_rate(void)
 {
+#if CONFIG_IS_ENABLED(RISCV_SMODE)
        return RISCV_SMODE_TIMER_FREQ;
+#elif CONFIG_IS_ENABLED(RISCV_MMODE)
+       return RISCV_MMODE_TIMER_FREQ;
+#endif
 }
+#endif
 
 /**
  * timer_early_get_count() - Get the timer count before driver model
@@ -50,7 +57,6 @@ u64 notrace timer_early_get_count(void)
 {
        return riscv_timer_get_count(NULL);
 }
-#endif
 
 #if CONFIG_IS_ENABLED(RISCV_SMODE) && CONFIG_IS_ENABLED(BOOTSTAGE)
 ulong timer_get_boot_us(void)

-- 
2.54.0

Reply via email to