From 52ac5dd3b5da77c574b3bb166d4831ebf6729ec5 Mon Sep 17 00:00:00 2001
From: Quy Tran <quy.tran.pz@renesas.com>
Date: Wed, 14 May 2025 22:01:12 +0700
Subject: [PATCH 1/7] manifest: hal_renesas: Update commit ID for hal_renesas

Update commit ID to add support for IWDT driver on
Renesas HAL for RX

Signed-off-by: Quy Tran <quy.tran.pz@renesas.com>
---
 west.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/west.yml b/west.yml
index 555a2890c1fe7..6533ddd15628f 100644
--- a/west.yml
+++ b/west.yml
@@ -226,7 +226,7 @@ manifest:
         - hal
     - name: hal_renesas
       path: modules/hal/renesas
-      revision: 9b99067e29a1b44b53192c2c797db330f5703462
+      revision: pull/98/head
       groups:
         - hal
     - name: hal_rpi_pico

From f041653a7ba55c21193b4a486dc6b5885dcb3269 Mon Sep 17 00:00:00 2001
From: Sang Tran <sang.tran.jc@renesas.com>
Date: Thu, 26 Dec 2024 11:33:01 +0700
Subject: [PATCH 2/7] arch: rx: Add NMI vector table for Renesas RX MCU

Add support for non-maskable interrupt (NMI)  vector table for
Renesas RX architecture

Signed-off-by: Sang Tran <sang.tran.jc@renesas.com>
---
 arch/rx/core/vects.c                  | 81 ++++++++++++++++++++++++++-
 include/zephyr/arch/rx/sw_nmi_table.h | 29 ++++++++++
 2 files changed, 107 insertions(+), 3 deletions(-)
 create mode 100644 include/zephyr/arch/rx/sw_nmi_table.h

diff --git a/arch/rx/core/vects.c b/arch/rx/core/vects.c
index 836e9d3adb2ff..d1d137bbf29c2 100644
--- a/arch/rx/core/vects.c
+++ b/arch/rx/core/vects.c
@@ -8,10 +8,18 @@
 #include <zephyr/irq.h>
 #include <kswap.h>
 #include <zephyr/tracing/tracing.h>
+#include <zephyr/arch/rx/sw_nmi_table.h>
 
 typedef void (*fp)(void);
 extern void _start(void);
 extern void z_rx_irq_exit(void);
+extern void R_BSP_SoftwareReset(void);
+
+#define NMI_NMIST_MASK  0x01
+#define NMI_OSTST_MASK  0x02
+#define NMI_IWDTST_MASK 0x08
+#define NMI_LVD1ST_MASK 0x10
+#define NMI_LVD2ST_MASK 0x20
 
 /* this is mainly to give Visual Studio Code peace of mind */
 #ifndef CONFIG_GEN_IRQ_START_VECTOR
@@ -97,9 +105,9 @@ static void __ISR__ INT_Excep_FloatingPoint(void)
 static void __ISR__ INT_NonMaskableInterrupt(void)
 {
 	REGISTER_SAVE();
-	ISR_DIRECT_HEADER();
-	z_fatal_error(K_ERR_CPU_EXCEPTION, NULL);
-	ISR_DIRECT_FOOTER(1);
+	int nmi_vector = get_nmi_request();
+
+	handle_nmi(nmi_vector);
 	REGISTER_RESTORE_EXIT();
 }
 
@@ -141,6 +149,64 @@ static void __ISR__ reserved_isr(void)
 /* wrapper for z_rx_context_switch_isr, defined in switch.S */
 extern void __ISR__ switch_isr_wrapper(void);
 
