Message ID | 20240312192519.1602493-1-samuel.holland@sifive.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | clocksource/drivers/timer-sun4i: Partially convert to a platform driver | expand |
On 12/03/2024 20:25, Samuel Holland wrote: > Commit 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a > platform driver") broke the MMIO timer on the Allwinner D1 SoC because > the IRQ domain is no longer available when timer_probe() is called: > > [ 0.000000] irq: no irq domain found for interrupt-controller@10000000 ! > [ 0.000000] Failed to map interrupt for /soc/timer@2050000 > [ 0.000000] Failed to initialize '/soc/timer@2050000': -22 > > Fix this by wrapping the timer initialization in a platform driver. > builtin_platform_driver_probe() must be used because the driver uses > timer_of_init(), which is marked as __init. Only convert the sun8i > variants of the hardware, because some older SoCs still need the timer > probed early for sched_clock(). > > Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") > Signed-off-by: Samuel Holland <samuel.holland@sifive.com> > --- Applied, thanks
On 12/03/2024 20:25, Samuel Holland wrote: > Commit 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a > platform driver") broke the MMIO timer on the Allwinner D1 SoC because > the IRQ domain is no longer available when timer_probe() is called: Did you mean: s/no longer available/not yet available/ ? > [ 0.000000] irq: no irq domain found for interrupt-controller@10000000 ! > [ 0.000000] Failed to map interrupt for /soc/timer@2050000 > [ 0.000000] Failed to initialize '/soc/timer@2050000': -22 > > Fix this by wrapping the timer initialization in a platform driver. > builtin_platform_driver_probe() must be used because the driver uses > timer_of_init(), which is marked as __init. Only convert the sun8i > variants of the hardware, because some older SoCs still need the timer > probed early for sched_clock(). > > Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") > Signed-off-by: Samuel Holland <samuel.holland@sifive.com> > --- > > drivers/clocksource/timer-sun4i.c | 24 ++++++++++++++++++++---- > 1 file changed, 20 insertions(+), 4 deletions(-) > > diff --git a/drivers/clocksource/timer-sun4i.c b/drivers/clocksource/timer-sun4i.c > index 7bdcc60ad43c..728dac2baa84 100644 > --- a/drivers/clocksource/timer-sun4i.c > +++ b/drivers/clocksource/timer-sun4i.c > @@ -20,6 +20,7 @@ > #include <linux/of.h> > #include <linux/of_address.h> > #include <linux/of_irq.h> > +#include <linux/platform_device.h> > > #include "timer-of.h" > > @@ -218,9 +219,24 @@ static int __init sun4i_timer_init(struct device_node *node) > } > TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer", > sun4i_timer_init); > -TIMER_OF_DECLARE(sun8i_a23, "allwinner,sun8i-a23-timer", > - sun4i_timer_init); > -TIMER_OF_DECLARE(sun8i_v3s, "allwinner,sun8i-v3s-timer", > - sun4i_timer_init); > TIMER_OF_DECLARE(suniv, "allwinner,suniv-f1c100s-timer", > sun4i_timer_init); > + > +static int __init sun4i_timer_probe(struct platform_device *pdev) > +{ > + return sun4i_timer_init(dev_of_node(&pdev->dev)); > +} > + > +static const struct of_device_id sun4i_timer_of_match[] = { > + { .compatible = "allwinner,sun8i-a23-timer" }, > + { .compatible = "allwinner,sun8i-v3s-timer" }, > + { /* sentinel */ } > +}; > + > +static struct platform_driver sun4i_timer_driver = { > + .driver = { > + .name = "sun4i-timer", > + .of_match_table = sun4i_timer_of_match, > + }, > +}; > +builtin_platform_driver_probe(sun4i_timer_driver, sun4i_timer_probe);
On 12/03/2024 20:25, Samuel Holland wrote: > Commit 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a > platform driver") broke the MMIO timer on the Allwinner D1 SoC because > the IRQ domain is no longer available when timer_probe() is called: > > [ 0.000000] irq: no irq domain found for interrupt-controller@10000000 ! > [ 0.000000] Failed to map interrupt for /soc/timer@2050000 > [ 0.000000] Failed to initialize '/soc/timer@2050000': -22 > > Fix this by wrapping the timer initialization in a platform driver. > builtin_platform_driver_probe() must be used because the driver uses > timer_of_init(), which is marked as __init. Only convert the sun8i > variants of the hardware, because some older SoCs still need the timer > probed early for sched_clock(). > > Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") > Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Why EPROBE_DEFER in thermal-of can not fix the issue? I mean can't we check if of_irq_get_byname() returns EPROBE_DEFER and then return this value?
On 2024-03-13 9:43 AM, Daniel Lezcano wrote: > On 12/03/2024 20:25, Samuel Holland wrote: >> Commit 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a >> platform driver") broke the MMIO timer on the Allwinner D1 SoC because >> the IRQ domain is no longer available when timer_probe() is called: > > Did you mean: s/no longer available/not yet available/ ? I mean that, before this commit, the IRQ domain was available during timer_probe(); but after this commit, the IRQ domain is not available during timer_probe(). >> [ 0.000000] irq: no irq domain found for interrupt-controller@10000000 ! >> [ 0.000000] Failed to map interrupt for /soc/timer@2050000 >> [ 0.000000] Failed to initialize '/soc/timer@2050000': -22 >> >> Fix this by wrapping the timer initialization in a platform driver. >> builtin_platform_driver_probe() must be used because the driver uses >> timer_of_init(), which is marked as __init. Only convert the sun8i >> variants of the hardware, because some older SoCs still need the timer >> probed early for sched_clock(). >> >> Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform >> driver") >> Signed-off-by: Samuel Holland <samuel.holland@sifive.com> >> --- >> >> drivers/clocksource/timer-sun4i.c | 24 ++++++++++++++++++++---- >> 1 file changed, 20 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/clocksource/timer-sun4i.c >> b/drivers/clocksource/timer-sun4i.c >> index 7bdcc60ad43c..728dac2baa84 100644 >> --- a/drivers/clocksource/timer-sun4i.c >> +++ b/drivers/clocksource/timer-sun4i.c >> @@ -20,6 +20,7 @@ >> #include <linux/of.h> >> #include <linux/of_address.h> >> #include <linux/of_irq.h> >> +#include <linux/platform_device.h> >> #include "timer-of.h" >> @@ -218,9 +219,24 @@ static int __init sun4i_timer_init(struct device_node >> *node) >> } >> TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer", >> sun4i_timer_init); >> -TIMER_OF_DECLARE(sun8i_a23, "allwinner,sun8i-a23-timer", >> - sun4i_timer_init); >> -TIMER_OF_DECLARE(sun8i_v3s, "allwinner,sun8i-v3s-timer", >> - sun4i_timer_init); >> TIMER_OF_DECLARE(suniv, "allwinner,suniv-f1c100s-timer", >> sun4i_timer_init); >> + >> +static int __init sun4i_timer_probe(struct platform_device *pdev) >> +{ >> + return sun4i_timer_init(dev_of_node(&pdev->dev)); >> +} >> + >> +static const struct of_device_id sun4i_timer_of_match[] = { >> + { .compatible = "allwinner,sun8i-a23-timer" }, >> + { .compatible = "allwinner,sun8i-v3s-timer" }, >> + { /* sentinel */ } >> +}; >> + >> +static struct platform_driver sun4i_timer_driver = { >> + .driver = { >> + .name = "sun4i-timer", >> + .of_match_table = sun4i_timer_of_match, >> + }, >> +}; >> +builtin_platform_driver_probe(sun4i_timer_driver, sun4i_timer_probe); >
On 2024-03-13 10:29 AM, Daniel Lezcano wrote: > On 12/03/2024 20:25, Samuel Holland wrote: >> Commit 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a >> platform driver") broke the MMIO timer on the Allwinner D1 SoC because >> the IRQ domain is no longer available when timer_probe() is called: >> >> [ 0.000000] irq: no irq domain found for interrupt-controller@10000000 ! >> [ 0.000000] Failed to map interrupt for /soc/timer@2050000 >> [ 0.000000] Failed to initialize '/soc/timer@2050000': -22 >> >> Fix this by wrapping the timer initialization in a platform driver. >> builtin_platform_driver_probe() must be used because the driver uses >> timer_of_init(), which is marked as __init. Only convert the sun8i >> variants of the hardware, because some older SoCs still need the timer >> probed early for sched_clock(). >> >> Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform >> driver") >> Signed-off-by: Samuel Holland <samuel.holland@sifive.com> > > Why EPROBE_DEFER in thermal-of can not fix the issue? > > I mean can't we check if of_irq_get_byname() returns EPROBE_DEFER and then > return this value? EPROBE_DEFER would not help either before or after this patch. Before this patch, the driver uses TIMER_OF_DECLARE, which means the timer gets initialized from the loop in timer_probe(). That function does not retry if the initialization function returns EPROBE_DEFER. And timer_probe() is only meant to be called once, before any platform drivers are registered. It does not help after this patch either, because __platform_driver_probe() also requires the probe to succeed the first time. This is needed to ensure the probe function runs before __init memory is discarded. (To support deferred probing in timer-of, none of the functions could be marked as __init.) But that is okay, because if both the irqchip and the timer use platform drivers, fw_devlink ensures they are probed in the right order. So this patch reliably allows the timer to probe successfully. Regards, Samuel
diff --git a/drivers/clocksource/timer-sun4i.c b/drivers/clocksource/timer-sun4i.c index 7bdcc60ad43c..728dac2baa84 100644 --- a/drivers/clocksource/timer-sun4i.c +++ b/drivers/clocksource/timer-sun4i.c @@ -20,6 +20,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> #include "timer-of.h" @@ -218,9 +219,24 @@ static int __init sun4i_timer_init(struct device_node *node) } TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer", sun4i_timer_init); -TIMER_OF_DECLARE(sun8i_a23, "allwinner,sun8i-a23-timer", - sun4i_timer_init); -TIMER_OF_DECLARE(sun8i_v3s, "allwinner,sun8i-v3s-timer", - sun4i_timer_init); TIMER_OF_DECLARE(suniv, "allwinner,suniv-f1c100s-timer", sun4i_timer_init); + +static int __init sun4i_timer_probe(struct platform_device *pdev) +{ + return sun4i_timer_init(dev_of_node(&pdev->dev)); +} + +static const struct of_device_id sun4i_timer_of_match[] = { + { .compatible = "allwinner,sun8i-a23-timer" }, + { .compatible = "allwinner,sun8i-v3s-timer" }, + { /* sentinel */ } +}; + +static struct platform_driver sun4i_timer_driver = { + .driver = { + .name = "sun4i-timer", + .of_match_table = sun4i_timer_of_match, + }, +}; +builtin_platform_driver_probe(sun4i_timer_driver, sun4i_timer_probe);
Commit 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") broke the MMIO timer on the Allwinner D1 SoC because the IRQ domain is no longer available when timer_probe() is called: [ 0.000000] irq: no irq domain found for interrupt-controller@10000000 ! [ 0.000000] Failed to map interrupt for /soc/timer@2050000 [ 0.000000] Failed to initialize '/soc/timer@2050000': -22 Fix this by wrapping the timer initialization in a platform driver. builtin_platform_driver_probe() must be used because the driver uses timer_of_init(), which is marked as __init. Only convert the sun8i variants of the hardware, because some older SoCs still need the timer probed early for sched_clock(). Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") Signed-off-by: Samuel Holland <samuel.holland@sifive.com> --- drivers/clocksource/timer-sun4i.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)