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