Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [RFT PATCH v3] ARM: omap1: enable real software node lookup of GPIOs on Nokia 770
From: Dmitry Torokhov @ 2026-03-27 18:16 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Janusz Krzysztofik, Arnd Bergmann, Bartosz Golaszewski,
	Tony Lindgren, Russell King, Hans de Goede, Linux-OMAP,
	linux-arm-kernel, linux-kernel, Kevin Hilman, Aaro Koskinen,
	Andy Shevchenko
In-Reply-To: <CAMRc=MeUEApQuw8prxr6ku674fqORCy2=givJxLe+cUCC0PGww@mail.gmail.com>

On Fri, Mar 27, 2026 at 10:27:07AM -0700, Bartosz Golaszewski wrote:
> On Fri, 27 Mar 2026 18:23:29 +0100, Bartosz Golaszewski <brgl@kernel.org> said:
> > On Fri, Mar 27, 2026 at 5:59 PM Aaro Koskinen <aaro.koskinen@iki.fi> wrote:
> >>
> >> Hi,
> >>
> >> On Fri, Mar 27, 2026 at 03:22:12PM +0100, Bartosz Golaszewski wrote:
> >> > Hmm, I'm wondering if there's a race with consumers already requesting
> >> > the GPIOs after the controller device is registered but before the
> >> > software node is added. I'll send a version with software nodes being
> >> > registered first, then passes as firmware nodes to the platform device
> >> > API before the device is registered.
> >>
> >> It crashes early, I was able to get an UART log from OSK (another
> >> 16xx board):
> >>
> >> [    1.001525] Register r12 information: 2-page vmalloc region starting at 0xc2808000 allocated at kernel_clone+0xa4/0x20c
> >> [    1.013092] Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
> >> [    1.019500] Stack: (0xc2809ed0 to 0xc280a000)
> >> [    1.024230] 9ec0:                                     c072d000 c0529474 c06b3aa0 c050a3cc
> >> [    1.032958] 9ee0: c072d000 c085c000 00000002 c052582c c050a324 c072d000 00000000 c0503160
> >> [    1.041687] 9f00: 00002710 00000000 c04da8f8 c0060900 c2809f64 ffffffff 00010000 946f70b5
> >> [    1.050384] 9f20: 00000062 c0816120 00000002 c052582c c0525848 c072d000 c04da8f8 c0060a18
> >> [    1.059112] 9f40: c2809f64 c2809f64 00000000 946f70b5 00000062 c0816120 00000002 c052582c
> >> [    1.067810] 9f60: c052584c c072d000 c04da8f8 c050352c 00000002 00000002 00000000 c0502400
> >> [    1.076507] 9f80: c2809f7c 00000000 c03f86f4 00000000 00000000 00000000 00000000 00000000
> >> [    1.085205] 9fa0: 00000000 c03f8704 00000000 c000850c 00000000 00000000 00000000 00000000
> >> [    1.093902] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> >> [    1.102600] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
> >> [    1.111206] Call trace:
> >> [    1.111328]  software_node_to_swnode from device_add_software_node+0x20/0x80
> >> [    1.121704]  device_add_software_node from omap16xx_gpio_init+0xa8/0xe4
> >> [    1.128997]  omap16xx_gpio_init from do_one_initcall+0x68/0x1f4
> >> [    1.135620]  do_one_initcall from kernel_init_freeable+0x1ec/0x240
> >> [    1.142517]  kernel_init_freeable from kernel_init+0x10/0x108
> >> [    1.148864]  kernel_init from ret_from_fork+0x14/0x28
> >> [    1.154357] Exception stack(0xc2809fb0 to 0xc2809ff8)
> >> [    1.159820] 9fa0:                                     00000000 00000000 00000000 00000000
> >> [    1.168518] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> >> [    1.177185] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> >> [    1.184295] Code: e3500000 012fff1e e59f3034 e5932000 (e5923000)
> >> [    1.191040] ---[ end trace 0000000000000000 ]---
> >> [    1.196350] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
> >> [    1.204559] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
> >>
> >
> > Thanks. This makes sense. Both omap16xx_gpio_init() and
> > software_node_init() run as postcore_initcall() so if the order is not
> > right, it will fail.
> >
> > Cc'ing Andy who's a reviewer for software nodes. Andy: is there any
> > reason to run software_node_init() as a postcore initcall? It only
> > allocates the kset, can we move it to core_initcall() by any chance?
> >
> > Bart
> >
> 
> In any case, Aaro: the following should theoretically fix it:
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 51320837f3a9..5ba904f8a08a 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -1134,7 +1134,7 @@ static int __init software_node_init(void)
>  		return -ENOMEM;
>  	return 0;
>  }
> -postcore_initcall(software_node_init);
> +core_initcall(software_node_init);

This is wrong direction IMO. The matching by label is working now, so
there is no reason to rush this change into the kernel, it is simply a
cleanup.

Wait until the resolution of my pact allowing using node names, or your
proposal that installs and attaches nodes dynamically based on bus
notifiers (or both) and then make the conversion. Then you will not need
to move init order around, add new dependencies between drivers, and so
on.

Thanks.

-- 
Dmitry


^ permalink raw reply

* Re: [PATCH v4 00/38] KVM: arm64: Add support for protected guest memory with pKVM
From: Will Deacon @ 2026-03-27 18:13 UTC (permalink / raw)
  To: kvmarm
  Cc: linux-arm-kernel, Marc Zyngier, Oliver Upton, Joey Gouly,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Quentin Perret,
	Fuad Tabba, Vincent Donnefort, Mostafa Saleh, Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>

On Fri, Mar 27, 2026 at 01:59:59PM +0000, Will Deacon wrote:
> I fully expect to send a v5, as this is the first time Sashiko has had
> a chance to chew on this and I'm expecting a roasting.

After going through it, the report isn't as bad as it looks and some of
the comments are actively wrong, which I suppose is inevitable.

That being said, I've got a handful of fixes to fold in now and it's
pointed out some unrelated life-cycle issues that we want want to fix
separately.

Will


^ permalink raw reply

* ✅ PASS: Test report for for-kernelci (7.0.0-rc5, upstream-arm-next, 2b285798)
From: cki-project @ 2026-03-27 18:12 UTC (permalink / raw)
  To: will, catalin.marinas, linux-arm-kernel

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK
              Test: OK

Tested-by: CKI Project <cki-project@redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:2413719816


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



^ permalink raw reply

* [PATCH resend v1 7/7] clocksource/drivers/mediatek: Convert to module support
From: Daniel Lezcano @ 2026-03-27 18:05 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <20260327180600.8150-1-daniel.lezcano@kernel.org>

Now the TIMER_PDEV_DECLARE() allows the driver to be compiled as a
module. Add the MODULE_DESCRIPTION and the MODULE_LICENSE left for the
one converting the driver as a module.

Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/clocksource/timer-mediatek.c | 29 ++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/timer-mediatek.c b/drivers/clocksource/timer-mediatek.c
index 7bcb4a3f26fb..f5de5f397730 100644
--- a/drivers/clocksource/timer-mediatek.c
+++ b/drivers/clocksource/timer-mediatek.c
@@ -215,8 +215,7 @@ static irqreturn_t mtk_gpt_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void
-__init mtk_gpt_setup(struct timer_of *to, u8 timer, u8 option)
+static void mtk_gpt_setup(struct timer_of *to, u8 timer, u8 option)
 {
 	writel(GPT_CTRL_CLEAR | GPT_CTRL_DISABLE,
 	       timer_of_base(to) + GPT_CTRL_REG(timer));
@@ -281,7 +280,7 @@ static struct timer_of to = {
 	},
 };
 
-static int __init mtk_syst_init(struct device_node *node)
+static int mtk_syst_init(struct device_node *node)
 {
 	int ret;
 
@@ -302,7 +301,7 @@ static int __init mtk_syst_init(struct device_node *node)
 	return 0;
 }
 
-static int __init mtk_gpt_init(struct device_node *node)
+static int mtk_gpt_init(struct device_node *node)
 {
 	int ret;
 
@@ -337,5 +336,23 @@ static int __init mtk_gpt_init(struct device_node *node)
 
 	return 0;
 }
-TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_gpt_init);
-TIMER_OF_DECLARE(mtk_mt6765, "mediatek,mt6765-timer", mtk_syst_init);
+
+static int mtk_timer_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int (*probe_func)(struct device_node *node);
+
+	probe_func = of_device_get_match_data(&pdev->dev);
+
+	return probe_func(np);
+}
+
+static const struct of_device_id mtk_timer_match_table[] = {
+	{ .compatible =  "mediatek,mt6577-timer", .data = mtk_gpt_init },
+	{ .compatible =  "mediatek,mt6765-timer", .data = mtk_syst_init },
+	{ /* sentinel */ }
+};
+
+TIMER_PDEV_DECLARE(mtk_timer, mtk_timer_probe, NULL, mtk_timer_match_table);
+MODULE_DESCRIPTION("Mediatek timer driver");
+MODULE_LICENSE("GPL");
-- 
2.43.0



^ permalink raw reply related

* [PATCH resend v1 6/7] clocksource/drivers/rockchip: Add rockchip timer module support
From: Daniel Lezcano @ 2026-03-27 18:05 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Heiko Stuebner,
	moderated list:ARM/Rockchip SoC support,
	open list:ARM/Rockchip SoC support
In-Reply-To: <20260327180600.8150-1-daniel.lezcano@kernel.org>

Now the TIMER_PDEV_DECLARE() allows the driver to be compiled as a
module. Add the MODULE_DESCRIPTION and the MODULE_LICENSE left for the
one converting the driver as a module.

Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/clocksource/timer-rockchip.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clocksource/timer-rockchip.c b/drivers/clocksource/timer-rockchip.c
index 486bbffba464..61433b295882 100644
--- a/drivers/clocksource/timer-rockchip.c
+++ b/drivers/clocksource/timer-rockchip.c
@@ -271,3 +271,5 @@ static const struct of_device_id rk_timer_match_table[] = {
 };
 
 TIMER_PDEV_DECLARE(rk_timer, rk_timer_probe, NULL, rk_timer_match_table);
+MODULE_DESCRIPTION("Rockchip timer driver");
+MODULE_LICENSE("GPL");
-- 
2.43.0



^ permalink raw reply related

* [PATCH resend v1 5/7] clocksource/drivers/rockchip: Use the TIMER_PDEV_DECLARE() macro
From: Daniel Lezcano @ 2026-03-27 18:05 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Heiko Stuebner,
	moderated list:ARM/Rockchip SoC support,
	open list:ARM/Rockchip SoC support
In-Reply-To: <20260327180600.8150-1-daniel.lezcano@kernel.org>

