summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2016-11-17 17:10:40 +0800
committerYe Li <ye.li@nxp.com>2016-11-22 17:49:33 +0800
commit444a28ad595b0e787ed88f1ec828d1a32fd65ee4 (patch)
treee00b644caa30050d42735df0c1fded9ae2c34db0
parent049a20d1c74b1517abe8c7ea818748ca651a0f39 (diff)
downloadu-boot-imx-444a28ad595b0e787ed88f1ec828d1a32fd65ee4.zip
u-boot-imx-444a28ad595b0e787ed88f1ec828d1a32fd65ee4.tar.gz
u-boot-imx-444a28ad595b0e787ed88f1ec828d1a32fd65ee4.tar.bz2
MLK-13450-18 wdog: Add the watchdog driver for MX7ULP.
This driver implements the HW WATCHDOG functions. Which needs to set CONFIG_HW_WATCHDOG to use them. This is disabled by default for mx7ulp. We will use watchdog for reset cpu. Implement this in the driver. Need to define CONFIG_ULP_WATCHDOG to build it. Signed-off-by: Ye Li <ye.li@nxp.com> Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/ulp_wdog.c92
2 files changed, 93 insertions, 0 deletions
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a007ae8..350e9b8 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -11,6 +11,7 @@ ifneq (,$(filter $(SOC), mx31 mx35 mx5 mx6 mx7 vf610))
obj-y += imx_watchdog.o
endif
obj-$(CONFIG_S5P) += s5p_wdt.o
+obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o
obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o
obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
diff --git a/drivers/watchdog/ulp_wdog.c b/drivers/watchdog/ulp_wdog.c
new file mode 100644
index 0000000..30dbff6
--- /dev/null
+++ b/drivers/watchdog/ulp_wdog.c
@@ -0,0 +1,92 @@
+#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);
+}