From 1031cfd51e06b7e1cadbfaeb8de44e952ebbadcf Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Tue, 21 Sep 2021 10:49:25 +0200 Subject: [PATCH] drivers: serial: ns16550: fill full fifo Put the maximum number of bytes into Tx FIFO in the fill_fifo routine to reduce CPU usage. Previously, the THRE bit was checked in a loop, but, according to doc - "In the FIFO mode, it is set when the XMIT FIFO is empty, and is cleared when at least one byte is written to XMIT FIFO.", so only one byte was transferred every interrupt. That was generating a big amount of interrupts, which consumes CPU time. Signed-off-by: Dawid Niedzwiecki --- drivers/serial/uart_ns16550.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 484ed60b3a4..707a0adbf20 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -87,6 +87,7 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define IIR_LS 0x06 /* receiver line status interrupt */ #define IIR_MASK 0x07 /* interrupt id bits mask */ #define IIR_ID 0x06 /* interrupt ID mask without NIP */ +#define IIR_FE 0xC0 /* FIFO mode enabled */ /* equates for FIFO control register */ @@ -262,6 +263,7 @@ struct uart_ns16550_dev_data { #endif struct uart_config uart_config; struct k_spinlock lock; + uint8_t fifo_size; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uint8_t iir_cache; /**< cache of IIR since it clears when read */ @@ -464,6 +466,16 @@ static int uart_ns16550_configure(const struct device *dev, #endif ); + if ((INBYTE(IIR(dev)) & IIR_FE) == IIR_FE) { +#ifdef CONFIG_UART_NS16750 + dev_data->fifo_size = 64; +#else + dev_data->fifo_size = 16; +#endif + } else { + dev_data->fifo_size = 1; + } + /* clear the port */ INBYTE(RDR(dev)); @@ -601,7 +613,7 @@ static int uart_ns16550_fifo_fill(const struct device *dev, int i; k_spinlock_key_t key = k_spin_lock(&DEV_DATA(dev)->lock); - for (i = 0; (i < size) && (INBYTE(LSR(dev)) & LSR_THRE) != 0; i++) { + for (i = 0; (i < size) && (i < DEV_DATA(dev)->fifo_size); i++) { OUTBYTE(THR(dev), tx_data[i]); }