The previous changes introduced the TIMER_PDEV_DECLARE() macro which
allows to use the platform driver to initialize a timer driver with
the benefit of having the devres to rollback automatically in case of
error.

Use this macro and change the function to rely on the devm_ variants,
allowing to cleanup the code.

Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/clocksource/timer-rockchip.c | 99 ++++++++++------------------
 1 file changed, 34 insertions(+), 65 deletions(-)

diff --git a/drivers/clocksource/timer-rockchip.c b/drivers/clocksource/timer-rockchip.c
index 540a16667145..486bbffba464 100644
--- a/drivers/clocksource/timer-rockchip.c
+++ b/drivers/clocksource/timer-rockchip.c
@@ -124,18 +124,18 @@ static u64 notrace rk_timer_sched_read(void)
 	return ~readl_relaxed(rk_clksrc->base + TIMER_CURRENT_VALUE0);
 }
 
-static int __init
-rk_timer_probe(struct rk_timer *timer, struct device_node *np)
+static int rk_timer_init(struct rk_timer *timer, struct device *dev)
 {
+	struct device_node *np = dev->of_node;
 	struct clk *timer_clk;
 	struct clk *pclk;
-	int ret = -EINVAL, irq;
+	int irq;
 	u32 ctrl_reg = TIMER_CONTROL_REG3288;
 
-	timer->base = of_iomap(np, 0);
-	if (!timer->base) {
+	timer->base = devm_of_iomap(dev, np, 0, NULL);
+	if (IS_ERR(timer->base)) {
 		pr_err("Failed to get base address for '%s'\n", TIMER_NAME);
-		return -ENXIO;
+		return PTR_ERR(timer->base);
 	}
 
 	if (of_device_is_compatible(np, "rockchip,rk3399-timer"))
@@ -143,31 +143,17 @@ rk_timer_probe(struct rk_timer *timer, struct device_node *np)
 
 	timer->ctrl = timer->base + ctrl_reg;
 
-	pclk = of_clk_get_by_name(np, "pclk");
+	pclk = devm_clk_get_enabled(dev, "pclk");
 	if (IS_ERR(pclk)) {
-		ret = PTR_ERR(pclk);
 		pr_err("Failed to get pclk for '%s'\n", TIMER_NAME);
-		goto out_unmap;
-	}
-
-	ret = clk_prepare_enable(pclk);
-	if (ret) {
-		pr_err("Failed to enable pclk for '%s'\n", TIMER_NAME);
-		goto out_unmap;
+		return PTR_ERR(pclk);
 	}
 	timer->pclk = pclk;
 
-	timer_clk = of_clk_get_by_name(np, "timer");
+	timer_clk = devm_clk_get_enabled(dev, "timer");
 	if (IS_ERR(timer_clk)) {
-		ret = PTR_ERR(timer_clk);
 		pr_err("Failed to get timer clock for '%s'\n", TIMER_NAME);
-		goto out_timer_clk;
-	}
-
-	ret = clk_prepare_enable(timer_clk);
-	if (ret) {
-		pr_err("Failed to enable timer clock\n");
-		goto out_timer_clk;
+		return PTR_ERR(timer_clk);
 	}
 	timer->clk = timer_clk;
 
@@ -175,47 +161,32 @@ rk_timer_probe(struct rk_timer *timer, struct device_node *np)
 
 	irq = irq_of_parse_and_map(np, 0);
 	if (!irq) {
-		ret = -EINVAL;
 		pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME);
-		goto out_irq;
+		return -EINVAL;
 	}
 	timer->irq = irq;
 
 	rk_timer_interrupt_clear(timer);
 	rk_timer_disable(timer);
-	return 0;
-
-out_irq:
-	clk_disable_unprepare(timer_clk);
-out_timer_clk:
-	clk_disable_unprepare(pclk);
-out_unmap:
-	iounmap(timer->base);
-
-	return ret;
-}
 
-static void __init rk_timer_cleanup(struct rk_timer *timer)
-{
-	clk_disable_unprepare(timer->clk);
-	clk_disable_unprepare(timer->pclk);
-	iounmap(timer->base);
+	return 0;
 }
 
-static int __init rk_clkevt_init(struct device_node *np)
+static int rk_clkevt_init(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	struct clock_event_device *ce;
 	int ret = -EINVAL;
 
-	rk_clkevt = kzalloc_obj(struct rk_clkevt);
+	rk_clkevt = devm_kzalloc(dev, sizeof(*rk_clkevt), GFP_KERNEL);
 	if (!rk_clkevt) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rk_timer_probe(&rk_clkevt->timer, np);
+	ret = rk_timer_init(&rk_clkevt->timer, dev);
 	if (ret)
-		goto out_probe;
+		goto out;
 
 	ce = &rk_clkevt->ce;
 	ce->name = TIMER_NAME;
@@ -233,36 +204,33 @@ static int __init rk_clkevt_init(struct device_node *np)
 	if (ret) {
 		pr_err("Failed to initialize '%s': %d\n",
 			TIMER_NAME, ret);
-		goto out_irq;
+		goto out;
 	}
 
 	clockevents_config_and_register(&rk_clkevt->ce,
 					rk_clkevt->timer.freq, 1, UINT_MAX);
 	return 0;
 
-out_irq:
-	rk_timer_cleanup(&rk_clkevt->timer);
-out_probe:
-	kfree(rk_clkevt);
 out:
 	/* Leave rk_clkevt not NULL to prevent future init */
 	rk_clkevt = ERR_PTR(ret);
 	return ret;
 }
 
-static int __init rk_clksrc_init(struct device_node *np)
+static int rk_clksrc_init(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	int ret = -EINVAL;
 
-	rk_clksrc = kzalloc_obj(struct rk_timer);
+	rk_clksrc = devm_kzalloc(dev, sizeof(*rk_clksrc), GFP_KERNEL);
 	if (!rk_clksrc) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rk_timer_probe(rk_clksrc, np);
+	ret = rk_timer_init(rk_clksrc, dev);
 	if (ret)
-		goto out_probe;
+		goto out;
 
 	rk_timer_update_counter(UINT_MAX, rk_clksrc);
 	rk_timer_enable(rk_clksrc, 0);
@@ -272,33 +240,34 @@ static int __init rk_clksrc_init(struct device_node *np)
 		clocksource_mmio_readl_down);
 	if (ret) {
 		pr_err("Failed to register clocksource\n");
-		goto out_clocksource;
+		goto out;
 	}
 
 	sched_clock_register(rk_timer_sched_read, 32, rk_clksrc->freq);
 	return 0;
 
-out_clocksource:
-	rk_timer_cleanup(rk_clksrc);
-out_probe:
-	kfree(rk_clksrc);
 out:
 	/* Leave rk_clksrc not NULL to prevent future init */
 	rk_clksrc = ERR_PTR(ret);
 	return ret;
 }
 
-static int __init rk_timer_init(struct device_node *np)
+static int rk_timer_probe(struct platform_device *pdev)
 {
 	if (!rk_clkevt)
-		return rk_clkevt_init(np);
+		return rk_clkevt_init(pdev);
 
 	if (!rk_clksrc)
-		return rk_clksrc_init(np);
+		return rk_clksrc_init(pdev);
 
 	pr_err("Too many timer definitions for '%s'\n", TIMER_NAME);
 	return -EINVAL;
 }
 
-TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);
-TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);
+static const struct of_device_id rk_timer_match_table[] = {
+	{ .compatible = "rockchip,rk3288-timer" },
+	{ .compatible = "rockchip,rk3399-timer" },
+	{ /* sentinel */ }
+};
+
+TIMER_PDEV_DECLARE(rk_timer, rk_timer_probe, NULL, rk_timer_match_table);
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 resend 0/7] Timer driver module support
From: Daniel Lezcano @ 2026-03-27 18:05 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support

Converting the timer driver modules requires a particular care
because, depending on the platform, that may be not supported.

A previous study showed we are safe regarding how the module refcount
is held and if THIS_MODULE is set for the clockevent and the
clocksource when they are registered.

It won't be possible to unload a module if a clockevent is registered.

It will be possible to unload a module if only a clocksource is
registered and it is not the current one.

However platforms without architected timers may need the timer driver
to be initialized very early and others can be initialized later. The
former can not be a module and the init function receives a
device_node pointer, there is no device associated and devres is not
used. That results in a lot of rollbacking code where usually it is
where we find bug and resource leaks. The latter can be converted to a
module and uses a module_platform_driver(), thus the init function is
a probe function receiving a struct platform_device pointer parameter.

We end up with two approaches and duplicate code for the init
functions. This is not optimal.

Finally, we have the driver having to be initialized very early on
some platforms and be built as a module on other platforms, resulting
on having two init functions co-existing in the same driver.

This series provides what is needed to move to the same probe function
for early init, builtin and module timers.

A new macro is introduced: TIMER_PDEV_DECLARE() and a new Kconfig
option is added CONFIG_EARLY_TIMER. TIMER_PDEV_DECLARE() will have
different behavior depending on the context:

 - The driver is a module and CONFIG_EARLY_TIMER=no
   --> the driver is a module

 - The driver is builtin and CONFIG_EARLY_TIMER=no
   --> the driver is loaded later

 - The driver is builtin or a module but CONFIG_EARLY_TIMER=yes
   --> the driver is initialized through the timer-probe function

The different timer driver framework functions have their __init
sections removed and the symbols exported in order to be compatible
with the drivers converted into modules.

The series provides a couple of drivers changed. The Mediatek as a
recent requested target which is only compiled-tested. The Rockchip
timer which was tested on a rk3588 in the three different
configurations.

Daniel Lezcano (7):
  clocksource/drivers/timer-probe: Create a platform_device before the
    framework is initialized
  drivers/clocksource/rockchip: Use the TIMER_PDEV_DECLARE() macro
  clocksource/drivers/mmio: Make the code compatible with modules
  clocksource/drivers/timer-of: Make the code compatible with modules
  clocksource/drivers/timer-probe: Add the module support for the
    TIMER_PDEV_DECLARE() macro
  clocksource/drivers/rockchip: Add rockchip timer module support
  clocksource/drivers/mediatek: Convert to module support

 drivers/clocksource/Kconfig          |   7 +-
 drivers/clocksource/mmio.c           |  11 ++-
 drivers/clocksource/timer-mediatek.c |  29 ++++++--
 drivers/clocksource/timer-of.c       |  24 ++++---
 drivers/clocksource/timer-of.h       |   5 +-
 drivers/clocksource/timer-probe.c    |  69 ++++++++++++++++--
 drivers/clocksource/timer-rockchip.c | 101 ++++++++++-----------------
 include/asm-generic/vmlinux.lds.h    |  10 +++
 include/linux/clocksource.h          |  31 ++++++++
 9 files changed, 194 insertions(+), 93 deletions(-)

