summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/Kconfig8
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/ulp_wdog.c98
3 files changed, 107 insertions, 0 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e69de29bb2..dbdaafc149 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -0,0 +1,8 @@
+menu "WATCHDOG support"
+
+config ULP_WATCHDOG
+ bool "i.MX7ULP watchdog"
+ help
+ Say Y here to enable i.MX7ULP watchdog driver.
+
+endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a007ae8234..dea18363ca 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o
obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
+obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o
diff --git a/drivers/watchdog/ulp_wdog.c b/drivers/watchdog/ulp_wdog.c
new file mode 100644
index 0000000000..72ec694cdd
--- /dev/null
+++ b/drivers/watchdog/ulp_wdog.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/*
+ * MX7ULP WDOG Register Map
+ */
+struct wdog_regs {
+ u8 cs1;
+ u8 cs2;
+ u16 reserve0;
+ u32 cnt;
+ u32 toval;
+ u32 win;
+};
+
+#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
+#define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500
+#endif
+
+#define REFRESH_WORD0 0xA602 /* 1st refresh word */
+#define REFRESH_WORD1 0xB480 /* 2nd refresh word */
+
+#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
+#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
+
+#define WDGCS1_WDGE (1<<7)
+#define WDGCS1_WDGUPDATE (1<<5)
+
+#define WDGCS2_FLG (1<<6)
+
+#define WDG_BUS_CLK (0x0)
+#define WDG_LPO_CLK (0x1)
+#define WDG_32KHZ_CLK (0x2)
+#define WDG_EXT_CLK (0x3)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void hw_watchdog_set_timeout(u16 val)
+{
+ /* setting timeout value */
+ struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
+
+ writel(val, &wdog->toval);
+}
+
+void hw_watchdog_reset(void)
+{
+ struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
+
+ writel(REFRESH_WORD0, &wdog->cnt);
+ writel(REFRESH_WORD1, &wdog->cnt);
+}
+
+void hw_watchdog_init(void)
+{
+ u8 val;
+ struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
+
+ writel(UNLOCK_WORD0, &wdog->cnt);
+ writel(UNLOCK_WORD1, &wdog->cnt);
+
+ val = readb(&wdog->cs2);
+ val |= WDGCS2_FLG;
+ writeb(val, &wdog->cs2);
+
+ hw_watchdog_set_timeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
+ writel(0, &wdog->win);
+
+ writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */
+ writeb((WDGCS1_WDGE | WDGCS1_WDGUPDATE), &wdog->cs1);/* enable counter running */
+
+ hw_watchdog_reset();
+}
+
+void reset_cpu(ulong addr)
+{
+ struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
+
+ writel(UNLOCK_WORD0, &wdog->cnt);
+ writel(UNLOCK_WORD1, &wdog->cnt);
+
+ hw_watchdog_set_timeout(5); /* 5ms timeout */
+ writel(0, &wdog->win);
+
+ writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */
+ writeb(WDGCS1_WDGE, &wdog->cs1);/* enable counter running */
+
+ hw_watchdog_reset();
+
+ while (1);
+}