diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index ed4ad40f83de..71ace116fe6b 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -139,6 +139,9 @@ static inline bool serial8250_set_THRI(struct uart_8250_port *up) if (up->ier & UART_IER_THRI) return false; up->ier |= UART_IER_THRI; +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + up->ier |= UART_IER_PTIME; +#endif serial_out(up, UART_IER, up->ier); return true; } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index a9c9ee29e791..77594cb4dbbe 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1911,8 +1911,9 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) unsigned char status; unsigned long flags; struct uart_8250_port *up = up_to_u8250p(port); +#ifndef CONFIG_ARCH_ROCKCHIP bool skip_rx = false; - int dma_err = -1; +#endif if (iir & UART_IIR_NO_INT) return 0; @@ -1921,6 +1922,17 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) status = serial_port_in(port, UART_LSR); +#ifdef CONFIG_ARCH_ROCKCHIP + if (status & (UART_LSR_DR | UART_LSR_BI)) { + int dma_err = -1; + + if (up->dma && up->dma->rxchan) + dma_err = handle_rx_dma(up, iir); + + if (!up->dma || dma_err) + status = serial8250_rx_chars(up, status); + } +#else /* * If port is stopped and there are no error conditions in the * FIFO, then don't drain the FIFO, as this may lead to TTY buffer @@ -1934,15 +1946,6 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) !(port->read_status_mask & UART_LSR_DR)) skip_rx = true; -#ifdef CONFIG_ARCH_ROCKCHIP - if (status & (UART_LSR_DR | UART_LSR_BI)) { - if (up->dma && up->dma->rxchan) - dma_err = handle_rx_dma(up, iir); - - if (!up->dma || dma_err) - status = serial8250_rx_chars(up, status); - } -#else if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) { if (!up->dma || handle_rx_dma(up, iir)) status = serial8250_rx_chars(up, status); @@ -1951,7 +1954,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) serial8250_modem_status(up); #ifdef CONFIG_ARCH_ROCKCHIP if ((!up->dma || (up->dma && (!up->dma->txchan || up->dma->tx_err))) && - (status & UART_LSR_THRE)) + ((iir & 0xf) == UART_IIR_THRI)) serial8250_tx_chars(up); #else if ((!up->dma || (up->dma && up->dma->tx_err)) && diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index be07b5470f4b..e5dd5630f8a4 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -30,6 +30,7 @@ * Sleep mode for ST16650 and TI16750. For the ST16650, EFR[4]=1 */ #define UART_IERX_SLEEP 0x10 /* Enable sleep mode */ +#define UART_IER_PTIME 0x80 /* Enable programmable transmit interrupt mode */ #define UART_IIR 2 /* In: Interrupt ID Register */ #define UART_IIR_NO_INT 0x01 /* No interrupts pending */