-- 
2.43.0



^ permalink raw reply

* Re: [PATCH v1 0/7] Timer driver module support
From: Daniel Lezcano @ 2026-03-27 18:02 UTC (permalink / raw)
  To: Daniel Lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <20260327175533.3044-1-daniel.lezcano@kernel.org>

On 3/27/26 18:55, Daniel Lezcano wrote:
> Converting the timer driver modules requires a particular care
> because, depending on the platform, that may be not supported.

Sorry this series has been corrupted with a previous draft series.

I'll resend.


^ permalink raw reply

* Re: [PATCH v3 0/8] Bluetooth: Add MediaTek MT7927 (MT6639) support
From: Luiz Augusto von Dentz @ 2026-03-27 17:58 UTC (permalink / raw)
  To: Javier Tia
  Cc: Marcel Holtmann, Matthias Brugger, AngeloGioacchino Del Regno,
	linux-bluetooth, linux-kernel, linux-arm-kernel, linux-mediatek,
	Ryan Gilbert, Jose Tiburcio Ribeiro Netto, Llewellyn Curran,
	Chapuis Dario, Evgeny Kapusta, Nitin Gurram, Thibaut FRANCOIS,
	Ivan Lubnin
In-Reply-To: <20260326-mt7927-bt-support-v3-0-fa7ebd424323@jetm.me>

Hi Javier,

On Thu, Mar 26, 2026 at 6:13 PM Javier Tia <floss@jetm.me> wrote:
>
> This series adds Bluetooth support for the MediaTek MT7927 (Filogic 380)
> combo WiFi 7 + BT 5.4 module. The BT subsystem uses hardware variant
> 0x6639 and connects via USB.
>
> The MT7927 is shipping in motherboards and PCIe add-in cards from ASUS,
> Gigabyte, Lenovo, MSI, and TP-Link since mid-2024. Without these patches,
> users see "Unsupported hardware variant (00006639)" or the BT subsystem
> hangs during firmware download.
>
> The series consists of eight patches:
>
>   [1/8] Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support
>   [2/8] Bluetooth: btmtk: fix ISO interface setup for single alt setting
>   [3/8] Bluetooth: btusb: Add MT7927 ID for ASUS ROG Crosshair X870E Hero
>   [4/8] Bluetooth: btusb: Add MT7927 ID for Lenovo Legion Pro 7 16ARX9
>   [5/8] Bluetooth: btusb: Add MT7927 ID for Gigabyte Z790 AORUS MASTER X
>   [6/8] Bluetooth: btusb: Add MT7927 ID for MSI X870E Ace Max
>   [7/8] Bluetooth: btusb: Add MT7927 ID for TP-Link Archer TBE550E
>   [8/8] Bluetooth: btusb: Add MT7927 ID for ASUS X870E / ProArt X870E-Creator
>
> Three driver changes are needed for MT6639 (patch 1):
>
> 1. CHIPID workaround: On some boards the BT USB MMIO register reads
>    0x0000 for dev_id. Force dev_id to 0x6639 only when the USB VID/PID
>    matches a known MT6639 device, avoiding misdetection if a future
>    chip also reads zero. This follows the WiFi-side pattern.
>
> 2. Firmware naming: MT6639 uses firmware version prefix "2_1" instead of
>    "1_1" used by MT7925 and other variants. The firmware path is
>    mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin, using the mt7927
>    directory to match the WiFi firmware convention. The filename will
>    likely change to use MT7927 once MediaTek submits a dedicated
>    Linux firmware binary.
>
> 3. Section filtering: The firmware binary contains 9 sections, but only
>    sections with (dlmodecrctype & 0xff) == 0x01 are Bluetooth-related.
>    Sending WiFi/other sections causes an irreversible BT subsystem hang.
>
> Patch 2 fixes the ISO interface setup for devices that expose only a
> single alternate setting (alt 0) on the ISO endpoint. Without this fix,
> btmtk_usb_claim_iso_intf() fails with EINVAL, causing ~20 second
> initialization delays on 13d3:3588 devices.
>
> Tested on:
> - ASUS ROG Crosshair X870E Hero (USB 0489:e13a)
> - ASUS ROG STRIX X870E-E (USB 13d3:3588)
> - ASUS ROG STRIX B850-E GAMING WIFI (USB 0489:e13a)
> - Gigabyte Z790 AORUS MASTER X (USB 0489:e10f)
> - Lenovo Legion Pro 7 16ARX9 (USB 0489:e0fa)
> - MSI MEG X870E ACE MAX (USB 0489:e110)
> - TP-Link Archer TBE550E PCIe (USB 0489:e116)
>
> The firmware blob is being submitted separately to linux-firmware via
> GitLab MR !946. The firmware path has been updated to mediatek/mt7927/
> per maintainer feedback.
>
> Changes in v3 (suggested by Sean Wang):
> - Scoped CHIPID workaround to a static VID/PID table of known MT6639
>   USB devices instead of mapping all zero-CHIPID cases to 0x6639
> - Changed firmware path from mediatek/mt6639/ to mediatek/mt7927/ to
>   match the WiFi firmware convention and avoid confusion
> - Added MODULE_FIRMWARE(FIRMWARE_MT7927) for initramfs firmware discovery
> - Added Tested-by for 0489:e110 (Nitin Gurram)
>
> Changes in v2:
> - Split USB device IDs into per-device commits as requested (Luiz)
> - Added 0489:e110 (MSI X870E Ace Max, new hardware report)
> - Added ISO interface fix for single alt setting (13d3:3588 devices)
> - Added Tested-by trailers for all USB IDs
> - Added USB descriptor output to all per-device commits
> - Removed BTMTK_FIRMWARE_LOADED skip logic (Sean Wang)
>
> Link to v2: https://lore.kernel.org/linux-bluetooth/20260325-mt7927-bt-support-v2-0-b892a3252880@jetm.me/T/#t
> Link to v1: https://lore.kernel.org/linux-bluetooth/177272816248.352280.12453518046823439297@jetm.me/
>
> Signed-off-by: Javier Tia <floss@jetm.me>
> ---
> Javier Tia (8):
>       Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support
>       Bluetooth: btmtk: fix ISO interface setup for single alt setting
>       Bluetooth: btusb: Add MT7927 ID for ASUS ROG Crosshair X870E Hero
>       Bluetooth: btusb: Add MT7927 ID for Lenovo Legion Pro 7 16ARX9
>       Bluetooth: btusb: Add MT7927 ID for Gigabyte Z790 AORUS MASTER X
>       Bluetooth: btusb: Add MT7927 ID for MSI X870E Ace Max
>       Bluetooth: btusb: Add MT7927 ID for TP-Link Archer TBE550E
>       Bluetooth: btusb: Add MT7927 ID for ASUS X870E / ProArt X870E-Creator
>
>  drivers/bluetooth/btmtk.c | 56 ++++++++++++++++++++++++++++++++++++++++++++---
>  drivers/bluetooth/btmtk.h |  1 +
>  drivers/bluetooth/btusb.c | 12 ++++++++++
>  3 files changed, 66 insertions(+), 3 deletions(-)
> ---
> base-commit: 50003ce2085a7f7dacf2426065d1a69c84b5b963
> change-id: 20260305-mt7927-bt-support-6589a50c961f
>
> Best regards,
> --
> Javier Tia <floss@jetm.me>

https://sashiko.dev/#/patchset/20260326-mt7927-bt-support-v3-0-fa7ebd424323%40jetm.me

First one is more concerning since it may mean it can lead to crashes
with SDIO driver, the other comment may actually need to be addressed
separately, perhaps WBS handling needs to be fixed on this family of
controllers.

-- 
Luiz Augusto von Dentz


^ permalink raw reply

* [PATCH v1 7/7] clocksource/drivers/mediatek: Convert to module support
From: Daniel Lezcano @ 2026-03-27 17:55 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <20260327175533.3044-1-daniel.lezcano@kernel.org>

Now the TIMER_PDEV_DECLARE() allows the driver to be compiled as a
module. Add the MODULE_DESCRIPTION and the MODULE_LICENSE left for the
one converting the driver as a module.

Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/clocksource/timer-mediatek.c | 29 ++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/timer-mediatek.c b/drivers/clocksource/timer-mediatek.c
index 7bcb4a3f26fb..f5de5f397730 100644
--- a/drivers/clocksource/timer-mediatek.c
+++ b/drivers/clocksource/timer-mediatek.c
@@ -215,8 +215,7 @@ static irqreturn_t mtk_gpt_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void
-__init mtk_gpt_setup(struct timer_of *to, u8 timer, u8 option)
+static void mtk_gpt_setup(struct timer_of *to, u8 timer, u8 option)
 {
 	writel(GPT_CTRL_CLEAR | GPT_CTRL_DISABLE,
 	       timer_of_base(to) + GPT_CTRL_REG(timer));
@@ -281,7 +280,7 @@ static struct timer_of to = {
 	},
 };
 
-static int __init mtk_syst_init(struct device_node *node)
+static int mtk_syst_init(struct device_node *node)
 {
 	int ret;
 
@@ -302,7 +301,7 @@ static int __init mtk_syst_init(struct device_node *node)
 	return 0;
 }
 
-static int __init mtk_gpt_init(struct device_node *node)
+static int mtk_gpt_init(struct device_node *node)
 {
 	int ret;
 
@@ -337,5 +336,23 @@ static int __init mtk_gpt_init(struct device_node *node)
 
 	return 0;
 }
-TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_gpt_init);
-TIMER_OF_DECLARE(mtk_mt6765, "mediatek,mt6765-timer", mtk_syst_init);
+
+static int mtk_timer_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int (*probe_func)(struct device_node *node);
+
+	probe_func = of_device_get_match_data(&pdev->dev);
+
+	return probe_func(np);
+}
+
+static const struct of_device_id mtk_timer_match_table[] = {
+	{ .compatible =  "mediatek,mt6577-timer", .data = mtk_gpt_init },
+	{ .compatible =  "mediatek,mt6765-timer", .data = mtk_syst_init },
+	{ /* sentinel */ }
+};
+
+TIMER_PDEV_DECLARE(mtk_timer, mtk_timer_probe, NULL, mtk_timer_match_table);
+MODULE_DESCRIPTION("Mediatek timer driver");
+MODULE_LICENSE("GPL");
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 6/7] clocksource/drivers/rockchip: Add rockchip timer module support
From: Daniel Lezcano @ 2026-03-27 17:55 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Heiko Stuebner,
	moderated list:ARM/Rockchip SoC support,
	open list:ARM/Rockchip SoC support
In-Reply-To: <20260327175533.3044-1-daniel.lezcano@kernel.org>

