From 171285140cf004a4882ad7e6ccc4db908d1f2207 Mon Sep 17 00:00:00 2001 From: Mateusz Sierszulski Date: Fri, 11 Aug 2023 13:57:38 +0200 Subject: [PATCH] drivers: watchdog: Add Ambiq wdt driver This commits add watchdog driver for Apollo4 SoCs Signed-off-by: Mateusz Sierszulski --- drivers/watchdog/CMakeLists.txt | 1 + drivers/watchdog/Kconfig | 2 + drivers/watchdog/Kconfig.ambiq | 14 ++ drivers/watchdog/wdt_ambiq.c | 165 ++++++++++++++++++++++ dts/bindings/watchdog/ambiq,watchdog.yaml | 19 +++ modules/hal_ambiq/Kconfig | 5 + west.yml | 2 +- 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 drivers/watchdog/Kconfig.ambiq create mode 100644 drivers/watchdog/wdt_ambiq.c create mode 100644 dts/bindings/watchdog/ambiq,watchdog.yaml diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt index 8faf4c82fb..a5ca984b9a 100644 --- a/drivers/watchdog/CMakeLists.txt +++ b/drivers/watchdog/CMakeLists.txt @@ -38,6 +38,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_TI_TPS382X wdt_ti_tps382x.c) zephyr_library_sources_ifdef(CONFIG_WDT_XILINX_AXI wdt_xilinx_axi.c) zephyr_library_sources_ifdef(CONFIG_WDT_INFINEON_CAT1 wdt_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_WDT_OPENTITAN wdt_opentitan.c) +zephyr_library_sources_ifdef(CONFIG_WDT_AMBIQ wdt_ambiq.c) zephyr_library_sources_ifdef(CONFIG_WDT_DW wdt_dw.c wdt_dw_common.c) zephyr_library_sources_ifdef(CONFIG_WDT_INTEL_ADSP wdt_intel_adsp.c wdt_dw_common.c) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4f01881fd0..7e37e137f0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -116,4 +116,6 @@ source "drivers/watchdog/Kconfig.andes_atcwdt200" source "drivers/watchdog/Kconfig.nxp_fs26" +source "drivers/watchdog/Kconfig.ambiq" + endif # WATCHDOG diff --git a/drivers/watchdog/Kconfig.ambiq b/drivers/watchdog/Kconfig.ambiq new file mode 100644 index 0000000000..c9e307b480 --- /dev/null +++ b/drivers/watchdog/Kconfig.ambiq @@ -0,0 +1,14 @@ +# Ambiq SDK WDT +# +# Copyright (c) 2023 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 +# +config WDT_AMBIQ + bool "AMBIQ WDT driver" + default y + depends on DT_HAS_AMBIQ_WATCHDOG_ENABLED + select AMBIQ_HAL + select AMBIQ_HAL_USE_WDT + help + Enable driver for Ambiq WDT. diff --git a/drivers/watchdog/wdt_ambiq.c b/drivers/watchdog/wdt_ambiq.c new file mode 100644 index 0000000000..5e3cf663b8 --- /dev/null +++ b/drivers/watchdog/wdt_ambiq.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ambiq_watchdog + +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(wdt_ambiq, CONFIG_WDT_LOG_LEVEL); + +typedef void (*ambiq_wdt_cfg_func_t)(void); + +struct wdt_ambiq_config { + uint32_t base; + uint32_t irq_num; + uint8_t clk_freq; + ambiq_wdt_cfg_func_t cfg_func; +}; + +struct wdt_ambiq_data { + wdt_callback_t callback; + uint32_t timeout; + bool reset; +}; + +static void wdt_ambiq_isr(void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct wdt_ambiq_data *data = dev->data; + + uint32_t status; + + am_hal_wdt_interrupt_status_get(AM_HAL_WDT_MCU, &status, false); + am_hal_wdt_interrupt_clear(AM_HAL_WDT_MCU, status); + + if (data->callback) { + data->callback(dev, 0); + } +} + +static int wdt_ambiq_setup(const struct device *dev, uint8_t options) +{ + const struct wdt_ambiq_config *dev_cfg = dev->config; + struct wdt_ambiq_data *data = dev->data; + am_hal_wdt_config_t cfg; + + if (dev_cfg->clk_freq == 128) { + cfg.eClockSource = AM_HAL_WDT_128HZ; + } else if (dev_cfg->clk_freq == 16) { + cfg.eClockSource = AM_HAL_WDT_16HZ; + } else if (dev_cfg->clk_freq == 1) { + cfg.eClockSource = AM_HAL_WDT_1HZ; + } + + cfg.bInterruptEnable = true; + cfg.ui32InterruptValue = data->timeout; + cfg.bResetEnable = data->reset; + cfg.ui32ResetValue = data->timeout; + cfg.bAlertOnDSPReset = false; + + am_hal_wdt_config(AM_HAL_WDT_MCU, &cfg); + am_hal_wdt_interrupt_enable(AM_HAL_WDT_MCU, AM_HAL_WDT_INTERRUPT_MCU); + am_hal_wdt_start(AM_HAL_WDT_MCU, false); + + return 0; +} + +static int wdt_ambiq_disable(const struct device *dev) +{ + ARG_UNUSED(dev); + + am_hal_wdt_stop(AM_HAL_WDT_MCU); + + return 0; +} + +static int wdt_ambiq_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg) +{ + const struct wdt_ambiq_config *dev_cfg = dev->config; + struct wdt_ambiq_data *data = dev->data; + + if (cfg->window.min != 0U || cfg->window.max == 0U) { + return -EINVAL; + } + + data->timeout = cfg->window.max / 1000 * dev_cfg->clk_freq; + data->callback = cfg->callback; + + switch (cfg->flags) { + case WDT_FLAG_RESET_CPU_CORE: + case WDT_FLAG_RESET_SOC: + data->reset = true; + break; + case WDT_FLAG_RESET_NONE: + data->reset = false; + break; + default: + LOG_ERR("Unsupported watchdog config flag"); + return -EINVAL; + } + + return 0; +} + +static int wdt_ambiq_feed(const struct device *dev, int channel_id) +{ + ARG_UNUSED(dev); + ARG_UNUSED(channel_id); + + am_hal_wdt_restart(AM_HAL_WDT_MCU); + LOG_DBG("Fed the watchdog"); + + return 0; +} + +static int wdt_ambiq_init(const struct device *dev) +{ + const struct wdt_ambiq_config *dev_cfg = dev->config; + + if (dev_cfg->clk_freq != 128 && dev_cfg->clk_freq != 16 && dev_cfg->clk_freq != 1) { + return -ENOTSUP; + } + + NVIC_ClearPendingIRQ(dev_cfg->irq_num); + + dev_cfg->cfg_func(); + + irq_enable(dev_cfg->irq_num); + + return 0; +} + +static const struct wdt_driver_api wdt_ambiq_driver_api = { + .setup = wdt_ambiq_setup, + .disable = wdt_ambiq_disable, + .install_timeout = wdt_ambiq_install_timeout, + .feed = wdt_ambiq_feed, +}; + +#define AMBIQ_WDT_INIT(n) \ + static struct wdt_ambiq_data wdt_ambiq_data##n; \ + static void ambiq_wdt_cfg_func_##n(void) \ + { \ + \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), wdt_ambiq_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + }; \ + static const struct wdt_ambiq_config wdt_ambiq_config##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .clk_freq = DT_INST_PROP(n, clock_frequency), \ + .irq_num = DT_INST_IRQN(n), \ + .cfg_func = ambiq_wdt_cfg_func_##n}; \ + \ + DEVICE_DT_INST_DEFINE(n, wdt_ambiq_init, NULL, &wdt_ambiq_data##n, &wdt_ambiq_config##n, \ + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &wdt_ambiq_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_WDT_INIT) diff --git a/dts/bindings/watchdog/ambiq,watchdog.yaml b/dts/bindings/watchdog/ambiq,watchdog.yaml new file mode 100644 index 0000000000..8cf8b301c5 --- /dev/null +++ b/dts/bindings/watchdog/ambiq,watchdog.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: Ambiq Watchdog + +compatible: "ambiq,watchdog" + +include: base.yaml + +properties: + reg: + required: true + + clock-frequency: + type: int + required: true + + interrupts: + required: true diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index 9ea5b63b12..a116083ad2 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -25,4 +25,9 @@ config AMBIQ_HAL_USE_TIMER help Use the TIMER driver from Ambiq HAL +config AMBIQ_HAL_USE_WDT + bool + help + Use the WDT driver from Ambiq HAL + endif # AMBIQ_HAL diff --git a/west.yml b/west.yml index 4f1bf09360..d225084dff 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: 5079b0096479a5630b91d38a891c2db1693faa2a + revision: fe158a4395ba80a9d46c6782e23c277149855a57 path: modules/hal/ambiq groups: - hal