summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/lantiq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/lantiq.c')
-rw-r--r--drivers/tty/serial/lantiq.c73
1 files changed, 24 insertions, 49 deletions
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 3e324d3f0a6d..62cd9e0bb377 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -8,6 +8,7 @@
* Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/device.h>
@@ -16,7 +17,8 @@
#include <linux/ioport.h>
#include <linux/lantiq.h>
#include <linux/module.h>
-#include <linux/of_platform.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
@@ -93,9 +95,7 @@
#define ASCFSTAT_RXFFLMASK 0x003F
#define ASCFSTAT_TXFFLMASK 0x3F00
#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;
@@ -139,14 +139,24 @@ 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 FIELD_GET(ASCFSTAT_TXFREEMASK, fstat);
+}
+
static void
lqasc_start_tx(struct uart_port *port)
{
unsigned long flags;
struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+ u8 ch;
spin_lock_irqsave(&ltq_port->lock, flags);
- lqasc_tx_chars(port);
+ uart_port_tx(port, ch,
+ lqasc_tx_ready(port),
+ writeb(ch, port->membase + LTQ_ASC_TBUF));
spin_unlock_irqrestore(&ltq_port->lock, flags);
return;
}
@@ -219,37 +229,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)
{
@@ -272,6 +251,7 @@ lqasc_err_int(int irq, void *_port)
struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
spin_lock_irqsave(&ltq_port->lock, flags);
+ __raw_writel(ASC_IRNCR_EIR, port->membase + LTQ_ASC_IRNCR);
/* clear any pending interrupts */
asc_update_bits(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
@@ -405,8 +385,8 @@ lqasc_shutdown(struct uart_port *port)
}
static void
-lqasc_set_termios(struct uart_port *port,
- struct ktermios *new, struct ktermios *old)
+lqasc_set_termios(struct uart_port *port, struct ktermios *new,
+ const struct ktermios *old)
{
unsigned int cflag;
unsigned int iflag;
@@ -598,17 +578,14 @@ static const struct uart_ops lqasc_pops = {
#ifdef CONFIG_SERIAL_LANTIQ_CONSOLE
static void
-lqasc_console_putchar(struct uart_port *port, int ch)
+lqasc_console_putchar(struct uart_port *port, unsigned char ch)
{
- int fifofree;
-
if (!port->membase)
return;
- do {
- fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT)
- & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
- } while (fifofree == 0);
+ while (!lqasc_tx_ready(port))
+ ;
+
writeb(ch, port->membase + LTQ_ASC_TBUF);
}
@@ -796,10 +773,8 @@ static int fetch_irq_intel(struct device *dev, struct ltq_uart_port *ltq_port)
int ret;
ret = platform_get_irq(to_platform_device(dev), 0);
- if (ret < 0) {
- dev_err(dev, "failed to fetch IRQ for serial port\n");
+ if (ret < 0)
return ret;
- }
ltq_port->common_irq = ret;
port->irq = ret;
@@ -910,11 +885,11 @@ static int lqasc_probe(struct platform_device *pdev)
return ret;
}
-static int lqasc_remove(struct platform_device *pdev)
+static void lqasc_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
- return uart_remove_one_port(&lqasc_reg, port);
+ uart_remove_one_port(&lqasc_reg, port);
}
static const struct ltq_soc_data soc_data_lantiq = {