Now the TIMER_PDEV_DECLARE() allows the driver to be compiled as a
module. Add the MODULE_DESCRIPTION and the MODULE_LICENSE left for the
one converting the driver as a module.

Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/clocksource/timer-rockchip.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clocksource/timer-rockchip.c b/drivers/clocksource/timer-rockchip.c
index 486bbffba464..61433b295882 100644
--- a/drivers/clocksource/timer-rockchip.c
+++ b/drivers/clocksource/timer-rockchip.c
@@ -271,3 +271,5 @@ static const struct of_device_id rk_timer_match_table[] = {
 };
 
 TIMER_PDEV_DECLARE(rk_timer, rk_timer_probe, NULL, rk_timer_match_table);
+MODULE_DESCRIPTION("Rockchip timer driver");
+MODULE_LICENSE("GPL");
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 5/7] clocksource/drivers/rockchip: Use the TIMER_PDEV_DECLARE() macro
From: Daniel Lezcano @ 2026-03-27 17:55 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Heiko Stuebner,
	moderated list:ARM/Rockchip SoC support,
	open list:ARM/Rockchip SoC support
In-Reply-To: <20260327175533.3044-1-daniel.lezcano@kernel.org>

The previous changes introduced the TIMER_PDEV_DECLARE() macro which
allows to use the platform driver to initialize a timer driver with
the benefit of having the devres to rollback automatically in case of
error.

Use this macro and change the function to rely on the devm_ variants,
allowing to cleanup the code.

Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/clocksource/timer-rockchip.c | 99 ++++++++++------------------
 1 file changed, 34 insertions(+), 65 deletions(-)

diff --git a/drivers/clocksource/timer-rockchip.c b/drivers/clocksource/timer-rockchip.c
index 540a16667145..486bbffba464 100644
--- a/drivers/clocksource/timer-rockchip.c
+++ b/drivers/clocksource/timer-rockchip.c
@@ -124,18 +124,18 @@ static u64 notrace rk_timer_sched_read(void)
 	return ~readl_relaxed(rk_clksrc->base + TIMER_CURRENT_VALUE0);
 }
 
-static int __init
-rk_timer_probe(struct rk_timer *timer, struct device_node *np)
+static int rk_timer_init(struct rk_timer *timer, struct device *dev)
 {
+	struct device_node *np = dev->of_node;
 	struct clk *timer_clk;
 	struct clk *pclk;
-	int ret = -EINVAL, irq;
+	int irq;
 	u32 ctrl_reg = TIMER_CONTROL_REG3288;
 
-	timer->base = of_iomap(np, 0);
-	if (!timer->base) {
+	timer->base = devm_of_iomap(dev, np, 0, NULL);
+	if (IS_ERR(timer->base)) {
 		pr_err("Failed to get base address for '%s'\n", TIMER_NAME);
-		return -ENXIO;
+		return PTR_ERR(timer->base);
 	}
 
 	if (of_device_is_compatible(np, "rockchip,rk3399-timer"))
@@ -143,31 +143,17 @@ rk_timer_probe(struct rk_timer *timer, struct device_node *np)
 
 	timer->ctrl = timer->base + ctrl_reg;
 
-	pclk = of_clk_get_by_name(np, "pclk");
+	pclk = devm_clk_get_enabled(dev, "pclk");
 	if (IS_ERR(pclk)) {
-		ret = PTR_ERR(pclk);
 		pr_err("Failed to get pclk for '%s'\n", TIMER_NAME);
-		goto out_unmap;
-	}
-
-	ret = clk_prepare_enable(pclk);
-	if (ret) {
-		pr_err("Failed to enable pclk for '%s'\n", TIMER_NAME);
-		goto out_unmap;
+		return PTR_ERR(pclk);
 	}
 	timer->pclk = pclk;
 
-	timer_clk = of_clk_get_by_name(np, "timer");
+	timer_clk = devm_clk_get_enabled(dev, "timer");
 	if (IS_ERR(timer_clk)) {
-		ret = PTR_ERR(timer_clk);
 		pr_err("Failed to get timer clock for '%s'\n", TIMER_NAME);
-		goto out_timer_clk;
-	}
-
-	ret = clk_prepare_enable(timer_clk);
-	if (ret) {
-		pr_err("Failed to enable timer clock\n");
-		goto out_timer_clk;
+		return PTR_ERR(timer_clk);
 	}
 	timer->clk = timer_clk;
 
@@ -175,47 +161,32 @@ rk_timer_probe(struct rk_timer *timer, struct device_node *np)
 
 	irq = irq_of_parse_and_map(np, 0);
 	if (!irq) {
-		ret = -EINVAL;
 		pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME);
-		goto out_irq;
+		return -EINVAL;
 	}
 	timer->irq = irq;
 
 	rk_timer_interrupt_clear(timer);
 	rk_timer_disable(timer);
-	return 0;
-
-out_irq:
-	clk_disable_unprepare(timer_clk);
-out_timer_clk:
-	clk_disable_unprepare(pclk);
-out_unmap:
-	iounmap(timer->base);
-
-	return ret;
-}
 
-static void __init rk_timer_cleanup(struct rk_timer *timer)
-{
-	clk_disable_unprepare(timer->clk);
-	clk_disable_unprepare(timer->pclk);
-	iounmap(timer->base);
+	return 0;
 }
 
-static int __init rk_clkevt_init(struct device_node *np)
+static int rk_clkevt_init(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	struct clock_event_device *ce;
 	int ret = -EINVAL;
 
-	rk_clkevt = kzalloc_obj(struct rk_clkevt);
+	rk_clkevt = devm_kzalloc(dev, sizeof(*rk_clkevt), GFP_KERNEL);
 	if (!rk_clkevt) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rk_timer_probe(&rk_clkevt->timer, np);
+	ret = rk_timer_init(&rk_clkevt->timer, dev);
 	if (ret)
-		goto out_probe;
+		goto out;
 
 	ce = &rk_clkevt->ce;
 	ce->name = TIMER_NAME;
@@ -233,36 +204,33 @@ static int __init rk_clkevt_init(struct device_node *np)
 	if (ret) {
 		pr_err("Failed to initialize '%s': %d\n",
 			TIMER_NAME, ret);
-		goto out_irq;
+		goto out;
 	}
 
 	clockevents_config_and_register(&rk_clkevt->ce,
 					rk_clkevt->timer.freq, 1, UINT_MAX);
 	return 0;
 
-out_irq:
-	rk_timer_cleanup(&rk_clkevt->timer);
-out_probe:
-	kfree(rk_clkevt);
 out:
 	/* Leave rk_clkevt not NULL to prevent future init */
 	rk_clkevt = ERR_PTR(ret);
 	return ret;
 }
 
-static int __init rk_clksrc_init(struct device_node *np)
+static int rk_clksrc_init(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	int ret = -EINVAL;
 
-	rk_clksrc = kzalloc_obj(struct rk_timer);
+	rk_clksrc = devm_kzalloc(dev, sizeof(*rk_clksrc), GFP_KERNEL);
 	if (!rk_clksrc) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rk_timer_probe(rk_clksrc, np);
+	ret = rk_timer_init(rk_clksrc, dev);
 	if (ret)
-		goto out_probe;
+		goto out;
 
 	rk_timer_update_counter(UINT_MAX, rk_clksrc);
 	rk_timer_enable(rk_clksrc, 0);
@@ -272,33 +240,34 @@ static int __init rk_clksrc_init(struct device_node *np)
 		clocksource_mmio_readl_down);
 	if (ret) {
 		pr_err("Failed to register clocksource\n");
-		goto out_clocksource;
+		goto out;
 	}
 
 	sched_clock_register(rk_timer_sched_read, 32, rk_clksrc->freq);
 	return 0;
 
-out_clocksource:
-	rk_timer_cleanup(rk_clksrc);
-out_probe:
-	kfree(rk_clksrc);
 out:
 	/* Leave rk_clksrc not NULL to prevent future init */
 	rk_clksrc = ERR_PTR(ret);
 	return ret;
 }
 
-static int __init rk_timer_init(struct device_node *np)
+static int rk_timer_probe(struct platform_device *pdev)
 {
 	if (!rk_clkevt)
-		return rk_clkevt_init(np);
+		return rk_clkevt_init(pdev);
 
 	if (!rk_clksrc)
-		return rk_clksrc_init(np);
+		return rk_clksrc_init(pdev);
 
 	pr_err("Too many timer definitions for '%s'\n", TIMER_NAME);
 	return -EINVAL;
 }
 
-TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);
-TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);
+static const struct of_device_id rk_timer_match_table[] = {
+	{ .compatible = "rockchip,rk3288-timer" },
+	{ .compatible = "rockchip,rk3399-timer" },
+	{ /* sentinel */ }
+};
+
+TIMER_PDEV_DECLARE(rk_timer, rk_timer_probe, NULL, rk_timer_match_table);
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 2/7] drivers/clocksource/rockchip: Use the TIMER_PDEV_DECLARE() macro
From: Daniel Lezcano @ 2026-03-27 17:55 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Heiko Stuebner,
	moderated list:ARM/Rockchip SoC support,
	open list:ARM/Rockchip SoC support
In-Reply-To: <20260327175533.3044-1-daniel.lezcano@kernel.org>

The previous change introduce the TIMER_PDEV_DECLARE() marco which
allows to use the platform driver to initialize a timer driver with
the benefit of having the devres to rollback automatically in case of
error.

Use this macro and change the function to rely on the devm_ variants,
allowing to cleanup the code.

Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/clocksource/timer-rockchip.c | 99 ++++++++++------------------
 1 file changed, 34 insertions(+), 65 deletions(-)

diff --git a/drivers/clocksource/timer-rockchip.c b/drivers/clocksource/timer-rockchip.c
index 540a16667145..486bbffba464 100644
--- a/drivers/clocksource/timer-rockchip.c
+++ b/drivers/clocksource/timer-rockchip.c
@@ -124,18 +124,18 @@ static u64 notrace rk_timer_sched_read(void)
 	return ~readl_relaxed(rk_clksrc->base + TIMER_CURRENT_VALUE0);
 }
 
