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