[PATCH v1 5/7] clocksource/drivers/timer-probe: Add the module support for the TIMER_PDEV_DECLARE() macro

From: Daniel Lezcano

Date: Fri Mar 27 2026 - 13:58:34 EST


A driver using the macro TIMER_PDEV_DECLARE can now be compiled as a
module. When it is the case the TIMER_PDEV_DECLARE() macro will add
module_platform_driver() and MODULE_DEVICE_TABLE() automatically.

However if the early timer initialization is needed in place of the
module init section like what we have now, we should enable
CONFIG_EARLY_TIMER.

When all drivers will be converted to TIMER_PDEV_DECLARE(), the
TIMER_OF_DECLARE() can be removed and we will end up with the
following configuration:

* On ARM architecture, we enable automatically CONFIG_EARLY_TIMER, no
timer can be compiled as a module

* On ARM64 architecture, we can enable as a module, otherwise it will
be compiled-in. The CONFIG_EARLY_TIMER is not needed on this arch
because the architected timers are always present

* On other architecture, that needs to be defined but I suspect we
have the same scheme

Signed-off-by: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx>
---
drivers/clocksource/Kconfig | 7 ++++++-
drivers/clocksource/timer-probe.c | 3 +++
include/linux/clocksource.h | 12 +++++++++++-
3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index fd9112706545..ee2372f21e78 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -2,6 +2,11 @@
menu "Clock Source drivers"
depends on GENERIC_CLOCKEVENTS

+config EARLY_TIMER
+ bool "Early driver initialization"
+ help
+ Enables early timer driver loading
+
config TIMER_OF
bool
select TIMER_PROBE
@@ -100,7 +105,7 @@ config IXP4XX_TIMER
Enables support for the Intel XScale IXP4xx SoC timer.

config ROCKCHIP_TIMER
- bool "Rockchip timer driver" if COMPILE_TEST
+ bool "Rockchip timer driver" if COMPILE_TEST
depends on ARM || ARM64
select TIMER_OF
select CLKSRC_MMIO
diff --git a/drivers/clocksource/timer-probe.c b/drivers/clocksource/timer-probe.c
index cdaceb68d356..0fc582e4afde 100644
--- a/drivers/clocksource/timer-probe.c
+++ b/drivers/clocksource/timer-probe.c
@@ -84,6 +84,9 @@ static int __init timer_pdev_probe(void)
{
struct platform_driver **drv;

+ if (!IS_ENABLED(CONFIG_EARLY_TIMER))
+ return 0;
+
for_each_pdev_timer_table(drv)
__timer_pdev_probe(*drv);

diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 6e05b78e64b8..6b09fe67d37f 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -299,7 +299,7 @@ static inline void timer_probe(void) {}
extern struct platform_driver *__pdev_timer_table[];
extern struct platform_driver *__pdev_timer_table_end[];

-#define TIMER_PDEV_DECLARE(__name, __probe, __remove, __match) \
+#define __TIMER_PDEV_DECLARE(__name, __probe, __remove, __match) \
static struct platform_driver __pdev_timer_table_entry_##__name = { \
.probe = __probe, \
.remove = __remove, \
@@ -311,6 +311,16 @@ extern struct platform_driver *__pdev_timer_table_end[];
static struct platform_driver *___pdev_timer_table_entry_##__name \
__used __section("__pdev_timer_table") = &__pdev_timer_table_entry_##__name

+#if !defined(CONFIG_EARLY_TIMER) || defined(MODULE)
+#define TIMER_PDEV_DECLARE(__name, __probe, __remove, __match) \
+ MODULE_DEVICE_TABLE(of, __match); \
+ __TIMER_PDEV_DECLARE(__name, __probe, __remove, __match); \
+ module_platform_driver(__pdev_timer_table_entry_##__name);
+#else
+#define TIMER_PDEV_DECLARE(__name, __probe, __remove, __match) \
+ __TIMER_PDEV_DECLARE(__name, __probe, __remove, __match)
+#endif
+
#define for_each_pdev_timer_table(__pdev) \
for (__pdev = __pdev_timer_table; \
__pdev < __pdev_timer_table_end; \
--
2.43.0