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