-static int __init
-rk_timer_probe(struct rk_timer *timer, struct device_node *np)
+static int rk_timer_init(struct rk_timer *timer, struct device *dev)
 {
+	struct device_node *np = dev->of_node;
 	struct clk *timer_clk;
 	struct clk *pclk;
-	int ret = -EINVAL, irq;
+	int irq;
 	u32 ctrl_reg = TIMER_CONTROL_REG3288;
 
-	timer->base = of_iomap(np, 0);
-	if (!timer->base) {
+	timer->base = devm_of_iomap(dev, np, 0, NULL);
+	if (IS_ERR(timer->base)) {
 		pr_err("Failed to get base address for '%s'\n", TIMER_NAME);
-		return -ENXIO;
+		return PTR_ERR(timer->base);
 	}
 
 	if (of_device_is_compatible(np, "rockchip,rk3399-timer"))
@@ -143,31 +143,17 @@ rk_timer_probe(struct rk_timer *timer, struct device_node *np)
 
 	timer->ctrl = timer->base + ctrl_reg;
 
-	pclk = of_clk_get_by_name(np, "pclk");
+	pclk = devm_clk_get_enabled(dev, "pclk");
 	if (IS_ERR(pclk)) {
-		ret = PTR_ERR(pclk);
 		pr_err("Failed to get pclk for '%s'\n", TIMER_NAME);
-		goto out_unmap;
-	}
-
-	ret = clk_prepare_enable(pclk);
-	if (ret) {
-		pr_err("Failed to enable pclk for '%s'\n", TIMER_NAME);
-		goto out_unmap;
+		return PTR_ERR(pclk);
 	}
 	timer->pclk = pclk;
 
-	timer_clk = of_clk_get_by_name(np, "timer");
+	timer_clk = devm_clk_get_enabled(dev, "timer");
 	if (IS_ERR(timer_clk)) {
-		ret = PTR_ERR(timer_clk);
 		pr_err("Failed to get timer clock for '%s'\n", TIMER_NAME);
-		goto out_timer_clk;
-	}
-
-	ret = clk_prepare_enable(timer_clk);
-	if (ret) {
-		pr_err("Failed to enable timer clock\n");
-		goto out_timer_clk;
+		return PTR_ERR(timer_clk);
 	}
 	timer->clk = timer_clk;
 
@@ -175,47 +161,32 @@ rk_timer_probe(struct rk_timer *timer, struct device_node *np)
 
 	irq = irq_of_parse_and_map(np, 0);
 	if (!irq) {
-		ret = -EINVAL;
 		pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME);
-		goto out_irq;
+		return -EINVAL;
 	}
 	timer->irq = irq;
 
 	rk_timer_interrupt_clear(timer);
 	rk_timer_disable(timer);
-	return 0;
-
-out_irq:
-	clk_disable_unprepare(timer_clk);
-out_timer_clk:
-	clk_disable_unprepare(pclk);
-out_unmap:
-	iounmap(timer->base);
-
-	return ret;
-}
 
-static void __init rk_timer_cleanup(struct rk_timer *timer)
-{
-	clk_disable_unprepare(timer->clk);
-	clk_disable_unprepare(timer->pclk);
-	iounmap(timer->base);
+	return 0;
 }
 
-static int __init rk_clkevt_init(struct device_node *np)
+static int rk_clkevt_init(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	struct clock_event_device *ce;
 	int ret = -EINVAL;
 
-	rk_clkevt = kzalloc_obj(struct rk_clkevt);
+	rk_clkevt = devm_kzalloc(dev, sizeof(*rk_clkevt), GFP_KERNEL);
 	if (!rk_clkevt) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rk_timer_probe(&rk_clkevt->timer, np);
+	ret = rk_timer_init(&rk_clkevt->timer, dev);
 	if (ret)
-		goto out_probe;
+		goto out;
 
 	ce = &rk_clkevt->ce;
 	ce->name = TIMER_NAME;
@@ -233,36 +204,33 @@ static int __init rk_clkevt_init(struct device_node *np)
 	if (ret) {
 		pr_err("Failed to initialize '%s': %d\n",
 			TIMER_NAME, ret);
-		goto out_irq;
+		goto out;
 	}
 
 	clockevents_config_and_register(&rk_clkevt->ce,
 					rk_clkevt->timer.freq, 1, UINT_MAX);
 	return 0;
 
-out_irq:
-	rk_timer_cleanup(&rk_clkevt->timer);
-out_probe:
-	kfree(rk_clkevt);
 out:
 	/* Leave rk_clkevt not NULL to prevent future init */
 	rk_clkevt = ERR_PTR(ret);
 	return ret;
 }
 
-static int __init rk_clksrc_init(struct device_node *np)
+static int rk_clksrc_init(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	int ret = -EINVAL;
 
-	rk_clksrc = kzalloc_obj(struct rk_timer);
+	rk_clksrc = devm_kzalloc(dev, sizeof(*rk_clksrc), GFP_KERNEL);
 	if (!rk_clksrc) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rk_timer_probe(rk_clksrc, np);
+	ret = rk_timer_init(rk_clksrc, dev);
 	if (ret)
-		goto out_probe;
+		goto out;
 
 	rk_timer_update_counter(UINT_MAX, rk_clksrc);
 	rk_timer_enable(rk_clksrc, 0);
@@ -272,33 +240,34 @@ static int __init rk_clksrc_init(struct device_node *np)
 		clocksource_mmio_readl_down);
 	if (ret) {
 		pr_err("Failed to register clocksource\n");
-		goto out_clocksource;
+		goto out;
 	}
 
 	sched_clock_register(rk_timer_sched_read, 32, rk_clksrc->freq);
 	return 0;
 
-out_clocksource:
-	rk_timer_cleanup(rk_clksrc);
-out_probe:
-	kfree(rk_clksrc);
 out:
 	/* Leave rk_clksrc not NULL to prevent future init */
 	rk_clksrc = ERR_PTR(ret);
 	return ret;
 }
 
-static int __init rk_timer_init(struct device_node *np)
+static int rk_timer_probe(struct platform_device *pdev)
 {
 	if (!rk_clkevt)
-		return rk_clkevt_init(np);
+		return rk_clkevt_init(pdev);
 
 	if (!rk_clksrc)
-		return rk_clksrc_init(np);
+		return rk_clksrc_init(pdev);
 
 	pr_err("Too many timer definitions for '%s'\n", TIMER_NAME);
 	return -EINVAL;
 }
 
-TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);
-TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);
+static const struct of_device_id rk_timer_match_table[] = {
+	{ .compatible = "rockchip,rk3288-timer" },
+	{ .compatible = "rockchip,rk3399-timer" },
+	{ /* sentinel */ }
+};
+
+TIMER_PDEV_DECLARE(rk_timer, rk_timer_probe, NULL, rk_timer_match_table);
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 0/7] Timer driver module support
From: Daniel Lezcano @ 2026-03-27 17:55 UTC (permalink / raw)
  To: daniel.lezcano, tglx, zhipeng.wang_1
  Cc: shawnguo, jstultz, linux-kernel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support

Converting the timer driver modules requires a particular care
because, depending on the platform, that may be not supported.

A previous study showed we are safe regarding how the module refcount
is held and if THIS_MODULE is set for the clockevent and the
clocksource when they are registered.

It won't be possible to unload a module if a clockevent is registered.

It will be possible to unload a module if only a clocksource is
registered and it is not the current one.

However platforms without architected timers may need the timer driver
to be initialized very early and others can be initialized later. The
former can not be a module and the init function receives a
device_node pointer, there is no device associated and devres is not
used. That results in a lot of rollbacking code where usually it is
where we find bug and resource leaks. The latter can be converted to a
module and uses a module_platform_driver(), thus the init function is
a probe function receiving a struct platform_device pointer parameter.

We end up with two approaches and duplicate code for the init
functions. This is not optimal.

Finally, we have the driver having to be initialized very early on
some platforms and be built as a module on other platforms, resulting
on having two init functions co-existing in the same driver.

This series provides what is needed to move to the same probe function
for early init, builtin and module timers.

A new macro is introduced: TIMER_PDEV_DECLARE() and a new Kconfig
option is added CONFIG_EARLY_TIMER. TIMER_PDEV_DECLARE() will have
different behavior depending on the context:

 - The driver is a module and CONFIG_EARLY_TIMER=no
   --> the driver is a module

 - The driver is builtin and CONFIG_EARLY_TIMER=no
   --> the driver is loaded later

 - The driver is builtin or a module but CONFIG_EARLY_TIMER=yes
   --> the driver is initialized through the timer-probe function

The different timer driver framework functions have their __init
sections removed and the symbols exported in order to be compatible
with the drivers converted into modules.

The series provides a couple of drivers changed. The Mediatek as a
recent requested target which is only compiled-tested. The Rockchip
timer which was tested on a rk3588 in the three different
configurations.

Daniel Lezcano (7):
  clocksource/drivers/timer-probe: Create a platform_device before the
    framework is initialized
  drivers/clocksource/rockchip: Use the TIMER_PDEV_DECLARE() macro
  clocksource/drivers/mmio: Make the code compatible with modules
  clocksource/drivers/timer-of: Make the code compatible with modules
  clocksource/drivers/timer-probe: Add the module support for the
    TIMER_PDEV_DECLARE() macro
  clocksource/drivers/rockchip: Add rockchip timer module support
  clocksource/drivers/mediatek: Convert to module support

 drivers/clocksource/Kconfig          |   7 +-
 drivers/clocksource/mmio.c           |  11 ++-
 drivers/clocksource/timer-mediatek.c |  29 ++++++--
 drivers/clocksource/timer-of.c       |  24 ++++---
 drivers/clocksource/timer-of.h       |   5 +-
 drivers/clocksource/timer-probe.c    |  69 ++++++++++++++++--
 drivers/clocksource/timer-rockchip.c | 101 ++++++++++-----------------
 include/asm-generic/vmlinux.lds.h    |  10 +++
 include/linux/clocksource.h          |  31 ++++++++
 9 files changed, 194 insertions(+), 93 deletions(-)

-- 
2.43.0



^ permalink raw reply

* [PATCH v3 0/3] arm64: Add HPE GSC platform support
From: nick.hawkins @ 2026-03-27 17:44 UTC (permalink / raw)
  To: catalin.marinas, will, robh, krzk+dt, conor+dt
  Cc: nick.hawkins, linux-arm-kernel, devicetree, linux-kernel

From: Nick Hawkins <nick.hawkins@hpe.com>

Add initial platform support for the HPE GSC ARM64 BMC SoC.

Changes since v2:
- Patch 1: Removed separate ARM64/HPE GSC MAINTAINERS entry; instead
  renamed existing ARM/HPE GXP to ARM/HPE GXP/GSC and added arm64 DTS
  path there (Conor Dooley)
- Patch 2: Replaced menuconfig ARCH_HPE + nested ARCH_HPE_GSC with a
  single config ARCH_HPE; removed extra blank line (Krzysztof Kozlowski)
- Patch 3: Dropped clocks wrapper node, renamed fixed clock to
  clock-33333333; renamed ahb bus node to soc; reordered UART nodes by
  address for DTS coding style; replaced raw interrupt triplets with
  GIC_SPI/IRQ_TYPE_LEVEL_HIGH defines (Krzysztof Kozlowski)