+void nmi_enable(uint8_t nmi_vector, nmi_callback_t callback, void *arg)
+{
+	if (nmi_vector >= NMI_TABLE_SIZE) {
+		return;
+	}
+
+	_nmi_vector_table[nmi_vector].callback = callback;
+	_nmi_vector_table[nmi_vector].arg = arg;
+}
+
+int get_nmi_request(void)
+{
+	uint32_t nmi_status = ICU.NMISR.BYTE;
+
+	if (nmi_status & NMI_NMIST_MASK) {
+		return 0;
+	} else if (nmi_status & NMI_OSTST_MASK) {
+		return 1;
+	} else if (nmi_status & NMI_IWDTST_MASK) {
+		return 2;
+	} else if (nmi_status & NMI_LVD1ST_MASK) {
+		return 3;
+	} else if (nmi_status & NMI_LVD2ST_MASK) {
+		return 4;
+	}
+
+	return NMI_TABLE_SIZE;
+}
+
+void handle_nmi(uint8_t nmi_vector)
+{
+	if (nmi_vector >= NMI_TABLE_SIZE) {
+		return;
+	}
+
+	_nmi_vector_table[nmi_vector].callback(_nmi_vector_table[nmi_vector].arg);
+
+	switch (nmi_vector) {
+	case 0:
+		ICU.NMICLR.BIT.NMICLR = 0x01;
+		break;
+	case 1:
+		ICU.NMICLR.BIT.OSTCLR = 0x01;
+		break;
+	case 2:
+		ICU.NMICLR.BIT.IWDTCLR = 0x01;
+		break;
+	case 3:
+		ICU.NMICLR.BIT.LVD1CLR = 0x01;
+		break;
+	case 4:
+		ICU.NMICLR.BIT.LVD2CLR = 0x01;
+		break;
+	default:
+		break;
+	}
+}
+
 /* this macro is used to define "demuxing" ISRs for all interrupts that are
  * handled through Zephyr's software isr table.
  */
@@ -394,6 +460,15 @@ INT_DEMUX(253);
 INT_DEMUX(254);
 INT_DEMUX(255);
 
