This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit e5f385532e00fe6fb6ac29ea3ea0ab30f74eba14
Author: Brijesh Thakkar <[email protected]>
AuthorDate: Tue Oct 20 18:10:26 2026 +0530

    drivers/serial/uart_16550: Add optional attach/detach ops
    
    u16550_attach() and u16550_detach() always call irq_attach() and
    up_enable_irq() (or up_disable_irq() and irqchain_detach()) for
    priv->irq.  That does not fit a board whose interrupt cannot be
    registered this way, e.g. one that shares the IRQ line with another
    UART or routes it through its own controller.
    
    Add optional attach and detach members to struct u16550_ops_s.  When they
    are NULL the previous behavior is used unchanged, so existing boards and
    the PCI driver are not affected.
    
    Assisted-by: Claude:claude-sonnet-5-5
    Signed-off-by: Brijesh Thakkar <[email protected]>
---
 drivers/serial/uart_16550.c       | 42 ++++++++++++++++++++++++++-------------
 include/nuttx/serial/uart_16550.h |  9 +++++++++
 2 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/drivers/serial/uart_16550.c b/drivers/serial/uart_16550.c
index a6a4a61832c..81309a84117 100644
--- a/drivers/serial/uart_16550.c
+++ b/drivers/serial/uart_16550.c
@@ -983,23 +983,30 @@ static int u16550_attach(struct uart_dev_s *dev)
 
   /* Attach and enable the IRQ */
 
-  ret = irq_attach(priv->irq, priv->ops->isr, dev);
-#ifndef CONFIG_ARCH_NOINTC
-  if (ret == OK)
+  if (priv->ops->attach != NULL)
     {
-      /* Enable the interrupt (RX and TX interrupts are still disabled
-       * in the UART
-       */
-
-      up_enable_irq(priv->irq);
-
-#ifdef HAVE_16550_UART_DMA
-      if (priv->chanrx)
+      ret = priv->ops->attach(priv, dev);
+    }
+  else
+    {
+      ret = irq_attach(priv->irq, priv->ops->isr, dev);
+#ifndef CONFIG_ARCH_NOINTC
+      if (ret == OK)
         {
-          DMA_RESUME(priv->chanrx);
+          /* Enable the interrupt (RX and TX interrupts are still disabled
+           * in the UART
+           */
+
+          up_enable_irq(priv->irq);
         }
 #endif
     }
+
+#ifdef HAVE_16550_UART_DMA
+  if (ret == OK && priv->chanrx)
+    {
+      DMA_RESUME(priv->chanrx);
+    }
 #endif
 
   return ret;
@@ -1026,8 +1033,15 @@ static void u16550_detach(FAR struct uart_dev_s *dev)
     }
 #endif
 
-  up_disable_irq(priv->irq);
-  irqchain_detach(priv->irq, priv->ops->isr, dev);
+  if (priv->ops->detach != NULL)
+    {
+      priv->ops->detach(priv, dev);
+    }
+  else
+    {
+      up_disable_irq(priv->irq);
+      irqchain_detach(priv->irq, priv->ops->isr, dev);
+    }
 
 #ifdef CONFIG_CLK
   /* Clk disaable */
diff --git a/include/nuttx/serial/uart_16550.h 
b/include/nuttx/serial/uart_16550.h
index f88d0c75102..6367e694113 100644
--- a/include/nuttx/serial/uart_16550.h
+++ b/include/nuttx/serial/uart_16550.h
@@ -335,6 +335,15 @@ struct u16550_ops_s
   CODE int (*ioctl)(FAR struct u16550_s *priv, int cmd, unsigned long arg);
   CODE FAR struct dma_chan_s *(*dmachan)(FAR struct u16550_s *priv,
                                          unsigned int ident);
+
+  /* Optional interrupt registration hooks.  If attach is NULL the driver
+   * calls irq_attach() with the isr above and up_enable_irq().  If detach
+   * is NULL it calls up_disable_irq() and irqchain_detach().  RX and TX
+   * interrupts are not enabled in the UART by either hook.
+   */
+
+  CODE int (*attach)(FAR struct u16550_s *priv, FAR uart_dev_t *dev);
+  CODE void (*detach)(FAR struct u16550_s *priv, FAR uart_dev_t *dev);
 };
 
 /* UART 16550 private data */

Reply via email to