summaryrefslogtreecommitdiff
path: root/drivers/watchdog/ulp_wdog.c
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2017-02-22 16:21:48 +0800
committerStefano Babic <sbabic@denx.de>2017-03-17 09:27:08 +0100
commit253531bbd9cd2fe39359962bfb4338970bf56185 (patch)
treed577b2842a1183661884933990cce7bb0e6849bc /drivers/watchdog/ulp_wdog.c
parent8359e556f819bfa0f560d4d6a66449b5fa544488 (diff)
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. 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>
Diffstat (limited to 'drivers/watchdog/ulp_wdog.c')
-rw-r--r--drivers/watchdog/ulp_wdog.c98
1 files changed, 98 insertions, 0 deletions
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);
+}