From 078e7099b7545517274a369f6681a32cb8dd159d Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Sun, 15 Mar 2026 21:42:24 +0800 Subject: [PATCH] arch/risc-v/k210: Add Watchdog Timer (WDT) driver support. Add WDT driver for K210 with support for both WDT0 and WDT1 peripherals. This includes: - Add k210_wdt.c and k210_wdt.h driver files with interrupt-based watchdog timer functionality - Add hardware register definitions in k210_wdt.h - Add K210_WDT, K210_WDT0, K210_WDT1 Kconfig options - Add memory map definitions for WDT0 (0x50400000) and WDT1 (0x50410000) - Reorder WDT IRQ definitions (IRQ 21, 22) before UART0 (IRQ 33) in irq.h - Add WDT initialization in board bringup for maix-bit Signed-off-by: Huang Qi --- Documentation/platforms/risc-v/k210/index.rst | 14 + arch/risc-v/include/k210/irq.h | 2 + arch/risc-v/src/k210/CMakeLists.txt | 4 + arch/risc-v/src/k210/Kconfig | 14 + arch/risc-v/src/k210/Make.defs | 4 + .../risc-v/src/k210/hardware/k210_memorymap.h | 3 + arch/risc-v/src/k210/hardware/k210_wdt.h | 54 ++ arch/risc-v/src/k210/k210_wdt.c | 516 ++++++++++++++++++ arch/risc-v/src/k210/k210_wdt.h | 60 ++ .../risc-v/k210/maix-bit/src/k210_bringup.c | 23 + 10 files changed, 694 insertions(+) create mode 100644 arch/risc-v/src/k210/hardware/k210_wdt.h create mode 100644 arch/risc-v/src/k210/k210_wdt.c create mode 100644 arch/risc-v/src/k210/k210_wdt.h diff --git a/Documentation/platforms/risc-v/k210/index.rst b/Documentation/platforms/risc-v/k210/index.rst index 7dfc61b80cc..584c704fff4 100644 --- a/Documentation/platforms/risc-v/k210/index.rst +++ b/Documentation/platforms/risc-v/k210/index.rst @@ -22,6 +22,20 @@ The driver supports querying clock frequencies for: CPU frequency can be configured at build time using the ``K210_CPU_FREQ`` Kconfig option (default: 400 MHz, range: 40-600 MHz). +Watchdog Timers +=============== + +The K210 has two independent watchdog timers (WDT0 and WDT1) for system +reliability. Both are accessible as character drivers via the standard +NuttX watchdog interface. + +* **WDT0**: Base address ``0x50400000``, IRQ 21 +* **WDT1**: Base address ``0x50410000``, IRQ 22 +* **Timeout range**: Programmable based on 16-bit counter + +Enable via Kconfig: ``CONFIG_K210_WDT`` (automatically selects +``CONFIG_WATCHDOG``). Devices are ``/dev/watchdog0`` and ``/dev/watchdog1``. + Supported Boards ================ diff --git a/arch/risc-v/include/k210/irq.h b/arch/risc-v/include/k210/irq.h index 9d4fc6de75d..728da5b5fa6 100644 --- a/arch/risc-v/include/k210/irq.h +++ b/arch/risc-v/include/k210/irq.h @@ -36,6 +36,8 @@ #ifdef CONFIG_K210_WITH_QEMU #define K210_IRQ_UART0 (RISCV_IRQ_MEXT + 4) #else +#define K210_IRQ_WDT0 (RISCV_IRQ_MEXT + 21) +#define K210_IRQ_WDT1 (RISCV_IRQ_MEXT + 22) #define K210_IRQ_UART0 (RISCV_IRQ_MEXT + 33) #endif diff --git a/arch/risc-v/src/k210/CMakeLists.txt b/arch/risc-v/src/k210/CMakeLists.txt index 4df61aab560..dbb7909e00b 100644 --- a/arch/risc-v/src/k210/CMakeLists.txt +++ b/arch/risc-v/src/k210/CMakeLists.txt @@ -32,4 +32,8 @@ if(CONFIG_BUILD_PROTECTED) list(APPEND SRCS k210_userspace.c) endif() +if(CONFIG_K210_WDT) + list(APPEND SRCS k210_wdt.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/risc-v/src/k210/Kconfig b/arch/risc-v/src/k210/Kconfig index 4416e294c20..385fc6843c4 100644 --- a/arch/risc-v/src/k210/Kconfig +++ b/arch/risc-v/src/k210/Kconfig @@ -25,6 +25,20 @@ config K210_UART0 select ARCH_HAVE_SERIAL_TERMIOS select K210_UART +config K210_WDT + bool + select WATCHDOG + +config K210_WDT0 + bool "WDT0" + default n + select K210_WDT + +config K210_WDT1 + bool "WDT1" + default n + select K210_WDT + endmenu config K210_CPU_FREQ diff --git a/arch/risc-v/src/k210/Make.defs b/arch/risc-v/src/k210/Make.defs index 42d2d705140..38f8d842fd9 100644 --- a/arch/risc-v/src/k210/Make.defs +++ b/arch/risc-v/src/k210/Make.defs @@ -35,3 +35,7 @@ CHIP_CSRCS += k210_start.c k210_timerisr.c k210_gpiohs.c k210_sysctl.c ifeq ($(CONFIG_BUILD_PROTECTED),y) CHIP_CSRCS += k210_userspace.c endif + +ifeq ($(CONFIG_K210_WDT),y) +CHIP_CSRCS += k210_wdt.c +endif diff --git a/arch/risc-v/src/k210/hardware/k210_memorymap.h b/arch/risc-v/src/k210/hardware/k210_memorymap.h index 612fe99d667..59f6ab15a17 100644 --- a/arch/risc-v/src/k210/hardware/k210_memorymap.h +++ b/arch/risc-v/src/k210/hardware/k210_memorymap.h @@ -40,6 +40,9 @@ #define K210_GPIOHS_BASE 0x38001000 #define K210_FPIOA_BASE 0x502B0000 +#define K210_WDT0_BASE 0x50400000 +#define K210_WDT1_BASE 0x50410000 + #define K210_SYSCTL_BASE 0x50440000 #endif /* __ARCH_RISCV_SRC_K210_HARDWARE_K210_MEMORYMAP_H */ diff --git a/arch/risc-v/src/k210/hardware/k210_wdt.h b/arch/risc-v/src/k210/hardware/k210_wdt.h new file mode 100644 index 00000000000..636c7f4f72d --- /dev/null +++ b/arch/risc-v/src/k210/hardware/k210_wdt.h @@ -0,0 +1,54 @@ +/**************************************************************************** + * arch/risc-v/src/k210/hardware/k210_wdt.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_K210_HARDWARE_K210_WDT_H +#define __ARCH_RISCV_SRC_K210_HARDWARE_K210_WDT_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define K210_WDT_CR_OFFSET 0x0000 +#define K210_WDT_TORR_OFFSET 0x0004 +#define K210_WDT_CCVR_OFFSET 0x0008 +#define K210_WDT_CRR_OFFSET 0x000c +#define K210_WDT_STAT_OFFSET 0x0010 +#define K210_WDT_EOI_OFFSET 0x0014 +#define K210_WDT_PROT_LEVEL_OFFSET 0x001c + +#define K210_WDT_CR(base) ((base) + K210_WDT_CR_OFFSET) +#define K210_WDT_TORR(base) ((base) + K210_WDT_TORR_OFFSET) +#define K210_WDT_CCVR(base) ((base) + K210_WDT_CCVR_OFFSET) +#define K210_WDT_CRR(base) ((base) + K210_WDT_CRR_OFFSET) +#define K210_WDT_STAT(base) ((base) + K210_WDT_STAT_OFFSET) +#define K210_WDT_EOI(base) ((base) + K210_WDT_EOI_OFFSET) + +#define K210_WDT_CR_ENABLE 0x00000001u +#define K210_WDT_CR_RMOD_MASK 0x00000002u +#define K210_WDT_CR_RMOD_RESET 0x00000000u +#define K210_WDT_CR_RMOD_INTERRUPT 0x00000002u + +#define K210_WDT_TORR_TOP(n) (((n) << 4) | ((n) << 0)) + +#define K210_WDT_CRR_RESTART 0x00000076u + +#endif /* __ARCH_RISCV_SRC_K210_HARDWARE_K210_WDT_H */ diff --git a/arch/risc-v/src/k210/k210_wdt.c b/arch/risc-v/src/k210/k210_wdt.c new file mode 100644 index 00000000000..f4abcc8617a --- /dev/null +++ b/arch/risc-v/src/k210/k210_wdt.c @@ -0,0 +1,516 @@ +/**************************************************************************** + * arch/risc-v/src/k210/k210_wdt.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_K210_WDT0) || defined(CONFIG_K210_WDT1) + +#include +#include +#include +#include + +#include +#include + +#include "riscv_internal.h" +#include "k210.h" +#include "k210_sysctl.h" +#include "k210_wdt.h" +#include "hardware/k210_sysctl.h" +#include "hardware/k210_wdt.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define K210_WDT_IN0_FREQ 26000000u +#define K210_WDT_DEFAULT_PCLK (K210_WDT_IN0_FREQ / 2u) +#define K210_WDT_MAX_TOP 0x0f +#define K210_WDT_BASE_COUNT (1ull << 16) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct k210_wdt_lowerhalf_s +{ + const struct watchdog_ops_s *ops; + uintptr_t base; + int irq; + k210_clockid_t clkid; + k210_rstidx_t rstidx; + xcpt_t handler; + void *upper; + uint32_t timeout; + uint8_t top; + bool started; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int k210_wdt_start(struct watchdog_lowerhalf_s *lower); +static int k210_wdt_stop(struct watchdog_lowerhalf_s *lower); +static int k210_wdt_keepalive(struct watchdog_lowerhalf_s *lower); +static int k210_wdt_getstatus(struct watchdog_lowerhalf_s *lower, + struct watchdog_status_s *status); +static int k210_wdt_settimeout(struct watchdog_lowerhalf_s *lower, + uint32_t timeout); +static xcpt_t k210_wdt_capture(struct watchdog_lowerhalf_s *lower, + xcpt_t handler); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct watchdog_ops_s g_k210_wdt_ops = +{ + .start = k210_wdt_start, + .stop = k210_wdt_stop, + .keepalive = k210_wdt_keepalive, + .getstatus = k210_wdt_getstatus, + .settimeout = k210_wdt_settimeout, + .capture = k210_wdt_capture, + .ioctl = NULL, +}; + +#ifdef CONFIG_K210_WDT0 +static struct k210_wdt_lowerhalf_s g_k210_wdt0_lowerhalf = +{ + .ops = &g_k210_wdt_ops, + .base = K210_WDT0_BASE, + .irq = K210_IRQ_WDT0, + .clkid = K210_CLOCK_WDT0, + .rstidx = K210_RESET_WDT0, + .timeout = 0, + .top = K210_WDT_MAX_TOP, +}; +#endif + +#ifdef CONFIG_K210_WDT1 +static struct k210_wdt_lowerhalf_s g_k210_wdt1_lowerhalf = +{ + .ops = &g_k210_wdt_ops, + .base = K210_WDT1_BASE, + .irq = K210_IRQ_WDT1, + .clkid = K210_CLOCK_WDT1, + .rstidx = K210_RESET_WDT1, + .timeout = 0, + .top = K210_WDT_MAX_TOP, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint32_t k210_wdt_get_pclk(struct k210_wdt_lowerhalf_s *priv) +{ + uint32_t pclk; + + if (!priv->started) + { + return K210_WDT_DEFAULT_PCLK; + } + + pclk = k210_sysctl_clock_get_freq(priv->clkid); + + if (pclk == 0) + { + pclk = K210_WDT_DEFAULT_PCLK; + } + + return pclk; +} + +static void k210_wdt_set_threshold_zero(struct k210_wdt_lowerhalf_s *priv) +{ + uint32_t clearbits = (priv->clkid == K210_CLOCK_WDT0) ? + CLK_TH6_WDT0_MASK : CLK_TH6_WDT1_MASK; + + modifyreg32(K210_SYSCTL_CLK_TH6, clearbits, 0); +} + +static void k210_wdt_enable(struct k210_wdt_lowerhalf_s *priv) +{ + uint32_t regval; + + putreg32(K210_WDT_CRR_RESTART, K210_WDT_CRR(priv->base)); + regval = getreg32(K210_WDT_CR(priv->base)); + regval |= K210_WDT_CR_ENABLE; + putreg32(regval, K210_WDT_CR(priv->base)); +} + +static void k210_wdt_disable(struct k210_wdt_lowerhalf_s *priv) +{ + uint32_t regval; + + putreg32(K210_WDT_CRR_RESTART, K210_WDT_CRR(priv->base)); + regval = getreg32(K210_WDT_CR(priv->base)); + regval &= ~K210_WDT_CR_ENABLE; + putreg32(regval, K210_WDT_CR(priv->base)); +} + +static void k210_wdt_feed_internal(struct k210_wdt_lowerhalf_s *priv) +{ + putreg32(K210_WDT_CRR_RESTART, K210_WDT_CRR(priv->base)); +} + +static void k210_wdt_clear_interrupt(struct k210_wdt_lowerhalf_s *priv) +{ + uint32_t regval; + + regval = getreg32(K210_WDT_EOI(priv->base)); + putreg32(regval, K210_WDT_EOI(priv->base)); +} + +static void k210_wdt_set_timeout_top(struct k210_wdt_lowerhalf_s *priv, + uint8_t top) +{ + putreg32(K210_WDT_TORR_TOP(top), K210_WDT_TORR(priv->base)); +} + +static void k210_wdt_set_response_mode(struct k210_wdt_lowerhalf_s *priv, + uint32_t mode) +{ + uint32_t regval; + + regval = getreg32(K210_WDT_CR(priv->base)); + regval &= ~K210_WDT_CR_RMOD_MASK; + regval |= mode; + putreg32(regval, K210_WDT_CR(priv->base)); +} + +static uint8_t k210_wdt_get_top(struct k210_wdt_lowerhalf_s *priv, + uint32_t timeout_ms) +{ + uint64_t counts; + uint64_t level; + uint8_t top = 0; + + counts = ((uint64_t)timeout_ms * (uint64_t)k210_wdt_get_pclk(priv) + + 999u) / 1000u; + + level = (counts + K210_WDT_BASE_COUNT - 1) / K210_WDT_BASE_COUNT; + + if (level == 0) + { + level = 1; + } + + while ((1ull << top) < level && top < K210_WDT_MAX_TOP) + { + top++; + } + + return top; +} + +static uint32_t k210_wdt_top_to_timeout(struct k210_wdt_lowerhalf_s *priv, + uint8_t top) +{ + uint64_t timeout; + uint32_t pclk = k210_wdt_get_pclk(priv); + + timeout = (K210_WDT_BASE_COUNT << top) * 1000ull; + timeout /= (uint64_t)pclk; + + return (uint32_t)timeout; +} + +static int k210_wdt_interrupt(int irq, void *context, void *arg) +{ + struct k210_wdt_lowerhalf_s *priv = arg; + + if (priv->handler != NULL) + { + priv->handler(irq, context, priv->upper); + } + + k210_wdt_clear_interrupt(priv); + return OK; +} + +/**************************************************************************** + * Name: k210_wdt_start + ****************************************************************************/ + +static int k210_wdt_start(struct watchdog_lowerhalf_s *lower) +{ + struct k210_wdt_lowerhalf_s *priv = + (struct k210_wdt_lowerhalf_s *)lower; + irqstate_t flags; + int ret; + + if (priv->started) + { + return -EBUSY; + } + + flags = enter_critical_section(); + + ret = k210_sysctl_reset(priv->rstidx); + if (ret < 0) + { + leave_critical_section(flags); + return ret; + } + + k210_wdt_set_threshold_zero(priv); + + ret = k210_sysctl_clock_enable(priv->clkid); + if (ret < 0) + { + leave_critical_section(flags); + return ret; + } + + putreg32(1, K210_PLIC_PRIORITY + + ((priv->irq - RISCV_IRQ_MEXT) * sizeof(uint32_t))); + + if (priv->handler != NULL) + { + k210_wdt_set_response_mode(priv, K210_WDT_CR_RMOD_INTERRUPT); + up_enable_irq(priv->irq); + } + else + { + k210_wdt_set_response_mode(priv, K210_WDT_CR_RMOD_RESET); + up_disable_irq(priv->irq); + } + + k210_wdt_set_timeout_top(priv, priv->top); + k210_wdt_enable(priv); + priv->started = true; + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: k210_wdt_stop + ****************************************************************************/ + +static int k210_wdt_stop(struct watchdog_lowerhalf_s *lower) +{ + struct k210_wdt_lowerhalf_s *priv = + (struct k210_wdt_lowerhalf_s *)lower; + irqstate_t flags; + + flags = enter_critical_section(); + up_disable_irq(priv->irq); + k210_wdt_disable(priv); + priv->started = false; + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: k210_wdt_keepalive + ****************************************************************************/ + +static int k210_wdt_keepalive(struct watchdog_lowerhalf_s *lower) +{ + struct k210_wdt_lowerhalf_s *priv = + (struct k210_wdt_lowerhalf_s *)lower; + + if (!priv->started) + { + return -EIO; + } + + k210_wdt_feed_internal(priv); + return OK; +} + +/**************************************************************************** + * Name: k210_wdt_getstatus + ****************************************************************************/ + +static int k210_wdt_getstatus(struct watchdog_lowerhalf_s *lower, + struct watchdog_status_s *status) +{ + struct k210_wdt_lowerhalf_s *priv = + (struct k210_wdt_lowerhalf_s *)lower; + uint64_t timeleft = priv->timeout; + + status->flags = 0; + + if (priv->started) + { + status->flags |= WDFLAGS_ACTIVE; + timeleft = ((uint64_t)getreg32(K210_WDT_CCVR(priv->base)) * 1000ull) / + (uint64_t)k210_wdt_get_pclk(priv); + if (timeleft > priv->timeout) + { + timeleft = priv->timeout; + } + } + + if (priv->handler != NULL) + { + status->flags |= WDFLAGS_CAPTURE; + } + else + { + status->flags |= WDFLAGS_RESET; + } + + status->timeout = priv->timeout; + status->timeleft = (uint32_t)timeleft; + return OK; +} + +/**************************************************************************** + * Name: k210_wdt_settimeout + ****************************************************************************/ + +static int k210_wdt_settimeout(struct watchdog_lowerhalf_s *lower, + uint32_t timeout) +{ + struct k210_wdt_lowerhalf_s *priv = + (struct k210_wdt_lowerhalf_s *)lower; + irqstate_t flags; + + if (timeout == 0) + { + return -EINVAL; + } + + if (timeout > k210_wdt_top_to_timeout(priv, K210_WDT_MAX_TOP)) + { + return -ERANGE; + } + + priv->top = k210_wdt_get_top(priv, timeout); + priv->timeout = k210_wdt_top_to_timeout(priv, priv->top); + + if (!priv->started) + { + return OK; + } + + flags = enter_critical_section(); + k210_wdt_set_timeout_top(priv, priv->top); + k210_wdt_feed_internal(priv); + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: k210_wdt_capture + ****************************************************************************/ + +static xcpt_t k210_wdt_capture(struct watchdog_lowerhalf_s *lower, + xcpt_t handler) +{ + struct k210_wdt_lowerhalf_s *priv = + (struct k210_wdt_lowerhalf_s *)lower; + irqstate_t flags; + xcpt_t oldhandler; + + flags = enter_critical_section(); + oldhandler = priv->handler; + priv->handler = handler; + + if (priv->started) + { + if (handler != NULL) + { + putreg32(1, K210_PLIC_PRIORITY + + ((priv->irq - RISCV_IRQ_MEXT) * sizeof(uint32_t))); + k210_wdt_set_response_mode(priv, K210_WDT_CR_RMOD_INTERRUPT); + up_enable_irq(priv->irq); + } + else + { + up_disable_irq(priv->irq); + k210_wdt_set_response_mode(priv, K210_WDT_CR_RMOD_RESET); + } + } + + leave_critical_section(flags); + return oldhandler; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: k210_wdt_initialize + ****************************************************************************/ + +int k210_wdt_initialize(const char *devpath, k210_wdt_id_t id) +{ + struct k210_wdt_lowerhalf_s *priv; + void *handle; + int ret; + + switch (id) + { +#ifdef CONFIG_K210_WDT0 + case K210_WDT_DEVICE0: + priv = &g_k210_wdt0_lowerhalf; + break; +#endif +#ifdef CONFIG_K210_WDT1 + case K210_WDT_DEVICE1: + priv = &g_k210_wdt1_lowerhalf; + break; +#endif + default: + return -EINVAL; + } + + if (priv->timeout == 0) + { + priv->timeout = k210_wdt_top_to_timeout(priv, priv->top); + } + + ret = irq_attach(priv->irq, k210_wdt_interrupt, priv); + if (ret < 0) + { + return ret; + } + + up_disable_irq(priv->irq); + + handle = watchdog_register(devpath, (struct watchdog_lowerhalf_s *)priv); + if (handle == NULL) + { + return -EEXIST; + } + + priv->upper = handle; + return OK; +} + +#endif /* CONFIG_K210_WDT0 || CONFIG_K210_WDT1 */ diff --git a/arch/risc-v/src/k210/k210_wdt.h b/arch/risc-v/src/k210/k210_wdt.h new file mode 100644 index 00000000000..19c28c22a80 --- /dev/null +++ b/arch/risc-v/src/k210/k210_wdt.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * arch/risc-v/src/k210/k210_wdt.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_K210_K210_WDT_H +#define __ARCH_RISCV_SRC_K210_K210_WDT_H + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef enum +{ + K210_WDT_DEVICE0 = 0, + K210_WDT_DEVICE1, + K210_WDT_DEVICE_MAX +} k210_wdt_id_t; + +#ifndef __ASSEMBLY__ + +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int k210_wdt_initialize(const char *devpath, k210_wdt_id_t id); + +#undef EXTERN + +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_K210_K210_WDT_H */ diff --git a/boards/risc-v/k210/maix-bit/src/k210_bringup.c b/boards/risc-v/k210/maix-bit/src/k210_bringup.c index e84e7332f16..7f0441ff2f8 100644 --- a/boards/risc-v/k210/maix-bit/src/k210_bringup.c +++ b/boards/risc-v/k210/maix-bit/src/k210_bringup.c @@ -35,6 +35,7 @@ #include #include "k210.h" +#include "k210_wdt.h" #include "maix-bit.h" /**************************************************************************** @@ -68,5 +69,27 @@ int k210_bringup(void) } #endif +#ifdef CONFIG_K210_WDT0 + ret = k210_wdt_initialize(CONFIG_WATCHDOG_DEVPATH, K210_WDT_DEVICE0); + if (ret < 0) + { + syslog(LOG_WARNING, "WARNING: Failed to initialize WDT0: %d\n", ret); + } +#endif + +#ifdef CONFIG_K210_WDT1 + ret = k210_wdt_initialize( +#ifdef CONFIG_K210_WDT0 + "/dev/watchdog1", +#else + CONFIG_WATCHDOG_DEVPATH, +#endif + K210_WDT_DEVICE1); + if (ret < 0) + { + syslog(LOG_WARNING, "WARNING: Failed to initialize WDT1: %d\n", ret); + } +#endif + return ret; }