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