summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-08 18:49:23 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-08 18:49:23 -0700
commit8f3207c7eab9d885cc64c778416537034a7d9c5b (patch)
tree733ec3a8c62b1906a72a6075966c1f57a37b0387 /drivers/tty/serial
parentbf5f89463f5b3109a72ed13ca62b57e90213387d (diff)
parent8e1c21f486944bf92f2a981f23ee811a45f5eaff (diff)
Merge tag 'tty-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial updates from Greg KH: "Here is the "big" TTY/Serial patch updates for 4.12-rc1 Not a lot of new things here, the normal number of serial driver updates and additions, tiny bugs fixed, and some core files split up to make future changes a bit easier for Nicolas's "tiny-tty" work. All of these have been in linux-next for a while" * tag 'tty-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (62 commits) serial: small Makefile reordering tty: split job control support into a file of its own tty: move baudrate handling code to a file of its own console: move console_init() out of tty_io.c serial: 8250_early: Add earlycon support for Palmchip UART tty: pl011: use "qdf2400_e44" as the earlycon name for QDF2400 E44 vt: make mouse selection of non-ASCII consistent vt: set mouse selection word-chars to gpm's default imx-serial: Reduce RX DMA startup latency when opening for reading serial: omap: suspend device on probe errors serial: omap: fix runtime-pm handling on unbind tty: serial: omap: add UPF_BOOT_AUTOCONF flag for DT init serial: samsung: Remove useless spinlock serial: samsung: Add missing checks for dma_map_single failure serial: samsung: Use right device for DMA-mapping calls serial: imx: setup DCEDTE early and ensure DCD and RI irqs to be off tty: fix comment typo s/repsonsible/responsible/ tty: amba-pl011: Fix spurious TX interrupts serial: xuartps: Enable clocks in the pm disable case also serial: core: Re-use struct uart_port {name} field ...
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_early.c24
-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/8250/8250_port.c4
-rw-r--r--drivers/tty/serial/Kconfig11
-rw-r--r--drivers/tty/serial/Makefile3
-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.c54
-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.c9
-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
25 files changed, 585 insertions, 154 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_early.c b/drivers/tty/serial/8250/8250_early.c
index 85a12f032402..82fc48eca1df 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -39,6 +39,7 @@
static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
{
+ int reg_offset = offset;
offset <<= port->regshift;
switch (port->iotype) {
@@ -52,6 +53,8 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
return ioread32be(port->membase + offset);
case UPIO_PORT:
return inb(port->iobase + offset);
+ case UPIO_AU:
+ return port->serial_in(port, reg_offset);
default:
return 0;
}
@@ -59,6 +62,7 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
{
+ int reg_offset = offset;
offset <<= port->regshift;
switch (port->iotype) {
@@ -77,6 +81,9 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
case UPIO_PORT:
outb(value, port->iobase + offset);
break;
+ case UPIO_AU:
+ port->serial_out(port, reg_offset, value);
+ break;
}
}
@@ -172,3 +179,20 @@ OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup);
OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);
#endif
+
+#ifdef CONFIG_SERIAL_8250_RT288X
+
+unsigned int au_serial_in(struct uart_port *p, int offset);
+void au_serial_out(struct uart_port *p, int offset, int value);
+
+static int __init early_au_setup(struct earlycon_device *dev, const char *opt)
+{
+ dev->port.serial_in = au_serial_in;
+ dev->port.serial_out = au_serial_out;
+ dev->port.iotype = UPIO_AU;
+ dev->con->write = early_serial8250_write;
+ return 0;
+}
+OF_EARLYCON_DECLARE(palmchip, "ralink,rt2880-uart", early_au_setup);
+
+#endif
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/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 6119516ef5fc..09a65a3ec7f7 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -328,7 +328,7 @@ static const s8 au_io_out_map[8] = {
-1, /* UART_SCR (unmapped) */
};
-static unsigned int au_serial_in(struct uart_port *p, int offset)
+unsigned int au_serial_in(struct uart_port *p, int offset)
{
if (offset >= ARRAY_SIZE(au_io_in_map))
return UINT_MAX;
@@ -338,7 +338,7 @@ static unsigned int au_serial_in(struct uart_port *p, int offset)
return __raw_readl(p->membase + (offset << p->regshift));
}
-static void au_serial_out(struct uart_port *p, int offset, int value)
+void au_serial_out(struct uart_port *p, int offset, int value)
{
if (offset >= ARRAY_SIZE(au_io_out_map))
return;
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/Makefile b/drivers/tty/serial/Makefile
index 2d6288bc4554..53c03e005132 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -3,7 +3,6 @@
#
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
-obj-$(CONFIG_SERIAL_21285) += 21285.o
obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
obj-$(CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST) += earlycon-arm-semihost.o
@@ -17,6 +16,8 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
+obj-$(CONFIG_SERIAL_21285) += 21285.o
+
# Now bring in any enabled 8250/16450/16550 type drivers.
obj-$(CONFIG_SERIAL_8250) += 8250/
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..8a857bb34fbb 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)
@@ -2470,19 +2475,34 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
if (!device->port.membase)
return -ENODEV;
- /* On QDF2400 SOCs affected by Erratum 44, the "qdf2400_e44" must
- * also be specified, e.g. "earlycon=pl011,<address>,qdf2400_e44".
- */
- if (!strcmp(device->options, "qdf2400_e44"))
- device->con->write = qdf2400_e44_early_write;
- else
- device->con->write = pl011_early_write;
+ device->con->write = pl011_early_write;
return 0;
}
OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
OF_EARLYCON_DECLARE(pl011, "arm,sbsa-uart", pl011_early_console_setup);
-EARLYCON_DECLARE(qdf2400_e44, pl011_early_console_setup);
+
+/*
+ * On Qualcomm Datacenter Technologies QDF2400 SOCs affected by
+ * Erratum 44, traditional earlycon can be enabled by specifying
+ * "earlycon=qdf2400_e44,<address>". Any options are ignored.
+ *
+ * Alternatively, you can just specify "earlycon", and the early console
+ * will be enabled with the information from the SPCR table. In this
+ * case, the SPCR code will detect the need for the E44 work-around,
+ * and set the console name to "qdf2400_e44".
+ */
+static int __init
+qdf2400_e44_early_console_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->con->write = qdf2400_e44_early_write;
+ return 0;
+}
+EARLYCON_DECLARE(qdf2400_e44, qdf2400_e44_early_console_setup);
#else
#define AMBA_CONSOLE NULL
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, unsi