Nick Hawkins (3):
  dt-bindings: arm: hpe,gxp: Add HPE GSC platform compatible
  arm64: Kconfig: Add ARCH_HPE platform
  arm64: dts: hpe: Add HPE GSC SoC and DL340 Gen12 board DTS

 .../devicetree/bindings/arm/hpe,gxp.yaml      |   7 +-
 MAINTAINERS                                   |   3 +-
 arch/arm64/Kconfig.platforms                  |  11 ++
 arch/arm64/boot/dts/hpe/Makefile              |   2 +
 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts    |  18 +++
 arch/arm64/boot/dts/hpe/gsc.dtsi              | 104 ++++++++++++++++++
 6 files changed, 143 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/boot/dts/hpe/Makefile
 create mode 100644 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
 create mode 100644 arch/arm64/boot/dts/hpe/gsc.dtsi

-- 
2.34.1



^ permalink raw reply

* [PATCH v3 3/3] arm64: dts: hpe: Add HPE GSC SoC and DL340 Gen12 board DTS
From: nick.hawkins @ 2026-03-27 17:44 UTC (permalink / raw)
  To: catalin.marinas, will, robh, krzk+dt, conor+dt
  Cc: nick.hawkins, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260327174445.3275835-1-nick.hawkins@hpe.com>

From: Nick Hawkins <nick.hawkins@hpe.com>

Add SoC-level DTSI for the HPE GSC ARM64 BMC SoC, covering the CPU
cluster, GIC v3 interrupt controller, ARM64 generic timer, and console
UART.

Add the board-level DTS for the HPE DL340 Gen12, which includes
gsc.dtsi and adds memory and chosen nodes.

Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
---
 arch/arm64/boot/dts/hpe/Makefile           |   2 +
 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts |  18 ++++
 arch/arm64/boot/dts/hpe/gsc.dtsi           | 104 +++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 arch/arm64/boot/dts/hpe/Makefile
 create mode 100644 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
 create mode 100644 arch/arm64/boot/dts/hpe/gsc.dtsi

diff --git a/arch/arm64/boot/dts/hpe/Makefile b/arch/arm64/boot/dts/hpe/Makefile
new file mode 100644
index 000000000000..6b547b8a8154
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+dtb-$(CONFIG_ARCH_HPE) += gsc-dl340gen12.dtb
diff --git a/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts b/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
new file mode 100644
index 000000000000..42cfeac99029
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/dts-v1/;
+
+#include "gsc.dtsi"
+
+/ {
+	compatible = "hpe,gsc-dl340gen12", "hpe,gsc";
+	model = "HPE ProLiant DL340 Gen12";
+
+	chosen {
+		stdout-path = &uartc;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/hpe/gsc.dtsi b/arch/arm64/boot/dts/hpe/gsc.dtsi
new file mode 100644
index 000000000000..087688b089e9
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/gsc.dtsi
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for HPE GSC
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0xa0008048>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0xa0008048>;
+		};
+	};
+
+	osc: clock-33333333 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-output-names = "osc";
+		clock-frequency = <33333333>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-parent = <&gic>;
+	};
+
+	soc: soc@80000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x80000000 0x80000000>;
+		ranges;
+
+		gic: gic@ce000000 {
+			compatible = "arm,gic-v3";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			redistributor-stride = <0x0 0x20000>;
+			#redistributor-regions = <1>;
+			reg = <0xce000000 0x10000>,
+			      <0xce060000 0x40000>,
+			      <0xce200000 0x40000>;
+		};
+
+		uarta: serial@c00000e0 {
+			compatible = "ns16550a";
+			reg = <0xc00000e0 0x8>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-parent = <&gic>;
+			clock-frequency = <1846153>;
+			reg-shift = <0>;
+		};
+
+		uartb: serial@c00000e8 {
+			compatible = "ns16550a";
+			reg = <0xc00000e8 0x8>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-parent = <&gic>;
+			clock-frequency = <1846153>;
+			reg-shift = <0>;
+		};
+
+		uartc: serial@c00000f0 {
+			compatible = "ns16550a";
+			reg = <0xc00000f0 0x8>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-parent = <&gic>;
+			clock-frequency = <1846153>;
+			reg-shift = <0>;
+		};
+
+		uarte: serial@c00003e0 {
+			compatible = "ns16550a";
+			reg = <0xc00003e0 0x8>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-parent = <&gic>;
+			clock-frequency = <1846153>;
+			reg-shift = <0>;
+		};
+	};
+};
-- 
2.34.1



^ permalink raw reply related

* [PATCH v3 1/3] dt-bindings: arm: hpe,gxp: Add HPE GSC platform compatible
From: nick.hawkins @ 2026-03-27 17:44 UTC (permalink / raw)
  To: catalin.marinas, will, robh, krzk+dt, conor+dt
  Cc: nick.hawkins, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260327174445.3275835-1-nick.hawkins@hpe.com>

From: Nick Hawkins <nick.hawkins@hpe.com>

Add the HPE GSC ARM64 BMC SoC compatibles to the existing
hpe,gxp.yaml binding.

The initial board compatible is hpe,gsc-dl340gen12 for the DL340 Gen12
server platform.

Add the arm64 DTS path to the existing ARM/HPE GXP MAINTAINERS entry,
renamed to ARM/HPE GXP/GSC ARCHITECTURE.

Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
---
 Documentation/devicetree/bindings/arm/hpe,gxp.yaml | 7 ++++++-
 MAINTAINERS                                        | 3 ++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/hpe,gxp.yaml b/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
index 224bbcb93f95..6f057cd58571 100644
--- a/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
+++ b/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/arm/hpe,gxp.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: HPE BMC GXP platforms
+title: HPE BMC GXP and GSC platforms
 
 maintainers:
   - Nick Hawkins <nick.hawkins@hpe.com>
@@ -18,6 +18,11 @@ properties:
           - enum:
               - hpe,gxp-dl360gen10
           - const: hpe,gxp
+      - description: GSC Based Boards
+        items:
+          - enum:
+              - hpe,gsc-dl340gen12
+          - const: hpe,gsc
 
 required:
   - compatible
diff --git a/MAINTAINERS b/MAINTAINERS
index 2265e2c9bfbe..80c66de5e342 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2859,7 +2859,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:	arch/arm/mach-sa1100/include/mach/jornada720.h
 F:	arch/arm/mach-sa1100/jornada720.c
 
-ARM/HPE GXP ARCHITECTURE
+ARM/HPE GXP/GSC ARCHITECTURE
 M:	Jean-Marie Verdun <verdun@hpe.com>
 M:	Nick Hawkins <nick.hawkins@hpe.com>
 S:	Maintained
@@ -2870,6 +2870,7 @@ F:	Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
 F:	Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
 F:	Documentation/hwmon/gxp-fan-ctrl.rst
 F:	arch/arm/boot/dts/hpe/
+F:	arch/arm64/boot/dts/hpe/
 F:	drivers/clocksource/timer-gxp.c
 F:	drivers/hwmon/gxp-fan-ctrl.c
 F:	drivers/i2c/busses/i2c-gxp.c
-- 
2.34.1



^ permalink raw reply related

* [PATCH v3 2/3] arm64: Kconfig: Add ARCH_HPE platform
From: nick.hawkins @ 2026-03-27 17:44 UTC (permalink / raw)
  To: catalin.marinas, will, robh, krzk+dt, conor+dt
  Cc: nick.hawkins, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260327174445.3275835-1-nick.hawkins@hpe.com>

From: Nick Hawkins <nick.hawkins@hpe.com>

Add the ARCH_HPE config for HPE ARM64 BMC SoCs to Kconfig.platforms.

Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
---
 arch/arm64/Kconfig.platforms | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 54eb1d7fd419..b4217809c774 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -168,6 +168,17 @@ config ARCH_HISI
 	help
 	  This enables support for Hisilicon ARMv8 SoC family
 
+config ARCH_HPE
+	bool "HPE SoC Support"
+	select PINCTRL
+	select GENERIC_IRQ_CHIP
+	select CLKSRC_MMIO
+	help
+	  This enables support for HPE ARM-based SoC chips used
+	  on HPE servers. HPE SoCs serve as the Baseboard
+	  Management Controller (BMC) providing out-of-band server
+	  management.
+
 config ARCH_KEEMBAY
 	bool "Keem Bay SoC"
 	help
-- 
2.34.1



^ permalink raw reply related

* Re: [RFT PATCH v3] ARM: omap1: enable real software node lookup of GPIOs on Nokia 770
From: Bartosz Golaszewski @ 2026-03-27 17:27 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Janusz Krzysztofik, Arnd Bergmann, Bartosz Golaszewski,
	Tony Lindgren, Russell King, Dmitry Torokhov, Hans de Goede,
	Linux-OMAP, linux-arm-kernel, linux-kernel, Kevin Hilman,
	Aaro Koskinen, Andy Shevchenko
In-Reply-To: <CAMRc=McVPskF4pMQSz=hR8CkyZhoPmCU_yJFT66vgTCPJd3-Vw@mail.gmail.com>

