tty: xuartps: Consolidate TX handling
start_tx and the ISR used largely identical code to transmit data. Consolidate that in one place. Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
a8df6a5160
commit
07986580d0
@@ -239,6 +239,41 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus)
|
|||||||
tty_flip_buffer_push(&port->state->port);
|
tty_flip_buffer_push(&port->state->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cdns_uart_handle_tx(struct uart_port *port)
|
||||||
|
{
|
||||||
|
unsigned int numbytes;
|
||||||
|
|
||||||
|
if (uart_circ_empty(&port->state->xmit)) {
|
||||||
|
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
numbytes = port->fifosize;
|
||||||
|
while (numbytes && !uart_circ_empty(&port->state->xmit) &&
|
||||||
|
!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) {
|
||||||
|
/*
|
||||||
|
* Get the data from the UART circular buffer
|
||||||
|
* and write it to the cdns_uart's TX_FIFO
|
||||||
|
* register.
|
||||||
|
*/
|
||||||
|
writel(port->state->xmit.buf[port->state->xmit.tail],
|
||||||
|
port->membase + CDNS_UART_FIFO);
|
||||||
|
port->icount.tx++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust the tail of the UART buffer and wrap
|
||||||
|
* the buffer if it reaches limit.
|
||||||
|
*/
|
||||||
|
port->state->xmit.tail =
|
||||||
|
(port->state->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
|
|
||||||
|
numbytes--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS)
|
||||||
|
uart_write_wakeup(port);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cdns_uart_isr - Interrupt handler
|
* cdns_uart_isr - Interrupt handler
|
||||||
* @irq: Irq number
|
* @irq: Irq number
|
||||||
@@ -250,7 +285,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
|
|||||||
{
|
{
|
||||||
struct uart_port *port = (struct uart_port *)dev_id;
|
struct uart_port *port = (struct uart_port *)dev_id;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int isrstatus, numbytes;
|
unsigned int isrstatus;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
@@ -262,40 +297,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
|
|||||||
if (isrstatus & CDNS_UART_RX_IRQS)
|
if (isrstatus & CDNS_UART_RX_IRQS)
|
||||||
cdns_uart_handle_rx(port, isrstatus);
|
cdns_uart_handle_rx(port, isrstatus);
|
||||||
|
|
||||||
/* Dispatch an appropriate handler */
|
if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY)
|
||||||
if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) {
|
cdns_uart_handle_tx(port);
|
||||||
if (uart_circ_empty(&port->state->xmit)) {
|
|
||||||
writel(CDNS_UART_IXR_TXEMPTY,
|
|
||||||
port->membase + CDNS_UART_IDR);
|
|
||||||
} else {
|
|
||||||
numbytes = port->fifosize;
|
|
||||||
/* Break if no more data available in the UART buffer */
|
|
||||||
while (numbytes--) {
|
|
||||||
if (uart_circ_empty(&port->state->xmit))
|
|
||||||
break;
|
|
||||||
/* Get the data from the UART circular buffer
|
|
||||||
* and write it to the cdns_uart's TX_FIFO
|
|
||||||
* register.
|
|
||||||
*/
|
|
||||||
writel(port->state->xmit.buf[
|
|
||||||
port->state->xmit.tail],
|
|
||||||
port->membase + CDNS_UART_FIFO);
|
|
||||||
|
|
||||||
port->icount.tx++;
|
|
||||||
|
|
||||||
/* Adjust the tail of the UART buffer and wrap
|
|
||||||
* the buffer if it reaches limit.
|
|
||||||
*/
|
|
||||||
port->state->xmit.tail =
|
|
||||||
(port->state->xmit.tail + 1) &
|
|
||||||
(UART_XMIT_SIZE - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uart_circ_chars_pending(
|
|
||||||
&port->state->xmit) < WAKEUP_CHARS)
|
|
||||||
uart_write_wakeup(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writel(isrstatus, port->membase + CDNS_UART_ISR);
|
writel(isrstatus, port->membase + CDNS_UART_ISR);
|
||||||
|
|
||||||
@@ -502,7 +505,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
|
|||||||
*/
|
*/
|
||||||
static void cdns_uart_start_tx(struct uart_port *port)
|
static void cdns_uart_start_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
unsigned int status, numbytes = port->fifosize;
|
unsigned int status;
|
||||||
|
|
||||||
if (uart_tx_stopped(port))
|
if (uart_tx_stopped(port))
|
||||||
return;
|
return;
|
||||||
@@ -519,31 +522,11 @@ static void cdns_uart_start_tx(struct uart_port *port)
|
|||||||
if (uart_circ_empty(&port->state->xmit))
|
if (uart_circ_empty(&port->state->xmit))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (numbytes-- && ((readl(port->membase + CDNS_UART_SR) &
|
cdns_uart_handle_tx(port);
|
||||||
CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) {
|
|
||||||
/* Break if no more data available in the UART buffer */
|
|
||||||
if (uart_circ_empty(&port->state->xmit))
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Get the data from the UART circular buffer and
|
|
||||||
* write it to the cdns_uart's TX_FIFO register.
|
|
||||||
*/
|
|
||||||
writel(port->state->xmit.buf[port->state->xmit.tail],
|
|
||||||
port->membase + CDNS_UART_FIFO);
|
|
||||||
port->icount.tx++;
|
|
||||||
|
|
||||||
/* Adjust the tail of the UART buffer and wrap
|
|
||||||
* the buffer if it reaches limit.
|
|
||||||
*/
|
|
||||||
port->state->xmit.tail = (port->state->xmit.tail + 1) &
|
|
||||||
(UART_XMIT_SIZE - 1);
|
|
||||||
}
|
|
||||||
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR);
|
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR);
|
||||||
/* Enable the TX Empty interrupt */
|
/* Enable the TX Empty interrupt */
|
||||||
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER);
|
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER);
|
||||||
|
|
||||||
if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS)
|
|
||||||
uart_write_wakeup(port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user