diff --git a/drivers/watchdog/wdt_sam0.c b/drivers/watchdog/wdt_sam0.c index fe08af179aa..ed6789b91f9 100644 --- a/drivers/watchdog/wdt_sam0.c +++ b/drivers/watchdog/wdt_sam0.c @@ -14,6 +14,16 @@ LOG_MODULE_REGISTER(wdt_sam0); #define WDT_REGS ((Wdt *)DT_INST_0_ATMEL_SAM0_WATCHDOG_BASE_ADDRESS) +#ifndef WDT_CONFIG_PER_8_Val +#define WDT_CONFIG_PER_8_Val WDT_CONFIG_PER_CYC8_Val +#endif +#ifndef WDT_CONFIG_PER_8K_Val +#define WDT_CONFIG_PER_8K_Val WDT_CONFIG_PER_CYC8192_Val +#endif +#ifndef WDT_CONFIG_PER_16K_Val +#define WDT_CONFIG_PER_16K_Val WDT_CONFIG_PER_CYC16384_Val +#endif + struct wdt_sam0_dev_data { wdt_callback_t cb; bool timeout_valid; @@ -25,8 +35,31 @@ static struct wdt_sam0_dev_data wdt_sam0_data = { 0 }; static void wdt_sam0_wait_synchronization(void) { +#ifdef WDT_STATUS_SYNCBUSY while (WDT_REGS->STATUS.bit.SYNCBUSY) { } +#else + while (WDT_REGS->SYNCBUSY.reg) { + } +#endif +} + +static inline void wdt_sam0_set_enable(bool on) +{ +#ifdef WDT_CTRLA_ENABLE + WDT_REGS->CTRLA.bit.ENABLE = on; +#else + WDT_REGS->CTRL.bit.ENABLE = on; +#endif +} + +static inline bool wdt_sam0_is_enabled(void) +{ +#ifdef WDT_CTRLA_ENABLE + return WDT_REGS->CTRLA.bit.ENABLE; +#else + return WDT_REGS->CTRL.bit.ENABLE; +#endif } static u32_t wdt_sam0_timeout_to_wdt_period(u32_t timeout_ms) @@ -62,7 +95,7 @@ static int wdt_sam0_setup(struct device *dev, u8_t options) { struct wdt_sam0_dev_data *data = dev->driver_data; - if (WDT_REGS->CTRL.reg == WDT_CTRL_ENABLE) { + if (wdt_sam0_is_enabled()) { LOG_ERR("Watchdog already setup"); return -EBUSY; } @@ -83,7 +116,7 @@ static int wdt_sam0_setup(struct device *dev, u8_t options) } /* Enable watchdog */ - WDT_REGS->CTRL.bit.ENABLE = 1; + wdt_sam0_set_enable(1); wdt_sam0_wait_synchronization(); return 0; @@ -91,12 +124,12 @@ static int wdt_sam0_setup(struct device *dev, u8_t options) static int wdt_sam0_disable(struct device *dev) { - if (!WDT_REGS->CTRL.bit.ENABLE) { + if (!wdt_sam0_is_enabled()) { LOG_ERR("Watchdog not enabled"); return -EFAULT; } - WDT_REGS->CTRL.bit.ENABLE = 0; + wdt_sam0_set_enable(0); wdt_sam0_wait_synchronization(); return 0; @@ -109,7 +142,7 @@ static int wdt_sam0_install_timeout(struct device *dev, u32_t window, per; /* CONFIG is enable protected, error out if already enabled */ - if (WDT_REGS->CTRL.bit.ENABLE) { + if (wdt_sam0_is_enabled()) { LOG_ERR("Watchdog already setup"); return -EBUSY; } @@ -141,7 +174,11 @@ static int wdt_sam0_install_timeout(struct device *dev, /* Ensure we have a window */ per = window + 1; } +#ifdef WDT_CTRLA_WEN + WDT_REGS->CTRLA.bit.WEN = 1; +#else WDT_REGS->CTRL.bit.WEN = 1; +#endif wdt_sam0_wait_synchronization(); } else { /* Normal mode */ @@ -153,7 +190,11 @@ static int wdt_sam0_install_timeout(struct device *dev, WDT_REGS->EWCTRL.bit.EWOFFSET = per - 1U; } window = WDT_CONFIG_PER_8_Val; +#ifdef WDT_CTRLA_WEN + WDT_REGS->CTRLA.bit.WEN = 0; +#else WDT_REGS->CTRL.bit.WEN = 0; +#endif wdt_sam0_wait_synchronization(); } @@ -208,12 +249,18 @@ static int wdt_sam0_init(struct device *dev) wdt_sam0_disable(dev); #endif /* Enable APB clock */ +#ifdef MCLK + MCLK->APBAMASK.bit.WDT_ = 1; + + /* watchdog clock is fed by OSCULP32K */ +#else PM->APBAMASK.bit.WDT_ = 1; /* Connect to GCLK2 (~1.024 kHz) */ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_WDT | GCLK_CLKCTRL_GEN_GCLK2 | GCLK_CLKCTRL_CLKEN; +#endif IRQ_CONNECT(DT_INST_0_ATMEL_SAM0_WATCHDOG_IRQ_0, DT_INST_0_ATMEL_SAM0_WATCHDOG_IRQ_0_PRIORITY, wdt_sam0_isr,