On Fri, 27 Mar 2026 18:23:29 +0100, Bartosz Golaszewski <brgl@kernel.org> said:
> On Fri, Mar 27, 2026 at 5:59 PM Aaro Koskinen <aaro.koskinen@iki.fi> wrote:
>>
>> Hi,
>>
>> On Fri, Mar 27, 2026 at 03:22:12PM +0100, Bartosz Golaszewski wrote:
>> > Hmm, I'm wondering if there's a race with consumers already requesting
>> > the GPIOs after the controller device is registered but before the
>> > software node is added. I'll send a version with software nodes being
>> > registered first, then passes as firmware nodes to the platform device
>> > API before the device is registered.
>>
>> It crashes early, I was able to get an UART log from OSK (another
>> 16xx board):
>>
>> [    1.001525] Register r12 information: 2-page vmalloc region starting at 0xc2808000 allocated at kernel_clone+0xa4/0x20c
>> [    1.013092] Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
>> [    1.019500] Stack: (0xc2809ed0 to 0xc280a000)
>> [    1.024230] 9ec0:                                     c072d000 c0529474 c06b3aa0 c050a3cc
>> [    1.032958] 9ee0: c072d000 c085c000 00000002 c052582c c050a324 c072d000 00000000 c0503160
>> [    1.041687] 9f00: 00002710 00000000 c04da8f8 c0060900 c2809f64 ffffffff 00010000 946f70b5
>> [    1.050384] 9f20: 00000062 c0816120 00000002 c052582c c0525848 c072d000 c04da8f8 c0060a18
>> [    1.059112] 9f40: c2809f64 c2809f64 00000000 946f70b5 00000062 c0816120 00000002 c052582c
>> [    1.067810] 9f60: c052584c c072d000 c04da8f8 c050352c 00000002 00000002 00000000 c0502400
>> [    1.076507] 9f80: c2809f7c 00000000 c03f86f4 00000000 00000000 00000000 00000000 00000000
>> [    1.085205] 9fa0: 00000000 c03f8704 00000000 c000850c 00000000 00000000 00000000 00000000
>> [    1.093902] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>> [    1.102600] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
>> [    1.111206] Call trace:
>> [    1.111328]  software_node_to_swnode from device_add_software_node+0x20/0x80
>> [    1.121704]  device_add_software_node from omap16xx_gpio_init+0xa8/0xe4
>> [    1.128997]  omap16xx_gpio_init from do_one_initcall+0x68/0x1f4
>> [    1.135620]  do_one_initcall from kernel_init_freeable+0x1ec/0x240
>> [    1.142517]  kernel_init_freeable from kernel_init+0x10/0x108
>> [    1.148864]  kernel_init from ret_from_fork+0x14/0x28
>> [    1.154357] Exception stack(0xc2809fb0 to 0xc2809ff8)
>> [    1.159820] 9fa0:                                     00000000 00000000 00000000 00000000
>> [    1.168518] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>> [    1.177185] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
>> [    1.184295] Code: e3500000 012fff1e e59f3034 e5932000 (e5923000)
>> [    1.191040] ---[ end trace 0000000000000000 ]---
>> [    1.196350] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
>> [    1.204559] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
>>
>
> Thanks. This makes sense. Both omap16xx_gpio_init() and
> software_node_init() run as postcore_initcall() so if the order is not
> right, it will fail.
>
> Cc'ing Andy who's a reviewer for software nodes. Andy: is there any
> reason to run software_node_init() as a postcore initcall? It only
> allocates the kset, can we move it to core_initcall() by any chance?
>
> Bart
>

In any case, Aaro: the following should theoretically fix it:

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 51320837f3a9..5ba904f8a08a 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -1134,7 +1134,7 @@ static int __init software_node_init(void)
 		return -ENOMEM;
 	return 0;
 }
-postcore_initcall(software_node_init);
+core_initcall(software_node_init);

 static void __exit software_node_exit(void)
 {

If you could give it a spin and let me know if it does, it would be awesome.

Bart


^ permalink raw reply related

* Re: [RFT PATCH v3] ARM: omap1: enable real software node lookup of GPIOs on Nokia 770
From: Bartosz Golaszewski @ 2026-03-27 17:23 UTC (permalink / raw)
  To: Aaro Koskinen, Andy Shevchenko
  Cc: Janusz Krzysztofik, Arnd Bergmann, Bartosz Golaszewski,
	Tony Lindgren, Russell King, Dmitry Torokhov, Hans de Goede,
	Linux-OMAP, linux-arm-kernel, linux-kernel, Kevin Hilman
In-Reply-To: <aca3ajb_G3gD24S7@darkstar.musicnaut.iki.fi>

On Fri, Mar 27, 2026 at 5:59 PM Aaro Koskinen <aaro.koskinen@iki.fi> wrote:
>
> Hi,
>
> On Fri, Mar 27, 2026 at 03:22:12PM +0100, Bartosz Golaszewski wrote:
> > Hmm, I'm wondering if there's a race with consumers already requesting
> > the GPIOs after the controller device is registered but before the
> > software node is added. I'll send a version with software nodes being
> > registered first, then passes as firmware nodes to the platform device
> > API before the device is registered.
>
> It crashes early, I was able to get an UART log from OSK (another
> 16xx board):
>
> [    1.001525] Register r12 information: 2-page vmalloc region starting at 0xc2808000 allocated at kernel_clone+0xa4/0x20c
> [    1.013092] Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
> [    1.019500] Stack: (0xc2809ed0 to 0xc280a000)
> [    1.024230] 9ec0:                                     c072d000 c0529474 c06b3aa0 c050a3cc
> [    1.032958] 9ee0: c072d000 c085c000 00000002 c052582c c050a324 c072d000 00000000 c0503160
> [    1.041687] 9f00: 00002710 00000000 c04da8f8 c0060900 c2809f64 ffffffff 00010000 946f70b5
> [    1.050384] 9f20: 00000062 c0816120 00000002 c052582c c0525848 c072d000 c04da8f8 c0060a18
> [    1.059112] 9f40: c2809f64 c2809f64 00000000 946f70b5 00000062 c0816120 00000002 c052582c
> [    1.067810] 9f60: c052584c c072d000 c04da8f8 c050352c 00000002 00000002 00000000 c0502400
> [    1.076507] 9f80: c2809f7c 00000000 c03f86f4 00000000 00000000 00000000 00000000 00000000
> [    1.085205] 9fa0: 00000000 c03f8704 00000000 c000850c 00000000 00000000 00000000 00000000
> [    1.093902] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [    1.102600] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
> [    1.111206] Call trace:
> [    1.111328]  software_node_to_swnode from device_add_software_node+0x20/0x80
> [    1.121704]  device_add_software_node from omap16xx_gpio_init+0xa8/0xe4
> [    1.128997]  omap16xx_gpio_init from do_one_initcall+0x68/0x1f4
> [    1.135620]  do_one_initcall from kernel_init_freeable+0x1ec/0x240
> [    1.142517]  kernel_init_freeable from kernel_init+0x10/0x108
> [    1.148864]  kernel_init from ret_from_fork+0x14/0x28
> [    1.154357] Exception stack(0xc2809fb0 to 0xc2809ff8)
> [    1.159820] 9fa0:                                     00000000 00000000 00000000 00000000
> [    1.168518] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [    1.177185] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> [    1.184295] Code: e3500000 012fff1e e59f3034 e5932000 (e5923000)
> [    1.191040] ---[ end trace 0000000000000000 ]---
> [    1.196350] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
> [    1.204559] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
>

Thanks. This makes sense. Both omap16xx_gpio_init() and
software_node_init() run as postcore_initcall() so if the order is not
right, it will fail.

Cc'ing Andy who's a reviewer for software nodes. Andy: is there any
reason to run software_node_init() as a postcore initcall? It only
allocates the kset, can we move it to core_initcall() by any chance?

Bart


^ permalink raw reply

* Re: (subset) [PATCH v17 0/8] support FEAT_LSUI
From: Catalin Marinas @ 2026-03-27 17:18 UTC (permalink / raw)
  To: Yeoreum Yun
  Cc: linux-arm-kernel, linux-kernel, kvmarm, kvm, linux-kselftest,
	will, maz, oupton, miko.lenczewski, kevin.brodsky, broonie, ardb,
	suzuki.poulose, lpieralisi, joey.gouly, yuzenghui
In-Reply-To: <acaMex3Pq13njdRt@e129823.arm.com>

On Fri, Mar 27, 2026 at 01:56:11PM +0000, Yeoreum Yun wrote:
> > I decided to drop patch [6/8] (arm64: armv8_deprecated: disable swp
> > emulation when FEAT_LSUI present). The way FEAT_LSUI support looks now,
> > we still have uaccess_enable_privileged() working properly and we could
> > even support SWP emulation using exclusives. While it's highly unlikely
> > to see both 32-bit EL0 and FEAT_LSUI in practice,
> 
> This is one of decisive reason to drop the swp emulation with LSUI
> (https://lore.kernel.org/all/aXDbBKhE1SdCW6q4@willie-the-truck/)

Ah, I forgot about this discussion. It's a valid point, I just thought
it's unnecessary given that __uaccess_disable_hw_pan() still works.

If we want strict no PAN, I can add it back (really small patch). I
wonder whether we should also add a
WARN_ON_ONCE(cpus_have_final_cap(ARM64_HAS_LSUI)) to the pan disabling
function. Not urgent though.

-- 
Catalin


^ permalink raw reply

* Re: [PATCH v1 1/1] arm64: dts: imx91-var-dart-sonata: add RGB select supply for PCA6408
From: Stefano Radaelli @ 2026-03-27 17:16 UTC (permalink / raw)
  To: Frank Li
  Cc: linux-kernel, devicetree, imx, linux-arm-kernel, pierluigi.p,
	Stefano Radaelli, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
In-Reply-To: <aca1jdx0DjmmHqFk@lizhi-Precision-Tower-5810>

Hi Frank,

On Fri, Mar 27, 2026 at 12:51:25PM -0400, Frank Li wrote:
> On Fri, Mar 27, 2026 at 05:32:43PM +0100, Stefano Radaelli wrote:
> > From: Stefano Radaelli <stefano.r@variscite.com>
> >
> > RGB_SEL controls the routing of some carrier board lines on the Sonata
> > board. The two PCA6408 GPIO expanders depend on that path being enabled,
> > so describe the selector as a fixed regulator and use it as their
> > vcc-supply.
> 
> Does below resolve your problem?
>  https://lore.kernel.org/imx/20260325-pinctrl-mux-v4-0-043c2c82e623@nxp.com/
> 
> So needn't hack select as regualtor
> 

Thanks for pointing me your patch, interesting improvement!

Actually, in this case RGB_SEL is not meant to model a selectable mux
on the Sonata carrier.
On this board it must stay asserted permanently, otherwise the
downstream path to the two PCA6408 expanders is not accessible.

Modeling it as a mux might be confusing for users of the DART-MX91, as
as it would suggest that the routing is configurable, while on this
board it is actually fixed.

Best Regards,
Stefano


^ permalink raw reply

* [PATCH] ARM: OMAP1: Fix DEBUG_LL and earlyprintk on OMAP16XX
From: Aaro Koskinen @ 2026-03-27 17:15 UTC (permalink / raw)
  To: Janusz Krzysztofik, Tony Lindgren, Kevin Hilman, linux-omap
  Cc: linux-arm-kernel, linux-kernel

On OMAP16XX, the UART enable bit shifts are written instead of the actual
bits. This breaks the boot when DEBUG_LL and earlyprintk is enabled;
the UART gets disabled and some random bits get enabled. Fix that.

Fixes: 34c86239b184 ("ARM: OMAP1: clock: Fix early UART rate issues")
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
---
 arch/arm/mach-omap1/clock_data.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index c58d200e4816..5203b047deac 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -700,8 +700,8 @@ int __init omap1_clk_init(void)
 	/* Make sure UART clocks are enabled early */
 	if (cpu_is_omap16xx())
 		omap_writel(omap_readl(MOD_CONF_CTRL_0) |
-			    CONF_MOD_UART1_CLK_MODE_R |
-			    CONF_MOD_UART3_CLK_MODE_R, MOD_CONF_CTRL_0);
+			    (1 << CONF_MOD_UART1_CLK_MODE_R) |
+			    (1 << CONF_MOD_UART3_CLK_MODE_R), MOD_CONF_CTRL_0);
 #endif
 
 	/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
-- 
2.39.2



^ permalink raw reply related

* Re: [PATCH v4 3/7] pinctrl: extract pinctrl_generic_to_map() from pinctrl_generic_pins_function_dt_node_to_map()
From: Conor Dooley @ 2026-03-27 17:14 UTC (permalink / raw)
  To: Frank Li
  Cc: Peter Rosin, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rafał Miłecki, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
	devicetree, imx, linux-arm-kernel, Haibo Chen
In-Reply-To: <aca2UquiW9lFikhR@lizhi-Precision-Tower-5810>

[-- Attachment #1: Type: text/plain, Size: 4641 bytes --]

On Fri, Mar 27, 2026 at 12:54:42PM -0400, Frank Li wrote:
> On Fri, Mar 27, 2026 at 12:09:32AM +0000, Conor Dooley wrote:
> > On Wed, Mar 25, 2026 at 07:04:12PM -0400, Frank Li wrote:
> > > Refactor pinctrl_generic_pins_function_dt_subnode_to_map() by separating DT
> > > parsing logic from map creation. Introduce a new helper
> > > pinctrl_generic_to_map() to handle mapping to kernel data structures, while
> > > keeping DT property parsing in the subnode function.
> > >
> > > Improve code structure and enables easier reuse for platforms using
> > > different DT properties (e.g. pinmux) without modifying the
> > > dt_node_to_map-style callback API. Avoid unnecessary coupling to
> > > pinctrl_generic_pins_function_dt_node_to_map(), which provides
> > > functionality not needed when the phandle target is unambiguous.
> > >
> > > Maximize code reuse and provide a cleaner extension point for future
> > > pinctrl drivers.
> > >
> > > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > > ---
> > > change in v4
> > > - new patch
> > > ---
> > >  drivers/pinctrl/pinconf.h         | 18 ++++++++
> > >  drivers/pinctrl/pinctrl-generic.c | 91 ++++++++++++++++++++++++---------------
> > >  2 files changed, 74 insertions(+), 35 deletions(-)
> > >
> > > diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
> > > index 2880adef476e68950ffdd540ea42cdee6a16ec27..ffdabddb9660324ed8886a2e8dcacff7e1c6c529 100644
> > > --- a/drivers/pinctrl/pinconf.h
> > > +++ b/drivers/pinctrl/pinconf.h
> > > @@ -166,6 +166,13 @@ int pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev,
> > >  						 struct device_node *np,
> > >  						 struct pinctrl_map **maps,
> > >  						 unsigned int *num_maps);
> > > +
> > > +int
> > > +pinctrl_generic_to_map(struct pinctrl_dev *pctldev, struct device_node *parent,
> > > +		       struct device_node *np, struct pinctrl_map **maps,
> > > +		       unsigned int *num_maps, unsigned int *num_reserved_maps,
> > > +		       const char **group_name, unsigned int ngroups,
> > > +		       const char **functions, unsigned int *pins);
> > >  #else
> > >  static inline int
> > >  pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev,
> > > @@ -175,4 +182,15 @@ pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev,
> > >  {
> > >  	return -ENOTSUPP;
> > >  }
> > > +
> > > +static inline int
> > > +pinctrl_generic_to_map(struct pinctrl_dev *pctldev, struct device_node *parent,
> > > +		       struct device_node *np, struct pinctrl_map **maps,
> > > +		       unsigned int *num_maps, unsigned int *num_reserved_maps,
> > > +		       const char **group_name, unsigned int ngroups,
> > > +		       const char **functions, unsigned int *pins,
> > > +		       void *function_data)
> > > +{
> > > +	return -ENOTSUPP;
> > > +}
> > >  #endif
> > > diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
> > > index efb39c6a670331775855efdc8566102b5c6202ef..20a216ae63e91b69985ea4cfcd0b57103c6ca950 100644
> > > --- a/drivers/pinctrl/pinctrl-generic.c
> > > +++ b/drivers/pinctrl/pinctrl-generic.c
> > > @@ -17,29 +17,18 @@
> > >  #include "pinctrl-utils.h"
> > >  #include "pinmux.h"
> > >
> > > -static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
> > > -							   struct device_node *parent,
> > > -							   struct device_node *np,
> > > -							   struct pinctrl_map **maps,
> > > -							   unsigned int *num_maps,
> > > -							   unsigned int *num_reserved_maps,
> > > -							   const char **group_names,
> > > -							   unsigned int ngroups)
> > > +int
> > > +pinctrl_generic_to_map(struct pinctrl_dev *pctldev, struct device_node *parent,
> > > +		       struct device_node *np, struct pinctrl_map **maps,
> > > +		       unsigned int *num_maps, unsigned int *num_reserved_maps,
> > > +		       const char **group_names, unsigned int ngroups,
> > > +		       const char **functions, unsigned int *pins)
> >
> > npins needs to be an argument to this function also, otherwise
> > pinctrl_generic_add_group() uses it uninitialised...
> 
> Is this one the root cause of then broken?

