Thread (13 messages) 13 messages, 5 authors, 2025-07-10

Re: [PATCH RFC] timer: of: Create a platform_device before the framework is initialized

From: "Arnd Bergmann" <arnd@arndb.de>
Date: 2025-07-08 16:10:53
Also in: linux-devicetree, lkml

On Tue, Jul 8, 2025, at 11:50, Daniel Lezcano wrote:
On Tue, Jul 01, 2025 at 09:52:45AM +0200, Arnd Bergmann wrote:
quoted
On Tue, Jul 1, 2025, at 01:53, William McVicker wrote:
quoted
quoted
@@ -1550,6 +1553,8 @@ typedef void (*of_init_fn_1)(struct device_node *);
 		_OF_DECLARE(table, name, compat, fn, of_init_fn_1_ret)
 #define OF_DECLARE_2(table, name, compat, fn) \
 		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
+#define OF_DECLARE_PDEV(table, name, compat, fn) \
+		_OF_DECLARE(table, name, compat, fn, of_init_fn_pdev)
To support auto-module loading you'll need to also define the
MODULE_DEVICE_TABLE() as part of TIMER_OF_DECLARE_PDEV().

I haven't tested the patch yet, but aside from my comment above it LGTM.
The patch doesn't actually have a module_platform_driver_probe()
yet either, so loading the module wouldn't actually do anything.

I feel that this RFC by itself a good step in the direction we want, 
so Daniel should go ahead with prototyping the next two steps:
adding the platform_driver registration into OF_DECLARE_PDEV,
and converting a driver so it can be used either with the _OF_DECLARE()
or the platform_driver case.
I'm questioning the relevance of adding the macro when the driver is
not compiled as a module.

The first step of this macro is to allow the existing init functions
to be converted to the same signature as the module probe functions in
order to share the same code and take benefit of the devm_ variants
function which will considerably reduce the code size of the drivers.

Then we have the following situations:

 1. The driver has to be loaded very early TIMER_OF_DECLARE_PDEV
 (MODULE=no) the function timer-probe() is used

 2. The driver is a module_platform_driver() and MODULE=no, then it is
 built as a builtin_platform_driver(), we do not care about having it
 loaded by timer-probe()

 3. The driver is a module_platform_driver() and MODULE=yes

If we do the change to have the TIMER_OF_DECLARE_PDEV() adding the
platform_driver registration when MODULE=yes but using timer-probe
when MODULE=no, we change the initialization and we will have issues
with timers needing resources like SCMI clocks and where the
mechanisms rely on EPROBE_DEFER.

IMO, module_platform_driver and timer_probe must be separated.
I assumed that the entire point of your work was to simplify
the code when you have both a early and platform_driver based
probing in a single driver.
Let's assume the one possible future use case with the VF PIT. This
timer is only used on ARM but now it is also supported for the ARM64
s32g2. For the first platform we need it very early and in the second
case, we need it later because the architected timers are there.

We should endup with:

static const struct of_device_id pit_timer_of_match[] = {
	{ .compatible = "nxp,s32g2-pit", .data = &s32g2_data },
	{ .compatible = "nxp,s32g3-pit", .data = &s32g3_data },
	{ }
};
MODULE_DEVICE_TABLE(of, pit_timer_of_match);

static struct platform_driver nxp_pit_driver = {
	.driver = {
		.name = "nxp-pit",
		.of_match_table = pit_timer_of_match,
	},
	.probe = pit_timer_probe,
};
module_platform_driver(nxp_pit_driver);

TIMER_OF_DECLARE_PDEV(vf610, "fsl,vf610-pit", pit_timer_probe);
If you think we still need a module_platform_driver(), I would
not bother adding TIMER_OF_DECLARE_PDEV() either, as the
probe functions can easily be shared as well, the way that
drivers/clocksource/renesas-ostm.c does.

The only thing that would lose is the ability to call devm_
functions because the device pointer is unavailable here.
If we change the TIMER_OF_DECLARE_PDEV to a macro which relies on
timer_probe when MODULE=no, then the "nxp-pit" on the s32gX will fail
to initialize because of the SCMI clocks not ready and the routine
won't reprobe the function. This issue won't happen with
builtin_platform_driver
The way I had expected this to work was that TIMER_OF_DECLARE_PDEV()
always registers the platform_driver and just skips the
section magic when it's in a loadable module.

    Arnd
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help