All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] timer: add SP804 DM_TIMER driver (and use it)
@ 2022-10-20 22:10 Andre Przywara
  2022-10-20 22:10 ` [PATCH 1/3] timer: add SP804 UCLASS timer driver Andre Przywara
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Andre Przywara @ 2022-10-20 22:10 UTC (permalink / raw)
  To: Tom Rini, Simon Glass; +Cc: u-boot

Some boards were using an ARM SP804 timer IP, but were driving that
using hardcoded addresses and input frequencies, using the
CONFIG_SYS_TIMER_* macros. This is deprecated and scheduled for removal.

This series adds a DM_TIMER compliant SP804 driver in patch 1, and lets
the Highbank board use that (patch 3).
Since the Highbank DT somewhat hides the timer base fixed-clock inside
a subnode, we need some simple-bus like driver in patch 2 to help the
driver find the timer frequency.

The SP804 driver should be usable by other SoCs using the SP804 timer,
but I don't have any to test it there.

Cheers,
Andre

Andre Przywara (3):
  timer: add SP804 UCLASS timer driver
  highbank: scan into hb_sregs DT subnodes
  highbank: switch to use the Arm SP804 DM_TIMER driver

 arch/arm/Kconfig            |   2 +
 board/highbank/Makefile     |   2 +-
 board/highbank/hb_sregs.c   |  45 +++++++++++++++
 drivers/timer/Kconfig       |   6 ++
 drivers/timer/Makefile      |   1 +
 drivers/timer/sp804_timer.c | 108 ++++++++++++++++++++++++++++++++++++
 include/configs/highbank.h  |   4 --
 7 files changed, 163 insertions(+), 5 deletions(-)
 create mode 100644 board/highbank/hb_sregs.c
 create mode 100644 drivers/timer/sp804_timer.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] timer: add SP804 UCLASS timer driver
  2022-10-20 22:10 [PATCH 0/3] timer: add SP804 DM_TIMER driver (and use it) Andre Przywara
@ 2022-10-20 22:10 ` Andre Przywara
  2022-11-03 16:57   ` Tom Rini
  2022-10-20 22:10 ` [PATCH 2/3] highbank: scan into hb_sregs DT subnodes Andre Przywara
  2022-10-20 22:10 ` [PATCH 3/3] highbank: switch to use the Arm SP804 DM_TIMER driver Andre Przywara
  2 siblings, 1 reply; 7+ messages in thread
From: Andre Przywara @ 2022-10-20 22:10 UTC (permalink / raw)
  To: Tom Rini, Simon Glass; +Cc: u-boot

The "Arm Ltd. Dual-Timer Module (SP804)" is a simple 32-bit count-down
timer IP with interrupt functionality, and is used in some SoCs from
various vendors.

Add a simple DM compliant timer driver, to allow users of the SP804 to
switch to DM_TIMER.

This relies on the input clock to be accessible via the DM clock
framework, which should be fine as we probably look at fixed-clock's
here anyway.
We re-program the control register in the probe() function, but keep
the divider in place, in case this has been set to something on purpose
before.

The TRM for the timer IP can be found here:
https://developer.arm.com/documentation/ddi0271/latest

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/timer/Kconfig       |   6 ++
 drivers/timer/Makefile      |   1 +
 drivers/timer/sp804_timer.c | 108 ++++++++++++++++++++++++++++++++++++
 3 files changed, 115 insertions(+)
 create mode 100644 drivers/timer/sp804_timer.c

diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index fd8745ffc2e..22da516f045 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -230,6 +230,12 @@ config SANDBOX_TIMER
 	  Select this to enable an emulated timer for sandbox. It gets
 	  time from host os.
 
+config SP804_TIMER
+	bool "ARM SP804 timer support"
+	depends on TIMER
+	help
+	  ARM SP804 dual timer IP support
+
 config STI_TIMER
 	bool "STi timer support"
 	depends on TIMER
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index 7bfb7749e97..ec332943876 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_RENESAS_OSTM_TIMER) += ostm_timer.o
 obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o
 obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
 obj-$(CONFIG_SANDBOX_TIMER)	+= sandbox_timer.o
+obj-$(CONFIG_SP804_TIMER)	+= sp804_timer.o
 obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint_timer.o
 obj-$(CONFIG_STI_TIMER)		+= sti-timer.o
 obj-$(CONFIG_STM32_TIMER)	+= stm32_timer.o
diff --git a/drivers/timer/sp804_timer.c b/drivers/timer/sp804_timer.c
new file mode 100644
index 00000000000..8fd4afb15a5
--- /dev/null
+++ b/drivers/timer/sp804_timer.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ARM PrimeCell Dual-Timer Module (SP804) driver
+ * Copyright (C) 2022 Arm Ltd.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <init.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/ofnode.h>
+#include <mapmem.h>
+#include <dt-structs.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SP804_TIMERX_LOAD		0x00
+#define SP804_TIMERX_VALUE		0x04
+#define SP804_TIMERX_CONTROL		0x08
+
+#define SP804_CTRL_TIMER_ENABLE		(1U << 7)
+#define SP804_CTRL_TIMER_PERIODIC	(1U << 6)
+#define SP804_CTRL_INT_ENABLE		(1U << 5)
+#define SP804_CTRL_TIMER_PRESCALE_SHIFT	2
+#define SP804_CTRL_TIMER_PRESCALE_MASK	(3U << SP804_CTRL_TIMER_PRESCALE_SHIFT)
+#define SP804_CTRL_TIMER_32BIT		(1U << 1)
+#define SP804_CTRL_ONESHOT		(1U << 0)
+
+
+struct sp804_timer_plat {
+	uintptr_t base;
+};
+
+static u64 sp804_timer_get_count(struct udevice *dev)
+{
+	struct sp804_timer_plat *plat = dev_get_plat(dev);
+	uint32_t cntr = readl(plat->base + SP804_TIMERX_VALUE);
+
+	/* timers are down-counting */
+	return ~0u - cntr;
+}
+
+static int sp804_clk_of_to_plat(struct udevice *dev)
+{
+	struct sp804_timer_plat *plat = dev_get_plat(dev);
+
+	plat->base = dev_read_addr(dev);
+	if (!plat->base)
+		return -ENOENT;
+
+	return 0;
+}
+
+static int sp804_timer_probe(struct udevice *dev)
+{
+	struct sp804_timer_plat *plat = dev_get_plat(dev);
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct clk base_clk;
+	unsigned int divider = 1;
+	uint32_t ctlr;
+	int ret;
+
+	ctlr = readl(plat->base + SP804_TIMERX_CONTROL);
+	ctlr &= SP804_CTRL_TIMER_PRESCALE_MASK;
+	switch (ctlr >> SP804_CTRL_TIMER_PRESCALE_SHIFT) {
+	case 0x0: divider = 1; break;
+	case 0x1: divider = 16; break;
+	case 0x2: divider = 256; break;
+	case 0x3: printf("illegal!\n"); break;
+	}
+
+	ret = clk_get_by_index(dev, 0, &base_clk);
+	if (ret) {
+		printf("could not find SP804 timer base clock in DT\n");
+		return ret;
+	}
+
+	uc_priv->clock_rate = clk_get_rate(&base_clk) / divider;
+
+	/* keep divider, free-running, wrapping, no IRQs, 32-bit mode */
+	ctlr |= SP804_CTRL_TIMER_32BIT | SP804_CTRL_TIMER_ENABLE;
+	writel(ctlr, plat->base + SP804_TIMERX_CONTROL);
+
+	return 0;
+}
+
+static const struct timer_ops sp804_timer_ops = {
+	.get_count = sp804_timer_get_count,
+};
+
+static const struct udevice_id sp804_timer_ids[] = {
+	{ .compatible = "arm,sp804" },
+	{}
+};
+
+U_BOOT_DRIVER(arm_sp804_timer) = {
+	.name		= "arm_sp804_timer",
+	.id		= UCLASS_TIMER,
+	.of_match 	= sp804_timer_ids,
+	.probe		= sp804_timer_probe,
+	.ops		= &sp804_timer_ops,
+	.plat_auto	= sizeof(struct sp804_timer_plat),
+	.of_to_plat 	= sp804_clk_of_to_plat,
+};
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] highbank: scan into hb_sregs DT subnodes
  2022-10-20 22:10 [PATCH 0/3] timer: add SP804 DM_TIMER driver (and use it) Andre Przywara
  2022-10-20 22:10 ` [PATCH 1/3] timer: add SP804 UCLASS timer driver Andre Przywara
@ 2022-10-20 22:10 ` Andre Przywara
  2022-11-03 16:57   ` Tom Rini
  2022-10-20 22:10 ` [PATCH 3/3] highbank: switch to use the Arm SP804 DM_TIMER driver Andre Przywara
  2 siblings, 1 reply; 7+ messages in thread
From: Andre Przywara @ 2022-10-20 22:10 UTC (permalink / raw)
  To: Tom Rini, Simon Glass; +Cc: u-boot

The DT used for Calxeda Highbank and Midway systems exposes a "system
registers" block, modeled as a DT subnode.
This includes several clocks, including the two fixed clocks for the
main oscillator and timer.

So far U-Boot was ignorant of this special construct (a "clocks" node
within the "hb-sregs" node), as it didn't need the PLL clocks in there.
But that also meant we lost the fixed clocks, which form the base for
the UART baudrate generator and also the SP804 timer.

To allow the generic PL011 and SP804 driver to read the clock rate,
add a simple bus driver, which triggers the DT node discovery inside this
special node. As we only care about the fixed clocks (we don't have
drivers for the PLLs anyway), just ignore the address translation (for
now).

The binding is described in bindings/arm/calxeda/hb-sregs.yaml, the DT
snippet in question looks like:

=======================
	sregs@fff3c000 {
		compatible = "calxeda,hb-sregs";
		reg = <0xfff3c000 0x1000>;

		clocks {
			#address-cells = <1>;
			#size-cells = <0>;

			osc: oscillator {
				#clock-cells = <0>;
				compatible = "fixed-clock";
				clock-frequency = <33333000>;
			};
			....
		};
	};
=======================

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 board/highbank/Makefile   |  2 +-
 board/highbank/hb_sregs.c | 45 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 board/highbank/hb_sregs.c

diff --git a/board/highbank/Makefile b/board/highbank/Makefile
index 57f7f2e2a65..9e432119849 100644
--- a/board/highbank/Makefile
+++ b/board/highbank/Makefile
@@ -3,4 +3,4 @@
 # (C) Copyright 2000-2006
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
-obj-y	:= highbank.o ahci.o
+obj-y	:= highbank.o ahci.o hb_sregs.o
diff --git a/board/highbank/hb_sregs.c b/board/highbank/hb_sregs.c
new file mode 100644
index 00000000000..d9dd2c2bf67
--- /dev/null
+++ b/board/highbank/hb_sregs.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Calxeda Highbank/Midway "system registers" bus driver
+ *
+ * There is a "clocks" subnode inside the top node, which groups all clocks,
+ * both programmable PLLs as well as fixed clocks.
+ * Simple allow the DT enumeration to look inside this node, so that we can
+ * read the fixed clock frequencies using the DM clock framework.
+ *
+ * Copyright (C) 2019 Arm Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/lists.h>
+
+static int hb_sregs_scan_fdt_dev(struct udevice *dev)
+{
+	ofnode clock_node, node;
+
+	/* Search for subnode called "clocks". */
+	ofnode_for_each_subnode(clock_node, dev_ofnode(dev)) {
+		if (!ofnode_name_eq(clock_node, "clocks"))
+			continue;
+
+		/* Enumerate all nodes inside this "clocks" subnode. */
+		ofnode_for_each_subnode(node, clock_node)
+			lists_bind_fdt(dev, node, NULL, NULL, false);
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+static const struct udevice_id highbank_sreg_ids[] = {
+	{ .compatible = "calxeda,hb-sregs" },
+	{}
+};
+
+U_BOOT_DRIVER(hb_sregs) = {
+	.name = "hb-sregs",
+	.id = UCLASS_SIMPLE_BUS,
+	.bind = hb_sregs_scan_fdt_dev,
+	.of_match = highbank_sreg_ids,
+};
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] highbank: switch to use the Arm SP804 DM_TIMER driver
  2022-10-20 22:10 [PATCH 0/3] timer: add SP804 DM_TIMER driver (and use it) Andre Przywara
  2022-10-20 22:10 ` [PATCH 1/3] timer: add SP804 UCLASS timer driver Andre Przywara
  2022-10-20 22:10 ` [PATCH 2/3] highbank: scan into hb_sregs DT subnodes Andre Przywara
@ 2022-10-20 22:10 ` Andre Przywara
  2022-11-03 16:57   ` Tom Rini
  2 siblings, 1 reply; 7+ messages in thread
From: Andre Przywara @ 2022-10-20 22:10 UTC (permalink / raw)
  To: Tom Rini, Simon Glass; +Cc: u-boot

So far the Calxeda machines were using the CONFIG_SYS_TIMER_* macros to
simply hardcode the address of the counter register of the SP804 timer.
This method is deprecated and scheduled for removal.

Use the newly introduced SP804 DM_TIMER driver to provide timer
functionality on Highbank and Midway machines. The base address and base
frequency are taken from the devicetree.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/Kconfig           | 2 ++
 include/configs/highbank.h | 4 ----
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2e833940525..3269d0c5196 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -793,6 +793,8 @@ config ARCH_HIGHBANK
 	select AHCI
 	select DM_ETH
 	select PHYS_64BIT
+	select TIMER
+	select SP804_TIMER
 	imply OF_HAS_PRIOR_STAGE
 
 config ARCH_INTEGRATOR
diff --git a/include/configs/highbank.h b/include/configs/highbank.h
index bb6cc957261..5e2b50bbac1 100644
--- a/include/configs/highbank.h
+++ b/include/configs/highbank.h
@@ -8,10 +8,6 @@
 
 #define CONFIG_SYS_BOOTMAPSZ		(16 << 20)
 
-#define CONFIG_SYS_TIMER_RATE		(150000000/256)
-#define CONFIG_SYS_TIMER_COUNTER	(0xFFF34000 + 0x4)
-#define CONFIG_SYS_TIMER_COUNTS_DOWN
-
 #define CONFIG_PL011_CLOCK		150000000
 
 /*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] timer: add SP804 UCLASS timer driver
  2022-10-20 22:10 ` [PATCH 1/3] timer: add SP804 UCLASS timer driver Andre Przywara
@ 2022-11-03 16:57   ` Tom Rini
  0 siblings, 0 replies; 7+ messages in thread
From: Tom Rini @ 2022-11-03 16:57 UTC (permalink / raw)
  To: Andre Przywara; +Cc: Simon Glass, u-boot

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

On Thu, Oct 20, 2022 at 11:10:23PM +0100, Andre Przywara wrote:

> The "Arm Ltd. Dual-Timer Module (SP804)" is a simple 32-bit count-down
> timer IP with interrupt functionality, and is used in some SoCs from
> various vendors.
> 
> Add a simple DM compliant timer driver, to allow users of the SP804 to
> switch to DM_TIMER.
> 
> This relies on the input clock to be accessible via the DM clock
> framework, which should be fine as we probably look at fixed-clock's
> here anyway.
> We re-program the control register in the probe() function, but keep
> the divider in place, in case this has been set to something on purpose
> before.
> 
> The TRM for the timer IP can be found here:
> https://developer.arm.com/documentation/ddi0271/latest
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>

Applied to u-boot/master, thanks!

-- 
Tom

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] highbank: scan into hb_sregs DT subnodes
  2022-10-20 22:10 ` [PATCH 2/3] highbank: scan into hb_sregs DT subnodes Andre Przywara
@ 2022-11-03 16:57   ` Tom Rini
  0 siblings, 0 replies; 7+ messages in thread
From: Tom Rini @ 2022-11-03 16:57 UTC (permalink / raw)
  To: Andre Przywara; +Cc: Simon Glass, u-boot

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

On Thu, Oct 20, 2022 at 11:10:24PM +0100, Andre Przywara wrote:

> The DT used for Calxeda Highbank and Midway systems exposes a "system
> registers" block, modeled as a DT subnode.
> This includes several clocks, including the two fixed clocks for the
> main oscillator and timer.
> 
> So far U-Boot was ignorant of this special construct (a "clocks" node
> within the "hb-sregs" node), as it didn't need the PLL clocks in there.
> But that also meant we lost the fixed clocks, which form the base for
> the UART baudrate generator and also the SP804 timer.
> 
> To allow the generic PL011 and SP804 driver to read the clock rate,
> add a simple bus driver, which triggers the DT node discovery inside this
> special node. As we only care about the fixed clocks (we don't have
> drivers for the PLLs anyway), just ignore the address translation (for
> now).
> 
> The binding is described in bindings/arm/calxeda/hb-sregs.yaml, the DT
> snippet in question looks like:
> 
> =======================
> 	sregs@fff3c000 {
> 		compatible = "calxeda,hb-sregs";
> 		reg = <0xfff3c000 0x1000>;
> 
> 		clocks {
> 			#address-cells = <1>;
> 			#size-cells = <0>;
> 
> 			osc: oscillator {
> 				#clock-cells = <0>;
> 				compatible = "fixed-clock";
> 				clock-frequency = <33333000>;
> 			};
> 			....
> 		};
> 	};
> =======================
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>

Applied to u-boot/master, thanks!

-- 
Tom

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] highbank: switch to use the Arm SP804 DM_TIMER driver
  2022-10-20 22:10 ` [PATCH 3/3] highbank: switch to use the Arm SP804 DM_TIMER driver Andre Przywara
