/* * Copyright (c) 2006-2019, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-07-29 zdzn first version */ #include "drv_wdt.h" #ifdef BSP_USING_WDT #define PM_RSTC 0x1c #define PM_RSTS 0x20 #define PM_WDOG 0x24 #define PM_PASSWORD 0x5a000000 #define PM_WDOG_TIME_SET 0x000fffff #define PM_RSTC_WRCFG_CLR 0xffffffcf #define PM_RSTS_HADWRH_SET 0x00000040 #define PM_RSTC_WRCFG_SET 0x00000030 #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 #define PM_RSTC_RESET 0x00000102 #define PM_RSTS_PARTITION_CLR 0xfffffaaa #define SECS_TO_WDOG_TICKS(x) ((x) << 16) #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) static struct raspi_wdt_driver bcm_wdt = { .base = PER_BASE, }; void raspi_watchdog_init(rt_uint32_t time_init) { bcm_wdt.timeout = time_init; } void raspi_watchdog_start() { volatile rt_uint32_t cur; bcm283x_peri_write(bcm_wdt.base + PM_WDOG, PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET)); bcm283x_peri_write(bcm_wdt.base + PM_WDOG, PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET)); cur = bcm283x_peri_read(bcm_wdt.base + PM_RSTC); bcm283x_peri_write(bcm_wdt.base + PM_RSTC, PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET); } void raspi_watchdog_stop() { bcm283x_peri_write(bcm_wdt.base + 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 = bcm283x_peri_read(bcm_wdt.base + 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); #endif /*BSP_USING_WDT */