/* * Copyright (c) 2017 Actions Semiconductor Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #define WD_CTL_EN (1 << 4) #define WD_CTL_CLKSEL_MASK (0x7 << 1) #define WD_CTL_CLKSEL_SHIFT (1) #define WD_CTL_CLKSEL(n) ((n) << WD_CTL_CLKSEL_SHIFT) #define WD_CTL_CLR (1 << 0) #define WD_CTL_IRQ_PD (1 << 6) #define WD_CTL_IRQ_EN (1 << 5) /* timeout: 176ms * 2^n */ #define WD_TIMEOUT_CLKSEL_TO_MS(n) (176 << (n)) #define WD_TIMEOUT_MS_TO_CLKSEL(ms) (find_msb_set(((ms) + 1) / 176)) static wdt_callback_t g_irq_handler_wdg; DEVICE_DECLARE(wdg0); static void wdg_acts_enable(const struct device *dev) { ARG_UNUSED(dev); sys_write32(sys_read32(WD_CTL) | WD_CTL_EN, WD_CTL); } static int wdg_acts_disable(const struct device *dev) { ARG_UNUSED(dev); sys_write32(sys_read32(WD_CTL) & ~WD_CTL_EN, WD_CTL); return 0; } static void wdg_acts_clear_irq_pd(void) { sys_write32(sys_read32(WD_CTL), WD_CTL); } static void wdg_irq_handler(void *arg) { wdg_acts_clear_irq_pd(); if (g_irq_handler_wdg) g_irq_handler_wdg(arg, 0); } static int wdg_acts_feed(const struct device *dev, int channel_id) { ARG_UNUSED(dev); ARG_UNUSED(channel_id); sys_write32(sys_read32(WD_CTL) | WD_CTL_CLR, WD_CTL); return 0; } static int wdg_acts_setup(const struct device *dev, uint8_t options) { ARG_UNUSED(options); wdg_acts_enable(dev); return 0; } static int wdg_acts_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg) { int clksel; if (cfg->flags != WDT_FLAG_RESET_SOC) { return -ENOTSUP; } if (cfg->window.max == 0U) return -EINVAL; ARG_UNUSED(dev); clksel = WD_TIMEOUT_MS_TO_CLKSEL(cfg->window.max); if (cfg->callback == NULL) { g_irq_handler_wdg = NULL; irq_disable(IRQ_ID_WD2HZ); sys_write32((sys_read32(WD_CTL) & ~WD_CTL_CLKSEL_MASK) | WD_CTL_CLKSEL(clksel), WD_CTL); sys_write32((sys_read32(WD_CTL) & ~WD_CTL_IRQ_EN), WD_CTL); } else { g_irq_handler_wdg = cfg->callback; IRQ_CONNECT(IRQ_ID_WD2HZ, CONFIG_WDT_0_IRQ_PRI, wdg_irq_handler, DEVICE_GET(wdg0), 0); irq_enable(IRQ_ID_WD2HZ); sys_write32((sys_read32(WD_CTL) & ~WD_CTL_CLKSEL_MASK) | WD_CTL_CLKSEL(clksel) | WD_CTL_IRQ_EN, WD_CTL); } return 0; } static const struct wdt_driver_api wdg_acts_driver_api = { .setup = wdg_acts_setup, .disable = wdg_acts_disable, .install_timeout = wdg_acts_install_timeout, .feed = wdg_acts_feed, }; static int wdg_acts_init(const struct device *dev) { //sys_write32(0x0, WD_CTL); #ifdef CONFIG_WDT_ACTS_START_AT_BOOT wdg_acts_enable(dev); #endif return 0; } DEVICE_DEFINE(wdg0, CONFIG_WDT_ACTS_NAME, wdg_acts_init, NULL, NULL, NULL, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdg_acts_driver_api);