blob: 1b286816b574877e875ed6c034c6bfcf61a2dc9a [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Ye Li253531b2017-02-22 16:21:48 +08002/*
3 * Copyright (C) 2016 Freescale Semiconductor, Inc.
Ye Li253531b2017-02-22 16:21:48 +08004 */
5
6#include <common.h>
Simon Glass9a3b4ce2019-12-28 10:45:01 -07007#include <cpu_func.h>
Ye Li253531b2017-02-22 16:21:48 +08008#include <asm/io.h>
9#include <asm/arch/imx-regs.h>
10
11/*
12 * MX7ULP WDOG Register Map
13 */
14struct wdog_regs {
Breno Limaedf95bd2021-06-29 10:32:35 +080015 u32 cs;
Ye Li253531b2017-02-22 16:21:48 +080016 u32 cnt;
17 u32 toval;
18 u32 win;
19};
20
21#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
22#define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500
23#endif
24
25#define REFRESH_WORD0 0xA602 /* 1st refresh word */
26#define REFRESH_WORD1 0xB480 /* 2nd refresh word */
27
28#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
29#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
30
Ye Lia79f2002022-10-21 16:41:15 +080031#define UNLOCK_WORD 0xD928C520 /* unlock word */
32#define REFRESH_WORD 0xB480A602 /* refresh word */
33
Breno Limaedf95bd2021-06-29 10:32:35 +080034#define WDGCS_WDGE BIT(7)
35#define WDGCS_WDGUPDATE BIT(5)
Ye Li253531b2017-02-22 16:21:48 +080036
Breno Limaedf95bd2021-06-29 10:32:35 +080037#define WDGCS_RCS BIT(10)
38#define WDGCS_ULK BIT(11)
Alice Guoef0ad9b2022-10-21 16:41:16 +080039#define WDOG_CS_PRES BIT(12)
Ye Lia79f2002022-10-21 16:41:15 +080040#define WDGCS_CMD32EN BIT(13)
Breno Limaedf95bd2021-06-29 10:32:35 +080041#define WDGCS_FLG BIT(14)
Alice Guoa7fd6332022-10-21 16:41:17 +080042#define WDGCS_INT BIT(6)
Ye Li253531b2017-02-22 16:21:48 +080043
44#define WDG_BUS_CLK (0x0)
45#define WDG_LPO_CLK (0x1)
46#define WDG_32KHZ_CLK (0x2)
47#define WDG_EXT_CLK (0x3)
48
Ye Li253531b2017-02-22 16:21:48 +080049void hw_watchdog_set_timeout(u16 val)
50{
51 /* setting timeout value */
52 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
53
54 writel(val, &wdog->toval);
55}
56
57void hw_watchdog_reset(void)
58{
59 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
60
Ye Lia79f2002022-10-21 16:41:15 +080061 if (readl(&wdog->cs) & WDGCS_CMD32EN) {
62 writel(REFRESH_WORD, &wdog->cnt);
63 } else {
64 dmb();
65 __raw_writel(REFRESH_WORD0, &wdog->cnt);
66 __raw_writel(REFRESH_WORD1, &wdog->cnt);
67 dmb();
68 }
Ye Li253531b2017-02-22 16:21:48 +080069}
70
71void hw_watchdog_init(void)
72{
Ye Li253531b2017-02-22 16:21:48 +080073 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
Ye Lia79f2002022-10-21 16:41:15 +080074 u32 cmd32 = 0;
Ye Li253531b2017-02-22 16:21:48 +080075
Ye Lia79f2002022-10-21 16:41:15 +080076 if (readl(&wdog->cs) & WDGCS_CMD32EN) {
77 writel(UNLOCK_WORD, &wdog->cnt);
78 cmd32 = WDGCS_CMD32EN;
79 } else {
80 dmb();
81 __raw_writel(UNLOCK_WORD0, &wdog->cnt);
82 __raw_writel(UNLOCK_WORD1, &wdog->cnt);
83 dmb();
84 }
Ye Li253531b2017-02-22 16:21:48 +080085
Breno Limaedf95bd2021-06-29 10:32:35 +080086 /* Wait WDOG Unlock */
87 while (!(readl(&wdog->cs) & WDGCS_ULK))
88 ;
Ye Li253531b2017-02-22 16:21:48 +080089
90 hw_watchdog_set_timeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
91 writel(0, &wdog->win);
92
Breno Limaedf95bd2021-06-29 10:32:35 +080093 /* setting 1-kHz clock source, enable counter running, and clear interrupt */
Alice Guoef0ad9b2022-10-21 16:41:16 +080094 if (IS_ENABLED(CONFIG_ARCH_IMX9))
95 writel((cmd32 | WDGCS_WDGE | WDGCS_WDGUPDATE | (WDG_LPO_CLK << 8) |
Alice Guoa7fd6332022-10-21 16:41:17 +080096 WDGCS_FLG | WDOG_CS_PRES | WDGCS_INT), &wdog->cs);
Alice Guoef0ad9b2022-10-21 16:41:16 +080097 else
98 writel((cmd32 | WDGCS_WDGE | WDGCS_WDGUPDATE | (WDG_LPO_CLK << 8) |
99 WDGCS_FLG), &wdog->cs);
Breno Limaedf95bd2021-06-29 10:32:35 +0800100
101 /* Wait WDOG reconfiguration */
102 while (!(readl(&wdog->cs) & WDGCS_RCS))
103 ;
Ye Li253531b2017-02-22 16:21:48 +0800104
105 hw_watchdog_reset();
106}
107
Harald Seiler35b65dd2020-12-15 16:47:52 +0100108void reset_cpu(void)
Ye Li253531b2017-02-22 16:21:48 +0800109{
110 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
Ye Lia79f2002022-10-21 16:41:15 +0800111 u32 cmd32 = 0;
Ye Li253531b2017-02-22 16:21:48 +0800112
Ye Lia79f2002022-10-21 16:41:15 +0800113 if (readl(&wdog->cs) & WDGCS_CMD32EN) {
114 writel(UNLOCK_WORD, &wdog->cnt);
115 cmd32 = WDGCS_CMD32EN;
116 } else {
117 dmb();
118 __raw_writel(UNLOCK_WORD0, &wdog->cnt);
119 __raw_writel(UNLOCK_WORD1, &wdog->cnt);
120 dmb();
121 }
Ye Li253531b2017-02-22 16:21:48 +0800122
Breno Limaedf95bd2021-06-29 10:32:35 +0800123 /* Wait WDOG Unlock */
124 while (!(readl(&wdog->cs) & WDGCS_ULK))
125 ;
126
Alice Guoef0ad9b2022-10-21 16:41:16 +0800127 hw_watchdog_set_timeout(5); /* 5ms timeout for general; 40ms timeout for imx93 */
Ye Li253531b2017-02-22 16:21:48 +0800128 writel(0, &wdog->win);
129
Breno Limaedf95bd2021-06-29 10:32:35 +0800130 /* enable counter running */
Alice Guoef0ad9b2022-10-21 16:41:16 +0800131 if (IS_ENABLED(CONFIG_ARCH_IMX9))
Alice Guoa7fd6332022-10-21 16:41:17 +0800132 writel((cmd32 | WDGCS_WDGE | (WDG_LPO_CLK << 8) | WDOG_CS_PRES |
133 WDGCS_INT), &wdog->cs);
Alice Guoef0ad9b2022-10-21 16:41:16 +0800134 else
135 writel((cmd32 | WDGCS_WDGE | (WDG_LPO_CLK << 8)), &wdog->cs);
Breno Limaedf95bd2021-06-29 10:32:35 +0800136
137 /* Wait WDOG reconfiguration */
138 while (!(readl(&wdog->cs) & WDGCS_RCS))
139 ;
Ye Li253531b2017-02-22 16:21:48 +0800140
141 hw_watchdog_reset();
142
143 while (1);
144}