mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
tty: serial: use uart_port_tx_limited()
uart_port_tx_limited() is a new helper to send characters to the device. Use it in these drivers. mux.c also needs to define tx_done(). But I'm not sure if the driver really wants to wait for all the characters to dismiss from the HW fifo at this code point. Hence I marked this as FIXME. Cc: Russell King <linux@armlinux.org.uk> Cc: Florian Fainelli <f.fainelli@gmail.com> Cc: bcm-kernel-feedback-list@broadcom.com Cc: "Pali Rohár" <pali@kernel.org> Cc: Kevin Cernekee <cernekee@gmail.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Orson Zhai <orsonzhai@gmail.com> Cc: Baolin Wang <baolin.wang7@gmail.com> Cc: Chunyan Zhang <zhang.lyra@gmail.com> Cc: Patrice Chotard <patrice.chotard@foss.st.com> Cc: linux-riscv@lists.infradead.org Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org> Link: https://lore.kernel.org/r/20221004104927.14361-4-jirislaby@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
2d141e683e
commit
d11cc8c3c4
@ -154,35 +154,13 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
|
||||
static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
int count = 256;
|
||||
u8 ch;
|
||||
|
||||
if (port->x_char) {
|
||||
*CSR_UARTDR = port->x_char;
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
goto out;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
serial21285_stop_tx(port);
|
||||
goto out;
|
||||
}
|
||||
uart_port_tx_limited(port, ch, 256,
|
||||
!(*CSR_UARTFLG & 0x20),
|
||||
*CSR_UARTDR = ch,
|
||||
({}));
|
||||
|
||||
do {
|
||||
*CSR_UARTDR = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0 && !(*CSR_UARTFLG & 0x20));
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
serial21285_stop_tx(port);
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -146,37 +146,15 @@ static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
|
||||
static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
|
||||
{
|
||||
struct uart_port *port = &pp->port;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned int pending, count;
|
||||
unsigned int count;
|
||||
u8 ch;
|
||||
|
||||
if (port->x_char) {
|
||||
/* Send special char - probably flow control */
|
||||
writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG);
|
||||
port->x_char = 0;
|
||||
port->icount.tx++;
|
||||
return;
|
||||
}
|
||||
count = altera_jtaguart_tx_space(port, NULL);
|
||||
|
||||
pending = uart_circ_chars_pending(xmit);
|
||||
if (pending > 0) {
|
||||
count = altera_jtaguart_tx_space(port, NULL);
|
||||
if (count > pending)
|
||||
count = pending;
|
||||
if (count > 0) {
|
||||
pending -= count;
|
||||
while (count--) {
|
||||
writel(xmit->buf[xmit->tail],
|
||||
port->membase + ALTERA_JTAGUART_DATA_REG);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
}
|
||||
if (pending < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
}
|
||||
}
|
||||
|
||||
if (pending == 0)
|
||||
altera_jtaguart_stop_tx(port);
|
||||
uart_port_tx_limited(port, ch, count,
|
||||
true,
|
||||
writel(ch, port->membase + ALTERA_JTAGUART_DATA_REG),
|
||||
({}));
|
||||
}
|
||||
|
||||
static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
|
||||
|
@ -164,34 +164,12 @@ static void pl010_rx_chars(struct uart_port *port)
|
||||
|
||||
static void pl010_tx_chars(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
int count;
|
||||
u8 ch;
|
||||
|
||||
if (port->x_char) {
|
||||
writel(port->x_char, port->membase + UART01x_DR);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
pl010_stop_tx(port);
|
||||
return;
|
||||
}
|
||||
|
||||
count = port->fifosize >> 1;
|
||||
do {
|
||||
writel(xmit->buf[xmit->tail], port->membase + UART01x_DR);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
pl010_stop_tx(port);
|
||||
uart_port_tx_limited(port, ch, port->fifosize >> 1,
|
||||
true,
|
||||
writel(ch, port->membase + UART01x_DR),
|
||||
({}));
|
||||
}
|
||||
|
||||
static void pl010_modem_status(struct uart_amba_port *uap)
|
||||
|
@ -122,36 +122,12 @@ static void apbuart_rx_chars(struct uart_port *port)
|
||||
|
||||
static void apbuart_tx_chars(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
int count;
|
||||
u8 ch;
|
||||
|
||||
if (port->x_char) {
|
||||
UART_PUT_CHAR(port, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
apbuart_stop_tx(port);
|
||||
return;
|
||||
}
|
||||
|
||||
/* amba: fill FIFO */
|
||||
count = port->fifosize >> 1;
|
||||
do {
|
||||
UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
apbuart_stop_tx(port);
|
||||
uart_port_tx_limited(port, ch, port->fifosize >> 1,
|
||||
true,
|
||||
UART_PUT_CHAR(port, ch),
|
||||
({}));
|
||||
}
|
||||
|
||||
static irqreturn_t apbuart_int(int irq, void *dev_id)
|
||||
|
@ -303,53 +303,24 @@ static void bcm_uart_do_rx(struct uart_port *port)
|
||||
*/
|
||||
static void bcm_uart_do_tx(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit;
|
||||
unsigned int val, max_count;
|
||||
|
||||
if (port->x_char) {
|
||||
bcm_uart_writel(port, port->x_char, UART_FIFO_REG);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uart_tx_stopped(port)) {
|
||||
bcm_uart_stop_tx(port);
|
||||
return;
|
||||
}
|
||||
|
||||
xmit = &port->state->xmit;
|
||||
if (uart_circ_empty(xmit))
|
||||
goto txq_empty;
|
||||
unsigned int val;
|
||||
bool pending;
|
||||
u8 ch;
|
||||
|
||||
val = bcm_uart_readl(port, UART_MCTL_REG);
|
||||
val = (val & UART_MCTL_TXFIFOFILL_MASK) >> UART_MCTL_TXFIFOFILL_SHIFT;
|
||||
max_count = port->fifosize - val;
|
||||
|
||||
while (max_count--) {
|
||||
unsigned int c;
|
||||
pending = uart_port_tx_limited(port, ch, port->fifosize - val,
|
||||
true,
|
||||
bcm_uart_writel(port, ch, UART_FIFO_REG),
|
||||
({}));
|
||||
if (pending)
|
||||
return;
|
||||
|
||||
c = xmit->buf[xmit->tail];
|
||||
bcm_uart_writel(port, c, UART_FIFO_REG);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
goto txq_empty;
|
||||
return;
|
||||
|
||||
txq_empty:
|
||||
/* nothing to send, disable transmit interrupt */
|
||||
val = bcm_uart_readl(port, UART_IR_REG);
|
||||
val &= ~UART_TX_INT_MASK;
|
||||
bcm_uart_writel(port, val, UART_IR_REG);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -171,6 +171,13 @@ static void mux_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
}
|
||||
|
||||
static void mux_tx_done(struct uart_port *port)
|
||||
{
|
||||
/* FIXME js: really needs to wait? */
|
||||
while (UART_GET_FIFO_CNT(port))
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_write - Write chars to the mux fifo.
|
||||
* @port: Ptr to the uart_port.
|
||||
@ -180,39 +187,13 @@ static void mux_break_ctl(struct uart_port *port, int break_state)
|
||||
*/
|
||||
static void mux_write(struct uart_port *port)
|
||||
{
|
||||
int count;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
u8 ch;
|
||||
|
||||
if(port->x_char) {
|
||||
UART_PUT_CHAR(port, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
mux_stop_tx(port);
|
||||
return;
|
||||
}
|
||||
|
||||
count = (port->fifosize) - UART_GET_FIFO_CNT(port);
|
||||
do {
|
||||
UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if(uart_circ_empty(xmit))
|
||||
break;
|
||||
|
||||
} while(--count > 0);
|
||||
|
||||
while(UART_GET_FIFO_CNT(port))
|
||||
udelay(1);
|
||||
|
||||
if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
mux_stop_tx(port);
|
||||
uart_port_tx_limited(port, ch,
|
||||
port->fifosize - UART_GET_FIFO_CNT(port),
|
||||
true,
|
||||
UART_PUT_CHAR(port, ch),
|
||||
mux_tx_done(port));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -335,40 +335,12 @@ static void mvebu_uart_rx_chars(struct uart_port *port, unsigned int status)
|
||||
|
||||
static void mvebu_uart_tx_chars(struct uart_port *port, unsigned int status)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
unsigned int count;
|
||||
unsigned int st;
|
||||
u8 ch;
|
||||
|
||||
if (port->x_char) {
|
||||
writel(port->x_char, port->membase + UART_TSH(port));
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
mvebu_uart_stop_tx(port);
|
||||
return;
|
||||
}
|
||||
|
||||
for (count = 0; count < port->fifosize; count++) {
|
||||
writel(xmit->buf[xmit->tail], port->membase + UART_TSH(port));
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
|
||||
st = readl(port->membase + UART_STAT);
|
||||
if (st & STAT_TX_FIFO_FUL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
mvebu_uart_stop_tx(port);
|
||||
uart_port_tx_limited(port, ch, port->fifosize,
|
||||
!(readl(port->membase + UART_STAT) & STAT_TX_FIFO_FUL),
|
||||
writel(ch, port->membase + UART_TSH(port)),
|
||||
({}));
|
||||
}
|
||||
|
||||
static irqreturn_t mvebu_uart_isr(int irq, void *dev_id)
|
||||
|
@ -347,34 +347,12 @@ static void serial_omap_put_char(struct uart_omap_port *up, unsigned char ch)
|
||||
|
||||
static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
|
||||
{
|
||||
struct circ_buf *xmit = &up->port.state->xmit;
|
||||
int count;
|
||||
u8 ch;
|
||||
|
||||
if (up->port.x_char) {
|
||||
serial_omap_put_char(up, up->port.x_char);
|
||||
up->port.icount.tx++;
|
||||
up->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
|
||||
serial_omap_stop_tx(&up->port);
|
||||
return;
|
||||
}
|
||||
count = up->port.fifosize / 4;
|
||||
do {
|
||||
serial_omap_put_char(up, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
up->port.icount.tx++;
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&up->port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
serial_omap_stop_tx(&up->port);
|
||||
uart_port_tx_limited(&up->port, ch, up->port.fifosize / 4,
|
||||
true,
|
||||
serial_omap_put_char(up, ch),
|
||||
({}));
|
||||
}
|
||||
|
||||
static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
|
||||
|
@ -174,35 +174,12 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status)
|
||||
|
||||
static void transmit_chars(struct uart_pxa_port *up)
|
||||
{
|
||||
struct circ_buf *xmit = &up->port.state->xmit;
|
||||
int count;
|
||||
u8 ch;
|
||||
|
||||
if (up->port.x_char) {
|
||||
serial_out(up, UART_TX, up->port.x_char);
|
||||
up->port.icount.tx++;
|
||||
up->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
|
||||
serial_pxa_stop_tx(&up->port);
|
||||
return;
|
||||
}
|
||||
|
||||
count = up->port.fifosize / 2;
|
||||
do {
|
||||
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
up->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&up->port);
|
||||
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
serial_pxa_stop_tx(&up->port);
|
||||
uart_port_tx_limited(&up->port, ch, up->port.fifosize / 2,
|
||||
true,
|
||||
serial_out(up, UART_TX, ch),
|
||||
({}));
|
||||
}
|
||||
|
||||
static void serial_pxa_start_tx(struct uart_port *port)
|
||||
|
@ -427,32 +427,13 @@ static void rp2_rx_chars(struct rp2_uart_port *up)
|
||||
|
||||
static void rp2_tx_chars(struct rp2_uart_port *up)
|
||||
{
|
||||
u16 max_tx = FIFO_SIZE - readw(up->base + RP2_TX_FIFO_COUNT);
|
||||
struct circ_buf *xmit = &up->port.state->xmit;
|
||||
u8 ch;
|
||||
|
||||
if (uart_tx_stopped(&up->port)) {
|
||||
rp2_uart_stop_tx(&up->port);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; max_tx != 0; max_tx--) {
|
||||
if (up->port.x_char) {
|
||||
writeb(up->port.x_char, up->base + RP2_DATA_BYTE);
|
||||
up->port.x_char = 0;
|
||||
up->port.icount.tx++;
|
||||
continue;
|
||||
}
|
||||
if (uart_circ_empty(xmit)) {
|
||||
rp2_uart_stop_tx(&up->port);
|
||||
break;
|
||||
}
|
||||
writeb(xmit->buf[xmit->tail], up->base + RP2_DATA_BYTE);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
up->port.icount.tx++;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&up->port);
|
||||
uart_port_tx_limited(&up->port, ch,
|
||||
FIFO_SIZE - readw(up->base + RP2_TX_FIFO_COUNT),
|
||||
true,
|
||||
writeb(ch, up->base + RP2_DATA_BYTE),
|
||||
({}));
|
||||
}
|
||||
|
||||
static void rp2_ch_interrupt(struct rp2_uart_port *up)
|
||||
|
@ -321,34 +321,12 @@ receive_chars(struct uart_port *up, unsigned int *status)
|
||||
|
||||
static inline void transmit_chars(struct uart_port *up)
|
||||
{
|
||||
struct circ_buf *xmit = &up->state->xmit;
|
||||
int count;
|
||||
u8 ch;
|
||||
|
||||
if (up->x_char) {
|
||||
sio_out(up, TXX9_SITFIFO, up->x_char);
|
||||
up->icount.tx++;
|
||||
up->x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
|
||||
serial_txx9_stop_tx(up);
|
||||
return;
|
||||
}
|
||||
|
||||
count = TXX9_SIO_TX_FIFO;
|
||||
do {
|
||||
sio_out(up, TXX9_SITFIFO, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
up->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(up);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
serial_txx9_stop_tx(up);
|
||||
uart_port_tx_limited(up, ch, TXX9_SIO_TX_FIFO,
|
||||
true,
|
||||
sio_out(up, TXX9_SITFIFO, ch),
|
||||
({}));
|
||||
}
|
||||
|
||||
static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
|
||||
|
@ -288,33 +288,12 @@ static void __ssp_transmit_char(struct sifive_serial_port *ssp, int ch)
|
||||
*/
|
||||
static void __ssp_transmit_chars(struct sifive_serial_port *ssp)
|
||||
{
|
||||
struct circ_buf *xmit = &ssp->port.state->xmit;
|
||||
int count;
|
||||
u8 ch;
|
||||
|
||||
if (ssp->port.x_char) {
|
||||
__ssp_transmit_char(ssp, ssp->port.x_char);
|
||||
ssp->port.icount.tx++;
|
||||
ssp->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&ssp->port)) {
|
||||
sifive_serial_stop_tx(&ssp->port);
|
||||
return;
|
||||
}
|
||||
count = SIFIVE_TX_FIFO_DEPTH;
|
||||
do {
|
||||
__ssp_transmit_char(ssp, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
ssp->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&ssp->port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
sifive_serial_stop_tx(&ssp->port);
|
||||
uart_port_tx_limited(&ssp->port, ch, SIFIVE_TX_FIFO_DEPTH,
|
||||
true,
|
||||
__ssp_transmit_char(ssp, ch),
|
||||
({}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -626,35 +626,12 @@ static inline void sprd_rx(struct uart_port *port)
|
||||
|
||||
static inline void sprd_tx(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
int count;
|
||||
u8 ch;
|
||||
|
||||
if (port->x_char) {
|
||||
serial_out(port, SPRD_TXD, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
sprd_stop_tx(port);
|
||||
return;
|
||||
}
|
||||
|
||||
count = THLD_TX_EMPTY;
|
||||
do {
|
||||
serial_out(port, SPRD_TXD, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
sprd_stop_tx(port);
|
||||
uart_port_tx_limited(port, ch, THLD_TX_EMPTY,
|
||||
true,
|
||||
serial_out(port, SPRD_TXD, ch),
|
||||
({}));
|
||||
}
|
||||
|
||||
/* this handles the interrupt from one port */
|
||||
|
@ -237,50 +237,12 @@ static inline unsigned asc_hw_txroom(struct uart_port *port)
|
||||
*/
|
||||
static void asc_transmit_chars(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
int txroom;
|
||||
unsigned char c;
|
||||
u8 ch;
|
||||
|
||||
txroom = asc_hw_txroom(port);
|
||||
|
||||
if ((txroom != 0) && port->x_char) {
|
||||
c = port->x_char;
|
||||
port->x_char = 0;
|
||||
asc_out(port, ASC_TXBUF, c);
|
||||
port->icount.tx++;
|
||||
txroom = asc_hw_txroom(port);
|
||||
}
|
||||
|
||||
if (uart_tx_stopped(port)) {
|
||||
/*
|
||||
* We should try and stop the hardware here, but I
|
||||
* don't think the ASC has any way to do that.
|
||||
*/
|
||||
asc_disable_tx_interrupts(port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit)) {
|
||||
asc_disable_tx_interrupts(port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (txroom == 0)
|
||||
return;
|
||||
|
||||
do {
|
||||
c = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
asc_out(port, ASC_TXBUF, c);
|
||||
port->icount.tx++;
|
||||
txroom--;
|
||||
} while ((txroom > 0) && (!uart_circ_empty(xmit)));
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
asc_disable_tx_interrupts(port);
|
||||
uart_port_tx_limited(port, ch, asc_hw_txroom(port),
|
||||
true,
|
||||
asc_out(port, ASC_TXBUF, ch),
|
||||
({}));
|
||||
}
|
||||
|
||||
static void asc_receive_chars(struct uart_port *port)
|
||||
|
Loading…
Reference in New Issue
Block a user