wdt: Add MT7621 watchdog driver
authorStefan Roese <sr@denx.de>
Thu, 4 Oct 2018 11:39:07 +0000 (13:39 +0200)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Sun, 18 Nov 2018 15:02:22 +0000 (16:02 +0100)
This patch adds watchdog support for the Mediatek MT7621 SoC. The driver
is loosly based on the Linux kernel version.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
[fixed merge conflict in drivers/watchdog/Kconfig]
Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/mt7621_wdt.c [new file with mode: 0644]

index a911dba73a4c439d5f9101ed30eba5ccde3fd6d3..4796da082395661f37020a9cf1ac67a2f7dfdd6c 100644 (file)
@@ -128,4 +128,12 @@ config WDT_AT91
 config AT91_HW_WDT_TIMEOUT
        bool "AT91 watchdog timeout specified"
        depends on WDT_AT91
+
+config WDT_MT7621
+       bool "MediaTek MT7621 watchdog timer support"
+       depends on WDT && ARCH_MT7620
+       help
+          Select this to enable Ralink / Mediatek watchdog timer,
+          which can be found on some MediaTek chips.
+
 endmenu
index a5c27b0f4cf86633066a571686fb608cc2d3121c..b8f2842f7ec22f3e61ffc64bb74de3c21b0ef6fa 100644 (file)
@@ -23,3 +23,4 @@ obj-$(CONFIG_BCM2835_WDT)       += bcm2835_wdt.o
 obj-$(CONFIG_WDT_ORION) += orion_wdt.o
 obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
 obj-$(CONFIG_MPC8xx_WATCHDOG) += mpc8xx_wdt.o
+obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
diff --git a/drivers/watchdog/mt7621_wdt.c b/drivers/watchdog/mt7621_wdt.c
new file mode 100644 (file)
index 0000000..3886614
--- /dev/null
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Ralink / Mediatek RT288x/RT3xxx/MT76xx built-in hardware watchdog timer
+ *
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ *
+ * Based on the Linux driver version which is:
+ *   Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *   Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <linux/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mt762x_wdt {
+       void __iomem *regs;
+};
+
+#define TIMER_REG_TMRSTAT              0x00
+#define TIMER_REG_TMR1CTL              0x20
+#define TIMER_REG_TMR1LOAD             0x24
+
+#define TMR1CTL_ENABLE                 BIT(7)
+#define TMR1CTL_RESTART                        BIT(9)
+#define TMR1CTL_PRESCALE_SHIFT         16
+
+static int mt762x_wdt_ping(struct mt762x_wdt *priv)
+{
+       writel(TMR1CTL_RESTART, priv->regs + TIMER_REG_TMRSTAT);
+
+       return 0;
+}
+
+static int mt762x_wdt_start(struct udevice *dev, u64 ms, ulong flags)
+{
+       struct mt762x_wdt *priv = dev_get_priv(dev);
+
+       /* set the prescaler to 1ms == 1000us */
+       writel(1000 << TMR1CTL_PRESCALE_SHIFT, priv->regs + TIMER_REG_TMR1CTL);
+       writel(ms, priv->regs + TIMER_REG_TMR1LOAD);
+
+       setbits_le32(priv->regs + TIMER_REG_TMR1CTL, TMR1CTL_ENABLE);
+
+       return 0;
+}
+
+static int mt762x_wdt_stop(struct udevice *dev)
+{
+       struct mt762x_wdt *priv = dev_get_priv(dev);
+
+       mt762x_wdt_ping(priv);
+
+       clrbits_le32(priv->regs + TIMER_REG_TMR1CTL, TMR1CTL_ENABLE);
+
+       return 0;
+}
+
+static int mt762x_wdt_reset(struct udevice *dev)
+{
+       struct mt762x_wdt *priv = dev_get_priv(dev);
+
+       mt762x_wdt_ping(priv);
+
+       return 0;
+}
+
+static int mt762x_wdt_probe(struct udevice *dev)
+{
+       struct mt762x_wdt *priv = dev_get_priv(dev);
+
+       priv->regs = dev_remap_addr(dev);
+       if (!priv->regs)
+               return -EINVAL;
+
+       mt762x_wdt_stop(dev);
+
+       return 0;
+}
+
+static const struct wdt_ops mt762x_wdt_ops = {
+       .start = mt762x_wdt_start,
+       .reset = mt762x_wdt_reset,
+       .stop = mt762x_wdt_stop,
+};
+
+static const struct udevice_id mt762x_wdt_ids[] = {
+       { .compatible = "mediatek,mt7621-wdt" },
+       {}
+};
+
+U_BOOT_DRIVER(mt762x_wdt) = {
+       .name = "mt762x_wdt",
+       .id = UCLASS_WDT,
+       .of_match = mt762x_wdt_ids,
+       .probe = mt762x_wdt_probe,
+       .priv_auto_alloc_size = sizeof(struct mt762x_wdt),
+       .ops = &mt762x_wdt_ops,
+};