pkarashchenko commented on a change in pull request #5698:
URL: https://github.com/apache/incubator-nuttx/pull/5698#discussion_r822121474



##########
File path: arch/xtensa/src/esp32s2/esp32s2_wdt.c
##########
@@ -22,15 +22,824 @@
  * Included Files
  ****************************************************************************/
 
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <debug.h>
+
 #include "xtensa.h"
+#include "esp32s2_irq.h"
+#include "esp32s2_wdt.h"
+#include "hardware/esp32s2_efuse.h"
 #include "hardware/esp32s2_rtccntl.h"
+#include "hardware/esp32s2_tim.h"
 
-#include "esp32s2_wdt.h"
+#ifdef CONFIG_ESP32S2_RWDT
+#  error "RWDT not yet supported due to missing RTC driver!"
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Check whether the provided device is a RTC Watchdog Timer */
+
+#define IS_RWDT(dev)    (((struct esp32s2_wdt_priv_s *)dev)->base == \

Review comment:
       ```suggestion
   #define IS_RWDT(dev)    (((struct esp32s2_wdt_priv_s *)(dev))->base == \
   ```

##########
File path: arch/xtensa/src/esp32s2/esp32s2_wdt.c
##########
@@ -48,3 +857,64 @@ void esp32s2_wdt_early_deinit(void)
   putreg32(regval, RTC_CNTL_WDTCONFIG0_REG);
   putreg32(0, RTC_CNTL_WDTWPROTECT_REG);
 }
