1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2019-07-29 zdzn first version
9 */
10 #include "drv_wdt.h"
11
12 #ifdef BSP_USING_WDT
13
14 #define SECS_TO_WDOG_TICKS(x) ((x) << 16)
15 #define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
16
17 static struct raspi_wdt_driver bcm_wdt;
18
raspi_watchdog_init(rt_uint32_t time_init)19 void raspi_watchdog_init(rt_uint32_t time_init)
20 {
21 bcm_wdt.timeout = time_init;
22 }
23
raspi_watchdog_start()24 void raspi_watchdog_start()
25 {
26 volatile rt_uint32_t cur;
27 PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET);
28 cur = PM_RSTC;
29 PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
30 }
31
raspi_watchdog_stop()32 void raspi_watchdog_stop()
33 {
34 PM_RSTC = PM_PASSWORD | PM_RSTC_RESET;
35 }
36
raspi_watchdog_clr()37 void raspi_watchdog_clr()
38 {
39 bcm_wdt.timeout = 0;
40 }
41
raspi_watchdog_set_timeout(rt_uint32_t timeout_us)42 void raspi_watchdog_set_timeout(rt_uint32_t timeout_us)
43 {
44 bcm_wdt.timeout = timeout_us;
45 }
46
raspi_watchdog_get_timeout()47 rt_uint64_t raspi_watchdog_get_timeout()
48 {
49 return bcm_wdt.timeout;
50 }
51
raspi_watchdog_get_timeleft()52 rt_uint64_t raspi_watchdog_get_timeleft()
53 {
54 rt_uint32_t ret = PM_WDOG;
55 return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
56 }
57
raspi_wdg_init(rt_watchdog_t * wdt)58 static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt)
59 {
60 /*init for 10S*/
61 raspi_watchdog_init(1000000);
62 raspi_watchdog_start();
63 raspi_watchdog_stop();
64 return RT_EOK;
65 }
66
raspi_wdg_control(rt_watchdog_t * wdt,int cmd,void * arg)67 static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg)
68 {
69 rt_uint64_t timeout_us = 0;
70 switch (cmd)
71 {
72 case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
73 timeout_us = *((rt_uint32_t *)arg) * 1000000;
74 if (timeout_us >= 0xFFFFFFFF)
75 timeout_us = 0xFFFFFFFF;
76 raspi_watchdog_set_timeout((rt_uint32_t)timeout_us);
77 break;
78 case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
79 timeout_us = raspi_watchdog_get_timeout();
80 *((rt_uint32_t *)arg) = timeout_us / 1000000;
81 break;
82 case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
83 timeout_us = raspi_watchdog_get_timeleft();
84 *((rt_uint32_t *)arg) = timeout_us / 1000000;
85 break;
86 case RT_DEVICE_CTRL_WDT_KEEPALIVE:
87 raspi_watchdog_clr();
88 break;
89 case RT_DEVICE_CTRL_WDT_START:
90 raspi_watchdog_start();
91 break;
92 case RT_DEVICE_CTRL_WDT_STOP:
93 raspi_watchdog_stop();
94 break;
95 default:
96 return -RT_EIO;
97 }
98 return RT_EOK;
99 }
100
101 static const struct rt_watchdog_ops raspi_wdg_pos =
102 {
103 raspi_wdg_init,
104 raspi_wdg_control,
105 };
106
107 static rt_watchdog_t raspi_wdg;
108
rt_hw_wdt_init(void)109 int rt_hw_wdt_init(void)
110 {
111 raspi_wdg.ops = &raspi_wdg_pos;
112 rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL);
113 return RT_EOK;
114 }
115
116 INIT_DEVICE_EXPORT(rt_hw_wdt_init);
117
118 /**
119 * Reboot
120 */
reboot(void)121 int reboot(void)
122 {
123 unsigned int r;
124
125 rt_kprintf("reboot system...\n");
126 rt_thread_mdelay(100);
127 // trigger a restart by instructing the GPU to boot from partition 0
128 r = PM_RSTS; r &= ~0xfffffaaa;
129 PM_RSTS = PM_PASSWORD | r; // boot from partition 0
130 PM_WDOG = PM_PASSWORD | 10;
131 PM_RSTC = PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
132
133 while (1);
134
135 return 0;
136 }
137 MSH_CMD_EXPORT(reboot,reboot system...);
138
139 #endif /*BSP_USING_WDT */
140