/* * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT espressif_esp32_xt_wdt #include #include #include #include #include #include #include #ifndef CONFIG_SOC_SERIES_ESP32C3 #include #else #include #endif #include #include LOG_MODULE_REGISTER(xt_wdt_esp32, CONFIG_WDT_LOG_LEVEL); #ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t #endif #define ESP32_XT_WDT_MAX_TIMEOUT 255 struct esp32_xt_wdt_data { xt_wdt_hal_context_t hal; wdt_callback_t callback; uint32_t timeout; }; struct esp32_xt_wdt_config { const struct device *clock_dev; const clock_control_subsys_t clock_subsys; int irq_source; int irq_priority; int irq_flags; }; static int esp32_xt_wdt_setup(const struct device *dev, uint8_t options) { ARG_UNUSED(options); struct esp32_xt_wdt_data *data = dev->data; xt_wdt_hal_config_t xt_wdt_hal_config = { .timeout = data->timeout, }; xt_wdt_hal_init(&data->hal, &xt_wdt_hal_config); xt_wdt_hal_enable(&data->hal, true); return 0; } static int esp32_xt_wdt_disable(const struct device *dev) { struct esp32_xt_wdt_data *data = dev->data; xt_wdt_hal_enable(&data->hal, false); return 0; } static int esp32_xt_wdt_feed(const struct device *dev, int channel_id) { ARG_UNUSED(dev); ARG_UNUSED(channel_id); return -ENOSYS; } static int esp32_xt_wdt_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg) { struct esp32_xt_wdt_data *data = dev->data; if (cfg->window.min != 0U || cfg->window.max == 0U || cfg->window.max >= ESP32_XT_WDT_MAX_TIMEOUT) { LOG_ERR("Invalid timeout configuration"); return -EINVAL; } data->timeout = cfg->window.max; data->callback = cfg->callback; return 0; } static void esp32_xt_wdt_isr(void *arg) { const struct device *dev = (const struct device *)arg; const struct esp32_xt_wdt_config *cfg = dev->config; struct esp32_xt_wdt_data *data = dev->data; struct esp32_clock_config clk_cfg = {0}; uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG); REG_WRITE(RTC_CNTL_INT_CLR_REG, status); clk_cfg.rtc.rtc_slow_clock_src = ESP32_RTC_SLOW_CLK_SRC_RC_SLOW; clock_control_configure(cfg->clock_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, &clk_cfg); if (data->callback != NULL) { data->callback(dev, 0); } } static int esp32_xt_wdt_init(const struct device *dev) { const struct esp32_xt_wdt_config *cfg = dev->config; struct esp32_xt_wdt_data *data = dev->data; xt_wdt_hal_config_t xt_wdt_hal_config = { .timeout = ESP32_XT_WDT_MAX_TIMEOUT, }; xt_wdt_hal_init(&data->hal, &xt_wdt_hal_config); xt_wdt_hal_enable_backup_clk(&data->hal, ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ/1000); int err = esp_intr_alloc(cfg->irq_source, ESP_PRIO_TO_FLAGS(cfg->irq_priority) | ESP_INT_FLAGS_CHECK(cfg->irq_flags), (ISR_HANDLER)esp32_xt_wdt_isr, (void *)dev, NULL); if (err) { LOG_ERR("Failed to register ISR\n"); return -EFAULT; } REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); return 0; } static const struct wdt_driver_api esp32_xt_wdt_api = { .setup = esp32_xt_wdt_setup, .disable = esp32_xt_wdt_disable, .install_timeout = esp32_xt_wdt_install_timeout, .feed = esp32_xt_wdt_feed }; static struct esp32_xt_wdt_data esp32_xt_wdt_data0; static struct esp32_xt_wdt_config esp32_xt_wdt_config0 = { .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)), .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset), .irq_source = DT_INST_IRQ_BY_IDX(0, 0, irq), .irq_priority = DT_INST_IRQ_BY_IDX(0, 0, priority), .irq_flags = DT_INST_IRQ_BY_IDX(0, 0, flags) }; DEVICE_DT_DEFINE(DT_NODELABEL(xt_wdt), &esp32_xt_wdt_init, NULL, &esp32_xt_wdt_data0, &esp32_xt_wdt_config0, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &esp32_xt_wdt_api); #if !(defined(CONFIG_SOC_SERIES_ESP32S2) || \ defined(CONFIG_SOC_SERIES_ESP32S3) || \ defined(CONFIG_SOC_SERIES_ESP32C3)) #error "XT WDT is not supported" #else BUILD_ASSERT((DT_PROP(DT_INST(0, espressif_esp32_rtc), slow_clk_src) == ESP32_RTC_SLOW_CLK_SRC_XTAL32K) || (DT_PROP(DT_INST(0, espressif_esp32_rtc), slow_clk_src) == ESP32_RTC_SLOW_CLK_32K_EXT_OSC), "XT WDT is only supported with XTAL32K or 32K_EXT_OSC as slow clock source"); #endif