+
+/****************************************************************************
+ * Name: esp32s2_wdt_deinit
+ *
+ * Description:
+ *   Deinitialize a WDT device.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+void esp32s2_wdt_deinit(struct esp32s2_wdt_dev_s *dev)
+{
+  struct esp32s2_wdt_priv_s *wdt = NULL;

Review comment:
       ```suggestion
     struct esp32s2_wdt_priv_s *wdt;
   ```
   as `wdt` is unconditionally initialized few lines below

##########
File path: arch/xtensa/src/esp32s2/esp32s2_wdt_lowerhalf.c
##########
@@ -0,0 +1,740 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/esp32s2_wdt_lowerhalf.c
+ *
+ * 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 <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/clock.h>
+#include <nuttx/timers/watchdog.h>
+
+#include "xtensa.h"
+#include "esp32s2_wdt.h"
+#include "esp32s2_wdt_lowerhalf.h"
+#include "hardware/esp32s2_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* MWDT clock period in microseconds */
+
+#define MWDT_CLK_PERIOD_US        (500)
+
+/* Number of MWDT cycles per microseconds */
+
+#define MWDT_CYCLES_PER_MS        (USEC_PER_MSEC / MWDT_CLK_PERIOD_US)
+
+/* Convert MWDT timeout cycles to milliseconds */
+
+#define MWDT_TIMEOUT_MS(t)        ((t) * MWDT_CYCLES_PER_MS)
+
+/* Maximum number of MWDT cycles supported for timeout */
+
+#define MWDT_MAX_TIMEOUT_MS       (UINT32_MAX / MWDT_CYCLES_PER_MS)
+
+/* MWDT clock prescaler value */
+
+#define MWDT_CLK_PRESCALER_VALUE  (MWDT_CLK_PERIOD_US * NSEC_PER_USEC / 12.5)
+
+/* Maximum number of cycles supported for a RWDT stage timeout */
+
+#define RWDT_FULL_STAGE           (UINT32_MAX)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+enum wdt_peripheral_e
+{
+  RTC,
+  TIMER,

Review comment:
       ```suggestion
     TIMER
   ```

##########
File path: arch/xtensa/src/esp32s2/esp32s2_wdt.c
##########
@@ -22,15 +22,824 @@
  * Included Files
  ****************************************************************************/
 
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <debug.h>
+
 #include "xtensa.h"
+#include "esp32s2_irq.h"
+#include "esp32s2_wdt.h"
+#include "hardware/esp32s2_efuse.h"
 #include "hardware/esp32s2_rtccntl.h"
+#include "hardware/esp32s2_tim.h"
 
-#include "esp32s2_wdt.h"
+#ifdef CONFIG_ESP32S2_RWDT
+#  error "RWDT not yet supported due to missing RTC driver!"
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Check whether the provided device is a RTC Watchdog Timer */
+
+#define IS_RWDT(dev)    (((struct esp32s2_wdt_priv_s *)dev)->base == \
+                         RTC_CNTL_OPTIONS0_REG)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct esp32s2_wdt_priv_s
+{
+  struct esp32s2_wdt_ops_s *ops;
+  uint32_t                  base;    /* WDT register base address */
+  uint8_t                   periph;  /* Peripheral ID */
+  uint8_t                   irq;     /* Interrupt ID */
+  int32_t                   cpuint;  /* CPU interrupt assigned to this WDT */
+  bool                      inuse;   /* Flag indicating if this WDT is in use 
*/
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* WDT registers access *****************************************************/
+
+static void wdt_putreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                       uint32_t value);
+static void wdt_modifyreg32(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                            uint32_t clearbits, uint32_t setbits);
+static uint32_t wdt_getreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset);
+
+/* WDT operations ***********************************************************/
+
+static void wdt_start(struct esp32s2_wdt_dev_s *dev);
+static void wdt_stop(struct esp32s2_wdt_dev_s *dev);
+static void wdt_enablewp(struct esp32s2_wdt_dev_s *dev);
+static void wdt_disablewp(struct esp32s2_wdt_dev_s *dev);
+static void wdt_pre(struct esp32s2_wdt_dev_s *dev,
+                    uint16_t value);
+static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev,
+                              uint32_t value,
+                              enum esp32s2_wdt_stage_e stage);
+static void wdt_feed(struct esp32s2_wdt_dev_s *dev);
+static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
+                                enum esp32s2_wdt_stage_e stage,
+                                enum esp32s2_wdt_stage_action_e cfg);
+static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev,
+                          xcpt_t handler, void *arg);
+static void wdt_enableint(struct esp32s2_wdt_dev_s *dev);
+static void wdt_disableint(struct esp32s2_wdt_dev_s *dev);
+static void wdt_ackint(struct esp32s2_wdt_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* ESP32-S2 WDT ops */
+
+struct esp32s2_wdt_ops_s esp32s2_mwdt_ops =
+{
+  .start         = wdt_start,
+  .stop          = wdt_stop,
+  .enablewp      = wdt_enablewp,
+  .disablewp     = wdt_disablewp,
+  .pre           = wdt_pre,
+  .settimeout    = wdt_settimeout,
+  .feed          = wdt_feed,
+  .stg_conf      = wdt_config_stage,
+  .rtc_clk       = NULL,
+  .setisr        = wdt_setisr,
+  .enableint     = wdt_enableint,
+  .disableint    = wdt_disableint,
+  .ackint        = wdt_ackint,
+};
+
+struct esp32s2_wdt_ops_s esp32s2_rwdt_ops =
+{
+  .start         = wdt_start,
+  .stop          = wdt_stop,
+  .enablewp      = wdt_enablewp,
+  .disablewp     = wdt_disablewp,
+  .pre           = NULL,
+  .settimeout    = wdt_settimeout,
+  .feed          = wdt_feed,
+  .stg_conf      = wdt_config_stage,
+  .rtc_clk       = NULL,
+  .setisr        = wdt_setisr,
+  .enableint     = wdt_enableint,
+  .disableint    = wdt_disableint,
+  .ackint        = wdt_ackint,
+};
+
+#ifdef CONFIG_ESP32S2_MWDT0
+struct esp32s2_wdt_priv_s g_esp32s2_mwdt0_priv =
+{
+  .ops    = &esp32s2_mwdt_ops,
+  .base   = TIMG_T0CONFIG_REG(0),
+  .periph = ESP32S2_PERIPH_TG_WDT_LEVEL,
+  .irq    = ESP32S2_IRQ_TG_WDT_LEVEL,
+  .cpuint = -ENOMEM,
+  .inuse  = false,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_MWDT1
+struct esp32s2_wdt_priv_s g_esp32s2_mwdt1_priv =
+{
+  .ops    = &esp32s2_mwdt_ops,
+  .base   = TIMG_T0CONFIG_REG(1),
+  .periph = ESP32S2_PERIPH_TG1_WDT_LEVEL,
+  .irq    = ESP32S2_IRQ_TG1_WDT_LEVEL,
+  .cpuint = -ENOMEM,
+  .inuse  = false,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_RWDT
+struct esp32s2_wdt_priv_s g_esp32s2_rwdt_priv =
+{
+  .ops    = &esp32s2_rwdt_ops,
+  .base   = RTC_CNTL_OPTIONS0_REG,
+  .periph = ESP32S2_PERIPH_RTC_CORE,
+  .irq    = ESP32S2_IRQ_RTC_CORE,
+  .cpuint = -ENOMEM,
+  .inuse  = false,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: wdt_putreg
+ *
+ * Description:
+ *   Write a 32-bit register value by offset.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   offset        - Offset value to the base address of the WDT device.
+ *   value         - Value to written to the specified memory region.
+ *
+ ****************************************************************************/
+
+static void wdt_putreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                       uint32_t value)
+{
+  DEBUGASSERT(dev != NULL);
+
+  putreg32(value, ((struct esp32s2_wdt_priv_s *)dev)->base + offset);
+}
+
+/****************************************************************************
+ * Name: wdt_modifyreg32
+ *
+ * Description:
+ *   Atomically modify a 32-bit register value by offset.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   offset        - Offset value to the base address of the WDT device.
+ *   clearbits     - Bits to be cleared on the specified memory region.
+ *   setbits       - Bits to be set on the specified memory region.
+ *
+ ****************************************************************************/
+
+static void wdt_modifyreg32(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                            uint32_t clearbits, uint32_t setbits)
+{
+  DEBUGASSERT(dev != NULL);
+
+  modifyreg32(((struct esp32s2_wdt_priv_s *)dev)->base + offset,
+                clearbits, setbits);
+}
+
+/****************************************************************************
+ * Name: wdt_getreg
+ *
+ * Description:
+ *   Read a 32-bit register value by offset.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   offset        - Offset value to the base address of the WDT device.
+ *
+ *  Returned Values:
+ *    A 32-bit value from the provided memory region of the WDT device.
+ *
+ ****************************************************************************/
+
+static uint32_t wdt_getreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset)
+{
+  DEBUGASSERT(dev != NULL);
+
+  return getreg32(((struct esp32s2_wdt_priv_s *)dev)->base + offset);
+}
+
+/****************************************************************************
+ * Name: wdt_start
+ *
+ * Description:
+ *   Release the counter.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_start(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, 0, RTC_CNTL_WDT_EN);
+    }
+  else
+    {
+      wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, 0, TIMG_WDT_EN);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_config_stage
+ *
+ * Description:
+ *   Configure the action to be triggered by a stage on expiration.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   stage         - WDT stage to be configured.
+ *   cfg           - Action to be executed on stage expiration.
+ *
+ * Returned Values:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
+                                enum esp32s2_wdt_stage_e stage,
+                                enum esp32s2_wdt_stage_action_e cfg)
+{
+  int32_t ret = OK;
+  uint32_t mask;
+
+  DEBUGASSERT(dev != NULL);
+
+  switch (stage)
+  {
+    case ESP32S2_WDT_STAGE0:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG0_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG0_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG0_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG0_M, mask);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE1:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG1_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG1_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG1_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG1_M, mask);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE2:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG2_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG2_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG2_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG2_M, mask);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE3:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG3_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG3_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG3_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG3_M, mask);
+          }
+        break;
+      }
+
+    default:
+      {
+        wderr("ERROR: unsupported stage %d\n", stage);
+        ret = -EINVAL;
+        goto errout;
+      }
+  }
+
+  errout:
+    return ret;
+}
+
+/****************************************************************************
+ * Name: wdt_stop
+ *
+ * Description:
+ *   Disable the watchdog.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_stop(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_EN, 0);
+    }
+  else
+    {
+      wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_EN, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_enablewp
+ *
+ * Description:
+ *   Enable write protection (WP) on registers against accidental writing.
+ *   TRM recommends to change any WDT register through this sequence:
+ *   - Disable WP
+ *   - Do the op
+ *   - Re-enable WP
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_enablewp(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_putreg(dev, RWDT_WP_REG, 0);
+    }
+  else
+    {
+      wdt_putreg(dev, MWDT_WP_REG, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_disablewp
+ *
+ * Description:
+ *   Disable write protection (WP) on registers against accidental writing.
+ *   TRM recommends to change any WDT register through this sequence:
+ *   - Disable WP
+ *   - Do the op
+ *   - Re-enable WP
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_disablewp(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_putreg(dev, RWDT_WP_REG, RTC_CNTL_WDT_WKEY_VALUE);
+    }
+  else
+    {
+      wdt_putreg(dev, MWDT_WP_REG, TIMG_WDT_WKEY_VALUE);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_pre
+ *
+ * Description:
+ *   Set a prescale value.
+ *   The MWDT clock period is 12.5 ns * value (pre).
+ *   NOTE: There's no prescaler register for RWDT and its source clock is
+ *   clocked from the RTC slow clock.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   pre           - Prescaler value to be configured.
+ *
+ ****************************************************************************/
+
+static void wdt_pre(struct esp32s2_wdt_dev_s *dev, uint16_t pre)
+{
+  uint32_t mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALER_S;
+
+  DEBUGASSERT(dev != NULL);
+
+  wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET, TIMG_WDT_CLK_PRESCALER_M,
+                  mask);
+}
+
+/****************************************************************************
+ * Name: wdt_settimeout
+ *
+ * Description:
+ *   Set the WDT timeout.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   value         - Timeout value in number of WDT cycles.
+ *   stage         - Stage whose timeout value needs to be configured.
+ *
+ * Returned Values:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev, uint32_t value,
+                              enum esp32s2_wdt_stage_e stage)
+{
+  int32_t ret = OK;
+
+  DEBUGASSERT(dev != NULL);
+
+  switch (stage)
+  {
+    case ESP32S2_WDT_STAGE0:
+      {
+        if (IS_RWDT(dev))
+          {
+            /* The timeout of only stage 0 happens at:
+             * Thold0 = RTC_CNTL_WDT_STG0_HOLD << (EFUSE_WDT_DELAY_SEL + 1)
+             */
+
+            uint32_t delay;
+            delay = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG,
+                                  EFUSE_WDT_DELAY_SEL);
+            value = value >> (delay + 1);
+            wdt_putreg(dev, RWDT_STAGE0_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE0_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE1:
+      {
+        if (IS_RWDT(dev))
+          {
+            wdt_putreg(dev, RWDT_STAGE1_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE1_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE2:
+      {
+        if (IS_RWDT(dev))
+          {
+            wdt_putreg(dev, RWDT_STAGE2_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE2_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE3:
+      {
+        if (IS_RWDT(dev))
+          {
+            wdt_putreg(dev, RWDT_STAGE3_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE3_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    default:
+      {
+        wderr("ERROR: unsupported stage %d\n", stage);
+        ret = -EINVAL;
+        goto errout;
+      }
+  }
+
+  errout:
+    return ret;
+}
+
+/****************************************************************************
+ * Name: wdt_feed
+ *
+ * Description:
+ *   Feed the watchdog.
+ *   The watchdog timer returns to stage 0 and its counter restarts from 0.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_feed(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_FEED_OFFSET, 0, RTC_CNTL_WDT_FEED);
+    }
+  else
+    {
+      wdt_putreg(dev, MWDT_FEED_OFFSET, TIMG_WDT_FEED);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_setisr
+ *
+ * Description:
+ *   Allocate a Level CPU Interrupt, connect the peripheral source to this
+ *   Interrupt, register the callback and enable the interrupt.
+ *   In case a NULL handler is provided, deallocate the interrupt and
+ *   unregister the previously provided handler.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   handler       - Callback to be invoked on watchdog timer interrupt.
+ *   arg           - Argument to be passed to the handler callback.
+ *
+ * Returned Values:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev, xcpt_t handler,
+                          void *arg)
+{
+  struct esp32s2_wdt_priv_s *wdt = NULL;

Review comment:
       ```suggestion
     struct esp32s2_wdt_priv_s *wdt;
   ```
   as `wdt` is unconditionally initialized few lines below

##########
File path: arch/xtensa/src/esp32s2/esp32s2_wdt_lowerhalf.c
##########
@@ -0,0 +1,740 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/esp32s2_wdt_lowerhalf.c
+ *
+ * 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 <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/clock.h>
+#include <nuttx/timers/watchdog.h>
+
+#include "xtensa.h"
+#include "esp32s2_wdt.h"
+#include "esp32s2_wdt_lowerhalf.h"
+#include "hardware/esp32s2_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* MWDT clock period in microseconds */
+
+#define MWDT_CLK_PERIOD_US        (500)
+
+/* Number of MWDT cycles per microseconds */
+
+#define MWDT_CYCLES_PER_MS        (USEC_PER_MSEC / MWDT_CLK_PERIOD_US)
+
+/* Convert MWDT timeout cycles to milliseconds */
+
+#define MWDT_TIMEOUT_MS(t)        ((t) * MWDT_CYCLES_PER_MS)
+
+/* Maximum number of MWDT cycles supported for timeout */
+
+#define MWDT_MAX_TIMEOUT_MS       (UINT32_MAX / MWDT_CYCLES_PER_MS)
+
+/* MWDT clock prescaler value */
+
+#define MWDT_CLK_PRESCALER_VALUE  (MWDT_CLK_PERIOD_US * NSEC_PER_USEC / 12.5)
+
+/* Maximum number of cycles supported for a RWDT stage timeout */
+
+#define RWDT_FULL_STAGE           (UINT32_MAX)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+enum wdt_peripheral_e
+{
+  RTC,
+  TIMER,
+};
+
+/* This structure provides the private representation of the "lower-half"
+ * driver state structure.  This structure must be cast-compatible with the
+ * well-known watchdog_lowerhalf_s structure.
+ */
+
+struct esp32s2_wdt_lowerhalf_s
+{
+  const struct watchdog_ops_s *ops;        /* Lower-half operations */
+  struct esp32s2_wdt_dev_s *wdt;           /* ESP32-S2 watchdog driver */
+  uint32_t timeout;                        /* The current timeout */
+  enum wdt_peripheral_e peripheral;        /* Indicates if it is from RTC or 
Timer Module */
+  uint32_t lastreset;                      /* The last reset time */
+  bool started;                            /* True: Timer has been started */
+  xcpt_t handler;                          /* User Handler */
+  void *upper;                             /* Pointer to watchdog_upperhalf_s 
*/
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Interrupt handling *******************************************************/
+
+static int    wdt_handler(int irq, void *context, void *arg);
+
+/* "Lower-half" driver methods **********************************************/
+
+static int    wdt_lh_start(struct watchdog_lowerhalf_s *lower);
+static int    wdt_lh_stop(struct watchdog_lowerhalf_s *lower);
+static int    wdt_lh_keepalive(struct watchdog_lowerhalf_s *lower);
+static int    wdt_lh_getstatus(struct watchdog_lowerhalf_s *lower,
+                               struct watchdog_status_s *status);
+static int    wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
+                                uint32_t timeout);
+static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
+                             xcpt_t handler);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* "Lower-half" driver methods */
+
+static const struct watchdog_ops_s g_esp32s2_wdg_ops =
+{
+  .start      = wdt_lh_start,
+  .stop       = wdt_lh_stop,
+  .keepalive  = wdt_lh_keepalive,
+  .getstatus  = wdt_lh_getstatus,
+  .settimeout = wdt_lh_settimeout,
+  .capture    = wdt_lh_capture,
+  .ioctl      = NULL,
+};
+
+#ifdef CONFIG_ESP32S2_MWDT0
+/* MWDT0 lower-half */
+
+static struct esp32s2_wdt_lowerhalf_s g_esp32s2_mwdt0_lowerhalf =
+{
+  .ops = &g_esp32s2_wdg_ops,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_MWDT1
+/* MWDT1 lower-half */
+
+static struct esp32s2_wdt_lowerhalf_s g_esp32s2_mwdt1_lowerhalf =
+{
+  .ops = &g_esp32s2_wdg_ops,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_RWDT
+/* RWDT lower-half */
+
+static struct esp32s2_wdt_lowerhalf_s g_esp32s2_rwdt_lowerhalf =
+{
+  .ops = &g_esp32s2_wdg_ops,
+};
+#endif
+
+/****************************************************************************
+ * Name: wdt_lh_start
+ *
+ * Description:
+ *   Start the watchdog timer, register a callback if there is one and
+ *   enables interrupt, otherwise, configure it to reset system on
+ *   expiration.
+ *
+ * Input Parameters:
+ *   lower - A pointer the publicly visible representation of the
+ *           "lower-half" driver state structure.
+ *
+ * Returned Values:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int wdt_lh_start(struct watchdog_lowerhalf_s *lower)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv =
+    (struct esp32s2_wdt_lowerhalf_s *)lower;
+  int ret = OK;
+
+  wdinfo("Entry: wdt_lh_start\n");
+
+  DEBUGASSERT(priv);
+
+  if (priv->started == true)

Review comment:
       ```suggestion
     if (priv->started)
   ```

##########
File path: arch/xtensa/src/esp32s2/esp32s2_wdt_lowerhalf.c
##########
@@ -0,0 +1,740 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/esp32s2_wdt_lowerhalf.c
+ *
+ * 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 <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/clock.h>
+#include <nuttx/timers/watchdog.h>
+
+#include "xtensa.h"
+#include "esp32s2_wdt.h"
+#include "esp32s2_wdt_lowerhalf.h"
+#include "hardware/esp32s2_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* MWDT clock period in microseconds */
+
+#define MWDT_CLK_PERIOD_US        (500)
+
+/* Number of MWDT cycles per microseconds */
+
+#define MWDT_CYCLES_PER_MS        (USEC_PER_MSEC / MWDT_CLK_PERIOD_US)
+
+/* Convert MWDT timeout cycles to milliseconds */
+
+#define MWDT_TIMEOUT_MS(t)        ((t) * MWDT_CYCLES_PER_MS)
+
+/* Maximum number of MWDT cycles supported for timeout */
+
+#define MWDT_MAX_TIMEOUT_MS       (UINT32_MAX / MWDT_CYCLES_PER_MS)
+
+/* MWDT clock prescaler value */
+
+#define MWDT_CLK_PRESCALER_VALUE  (MWDT_CLK_PERIOD_US * NSEC_PER_USEC / 12.5)
+
+/* Maximum number of cycles supported for a RWDT stage timeout */
+
+#define RWDT_FULL_STAGE           (UINT32_MAX)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+enum wdt_peripheral_e
+{
+  RTC,
+  TIMER,
+};
+
+/* This structure provides the private representation of the "lower-half"
+ * driver state structure.  This structure must be cast-compatible with the
+ * well-known watchdog_lowerhalf_s structure.
+ */
+
+struct esp32s2_wdt_lowerhalf_s
+{
+  const struct watchdog_ops_s *ops;        /* Lower-half operations */
+  struct esp32s2_wdt_dev_s *wdt;           /* ESP32-S2 watchdog driver */
+  uint32_t timeout;                        /* The current timeout */
+  enum wdt_peripheral_e peripheral;        /* Indicates if it is from RTC or 
Timer Module */
+  uint32_t lastreset;                      /* The last reset time */
+  bool started;                            /* True: Timer has been started */
+  xcpt_t handler;                          /* User Handler */
+  void *upper;                             /* Pointer to watchdog_upperhalf_s 
*/
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Interrupt handling *******************************************************/
+
+static int    wdt_handler(int irq, void *context, void *arg);
+
+/* "Lower-half" driver methods **********************************************/
+
+static int    wdt_lh_start(struct watchdog_lowerhalf_s *lower);
+static int    wdt_lh_stop(struct watchdog_lowerhalf_s *lower);
+static int    wdt_lh_keepalive(struct watchdog_lowerhalf_s *lower);
+static int    wdt_lh_getstatus(struct watchdog_lowerhalf_s *lower,
+                               struct watchdog_status_s *status);
+static int    wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
+                                uint32_t timeout);
+static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
+                             xcpt_t handler);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* "Lower-half" driver methods */
+
+static const struct watchdog_ops_s g_esp32s2_wdg_ops =
+{
+  .start      = wdt_lh_start,
+  .stop       = wdt_lh_stop,
+  .keepalive  = wdt_lh_keepalive,
+  .getstatus  = wdt_lh_getstatus,
+  .settimeout = wdt_lh_settimeout,
+  .capture    = wdt_lh_capture,
+  .ioctl      = NULL,
+};
+
+#ifdef CONFIG_ESP32S2_MWDT0
+/* MWDT0 lower-half */
+
+static struct esp32s2_wdt_lowerhalf_s g_esp32s2_mwdt0_lowerhalf =
+{
+  .ops = &g_esp32s2_wdg_ops,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_MWDT1
+/* MWDT1 lower-half */
+
+static struct esp32s2_wdt_lowerhalf_s g_esp32s2_mwdt1_lowerhalf =
+{
+  .ops = &g_esp32s2_wdg_ops,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_RWDT
+/* RWDT lower-half */
+
+static struct esp32s2_wdt_lowerhalf_s g_esp32s2_rwdt_lowerhalf =
+{
+  .ops = &g_esp32s2_wdg_ops,
+};
+#endif
+
+/****************************************************************************
+ * Name: wdt_lh_start
+ *
+ * Description:
+ *   Start the watchdog timer, register a callback if there is one and
+ *   enables interrupt, otherwise, configure it to reset system on
+ *   expiration.
+ *
+ * Input Parameters:
+ *   lower - A pointer the publicly visible representation of the
+ *           "lower-half" driver state structure.
+ *
+ * Returned Values:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int wdt_lh_start(struct watchdog_lowerhalf_s *lower)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv =
+    (struct esp32s2_wdt_lowerhalf_s *)lower;
+  int ret = OK;
+
+  wdinfo("Entry: wdt_lh_start\n");
+
+  DEBUGASSERT(priv);
+
+  if (priv->started == true)
+    {
+      /* Return EBUSY to indicate that the timer was already running */
+
+      ret = -EBUSY;
+      goto errout;
+    }
+
+  /* If WDT was not started yet */
+
+  else
+    {
+      irqstate_t flags;
+
+      priv->started = true;
+
+      /* Unlock WDT */
+
+      ESP32S2_WDT_UNLOCK(priv->wdt);
+
+      /* No User Handler */
+
+      if (priv->handler == NULL)
+        {
+             /* Then configure it to reset on wdt expiration */
+
+            if (priv->peripheral == TIMER)
+              {
+                ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
+                                     ESP32S2_WDT_STAGE_ACTION_RESET_SYSTEM);
+              }
+            else
+              {
+                ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
+                                     ESP32S2_WDT_STAGE_ACTION_RESET_RTC);
+              }
+        }
+
+      /* User handler was already provided */
+
+      else
+        {
+          /* Then configure it to call the user handler on wdt expiration */
+
+          ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
+                               ESP32S2_WDT_STAGE_ACTION_INT);
+
+          /* Set the lower-half handler and enable interrupt */
+
+          flags = enter_critical_section();
+          ESP32S2_WDT_SETISR(priv->wdt, wdt_handler, priv);
+          leave_critical_section(flags);
+          ESP32S2_WDT_ENABLEINT(priv->wdt);
+        }
+
+      flags = enter_critical_section();
+      priv->lastreset = clock_systime_ticks();
+      ESP32S2_WDT_START(priv->wdt);
+      leave_critical_section(flags);
+
+      /* Lock it again */
+
+      ESP32S2_WDT_LOCK(priv->wdt);
+    }
+
+  errout:
+    return ret;
+}
+
+/****************************************************************************
+ * Name: wdt_lh_stop
+ *
+ * Description:
+ *   Stop the watchdog timer. In case a callback was previously configured,
+ *   unregister and deallocate it.
+ *
+ * Input Parameters:
+ *   lower - A pointer the publicly visible representation of the
+ *           "lower-half" driver state structure.
+ *
+ ****************************************************************************/
+
+static int wdt_lh_stop(struct watchdog_lowerhalf_s *lower)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv =
+    (struct esp32s2_wdt_lowerhalf_s *)lower;
+
+  /* Unlock WDT */
+
+  ESP32S2_WDT_UNLOCK(priv->wdt);
+
+  /* Disable the WDT */
+
+  ESP32S2_WDT_STOP(priv->wdt);
+
+  /* In case there is some callback registered, disable and deallocate */
+
+  if (priv->handler != NULL)
+    {
+      irqstate_t flags;
+
+      ESP32S2_WDT_DISABLEINT(priv->wdt);
+
+      flags = enter_critical_section();
+      ESP32S2_WDT_SETISR(priv->wdt, NULL, NULL);
+      leave_critical_section(flags);
+    }
+
+  /* Lock it again */
+
+  ESP32S2_WDT_LOCK(priv->wdt);
+
+  priv->started = false;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: wdt_lh_keepalive
+ *
+ * Description:
+ *   Reset the watchdog timer, prevent any
+ *   imminent watchdog timeouts.  This is sometimes referred as "pinging"
+ *   the watchdog timer or "petting the dog".
+ *
+ * Input Parameters:
+ *   lower - A pointer the publicly visible representation of the
+ *           "lower-half" driver state structure.
+ *
+ *
+ ****************************************************************************/
+
+static int wdt_lh_keepalive(struct watchdog_lowerhalf_s *lower)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv =
+    (struct esp32s2_wdt_lowerhalf_s *)lower;
+  irqstate_t flags;
+
+  wdinfo("Entry\n");
+
+  /* Unlock */
+
+  ESP32S2_WDT_UNLOCK(priv->wdt);
+
+  /* Feed the dog and updates the lastreset variable */
+
+  flags = enter_critical_section();
+  priv->lastreset = clock_systime_ticks();
+  ESP32S2_WDT_FEED(priv->wdt);
+  leave_critical_section(flags);
+
+  /* Lock */
+
+  ESP32S2_WDT_LOCK(priv->wdt);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: wdt_lh_getstatus
+ *
+ * Description:
+ *   Get the current watchdog timer status
+ *
+ * Input Parameters:
+ *   lower  - A pointer the publicly visible representation of
+ *            the "lower-half" driver state structure.
+ *   status - The location to return the watchdog status information.
+ *
+ ****************************************************************************/
+
+static int wdt_lh_getstatus(struct watchdog_lowerhalf_s *lower,
+                            struct watchdog_status_s *status)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv =
+    (struct esp32s2_wdt_lowerhalf_s *)lower;
+  uint32_t ticks;
+  uint32_t elapsed;
+
+  DEBUGASSERT(priv);
+
+  /* Flags */
+
+  status->flags = 0;
+
+  /* If no handler was settled, then RESET on expiration.
+   * Otherwise, call the user handler.
+   */
+
+  if (priv->handler == NULL)
+    {
+      status->flags |= WDFLAGS_RESET;
+    }
+  else
+    {
+      status->flags |= WDFLAGS_CAPTURE;
+    }
+
+  if (priv->started)
+    {
+      status->flags |= WDFLAGS_ACTIVE;
+    }
+
+  /* Return the current timeout in milliseconds */
+
+  status->timeout = priv->timeout;
+
+  /* Get the elapsed time since the last ping */
+
+  ticks   = clock_systime_ticks() - priv->lastreset;
+  elapsed = (uint32_t)TICK2MSEC(ticks);
+
+  if (elapsed < priv->timeout)
+    {
+      /* Return the approximate time until the watchdog timer expiration */
+
+      status->timeleft = priv->timeout - elapsed;
+    }
+  else
+    {
+      status->timeleft = 0;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: wdt_lh_settimeout
+ *
+ * Description:
+ *   Set a new timeout value (and reset the watchdog timer)
+ *
+ * Input Parameters:
+ *   lower   - A pointer the publicly visible representation of
+ *             the "lower-half" driver state structure.
+ *   timeout - The new timeout value in milliseconds.
+ *
+ * Returned Values:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
+                             uint32_t timeout)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv =
+    (struct esp32s2_wdt_lowerhalf_s *)lower;
+  uint16_t rtc_cycles = 0;
+  uint32_t rtc_ms_max = 0;
+
+  wdinfo("Entry: timeout=%" PRIu32 "\n", timeout);
+  DEBUGASSERT(priv);
+
+  /* Unlock WDT */
+
+  ESP32S2_WDT_UNLOCK(priv->wdt);
+
+  /* Write the timeout value */
+
+  priv->timeout = timeout;
+
+  /* Watchdog from Timer Module */
+
+  if (priv->peripheral == TIMER)
+    {
+      /* Is this timeout a valid value for Timer's WDT? */
+
+      if (timeout == 0 || timeout > MWDT_MAX_TIMEOUT_MS)
+        {
+          wderr("Cannot represent timeout=%" PRIu32 " > %" PRIu32 "\n",
+                timeout, MWDT_MAX_TIMEOUT_MS);
+          return -ERANGE;
+        }
+      else
+        {
+          ESP32S2_WDT_STO(priv->wdt, MWDT_TIMEOUT_MS(timeout),
+                          ESP32S2_WDT_STAGE0);
+        }
+    }
+
+  /* Watchdog from RTC Module */
+
+  else
+    {
+      rtc_cycles = ESP32S2_RWDT_CLK(priv->wdt);
+      rtc_ms_max = (RWDT_FULL_STAGE / (uint32_t)rtc_cycles);
+
+      /* Is this timeout a valid value for RTC WDT? */
+
+      if (timeout == 0 || timeout > rtc_ms_max)
+        {
+          wderr("Cannot represent timeout=%" PRIu32 " > %" PRIu32 "\n",
+                timeout, rtc_ms_max);
+          return -ERANGE;
+        }
+      else
+        {
+          timeout = timeout * rtc_cycles;
+          ESP32S2_WDT_STO(priv->wdt, timeout, ESP32S2_WDT_STAGE0);
+        }
+    }
+
+  /* Reset the wdt */
+
+  ESP32S2_WDT_FEED(priv->wdt);
+
+  /* Lock it again */
+
+  ESP32S2_WDT_LOCK(priv->wdt);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: wdt_lh_capture
+ *
+ * Description:
+ *   Don't reset on watchdog timer timeout; instead, call this user provider
+ *   timeout handler.  NOTE:  Providing handler==NULL will restore the reset
+ *   behavior.
+ *
+ * Input Parameters:
+ *   lower      - A pointer the publicly visible representation of the
+ *                "lower-half" driver state structure.
+ *   newhandler - The new watchdog expiration function pointer.  If this
+ *                function pointer is NULL, then the reset-on-expiration
+ *                behavior is restored,
+ *
+ * Returned Value:
+ *   The previous watchdog expiration function pointer or NULL if there was
+ *   no previous function pointer, i.e., if the previous behavior was
+ *   reset-on-expiration (NULL is also returned if an error occurs).
+ *
+ ****************************************************************************/
+
+static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
+                             xcpt_t handler)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv =
+    (struct esp32s2_wdt_lowerhalf_s *)lower;
+  irqstate_t flags;
+  xcpt_t oldhandler;
+
+  DEBUGASSERT(priv);
+
+  wdinfo("Entry: handler=0x%" PRIxPTR "\n", (uintptr_t) handler);
+
+  /* Get the old handler to return it */
+
+  oldhandler = priv->handler;
+
+  ESP32S2_WDT_UNLOCK(priv->wdt);
+
+  flags = enter_critical_section();
+
+  /* Save the new user handler */
+
+  priv->handler = handler;
+
+  /* There is a user callback and the timer has already been started.
+   * The user wants to set a callback after starting the wdt or wants to
+   * change the callback function once a callback has already been settled.
+   */
+
+  if (priv->handler != NULL && priv->started)
+    {
+      /* Deallocate the previous allocated interrupt
+       * If there is a previous allocated interrupt.
+       */
+
+      if (oldhandler != NULL)
+        {
+          ESP32S2_WDT_SETISR(priv->wdt, NULL, NULL);
+        }
+      else
+        {
+          /* If it was previous configured to reset on timeout
+           * then change to interrupt.
+           */
+
+          ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
+                               ESP32S2_WDT_STAGE_ACTION_INT);
+        }
+
+      /* Set the lower-half handler and enable interrupt */
+
+      ESP32S2_WDT_SETISR(priv->wdt, wdt_handler, priv);
+      ESP32S2_WDT_ENABLEINT(priv->wdt);
+    }
+
+  /* In case the user wants to disable the callback */
+
+  else
+    {
+      ESP32S2_WDT_DISABLEINT(priv->wdt);
+      ESP32S2_WDT_SETISR(priv->wdt, NULL, NULL);
+
+      /* Then configure it to reset on WDT expiration */
+
+      if (priv->peripheral == TIMER)
+        {
+          ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
+                               ESP32S2_WDT_STAGE_ACTION_RESET_SYSTEM);
+        }
+      else
+        {
+          ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
+                               ESP32S2_WDT_STAGE_ACTION_RESET_RTC);
+        }
+    }
+
+  leave_critical_section(flags);
+  ESP32S2_WDT_LOCK(priv->wdt);
+  return oldhandler;
+}
+
+/* Interrupt handling *******************************************************/
+
+static int wdt_handler(int irq, void *context, void *arg)
+{
+  struct esp32s2_wdt_lowerhalf_s *priv = arg;

Review comment:
       ```suggestion
     struct esp32s2_wdt_lowerhalf_s *priv = (struct esp32s2_wdt_lowerhalf_s 
*)arg;
   ```

##########
File path: arch/xtensa/src/esp32s2/esp32s2_wdt.c
##########
@@ -22,15 +22,824 @@
  * Included Files
  ****************************************************************************/
 
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <debug.h>
+
 #include "xtensa.h"
+#include "esp32s2_irq.h"
+#include "esp32s2_wdt.h"
+#include "hardware/esp32s2_efuse.h"
 #include "hardware/esp32s2_rtccntl.h"
+#include "hardware/esp32s2_tim.h"
 
-#include "esp32s2_wdt.h"
+#ifdef CONFIG_ESP32S2_RWDT
+#  error "RWDT not yet supported due to missing RTC driver!"
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Check whether the provided device is a RTC Watchdog Timer */
+
+#define IS_RWDT(dev)    (((struct esp32s2_wdt_priv_s *)dev)->base == \
+                         RTC_CNTL_OPTIONS0_REG)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct esp32s2_wdt_priv_s
+{
+  struct esp32s2_wdt_ops_s *ops;
+  uint32_t                  base;    /* WDT register base address */
+  uint8_t                   periph;  /* Peripheral ID */
+  uint8_t                   irq;     /* Interrupt ID */
+  int32_t                   cpuint;  /* CPU interrupt assigned to this WDT */
+  bool                      inuse;   /* Flag indicating if this WDT is in use 
*/
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* WDT registers access *****************************************************/
+
+static void wdt_putreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                       uint32_t value);
+static void wdt_modifyreg32(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                            uint32_t clearbits, uint32_t setbits);
+static uint32_t wdt_getreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset);
+
+/* WDT operations ***********************************************************/
+
+static void wdt_start(struct esp32s2_wdt_dev_s *dev);
+static void wdt_stop(struct esp32s2_wdt_dev_s *dev);
+static void wdt_enablewp(struct esp32s2_wdt_dev_s *dev);
+static void wdt_disablewp(struct esp32s2_wdt_dev_s *dev);
+static void wdt_pre(struct esp32s2_wdt_dev_s *dev,
+                    uint16_t value);
+static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev,
+                              uint32_t value,
+                              enum esp32s2_wdt_stage_e stage);
+static void wdt_feed(struct esp32s2_wdt_dev_s *dev);
+static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
+                                enum esp32s2_wdt_stage_e stage,
+                                enum esp32s2_wdt_stage_action_e cfg);
+static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev,
+                          xcpt_t handler, void *arg);
+static void wdt_enableint(struct esp32s2_wdt_dev_s *dev);
+static void wdt_disableint(struct esp32s2_wdt_dev_s *dev);
+static void wdt_ackint(struct esp32s2_wdt_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* ESP32-S2 WDT ops */
+
+struct esp32s2_wdt_ops_s esp32s2_mwdt_ops =
+{
+  .start         = wdt_start,
+  .stop          = wdt_stop,
+  .enablewp      = wdt_enablewp,
+  .disablewp     = wdt_disablewp,
+  .pre           = wdt_pre,
+  .settimeout    = wdt_settimeout,
+  .feed          = wdt_feed,
+  .stg_conf      = wdt_config_stage,
+  .rtc_clk       = NULL,
+  .setisr        = wdt_setisr,
+  .enableint     = wdt_enableint,
+  .disableint    = wdt_disableint,
+  .ackint        = wdt_ackint,
+};
+
+struct esp32s2_wdt_ops_s esp32s2_rwdt_ops =
+{
+  .start         = wdt_start,
+  .stop          = wdt_stop,
+  .enablewp      = wdt_enablewp,
+  .disablewp     = wdt_disablewp,
+  .pre           = NULL,
+  .settimeout    = wdt_settimeout,
+  .feed          = wdt_feed,
+  .stg_conf      = wdt_config_stage,
+  .rtc_clk       = NULL,
+  .setisr        = wdt_setisr,
+  .enableint     = wdt_enableint,
+  .disableint    = wdt_disableint,
+  .ackint        = wdt_ackint,
+};
+
+#ifdef CONFIG_ESP32S2_MWDT0
+struct esp32s2_wdt_priv_s g_esp32s2_mwdt0_priv =
+{
+  .ops    = &esp32s2_mwdt_ops,
+  .base   = TIMG_T0CONFIG_REG(0),
+  .periph = ESP32S2_PERIPH_TG_WDT_LEVEL,
+  .irq    = ESP32S2_IRQ_TG_WDT_LEVEL,
+  .cpuint = -ENOMEM,
+  .inuse  = false,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_MWDT1
+struct esp32s2_wdt_priv_s g_esp32s2_mwdt1_priv =
+{
+  .ops    = &esp32s2_mwdt_ops,
+  .base   = TIMG_T0CONFIG_REG(1),
+  .periph = ESP32S2_PERIPH_TG1_WDT_LEVEL,
+  .irq    = ESP32S2_IRQ_TG1_WDT_LEVEL,
+  .cpuint = -ENOMEM,
+  .inuse  = false,
+};
+#endif
+
+#ifdef CONFIG_ESP32S2_RWDT
+struct esp32s2_wdt_priv_s g_esp32s2_rwdt_priv =
+{
+  .ops    = &esp32s2_rwdt_ops,
+  .base   = RTC_CNTL_OPTIONS0_REG,
+  .periph = ESP32S2_PERIPH_RTC_CORE,
+  .irq    = ESP32S2_IRQ_RTC_CORE,
+  .cpuint = -ENOMEM,
+  .inuse  = false,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: wdt_putreg
+ *
+ * Description:
+ *   Write a 32-bit register value by offset.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   offset        - Offset value to the base address of the WDT device.
+ *   value         - Value to written to the specified memory region.
+ *
+ ****************************************************************************/
+
+static void wdt_putreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                       uint32_t value)
+{
+  DEBUGASSERT(dev != NULL);
+
+  putreg32(value, ((struct esp32s2_wdt_priv_s *)dev)->base + offset);
+}
+
+/****************************************************************************
+ * Name: wdt_modifyreg32
+ *
+ * Description:
+ *   Atomically modify a 32-bit register value by offset.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   offset        - Offset value to the base address of the WDT device.
+ *   clearbits     - Bits to be cleared on the specified memory region.
+ *   setbits       - Bits to be set on the specified memory region.
+ *
+ ****************************************************************************/
+
+static void wdt_modifyreg32(struct esp32s2_wdt_dev_s *dev, uint32_t offset,
+                            uint32_t clearbits, uint32_t setbits)
+{
+  DEBUGASSERT(dev != NULL);
+
+  modifyreg32(((struct esp32s2_wdt_priv_s *)dev)->base + offset,
+                clearbits, setbits);
+}
+
+/****************************************************************************
+ * Name: wdt_getreg
+ *
+ * Description:
+ *   Read a 32-bit register value by offset.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   offset        - Offset value to the base address of the WDT device.
+ *
+ *  Returned Values:
+ *    A 32-bit value from the provided memory region of the WDT device.
+ *
+ ****************************************************************************/
+
+static uint32_t wdt_getreg(struct esp32s2_wdt_dev_s *dev, uint32_t offset)
+{
+  DEBUGASSERT(dev != NULL);
+
+  return getreg32(((struct esp32s2_wdt_priv_s *)dev)->base + offset);
+}
+
+/****************************************************************************
+ * Name: wdt_start
+ *
+ * Description:
+ *   Release the counter.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_start(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, 0, RTC_CNTL_WDT_EN);
+    }
+  else
+    {
+      wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, 0, TIMG_WDT_EN);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_config_stage
+ *
+ * Description:
+ *   Configure the action to be triggered by a stage on expiration.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   stage         - WDT stage to be configured.
+ *   cfg           - Action to be executed on stage expiration.
+ *
+ * Returned Values:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
+                                enum esp32s2_wdt_stage_e stage,
+                                enum esp32s2_wdt_stage_action_e cfg)
+{
+  int32_t ret = OK;
+  uint32_t mask;
+
+  DEBUGASSERT(dev != NULL);
+
+  switch (stage)
+  {
+    case ESP32S2_WDT_STAGE0:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG0_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG0_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG0_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG0_M, mask);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE1:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG1_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG1_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG1_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG1_M, mask);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE2:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG2_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG2_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG2_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG2_M, mask);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE3:
+      {
+        if (IS_RWDT(dev))
+          {
+            mask = (uint32_t)cfg << RTC_CNTL_WDT_STG3_S;
+            wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG3_M,
+                            mask);
+          }
+        else
+          {
+            mask = (uint32_t)cfg << TIMG_WDT_STG3_S;
+            wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG3_M, mask);
+          }
+        break;
+      }
+
+    default:
+      {
+        wderr("ERROR: unsupported stage %d\n", stage);
+        ret = -EINVAL;
+        goto errout;
+      }
+  }
+
+  errout:
+    return ret;
+}
+
+/****************************************************************************
+ * Name: wdt_stop
+ *
+ * Description:
+ *   Disable the watchdog.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_stop(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_EN, 0);
+    }
+  else
+    {
+      wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_EN, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_enablewp
+ *
+ * Description:
+ *   Enable write protection (WP) on registers against accidental writing.
+ *   TRM recommends to change any WDT register through this sequence:
+ *   - Disable WP
+ *   - Do the op
+ *   - Re-enable WP
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_enablewp(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_putreg(dev, RWDT_WP_REG, 0);
+    }
+  else
+    {
+      wdt_putreg(dev, MWDT_WP_REG, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_disablewp
+ *
+ * Description:
+ *   Disable write protection (WP) on registers against accidental writing.
+ *   TRM recommends to change any WDT register through this sequence:
+ *   - Disable WP
+ *   - Do the op
+ *   - Re-enable WP
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_disablewp(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_putreg(dev, RWDT_WP_REG, RTC_CNTL_WDT_WKEY_VALUE);
+    }
+  else
+    {
+      wdt_putreg(dev, MWDT_WP_REG, TIMG_WDT_WKEY_VALUE);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_pre
+ *
+ * Description:
+ *   Set a prescale value.
+ *   The MWDT clock period is 12.5 ns * value (pre).
+ *   NOTE: There's no prescaler register for RWDT and its source clock is
+ *   clocked from the RTC slow clock.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   pre           - Prescaler value to be configured.
+ *
+ ****************************************************************************/
+
+static void wdt_pre(struct esp32s2_wdt_dev_s *dev, uint16_t pre)
+{
+  uint32_t mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALER_S;
+
+  DEBUGASSERT(dev != NULL);
+
+  wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET, TIMG_WDT_CLK_PRESCALER_M,
+                  mask);
+}
+
+/****************************************************************************
+ * Name: wdt_settimeout
+ *
+ * Description:
+ *   Set the WDT timeout.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   value         - Timeout value in number of WDT cycles.
+ *   stage         - Stage whose timeout value needs to be configured.
+ *
+ * Returned Values:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev, uint32_t value,
+                              enum esp32s2_wdt_stage_e stage)
+{
+  int32_t ret = OK;
+
+  DEBUGASSERT(dev != NULL);
+
+  switch (stage)
+  {
+    case ESP32S2_WDT_STAGE0:
+      {
+        if (IS_RWDT(dev))
+          {
+            /* The timeout of only stage 0 happens at:
+             * Thold0 = RTC_CNTL_WDT_STG0_HOLD << (EFUSE_WDT_DELAY_SEL + 1)
+             */
+
+            uint32_t delay;
+            delay = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG,
+                                  EFUSE_WDT_DELAY_SEL);
+            value = value >> (delay + 1);
+            wdt_putreg(dev, RWDT_STAGE0_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE0_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE1:
+      {
+        if (IS_RWDT(dev))
+          {
+            wdt_putreg(dev, RWDT_STAGE1_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE1_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE2:
+      {
+        if (IS_RWDT(dev))
+          {
+            wdt_putreg(dev, RWDT_STAGE2_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE2_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    case ESP32S2_WDT_STAGE3:
+      {
+        if (IS_RWDT(dev))
+          {
+            wdt_putreg(dev, RWDT_STAGE3_TIMEOUT_OFFSET, value);
+          }
+        else
+          {
+            wdt_putreg(dev, MWDT_STAGE3_TIMEOUT_OFFSET, value);
+          }
+        break;
+      }
+
+    default:
+      {
+        wderr("ERROR: unsupported stage %d\n", stage);
+        ret = -EINVAL;
+        goto errout;
+      }
+  }
+
+  errout:
+    return ret;
+}
+
+/****************************************************************************
+ * Name: wdt_feed
+ *
+ * Description:
+ *   Feed the watchdog.
+ *   The watchdog timer returns to stage 0 and its counter restarts from 0.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_feed(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_FEED_OFFSET, 0, RTC_CNTL_WDT_FEED);
+    }
+  else
+    {
+      wdt_putreg(dev, MWDT_FEED_OFFSET, TIMG_WDT_FEED);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_setisr
+ *
+ * Description:
+ *   Allocate a Level CPU Interrupt, connect the peripheral source to this
+ *   Interrupt, register the callback and enable the interrupt.
+ *   In case a NULL handler is provided, deallocate the interrupt and
+ *   unregister the previously provided handler.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *   handler       - Callback to be invoked on watchdog timer interrupt.
+ *   arg           - Argument to be passed to the handler callback.
+ *
+ * Returned Values:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev, xcpt_t handler,
+                          void *arg)
+{
+  struct esp32s2_wdt_priv_s *wdt = NULL;
+  int32_t ret = OK;
+
+  DEBUGASSERT(dev != NULL);
+
+  wdt = (struct esp32s2_wdt_priv_s *)dev;
+
+  /* Disable interrupt when callback is removed. */
+
+  if (handler == NULL)
+    {
+      /* If a CPU Interrupt was previously allocated, then deallocate it */
+
+      if (wdt->cpuint >= 0)
+        {
+          /* Disable CPU Interrupt, free a previously allocated
+           * CPU Interrupt
+           */
+
+          up_disable_irq(wdt->irq);
+          esp32s2_teardown_irq(wdt->periph, wdt->cpuint);
+          irq_detach(wdt->irq);
+        }
+
+      ret = OK;
+      goto errout;
+    }
+
+  /* Otherwise set callback and enable interrupt. */
+
+  else
+    {
+      /* Set up to receive peripheral interrupts on the current CPU */
+
+      wdt->cpuint = esp32s2_setup_irq(wdt->periph, 1, ESP32S2_CPUINT_LEVEL);
+      if (wdt->cpuint < 0)
+        {
+          wderr("ERROR: No CPU Interrupt available");
+          ret = wdt->cpuint;
+          goto errout;
+        }
+
+      /* Associate an IRQ Number (from the WDT) to an ISR */
+
+      ret = irq_attach(wdt->irq, handler, arg);
+
+      if (ret != OK)
+        {
+          esp32s2_teardown_irq(wdt->periph, wdt->cpuint);
+          wderr("ERROR: Failed to associate an IRQ Number");
+          goto errout;
+        }
+
+      /* Enable the CPU Interrupt that is linked to the WDT */
+
+      up_enable_irq(wdt->irq);
+    }
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: wdt_enableint
+ *
+ * Description:
+ *   Enable a Level Interrupt at timeout.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_enableint(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, 0, RTC_CNTL_WDT_INT_ENA);
+    }
+  else
+    {
+      wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, 0, TIMG_WDT_INT_ENA);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_disableint
+ *
+ * Description:
+ *   Disable a Level Interrupt at timeout.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_disableint(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, RTC_CNTL_WDT_INT_ENA, 0);
+    }
+  else
+    {
+      wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, TIMG_WDT_INT_ENA, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: wdt_ackint
+ *
+ *   Description:
+ *   Acknowledge an interrupt.
+ *
+ * Parameters:
+ *   dev           - Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+static void wdt_ackint(struct esp32s2_wdt_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (IS_RWDT(dev))
+    {
+      wdt_putreg(dev, RWDT_INT_CLR_REG_OFFSET, RTC_CNTL_WDT_INT_CLR);
+    }
+  else
+    {
+      wdt_putreg(dev, MWDT_INT_CLR_REG_OFFSET, TIMG_WDT_INT_CLR);
+    }
+}
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: esp32s2_wdt_init
+ *
+ * Description:
+ *   Initialize WDT device.
+ *
+ * Parameters:
+ *   wdt_id           - A Watchdog Timer instance to be initialized.
+ *
+ * Return Values:
+ *   Pointer to the driver state structure.
+ *
+ ****************************************************************************/
+
+struct esp32s2_wdt_dev_s *esp32s2_wdt_init(enum esp32s2_wdt_inst_e wdt_id)
+{
+  struct esp32s2_wdt_priv_s *wdt = NULL;
+
+  /* Get WDT instance */
+
+  switch (wdt_id)
+    {
+#ifdef CONFIG_ESP32S2_MWDT0
+      case ESP32S2_WDT_MWDT0:
+        {
+          wdt = &g_esp32s2_mwdt0_priv;
+          break;
+        }
+
+#endif
+
+#ifdef CONFIG_ESP32S2_MWDT1
+      case ESP32S2_WDT_MWDT1:
+        {
+          wdt = &g_esp32s2_mwdt1_priv;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_ESP32S2_RWDT
+      case ESP32S2_WDT_RWDT:
+        {
+          wdt = &g_esp32s2_rwdt_priv;
+          break;
+        }
+
+#endif
+
+      default:
+        {
+          wderr("ERROR: unsupported WDT %d\n", wdt_id);
+          goto errout;
+        }
+    }
+
+  /* If some code is using it then sends an error message,
+   * Otherwise, inform it has been used.
+   */
+
+  if (wdt->inuse == true)

Review comment:
       ```suggestion
     if (wdt->inuse)
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to