drivers/serial/xlnxps: add polling mode support for serial drivers

Adds CONFIG_UART_XLNXPS_POLLING options to enable polling mode for
transmission. This avoids TX interrupts and reduces interrupt latency
at the cost of blocking during TX.

Implements sendbuf() method for efficient buffer transmission
in polling mode.

Signed-off-by: yinshengkai <yinshengkai@bytedance.com>
Signed-off-by: chao an <anchao.archer@bytedance.com>
This commit is contained in:
yinshengkai
2026-02-26 16:31:50 +08:00
committed by Alan C. Assis
parent cfd1771981
commit 8c035a2414
2 changed files with 43 additions and 4 deletions
+8
View File
@@ -5,6 +5,14 @@
if UART_XLNXPS
config UART_XLNXPS_POLLING
bool "Force polling mode for TX"
default n
---help---
Force using polling mode for transmission. This avoids using TX interrupts
and potentially reduces interrupt latency, at the cost of blocking execution
during transmission.
config XLNXPS_SERIAL_DISABLE_REORDERING
bool "Disable reordering of ttySx devices."
default n
+35 -4
View File
@@ -413,6 +413,8 @@ struct xlnxps_port_s
static void xlnxps_rxint(struct uart_dev_s *dev, bool enable);
static void xlnxps_txint(struct uart_dev_s *dev, bool enable);
static bool xlnxps_txready(struct uart_dev_s *dev);
static void xlnxps_wait_send(struct uart_dev_s *dev, int ch);
/***************************************************************************
* Private Functions
@@ -982,6 +984,26 @@ static void xlnxps_send(struct uart_dev_s *dev, int ch)
putreg8(ch, config->uart + XUARTPS_FIFO_OFFSET);
}
/***************************************************************************
* Name: xlnxps_sendbuf
*
* Description:
* This method will send a buffer of bytes on the UART
*
***************************************************************************/
static ssize_t xlnxps_sendbuf(struct uart_dev_s *dev,
const void *buffer, size_t size)
{
for (size_t i = 0; i < size; i++)
{
while (!xlnxps_txready(dev));
xlnxps_send(dev, ((const unsigned char *)buffer)[i]);
}
return (ssize_t)size;
}
/***************************************************************************
* Name: xlnxps_txint
*
@@ -1003,33 +1025,41 @@ static void xlnxps_txint(struct uart_dev_s *dev, bool enable)
struct xlnxps_config *config = &port->config;
irqstate_t flags;
flags = enter_critical_section();
/* Write to Interrupt Enable Register (UART_IER) */
if (enable)
{
#ifdef CONFIG_UART_XLNXPS_POLLING
/* In polling mode, we loop until the buffer is empty */
uart_xmitchars(dev);
#else
flags = enter_critical_section();
/* Set XUARTPS_IXR_TXEMPTY bit (Enable Tx Fifo Empty Interrupt) */
modreg32(XUARTPS_IXR_TXEMPTY, XUARTPS_IXR_TXEMPTY,
config->uart + XUARTPS_IER_OFFSET);
modreg32(0, XUARTPS_IXR_TXEMPTY, config->uart + XUARTPS_IDR_OFFSET);
leave_critical_section(flags);
/* Fake a TX interrupt */
uart_xmitchars(dev);
#endif
}
else
{
flags = enter_critical_section();
/* Clear XUARTPS_IXR_TXEMPTY bit (Disable Tx Fifo Empty Interrupt) */
modreg32(0, XUARTPS_IXR_TXEMPTY, config->uart + XUARTPS_IER_OFFSET);
modreg32(XUARTPS_IXR_TXEMPTY, XUARTPS_IXR_TXEMPTY,
config->uart + XUARTPS_IDR_OFFSET);
leave_critical_section(flags);
}
leave_critical_section(flags);
}
/***************************************************************************
@@ -1124,6 +1154,7 @@ static const struct uart_ops_s g_uart_ops =
.txint = xlnxps_txint,
.txready = xlnxps_txready,
.txempty = xlnxps_txempty,
.sendbuf = xlnxps_sendbuf,
};
#ifdef CONFIG_UART_XLNXPS0