123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- /*
- * Copyright (c) 2017 Actions Semiconductor Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <errno.h>
- #include <kernel.h>
- #include <drivers/watchdog.h>
- #include <soc.h>
- #include <board_cfg.h>
- #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);
|