+struct nmi_vector_entry _nmi_vector_table[NMI_TABLE_SIZE] = {
+	{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* NMI Pin Interrupt */
+	{(nmi_callback_t)0xFFFFFFFFU,
+	 (void *)0xFFFFFFFFU}, /* Oscillation Stop Detection Interrupt */
+	{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* IWDT Underflow/Refresh Error */
+	{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* Voltage Monitoring 1 Interrupt */
+	{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* Voltage Monitoring 2 Interrupt */
+};
+
 const void *FixedVectors[] FVECT_SECT = {
 	/* 0x00-0x4c: Reserved, must be 0xff (according to e2 studio example) */
 	/* Reserved for OFSM */
diff --git a/include/zephyr/arch/rx/sw_nmi_table.h b/include/zephyr/arch/rx/sw_nmi_table.h
new file mode 100644
index 0000000000000..db4ca84677e8c
--- /dev/null
+++ b/include/zephyr/arch/rx/sw_nmi_table.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_ARCH_RX_SW_NMI_TABLE_H
+#define ZEPHYR_INCLUDE_ARCH_RX_SW_NMI_TABLE_H
+
+#include <stdint.h>
+#include <soc.h>
+#include "iodefine.h"
+
+#define NMI_TABLE_SIZE (5)
+
+typedef void (*nmi_callback_t)(void *arg);
+
+struct nmi_vector_entry {
+	nmi_callback_t callback;
+	void *arg;
+};
+
+extern struct nmi_vector_entry _nmi_vector_table[NMI_TABLE_SIZE];
+
+void nmi_enable(uint8_t nmi_vector, nmi_callback_t callback, void *arg);
+int get_nmi_request(void);
+void handle_nmi(uint8_t nmi_vector);
+
+#endif /* ZEPHYR_INCLUDE_ARCH_RX_SW_NMI_TABLE_H */

From ca84c51437ab53d94e4a7e466da7b5ad2ec04506 Mon Sep 17 00:00:00 2001
From: Sang Tran <sang.tran.jc@renesas.com>
Date: Fri, 13 Dec 2024 17:05:17 +0700
Subject: [PATCH 3/7] drivers: watchdog: Support Renesas RX independent
 watchdog timer driver

Add initial support for independent watchdog driver for Renesas RX
with r_iwdt_rx RDP HAL

Signed-off-by: Sang Tran <sang.tran.jc@renesas.com>
---
 drivers/watchdog/CMakeLists.txt            |   1 +
 drivers/watchdog/Kconfig                   |   2 +
 drivers/watchdog/Kconfig.renesas_rx        | 104 ++++++++++
 drivers/watchdog/wdt_iwdt_renesas_rx.c     | 224 +++++++++++++++++++++
 dts/bindings/watchdog/renesas,rx-iwdt.yaml |  39 ++++
 modules/Kconfig.renesas                    |   5 +
 6 files changed, 375 insertions(+)
 create mode 100644 drivers/watchdog/Kconfig.renesas_rx
 create mode 100644 drivers/watchdog/wdt_iwdt_renesas_rx.c
 create mode 100644 dts/bindings/watchdog/renesas,rx-iwdt.yaml

diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt
index e7264362e3f4b..f581e64184192 100644
--- a/drivers/watchdog/CMakeLists.txt
+++ b/drivers/watchdog/CMakeLists.txt
@@ -5,6 +5,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/watchdog.h)
 zephyr_library()
 
 zephyr_library_sources_ifdef(CONFIG_IWDG_STM32 wdt_iwdg_stm32.c)
+zephyr_library_sources_ifdef(CONFIG_IWDT_RENESAS_RX wdt_iwdt_renesas_rx.c)
 zephyr_library_sources_ifdef(CONFIG_WWDG_STM32 wdt_wwdg_stm32.c)
 
 zephyr_library_sources_ifdef(CONFIG_FWDGT_GD32 wdt_fwdgt_gd32.c)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index bd445bda94f96..ad40e0cc05d88 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -153,6 +153,8 @@ source "drivers/watchdog/Kconfig.rts5912"
 
 source "drivers/watchdog/Kconfig.renesas_ra"
 
+source "drivers/watchdog/Kconfig.renesas_rx"
+
 source "drivers/watchdog/Kconfig.wch"
 
 source "drivers/watchdog/Kconfig.nxp_ewm"
diff --git a/drivers/watchdog/Kconfig.renesas_rx b/drivers/watchdog/Kconfig.renesas_rx
new file mode 100644
index 0000000000000..0ce79196b95c5
--- /dev/null
+++ b/drivers/watchdog/Kconfig.renesas_rx
@@ -0,0 +1,104 @@
+# Renesas RX Independent Watchdog (IWDT) configuration
+
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config IWDT_RENESAS_RX
+	bool "Renesas RX Series Independent Watchdog Driver"
+	default y
+	depends on DT_HAS_RENESAS_RX_IWDT_ENABLED
+	select HAS_WDT_DISABLE_AT_BOOT
+	select USE_RX_RDP_IWDT
+	help
+	  Enable Renesas RX series watchdog driver.
+
+if IWDT_RENESAS_RX
+
+config IWDT_RX_NMI
+	bool "Non-maskable interrupt for IWDT"
+	default y
+	help
+	  Enable NMI for IWDT.
+
+choice
+	prompt "IWDT Start Mode"
+	default IWDT_RENESAS_RX_IWDT
+	help
+	  Select the IWDT start mode.
+	  - IWDT_RENESAS_RX_AUTO_START_MODE: Counting automatically starts after a reset
+	  (auto-start mode), controlled by option function select register 0 (OFS0).
+	  - IWDT_RENESAS_RX_IWDT: Counting is started by refreshing the counter.
+	  (controlled by the IWDT registers)
+
+config IWDT_RENESAS_RX_AUTO_START_MODE
+	bool "Start IWDT automatically on reset"
+
+config IWDT_RENESAS_RX_IWDT
+	bool "IWDT Start Mode Select"
+	select USE_RX_RDP_IWDT
+
+endchoice
+
+if IWDT_RENESAS_RX_AUTO_START_MODE
+
+config IWDT_RENESAS_RX_IWDTSTRT
+	int "IWDT OFS0 Start Mode Select"
+	default 0
+	help
+	  0: IWDT is automatically activated in auto-start mode after a reset
+	  1: IWDT is halted after a reset
+
+config IWDT_RENESAS_RX_OFS0_IWDTTOPS
+	int "IWDT Timeout Period Select"
+	default 3
+	help
+	  0: 128 cycles (007Fh)
+	  1: 512 cycles (01FFh)
+	  2: 1024 cycles (03FFh)
+	  3: 2048 cycles (07FFh)
+
+config IWDT_RENESAS_RX_OFS0_IWDTCKS
+	int "IWDT Clock Divide Ratio Select"
+	default 15
+	help
+	  0: No division
+	  2: Divide-by-16
+	  3: Divide-by-32
+	  4: Divide-by-64
+	  15: Divide-by-128
+	  5: Divide-by-256
+
+config IWDT_RENESAS_RX_OFS0_IWDTRPSS
+	int "IWDT Window Start Position Select"
+	default 3
+	help
+	  0: 25%
+	  1: 50%
+	  2: 75%
+	  3: 100% (window start position is not specified.)
+
+config IWDT_RENESAS_RX_OFS0_IWDTRPES
+	int "IWDT Window End Position Select"
+	default 3
+	help
+	  0: 75%
+	  1: 50%
+	  2: 25%
+	  3: 0% (window end position is not specified.)
+
+config IWDT_RENESAS_RX_OFS0_IWDTRSTIRQS
+	int "IWDT Reset Interrupt Request Select"
+	default 0
+	help
+	  0: Non-maskable interrupt request output is enabled.
+	  1: Reset output is enabled.
+
+config IWDT_RENESAS_RX_OFS0_IWDTSLCSTP
+	int "IWDT Sleep Mode Count Stop Control"
+	default 0
+	help
+	  0: Count stop is disabled.
+	  1: Count is stopped at a transition to sleep mode, software standby mode, or deep sleep mode.
+
+endif # IWDT_RENESAS_RX_AUTO_START_MODE
+endif # IWDT_RENESAS_RX
diff --git a/drivers/watchdog/wdt_iwdt_renesas_rx.c b/drivers/watchdog/wdt_iwdt_renesas_rx.c
new file mode 100644
index 0000000000000..b7afbf1c3b414
--- /dev/null
+++ b/drivers/watchdog/wdt_iwdt_renesas_rx.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation and/or its affiliates
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @brief Independent Watchdog (IWDT) Driver for Renesas RX
+ */
+
+#define DT_DRV_COMPAT renesas_rx_iwdt
+
+#include <zephyr/drivers/watchdog.h>
+#include <soc.h>
+#include <zephyr/kernel.h>
+#include <stdlib.h>
+#include <zephyr/arch/rx/sw_nmi_table.h>
+
+#include "r_iwdt_rx_if.h"
+
+#include <platform.h>
+
+#define LOG_LEVEL CONFIG_WDT_LOG_LEVEL
+#include <zephyr/logging/log.h>
+LOG_MODULE_REGISTER(wdt_iwdt_rx);
+
+#define IWDT_NODELABEL    DT_NODELABEL(iwdt)
+#define IWDT_NMI_VECTOR   2
+#define IWDT_WINDOW_START DT_PROP(IWDT_NODELABEL, window_start)
+#define IWDT_WINDOW_END   DT_PROP(IWDT_NODELABEL, window_end)
+
+#define WDT_RENESAS_RX_SUPPORTED_FLAGS (WDT_FLAG_RESET_NONE | WDT_FLAG_RESET_SOC)
+struct wdt_iwdt_rx_config {
+	struct st_iwdt *const regs;
+	const struct device *clock_dev;
+};
+
+struct wdt_iwdt_rx_data {
+	wdt_callback_t callback;
+	iwdt_config_t iwdt_config;
+	bool timeout_installed;
+};
+
+#if CONFIG_IWDT_RX_NMI
+static void wdt_iwdt_isr(const struct device *dev)
+{
+	struct wdt_iwdt_rx_data *data = dev->data;
+
+	if (data->callback) {
+		data->callback(dev, 0);
+	}
+}
+
+static void iwdt_enable_nmi(void)
+{
+	ICU.NMIER.BIT.IWDTEN = 0x1;
+}
+#endif /* CONFIG_IWDT_RX_NMI */
+
+static int wdt_iwdt_rx_disable(const struct device *dev)
+{
+	ARG_UNUSED(dev);
+
+	/* watchdog cannot be stopped once started */
+	LOG_ERR("Independent Watchdog cannot be stopped once started");
+
+	return -EPERM;
+}
+
+static int wdt_iwdt_rx_feed(const struct device *dev, int channel_id)
+{
+	ARG_UNUSED(dev);
+	ARG_UNUSED(channel_id);
+	iwdt_err_t err;
+
+	/* Reset counter */
+	err = R_IWDT_Control(IWDT_CMD_REFRESH_COUNTING, NULL);
+	if (err != IWDT_SUCCESS) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int wdt_iwdt_rx_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg)
+{
+	struct wdt_iwdt_rx_data *data = dev->data;
+	const struct wdt_iwdt_rx_config *iwdt_cfg = dev->config;
+	uint32_t clock_rate;
+	int ret;
+
+	/* Get the iwdt clock rate in hz */
+	ret = clock_control_get_rate(iwdt_cfg->clock_dev, NULL, &clock_rate);
+	if (ret != 0) {
+		return ret;
+	}
+
+	uint32_t clock_rate_khz = clock_rate / 1000;
+
+	const uint16_t timeout_period[4] = {128, 512, 1024, 2048};
+	const uint16_t clock_divide[6][2] = {{IWDT_CLOCK_DIV_1, 1},     {IWDT_CLOCK_DIV_16, 16},
+					     {IWDT_CLOCK_DIV_32, 32},   {IWDT_CLOCK_DIV_64, 64},
+					     {IWDT_CLOCK_DIV_128, 128}, {IWDT_CLOCK_DIV_256, 256}};
+	int16_t last_error = INT16_MAX;
+	int32_t error;
+	uint16_t iwdt_tops = 0;
+	uint16_t iwdt_clock_div = 0;
+	uint16_t iwdt_timeout = ((uint32_t)timeout_period[0] * clock_divide[0][1]) / clock_rate_khz;
+
+	if (cfg->window.min > cfg->window.max || cfg->window.max < iwdt_timeout) {
+		return -EINVAL;
+	}
+
+	if ((cfg->flags & ~WDT_RENESAS_RX_SUPPORTED_FLAGS) != 0) {
+		return -ENOTSUP;
+	}
+
+	if (cfg->callback != NULL && (cfg->flags & WDT_FLAG_RESET_MASK) != 0) {
+		LOG_ERR("WDT_FLAG_RESET_NONE should be chosen in case of interrupt response");
+		return -ENOTSUP;
+	}
+
+#if CONFIG_IWDT_RENESAS_RX_IWDT
+	for (int idx_p = 0; idx_p < 4; idx_p++) {
+		for (int idx_d = 0; idx_d < 6; idx_d++) {
+			iwdt_timeout = ((uint32_t)timeout_period[idx_p] * clock_divide[idx_d][1]) /
+				       clock_rate_khz;
+			error = cfg->window.max - iwdt_timeout;
+
+			if (error < 0) {
+				break;
+			}
+
+			if (error < last_error) {
+				last_error = error;
+				iwdt_tops = idx_p;
+				iwdt_clock_div = clock_divide[idx_d][0];
+			}
+		}
+	}
+
+	data->iwdt_config.timeout = iwdt_tops;
+	data->iwdt_config.iwdtclk_div = iwdt_clock_div;
+	data->iwdt_config.window_start = IWDT_WINDOW_START;
+	data->iwdt_config.window_end = IWDT_WINDOW_END;
+	data->iwdt_config.timeout_control =
+		(cfg->flags & WDT_FLAG_RESET_MASK) != 0 ? IWDT_TIMEOUT_RESET : IWDT_TIMEOUT_NMI;
+	data->iwdt_config.count_stop_enable = IWDT_COUNT_STOP_DISABLE;
+#endif /* CONFIG_IWDT_RENESAS_RX_IWDT */
+
+	data->timeout_installed = true;
+
+#if CONFIG_IWDT_RX_NMI
+	data->callback = cfg->callback;
+#endif
+
+	return 0;
+}
+
+static int wdt_iwdt_rx_setup(const struct device *dev, uint8_t options)
+{
+	struct wdt_iwdt_rx_data *data = dev->data;
+	iwdt_err_t err;
+	int ret;
+
+#if CONFIG_IWDT_RENESAS_RX_IWDT
+	if (!data->timeout_installed) {
+		return -EINVAL;
+	}
+#endif /* CONFIG_IWDT_RENESAS_RX_IWDT */
+
+	if (options & WDT_OPT_PAUSE_IN_SLEEP) {
+		data->iwdt_config.count_stop_enable = IWDT_COUNT_STOP_ENABLE;
+	} else {
+		data->iwdt_config.count_stop_enable = IWDT_COUNT_STOP_DISABLE;
+	}
+
+	if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
+		return -ENOTSUP;
+	}
+
+#if CONFIG_IWDT_RX_NMI
+	nmi_enable(IWDT_NMI_VECTOR, (nmi_callback_t)wdt_iwdt_isr, (void *)dev);
+	iwdt_enable_nmi();
+#endif /* CONFIG_IWDT_RX_NMI */
+
+#if CONFIG_IWDT_RENESAS_RX_IWDT
+
+	err = R_IWDT_Open(&data->iwdt_config);
+	if (err != IWDT_SUCCESS) {
+		return -EINVAL;
+	}
+
+	ret = wdt_iwdt_rx_feed(dev, 0);
+	if (ret != 0) {
+		return ret;
+	}
+#endif /* CONFIG_IWDT_RENESAS_RX_IWDT */
+
+	return 0;
+}
+
+static DEVICE_API(wdt, wdt_iwdt_rx_api) = {
+	.disable = wdt_iwdt_rx_disable,
+	.feed = wdt_iwdt_rx_feed,
+	.install_timeout = wdt_iwdt_rx_install_timeout,
+	.setup = wdt_iwdt_rx_setup,
+};
+
+#define IWDT_RENESAS_RX_DEFINE(idx)                                                                \
+	static struct wdt_iwdt_rx_config iwdt_rx_cfg##idx = {                                      \
+		.regs = (struct st_iwdt *)DT_REG_ADDR(IWDT_NODELABEL),                             \
+		.clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(idx)),                                   \
+	};                                                                                         \
+	static struct wdt_iwdt_rx_data iwdt_rx_data##idx = {                                       \
+		.timeout_installed = false,                                                        \
+		.iwdt_config = {.count_stop_enable = IWDT_COUNT_STOP_DISABLE,                      \
+				.timeout_control = IWDT_TIMEOUT_RESET},                            \
+	};                                                                                         \
+                                                                                                   \
+	DEVICE_DT_DEFINE(idx, NULL, NULL, &iwdt_rx_data##idx, &iwdt_rx_cfg##idx, POST_KERNEL,      \
+			 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_iwdt_rx_api);
+
+DT_FOREACH_STATUS_OKAY(renesas_rx_iwdt, IWDT_RENESAS_RX_DEFINE);
diff --git a/dts/bindings/watchdog/renesas,rx-iwdt.yaml b/dts/bindings/watchdog/renesas,rx-iwdt.yaml
new file mode 100644
index 0000000000000..bcfd1b400c611
--- /dev/null
+++ b/dts/bindings/watchdog/renesas,rx-iwdt.yaml
@@ -0,0 +1,39 @@
+# Copyright (c) 2025 Renesas Electronics Corporation and/or its affiliates
+# SPDX-License-Identifier: Apache-2.0
+
+description: Renesas RX Independent Watchdog
+
+compatible: "renesas,rx-iwdt"
+
+include: base.yaml
+
+properties:
+  reg:
+    required: true
+
+  clocks:
+    required: true
+
+  window-start:
+    required: true
+    type: int
+    enum: [0, 0x1000, 0x2000, 0x3000]
+    description: |
+      The start of the window in clock cycles. The watchdog will reset the system
+      if the watchdog is not refreshed within the window.
+      - 0: 25%
+      - 0x1000: 50%
+      - 0x2000: 75%
+      - 0x3000: 100% (window end position is not specified.)
+
+  window-end:
+    required: true
+    type: int
+    enum: [0, 0x100, 0x200, 0x300]
+    description: |
+      The end of the window in clock cycles. The watchdog will reset the system
+      if the watchdog is not refreshed within the window.
+      - 0: 75%
+      - 0x200: 50%
+      - 0x200: 25%
+      - 0x300: 0% (window start position is not specified.)
diff --git a/modules/Kconfig.renesas b/modules/Kconfig.renesas
index 1f62e38720fb2..895073cf8267a 100644
--- a/modules/Kconfig.renesas
+++ b/modules/Kconfig.renesas
@@ -284,4 +284,9 @@ config USE_RX_RDP_RSPI
 	help
 	  Enable RX RDP RSPI driver
 