No, this is not the cause of the breakage. I can't believe I still have
to say that. Go read the code and you'll see why that allocation thing
is problematic.

> I am not sure why compiler have not report waring for it.

It did, that's how I found it. Used uninitialised warnings are normally
from clang, so your toolchain might not have seen it. clangd integration
with my editor is how I saw it.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: Warning from free_reserved_area() in next-20260325+
From: Mike Rapoport @ 2026-03-27 17:12 UTC (permalink / raw)
  To: Bert Karwatzki
  Cc: linux-kernel, Liam.Howlett, akpm, andreas, ardb, bp, brauner,
	catalin.marinas, chleroy, dave.hansen, davem, david, devicetree,
	dvyukov, elver, glider, hannes, hpa, ilias.apalodimas, iommu,
	jack, jackmanb, kasan-dev, linux-arm-kernel, linux-efi,
	linux-fsdevel, linux-mm, linux-trace-kernel, linuxppc-dev,
	lorenzo.stoakes, m.szyprowski, maddy, mhiramat, mhocko, mingo,
	mpe, npiggin, robh, robin.murphy, saravanak, sparclinux, surenb,
	tglx, vbabka, viro, will, x86, ziy
In-Reply-To: <20260327140109.7561-1-spasswolf@web.de>

Hi Bert,

On Fri, Mar 27, 2026 at 03:01:08PM +0100, Bert Karwatzki wrote:
> Starting with linux next-20260325 I see the following warning early in the
> boot process of a machine running debian stable (trixie) (except for the kernel):

Thanks for the report!

> [    0.027118] [      T0] ------------[ cut here ]------------
> [    0.027118] [      T0] Cannot free reserved memory because of deferred initialization of the memory map
> [    0.027119] [      T0] WARNING: mm/memblock.c:904 at __free_reserved_area+0xa9/0xc0, CPU#0: swapper/0/0
> [    0.027122] [      T0] Modules linked in:
> [    0.027123] [      T0] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.0.0-rc5-next-20260326-master #385 PREEMPT_RT 
> [    0.027125] [      T0] Hardware name: ASUS System Product Name/ROG STRIX B850-F GAMING WIFI, BIOS 1627 02/05/2026
> [    0.027125] [      T0] RIP: 0010:__free_reserved_area+0xa9/0xc0
> [    0.027126] [      T0] Code: 48 89 df 48 89 ee e8 06 fe ff ff 48 89 c3 48 39 e8 72 a0 5b 4c 89 e8 5d 41 5c 41 5d 41 5e c3 cc cc cc cc 48 8d 3d 97 c2 c6 00 <67> 48 0f b9 3a 45 31 ed eb df 66 66 2e 0f 1f 84 00 00 00 00 00 66
> [    0.027127] [      T0] RSP: 0000:ffffffff9b203e98 EFLAGS: 00010202
> [    0.027128] [      T0] RAX: 0000000e91c00001 RBX: ffffffff9b100c0f RCX: 0000000080000001
> [    0.027128] [      T0] RDX: 00000000000000cc RSI: 0000000e2d42d000 RDI: ffffffff9b32ef60
> [    0.027128] [      T0] RBP: ffff9eeafdd6fbc0 R08: 0000000000000000 R09: 0000000000000001
> [    0.027129] [      T0] R10: 0000000000001000 R11: 8000000000000163 R12: 000000000000006f
> [    0.027129] [      T0] R13: 0000000000000000 R14: 0000000000000045 R15: 000000005c8a1000
> [    0.027129] [      T0] FS:  0000000000000000(0000) GS:ffff9eeb21c05000(0000) knlGS:0000000000000000
> [    0.027130] [      T0] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [    0.027130] [      T0] CR2: ffff9ee8ad801000 CR3: 0000000e2ce1e000 CR4: 0000000000f50ef0
> [    0.027131] [      T0] PKRU: 55555554
> [    0.027131] [      T0] Call Trace:
> [    0.027132] [      T0]  <TASK>
> [    0.027132] [      T0]  free_reserved_area+0x89/0xd0
> [    0.027133] [      T0]  alternative_instructions+0xee/0x110
> [    0.027136] [      T0]  arch_cpu_finalize_init+0x10f/0x160
> [    0.027138] [      T0]  start_kernel+0x686/0x710
> [    0.027140] [      T0]  x86_64_start_reservations+0x24/0x30
> [    0.027141] [      T0]  x86_64_start_kernel+0xd4/0xe0
> [    0.027142] [      T0]  common_startup_64+0x13e/0x141
> [    0.027143] [      T0]  </TASK>
> [    0.027144] [      T0] ---[ end trace 0000000000000000 ]---

Does this patch fix it for you?

diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index e87da25d1236..62936a3bde19 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -2448,19 +2448,31 @@ void __init alternative_instructions(void)
 					    __smp_locks, __smp_locks_end,
 					    _text, _etext);
 	}
+#endif
 
+	restart_nmi();
+	alternatives_patched = 1;
+
+	alt_reloc_selftest();
+}
+
+#ifdef CONFIG_SMP
+/*
+ * With CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled we can free_init_pages() only
+ * after the deferred initialization of the memory map is complete.
+ */
+static int __init free_smp_locks(void)
+{
 	if (!uniproc_patched || num_possible_cpus() == 1) {
 		free_init_pages("SMP alternatives",
 				(unsigned long)__smp_locks,
 				(unsigned long)__smp_locks_end);
 	}
-#endif
 
-	restart_nmi();
-	alternatives_patched = 1;
-
-	alt_reloc_selftest();
+	return 0;
 }
+arch_initcall(free_smp_locks);
+#endif
 
 /**
  * text_poke_early - Update instructions on a live kernel at boot time
 
> Bert Karwatzki

-- 
Sincerely yours,
Mike.


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox