[PATCH v3 4/8] drivers: arm_architected_timer: refactor for pbl compatibility

Stefan Kerkmann <[email protected]>
Newsgroups org.infradead.lists.barebox
Message-ID <20260817-feature-pbl-get-time-ns-v3-4-9874c1438855@pengutronix.de>
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 <[email protected]>
---
 .../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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.