+config USE_RX_RDP_IWDT
+	bool
+	help
+	  Enable RX RDP IWDT driver
+
 endif # HAS_RENESAS_RX_RDP

From dfde76533b1bda25bad86b4f64a7a7301f7f60fc Mon Sep 17 00:00:00 2001
From: Quy Tran <quy.tran.pz@renesas.com>
Date: Thu, 20 Feb 2025 14:55:27 +0700
Subject: [PATCH 4/7] soc: renesas: rx: enable option function select register
 0

Enables OSF0 register select for IWDT driver setting on start mode

Signed-off-by: Quy Tran <quy.tran.pz@renesas.com>
---
 soc/renesas/rx/rx130/ofsm.c | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/soc/renesas/rx/rx130/ofsm.c b/soc/renesas/rx/rx130/ofsm.c
index 70fc502503e7e..6f82e4c0723a7 100644
--- a/soc/renesas/rx/rx130/ofsm.c
+++ b/soc/renesas/rx/rx130/ofsm.c
@@ -15,6 +15,8 @@
  */
 
 #define __OFS_MDE __attribute__((section(".ofs_mde")))
+#define __OFS0    __attribute__((section(".ofs0")))
+#define __OFS1    __attribute__((section(".ofs1")))
 
 /* Endian Select Register (MDE) at 0xFE7F5D00
  *
@@ -28,22 +30,29 @@
  */
 const unsigned long __OFS_MDE __MDEreg = 0xffffffff; /* little */
 
-struct st_ofs0 {
-	unsigned long res0: 1;
-	unsigned long IWDTSTRT: 1;
-	unsigned long IWDTTOPS: 2;
-	unsigned long IWDTCKS: 4;
-	unsigned long IWDTRPES: 2;
-	unsigned long IWDTRPSS: 2;
-	unsigned long IWDTRSTIRQS: 1;
-	unsigned long res1: 1;
-	unsigned long IWDTSLCSTP: 1;
-	unsigned long res2: 16;
+#ifdef CONFIG_IWDT_RENESAS_RX_AUTO_START_MODE
+/* Option Function Select Register 0 (OFS0)
+ * This section sets the IWDT (Independent Watchdog Timer) behavior immediately after reset
+ * by programming the OFS0 register. When enabled, IWDT starts counting automatically
+ * starts after a reset.
+ */
+struct st_ofs0 __OFS0 __OFS0reg = {
+	.res0 = 1,
+	.IWDTSTRT = CONFIG_IWDT_RENESAS_RX_IWDTSTRT,
+	.IWDTTOPS = CONFIG_IWDT_RENESAS_RX_OFS0_IWDTTOPS,
+	.IWDTCKS = CONFIG_IWDT_RENESAS_RX_OFS0_IWDTCKS,
+	.IWDTRPES = CONFIG_IWDT_RENESAS_RX_OFS0_IWDTRPES,
+	.IWDTRPSS = CONFIG_IWDT_RENESAS_RX_OFS0_IWDTRPSS,
+	.IWDTRSTIRQS = CONFIG_IWDT_RENESAS_RX_OFS0_IWDTRSTIRQS,
+	.res1 = 1,
+	.IWDTSLCSTP = CONFIG_IWDT_RENESAS_RX_OFS0_IWDTSLCSTP,
+	.res2 = 0xFFFF,
 };
-
-const unsigned long __OFS_MDE __OFS0reg = 0xffffffff;
+#else
+const unsigned long __OFS0 __OFS0reg = 0xffffffff;
+#endif
 
 /* Option Function Select Register 1 (OFS1) at 0xFE7F5D08 (Voltage detection and
  * HOCO)
  */
-const unsigned long __OFS_MDE __OFS1reg = 0xffffffff;
+const unsigned long __OFS1 __OFS1reg = 0xffffffff;

From 5addcecdf9609d23d1e5539da25bcb055a95ddce Mon Sep 17 00:00:00 2001
From: Quy Tran <quy.tran.pz@renesas.com>
Date: Thu, 20 Feb 2025 14:57:14 +0700
Subject: [PATCH 5/7] dts: renesas: rx: add iwdt property node for watchdog
 driver

Add iwdt property node on dts for watchdog driver

Signed-off-by: Quy Tran <quy.tran.pz@renesas.com>
---
 dts/rx/renesas/rx130-common.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/dts/rx/renesas/rx130-common.dtsi b/dts/rx/renesas/rx130-common.dtsi
index 50a6e3523d8d5..20bfe2b257183 100644
--- a/dts/rx/renesas/rx130-common.dtsi
+++ b/dts/rx/renesas/rx130-common.dtsi
@@ -519,5 +519,12 @@
 			zephyr,memory-region = "OFSM";
 			status = "okay";
 		};
