Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Stephen Eta Zhou and committed by
Daniel Lezcano
640594a0 576c564e

+24
+24
drivers/clocksource/timer-sp804.c
··· 21 21 #include <linux/of_irq.h> 22 22 #include <linux/sched_clock.h> 23 23 24 + #ifdef CONFIG_ARM 25 + #include <linux/delay.h> 26 + #endif 27 + 24 28 #include "timer-sp.h" 25 29 26 30 /* Hisilicon 64-bit timer(a variant of ARM SP804) */ ··· 106 102 return ~readl_relaxed(sched_clkevt->value); 107 103 } 108 104 105 + #ifdef CONFIG_ARM 106 + static struct delay_timer delay; 107 + static unsigned long sp804_read_delay_timer_read(void) 108 + { 109 + return sp804_read(); 110 + } 111 + 112 + static void sp804_register_delay_timer(int freq) 113 + { 114 + delay.freq = freq; 115 + delay.read_current_timer = sp804_read_delay_timer_read; 116 + register_current_timer_delay(&delay); 117 + } 118 + #else 119 + static inline void sp804_register_delay_timer(int freq) {} 120 + #endif 121 + 109 122 static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, 110 123 const char *name, 111 124 struct clk *clk, ··· 134 113 rate = sp804_get_clock_rate(clk, name); 135 114 if (rate < 0) 136 115 return -EINVAL; 116 + 117 + sp804_register_delay_timer(rate); 137 118 138 119 clkevt = sp804_clkevt_get(base); 139 120 ··· 341 318 if (ret) 342 319 goto err; 343 320 } 321 + 344 322 initialized = true; 345 323 346 324 return 0;