summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/8250/8250_core.c2
-rw-r--r--drivers/tty/serial/8250/8250_dw.c13
-rw-r--r--drivers/tty/serial/8250/8250_exar.c2
-rw-r--r--drivers/tty/serial/8250/8250_fintek.c43
-rw-r--r--drivers/tty/serial/8250/8250_lpss.c3
-rw-r--r--drivers/tty/serial/Kconfig11
-rw-r--r--drivers/tty/serial/altera_jtaguart.c20
-rw-r--r--drivers/tty/serial/altera_uart.c32
-rw-r--r--drivers/tty/serial/amba-pl011.c23
-rw-r--r--drivers/tty/serial/atmel_serial.c7
-rw-r--r--drivers/tty/serial/atmel_serial.h169
-rw-r--r--drivers/tty/serial/fsl_lpuart.c20
-rw-r--r--drivers/tty/serial/imx.c99
-rw-r--r--drivers/tty/serial/omap-serial.c12
-rw-r--r--drivers/tty/serial/samsung.c44
-rw-r--r--drivers/tty/serial/sb1250-duart.c18
-rw-r--r--drivers/tty/serial/serial_core.c34
-rw-r--r--drivers/tty/serial/sh-sci.c43
-rw-r--r--drivers/tty/serial/sprd_serial.c2
-rw-r--r--drivers/tty/serial/st-asc.c10
-rw-r--r--drivers/tty/serial/uartlite.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c71
22 files changed, 537 insertions, 143 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 76e03a7de9cc..48a07e2f617f 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -218,7 +218,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
spin_unlock_irq(&i->lock);
irq_flags |= up->port.irqflags;
ret = request_irq(up->port.irq, serial8250_interrupt,
- irq_flags, "serial", i);
+ irq_flags, up->port.name, i);
if (ret < 0)
serial_do_unlink(i, up);
}
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index e65808c482f1..787b1160d3a5 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -530,12 +530,11 @@ static int dw8250_probe(struct platform_device *pdev)
}
data->rst = devm_reset_control_get_optional(dev, NULL);
- if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) {
- err = -EPROBE_DEFER;
+ if (IS_ERR(data->rst)) {
+ err = PTR_ERR(data->rst);
goto err_pclk;
}
- if (!IS_ERR(data->rst))
- reset_control_deassert(data->rst);
+ reset_control_deassert(data->rst);
dw8250_quirks(p, data);
@@ -567,8 +566,7 @@ static int dw8250_probe(struct platform_device *pdev)
return 0;
err_reset:
- if (!IS_ERR(data->rst))
- reset_control_assert(data->rst);
+ reset_control_assert(data->rst);
err_pclk:
if (!IS_ERR(data->pclk))
@@ -589,8 +587,7 @@ static int dw8250_remove(struct platform_device *pdev)
serial8250_unregister_port(data->line);
- if (!IS_ERR(data->rst))
- reset_control_assert(data->rst);
+ reset_control_assert(data->rst);
if (!IS_ERR(data->pclk))
clk_disable_unprepare(data->pclk);
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index b89c4ffc0486..1270ff163f63 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -483,5 +483,5 @@ static struct pci_driver exar_pci_driver = {
module_pci_driver(exar_pci_driver);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Exar Serial Dricer");
+MODULE_DESCRIPTION("Exar Serial Driver");
MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c
index b67e7a544935..e500f7dd2470 100644
--- a/drivers/tty/serial/8250/8250_fintek.c
+++ b/drivers/tty/serial/8250/8250_fintek.c
@@ -61,6 +61,12 @@
* The IRQ setting mode of F81866 is not the same with F81216 series.
* Level/Low: IRQ_MODE0:0, IRQ_MODE1:0
* Edge/High: IRQ_MODE0:1, IRQ_MODE1:0
+ *
+ * Clock speeds for UART (register F2h)
+ * 00: 1.8432MHz.
+ * 01: 18.432MHz.
+ * 10: 24MHz.
+ * 11: 14.769MHz.
*/
#define F81866_IRQ_MODE 0xf0
#define F81866_IRQ_SHARE BIT(0)
@@ -72,6 +78,13 @@
#define F81866_LDN_LOW 0x10
#define F81866_LDN_HIGH 0x16
+#define F81866_UART_CLK 0xF2
+#define F81866_UART_CLK_MASK (BIT(1) | BIT(0))
+#define F81866_UART_CLK_1_8432MHZ 0
+#define F81866_UART_CLK_14_769MHZ (BIT(1) | BIT(0))
+#define F81866_UART_CLK_18_432MHZ BIT(0)
+#define F81866_UART_CLK_24MHZ BIT(1)
+
struct fintek_8250 {
u16 pid;
u16 base_port;
@@ -256,8 +269,26 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
}
}
-static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address,
- unsigned int irq)
+static void fintek_8250_goto_highspeed(struct uart_8250_port *uart,
+ struct fintek_8250 *pdata)
+{
+ sio_write_reg(pdata, LDN, pdata->index);
+
+ switch (pdata->pid) {
+ case CHIP_ID_F81866: /* set uart clock for high speed serial mode */
+ sio_write_mask_reg(pdata, F81866_UART_CLK,
+ F81866_UART_CLK_MASK,
+ F81866_UART_CLK_14_769MHZ);
+
+ uart->port.uartclk = 921600 * 16;
+ break;
+ default: /* leave clock speed untouched */
+ break;
+ }
+}
+
+static int probe_setup_port(struct fintek_8250 *pdata,
+ struct uart_8250_port *uart)
{
static const u16 addr[] = {0x4e, 0x2e};
static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
@@ -284,18 +315,20 @@ static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address,
sio_write_reg(pdata, LDN, k);
aux = sio_read_reg(pdata, IO_ADDR1);
aux |= sio_read_reg(pdata, IO_ADDR2) << 8;
- if (aux != io_address)
+ if (aux != uart->port.iobase)
continue;
pdata->index = k;
- irq_data = irq_get_irq_data(irq);
+ irq_data = irq_get_irq_data(uart->port.irq);
if (irq_data)
level_mode =
irqd_is_level_type(irq_data);
fintek_8250_set_irq_mode(pdata, level_mode);
fintek_8250_set_max_fifo(pdata);
+ fintek_8250_goto_highspeed(uart, pdata);
+
fintek_8250_exit_key(addr[i]);
return 0;
@@ -330,7 +363,7 @@ int fintek_8250_probe(struct uart_8250_port *uart)
struct fintek_8250 *pdata;
struct fintek_8250 probe_data;
- if (probe_setup_port(&probe_data, uart->port.iobase, uart->port.irq))
+ if (probe_setup_port(&probe_data, uart))
return -ENODEV;
pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL);
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index f3ea90f0e411..7dddd7e6a01c 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -183,7 +183,6 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port)
if (ret)
return;
- pci_set_master(pdev);
pci_try_set_mwi(pdev);
/* Special DMA address for UART */
@@ -216,6 +215,8 @@ static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
struct pci_dev *pdev = to_pci_dev(port->dev);
int ret;
+ pci_set_master(pdev);
+
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0)
return ret;
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 6117ac8da48f..5c8850f7a2a0 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -630,6 +630,15 @@ config SERIAL_UARTLITE_CONSOLE
console (the system console is the device which receives all kernel
messages and warnings and which allows logins in single user mode).
+config SERIAL_UARTLITE_NR_UARTS
+ int "Maximum number of uartlite serial ports"
+ depends on SERIAL_UARTLITE
+ range 1 256
+ default 1
+ help
+ Set this to the number of uartlites in your system, or the number
+ you think you might implement.
+
config SERIAL_SUNCORE
bool
depends on SPARC
@@ -1343,6 +1352,7 @@ config SERIAL_ALTERA_JTAGUART_CONSOLE
bool "Altera JTAG UART console support"
depends on SERIAL_ALTERA_JTAGUART=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
help
Enable a Altera JTAG UART port to be the system console.
@@ -1382,6 +1392,7 @@ config SERIAL_ALTERA_UART_CONSOLE
bool "Altera UART console support"
depends on SERIAL_ALTERA_UART=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
help
Enable a Altera UART port to be the system console.
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index e409d7dac7ab..18e3f8342b85 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -383,6 +383,26 @@ console_initcall(altera_jtaguart_console_init);
#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
+static void altera_jtaguart_earlycon_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct earlycon_device *dev = co->data;
+
+ uart_console_write(&dev->port, s, count, altera_jtaguart_console_putc);
+}
+
+static int __init altera_jtaguart_earlycon_setup(struct earlycon_device *dev,
+ const char *options)
+{
+ if (!dev->port.membase)
+ return -ENODEV;
+
+ dev->con->write = altera_jtaguart_earlycon_write;
+ return 0;
+}
+
+OF_EARLYCON_DECLARE(juart, "altr,juart-1.0", altera_jtaguart_earlycon_setup);
+
#else
#define ALTERA_JTAGUART_CONSOLE NULL
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 820a74208696..46d3438a0d27 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -489,6 +489,38 @@ console_initcall(altera_uart_console_init);
#define ALTERA_UART_CONSOLE (&altera_uart_console)
+static void altera_uart_earlycon_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct earlycon_device *dev = co->data;
+
+ uart_console_write(&dev->port, s, count, altera_uart_console_putc);
+}
+
+static int __init altera_uart_earlycon_setup(struct earlycon_device *dev,
+ const char *options)
+{
+ struct uart_port *port = &dev->port;
+
+ if (!port->membase)
+ return -ENODEV;
+
+ /* Enable RX interrupts now */
+ writel(ALTERA_UART_CONTROL_RRDY_MSK,
+ port->membase + ALTERA_UART_CONTROL_REG);
+
+ if (dev->baud) {
+ unsigned int baudclk = port->uartclk / dev->baud;
+
+ writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
+ }
+
+ dev->con->write = altera_uart_earlycon_write;
+ return 0;
+}
+
+OF_EARLYCON_DECLARE(uart, "altr,uart-1.0", altera_uart_earlycon_setup);
+
#else
#define ALTERA_UART_CONSOLE NULL
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b0a377725d63..37257badcb97 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1327,14 +1327,15 @@ static void pl011_stop_tx(struct uart_port *port)
pl011_dma_tx_stop(uap);
}
-static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
+static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
/* Start TX with programmed I/O only (no DMA) */
static void pl011_start_tx_pio(struct uart_amba_port *uap)
{
- uap->im |= UART011_TXIM;
- pl011_write(uap->im, uap, REG_IMSC);
- pl011_tx_chars(uap, false);
+ if (pl011_tx_chars(uap, false)) {
+ uap->im |= UART011_TXIM;
+ pl011_write(uap->im, uap, REG_IMSC);
+ }
}
static void pl011_start_tx(struct uart_port *port)
@@ -1414,25 +1415,26 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
return true;
}
-static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
+/* Returns true if tx interrupts have to be (kept) enabled */
+static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
{
struct circ_buf *xmit = &uap->port.state->xmit;
int count = uap->fifosize >> 1;
if (uap->port.x_char) {
if (!pl011_tx_char(uap, uap->port.x_char, from_irq))
- return;
+ return true;
uap->port.x_char = 0;
--count;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
pl011_stop_tx(&uap->port);
- return;
+ return false;
}
/* If we are using DMA mode, try to send some characters. */
if (pl011_dma_tx_irq(uap))
- return;
+ return true;
do {
if (likely(from_irq) && count-- == 0)
@@ -1447,8 +1449,11 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port);
- if (uart_circ_empty(xmit))
+ if (uart_circ_empty(xmit)) {
pl011_stop_tx(&uap->port);
+ return false;
+ }
+ return true;
}
static void pl011_modem_status(struct uart_amba_port *uap)
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 1f50a83ef958..c355ac9abafc 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -38,7 +38,6 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/atmel_pdc.h>
-#include <linux/atmel_serial.h>
#include <linux/uaccess.h>
#include <linux/platform_data/atmel.h>
#include <linux/timer.h>
@@ -71,6 +70,7 @@
#include <linux/serial_core.h>
#include "serial_mctrl_gpio.h"
+#include "atmel_serial.h"
static void atmel_start_rx(struct uart_port *port);
static void atmel_stop_rx(struct uart_port *port);
@@ -119,8 +119,9 @@ struct atmel_uart_char {
/*
* at91: 6 USARTs and one DBGU port (SAM9260)
* avr32: 4
+ * samx7: 3 USARTs and 5 UARTs
*/
-#define ATMEL_MAX_UART 7
+#define ATMEL_MAX_UART 8
/*
* We wrap our port structure around the generic uart_port.
@@ -175,6 +176,7 @@ struct atmel_uart_port {
unsigned int pending_status;
spinlock_t lock_suspended;
+#ifdef CONFIG_PM
struct {
u32 cr;
u32 mr;
@@ -185,6 +187,7 @@ struct atmel_uart_port {
u32 fmr;
u32 fimr;
} cache;
+#endif
int (*prepare_rx)(struct uart_port *port);
int (*prepare_tx)(struct uart_port *port);
diff --git a/drivers/tty/serial/atmel_serial.h b/drivers/tty/serial/atmel_serial.h
new file mode 100644
index 000000000000..bd2560502f3c
--- /dev/null
+++ b/drivers/tty/serial/atmel_serial.h
@@ -0,0 +1,169 @@
+/*
+ * include/linux/atmel_serial.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * USART registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef ATMEL_SERIAL_H
+#define ATMEL_SERIAL_H
+
+#define ATMEL_US_CR 0x00 /* Control Register */
+#define ATMEL_US_RSTRX BIT(2) /* Reset Receiver */
+#define ATMEL_US_RSTTX BIT(3) /* Reset Transmitter */
+#define ATMEL_US_RXEN BIT(4) /* Receiver Enable */
+#define ATMEL_US_RXDIS BIT(5) /* Receiver Disable */
+#define ATMEL_US_TXEN BIT(6) /* Transmitter Enable */
+#define ATMEL_US_TXDIS BIT(7) /* Transmitter Disable */
+#define ATMEL_US_RSTSTA BIT(8) /* Reset Status Bits */
+#define ATMEL_US_STTBRK BIT(9) /* Start Break */
+#define ATMEL_US_STPBRK BIT(10) /* Stop Break */
+#define ATMEL_US_STTTO BIT(11) /* Start Time-out */
+#define ATMEL_US_SENDA BIT(12) /* Send Address */
+#define ATMEL_US_RSTIT BIT(13) /* Reset Iterations */
+#define ATMEL_US_RSTNACK BIT(14) /* Reset Non Acknowledge */
+#define ATMEL_US_RETTO BIT(15) /* Rearm Time-out */
+#define ATMEL_US_DTREN BIT(16) /* Data Terminal Ready Enable */
+#define ATMEL_US_DTRDIS BIT(17) /* Data Terminal Ready Disable */
+#define ATMEL_US_RTSEN BIT(18) /* Request To Send Enable */
+#define ATMEL_US_RTSDIS BIT(19) /* Request To Send Disable */
+#define ATMEL_US_TXFCLR BIT(24) /* Transmit FIFO Clear */
+#define ATMEL_US_RXFCLR BIT(25) /* Receive FIFO Clear */
+#define ATMEL_US_TXFLCLR BIT(26) /* Transmit FIFO Lock Clear */
+#define ATMEL_US_FIFOEN BIT(30) /* FIFO enable */
+#define ATMEL_US_FIFODIS BIT(31) /* FIFO disable */
+
+#define ATMEL_US_MR 0x04 /* Mode Register */
+#define ATMEL_US_USMODE GENMASK(3, 0) /* Mode of the USART */
+#define ATMEL_US_USMODE_NORMAL 0
+#define ATMEL_US_USMODE_RS485 1
+#define ATMEL_US_USMODE_HWHS 2
+#define ATMEL_US_USMODE_MODEM 3
+#define ATMEL_US_USMODE_ISO7816_T0 4
+#define ATMEL_US_USMODE_ISO7816_T1 6
+#define ATMEL_US_USMODE_IRDA 8
+#define ATMEL_US_USCLKS GENMASK(5, 4) /* Clock Selection */
+#define ATMEL_US_USCLKS_MCK (0 << 4)
+#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
+#define ATMEL_US_USCLKS_SCK (3 << 4)
+#define ATMEL_US_CHRL GENMASK(7, 6) /* Character Length */
+#define ATMEL_US_CHRL_5 (0 << 6)
+#define ATMEL_US_CHRL_6 (1 << 6)
+#define ATMEL_US_CHRL_7 (2 << 6)
+#define ATMEL_US_CHRL_8 (3 << 6)
+#define ATMEL_US_SYNC BIT(8) /* Synchronous Mode Select */
+#define ATMEL_US_PAR GENMASK(11, 9) /* Parity Type */
+#define ATMEL_US_PAR_EVEN (0 << 9)
+#define ATMEL_US_PAR_ODD (1 << 9)
+#define ATMEL_US_PAR_SPACE (2 << 9)
+#define ATMEL_US_PAR_MARK (3 << 9)
+#define ATMEL_US_PAR_NONE (4 << 9)
+#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
+#define ATMEL_US_NBSTOP GENMASK(13, 12) /* Number of Stop Bits */
+#define ATMEL_US_NBSTOP_1 (0 << 12)
+#define ATMEL_US_NBSTOP_1_5 (1 << 12)
+#define ATMEL_US_NBSTOP_2 (2 << 12)
+#define ATMEL_US_CHMODE GENMASK(15, 14) /* Channel Mode */
+#define ATMEL_US_CHMODE_NORMAL (0 << 14)
+#define ATMEL_US_CHMODE_ECHO (1 << 14)
+#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
+#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
+#define ATMEL_US_MSBF BIT(16) /* Bit Order */
+#define ATMEL_US_MODE9 BIT(17) /* 9-bit Character Length */
+#define ATMEL_US_CLKO BIT(18) /* Clock Output Select */
+#define ATMEL_US_OVER BIT(19) /* Oversampling Mode */
+#define ATMEL_US_INACK BIT(20) /* Inhibit Non Acknowledge */
+#define ATMEL_US_DSNACK BIT(21) /* Disable Successive NACK */
+#define ATMEL_US_MAX_ITER GENMASK(26, 24) /* Max Iterations */
+#define ATMEL_US_FILTER BIT(28) /* Infrared Receive Line Filter */
+
+#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
+#define ATMEL_US_RXRDY BIT(0) /* Receiver Ready */
+#define ATMEL_US_TXRDY BIT(1) /* Transmitter Ready */
+#define ATMEL_US_RXBRK BIT(2) /* Break Received / End of Break */
+#define ATMEL_US_ENDRX BIT(3) /* End of Receiver Transfer */
+#define ATMEL_US_ENDTX BIT(4) /* End of Transmitter Transfer */
+#define ATMEL_US_OVRE BIT(5) /* Overrun Error */
+#define ATMEL_US_FRAME BIT(6) /* Framing Error */
+#define ATMEL_US_PARE BIT(7) /* Parity Error */
+#define ATMEL_US_TIMEOUT BIT(8) /* Receiver Time-out */
+#define ATMEL_US_TXEMPTY BIT(9) /* Transmitter Empty */
+#define ATMEL_US_ITERATION BIT(10) /* Max number of Repetitions Reached */
+#define ATMEL_US_TXBUFE BIT(11) /* Transmission Buffer Empty */
+#define ATMEL_US_RXBUFF BIT(12) /* Reception Buffer Full */
+#define ATMEL_US_NACK BIT(13) /* Non Acknowledge */
+#define ATMEL_US_RIIC BIT(16) /* Ring Indicator Input Change */
+#define ATMEL_US_DSRIC BIT(17) /* Data Set Ready Input Change */
+#define ATMEL_US_DCDIC BIT(18) /* Data Carrier Detect Input Change */
+#define ATMEL_US_CTSIC BIT(19) /* Clear to Send Input Change */
+#define ATMEL_US_RI BIT(20) /* RI */
+#define ATMEL_US_DSR BIT(21) /* DSR */
+#define ATMEL_US_DCD BIT(22) /* DCD */
+#define ATMEL_US_CTS BIT(23) /* CTS */
+
+#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
+#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
+#define ATMEL_US_CSR 0x14 /* Channel Status Register */
+#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
+#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
+#define ATMEL_US_SYNH BIT(15) /* Transmit/Receive Sync */
+
+#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
+#define ATMEL_US_CD GENMASK(15, 0) /* Clock Divider */
+#define ATMEL_US_FP_OFFSET 16 /* Fractional Part */
+#define ATMEL_US_FP_MASK 0x7
+
+#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register for USART */
+#define ATMEL_UA_RTOR 0x28 /* Receiver Time-out Register for UART */
+#define ATMEL_US_TO GENMASK(15, 0) /* Time-out Value */
+
+#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
+#define ATMEL_US_TG GENMASK(7, 0) /* Timeguard Value */
+
+#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
+#define ATMEL_US_NER 0x44 /* Number of Errors Register */
+#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
+
+#define ATMEL_US_CMPR 0x90 /* Comparaison Register */
+#define ATMEL_US_FMR 0xa0 /* FIFO Mode Register */
+#define ATMEL_US_TXRDYM(data) (((data) & 0x3) << 0) /* TX Ready Mode */
+#define ATMEL_US_RXRDYM(data) (((data) & 0x3) << 4) /* RX Ready Mode */
+#define ATMEL_US_ONE_DATA 0x0
+#define ATMEL_US_TWO_DATA 0x1
+#define ATMEL_US_FOUR_DATA 0x2
+#define ATMEL_US_FRTSC BIT(7) /* FIFO RTS pin Control */
+#define ATMEL_US_TXFTHRES(thr) (((thr) & 0x3f) << 8) /* TX FIFO Threshold */
+#define ATMEL_US_RXFTHRES(thr) (((thr) & 0x3f) << 16) /* RX FIFO Threshold */
+#define ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24) /* RX FIFO Threshold2 */
+
+#define ATMEL_US_FLR 0xa4 /* FIFO Level Register */
+#define ATMEL_US_TXFL(reg) (((reg) >> 0) & 0x3f) /* TX FIFO Level */
+#define ATMEL_US_RXFL(reg) (((reg) >> 16) & 0x3f) /* RX FIFO Level */
+
+#define ATMEL_US_FIER 0xa8 /* FIFO Interrupt Enable Register */
+#define ATMEL_US_FIDR 0xac /* FIFO Interrupt Disable Register */
+#define ATMEL_US_FIMR 0xb0 /* FIFO Interrupt Mask Register */
+#define ATMEL_US_FESR 0xb4 /* FIFO Event Status Register */
+#define ATMEL_US_TXFEF BIT(0) /* Transmit FIFO Empty Flag */
+#define ATMEL_US_TXFFF BIT(1) /* Transmit FIFO Full Flag */
+#define ATMEL_US_TXFTHF BIT(2) /* Transmit FIFO Threshold Flag */
+#define ATMEL_US_RXFEF BIT(3) /* Receive FIFO Empty Flag */
+#define ATMEL_US_RXFFF BIT(4) /* Receive FIFO Full Flag */
+#define ATMEL_US_RXFTHF BIT(5) /* Receive FIFO Threshold Flag */
+#define ATMEL_US_TXFPTEF BIT(6) /* Transmit FIFO Pointer Error Flag */
+#define ATMEL_US_RXFPTEF BIT(7) /* Receive FIFO Pointer Error Flag */
+#define ATMEL_US_TXFLOCK BIT(8) /* Transmit FIFO Lock (FESR only) */
+#define ATMEL_US_RXFTHF2 BIT(9) /* Receive FIFO Threshold Flag 2 */
+
+#define ATMEL_US_NAME 0xf0 /* Ip Name */
+#define ATMEL_US_VERSION 0xfc /* Ip Version */
+
+#endif
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index f02934ffb329..15df1ba78095 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1705,6 +1705,13 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
{
struct lpuart_port *sport = lpuart_ports[co->index];
unsigned char old_cr2, cr2;
+ unsigned long flags;
+ int locked = 1;
+
+ if (sport->port.sysrq || oops_in_progress)
+ locked = spin_trylock_irqsave(&sport->port.lock, flags);
+ else
+ spin_lock_irqsave(&sport->port.lock, flags);
/* first save CR2 and then disable interrupts */
cr2 = old_cr2 = readb(sport->port.membase + UARTCR2);
@@ -1719,6 +1726,9 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
barrier();
writeb(old_cr2, sport->port.membase + UARTCR2);
+
+ if (locked)
+ spin_unlock_irqrestore(&sport->port.lock, flags);
}
static void
@@ -1726,6 +1736,13 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
{
struct lpuart_port *sport = lpuart_ports[co->index];
unsigned long old_cr, cr;
+ unsigned long flags;
+ int locked = 1;
+
+ if (sport->port.sysrq || oops_in_progress)
+ locked = spin_trylock_irqsave(&sport->port.lock, flags);
+ else
+ spin_lock_irqsave(&sport->port.lock, flags);
/* first save CR2 and then disable interrupts */
cr = old_cr = lpuart32_read(sport->port.membase + UARTCTRL);
@@ -1740,6 +1757,9 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
barrier();
lpuart32_write(old_cr, sport->port.membase + UARTCTRL);
+
+ if (locked)
+ spin_unlock_irqrestore(&sport->port.lock, flags);
}
/*
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index e3e152cbc75e..33509b4beaec 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -719,6 +719,27 @@ out:
return IRQ_HANDLED;
}
+static void imx_disable_rx_int(struct imx_port *sport)
+{
+ unsigned long temp;
+
+ sport->dma_is_rxing = 1;
+
+ /* disable the receiver ready and aging timer interrupts */
+ temp = readl(sport->port.membase + UCR1);
+ temp &= ~(UCR1_RRDYEN);
+ writel(temp, sport->port.membase + UCR1);
+
+ temp = readl(sport->port.membase + UCR2);
+ temp &= ~(UCR2_ATEN);
+ writel(temp, sport->port.membase + UCR2);
+
+ /* disable the rx errors interrupts */
+ temp = readl(sport->port.membase + UCR4);
+ temp &= ~UCR4_OREN;
+ writel(temp, sport->port.membase + UCR4);
+}
+
static void clear_rx_errors(struct imx_port *sport);
static int start_rx_dma(struct imx_port *sport);
/*
@@ -734,21 +755,8 @@ static void imx_dma_rxint(struct imx_port *sport)
temp = readl(sport->port.membase + USR2);
if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
- sport->dma_is_rxing = 1;
- /* disable the receiver ready and aging timer interrupts */
- temp = readl(sport->port.membase + UCR1);
- temp &= ~(UCR1_RRDYEN);
- writel(temp, sport->port.membase + UCR1);
-
- temp = readl(sport->port.membase + UCR2);
- temp &= ~(UCR2_ATEN);
- writel(temp, sport->port.membase + UCR2);
-
- /* disable the rx errors interrupts */
- temp = readl(sport->port.membase + UCR4);
- temp &= ~UCR4_OREN;
- writel(temp, sport->port.membase + UCR4);
+ imx_disable_rx_int(sport);
/* tell the DMA to receive the data. */
start_rx_dma(sport);
@@ -1317,19 +1325,10 @@ static int imx_startup(struct uart_port *port)
if (!is_imx1_uart(sport)) {
temp = readl(sport->port.membase + UCR3);
- /*
- * The effect of RI and DCD differs depending on the UFCR_DCEDTE
- * bit. In DCE mode they control the outputs, in DTE mode they
- * enable the respective irqs. At least the DCD irq cannot be
- * cleared on i.MX25 at least, so it's not usable and must be
- * disabled. I don't have test hardware to check if RI has the
- * same problem but I consider this likely so it's disabled for
- * now, too.
- */
- temp |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP |
- UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
+ temp |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
if (sport->dte_mode)
+ /* disable broken interrupts */
temp &= ~(UCR3_RI | UCR3_DCD);
writel(temp, sport->port.membase + UCR3);
@@ -1339,6 +1338,33 @@ static int imx_startup(struct uart_port *port)
* Enable modem status interrupts
*/
imx_enable_ms(&sport->port);
+
+ /*
+ * If the serial port is opened for reading start RX DMA immediately
+ * instead of waiting for RX FIFO interrupts. In our iMX53 the average
+ * delay for the first reception dropped from approximately 35000
+ * microseconds to 1000 microseconds.
+ */
+ if (sport->dma_is_enabled) {
+ struct tty_struct *tty = sport->port.state->port.tty;
+ struct tty_file_private *file_priv;
+ int readcnt = 0;
+
+ spin_lock(&tty->files_lock);
+
+ if (!list_empty(&tty->tty_files))
+ list_for_each_entry(file_priv, &tty->tty_files, list)
+ if (!(file_priv->file->f_flags & O_WRONLY))
+ readcnt++;
+
+ spin_unlock(&tty->files_lock);
+
+ if (readcnt > 0) {
+ imx_disable_rx_int(sport);
+ start_rx_dma(sport);
+ }
+ }
+
spin_unlock_irqrestore(&sport->port.lock, flags);
return 0;
@@ -1584,8 +1610,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
ufcr = readl(sport->port.membase + UFCR);
ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div);
- if (sport->dte_mode)
- ufcr |= UFCR_DCEDTE;
writel(ufcr, sport->port.membase + UFCR);
writel(num, sport->port.membase + UBIR);
@@ -2153,6 +2177,27 @@ static int serial_imx_probe(struct platform_device *pdev)
UCR1_TXMPTYEN | UCR1_RTSDEN);
writel_relaxed(reg, sport->port.membase + UCR1);
+ if (!is_imx1_uart(sport) && sport->dte_mode) {
+ /*
+ * The DCEDTE bit changes the direction of DSR, DCD, DTR and RI
+ * and influences if UCR3_RI and UCR3_DCD changes the level of RI
+ * and DCD (when they are outputs) or enables the respective
+ * irqs. So set this bit early, i.e. before requesting irqs.
+ */
+ writel(UFCR_DCEDTE, sport->port.membase + UFCR);
+
+ /*
+ * Disable UCR3_RI and UCR3_DCD irqs. They are also not
+ * enabled later because they cannot be cleared
+ * (confirmed on i.MX25) which makes them unusable.
+ */
+ writel(IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP | UCR3_DSR,
+ sport->port.membase + UCR3);
+
+ } else {
+ writel(0, sport->port.membase + UFCR);
+ }
+
clk_disable_unprepare(sport->clk_ipg);
/*
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6c6f82ad8d5c..1ea05ac57aa7 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1597,6 +1597,9 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
of_property_read_u32(dev->of_node, "clock-frequency",
&omap_up_info->uartclk);
+
+ omap_up_info->flags = UPF_BOOT_AUTOCONF;
+
return omap_up_info;
}
@@ -1767,7 +1770,8 @@ static int serial_omap_probe(struct platform_device *pdev)
return 0;
err_add_port:
- pm_runtime_put(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_qos_remove_request(&up->pm_qos_request);
device_init_wakeup(up->dev, false);
@@ -1780,9 +1784,13 @@ static int serial_omap_remove(struct platform_device *dev)
{
struct uart_omap_port *up = platform_get_drvdata(dev);
+ pm_runtime_get_sync(up->dev);
+
+ uart_remove_one_port(&serial_omap_reg, &up->port);
+
+ pm_runtime_dont_use_autosuspend(up->dev);
pm_runtime_put_sync(up->dev);
pm_runtime_disable(up->dev);
- uart_remove_one_port(&serial_omap_reg, &up->port);
pm_qos_remove_request(&up->pm_qos_request);
device_init_wakeup(&dev->dev, false);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 7a17aedbf902..8aca18c4cdea 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -859,7 +859,7 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)