]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
zynq: Convert arm twd timer to DM driver
authorStefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
Fri, 5 Aug 2022 06:16:28 +0000 (08:16 +0200)
committerMichal Simek <michal.simek@amd.com>
Mon, 12 Sep 2022 10:03:17 +0000 (12:03 +0200)
Move arm twd timer driver from zynq to generic location.

DM timer drivers are designed differently to original driver. Timer is
counting up and not down.
Information about clock rates are find out in timer_pre_probe() that's
why there is no need to get any additional information from DT in the
driver itself (only register offset).

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
Link: https://lore.kernel.org/r/20220805061629.1207-1-stefan.herbrechtsmeier-oss@weidmueller.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
arch/arm/Kconfig
arch/arm/dts/zynq-7000.dtsi
arch/arm/mach-zynq/Makefile
arch/arm/mach-zynq/clk.c
arch/arm/mach-zynq/timer.c [deleted file]
drivers/timer/Kconfig
drivers/timer/Makefile
drivers/timer/arm_twd_timer.c [new file with mode: 0644]

index d6c5658ee8827102d35228b496ab90ee4e32ba00..3649222470eacbd516f403609ca49a43deb08ad1 100644 (file)
@@ -1259,6 +1259,7 @@ config ARCH_VF610
 
 config ARCH_ZYNQ
        bool "Xilinx Zynq based platform"
+       select ARM_TWD_TIMER
        select CLK
        select CLK_ZYNQ
        select CPU_V7A
@@ -1278,7 +1279,9 @@ config ARCH_ZYNQ
        select SPL_DM_SPI_FLASH if SPL
        select SPL_OF_CONTROL if SPL
        select SPL_SEPARATE_BSS if SPL
+       select SPL_TIMER if SPL
        select SUPPORT_SPL
+       select TIMER
        imply ARCH_EARLY_INIT_R
        imply BOARD_LATE_INIT
        imply CMD_CLK
index 37155df0fd42db3c995a557321a6220783b8aa5a..a7ca00fb76c6d8ff8801268e3ca77348110f40f4 100644 (file)
                };
 
                scutimer: timer@f8f00600 {
+                       u-boot,dm-pre-reloc;
                        interrupt-parent = <&intc>;
                        interrupts = <1 13 0x301>;
                        compatible = "arm,cortex-a9-twd-timer";
index 8737f434d93fed2798be98b8c01c57c331f6ad4a..d9b2b999e109d0c67956223a6deb0ea55f75e3c8 100644 (file)
@@ -6,7 +6,6 @@
 # (C) Copyright 2008
 # Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
 
-obj-y  := timer.o
 obj-y  += cpu.o
 obj-y  += ddrc.o
 obj-y  += slcr.o
index 27f6bf2183213793b295f3023fea029e41459673..1945f60e08f9f3234acf334309bd33d122786437 100644 (file)
@@ -52,10 +52,12 @@ int set_cpu_clk_info(void)
                        return ret;
 
                rate = clk_get_rate(&clk) / 1000000;
-               if (i)
+               if (i) {
                        gd->bd->bi_ddr_freq = rate;
-               else
+               } else {
                        gd->bd->bi_arm_freq = rate;
+                       gd->cpu_clk = clk_get_rate(&clk);
+               }
 
                clk_free(&clk);
        }
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
deleted file mode 100644 (file)
index a51822a..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2017 Weidmüller Interface GmbH & Co. KG
- * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
- *
- * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2011-2017 Xilinx, Inc. All rights reserved.
- *
- * (C) Copyright 2008
- * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
- *
- * (C) Copyright 2004
- * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
- *
- * (C) Copyright 2002-2004
- * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
- *
- * (C) Copyright 2003
- * Texas Instruments <www.ti.com>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger@sysgo.de>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Alex Zuepke <azu@sysgo.de>
- */
-
-#include <clk.h>
-#include <common.h>
-#include <div64.h>
-#include <dm.h>
-#include <init.h>
-#include <time.h>
-#include <malloc.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/clk.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct scu_timer {
-       u32 load; /* Timer Load Register */
-       u32 counter; /* Timer Counter Register */
-       u32 control; /* Timer Control Register */
-};
-
-static struct scu_timer *timer_base =
-                             (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR;
-
-#define SCUTIMER_CONTROL_PRESCALER_MASK        0x0000FF00 /* Prescaler */
-#define SCUTIMER_CONTROL_PRESCALER_SHIFT       8
-#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK      0x00000002 /* Auto-reload */
-#define SCUTIMER_CONTROL_ENABLE_MASK           0x00000001 /* Timer enable */
-
-#define TIMER_LOAD_VAL 0xFFFFFFFF
-#define TIMER_PRESCALE 255
-
-int timer_init(void)
-{
-       const u32 emask = SCUTIMER_CONTROL_AUTO_RELOAD_MASK |
-                       (TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
-                       SCUTIMER_CONTROL_ENABLE_MASK;
-
-       struct udevice *dev;
-       struct clk clk;
-       int ret;
-
-       ret = uclass_get_device_by_driver(UCLASS_CLK,
-               DM_DRIVER_GET(zynq_clk), &dev);
-       if (ret)
-               return ret;
-
-       clk.id = cpu_6or4x_clk;
-       ret = clk_request(dev, &clk);
-       if (ret < 0)
-               return ret;
-
-       gd->cpu_clk = clk_get_rate(&clk);
-
-       clk_free(&clk);
-
-       gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
-
-       /* Load the timer counter register */
-       writel(0xFFFFFFFF, &timer_base->load);
-
-       /*
-        * Start the A9Timer device
-        * Enable Auto reload mode, Clear prescaler control bits
-        * Set prescaler value, Enable the decrementer
-        */
-       clrsetbits_le32(&timer_base->control, SCUTIMER_CONTROL_PRESCALER_MASK,
-                                                               emask);
-
-       /* Reset time */
-       gd->arch.lastinc = readl(&timer_base->counter) /
-                               (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
-       gd->arch.tbl = 0;
-
-       return 0;
-}
-
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
-{
-       return gd->arch.timer_rate_hz;
-}
index 404929014810650393093b373af6bb535b56c8e6..1b49236039645661e4c69ccd4611853798c9be9e 100644 (file)
@@ -73,6 +73,12 @@ config ARC_TIMER
          usually at least one of them exists. Either of them is supported
          in U-Boot.
 
+config ARM_TWD_TIMER
+       bool "ARM timer watchdog (TWD) timer support"
+       depends on TIMER && CLK
+       help
+         Select this to enable support for the ARM global timer watchdog timer.
+
 config AST_TIMER
        bool "Aspeed ast2400/ast2500 timer support"
        depends on TIMER
index 560e2d27e14f37bbbb2ba92e03d5fb0b5ee7e472..7bfb7749e97939db49dc4cfbb8d96cb106e2f251 100644 (file)
@@ -6,6 +6,7 @@ obj-y += timer-uclass.o
 obj-$(CONFIG_ALTERA_TIMER)     += altera_timer.o
 obj-$(CONFIG_ANDES_PLMT_TIMER) += andes_plmt_timer.o
 obj-$(CONFIG_ARC_TIMER)        += arc_timer.o
+obj-$(CONFIG_ARM_TWD_TIMER)    += arm_twd_timer.o
 obj-$(CONFIG_AST_TIMER)        += ast_timer.o
 obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
 obj-$(CONFIG_$(SPL_)ATMEL_PIT_TIMER) += atmel_pit_timer.o
diff --git a/drivers/timer/arm_twd_timer.c b/drivers/timer/arm_twd_timer.c
new file mode 100644 (file)
index 0000000..40ccd16
--- /dev/null
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017-2022 Weidmüller Interface GmbH & Co. KG
+ * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
+ *
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2011-2017 Xilinx, Inc. All rights reserved.
+ *
+ * (C) Copyright 2008
+ * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
+ *
+ * (C) Copyright 2004
+ * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
+ *
+ * (C) Copyright 2002-2004
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2003
+ * Texas Instruments <www.ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <timer.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+
+#define SCUTIMER_CONTROL_PRESCALER_MASK                0x0000FF00 /* Prescaler */
+#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK      0x00000002 /* Auto-reload */
+#define SCUTIMER_CONTROL_ENABLE_MASK           0x00000001 /* Timer enable */
+
+#define TIMER_LOAD_VAL 0xFFFFFFFF
+
+struct arm_twd_timer_regs {
+       u32 load; /* Timer Load Register */
+       u32 counter; /* Timer Counter Register */
+       u32 control; /* Timer Control Register */
+};
+
+struct arm_twd_timer_priv {
+       struct arm_twd_timer_regs *base;
+};
+
+static u64 arm_twd_timer_get_count(struct udevice *dev)
+{
+       struct arm_twd_timer_priv *priv = dev_get_priv(dev);
+       struct arm_twd_timer_regs *regs = priv->base;
+       u32 count = TIMER_LOAD_VAL - readl(&regs->counter);
+
+       return timer_conv_64(count);
+}
+
+static int arm_twd_timer_probe(struct udevice *dev)
+{
+       struct arm_twd_timer_priv *priv = dev_get_priv(dev);
+       struct arm_twd_timer_regs *regs;
+       fdt_addr_t addr;
+
+       addr = dev_read_addr(dev);
+       if (addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       priv->base = (struct arm_twd_timer_regs *)addr;
+
+       regs = priv->base;
+
+       /* Load the timer counter register */
+       writel(0xFFFFFFFF, &regs->load);
+
+       /*
+        * Start the A9Timer device
+        * Enable Auto reload mode, Clear prescaler control bits
+        * Set prescaler value, Enable the decrementer
+        */
+       clrsetbits_le32(&regs->control, SCUTIMER_CONTROL_PRESCALER_MASK,
+                       SCUTIMER_CONTROL_AUTO_RELOAD_MASK |
+                       SCUTIMER_CONTROL_ENABLE_MASK);
+
+       return 0;
+}
+
+static const struct timer_ops arm_twd_timer_ops = {
+       .get_count = arm_twd_timer_get_count,
+};
+
+static const struct udevice_id arm_twd_timer_ids[] = {
+       { .compatible = "arm,cortex-a9-twd-timer" },
+       {}
+};
+
+U_BOOT_DRIVER(arm_twd_timer) = {
+       .name = "arm_twd_timer",
+       .id = UCLASS_TIMER,
+       .of_match = arm_twd_timer_ids,
+       .priv_auto      = sizeof(struct arm_twd_timer_priv),
+       .probe = arm_twd_timer_probe,
+       .ops = &arm_twd_timer_ops,
+};