wdog: Add the watchdog driver for MX7ULP.
authorYe Li <ye.li@nxp.com>
Wed, 22 Feb 2017 08:21:48 +0000 (16:21 +0800)
committerStefano Babic <sbabic@denx.de>
Fri, 17 Mar 2017 08:27:08 +0000 (09:27 +0100)
This driver implements the HW WATCHDOG functions. Which needs
to set CONFIG_HW_WATCHDOG to use them. This is disabled by default for
mx7ulp.

Use watchdog for reset cpu. Implement this in the driver.
Need to define CONFIG_ULP_WATCHDOG to build it.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Cc: Stefano Babic <sbabic@denx.de>
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/ulp_wdog.c [new file with mode: 0644]

index e69de29..dbdaafc 100644 (file)
@@ -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
index a007ae8..dea1836 100644 (file)
@@ -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 (file)
index 0000000..72ec694
--- /dev/null
@@ -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);
+}