Skip to content

Commit 640594a

Browse files
Stephen Eta Zhoudlezcano
authored andcommitted
clocksource/drivers/timer-sp804: Fix read_current_timer() issue when clock source is not registered
Register a valid read_current_timer() function for the SP804 timer on ARM32. On ARM32 platforms, when the SP804 timer is selected as the clocksource, the driver does not register a valid read_current_timer() function. As a result, features that rely on this API—such as rdseed—consistently return incorrect values. To fix this, a delay_timer structure is registered during the SP804 driver's initialization. The read_current_timer() function is implemented using the existing sp804_read() logic, and the timer frequency is reused from the already-initialized clocksource. Signed-off-by: Stephen Eta Zhou <stephen.eta.zhou@gmail.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://patch.msgid.link/20250525-sp804-fix-read_current_timer-v4-1-87a9201fa4ec@gmail.com
1 parent 576c564 commit 640594a

1 file changed

Lines changed: 24 additions & 0 deletions

File tree

drivers/clocksource/timer-sp804.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include <linux/of_irq.h>
2222
#include <linux/sched_clock.h>
2323

24+
#ifdef CONFIG_ARM
25+
#include <linux/delay.h>
26+
#endif
27+
2428
#include "timer-sp.h"
2529

2630
/* Hisilicon 64-bit timer(a variant of ARM SP804) */
@@ -102,6 +106,23 @@ static u64 notrace sp804_read(void)
102106
return ~readl_relaxed(sched_clkevt->value);
103107
}
104108

109+
#ifdef CONFIG_ARM
110+
static struct delay_timer delay;
111+
static unsigned long sp804_read_delay_timer_read(void)
112+
{
113+
return sp804_read();
114+
}
115+
116+
static void sp804_register_delay_timer(int freq)
117+
{
118+
delay.freq = freq;
119+
delay.read_current_timer = sp804_read_delay_timer_read;
120+
register_current_timer_delay(&delay);
121+
}
122+
#else
123+
static inline void sp804_register_delay_timer(int freq) {}
124+
#endif
125+
105126
static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
106127
const char *name,
107128
struct clk *clk,
@@ -114,6 +135,8 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
114135
if (rate < 0)
115136
return -EINVAL;
116137

138+
sp804_register_delay_timer(rate);
139+
117140
clkevt = sp804_clkevt_get(base);
118141

119142
writel(0, clkevt->ctrl);
@@ -318,6 +341,7 @@ static int __init sp804_of_init(struct device_node *np, struct sp804_timer *time
318341
if (ret)
319342
goto err;
320343
}
344+
321345
initialized = true;
322346

323347
return 0;

0 commit comments

Comments
 (0)