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 */