@ 2022-11-03 16:57   ` Tom Rini
  0 siblings, 0 replies; 7+ messages in thread
From: Tom Rini @ 2022-11-03 16:57 UTC (permalink / raw)
  To: Andre Przywara; +Cc: Simon Glass, u-boot

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

On Thu, Oct 20, 2022 at 11:10:25PM +0100, Andre Przywara wrote:

> So far the Calxeda machines were using the CONFIG_SYS_TIMER_* macros to
> simply hardcode the address of the counter register of the SP804 timer.
> This method is deprecated and scheduled for removal.
> 
> Use the newly introduced SP804 DM_TIMER driver to provide timer
> functionality on Highbank and Midway machines. The base address and base
> frequency are taken from the devicetree.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>

Applied to u-boot/master, thanks!

-- 
Tom

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-11-03 16:59 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-20 22:10 [PATCH 0/3] timer: add SP804 DM_TIMER driver (and use it) Andre Przywara
2022-10-20 22:10 ` [PATCH 1/3] timer: add SP804 UCLASS timer driver Andre Przywara
2022-11-03 16:57   ` Tom Rini
2022-10-20 22:10 ` [PATCH 2/3] highbank: scan into hb_sregs DT subnodes Andre Przywara
2022-11-03 16:57   ` Tom Rini
2022-10-20 22:10 ` [PATCH 3/3] highbank: switch to use the Arm SP804 DM_TIMER driver Andre Przywara
2022-11-03 16:57   ` Tom Rini

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.