Skip to content

Commit

Permalink
tty: serial: use DEFINE_UART_PORT_TX_HELPER()
Browse files Browse the repository at this point in the history
DEFINE_UART_PORT_TX_HELPER() is a new helper to send characters to the
device. Use it in these drivers.

Cc: Tobias Klauser <tklauser@distanz.ch>
Cc: Richard Genoud <richard.genoud@gmail.com>
Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Claudiu Beznea <claudiu.beznea@microchip.com>
Cc: Vladimir Zapolskiy <vz@mleia.com>
Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Pengutronix Kernel Team <kernel@pengutronix.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: NXP Linux Team <linux-imx@nxp.com>
Cc: "Andreas Färber" <afaerber@suse.de>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
  • Loading branch information
Jiri Slaby authored and intel-lab-lkp committed Sep 1, 2022
1 parent 91bbd7c commit 393b592
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 353 deletions.
37 changes: 5 additions & 32 deletions drivers/tty/serial/altera_uart.c
Expand Up @@ -246,37 +246,10 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
tty_flip_buffer_push(&port->state->port);
}

static void altera_uart_tx_chars(struct altera_uart *pp)
{
struct uart_port *port = &pp->port;
struct circ_buf *xmit = &port->state->xmit;

if (port->x_char) {
/* Send special char - probably flow control */
altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG);
port->x_char = 0;
port->icount.tx++;
return;
}

while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK) {
if (xmit->head == xmit->tail)
break;
altera_uart_writel(port, xmit->buf[xmit->tail],
ALTERA_UART_TXDATA_REG);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);

if (xmit->head == xmit->tail) {
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
altera_uart_update_ctrl_reg(pp);
}
}
static DEFINE_UART_PORT_TX_HELPER(altera_uart_tx_chars, port, ch,
altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK,
altera_uart_writel(port, ch, ALTERA_UART_TXDATA_REG));

static irqreturn_t altera_uart_interrupt(int irq, void *data)
{
Expand All @@ -290,7 +263,7 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data)
if (isr & ALTERA_UART_STATUS_RRDY_MSK)
altera_uart_rx_chars(pp);
if (isr & ALTERA_UART_STATUS_TRDY_MSK)
altera_uart_tx_chars(pp);
altera_uart_tx_chars(&pp->port);
spin_unlock(&port->lock);

return IRQ_RETVAL(isr);
Expand Down
29 changes: 7 additions & 22 deletions drivers/tty/serial/atmel_serial.c
Expand Up @@ -812,36 +812,21 @@ static void atmel_rx_chars(struct uart_port *port)
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
}

static DEFINE_UART_PORT_TX_HELPER(atmel_do_tx_chars, port, ch,
atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY,
atmel_uart_write_char(port, ch));

/*
* Transmit characters (called from tasklet with TXRDY interrupt
* disabled)
*/
static void atmel_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int pending;

if (port->x_char &&
(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY)) {
atmel_uart_write_char(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return;

while (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY) {
atmel_uart_write_char(port, xmit->buf[xmit->tail]);
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)) {
pending = atmel_do_tx_chars(port);
if (pending) {
/* we still have characters to transmit, so we should continue
* transmitting them when TX is ready, regardless of
* mode or duplexity
Expand Down
38 changes: 10 additions & 28 deletions drivers/tty/serial/fsl_lpuart.c
Expand Up @@ -740,36 +740,18 @@ static int lpuart32_poll_get_char(struct uart_port *port)
}
#endif

static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
static bool lpuart_tx_ready(struct uart_port *port)
{
struct circ_buf *xmit = &sport->port.state->xmit;

if (sport->port.x_char) {
writeb(sport->port.x_char, sport->port.membase + UARTDR);
sport->port.icount.tx++;
sport->port.x_char = 0;
return;
}

if (lpuart_stopped_or_empty(&sport->port)) {
lpuart_stop_tx(&sport->port);
return;
}

while (!uart_circ_empty(xmit) &&
(readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size)) {
writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
sport->port.icount.tx++;
}
struct lpuart_port *sport = container_of(port, struct lpuart_port,
port);

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port);

if (uart_circ_empty(xmit))
lpuart_stop_tx(&sport->port);
return readb(port->membase + UARTTCFIFO) < sport->txfifo_size;
}

static DEFINE_UART_PORT_TX_HELPER(lpuart_transmit_buffer, port, ch,
lpuart_tx_ready(port),
writeb(ch, port->membase + UARTDR));

static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
{
struct circ_buf *xmit = &sport->port.state->xmit;
Expand Down Expand Up @@ -820,7 +802,7 @@ static void lpuart_start_tx(struct uart_port *port)
lpuart_dma_tx(sport);
} else {
if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
lpuart_transmit_buffer(sport);
lpuart_transmit_buffer(&sport->port);
}
}

Expand Down Expand Up @@ -877,7 +859,7 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
static void lpuart_txint(struct lpuart_port *sport)
{
spin_lock(&sport->port.lock);
lpuart_transmit_buffer(sport);
lpuart_transmit_buffer(&sport->port);
spin_unlock(&sport->port.lock);
}

Expand Down
44 changes: 12 additions & 32 deletions drivers/tty/serial/lantiq.c
Expand Up @@ -95,7 +95,6 @@
#define ASCFSTAT_TXFREEMASK 0x3F000000
#define ASCFSTAT_TXFREEOFF 24

static void lqasc_tx_chars(struct uart_port *port);
static struct ltq_uart_port *lqasc_port[MAXPORTS];
static struct uart_driver lqasc_reg;

Expand Down Expand Up @@ -139,6 +138,18 @@ lqasc_stop_tx(struct uart_port *port)
return;
}

static bool
lqasc_tx_ready(struct uart_port *port)
{
u32 fstat = __raw_readl(port->membase + LTQ_ASC_FSTAT);

return (fstat & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
}

static DEFINE_UART_PORT_TX_HELPER(lqasc_tx_chars, port, ch,
lqasc_tx_ready(port),
writeb(ch, port->membase + LTQ_ASC_TBUF));

static void
lqasc_start_tx(struct uart_port *port)
{
Expand Down Expand Up @@ -219,37 +230,6 @@ lqasc_rx_chars(struct uart_port *port)
return 0;
}

static void
lqasc_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
if (uart_tx_stopped(port)) {
lqasc_stop_tx(port);
return;
}

while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) &
ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
if (port->x_char) {
writeb(port->x_char, port->membase + LTQ_ASC_TBUF);
port->icount.tx++;
port->x_char = 0;
continue;
}

if (uart_circ_empty(xmit))
break;

writeb(port->state->xmit.buf[port->state->xmit.tail],
port->membase + LTQ_ASC_TBUF);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
}

static irqreturn_t
lqasc_tx_int(int irq, void *_port)
{
Expand Down
38 changes: 7 additions & 31 deletions drivers/tty/serial/lpc32xx_hs.c
Expand Up @@ -276,41 +276,17 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
tty_flip_buffer_push(tport);
}

static void serial_lpc32xx_stop_tx(struct uart_port *port);

static void __serial_lpc32xx_tx(struct uart_port *port)
static bool serial_lpc32xx_tx_ready(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
u32 level = readl(LPC32XX_HSUART_LEVEL(port->membase));

if (port->x_char) {
writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase));
port->icount.tx++;
port->x_char = 0;
return;
}

if (uart_circ_empty(xmit) || uart_tx_stopped(port))
goto exit_tx;

/* Transfer data */
while (LPC32XX_HSU_TX_LEV(readl(
LPC32XX_HSUART_LEVEL(port->membase))) < 64) {
writel((u32) xmit->buf[xmit->tail],
LPC32XX_HSUART_FIFO(port->membase));
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);

exit_tx:
if (uart_circ_empty(xmit))
serial_lpc32xx_stop_tx(port);
return LPC32XX_HSU_TX_LEV(level) < 64;
}

static DEFINE_UART_PORT_TX_HELPER(__serial_lpc32xx_tx, port, ch,
serial_lpc32xx_tx_ready(port),
writel(ch, LPC32XX_HSUART_FIFO(port->membase)));

static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
Expand Down
27 changes: 5 additions & 22 deletions drivers/tty/serial/mcf.c
Expand Up @@ -324,32 +324,15 @@ static void mcf_rx_chars(struct mcf_uart *pp)

/****************************************************************************/

static DEFINE_UART_PORT_TX_HELPER(mcf_do_tx_chars, port, ch,
readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY,
writeb(ch, port->membase + MCFUART_UTB));

static void mcf_tx_chars(struct mcf_uart *pp)
{
struct uart_port *port = &pp->port;
struct circ_buf *xmit = &port->state->xmit;

if (port->x_char) {
/* Send special char - probably flow control */
writeb(port->x_char, port->membase + MCFUART_UTB);
port->x_char = 0;
port->icount.tx++;
return;
}

while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) {
if (uart_circ_empty(xmit))
break;
writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
port->icount.tx++;
}

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);

if (uart_circ_empty(xmit)) {
mcf_stop_tx(port);
if (!mcf_do_tx_chars(port)) {
/* Disable TX to negate RTS automatically */
if (port->rs485.flags & SER_RS485_ENABLED)
writeb(MCFUART_UCR_TXDISABLE,
Expand Down
44 changes: 3 additions & 41 deletions drivers/tty/serial/mpc52xx_uart.c
Expand Up @@ -1338,7 +1338,6 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
return 0;
}


static const struct uart_ops mpc52xx_uart_ops = {
.tx_empty = mpc52xx_uart_tx_empty,
.set_mctrl = mpc52xx_uart_set_mctrl,
Expand Down Expand Up @@ -1425,46 +1424,9 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
return psc_ops->raw_rx_rdy(port);
}

static inline int
mpc52xx_uart_int_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;

/* Process out of band chars */
if (port->x_char) {
psc_ops->write_char(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
return 1;
}

/* Nothing to do ? */
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
mpc52xx_uart_stop_tx(port);
return 0;
}

/* Send chars */
while (psc_ops->raw_tx_rdy(port)) {
psc_ops->write_char(port, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
}

/* Wake up */
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);

/* Maybe we're done after all */
if (uart_circ_empty(xmit)) {
mpc52xx_uart_stop_tx(port);
return 0;
}

return 1;
}
static DEFINE_UART_PORT_TX_HELPER(mpc52xx_uart_int_tx_chars, port, ch,
psc_ops->raw_tx_rdy(port),
psc_ops->write_char(port, ch));

static irqreturn_t
mpc5xxx_uart_process_int(struct uart_port *port)
Expand Down

0 comments on commit 393b592

Please sign in to comment.