/* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-10-26 bigmagic first version */ #include #include "drv_wdt.h" #include "raspi4.h" #ifdef BSP_USING_WDT #define SECS_TO_WDOG_TICKS(x) ((x) << 16) #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) static struct raspi_wdt_driver bcm_wdt; void raspi_watchdog_init(rt_uint32_t time_init) { bcm_wdt.timeout = time_init; } void raspi_watchdog_start() { volatile rt_uint32_t cur; PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET); cur = (PM_RSTC); PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; } void raspi_watchdog_stop() { PM_RSTC = PM_PASSWORD | PM_RSTC_RESET; } void raspi_watchdog_clr() { bcm_wdt.timeout = 0; } void raspi_watchdog_set_timeout(rt_uint32_t timeout_us) { bcm_wdt.timeout = timeout_us; } rt_uint64_t raspi_watchdog_get_timeout() { return bcm_wdt.timeout; } rt_uint64_t raspi_watchdog_get_timeleft() { rt_uint32_t ret = (PM_WDOG); return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET); } static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt) { /*init for 10S*/ raspi_watchdog_init(1000000); raspi_watchdog_start(); raspi_watchdog_stop(); return RT_EOK; } static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg) { rt_uint64_t timeout_us = 0; switch (cmd) { case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: timeout_us = *((rt_uint32_t *)arg) * 1000000; if (timeout_us >= 0xFFFFFFFF) timeout_us = 0xFFFFFFFF; raspi_watchdog_set_timeout((rt_uint32_t)timeout_us); break; case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: timeout_us = raspi_watchdog_get_timeout(); *((rt_uint32_t *)arg) = timeout_us / 1000000; break; case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: timeout_us = raspi_watchdog_get_timeleft(); *((rt_uint32_t *)arg) = timeout_us / 1000000; break; case RT_DEVICE_CTRL_WDT_KEEPALIVE: raspi_watchdog_clr(); break; case RT_DEVICE_CTRL_WDT_START: raspi_watchdog_start(); break; case RT_DEVICE_CTRL_WDT_STOP: raspi_watchdog_stop(); break; default: return -RT_EIO; } return RT_EOK; } static const struct rt_watchdog_ops raspi_wdg_pos = { raspi_wdg_init, raspi_wdg_control, }; static rt_watchdog_t raspi_wdg; int rt_hw_wdt_init(void) { raspi_wdg.ops = &raspi_wdg_pos; rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_wdt_init); void rt_hw_cpu_reset(void) { unsigned int r; rt_kprintf("reboot system...\n"); rt_thread_mdelay(100); r = PM_RSTS; // trigger a restart by instructing the GPU to boot from partition 0 r &= ~0xfffffaaa; PM_RSTS |= (PM_PASSWORD | r); // boot from partition 0 PM_WDOG |= (PM_PASSWORD | 0x0A); PM_RSTC |= (PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); while (1); } MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reboot system...); #endif /*BSP_USING_WDT */