+
+		iwdt: watchdog@88030 {
+			compatible = "renesas,rx-iwdt";
+			reg = <0x00088030 0x10>;
+			clocks = <&iwdtlsclk 0 0>;
+			status = "disabled";
+		};
 	};
 };

From d7a0a17fc48e5fa0ab93dfa9a45992711d2c5d90 Mon Sep 17 00:00:00 2001
From: Quy Tran <quy.tran.pz@renesas.com>
Date: Thu, 20 Feb 2025 14:59:14 +0700
Subject: [PATCH 6/7] boards: renesas: Enable watchdog driver on
 RSK-RX130-512kb

Enable iwdt dts nodes and iwdtsclk clock on RSK-RX130-512kb

Signed-off-by: Quy Tran <quy.tran.pz@renesas.com>
---
 boards/renesas/rsk_rx130/rsk_rx130.dts        | 11 +++++++++++
 boards/renesas/rsk_rx130/rsk_rx130_512kb.yaml |  1 +
 2 files changed, 12 insertions(+)

diff --git a/boards/renesas/rsk_rx130/rsk_rx130.dts b/boards/renesas/rsk_rx130/rsk_rx130.dts
index 0fed940418300..2eec9fc01bed1 100644
--- a/boards/renesas/rsk_rx130/rsk_rx130.dts
+++ b/boards/renesas/rsk_rx130/rsk_rx130.dts
@@ -38,6 +38,7 @@
 	aliases {
 		led0 = &led1;
 		led1 = &led3;
+		watchdog0 = &iwdt;
 	};
 };
 
@@ -58,6 +59,10 @@
 	status = "okay";
 };
 
+&iwdtlsclk {
+	status = "okay";
+};
+
 &cmt {
 	clock-frequency = <4000000>;
 	status = "okay";
@@ -88,3 +93,9 @@
 	ssl-assert = <0>;
 	status = "okay";
 };
+
+&iwdt {
+	window-start = <0x3000>;
+	window-end = <0x0300>;
+	status = "okay";
+};
diff --git a/boards/renesas/rsk_rx130/rsk_rx130_512kb.yaml b/boards/renesas/rsk_rx130/rsk_rx130_512kb.yaml
index 537d7e0a7bbbe..142447e717e62 100644
--- a/boards/renesas/rsk_rx130/rsk_rx130_512kb.yaml
+++ b/boards/renesas/rsk_rx130/rsk_rx130_512kb.yaml
@@ -12,5 +12,6 @@ supported:
   - serial
   - timer
   - spi
+  - watchdog
 ram: 48
 flash: 512

From e0de9ec290040af99e5c1f67c912f3358963d696 Mon Sep 17 00:00:00 2001
From: Quy Tran <quy.tran.pz@renesas.com>
Date: Thu, 22 May 2025 18:05:03 +0700
Subject: [PATCH 7/7] tests: driver: watchdog: add marco define for Renesas RX

