[PATCH v2] clocksource: timer-sp804: Fix read_current_timer() issue when clock source is not registered

From: stephen eta zhou
Date: Sat Mar 08 2025 - 11:31:27 EST


Hi Daniel

I referred to the improvement suggestions you provided and made the following improvements:

1. Added static keyword to struct delay_timer delay;
2. Integrate sp804_read_delay_timer_read and struct delay_timer delay together
3. I moved the acquisition of delay.freq to sp804_clocksource_and_sched_clock_init.
    sp804_clocksource_and_sched_clock_init has already acquired and judged freq, so I can use it directly, and in this way I don’t need to consider whether to use clk1 or clk2, which can ensure that the clock source is available and reliable.
4. Added detailed description information in Commit

>From cd6eedb2b117c5371b0a777e224b4094d7cbfd90 Mon Sep 17 00:00:00 2001
From: Stephen Eta Zhou <stephen.eta.zhou@xxxxxxxxxxx>
Date: Sat, 8 Mar 2025 20:24:18 +0800
Subject: [PATCH] clocksource: timer-sp804: Fix read_current_timer() issue when
 clock source is not registered
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch adds compatibility support for ARM32 for the SP804 clock driver.

This patch solves the problem that when using SP804 as the clock source
under ARM32, the kernel inserts a canary into the
interrupt stack due to the failure to register
read_current_timer (this error will appear in boot_init_stack_canary),
and it also affects the generation and collection of the entropy pool,
resulting in incorrect rdseed values.

Changes in v2:
1. Added static keyword to struct delay_timer delay
2. Integrate sp804_read_delay_timer_read and
   struct delay_timer delay together
3. I moved the acquisition of delay.freq to
   sp804_clocksource_and_sched_clock_init.
   sp804_clocksource_and_sched_clock_init has already
   acquired and judged freq, so I can use it directly,
   and in this way I don’t need to consider whether to
   use clk1 or clk2, which can ensure that the clock source
   is available and reliable.
4. Added detailed description information in Commit

CC: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx>
Signed-off-by: Stephen Eta Zhou <stephen.eta.zhou@xxxxxxxxxxx>
---
 drivers/clocksource/timer-sp804.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index cd1916c05325..3194c743ad1d 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -21,6 +21,10 @@
 #include <linux/of_irq.h>
 #include <linux/sched_clock.h>
 
+#ifdef CONFIG_ARM
+#include <linux/delay.h>
+#endif
+
 #include "timer-sp.h"
 
 /* Hisilicon 64-bit timer(a variant of ARM SP804) */
@@ -102,6 +106,15 @@ static u64 notrace sp804_read(void)
  return ~readl_relaxed(sched_clkevt->value);
 }
 
+#ifdef CONFIG_ARM
+static struct delay_timer delay;
+
+static unsigned long sp804_read_delay_timer_read(void)
+{
+ return sp804_read();
+}
+#endif
+
 static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
         const char *name,
         struct clk *clk,
@@ -114,6 +127,10 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
  if (rate < 0)
   return -EINVAL;
 
+#ifdef CONFIG_ARM
+ delay.freq = rate;
+#endif
+
  clkevt = sp804_clkevt_get(base);
 
  writel(0, clkevt->ctrl);
@@ -318,6 +335,12 @@ static int __init sp804_of_init(struct device_node *np, struct sp804_timer *time
   if (ret)
    goto err;
  }
+
+#ifdef CONFIG_ARM
+ delay.read_current_timer = sp804_read_delay_timer_read;
+ register_current_timer_delay(&delay);
+#endif
+
  initialized = true;
 
  return 0;
--
2.25.1