@@ -12,6 +12,13 @@ config BCM2835_WDT
This provides basic infrastructure to support BCM2835/2836 watchdog
hardware, with a max timeout of ~15secs.
+config ORION_WATCHDOG
+ bool "Enable "
+ select HW_WATCHDOG
+ help
+ Say Y here to enable the Orion watchdog, which can be found on some
+ Marvell Armada chips.
+
config ULP_WATCHDOG
bool "i.MX7ULP watchdog"
help
@@ -19,3 +19,4 @@ obj-$(CONFIG_WDT) += wdt-uclass.o
obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
+obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
new file mode 100644
@@ -0,0 +1,128 @@
+/*
+ * drivers/watchdog/orion_wdt.c
+ *
+ * Watchdog driver for Orion/Kirkwood processors
+ *
+ * Authors: Tomas Hlavacek <tmshlvck@gmail.com>
+ * Sylver Bruneau <sylver.bruneau@googlemail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+
+/*
+ * Watchdog timer block registers.
+ */
+
+#define ORION_WDT_REG MVEBU_REGISTER(0x20300)
+#define ORION_WDT_RSTOUTREG MVEBU_REGISTER(0x20704)
+#define ORION_WDT_RSTOUTMASKREG MVEBU_REGISTER(0x18260)
+
+#define RSTOUT_ENABLE_BIT BIT(8)
+#define RSTOUT_MASK_BIT BIT(10)
+#define WDT_ENABLE_BIT BIT(8)
+
+#define ORION_WDT_COUNTER_OFFSET 0x34
+
+
+#define TIMER_CTRL 0x0000
+#define TIMER_A370_STATUS 0x04
+
+#define WDT_MAX_CYCLE_COUNT 0xffffffff
+
+#define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
+#define WDT_A370_EXPIRED BIT(31)
+
+#define FIXED_CLKRATE 25000000 /* Hz */
+#ifndef ORION_WDT_TIMEOUT
+#define ORION_WDT_TIMEOUT 120 /* sec */
+#endif
+
+
+static int orion_wdt_ping(void)
+{
+ /* Reload watchdog duration */
+ writel((u32)FIXED_CLKRATE * ORION_WDT_TIMEOUT,
+ ORION_WDT_REG + ORION_WDT_COUNTER_OFFSET);
+ return 0;
+}
+
+static int orion_wdt_start(void)
+{
+ u32 reg;
+
+ /* Enable the fixed watchdog clock input */
+ reg = readl(ORION_WDT_REG + TIMER_CTRL);
+ reg |= WDT_AXP_FIXED_ENABLE_BIT;
+ writel(reg, ORION_WDT_REG + TIMER_CTRL);
+
+ /* Set watchdog duration */
+ writel((u32)FIXED_CLKRATE * ORION_WDT_TIMEOUT,
+ ORION_WDT_REG + ORION_WDT_COUNTER_OFFSET);
+
+ /* Clear the watchdog expiration bit */
+ reg = readl(ORION_WDT_REG + TIMER_A370_STATUS);
+ reg &= ~WDT_A370_EXPIRED;
+ writel(reg, ORION_WDT_REG + TIMER_A370_STATUS);
+
+ /* Enable watchdog timer */
+ reg = readl(ORION_WDT_REG + TIMER_CTRL);
+ reg |= WDT_ENABLE_BIT;
+ writel(reg, ORION_WDT_REG + TIMER_CTRL);
+
+ /* Enable reset on watchdog */
+ reg = readl(ORION_WDT_RSTOUTREG);
+ reg |= RSTOUT_ENABLE_BIT;
+ writel(reg, ORION_WDT_RSTOUTREG);
+
+ reg = readl(ORION_WDT_RSTOUTMASKREG);
+ reg &= ~RSTOUT_MASK_BIT;
+ writel(reg, ORION_WDT_RSTOUTMASKREG);
+
+ return 0;
+}
+
+static int orion_wdt_stop(void)
+{
+ u32 reg;
+
+ /* Disable reset on watchdog */
+ reg = readl(ORION_WDT_RSTOUTMASKREG);
+ reg |= RSTOUT_MASK_BIT;
+ writel(reg, ORION_WDT_RSTOUTMASKREG);
+
+ reg = readl(ORION_WDT_RSTOUTREG);
+ reg &= ~RSTOUT_ENABLE_BIT;
+ writel(reg, ORION_WDT_RSTOUTREG);
+
+ /* Disable watchdog timer */
+ reg = readl(ORION_WDT_REG + TIMER_CTRL);
+ reg &= ~WDT_ENABLE_BIT;
+ writel(reg, ORION_WDT_REG + TIMER_CTRL);
+
+ return 0;
+}
+
+void hw_watchdog_disable(void)
+{
+ orion_wdt_stop();
+}
+
+void hw_watchdog_reset(void)
+{
+ orion_wdt_ping();
+}
+
+void hw_watchdog_init(void)
+{
+ orion_wdt_start();
+}
+
This watchdog can be found on some Armada chips. Signed-off-by: Marek Behun <marek.behun@nic.cz> --- drivers/watchdog/Kconfig | 7 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/orion_wdt.c | 128 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 drivers/watchdog/orion_wdt.c