The Renesas RX watchdog doesn't support PAUSE_HALTED_BY_DBG
flag, so need to update the WDT_SETUP_FLAGS for this test

Signed-off-by: Quy Tran <quy.tran.pz@renesas.com>
---
 samples/drivers/watchdog/src/main.c                    | 3 +++
 tests/drivers/watchdog/wdt_basic_reset_none/src/main.c | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/samples/drivers/watchdog/src/main.c b/samples/drivers/watchdog/src/main.c
index 61a93c16d5dd5..87a05275125dc 100644
--- a/samples/drivers/watchdog/src/main.c
+++ b/samples/drivers/watchdog/src/main.c
@@ -45,6 +45,9 @@
 #elif DT_HAS_COMPAT_STATUS_OKAY(wch_iwdg)
 #define WDT_ALLOW_CALLBACK 0
 #define WDT_OPT            0
+#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rx_iwdt)
+#define WDT_ALLOW_CALLBACK 0
+#define WDT_OPT            0
 #endif
 
 #ifndef WDT_ALLOW_CALLBACK
diff --git a/tests/drivers/watchdog/wdt_basic_reset_none/src/main.c b/tests/drivers/watchdog/wdt_basic_reset_none/src/main.c
index 9fa744d0bba8f..a514910b26784 100644
--- a/tests/drivers/watchdog/wdt_basic_reset_none/src/main.c
+++ b/tests/drivers/watchdog/wdt_basic_reset_none/src/main.c
@@ -27,6 +27,10 @@
 #define WDT_SETUP_FLAGS		0
 #define WDT_TIMEOUT		K_TICKS(WDT_TIMEOUT_VALUE)
 #define SLEEP_TIME		K_TICKS(CONFIG_TEST_WDT_SLEEP_TIME)
+#elif defined(CONFIG_IWDT_RENESAS_RX)
+#define WDT_SETUP_FLAGS		0
+#define WDT_TIMEOUT		K_MSEC(WDT_TIMEOUT_VALUE)
+#define SLEEP_TIME		K_MSEC(CONFIG_TEST_WDT_SLEEP_TIME)
 #else
 #define WDT_SETUP_FLAGS		WDT_OPT_PAUSE_HALTED_BY_DBG
 #define WDT_TIMEOUT		K_MSEC(WDT_TIMEOUT_VALUE)