1 /*
2 * Copyright 2018 Rockchip Electronics Co., Ltd
3 *
4 */
5 #include <stdio.h>
6 #include <hal_osal.h>
7 #include <barrier.h>
8 #include "sunxi_hal_common.h"
9 #include "platform_watchdog.h"
10
11 #define writel_wdt hal_writel
12 #define readl_wdt hal_readl
13
14 static unsigned long running;
15 static unsigned long running_saved;
16
17 static const int wdt_timeout_map[] =
18 {
19 [1] = 0x1, /* 1s 32000cycles*/
20 [2] = 0x2, /* 2s 64000*/
21 [3] = 0x3, /* 3s 96000*/
22 [4] = 0x4, /* 4s 128000*/
23 [5] = 0x5, /* 5s 160000*/
24 [6] = 0x6, /* 6s 192000*/
25 [8] = 0x7, /* 8s 256000*/
26 [10] = 0x8, /* 10s 320000*/
27 [12] = 0x9, /* 12s 384000*/
28 [14] = 0xA, /* 14s 448000*/
29 [16] = 0xB, /* 16s 512000*/
30 };
31
hal_watchdog_is_running(void)32 int hal_watchdog_is_running(void)
33 {
34
35 return running_saved;
36 }
37
hal_watchdog_suspend(int timeout)38 int hal_watchdog_suspend(int timeout)
39 {
40
41 running_saved = running;
42
43 pr_debug("%s()\n", __func__);
44 if (hal_watchdog_is_running()) {
45 pr_debug("%s()\n", __func__);
46 hal_watchdog_stop(timeout);
47 }
48
49 return 0;
50 }
51
hal_watchdog_resume(int timeout)52 int hal_watchdog_resume(int timeout)
53 {
54
55 pr_debug("%s()\n", __func__);
56 if (hal_watchdog_is_running()) {
57 pr_debug("%s()\n", __func__);
58 hal_watchdog_start(timeout);
59 }
60
61 return 0;
62 }
hal_watchdog_info(void)63 void hal_watchdog_info(void)
64 {
65 struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
66 printf("mode: 0x%x, cfg=0x%x, ctl=0x%x\n",
67 (unsigned int)(wdt->mode), (unsigned int)(wdt->cfg), (unsigned int)(wdt->ctl));
68 }
69
hal_watchdog_disable(void)70 void hal_watchdog_disable(void)
71 {
72 struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
73 unsigned int wtmode;
74
75 pr_debug("%s()\n", __func__);
76 wtmode = readl_wdt(&wdt->mode);
77 wtmode &= ~WDT_MODE_EN;
78 wtmode |= KEY_FIELD_MAGIC;
79
80 writel_wdt(wtmode, &wdt->mode);
81 isb();
82 running = 0;
83 }
84
hal_watchdog_reset(int timeout)85 void hal_watchdog_reset(int timeout)
86 {
87 int timeout_set = timeout;
88 struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
89 unsigned int wtmode;
90
91 pr_debug("%s()\n", __func__);
92 hal_watchdog_disable();
93
94 if (timeout > 16)
95 {
96 timeout_set = 16;
97 }
98
99 if (wdt_timeout_map[timeout_set] == 0)
100 {
101 timeout_set++;
102 }
103
104 wtmode = KEY_FIELD_MAGIC | (wdt_timeout_map[timeout_set] << 4) | WDT_MODE_EN;
105
106 writel_wdt(KEY_FIELD_MAGIC | WDT_CFG_RESET, &wdt->cfg);
107 writel_wdt(wtmode, &wdt->mode);
108
109 isb();
110 writel_wdt(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdt->ctl);
111 running = 1;
112 }
113
hal_watchdog_restart(void)114 void hal_watchdog_restart(void)
115 {
116 struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
117
118 pr_debug("%s()\n", __func__);
119 hal_watchdog_disable();
120
121 /* add delay for watchdog disable */
122 udelay(50);
123 /* Set the watchdog for its shortest interval (.5s) and wait */
124 writel_wdt(KEY_FIELD_MAGIC | WDT_CFG_RESET, &wdt->cfg);
125 isb();
126 writel_wdt(KEY_FIELD_MAGIC | WDT_MODE_EN, &wdt->mode);
127
128 while (1) {};
129 }
130
hal_watchdog_init(void)131 void hal_watchdog_init(void)
132 {
133 pr_debug("%s()\n", __func__);
134 running = 0;
135 running_saved = 0;
136 }
137
hal_watchdog_stop(int timeout)138 void hal_watchdog_stop(int timeout)
139 {
140 pr_debug("%s()\n", __func__);
141 hal_watchdog_disable();
142 }
143
hal_watchdog_start(int timeout)144 void hal_watchdog_start(int timeout)
145 {
146 pr_debug("%s()\n", __func__);
147 hal_watchdog_reset(timeout);
148 }
149
hal_watchdog_feed(void)150 void hal_watchdog_feed(void)
151 {
152 struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
153 pr_debug("%s()\n", __func__);
154 writel_wdt(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdt->ctl);
155 }
156