summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/fsl_linflexuart.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/fsl_linflexuart.c')
-rw-r--r--drivers/tty/serial/fsl_linflexuart.c134
1 files changed, 57 insertions, 77 deletions
diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c
index 3e28be402aef..e70a56de1fce 100644
--- a/drivers/tty/serial/fsl_linflexuart.c
+++ b/drivers/tty/serial/fsl_linflexuart.c
@@ -11,7 +11,7 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
#include <linux/tty_flip.h>
@@ -157,33 +157,35 @@ static void linflex_stop_rx(struct uart_port *port)
writel(ier & ~LINFLEXD_LINIER_DRIE, port->membase + LINIER);
}
-static inline void linflex_transmit_buffer(struct uart_port *sport)
+static void linflex_put_char(struct uart_port *sport, unsigned char c)
{
- struct circ_buf *xmit = &sport->state->xmit;
- unsigned char c;
unsigned long status;
- while (!uart_circ_empty(xmit)) {
- c = xmit->buf[xmit->tail];
- writeb(c, sport->membase + BDRL);
+ writeb(c, sport->membase + BDRL);
- /* Waiting for data transmission completed. */
- while (((status = readl(sport->membase + UARTSR)) &
- LINFLEXD_UARTSR_DTFTFF) !=
- LINFLEXD_UARTSR_DTFTFF)
- ;
+ /* Waiting for data transmission completed. */
+ while (((status = readl(sport->membase + UARTSR)) &
+ LINFLEXD_UARTSR_DTFTFF) !=
+ LINFLEXD_UARTSR_DTFTFF)
+ ;
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- sport->icount.tx++;
+ writel(status | LINFLEXD_UARTSR_DTFTFF, sport->membase + UARTSR);
+}
+
+static inline void linflex_transmit_buffer(struct uart_port *sport)
+{
+ struct tty_port *tport = &sport->state->port;
+ unsigned char c;
- writel(status | LINFLEXD_UARTSR_DTFTFF,
- sport->membase + UARTSR);
+ while (uart_fifo_get(sport, &c)) {
+ linflex_put_char(sport, c);
+ sport->icount.tx++;
}
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(sport);
- if (uart_circ_empty(xmit))
+ if (kfifo_is_empty(&tport->xmit_fifo))
linflex_stop_tx(sport);
}
@@ -199,38 +201,24 @@ static void linflex_start_tx(struct uart_port *port)
static irqreturn_t linflex_txint(int irq, void *dev_id)
{
struct uart_port *sport = dev_id;
- struct circ_buf *xmit = &sport->state->xmit;
+ struct tty_port *tport = &sport->state->port;
unsigned long flags;
- unsigned long status;
- spin_lock_irqsave(&sport->lock, flags);
+ uart_port_lock_irqsave(sport, &flags);
if (sport->x_char) {
- writeb(sport->x_char, sport->membase + BDRL);
-
- /* waiting for data transmission completed */
- while (((status = readl(sport->membase + UARTSR)) &
- LINFLEXD_UARTSR_DTFTFF) != LINFLEXD_UARTSR_DTFTFF)
- ;
-
- writel(status | LINFLEXD_UARTSR_DTFTFF,
- sport->membase + UARTSR);
-
+ linflex_put_char(sport, sport->x_char);
goto out;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(sport)) {
+ if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(sport)) {
linflex_stop_tx(sport);
goto out;
}
linflex_transmit_buffer(sport);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(sport);
-
out:
- spin_unlock_irqrestore(&sport->lock, flags);
+ uart_port_unlock_irqrestore(sport, flags);
return IRQ_HANDLED;
}
@@ -243,7 +231,7 @@ static irqreturn_t linflex_rxint(int irq, void *dev_id)
unsigned char rx;
bool brk;
- spin_lock_irqsave(&sport->lock, flags);
+ uart_port_lock_irqsave(sport, &flags);
status = readl(sport->membase + UARTSR);
while (status & LINFLEXD_UARTSR_RMB) {
@@ -252,23 +240,22 @@ static irqreturn_t linflex_rxint(int irq, void *dev_id)
flg = TTY_NORMAL;
sport->icount.rx++;
- if (status & (LINFLEXD_UARTSR_BOF | LINFLEXD_UARTSR_SZF |
- LINFLEXD_UARTSR_FEF | LINFLEXD_UARTSR_PE)) {
- if (status & LINFLEXD_UARTSR_SZF)
- status |= LINFLEXD_UARTSR_SZF;
+ if (status & (LINFLEXD_UARTSR_BOF | LINFLEXD_UARTSR_FEF |
+ LINFLEXD_UARTSR_PE)) {
if (status & LINFLEXD_UARTSR_BOF)
- status |= LINFLEXD_UARTSR_BOF;
+ sport->icount.overrun++;
if (status & LINFLEXD_UARTSR_FEF) {
- if (!rx)
+ if (!rx) {
brk = true;
- status |= LINFLEXD_UARTSR_FEF;
+ sport->icount.brk++;
+ } else
+ sport->icount.frame++;
}
if (status & LINFLEXD_UARTSR_PE)
- status |= LINFLEXD_UARTSR_PE;
+ sport->icount.parity++;
}
- writel(status | LINFLEXD_UARTSR_RMB | LINFLEXD_UARTSR_DRFRFE,
- sport->membase + UARTSR);
+ writel(status, sport->membase + UARTSR);
status = readl(sport->membase + UARTSR);
if (brk) {
@@ -280,7 +267,7 @@ static irqreturn_t linflex_rxint(int irq, void *dev_id)
}
}
- spin_unlock_irqrestore(&sport->lock, flags);
+ uart_port_unlock_irqrestore(sport, flags);
tty_flip_buffer_push(port);
@@ -383,11 +370,11 @@ static int linflex_startup(struct uart_port *port)
int ret = 0;
unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
+ uart_port_lock_irqsave(port, &flags);
linflex_setup_watermark(port);
- spin_unlock_irqrestore(&port->lock, flags);
+ uart_port_unlock_irqrestore(port, flags);
ret = devm_request_irq(port->dev, port->irq, linflex_int, 0,
DRIVER_NAME, port);
@@ -400,21 +387,21 @@ static void linflex_shutdown(struct uart_port *port)
unsigned long ier;
unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
+ uart_port_lock_irqsave(port, &flags);
/* disable interrupts */
ier = readl(port->membase + LINIER);
ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);
writel(ier, port->membase + LINIER);
- spin_unlock_irqrestore(&port->lock, flags);
+ uart_port_unlock_irqrestore(port, flags);
devm_free_irq(port->dev, port->irq, port);
}
static void
linflex_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned long cr, old_cr, cr1;
@@ -488,7 +475,7 @@ linflex_set_termios(struct uart_port *port, struct ktermios *termios,
cr &= ~LINFLEXD_UARTCR_PCE;
}
- spin_lock_irqsave(&port->lock, flags);
+ uart_port_lock_irqsave(port, &flags);
port->read_status_mask = 0;
@@ -521,7 +508,7 @@ linflex_set_termios(struct uart_port *port, struct ktermios *termios,
writel(cr1, port->membase + LINCR1);
- spin_unlock_irqrestore(&port->lock, flags);
+ uart_port_unlock_irqrestore(port, flags);
}
static const char *linflex_type(struct uart_port *port)
@@ -566,7 +553,7 @@ static const struct uart_ops linflex_pops = {
static struct uart_port *linflex_ports[UART_NR];
#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE
-static void linflex_console_putchar(struct uart_port *port, int ch)
+static void linflex_console_putchar(struct uart_port *port, unsigned char ch)
{
unsigned long cr;
@@ -591,7 +578,7 @@ static void linflex_console_putchar(struct uart_port *port, int ch)
}
}
-static void linflex_earlycon_putchar(struct uart_port *port, int ch)
+static void linflex_earlycon_putchar(struct uart_port *port, unsigned char ch)
{
unsigned long flags;
char *ret;
@@ -660,14 +647,14 @@ linflex_console_write(struct console *co, const char *s, unsigned int count)
if (sport->sysrq)
locked = 0;
else if (oops_in_progress)
- locked = spin_trylock_irqsave(&sport->lock, flags);
+ locked = uart_port_trylock_irqsave(sport, &flags);
else
- spin_lock_irqsave(&sport->lock, flags);
+ uart_port_lock_irqsave(sport, &flags);
linflex_string_write(sport, s, count);
if (locked)
- spin_unlock_irqrestore(&sport->lock, flags);
+ uart_port_unlock_irqrestore(sport, flags);
}
/*
@@ -841,19 +828,18 @@ static int linflex_probe(struct platform_device *pdev)
sport->line = ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- sport->mapbase = res->start;
- sport->membase = devm_ioremap_resource(&pdev->dev, res);
+ sport->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(sport->membase))
return PTR_ERR(sport->membase);
+ sport->mapbase = res->start;
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
sport->dev = &pdev->dev;
- sport->type = PORT_LINFLEXUART;
sport->iotype = UPIO_MEM;
- sport->irq = platform_get_irq(pdev, 0);
+ sport->irq = ret;
sport->ops = &linflex_pops;
sport->flags = UPF_BOOT_AUTOCONF;
sport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE);
@@ -862,20 +848,14 @@ static int linflex_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sport);
- ret = uart_add_one_port(&linflex_reg, sport);
- if (ret)
- return ret;
-
- return 0;
+ return uart_add_one_port(&linflex_reg, sport);
}
-static int linflex_remove(struct platform_device *pdev)
+static void linflex_remove(struct platform_device *pdev)
{
struct uart_port *sport = platform_get_drvdata(pdev);
uart_remove_one_port(&linflex_reg, sport);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP