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