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