* [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros
@ 2026-08-17 14:01 Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 1/8] RISC-V: setup_c: avoid clearing BSS twice Stefan Kerkmann
` (8 more replies)
0 siblings, 9 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
Without a time source the read_poll_timeout functions will deadlock in
the PBL if the break condition is never met. This series introduces the
necessary timing functions in the PBL for arches/socs implementing
PBL_CLOCKSOURCE, which is every ARMv8 SoC as they implement an
architected timer and selected ARMv7 SoCs.
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
Changes in v3:
- Added PBL constructor support for ARM/ARM64/RISC-V
- Changed the implementation to PBL_CLOCKSOURCE
- Link to v2: https://patch.msgid.link/20260811-feature-pbl-get-time-ns-v2-0-754ee021b19d@pengutronix.de
Changes in v2:
- Strictly guard the pbl timer support on 32bit ARM for ARMv7 only builds
- Link to v1: https://lore.kernel.org/r/20250121-feature-pbl-get-time-ns-v1-0-c3d493397846@pengutronix.de
To: Sascha Hauer <s.hauer@pengutronix.de>
To: "open list:BAREBOX" <barebox@lists.infradead.org>
---
Stefan Kerkmann (8):
RISC-V: setup_c: avoid clearing BSS twice
ARM/ARM64/RISC-V: pbl: add constructor support
clocksource: allow re-init for same clock
drivers: arm_architected_timer: refactor for pbl compatibility
ARM: layerscape: re-init pbl clocksource
ARM: socfpga: agilex5: re-init pbl clocksource
ARM64: enable PBL_CLOCKSOURCE compatibility
linux/iopoll: enable polled timeouts for PBL_CLOCKSOURCE
arch/arm/cpu/setupc_32.S | 3 +++
arch/arm/cpu/setupc_64.S | 3 +++
.../include/asm/hardware/arm_architected_timer.h | 21 +++++++++++++++++++
arch/arm/lib/pbl.lds.S | 8 ++++++++
arch/arm/lib64/Makefile | 3 ++-
arch/arm/lib64/clocksource.c | 10 +++++++++
arch/arm/lib64/delay.c | 19 -----------------
arch/arm/mach-layerscape/lowlevel-ls1028a.c | 6 +++++-
arch/arm/mach-layerscape/lowlevel-ls1046a.c | 5 ++++-
arch/arm/mach-socfpga/agilex5-clock-manager.c | 7 +++----
arch/riscv/lib/pbl.lds.S | 9 ++++++++
arch/riscv/lib/setupc.S | 22 +++++++++++++++++++-
common/clock.c | 3 ++-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/Makefile | 2 +-
drivers/clocksource/arm_architected_timer.c | 24 ++++++++++++++--------
include/asm-generic/sections.h | 2 ++
include/linux/iopoll.h | 6 +++---
pbl/Makefile | 1 +
pbl/ctors.c | 13 ++++++++++++
20 files changed, 128 insertions(+), 40 deletions(-)
---
base-commit: 3317ac1baff3b0226caba7f83f3da61bc407343a
change-id: 20250121-feature-pbl-get-time-ns-6d9e8874d582
Best regards,
--
Stefan Kerkmann <s.kerkmann@pengutronix.de>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 1/8] RISC-V: setup_c: avoid clearing BSS twice
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 2/8] ARM/ARM64/RISC-V: pbl: add constructor support Stefan Kerkmann
` (7 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
This commit duplicates what is already implemented for ARM(64)[1].
Currently setup_c() isn't called twice but might be in the future.
[1]: 11c389397c ("ARM: setup_c: avoid clearing BSS twice")
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
arch/riscv/lib/setupc.S | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/lib/setupc.S b/arch/riscv/lib/setupc.S
index 423de4181e..5370e8a48e 100644
--- a/arch/riscv/lib/setupc.S
+++ b/arch/riscv/lib/setupc.S
@@ -10,13 +10,30 @@
*/
.section .text.setup_c
ENTRY(setup_c)
+ addi sp, sp, -SZREG * 2
+ REG_S ra, SZREG(sp)
+ lla a0, bss_cleared
+ lw a1, 0(a0)
+ bnez a1, zeroed
lla a0, __bss_start
li a1, 0
lla a2, __bss_stop
sub a2, a2, a0
- j __memset
+ jal __memset
+ lla a0, bss_cleared
+ li a1, 1
+ sw a1, 0(a0)
+zeroed:
+ REG_L ra, SZREG(sp)
+ addi sp, sp, SZREG * 2
+ ret
ENDPROC(setup_c)
+.section .data.bss_cleared
+.balign 4
+bss_cleared:
+ .word 0
+
/*
* void relocate_to_adr(unsigned long targetadr)
*
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 2/8] ARM/ARM64/RISC-V: pbl: add constructor support
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 1/8] RISC-V: setup_c: avoid clearing BSS twice Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-18 12:08 ` [PATCH] amend! " Stefan Kerkmann
2026-08-19 9:39 ` [PATCH v3 2/8] " Sascha Hauer
2026-08-17 14:01 ` [PATCH v3 3/8] clocksource: allow re-init for same clock Stefan Kerkmann
` (6 subsequent siblings)
8 siblings, 2 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
This commit allows running functions marked with
__attribute__((constructor))[1] automatically after the C environment is
setup in setup_c, which most likely will be early setup code shared
across SoCs/Arches in the PBL.
[1]: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/gcc/Common-Attributes.html#index-constructor
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
arch/arm/cpu/setupc_32.S | 3 +++
arch/arm/cpu/setupc_64.S | 3 +++
arch/arm/lib/pbl.lds.S | 8 ++++++++
arch/riscv/lib/pbl.lds.S | 9 +++++++++
arch/riscv/lib/setupc.S | 3 +++
include/asm-generic/sections.h | 2 ++
pbl/Makefile | 1 +
pbl/ctors.c | 13 +++++++++++++
8 files changed, 42 insertions(+)
diff --git a/arch/arm/cpu/setupc_32.S b/arch/arm/cpu/setupc_32.S
index fadfc28ae1..f34b144556 100644
--- a/arch/arm/cpu/setupc_32.S
+++ b/arch/arm/cpu/setupc_32.S
@@ -23,6 +23,9 @@ ENTRY(setup_c)
ldr r0, =bss_cleared
mov r1, #1
str r1, [r0] /* mark bss cleared */
+#ifdef __PBL__
+ bl pbl_do_ctors
+#endif
1: pop {r4, pc}
ENDPROC(setup_c)
diff --git a/arch/arm/cpu/setupc_64.S b/arch/arm/cpu/setupc_64.S
index a0767c5136..e3c6149e27 100644
--- a/arch/arm/cpu/setupc_64.S
+++ b/arch/arm/cpu/setupc_64.S
@@ -22,6 +22,9 @@ ENTRY(setup_c)
adr_l x0, bss_cleared
mov w1, #1
str w1, [x0] /* mark bss cleared */
+#ifdef __PBL__
+ bl pbl_do_ctors
+#endif
mov x30, x15
1: ret
ENDPROC(setup_c)
diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S
index 9c51f5eb3a..72aca83495 100644
--- a/arch/arm/lib/pbl.lds.S
+++ b/arch/arm/lib/pbl.lds.S
@@ -78,6 +78,14 @@ SECTIONS
. = ALIGN(4);
.rodata : { *(.rodata*) }
+ . = ALIGN(ASM_SZPTR);
+ __ctors_start = .;
+ .init_array : {
+ KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
+ KEEP(*(.init_array))
+ }
+ __ctors_end = .;
+
.barebox_imd : { BAREBOX_IMD }
. = ALIGN(PBL_SEGMENT_ALIGN);
diff --git a/arch/riscv/lib/pbl.lds.S b/arch/riscv/lib/pbl.lds.S
index 3a37d01475..17cd61ff75 100644
--- a/arch/riscv/lib/pbl.lds.S
+++ b/arch/riscv/lib/pbl.lds.S
@@ -4,6 +4,7 @@
#include <linux/sizes.h>
#include <asm/barebox.lds.h>
#include <asm-generic/memory_layout.h>
+#include <asm-generic/pointer.h>
OUTPUT_ARCH(BAREBOX_OUTPUT_ARCH)
OUTPUT_FORMAT(BAREBOX_OUTPUT_FORMAT)
@@ -32,6 +33,14 @@ SECTIONS
__start_rodata = .;
.rodata : { *(.rodata*) }
+ . = ALIGN(ASM_SZPTR);
+ __ctors_start = .;
+ .init_array : {
+ KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
+ KEEP(*(.init_array))
+ }
+ __ctors_end = .;
+
.barebox_imd : { BAREBOX_IMD }
__end_rodata = .;
diff --git a/arch/riscv/lib/setupc.S b/arch/riscv/lib/setupc.S
index 5370e8a48e..938c78350c 100644
--- a/arch/riscv/lib/setupc.S
+++ b/arch/riscv/lib/setupc.S
@@ -23,6 +23,9 @@ ENTRY(setup_c)
lla a0, bss_cleared
li a1, 1
sw a1, 0(a0)
+#ifdef __PBL__
+ jal pbl_do_ctors
+#endif
zeroed:
REG_L ra, SZREG(sp)
addi sp, sp, SZREG * 2
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 816e30341d..c7c576970a 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -49,4 +49,6 @@ static inline bool in_barebox_efi_runtime(unsigned long addr)
addr < (unsigned long)__efi_runtime_stop;
}
+void pbl_do_ctors(void);
+
#endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/pbl/Makefile b/pbl/Makefile
index 4506f192fe..7ce8cee077 100644
--- a/pbl/Makefile
+++ b/pbl/Makefile
@@ -3,6 +3,7 @@
#
# only unsed by the pbl
#
+pbl-y += ctors.o
pbl-y += misc.o
pbl-y += string.o
pbl-y += malloc.o
diff --git a/pbl/ctors.c b/pbl/ctors.c
new file mode 100644
index 0000000000..fcab599877
--- /dev/null
+++ b/pbl/ctors.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <asm-generic/sections.h>
+
+typedef void (*ctor_fn_t)(void);
+
+void pbl_do_ctors(void)
+{
+ ctor_fn_t *fn = (ctor_fn_t *)__ctors_start;
+
+ for (; fn < (ctor_fn_t *)__ctors_end; fn++)
+ (*fn)();
+}
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 3/8] clocksource: allow re-init for same clock
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 1/8] RISC-V: setup_c: avoid clearing BSS twice Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 2/8] ARM/ARM64/RISC-V: pbl: add constructor support Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility Stefan Kerkmann
` (5 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
A clocksource might need to be re-initialized if fundamental parameter
changes e.g. the clock frequency. With the change the init sequence
which sets the global clocksource can be called unconditionally again
for the same clock.
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
common/clock.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/common/clock.c b/common/clock.c
index 87109f3efc..fc770ac853 100644
--- a/common/clock.c
+++ b/common/clock.c
@@ -216,7 +216,8 @@ void clocksource_srand(void)
int init_clock(struct clocksource *cs)
{
- if (current_clock && cs->priority <= current_clock->priority)
+ if (current_clock && cs != current_clock &&
+ cs->priority <= current_clock->priority)
return 0;
if (cs->init) {
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
` (2 preceding siblings ...)
2026-08-17 14:01 ` [PATCH v3 3/8] clocksource: allow re-init for same clock Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-20 7:04 ` Sascha Hauer
2026-08-17 14:01 ` [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource Stefan Kerkmann
` (4 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
All ARMv8-A cores implement the 64bit wide generic timer CNTPCT[1]. Thus
the driver is the candidate for all AARCH64 SoCs to implement
PBL_CLOCKSOURCE compatibilty.
There is one catch though: the CNTFRQ_EL0 register[2] must be programmed
by the bootrom, barebox or the tf-a before the `arm_arch_timer_init`
call or the clocksource setup will return with -ENODEV. A later
re-initialization is also possible by calling `arm_arch_timer_init`
again.
[1]: See "ARM Architecture Reference Manual for A-profile architecture
(rev L.a)", chapter D12 "The Generic Timer in AArch64 state"
[2]: See "ARM Architecture Reference Manual for A-profile architecture
(rev L.a)", chapter D12.1.2.1 "Initializing and reading the system
effective frequency"
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
.../include/asm/hardware/arm_architected_timer.h | 21 +++++++++++++++++++
drivers/clocksource/Makefile | 2 +-
drivers/clocksource/arm_architected_timer.c | 24 ++++++++++++++--------
3 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/arch/arm/include/asm/hardware/arm_architected_timer.h b/arch/arm/include/asm/hardware/arm_architected_timer.h
new file mode 100644
index 0000000000..e0c1fd84fd
--- /dev/null
+++ b/arch/arm/include/asm/hardware/arm_architected_timer.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_ARM_HARDWARE_ARCH_TIMER_H
+#define __ASM_ARM_HARDWARE_ARCH_TIMER_H
+
+#include <linux/types.h>
+
+/**
+ * arm_arch_timer_init() - Initialize the ARM architected timer as global
+ * clocksource
+ * @cntfrq: The timer frequency, if zero the frequency is read from the
+ * CNTFRQ_EL0 register
+ *
+ * This function is meant to be called in a PBL constructor or in the driver
+ * probe function.
+ *
+ * Return: 0 on success, -ENODEV if the timer frequency can not be determined
+ */
+int arm_arch_timer_init(uint64_t cntfrq);
+
+#endif
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index dff8255650..0c92477247 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
obj-$(CONFIG_CLOCKSOURCE_UEMD) += uemd.o
obj-$(CONFIG_CLOCKSOURCE_ROCKCHIP)+= rk_timer.o
obj-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += timer-atmel-pit.o
-obj-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += arm_architected_timer.o
+obj-pbl-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += arm_architected_timer.o
ifneq ($(CONFIG_CPU_V8),y)
CFLAGS_arm_architected_timer.o := -march=armv7-a
endif
diff --git a/drivers/clocksource/arm_architected_timer.c b/drivers/clocksource/arm_architected_timer.c
index daced94c0e..ea5f5b8e05 100644
--- a/drivers/clocksource/arm_architected_timer.c
+++ b/drivers/clocksource/arm_architected_timer.c
@@ -9,6 +9,7 @@
#include <linux/clk.h>
#include <io.h>
#include <asm/system.h>
+#include <asm/hardware/arm_architected_timer.h>
static uint64_t arm_arch_clocksource_read(void)
{
@@ -22,22 +23,29 @@ static struct clocksource cs = {
.priority = 70,
};
-static int arm_arch_timer_probe(struct device *dev)
+int arm_arch_timer_init(uint64_t cntfrq)
{
- u32 cntfrq;
- int ret;
-
- /* Some platforms don't set CNTFRQ_EL0 before barebox */
- ret = of_property_read_u32(dev->of_node, "clock-frequency", &cntfrq);
-
- if (ret)
+ if (!cntfrq)
cntfrq = get_cntfrq();
+ if (!cntfrq)
+ return -ENODEV;
+
cs.mult = clocksource_hz2mult(cntfrq, cs.shift);
return init_clock(&cs);
}
+static int arm_arch_timer_probe(struct device *dev)
+{
+ u32 cntfrq = 0;
+
+ /* Some platforms don't set CNTFRQ_EL0 before barebox */
+ of_property_read_u32(dev->of_node, "clock-frequency", &cntfrq);
+
+ return arm_arch_timer_init(cntfrq);
+}
+
static struct of_device_id arm_arch_timer_dt_ids[] = {
{ .compatible = "arm,armv7-timer", },
{ .compatible = "arm,armv8-timer", },
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
` (3 preceding siblings ...)
2026-08-17 14:01 ` [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-17 15:42 ` Ahmad Fatoum
2026-08-20 6:59 ` Sascha Hauer
2026-08-17 14:01 ` [PATCH v3 6/8] ARM: socfpga: agilex5: " Stefan Kerkmann
` (3 subsequent siblings)
8 siblings, 2 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
After setting the cntfrq the global PBL clocksource must be
re-initialized to function correctly.
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
arch/arm/mach-layerscape/lowlevel-ls1028a.c | 6 +++++-
arch/arm/mach-layerscape/lowlevel-ls1046a.c | 5 ++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-layerscape/lowlevel-ls1028a.c b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
index fd013b2b52..ed9284d55a 100644
--- a/arch/arm/mach-layerscape/lowlevel-ls1028a.c
+++ b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
#include <common.h>
#include <io.h>
+#include <asm/hardware/arm_architected_timer.h>
#include <asm/syscounter.h>
#include <asm/system.h>
#include <mach/layerscape/errata.h>
@@ -35,8 +36,11 @@ static void ls1028a_timer_init(void)
void ls1028a_init_lowlevel(void)
{
+ const uint64_t cntfrq = 25000000;
+
scfg_init(SCFG_ENDIANESS_LITTLE);
- set_cntfrq(25000000);
+ set_cntfrq(cntfrq);
+ arm_arch_timer_init(cntfrq);
ls1028a_timer_init();
ls1028a_errata();
}
diff --git a/arch/arm/mach-layerscape/lowlevel-ls1046a.c b/arch/arm/mach-layerscape/lowlevel-ls1046a.c
index 1307c05eaf..cc2793acf2 100644
--- a/arch/arm/mach-layerscape/lowlevel-ls1046a.c
+++ b/arch/arm/mach-layerscape/lowlevel-ls1046a.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
#include <common.h>
#include <io.h>
+#include <asm/hardware/arm_architected_timer.h>
#include <asm/syscounter.h>
#include <asm/system.h>
#include <mach/layerscape/errata.h>
@@ -222,11 +223,13 @@ void ls1046a_init_lowlevel(void)
{
struct ccsr_cci400 __iomem *cci = IOMEM(LSCH2_CCI400_ADDR);
struct ccsr_scfg *scfg = IOMEM(LSCH2_SCFG_ADDR);
+ const uint64_t cntfrq = 25000000;
scfg_init(SCFG_ENDIANESS_BIG);
init_csu();
ls1046a_init_l2_latency();
- set_cntfrq(25000000);
+ set_cntfrq(cntfrq);
+ arm_arch_timer_init(cntfrq);
syscnt_enable(IOMEM(LSCH2_SYS_COUNTER_ADDR));
/* Make DMA master reads and writes snoopable */
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 6/8] ARM: socfpga: agilex5: re-init pbl clocksource
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
` (4 preceding siblings ...)
2026-08-17 14:01 ` [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 7/8] ARM64: enable PBL_CLOCKSOURCE compatibility Stefan Kerkmann
` (2 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
After changing the cntfrq register the global PBL clocksource must be
re-initialized. The inline assembly was dropped in favor of the
set_cntfrq function, the subsequent read is a no-op and dropped without
a replacement.
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
arch/arm/mach-socfpga/agilex5-clock-manager.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-socfpga/agilex5-clock-manager.c b/arch/arm/mach-socfpga/agilex5-clock-manager.c
index 4ce7a2d4a2..0b0425efc1 100644
--- a/arch/arm/mach-socfpga/agilex5-clock-manager.c
+++ b/arch/arm/mach-socfpga/agilex5-clock-manager.c
@@ -5,6 +5,7 @@
#include <common.h>
#include <io.h>
+#include <asm/hardware/arm_architected_timer.h>
#include <asm/system.h>
#include <dt-bindings/clock/intel,agilex5-clkmgr.h>
#include <linux/bitops.h>
@@ -252,8 +253,6 @@ static void clk_basic_init(struct socfpga_clk_plat *plat,
{
u32 vcocalib;
u32 cntfrq = COUNTER_FREQUENCY_REAL;
- u32 counter_freq = 0;
-
if (!cfg)
return;
@@ -361,8 +360,8 @@ static void clk_basic_init(struct socfpga_clk_plat *plat,
/* Update with accurate clock frequency */
if (current_el() == 3) {
- asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
- asm volatile("mrs %0, cntfrq_el0" : "=r" (counter_freq));
+ set_cntfrq(cntfrq);
+ arm_arch_timer_init(cntfrq);
}
/* Out of boot mode */
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 7/8] ARM64: enable PBL_CLOCKSOURCE compatibility
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
` (5 preceding siblings ...)
2026-08-17 14:01 ` [PATCH v3 6/8] ARM: socfpga: agilex5: " Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 8/8] linux/iopoll: enable polled timeouts for PBL_CLOCKSOURCE Stefan Kerkmann
2026-08-19 7:03 ` [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Sascha Hauer
8 siblings, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
All ARMv8-A cores implement the 64bit wide generic timer CNTPCT[1]. If
the architected timer driver is enabled the barebox PBL automatically is
PBL_CLOCKSOURCE compatible.
The setup of the PBL clocksource is implemented in the newly added PBL
constructors which are called at the end of setup_c. There is one catch
though:
The CNTFRQ_EL0 register[2] must be programmed by the bootrom, barebox or
the tf-a before the `arm_arch_timer_init` call. A later
re-initialization is also possible by calling `arm_arch_timer_init`
again.
[1]: See "ARM Architecture Reference Manual for A-profile architecture
(rev L.a)", chapter D12 "The Generic Timer in AArch64 state"
[2]: See "ARM Architecture Reference Manual for A-profile architecture
(rev L.a)", chapter D12.1.2.1 "Initializing and reading the system
effective frequency"
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
arch/arm/lib64/Makefile | 3 ++-
arch/arm/lib64/clocksource.c | 10 ++++++++++
arch/arm/lib64/delay.c | 19 -------------------
drivers/clocksource/Kconfig | 1 +
4 files changed, 13 insertions(+), 20 deletions(-)
diff --git a/arch/arm/lib64/Makefile b/arch/arm/lib64/Makefile
index f28cf81ab3..218de68a54 100644
--- a/arch/arm/lib64/Makefile
+++ b/arch/arm/lib64/Makefile
@@ -10,4 +10,5 @@ obj-pbl-y += runtime-offset.o
obj-pbl-y += setjmp.o
obj-pbl-y += reloc.o
obj-y += io.o
-pbl-y += div0.o delay.o
+pbl-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += clocksource.o
+pbl-y += div0.o
diff --git a/arch/arm/lib64/clocksource.c b/arch/arm/lib64/clocksource.c
new file mode 100644
index 0000000000..f992be09b8
--- /dev/null
+++ b/arch/arm/lib64/clocksource.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <debug_ll.h>
+#include <asm/hardware/arm_architected_timer.h>
+
+__attribute__((constructor)) static void init_arch_clock(void)
+{
+ if (arm_arch_timer_init(0))
+ puts_ll("Failed to setup architected timer\n");
+}
diff --git a/arch/arm/lib64/delay.c b/arch/arm/lib64/delay.c
deleted file mode 100644
index 78eab33f8d..0000000000
--- a/arch/arm/lib64/delay.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-#include <asm/system.h>
-#include <clock.h>
-#include <common.h>
-
-void udelay(unsigned long us)
-{
- unsigned long cntfrq = get_cntfrq();
- unsigned long ticks = (us * cntfrq) / 1000000;
- unsigned long start = get_cntpct();
-
- while ((long)(start + ticks - get_cntpct()) > 0);
-}
-
-void mdelay(unsigned long ms)
-{
- udelay(ms * 1000);
-}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 5ee83d2b38..6cf68d8be4 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -79,6 +79,7 @@ config CLOCKSOURCE_ARM_ARCHITECTED_TIMER
bool "ARM architected timer clock source" if COMPILE_TEST
default y
depends on ARM && (CPU_64v8 || CPU_V7)
+ select PBL_CLOCKSOURCE if CPU_64v8
config CLOCKSOURCE_ARM_GLOBAL_TIMER
bool "ARM global timer clock source" if COMPILE_TEST
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 8/8] linux/iopoll: enable polled timeouts for PBL_CLOCKSOURCE
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
` (6 preceding siblings ...)
2026-08-17 14:01 ` [PATCH v3 7/8] ARM64: enable PBL_CLOCKSOURCE compatibility Stefan Kerkmann
@ 2026-08-17 14:01 ` Stefan Kerkmann
2026-08-19 7:03 ` [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Sascha Hauer
8 siblings, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-17 14:01 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
This enables the usage of the polled timeout functions in the barebox
pbl with real timeouts for supported architectures. Currently only
AARCH64 and MACH_AM33XX is enabled.
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
include/linux/iopoll.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
index a6fade2a11..21014b73da 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -12,7 +12,7 @@
#include <clock.h>
#include <pbl.h>
-#if IN_PROPER
+#if IN_PROPER || IS_ENABLED(CONFIG_PBL_CLOCKSOURCE)
# define read_poll_get_time_ns() get_time_ns()
# define read_poll_is_timeout(s, t) is_timeout(s, t)
#else
@@ -38,8 +38,8 @@
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
*
- * We do not have timing functions in the PBL, so ignore the timeout value and
- * loop infinitely here.
+ * We might not have timing functions in the PBL, so ignore the timeout value
+ * and loop infinitely here.
*/
#define read_poll_timeout(op, val, cond, timeout_us, args...) \
({ \
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource
2026-08-17 14:01 ` [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource Stefan Kerkmann
@ 2026-08-17 15:42 ` Ahmad Fatoum
2026-08-20 6:59 ` Sascha Hauer
1 sibling, 0 replies; 19+ messages in thread
From: Ahmad Fatoum @ 2026-08-17 15:42 UTC (permalink / raw)
To: Stefan Kerkmann, Sascha Hauer, open list:BAREBOX
On 8/17/26 4:01 PM, Stefan Kerkmann wrote:
> After setting the cntfrq the global PBL clocksource must be
> re-initialized to function correctly.
>
> Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
I was unsure at first, but these function are indeed only called after
relocation.
Cheers,
Ahmad
> ---
> arch/arm/mach-layerscape/lowlevel-ls1028a.c | 6 +++++-
> arch/arm/mach-layerscape/lowlevel-ls1046a.c | 5 ++++-
> 2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-layerscape/lowlevel-ls1028a.c b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
> index fd013b2b52..ed9284d55a 100644
> --- a/arch/arm/mach-layerscape/lowlevel-ls1028a.c
> +++ b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0+
> #include <common.h>
> #include <io.h>
> +#include <asm/hardware/arm_architected_timer.h>
> #include <asm/syscounter.h>
> #include <asm/system.h>
> #include <mach/layerscape/errata.h>
> @@ -35,8 +36,11 @@ static void ls1028a_timer_init(void)
>
> void ls1028a_init_lowlevel(void)
> {
> + const uint64_t cntfrq = 25000000;
> +
> scfg_init(SCFG_ENDIANESS_LITTLE);
> - set_cntfrq(25000000);
> + set_cntfrq(cntfrq);
> + arm_arch_timer_init(cntfrq);
> ls1028a_timer_init();
> ls1028a_errata();
> }
> diff --git a/arch/arm/mach-layerscape/lowlevel-ls1046a.c b/arch/arm/mach-layerscape/lowlevel-ls1046a.c
> index 1307c05eaf..cc2793acf2 100644
> --- a/arch/arm/mach-layerscape/lowlevel-ls1046a.c
> +++ b/arch/arm/mach-layerscape/lowlevel-ls1046a.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0+
> #include <common.h>
> #include <io.h>
> +#include <asm/hardware/arm_architected_timer.h>
> #include <asm/syscounter.h>
> #include <asm/system.h>
> #include <mach/layerscape/errata.h>
> @@ -222,11 +223,13 @@ void ls1046a_init_lowlevel(void)
> {
> struct ccsr_cci400 __iomem *cci = IOMEM(LSCH2_CCI400_ADDR);
> struct ccsr_scfg *scfg = IOMEM(LSCH2_SCFG_ADDR);
> + const uint64_t cntfrq = 25000000;
>
> scfg_init(SCFG_ENDIANESS_BIG);
> init_csu();
> ls1046a_init_l2_latency();
> - set_cntfrq(25000000);
> + set_cntfrq(cntfrq);
> + arm_arch_timer_init(cntfrq);
> syscnt_enable(IOMEM(LSCH2_SYS_COUNTER_ADDR));
>
> /* Make DMA master reads and writes snoopable */
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH] amend! ARM/ARM64/RISC-V: pbl: add constructor support
2026-08-17 14:01 ` [PATCH v3 2/8] ARM/ARM64/RISC-V: pbl: add constructor support Stefan Kerkmann
@ 2026-08-18 12:08 ` Stefan Kerkmann
2026-08-19 9:39 ` [PATCH v3 2/8] " Sascha Hauer
1 sibling, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-18 12:08 UTC (permalink / raw)
To: Sascha Hauer, open list:BAREBOX; +Cc: Stefan Kerkmann
ARM/ARM64/RISC-V: pbl: add constructor support
This commit allows running functions marked with
__attribute__((constructor))[1] automatically after the C environment is
setup in setup_c, which most likely will be early setup code shared
across SoCs/Arches in the PBL.
The ARM64 setup_c function saved the link register (x30) in the caller
save register (x15). This is fragile as a constructor might use x15,
thus save it on the stack just like ARM32 and RISC-V.
[1]: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/gcc/Common-Attributes.html#index-constructor
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
arch/arm/cpu/setupc_64.S | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/arm/cpu/setupc_64.S b/arch/arm/cpu/setupc_64.S
index e3c6149e27..b1cfea47b1 100644
--- a/arch/arm/cpu/setupc_64.S
+++ b/arch/arm/cpu/setupc_64.S
@@ -10,10 +10,10 @@
* setup_c: clear bss if not yet done
*/
ENTRY(setup_c)
+ str x30, [sp, #-16]!
adr_l x0, bss_cleared
ldr w1, [x0]
cbnz w1, 1f /* skip if already done */
- mov x15, x30
adr_l x0, __bss_start
mov x1, #0
adr_l x2, __bss_stop
@@ -25,8 +25,9 @@ ENTRY(setup_c)
#ifdef __PBL__
bl pbl_do_ctors
#endif
- mov x30, x15
-1: ret
+1:
+ ldr x30, [sp], #16
+ ret
ENDPROC(setup_c)
.section .data.bss_cleared
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
` (7 preceding siblings ...)
2026-08-17 14:01 ` [PATCH v3 8/8] linux/iopoll: enable polled timeouts for PBL_CLOCKSOURCE Stefan Kerkmann
@ 2026-08-19 7:03 ` Sascha Hauer
8 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2026-08-19 7:03 UTC (permalink / raw)
To: open list:BAREBOX, Stefan Kerkmann
On Mon, 17 Aug 2026 16:01:11 +0200, Stefan Kerkmann wrote:
> Without a time source the read_poll_timeout functions will deadlock in
> the PBL if the break condition is never met. This series introduces the
> necessary timing functions in the PBL for arches/socs implementing
> PBL_CLOCKSOURCE, which is every ARMv8 SoC as they implement an
> architected timer and selected ARMv7 SoCs.
>
>
> [...]
Applied, thanks!
[1/8] RISC-V: setup_c: avoid clearing BSS twice
https://git.pengutronix.de/cgit/barebox/commit/?id=01c4186b3ea2 (link may not be stable)
[2/8] ARM/ARM64/RISC-V: pbl: add constructor support
https://git.pengutronix.de/cgit/barebox/commit/?id=bb07ef11d630 (link may not be stable)
[3/8] clocksource: allow re-init for same clock
https://git.pengutronix.de/cgit/barebox/commit/?id=ac074413caca (link may not be stable)
[4/8] drivers: arm_architected_timer: refactor for pbl compatibility
https://git.pengutronix.de/cgit/barebox/commit/?id=863ed4398f64 (link may not be stable)
[5/8] ARM: layerscape: re-init pbl clocksource
https://git.pengutronix.de/cgit/barebox/commit/?id=0e1c3c77947d (link may not be stable)
[6/8] ARM: socfpga: agilex5: re-init pbl clocksource
https://git.pengutronix.de/cgit/barebox/commit/?id=b28ad579be5a (link may not be stable)
[7/8] ARM64: enable PBL_CLOCKSOURCE compatibility
https://git.pengutronix.de/cgit/barebox/commit/?id=da7fa356d4a2 (link may not be stable)
[8/8] linux/iopoll: enable polled timeouts for PBL_CLOCKSOURCE
https://git.pengutronix.de/cgit/barebox/commit/?id=16e6243f96fd (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 2/8] ARM/ARM64/RISC-V: pbl: add constructor support
2026-08-17 14:01 ` [PATCH v3 2/8] ARM/ARM64/RISC-V: pbl: add constructor support Stefan Kerkmann
2026-08-18 12:08 ` [PATCH] amend! " Stefan Kerkmann
@ 2026-08-19 9:39 ` Sascha Hauer
1 sibling, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2026-08-19 9:39 UTC (permalink / raw)
To: Stefan Kerkmann; +Cc: open list:BAREBOX, Stefan Kerkmann
Hi Stefan,
On 2026-08-17 16:01, Stefan Kerkmann wrote:
> This commit allows running functions marked with
> __attribute__((constructor))[1] automatically after the C environment is
> setup in setup_c, which most likely will be early setup code shared
> across SoCs/Arches in the PBL.
This breaks hosttools_defconfig, sandbox_defconfig and targettools_defconfig with:
/usr/bin/ld: pbl/ctors.pbl.o: in function `pbl_do_ctors':
ctors.c:(.text.pbl_do_ctors+0x9): undefined reference to `__ctors_end'
/usr/bin/ld: ctors.c:(.text.pbl_do_ctors+0x11): undefined reference to `__ctors_start'
Could you send a fixup?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource
2026-08-17 14:01 ` [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource Stefan Kerkmann
2026-08-17 15:42 ` Ahmad Fatoum
@ 2026-08-20 6:59 ` Sascha Hauer
2026-08-20 8:06 ` Stefan Kerkmann
1 sibling, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2026-08-20 6:59 UTC (permalink / raw)
To: Stefan Kerkmann; +Cc: open list:BAREBOX, Stefan Kerkmann
On 2026-08-17 16:01, Stefan Kerkmann wrote:
> After setting the cntfrq the global PBL clocksource must be
> re-initialized to function correctly.
>
> Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
> ---
> arch/arm/mach-layerscape/lowlevel-ls1028a.c | 6 +++++-
> arch/arm/mach-layerscape/lowlevel-ls1046a.c | 5 ++++-
> 2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-layerscape/lowlevel-ls1028a.c b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
> index fd013b2b52..ed9284d55a 100644
> --- a/arch/arm/mach-layerscape/lowlevel-ls1028a.c
> +++ b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0+
> #include <common.h>
> #include <io.h>
> +#include <asm/hardware/arm_architected_timer.h>
> #include <asm/syscounter.h>
> #include <asm/system.h>
> #include <mach/layerscape/errata.h>
> @@ -35,8 +36,11 @@ static void ls1028a_timer_init(void)
>
> void ls1028a_init_lowlevel(void)
> {
> + const uint64_t cntfrq = 25000000;
> +
> scfg_init(SCFG_ENDIANESS_LITTLE);
> - set_cntfrq(25000000);
> + set_cntfrq(cntfrq);
> + arm_arch_timer_init(cntfrq);
> ls1028a_timer_init();
> ls1028a_errata();
> }
I had to squash this patch together with the next two to avoid
intermediate compile breakage. Otherwise we get an undefined reference
to clocksource_hz2mult().
One thing that strikes me here is that first arm_arch_timer_init() is
called and afterwards ls1028a_timer_init(). I have no idea what timer
ls1028a_timer_init() initializes and if that has anything to do with
the architected timer, but if it has the order should likely be the
other way round.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility
2026-08-17 14:01 ` [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility Stefan Kerkmann
@ 2026-08-20 7:04 ` Sascha Hauer
2026-08-20 7:32 ` Stefan Kerkmann
0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2026-08-20 7:04 UTC (permalink / raw)
To: Stefan Kerkmann; +Cc: open list:BAREBOX, Stefan Kerkmann
On 2026-08-17 16:01, Stefan Kerkmann wrote:
> All ARMv8-A cores implement the 64bit wide generic timer CNTPCT[1]. Thus
> the driver is the candidate for all AARCH64 SoCs to implement
> PBL_CLOCKSOURCE compatibilty.
>
> There is one catch though: the CNTFRQ_EL0 register[2] must be programmed
> by the bootrom, barebox or the tf-a before the `arm_arch_timer_init`
> call or the clocksource setup will return with -ENODEV. A later
> re-initialization is also possible by calling `arm_arch_timer_init`
> again.
>
> [1]: See "ARM Architecture Reference Manual for A-profile architecture
> (rev L.a)", chapter D12 "The Generic Timer in AArch64 state"
> [2]: See "ARM Architecture Reference Manual for A-profile architecture
> (rev L.a)", chapter D12.1.2.1 "Initializing and reading the system
> effective frequency"
>
> Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
> ---
> .../include/asm/hardware/arm_architected_timer.h | 21 +++++++++++++++++++
> drivers/clocksource/Makefile | 2 +-
> drivers/clocksource/arm_architected_timer.c | 24 ++++++++++++++--------
> 3 files changed, 38 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/include/asm/hardware/arm_architected_timer.h b/arch/arm/include/asm/hardware/arm_architected_timer.h
> new file mode 100644
> index 0000000000..e0c1fd84fd
> --- /dev/null
> +++ b/arch/arm/include/asm/hardware/arm_architected_timer.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +#ifndef __ASM_ARM_HARDWARE_ARCH_TIMER_H
> +#define __ASM_ARM_HARDWARE_ARCH_TIMER_H
> +
> +#include <linux/types.h>
> +
> +/**
> + * arm_arch_timer_init() - Initialize the ARM architected timer as global
> + * clocksource
> + * @cntfrq: The timer frequency, if zero the frequency is read from the
> + * CNTFRQ_EL0 register
> + *
> + * This function is meant to be called in a PBL constructor or in the driver
> + * probe function.
> + *
> + * Return: 0 on success, -ENODEV if the timer frequency can not be determined
> + */
> +int arm_arch_timer_init(uint64_t cntfrq);
> +
> +#endif
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index dff8255650..0c92477247 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -13,7 +13,7 @@ obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
> obj-$(CONFIG_CLOCKSOURCE_UEMD) += uemd.o
> obj-$(CONFIG_CLOCKSOURCE_ROCKCHIP)+= rk_timer.o
> obj-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += timer-atmel-pit.o
> -obj-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += arm_architected_timer.o
> +obj-pbl-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += arm_architected_timer.o
> ifneq ($(CONFIG_CPU_V8),y)
> CFLAGS_arm_architected_timer.o := -march=armv7-a
> endif
> diff --git a/drivers/clocksource/arm_architected_timer.c b/drivers/clocksource/arm_architected_timer.c
> index daced94c0e..ea5f5b8e05 100644
> --- a/drivers/clocksource/arm_architected_timer.c
> +++ b/drivers/clocksource/arm_architected_timer.c
> @@ -9,6 +9,7 @@
> #include <linux/clk.h>
> #include <io.h>
> #include <asm/system.h>
> +#include <asm/hardware/arm_architected_timer.h>
>
> static uint64_t arm_arch_clocksource_read(void)
> {
> @@ -22,22 +23,29 @@ static struct clocksource cs = {
> .priority = 70,
> };
>
> -static int arm_arch_timer_probe(struct device *dev)
> +int arm_arch_timer_init(uint64_t cntfrq)
> {
> - u32 cntfrq;
> - int ret;
> -
> - /* Some platforms don't set CNTFRQ_EL0 before barebox */
> - ret = of_property_read_u32(dev->of_node, "clock-frequency", &cntfrq);
> -
> - if (ret)
> + if (!cntfrq)
> cntfrq = get_cntfrq();
I wonder if we should just drop the cntfrq argument. All users call
set_cntfrq() before calling this, so get_cntfrq() should return the
correct value and we can rely on it.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility
2026-08-20 7:04 ` Sascha Hauer
@ 2026-08-20 7:32 ` Stefan Kerkmann
2026-08-20 8:00 ` Sascha Hauer
0 siblings, 1 reply; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-20 7:32 UTC (permalink / raw)
To: Sascha Hauer; +Cc: open list:BAREBOX
Hi Sascha,
On 8/20/26 09:04, Sascha Hauer wrote:
> On 2026-08-17 16:01, Stefan Kerkmann wrote:
>> All ARMv8-A cores implement the 64bit wide generic timer CNTPCT[1]. Thus
>> the driver is the candidate for all AARCH64 SoCs to implement
>> PBL_CLOCKSOURCE compatibilty.
>>
>> There is one catch though: the CNTFRQ_EL0 register[2] must be programmed
>> by the bootrom, barebox or the tf-a before the `arm_arch_timer_init`
>> call or the clocksource setup will return with -ENODEV. A later
>> re-initialization is also possible by calling `arm_arch_timer_init`
>> again.
>>
>> [1]: See "ARM Architecture Reference Manual for A-profile architecture
>> (rev L.a)", chapter D12 "The Generic Timer in AArch64 state"
>> [2]: See "ARM Architecture Reference Manual for A-profile architecture
>> (rev L.a)", chapter D12.1.2.1 "Initializing and reading the system
>> effective frequency"
>>
>> Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
>> ---
>> .../include/asm/hardware/arm_architected_timer.h | 21 +++++++++++++++++++
>> drivers/clocksource/Makefile | 2 +-
>> drivers/clocksource/arm_architected_timer.c | 24 ++++++++++++++--------
>> 3 files changed, 38 insertions(+), 9 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/hardware/arm_architected_timer.h b/arch/arm/include/asm/hardware/arm_architected_timer.h
>> new file mode 100644
>> index 0000000000..e0c1fd84fd
>> --- /dev/null
>> +++ b/arch/arm/include/asm/hardware/arm_architected_timer.h
>> @@ -0,0 +1,21 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +
>> +#ifndef __ASM_ARM_HARDWARE_ARCH_TIMER_H
>> +#define __ASM_ARM_HARDWARE_ARCH_TIMER_H
>> +
>> +#include <linux/types.h>
>> +
>> +/**
>> + * arm_arch_timer_init() - Initialize the ARM architected timer as global
>> + * clocksource
>> + * @cntfrq: The timer frequency, if zero the frequency is read from the
>> + * CNTFRQ_EL0 register
>> + *
>> + * This function is meant to be called in a PBL constructor or in the driver
>> + * probe function.
>> + *
>> + * Return: 0 on success, -ENODEV if the timer frequency can not be determined
>> + */
>> +int arm_arch_timer_init(uint64_t cntfrq);
>> +
>> +#endif
>> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
>> index dff8255650..0c92477247 100644
>> --- a/drivers/clocksource/Makefile
>> +++ b/drivers/clocksource/Makefile
>> @@ -13,7 +13,7 @@ obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
>> obj-$(CONFIG_CLOCKSOURCE_UEMD) += uemd.o
>> obj-$(CONFIG_CLOCKSOURCE_ROCKCHIP)+= rk_timer.o
>> obj-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += timer-atmel-pit.o
>> -obj-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += arm_architected_timer.o
>> +obj-pbl-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += arm_architected_timer.o
>> ifneq ($(CONFIG_CPU_V8),y)
>> CFLAGS_arm_architected_timer.o := -march=armv7-a
>> endif
>> diff --git a/drivers/clocksource/arm_architected_timer.c b/drivers/clocksource/arm_architected_timer.c
>> index daced94c0e..ea5f5b8e05 100644
>> --- a/drivers/clocksource/arm_architected_timer.c
>> +++ b/drivers/clocksource/arm_architected_timer.c
>> @@ -9,6 +9,7 @@
>> #include <linux/clk.h>
>> #include <io.h>
>> #include <asm/system.h>
>> +#include <asm/hardware/arm_architected_timer.h>
>>
>> static uint64_t arm_arch_clocksource_read(void)
>> {
>> @@ -22,22 +23,29 @@ static struct clocksource cs = {
>> .priority = 70,
>> };
>>
>> -static int arm_arch_timer_probe(struct device *dev)
>> +int arm_arch_timer_init(uint64_t cntfrq)
>> {
>> - u32 cntfrq;
>> - int ret;
>> -
>> - /* Some platforms don't set CNTFRQ_EL0 before barebox */
>> - ret = of_property_read_u32(dev->of_node, "clock-frequency", &cntfrq);
>> -
>> - if (ret)
>> + if (!cntfrq)
>> cntfrq = get_cntfrq();
>
> I wonder if we should just drop the cntfrq argument. All users call
> set_cntfrq() before calling this, so get_cntfrq() should return the
> correct value and we can rely on it.
>
Maybe keep the argument and use set_cntfrq in arm_arch_timer_init if the
argument is !=0? Then arm_arch_timer_init is the function to use if a C
environment is available? This would prevent any inconsistency.
> Sascha
>
Best regards,
Stefan
> --
> Pengutronix e.K. | |
> Steuerwalder Str. 21 | http://www.pengutronix.de/ |
> 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
>
--
Pengutronix e.K. | Stefan Kerkmann |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-128 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility
2026-08-20 7:32 ` Stefan Kerkmann
@ 2026-08-20 8:00 ` Sascha Hauer
2026-08-20 8:07 ` Stefan Kerkmann
0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2026-08-20 8:00 UTC (permalink / raw)
To: Stefan Kerkmann; +Cc: open list:BAREBOX
On 2026-08-20 09:32, Stefan Kerkmann wrote:
> >> diff --git a/drivers/clocksource/arm_architected_timer.c b/drivers/clocksource/arm_architected_timer.c
> >> index daced94c0e..ea5f5b8e05 100644
> >> --- a/drivers/clocksource/arm_architected_timer.c
> >> +++ b/drivers/clocksource/arm_architected_timer.c
> >> @@ -9,6 +9,7 @@
> >> #include <linux/clk.h>
> >> #include <io.h>
> >> #include <asm/system.h>
> >> +#include <asm/hardware/arm_architected_timer.h>
> >>
> >> static uint64_t arm_arch_clocksource_read(void)
> >> {
> >> @@ -22,22 +23,29 @@ static struct clocksource cs = {
> >> .priority = 70,
> >> };
> >>
> >> -static int arm_arch_timer_probe(struct device *dev)
> >> +int arm_arch_timer_init(uint64_t cntfrq)
> >> {
> >> - u32 cntfrq;
> >> - int ret;
> >> -
> >> - /* Some platforms don't set CNTFRQ_EL0 before barebox */
> >> - ret = of_property_read_u32(dev->of_node, "clock-frequency", &cntfrq);
> >> -
> >> - if (ret)
> >> + if (!cntfrq)
> >> cntfrq = get_cntfrq();
> >
> > I wonder if we should just drop the cntfrq argument. All users call
> > set_cntfrq() before calling this, so get_cntfrq() should return the
> > correct value and we can rely on it.
> >
>
> Maybe keep the argument and use set_cntfrq in arm_arch_timer_init if the
> argument is !=0? Then arm_arch_timer_init is the function to use if a C
> environment is available? This would prevent any inconsistency.
I am not sure, but set_cntfrq() might only be usable in EL3, so you
would have to be careful about the exception level when calling
arm_arch_timer_init() with a non zero argument.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource
2026-08-20 6:59 ` Sascha Hauer
@ 2026-08-20 8:06 ` Stefan Kerkmann
0 siblings, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-20 8:06 UTC (permalink / raw)
To: Sascha Hauer; +Cc: open list:BAREBOX
Hi Sascha,
On 8/20/26 08:59, Sascha Hauer wrote:
> On 2026-08-17 16:01, Stefan Kerkmann wrote:
>> After setting the cntfrq the global PBL clocksource must be
>> re-initialized to function correctly.
>>
>> Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
>> ---
>> arch/arm/mach-layerscape/lowlevel-ls1028a.c | 6 +++++-
>> arch/arm/mach-layerscape/lowlevel-ls1046a.c | 5 ++++-
>> 2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/mach-layerscape/lowlevel-ls1028a.c b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
>> index fd013b2b52..ed9284d55a 100644
>> --- a/arch/arm/mach-layerscape/lowlevel-ls1028a.c
>> +++ b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
>> @@ -1,6 +1,7 @@
>> // SPDX-License-Identifier: GPL-2.0+
>> #include <common.h>
>> #include <io.h>
>> +#include <asm/hardware/arm_architected_timer.h>
>> #include <asm/syscounter.h>
>> #include <asm/system.h>
>> #include <mach/layerscape/errata.h>
>> @@ -35,8 +36,11 @@ static void ls1028a_timer_init(void)
>>
>> void ls1028a_init_lowlevel(void)
>> {
>> + const uint64_t cntfrq = 25000000;
>> +
>> scfg_init(SCFG_ENDIANESS_LITTLE);
>> - set_cntfrq(25000000);
>> + set_cntfrq(cntfrq);
>> + arm_arch_timer_init(cntfrq);
>> ls1028a_timer_init();
>> ls1028a_errata();
>> }
>
> I had to squash this patch together with the next two to avoid
> intermediate compile breakage. Otherwise we get an undefined reference
> to clocksource_hz2mult().
>
> One thing that strikes me here is that first arm_arch_timer_init() is
> called and afterwards ls1028a_timer_init(). I have no idea what timer
> ls1028a_timer_init() initializes and if that has anything to do with
> the architected timer, but if it has the order should likely be the
> other way round.
>
>From my understanding this function enables the per-core timers which are driven
by the global system counter (cntfrq/cntpct) but distinct from it[1]. So the
order should be correct?
[1]: https://support.arm.com/documentation/102379/0104/System-Counter
> Sascha
>
> --
> Pengutronix e.K. | |
> Steuerwalder Str. 21 | http://www.pengutronix.de/ |
> 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
>
Best regards,
Stefan
--
Pengutronix e.K. | Stefan Kerkmann |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-128 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility
2026-08-20 8:00 ` Sascha Hauer
@ 2026-08-20 8:07 ` Stefan Kerkmann
0 siblings, 0 replies; 19+ messages in thread
From: Stefan Kerkmann @ 2026-08-20 8:07 UTC (permalink / raw)
To: Sascha Hauer; +Cc: open list:BAREBOX
Hi Sascha,
On 8/20/26 10:00, Sascha Hauer wrote:
> On 2026-08-20 09:32, Stefan Kerkmann wrote:
>>>> diff --git a/drivers/clocksource/arm_architected_timer.c b/drivers/clocksource/arm_architected_timer.c
>>>> index daced94c0e..ea5f5b8e05 100644
>>>> --- a/drivers/clocksource/arm_architected_timer.c
>>>> +++ b/drivers/clocksource/arm_architected_timer.c
>>>> @@ -9,6 +9,7 @@
>>>> #include <linux/clk.h>
>>>> #include <io.h>
>>>> #include <asm/system.h>
>>>> +#include <asm/hardware/arm_architected_timer.h>
>>>>
>>>> static uint64_t arm_arch_clocksource_read(void)
>>>> {
>>>> @@ -22,22 +23,29 @@ static struct clocksource cs = {
>>>> .priority = 70,
>>>> };
>>>>
>>>> -static int arm_arch_timer_probe(struct device *dev)
>>>> +int arm_arch_timer_init(uint64_t cntfrq)
>>>> {
>>>> - u32 cntfrq;
>>>> - int ret;
>>>> -
>>>> - /* Some platforms don't set CNTFRQ_EL0 before barebox */
>>>> - ret = of_property_read_u32(dev->of_node, "clock-frequency", &cntfrq);
>>>> -
>>>> - if (ret)
>>>> + if (!cntfrq)
>>>> cntfrq = get_cntfrq();
>>>
>>> I wonder if we should just drop the cntfrq argument. All users call
>>> set_cntfrq() before calling this, so get_cntfrq() should return the
>>> correct value and we can rely on it.
>>>
>>
>> Maybe keep the argument and use set_cntfrq in arm_arch_timer_init if the
>> argument is !=0? Then arm_arch_timer_init is the function to use if a C
>> environment is available? This would prevent any inconsistency.
>
> I am not sure, but set_cntfrq() might only be usable in EL3, so you
> would have to be careful about the exception level when calling
> arm_arch_timer_init() with a non zero argument.
>
Yes, it would have to be guarded by an el3 check.
> Sascha
>
Best regards,
Stefan
--
Pengutronix e.K. | Stefan Kerkmann |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-128 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-08-20 8:08 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-17 14:01 [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 1/8] RISC-V: setup_c: avoid clearing BSS twice Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 2/8] ARM/ARM64/RISC-V: pbl: add constructor support Stefan Kerkmann
2026-08-18 12:08 ` [PATCH] amend! " Stefan Kerkmann
2026-08-19 9:39 ` [PATCH v3 2/8] " Sascha Hauer
2026-08-17 14:01 ` [PATCH v3 3/8] clocksource: allow re-init for same clock Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility Stefan Kerkmann
2026-08-20 7:04 ` Sascha Hauer
2026-08-20 7:32 ` Stefan Kerkmann
2026-08-20 8:00 ` Sascha Hauer
2026-08-20 8:07 ` Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 5/8] ARM: layerscape: re-init pbl clocksource Stefan Kerkmann
2026-08-17 15:42 ` Ahmad Fatoum
2026-08-20 6:59 ` Sascha Hauer
2026-08-20 8:06 ` Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 6/8] ARM: socfpga: agilex5: " Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 7/8] ARM64: enable PBL_CLOCKSOURCE compatibility Stefan Kerkmann
2026-08-17 14:01 ` [PATCH v3 8/8] linux/iopoll: enable polled timeouts for PBL_CLOCKSOURCE Stefan Kerkmann
2026-08-19 7:03 ` [PATCH v3 0/8] PBL: enable timeouts in read_poll_timeout macros Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox