* [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init
@ 2026-06-10 17:53 Stephan Gerhold
2026-06-10 17:53 ` [PATCH 1/2] clocksource/drivers/arm_arch_timer_mmio: Refactor " Stephan Gerhold
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Stephan Gerhold @ 2026-06-10 17:53 UTC (permalink / raw)
To: Mark Rutland, Marc Zyngier, Daniel Lezcano, Thomas Gleixner,
Sudeep Holla
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Jack Matthews
Jack reported a regression for some single-core Qualcomm platforms (e.g.
MDM9625, MDM9607) that no longer boot because no timers can be found during
early boot [1]. These platforms rely on an obscure timer setup where the
global Arm MMIO timer (arm,armv7-timer-mem) is used as the only available
timer for the CPU. This setup used to work fine until commit 0f67b56d84b4
("clocksource/drivers/arm_arch_timer_mmio: Switch over to standalone
driver") when the early timer initialization using TIMER_OF_DECLARE() was
removed when moving to the standalone MMIO driver.
There doesn't seem to be any other usable CPU timer on those platforms, so
this series restores the early timer support using TIMER_OF_DECLARE()
inside the new standalone arm_arch_timer_mmio driver. This is pretty ugly,
but I could not think of a better solution so far. I tried to keep the
ugliness for the two probe paths as limited as possible. :-)
If someone has a better idea how to solve this, I would be happy to try it.
[1]: https://lore.kernel.org/r/46A20F89-E208-4091-8B6E-B5C38BF82B42@jackmatthe.ws/
Signed-off-by: Stephan Gerhold <stephan.gerhold@linaro.org>
---
Stephan Gerhold (2):
clocksource/drivers/arm_arch_timer_mmio: Refactor for early init
clocksource/drivers/arm_arch_timer_mmio: Restore support for early init
drivers/clocksource/arm_arch_timer_mmio.c | 180 ++++++++++++++++++++----------
1 file changed, 123 insertions(+), 57 deletions(-)
---
base-commit: 49e02880ec0a8c378e811bc9d85da188d7c6204c
change-id: 20260609-arm-arch-timer-mmio-early-de97155938e4
Best regards,
--
Stephan Gerhold <stephan.gerhold@linaro.org>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 1/2] clocksource/drivers/arm_arch_timer_mmio: Refactor for early init 2026-06-10 17:53 [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init Stephan Gerhold @ 2026-06-10 17:53 ` Stephan Gerhold 2026-06-10 17:53 ` [PATCH 2/2] clocksource/drivers/arm_arch_timer_mmio: Restore support " Stephan Gerhold 2026-06-11 7:59 ` [PATCH 0/2] " Marc Zyngier 2 siblings, 0 replies; 6+ messages in thread From: Stephan Gerhold @ 2026-06-10 17:53 UTC (permalink / raw) To: Mark Rutland, Marc Zyngier, Daniel Lezcano, Thomas Gleixner, Sudeep Holla Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Jack Matthews In preparation of restoring support for using arm,armv7-timer-mem as an early timer, refactor the driver to allow early initialization without a device pointer. Replace uses of dev_() logging with pr_(), replace devm helpers with manual cleanup or scope-based cleanup helpers where possible. Create a new arch_timer_mmio_init() function that performs the initialization and registration without a device pointer. This is not very pretty, although given that the driver cannot be removed at runtime due to .suppress_bind_attrs = true, at least the overhead for the manual resource management is limited. Signed-off-by: Stephan Gerhold <stephan.gerhold@linaro.org> --- drivers/clocksource/arm_arch_timer_mmio.c | 139 +++++++++++++++++------------- 1 file changed, 79 insertions(+), 60 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer_mmio.c b/drivers/clocksource/arm_arch_timer_mmio.c index d10362692fdd..5cb94051c4be 100644 --- a/drivers/clocksource/arm_arch_timer_mmio.c +++ b/drivers/clocksource/arm_arch_timer_mmio.c @@ -10,7 +10,9 @@ #define pr_fmt(fmt) "arch_timer_mmio: " fmt +#include <linux/cleanup.h> #include <linux/clockchips.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/io-64-nonatomic-lo-hi.h> #include <linux/of_irq.h> @@ -191,17 +193,16 @@ static irqreturn_t arch_timer_mmio_handler(int irq, void *dev_id) return IRQ_NONE; } -static struct arch_timer_mem_frame *find_best_frame(struct platform_device *pdev) +static struct arch_timer_mem_frame *find_best_frame(struct arch_timer *at) { struct arch_timer_mem_frame *frame, *best_frame = NULL; - struct arch_timer *at = platform_get_drvdata(pdev); void __iomem *cntctlbase; u32 cnttidr; cntctlbase = ioremap(at->gt_block->cntctlbase, at->gt_block->size); if (!cntctlbase) { - dev_err(&pdev->dev, "Can't map CNTCTLBase @ %pa\n", - &at->gt_block->cntctlbase); + pr_err("Can't map CNTCTLBase @ %pa\n", + &at->gt_block->cntctlbase); return NULL; } @@ -277,22 +278,21 @@ static void arch_timer_mmio_setup(struct arch_timer *at, int irq) clocksource_register_hz(&at->cs, at->rate); } -static int arch_timer_mmio_frame_register(struct platform_device *pdev, - struct arch_timer_mem_frame *frame) +static int arch_timer_mmio_frame_register(struct arch_timer *at, + struct arch_timer_mem_frame *frame, + struct device_node *np) { - struct arch_timer *at = platform_get_drvdata(pdev); - struct device_node *np = pdev->dev.of_node; int ret, irq; u32 rate; - if (!devm_request_mem_region(&pdev->dev, frame->cntbase, frame->size, - "arch_mem_timer")) + if (!request_mem_region(frame->cntbase, frame->size, "arch_mem_timer")) return -EBUSY; - at->base = devm_ioremap(&pdev->dev, frame->cntbase, frame->size); + at->base = ioremap(frame->cntbase, frame->size); if (!at->base) { - dev_err(&pdev->dev, "Can't map frame's registers\n"); - return -ENXIO; + pr_err("Can't map frame's registers @ %pa\n", &frame->cntbase); + ret = -ENXIO; + goto err_release_region; } /* @@ -310,49 +310,56 @@ static int arch_timer_mmio_frame_register(struct platform_device *pdev, at->rate = arch_timer_get_rate(); irq = at->access == VIRT_ACCESS ? frame->virt_irq : frame->phys_irq; - ret = devm_request_irq(&pdev->dev, irq, arch_timer_mmio_handler, - IRQF_TIMER | IRQF_NO_AUTOEN, "arch_mem_timer", - &at->evt); + ret = request_irq(irq, arch_timer_mmio_handler, + IRQF_TIMER | IRQF_NO_AUTOEN, "arch_mem_timer", + &at->evt); if (ret) { - dev_err(&pdev->dev, "Failed to request mem timer irq\n"); - return ret; + pr_err("Failed to request mem timer irq for frame @ %pa\n", + &frame->cntbase); + goto err_iounmap; } /* Afer this point, we're not allowed to fail anymore */ arch_timer_mmio_setup(at, irq); return 0; + +err_iounmap: + iounmap(at->base); +err_release_region: + release_mem_region(frame->cntbase, frame->size); + return ret; } -static int of_populate_gt_block(struct platform_device *pdev, - struct arch_timer *at) +static int of_populate_gt_block(struct device_node *np, struct arch_timer_mem *gt_block) { struct resource res; - if (of_address_to_resource(pdev->dev.of_node, 0, &res)) + if (of_address_to_resource(np, 0, &res)) return -EINVAL; - at->gt_block->cntctlbase = res.start; - at->gt_block->size = resource_size(&res); + gt_block->cntctlbase = res.start; + gt_block->size = resource_size(&res); - for_each_available_child_of_node_scoped(pdev->dev.of_node, frame_node) { + for_each_available_child_of_node_scoped(np, frame_node) { struct arch_timer_mem_frame *frame; u32 n; if (of_property_read_u32(frame_node, "frame-number", &n)) { - dev_err(&pdev->dev, FW_BUG "Missing frame-number\n"); + pr_err(FW_BUG "Missing frame-number for %pOF\n", + frame_node); return -EINVAL; } if (n >= ARCH_TIMER_MEM_MAX_FRAMES) { - dev_err(&pdev->dev, - FW_BUG "Wrong frame-number, only 0-%u are permitted\n", - ARCH_TIMER_MEM_MAX_FRAMES - 1); + pr_err(FW_BUG "Wrong frame-number %u for %pOF, only 0-%u are permitted\n", + n, frame_node, ARCH_TIMER_MEM_MAX_FRAMES - 1); return -EINVAL; } - frame = &at->gt_block->frame[n]; + frame = >_block->frame[n]; if (frame->valid) { - dev_err(&pdev->dev, FW_BUG "Duplicated frame-number\n"); + pr_err(FW_BUG "Duplicated frame-number %u for %pOF\n", + n, frame_node); return -EINVAL; } @@ -371,50 +378,62 @@ static int of_populate_gt_block(struct platform_device *pdev, return 0; } -static int arch_timer_mmio_probe(struct platform_device *pdev) +static struct arch_timer *arch_timer_mmio_init(struct arch_timer_mem *gt_block, + struct device_node *np) { + struct arch_timer *at __free(kfree) = kzalloc_obj(*at); struct arch_timer_mem_frame *frame; - struct arch_timer *at; - struct device_node *np; int ret; - np = pdev->dev.of_node; - - at = devm_kmalloc(&pdev->dev, sizeof(*at), GFP_KERNEL | __GFP_ZERO); if (!at) - return -ENOMEM; + return ERR_PTR(-ENOMEM); + + at->gt_block = gt_block; + + frame = find_best_frame(at); + if (!frame) { + pr_err("Unable to find a suitable frame in timer @ %pa\n", + &at->gt_block->cntctlbase); + return ERR_PTR(-EINVAL); + } + + ret = arch_timer_mmio_frame_register(at, frame, np); + if (ret) + return ERR_PTR(ret); + + pr_info("mmio timer running at %lu.%02luMHz (%s)\n", + (unsigned long)at->rate / 1000000, + (unsigned long)(at->rate / 10000) % 100, + at->access == VIRT_ACCESS ? "virt" : "phys"); + + return_ptr(at); +} + +static int arch_timer_mmio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct arch_timer_mem *gt_block; + struct arch_timer *at; + int ret; if (np) { - at->gt_block = devm_kmalloc(&pdev->dev, sizeof(*at->gt_block), - GFP_KERNEL | __GFP_ZERO); - if (!at->gt_block) + gt_block = devm_kzalloc(&pdev->dev, sizeof(*gt_block), + GFP_KERNEL); + if (!gt_block) return -ENOMEM; - ret = of_populate_gt_block(pdev, at); + ret = of_populate_gt_block(np, gt_block); if (ret) return ret; } else { - at->gt_block = dev_get_platdata(&pdev->dev); - } - - platform_set_drvdata(pdev, at); - - frame = find_best_frame(pdev); - if (!frame) { - dev_err(&pdev->dev, - "Unable to find a suitable frame in timer @ %pa\n", - &at->gt_block->cntctlbase); - return -EINVAL; + gt_block = dev_get_platdata(&pdev->dev); } - ret = arch_timer_mmio_frame_register(pdev, frame); - if (!ret) - dev_info(&pdev->dev, - "mmio timer running at %lu.%02luMHz (%s)\n", - (unsigned long)at->rate / 1000000, - (unsigned long)(at->rate / 10000) % 100, - at->access == VIRT_ACCESS ? "virt" : "phys"); + at = arch_timer_mmio_init(gt_block, np); + if (IS_ERR(at)) + return PTR_ERR(at); - return ret; + platform_set_drvdata(pdev, at); + return 0; } static const struct of_device_id arch_timer_mmio_of_table[] = { -- 2.54.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init 2026-06-10 17:53 [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init Stephan Gerhold 2026-06-10 17:53 ` [PATCH 1/2] clocksource/drivers/arm_arch_timer_mmio: Refactor " Stephan Gerhold @ 2026-06-10 17:53 ` Stephan Gerhold 2026-06-11 7:59 ` [PATCH 0/2] " Marc Zyngier 2 siblings, 0 replies; 6+ messages in thread From: Stephan Gerhold @ 2026-06-10 17:53 UTC (permalink / raw) To: Mark Rutland, Marc Zyngier, Daniel Lezcano, Thomas Gleixner, Sudeep Holla Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Jack Matthews Some single-core Qualcomm modem platforms (e.g. MDM9625, MDM9607) have an obscure timer setup where the global Arm MMIO timer (arm,armv7-timer-mem) is used as the only available timer for the CPU. This setup used to work fine until commit 0f67b56d84b4 ("clocksource/drivers/arm_arch_timer_mmio: Switch over to standalone driver") when the early timer initialization using TIMER_OF_DECLARE() was removed when moving to the standalone MMIO driver. We need some timer early to run properly, so without another timer in the system the only choice is to make the MMIO timer available early again using TIMER_OF_DECLARE(). Use the refactoring in the previous commit to reuse most of the initialization code in the new standalone driver and probe one timer early if required. ACPI-based systems and platforms with a CPU-local CP15 timer continue to probe the timer late as before. Reported-by: Jack Matthews <jack@jackmatthe.ws> Closes: https://lore.kernel.org/r/46A20F89-E208-4091-8B6E-B5C38BF82B42@jackmatthe.ws/ Fixes: 0f67b56d84b4 ("clocksource/drivers/arm_arch_timer_mmio: Switch over to standalone driver") Signed-off-by: Stephan Gerhold <stephan.gerhold@linaro.org> --- I couldn't find any existing (fully-supported) platform upstream that relies on this, so I omitted Cc stable. MDM9607 does have most of the necessary drivers upstream, it's just missing the DT (I would like to upstream that once ready). --- drivers/clocksource/arm_arch_timer_mmio.c | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/clocksource/arm_arch_timer_mmio.c b/drivers/clocksource/arm_arch_timer_mmio.c index 5cb94051c4be..d128dff7067f 100644 --- a/drivers/clocksource/arm_arch_timer_mmio.c +++ b/drivers/clocksource/arm_arch_timer_mmio.c @@ -15,6 +15,7 @@ #include <linux/err.h> #include <linux/interrupt.h> #include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/platform_device.h> @@ -409,6 +410,8 @@ static struct arch_timer *arch_timer_mmio_init(struct arch_timer_mem *gt_block, return_ptr(at); } +static struct device_node *arch_timer_mmio_early_np; + static int arch_timer_mmio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -417,6 +420,10 @@ static int arch_timer_mmio_probe(struct platform_device *pdev) int ret; if (np) { + /* Check if timer was already probed early */ + if (np == arch_timer_mmio_early_np) + return 0; + gt_block = devm_kzalloc(&pdev->dev, sizeof(*gt_block), GFP_KERNEL); if (!gt_block) @@ -436,6 +443,46 @@ static int arch_timer_mmio_probe(struct platform_device *pdev) return 0; } +static const struct of_device_id arch_timer_cp15_match[] __initconst = { + { .compatible = "arm,armv7-timer", }, + { .compatible = "arm,armv8-timer", }, + {} +}; + +static bool __init arch_timer_mmio_has_cp15(void) +{ + struct device_node *np __free(device_node) = + of_find_matching_node(NULL, arch_timer_cp15_match); + + return np && of_device_is_available(np); +} + +static int __init arch_timer_mmio_of_early_init(struct device_node *np) +{ + struct arch_timer *at; + int ret; + + if (arch_timer_mmio_early_np || arch_timer_mmio_has_cp15()) + return -EPROBE_DEFER; + + struct arch_timer_mem *gt_block __free(kfree) = kzalloc_obj(*gt_block); + if (!gt_block) + return -ENOMEM; + + ret = of_populate_gt_block(np, gt_block); + if (ret) + return ret; + + at = arch_timer_mmio_init(gt_block, np); + if (IS_ERR(at)) + return PTR_ERR(at); + retain_and_null_ptr(gt_block); + + arch_timer_mmio_early_np = np; + return 0; +} +TIMER_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", arch_timer_mmio_of_early_init); + static const struct of_device_id arch_timer_mmio_of_table[] = { { .compatible = "arm,armv7-timer-mem", }, {} -- 2.54.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init 2026-06-10 17:53 [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init Stephan Gerhold 2026-06-10 17:53 ` [PATCH 1/2] clocksource/drivers/arm_arch_timer_mmio: Refactor " Stephan Gerhold 2026-06-10 17:53 ` [PATCH 2/2] clocksource/drivers/arm_arch_timer_mmio: Restore support " Stephan Gerhold @ 2026-06-11 7:59 ` Marc Zyngier 2026-06-11 8:47 ` Stephan Gerhold 2 siblings, 1 reply; 6+ messages in thread From: Marc Zyngier @ 2026-06-11 7:59 UTC (permalink / raw) To: Stephan Gerhold Cc: Mark Rutland, Daniel Lezcano, Thomas Gleixner, Sudeep Holla, linux-arm-kernel, linux-kernel, linux-arm-msm, Jack Matthews On Wed, 10 Jun 2026 18:53:09 +0100, Stephan Gerhold <stephan.gerhold@linaro.org> wrote: > > Jack reported a regression for some single-core Qualcomm platforms (e.g. > MDM9625, MDM9607) that no longer boot because no timers can be found during > early boot [1]. Again, this is *not* a regression. These machines were *never* supported upstream. > These platforms rely on an obscure timer setup where the > global Arm MMIO timer (arm,armv7-timer-mem) is used as the only available > timer for the CPU. This setup used to work fine until commit 0f67b56d84b4 > ("clocksource/drivers/arm_arch_timer_mmio: Switch over to standalone > driver") when the early timer initialization using TIMER_OF_DECLARE() was > removed when moving to the standalone MMIO driver. > > There doesn't seem to be any other usable CPU timer on those platforms, so > this series restores the early timer support using TIMER_OF_DECLARE() > inside the new standalone arm_arch_timer_mmio driver. This is pretty ugly, > but I could not think of a better solution so far. I tried to keep the > ugliness for the two probe paths as limited as possible. :-) > > If someone has a better idea how to solve this, I would be happy to try it. I would suggest finding out what is the latest point in the init sequence where the timer can be probed without preventing boot. M. -- Jazz isn't dead. It just smells funny. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init 2026-06-11 7:59 ` [PATCH 0/2] " Marc Zyngier @ 2026-06-11 8:47 ` Stephan Gerhold 2026-06-11 13:57 ` Marc Zyngier 0 siblings, 1 reply; 6+ messages in thread From: Stephan Gerhold @ 2026-06-11 8:47 UTC (permalink / raw) To: Marc Zyngier Cc: Mark Rutland, Daniel Lezcano, Thomas Gleixner, Sudeep Holla, linux-arm-kernel, linux-kernel, linux-arm-msm, Jack Matthews On Thu, Jun 11, 2026 at 08:59:19AM +0100, Marc Zyngier wrote: > On Wed, 10 Jun 2026 18:53:09 +0100, > Stephan Gerhold <stephan.gerhold@linaro.org> wrote: > > > > Jack reported a regression for some single-core Qualcomm platforms (e.g. > > MDM9625, MDM9607) that no longer boot because no timers can be found during > > early boot [1]. > > Again, this is *not* a regression. These machines were *never* > supported upstream. > Sorry, I'll reword this next time. MDM9607 does have all required drivers and compatibles upstream already and is just missing the actual DT so it does feel somewhat supported to me, but I'm fine treating this as a feature extension without stable backporting etc. > > These platforms rely on an obscure timer setup where the > > global Arm MMIO timer (arm,armv7-timer-mem) is used as the only available > > timer for the CPU. This setup used to work fine until commit 0f67b56d84b4 > > ("clocksource/drivers/arm_arch_timer_mmio: Switch over to standalone > > driver") when the early timer initialization using TIMER_OF_DECLARE() was > > removed when moving to the standalone MMIO driver. > > > > There doesn't seem to be any other usable CPU timer on those platforms, so > > this series restores the early timer support using TIMER_OF_DECLARE() > > inside the new standalone arm_arch_timer_mmio driver. This is pretty ugly, > > but I could not think of a better solution so far. I tried to keep the > > ugliness for the two probe paths as limited as possible. :-) > > > > If someone has a better idea how to solve this, I would be happy to try it. > > I would suggest finding out what is the latest point in the init > sequence where the timer can be probed without preventing boot. > It doesn't get far without having any timer: [ 0.000000] timer_probe: no matching timers found [ 0.000000] entering initcall level: console [ 0.000000] calling con_init+0x0/0x354 @ 0 [ 0.000000] Console: colour dummy device 80x30 [ 0.000000] initcall con_init+0x0/0x354 returned 0 after 0 usecs [ 0.000000] sched_clock: 32 bits at 300 Hz, resolution 3333333ns, wraps every 7158278824300949ns [ 0.000000] Calibrating delay loop... <board hangs> If you look at start_kernel() in init/main.c it's basically time_init() that would normally probe the TIMER_OF_DECLARE() timers and calibrate_delay() that needs some timer to finish. There is also random_init() that comes directly after time_init(), which already wants to have access to timestamp counters. I don't see any other suitable place to hook into. :-/ I also don't see any other timer we could use, at least for MDM9625. It's a single-core Cortex-A5 and the downstream kernel defines only the arm,armv7-timer-mem, which seems to be used for everything... (The situation for MDM9607 is a bit different, but not any less messy, unfortunately.) Thanks, Stephan ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init 2026-06-11 8:47 ` Stephan Gerhold @ 2026-06-11 13:57 ` Marc Zyngier 0 siblings, 0 replies; 6+ messages in thread From: Marc Zyngier @ 2026-06-11 13:57 UTC (permalink / raw) To: Stephan Gerhold Cc: Mark Rutland, Daniel Lezcano, Thomas Gleixner, Sudeep Holla, linux-arm-kernel, linux-kernel, linux-arm-msm, Jack Matthews On Thu, 11 Jun 2026 09:47:58 +0100, Stephan Gerhold <stephan.gerhold@linaro.org> wrote: > > On Thu, Jun 11, 2026 at 08:59:19AM +0100, Marc Zyngier wrote: > > On Wed, 10 Jun 2026 18:53:09 +0100, > > Stephan Gerhold <stephan.gerhold@linaro.org> wrote: > > > > > > Jack reported a regression for some single-core Qualcomm platforms (e.g. > > > MDM9625, MDM9607) that no longer boot because no timers can be found during > > > early boot [1]. > > > > Again, this is *not* a regression. These machines were *never* > > supported upstream. > > > > Sorry, I'll reword this next time. MDM9607 does have all required > drivers and compatibles upstream already and is just missing the actual > DT so it does feel somewhat supported to me, but I'm fine treating this > as a feature extension without stable backporting etc. "Supported" has a different definition for me. Cortex-A5 without the A9-style TWD was so far never seen in the wild. The Generic MMIO timer was introduced way after Cortex-A5 shipped, and was designed to work with the CPU timers, making this QCOM contraption a franken-hack. So calling this supported is very much pushing the boundaries of what was supposed to be put together. > > > > These platforms rely on an obscure timer setup where the > > > global Arm MMIO timer (arm,armv7-timer-mem) is used as the only available > > > timer for the CPU. This setup used to work fine until commit 0f67b56d84b4 > > > ("clocksource/drivers/arm_arch_timer_mmio: Switch over to standalone > > > driver") when the early timer initialization using TIMER_OF_DECLARE() was > > > removed when moving to the standalone MMIO driver. > > > > > > There doesn't seem to be any other usable CPU timer on those platforms, so > > > this series restores the early timer support using TIMER_OF_DECLARE() > > > inside the new standalone arm_arch_timer_mmio driver. This is pretty ugly, > > > but I could not think of a better solution so far. I tried to keep the > > > ugliness for the two probe paths as limited as possible. :-) > > > > > > If someone has a better idea how to solve this, I would be happy to try it. > > > > I would suggest finding out what is the latest point in the init > > sequence where the timer can be probed without preventing boot. > > > > It doesn't get far without having any timer: > > [ 0.000000] timer_probe: no matching timers found > [ 0.000000] entering initcall level: console > [ 0.000000] calling con_init+0x0/0x354 @ 0 > [ 0.000000] Console: colour dummy device 80x30 > [ 0.000000] initcall con_init+0x0/0x354 returned 0 after 0 usecs > [ 0.000000] sched_clock: 32 bits at 300 Hz, resolution 3333333ns, wraps every 7158278824300949ns > [ 0.000000] Calibrating delay loop... > <board hangs> > This is nothing that "lpj=[some value]" on the command line can't help getting past. > If you look at start_kernel() in init/main.c it's basically time_init() > that would normally probe the TIMER_OF_DECLARE() timers and > calibrate_delay() that needs some timer to finish. There is also > random_init() that comes directly after time_init(), which already wants > to have access to timestamp counters. I don't see any other suitable > place to hook into. :-/ None of that should be a problem. I can boot a hacked arm64 kernel without any timer all the way to the point where it is waiting for a tick to enter the scheduler and run userspace. There's no reason why 32bit can't do something similar. Heck, 32bit doesn't even have a standard timer to rely on, so that's very much possible to do. Can you at least give it a try? > > I also don't see any other timer we could use, at least for MDM9625. > It's a single-core Cortex-A5 and the downstream kernel defines only the > arm,armv7-timer-mem, which seems to be used for everything... (The > situation for MDM9607 is a bit different, but not any less messy, > unfortunately.) MDM9607 appears to be a Cortex-A7, so it *definitely* has all the bells and whistles that we need. The DT I found doesn't make describe the timer, but it is absolutely part of the CPU. As for the A5, if we can't get this machine to use the driver as is without butchering it and going 15 years back in time, then I'd rather hack together a minimal driver that only this contraption will make use of, and be done with it. M. -- Jazz isn't dead. It just smells funny. ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-11 13:54 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-10 17:53 [PATCH 0/2] clocksource/drivers/arm_arch_timer_mmio: Restore support for early init Stephan Gerhold 2026-06-10 17:53 ` [PATCH 1/2] clocksource/drivers/arm_arch_timer_mmio: Refactor " Stephan Gerhold 2026-06-10 17:53 ` [PATCH 2/2] clocksource/drivers/arm_arch_timer_mmio: Restore support " Stephan Gerhold 2026-06-11 7:59 ` [PATCH 0/2] " Marc Zyngier 2026-06-11 8:47 ` Stephan Gerhold 2026-06-11 13:57 ` Marc Zyngier
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.