summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/serial/8250.txt1
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,sci-serial.txt2
-rw-r--r--Documentation/devicetree/bindings/serial/st,stm32-usart.txt2
-rw-r--r--arch/arm/boot/dts/stih407-b2120.dts4
-rw-r--r--arch/arm/boot/dts/stih410-b2120.dts4
-rw-r--r--arch/arm/boot/dts/stih410-b2260.dts4
-rw-r--r--arch/arm/boot/dts/stih418-b2199.dts4
-rw-r--r--drivers/parport/parport_serial.c3
-rw-r--r--drivers/tty/hvc/Kconfig10
-rw-r--r--drivers/tty/hvc/Makefile1
-rw-r--r--drivers/tty/hvc/hvc_riscv_sbi.c60
-rw-r--r--drivers/tty/serdev/core.c2
-rw-r--r--drivers/tty/serial/8250/8250_dw.c34
-rw-r--r--drivers/tty/serial/8250/8250_men_mcb.c125
-rw-r--r--drivers/tty/serial/8250/8250_of.c1
-rw-r--r--drivers/tty/serial/8250/8250_omap.c11
-rw-r--r--drivers/tty/serial/8250/8250_pci.c3
-rw-r--r--drivers/tty/serial/8250/8250_port.c36
-rw-r--r--drivers/tty/serial/8250/Kconfig5
-rw-r--r--drivers/tty/serial/Kconfig15
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/altera_uart.c58
-rw-r--r--drivers/tty/serial/arc_uart.c5
-rw-r--r--drivers/tty/serial/fsl_lpuart.c4
-rw-r--r--drivers/tty/serial/imx.c1209
-rw-r--r--drivers/tty/serial/max310x.c2
-rw-r--r--drivers/tty/serial/mvebu-uart.c4
-rw-r--r--drivers/tty/serial/mxs-auart.c40
-rw-r--r--drivers/tty/serial/pxa.c4
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c1158
-rw-r--r--drivers/tty/serial/samsung.c4
-rw-r--r--drivers/tty/serial/serial_core.c2
-rw-r--r--drivers/tty/serial/sh-sci.c51
-rw-r--r--drivers/tty/serial/sirfsoc_uart.c5
-rw-r--r--drivers/tty/serial/st-asc.c4
-rw-r--r--drivers/tty/serial/stm32-usart.c134
-rw-r--r--drivers/tty/serial/stm32-usart.h3
-rw-r--r--drivers/tty/serial/xilinx_uartps.c2
-rw-r--r--drivers/tty/vt/vt.c6
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c68
-rw-r--r--drivers/video/console/dummycon.c69
-rw-r--r--drivers/video/console/newport_con.c8
-rw-r--r--drivers/video/console/vgacon.c20
-rw-r--r--drivers/video/fbdev/core/fbcon.c3
-rw-r--r--fs/devpts/inode.c66
-rw-r--r--include/linux/console.h58
-rw-r--r--include/linux/pci_ids.h3
-rw-r--r--include/linux/serial_core.h2
-rw-r--r--include/uapi/linux/serial_core.h3
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/filesystems/.gitignore1
-rw-r--r--tools/testing/selftests/filesystems/Makefile2
-rw-r--r--tools/testing/selftests/filesystems/devpts_pts.c313
53 files changed, 2902 insertions, 738 deletions
diff --git a/Documentation/devicetree/bindings/serial/8250.txt b/Documentation/devicetree/bindings/serial/8250.txt
index dad3b2ec66d4..aeb6db4e35c3 100644
--- a/Documentation/devicetree/bindings/serial/8250.txt
+++ b/Documentation/devicetree/bindings/serial/8250.txt
@@ -24,6 +24,7 @@ Required properties:
- "ti,da830-uart"
- "aspeed,ast2400-vuart"
- "aspeed,ast2500-vuart"
+ - "nuvoton,npcm750-uart"
- "serial" if the port type is unknown.
- reg : offset and length of the register set for the device.
- interrupts : should contain uart interrupt.
diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
index cf504d0380ae..ad962f4ec3aa 100644
--- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
+++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
@@ -43,6 +43,8 @@ Required properties:
- "renesas,hscif-r8a7796" for R8A7796 (R-Car M3-W) HSCIF compatible UART.
- "renesas,scif-r8a77970" for R8A77970 (R-Car V3M) SCIF compatible UART.
- "renesas,hscif-r8a77970" for R8A77970 (R-Car V3M) HSCIF compatible UART.
+ - "renesas,scif-r8a77980" for R8A77980 (R-Car V3H) SCIF compatible UART.
+ - "renesas,hscif-r8a77980" for R8A77980 (R-Car V3H) HSCIF compatible UART.
- "renesas,scif-r8a77995" for R8A77995 (R-Car D3) SCIF compatible UART.
- "renesas,hscif-r8a77995" for R8A77995 (R-Car D3) HSCIF compatible UART.
- "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
index d150b04a6229..9d3efed55deb 100644
--- a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
@@ -15,6 +15,8 @@ Required properties:
Optional properties:
- pinctrl: The reference on the pins configuration
- st,hw-flow-ctrl: bool flag to enable hardware flow control.
+- rs485-rts-delay, rs485-rx-during-tx, rs485-rts-active-low,
+ linux,rs485-enabled-at-boot-time: see rs485.txt.
- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt
- dma-names: "rx" and/or "tx"
diff --git a/arch/arm/boot/dts/stih407-b2120.dts b/arch/arm/boot/dts/stih407-b2120.dts
index c8ad905d0309..a7a0f76e9cbc 100644
--- a/arch/arm/boot/dts/stih407-b2120.dts
+++ b/arch/arm/boot/dts/stih407-b2120.dts
@@ -14,7 +14,7 @@
compatible = "st,stih407-b2120", "st,stih407";
chosen {
- bootargs = "console=ttyAS0,115200 clk_ignore_unused";
+ bootargs = "clk_ignore_unused";
linux,stdout-path = &sbc_serial0;
};
@@ -24,7 +24,7 @@
};
aliases {
- ttyAS0 = &sbc_serial0;
+ serial0 = &sbc_serial0;
ethernet0 = &ethernet0;
};
diff --git a/arch/arm/boot/dts/stih410-b2120.dts b/arch/arm/boot/dts/stih410-b2120.dts
index 9830be577433..6c6b4cc37e97 100644
--- a/arch/arm/boot/dts/stih410-b2120.dts
+++ b/arch/arm/boot/dts/stih410-b2120.dts
@@ -14,7 +14,7 @@
compatible = "st,stih410-b2120", "st,stih410";
chosen {
- bootargs = "console=ttyAS0,115200 clk_ignore_unused";
+ bootargs = "clk_ignore_unused";
linux,stdout-path = &sbc_serial0;
};
@@ -24,7 +24,7 @@
};
aliases {
- ttyAS0 = &sbc_serial0;
+ serial0 = &sbc_serial0;
ethernet0 = &ethernet0;
};
diff --git a/arch/arm/boot/dts/stih410-b2260.dts b/arch/arm/boot/dts/stih410-b2260.dts
index c663b70c43a7..50d36758391c 100644
--- a/arch/arm/boot/dts/stih410-b2260.dts
+++ b/arch/arm/boot/dts/stih410-b2260.dts
@@ -15,7 +15,7 @@
compatible = "st,stih410-b2260", "st,stih410";
chosen {
- bootargs = "console=ttyAS1,115200 clk_ignore_unused";
+ bootargs = "clk_ignore_unused";
linux,stdout-path = &uart1;
};
@@ -25,7 +25,7 @@
};
aliases {
- ttyAS1 = &uart1;
+ serial1 = &uart1;
ethernet0 = &ethernet0;
};
diff --git a/arch/arm/boot/dts/stih418-b2199.dts b/arch/arm/boot/dts/stih418-b2199.dts
index 4e6d915c85ff..7f5f3252bfc7 100644
--- a/arch/arm/boot/dts/stih418-b2199.dts
+++ b/arch/arm/boot/dts/stih418-b2199.dts
@@ -14,7 +14,7 @@
compatible = "st,stih418-b2199", "st,stih418";
chosen {
- bootargs = "console=ttyAS0,115200 clk_ignore_unused";
+ bootargs = "clk_ignore_unused";
linux,stdout-path = &sbc_serial0;
};
@@ -24,7 +24,7 @@
};
aliases {
- ttyAS0 = &sbc_serial0;
+ serial0 = &sbc_serial0;
ethernet0 = &ethernet0;
};
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index e15b4845f7c6..087e847b1da2 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -156,9 +156,6 @@ static struct parport_pc_pci cards[] = {
/* sunix_2s1p */ { 1, { { 3, -1 }, } },
};
-#define PCI_VENDOR_ID_SUNIX 0x1fd4
-#define PCI_DEVICE_ID_SUNIX_1999 0x1999
-
static struct pci_device_id parport_serial_pci_tbl[] = {
/* PCI cards */
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 3bade5ad3d71..4293c172e120 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -88,6 +88,16 @@ config HVC_DCC
driver. This console is used through a JTAG only on ARM. If you don't have
a JTAG then you probably don't want this option.
+config HVC_RISCV_SBI
+ bool "RISC-V SBI console support"
+ depends on RISCV
+ select HVC_DRIVER
+ help
+ This enables support for console output via RISC-V SBI calls, which
+ is normally used only during boot to output printk.
+
+ If you don't know what do to here, say Y.
+
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
depends on PPC_PSERIES && HVC_CONSOLE
diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile
index 7da1934d34e8..98880e357941 100644
--- a/drivers/tty/hvc/Makefile
+++ b/drivers/tty/hvc/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_HVC_IRQ) += hvc_irq.o
obj-$(CONFIG_HVC_XEN) += hvc_xen.o
obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o
obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o
+obj-$(CONFIG_HVC_RISCV_SBI) += hvc_riscv_sbi.o
obj-$(CONFIG_HVCS) += hvcs.o
diff --git a/drivers/tty/hvc/hvc_riscv_sbi.c b/drivers/tty/hvc/hvc_riscv_sbi.c
new file mode 100644
index 000000000000..75155bde2b88
--- /dev/null
+++ b/drivers/tty/hvc/hvc_riscv_sbi.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2008 David Gibson, IBM Corporation
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ */
+
+#include <linux/console.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#include <asm/sbi.h>
+
+#include "hvc_console.h"
+
+static int hvc_sbi_tty_put(uint32_t vtermno, const char *buf, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ sbi_console_putchar(buf[i]);
+
+ return i;
+}
+
+static int hvc_sbi_tty_get(uint32_t vtermno, char *buf, int count)
+{
+ int i, c;
+
+ for (i = 0; i < count; i++) {
+ c = sbi_console_getchar();
+ if (c < 0)
+ break;
+ buf[i] = c;
+ }
+
+ return i;
+}
+
+static const struct hv_ops hvc_sbi_ops = {
+ .get_chars = hvc_sbi_tty_get,
+ .put_chars = hvc_sbi_tty_put,
+};
+
+static int __init hvc_sbi_init(void)
+{
+ return PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_ops, 16));
+}
+device_initcall(hvc_sbi_init);
+
+static int __init hvc_sbi_console_init(void)
+{
+ hvc_instantiate(0, 0, &hvc_sbi_ops);
+ add_preferred_console("hvc", 0, NULL);
+
+ return 0;
+}
+console_initcall(hvc_sbi_console_init);
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index f439c72b9e3c..df93b727e984 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -350,7 +350,7 @@ static struct bus_type serdev_bus_type = {
};
/**
- * serdev_controller_alloc() - Allocate a new serdev device
+ * serdev_device_alloc() - Allocate a new serdev device
* @ctrl: associated controller
*
* Caller is responsible for either calling serdev_device_add() to add the
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index cd1b94a0f451..6fcdb90f616a 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -9,6 +9,7 @@
* LCR is written whilst busy. If it is, then a busy detect interrupt is
* raised, the LCR needs to be rewritten and the uart status register read.
*/
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -119,10 +120,27 @@ static void dw8250_check_lcr(struct uart_port *p, int value)
*/
}
+/* Returns once the transmitter is empty or we run out of retries */
+static void dw8250_tx_wait_empty(struct uart_port *p, int tries)
+{
+ unsigned int lsr;
+
+ while (tries--) {
+ lsr = readb (p->membase + (UART_LSR << p->regshift));
+ if (lsr & UART_LSR_TEMT)
+ break;
+ udelay (10);
+ }
+}
+
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
+ /* Allow the TX to drain before we reconfigure */
+ if (offset == UART_LCR)
+ dw8250_tx_wait_empty(p, 1000);
+
writeb(value, p->membase + (offset << p->regshift));
if (offset == UART_LCR && !d->uart_16550_compatible)
@@ -339,17 +357,11 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
p->serial_in = dw8250_serial_in32be;
p->serial_out = dw8250_serial_out32be;
}
- } else if (has_acpi_companion(p->dev)) {
- const struct acpi_device_id *id;
-
- id = acpi_match_device(p->dev->driver->acpi_match_table,
- p->dev);
- if (id && !strcmp(id->id, "APMC0D08")) {
- p->iotype = UPIO_MEM32;
- p->regshift = 2;
- p->serial_in = dw8250_serial_in32;
- data->uart_16550_compatible = true;
- }
+ } else if (acpi_dev_present("APMC0D08", NULL, -1)) {
+ p->iotype = UPIO_MEM32;
+ p->regshift = 2;
+ p->serial_in = dw8250_serial_in32;
+ data->uart_16550_compatible = true;
}
/* Platforms with iDMA */
diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c
index 308977807994..127017cc41d9 100644
--- a/drivers/tty/serial/8250/8250_men_mcb.c
+++ b/drivers/tty/serial/8250/8250_men_mcb.c
@@ -1,12 +1,19 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/io.h>
#include <linux/mcb.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
#include <uapi/linux/serial_core.h>
+#define MEN_UART_ID_Z025 0x19
+#define MEN_UART_ID_Z057 0x39
+#define MEN_UART_ID_Z125 0x7d
+
+#define MEN_UART_MEM_SIZE 0x10
+
struct serial_8250_men_mcb_data {
struct uart_8250_port uart;
int line;
@@ -18,7 +25,7 @@ struct serial_8250_men_mcb_data {
* parameter in order to really set the correct baudrate, and
* do so if possible without user interaction
*/
-static u32 men_z125_lookup_uartclk(struct mcb_device *mdev)
+static u32 men_lookup_uartclk(struct mcb_device *mdev)
{
/* use default value if board is not available below */
u32 clkval = 1041666;
@@ -28,10 +35,12 @@ static u32 men_z125_lookup_uartclk(struct mcb_device *mdev)
mdev->bus->name);
if (strncmp(mdev->bus->name, "F075", 4) == 0)
clkval = 1041666;
- else if (strncmp(mdev->bus->name, "F216", 4) == 0)
+ else if (strncmp(mdev->bus->name, "F216", 4) == 0)
clkval = 1843200;
else if (strncmp(mdev->bus->name, "G215", 4) == 0)
clkval = 1843200;
+ else if (strncmp(mdev->bus->name, "F210", 4) == 0)
+ clkval = 115200;
else
dev_info(&mdev->dev,
"board not detected, using default uartclk\n");
@@ -41,62 +50,108 @@ static u32 men_z125_lookup_uartclk(struct mcb_device *mdev)
return clkval;
}
+static unsigned int get_num_ports(struct mcb_device *mdev,
+ void __iomem *membase)
+{
+ switch (mdev->id) {
+ case MEN_UART_ID_Z125:
+ return 1U;
+ case MEN_UART_ID_Z025:
+ return readb(membase) >> 4;
+ case MEN_UART_ID_Z057:
+ return 4U;
+ default:
+ dev_err(&mdev->dev, "no supported device!\n");
+ return -ENODEV;
+ }
+}
+
static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
const struct mcb_device_id *id)
{
struct serial_8250_men_mcb_data *data;
struct resource *mem;
-
- data = devm_kzalloc(&mdev->dev,
- sizeof(struct serial_8250_men_mcb_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- mcb_set_drvdata(mdev, data);
- data->uart.port.dev = mdev->dma_dev;
- spin_lock_init(&data->uart.port.lock);
-
- data->uart.port.type = PORT_16550;
- data->uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
- data->uart.port.iotype = UPIO_MEM;
- data->uart.port.uartclk = men_z125_lookup_uartclk(mdev);
- data->uart.port.regshift = 0;
- data->uart.port.fifosize = 60;
+ unsigned int num_ports;
+ unsigned int i;
+ void __iomem *membase;
mem = mcb_get_resource(mdev, IORESOURCE_MEM);
if (mem == NULL)
return -ENXIO;
+ membase = devm_ioremap_resource(&mdev->dev, mem);
+ if (IS_ERR(membase))
+ return PTR_ERR_OR_ZERO(membase);
- data->uart.port.irq = mcb_get_irq(mdev);
+ num_ports = get_num_ports(mdev, membase);
- data->uart.port.membase = devm_ioremap_resource(&mdev->dev, mem);
- if (IS_ERR(data->uart.port.membase))
- return PTR_ERR_OR_ZERO(data->uart.port.membase);
+ dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n",
+ mdev->id, num_ports);
- data->uart.port.mapbase = (unsigned long) mem->start;
- data->uart.port.iobase = data->uart.port.mapbase;
+ if (num_ports == 0 || num_ports > 4) {
+ dev_err(&mdev->dev, "unexpected number of ports: %u\n",
+ num_ports);
+ return -ENODEV;
+ }
- /* ok, register the port */
- data->line = serial8250_register_8250_port(&data->uart);
- if (data->line < 0)
- return data->line;
+ data = devm_kcalloc(&mdev->dev, num_ports,
+ sizeof(struct serial_8250_men_mcb_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- dev_info(&mdev->dev, "found 16Z125 UART: ttyS%d\n", data->line);
+ mcb_set_drvdata(mdev, data);
+
+ for (i = 0; i < num_ports; i++) {
+ data[i].uart.port.dev = mdev->dma_dev;
+ spin_lock_init(&data[i].uart.port.lock);
+
+ data[i].uart.port.type = PORT_16550;
+ data[i].uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ
+ | UPF_FIXED_TYPE;
+ data[i].uart.port.iotype = UPIO_MEM;
+ data[i].uart.port.uartclk = men_lookup_uartclk(mdev);
+ data[i].uart.port.regshift = 0;
+ data[i].uart.port.irq = mcb_get_irq(mdev);
+ data[i].uart.port.membase = membase;
+ data[i].uart.port.fifosize = 60;
+ data[i].uart.port.mapbase = (unsigned long) mem->start
+ + i * MEN_UART_MEM_SIZE;
+ data[i].uart.port.iobase = data[i].uart.port.mapbase;
+
+ /* ok, register the port */
+ data[i].line = serial8250_register_8250_port(&data[i].uart);
+ if (data[i].line < 0) {
+ dev_err(&mdev->dev, "unable to register UART port\n");
+ return data[i].line;
+ }
+ dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data[i].line);
+ }
return 0;
}
static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
{
+ unsigned int num_ports, i;
struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
- if (data)
- serial8250_unregister_port(data->line);
+ if (!data)
+ return;
+
+ num_ports = get_num_ports(mdev, data[0].uart.port.membase);
+ if (num_ports < 0 || num_ports > 4) {
+ dev_err(&mdev->dev, "error retrieving number of ports!\n");
+ return;
+ }
+
+ for (i = 0; i < num_ports; i++)
+ serial8250_unregister_port(data[i].line);
}
static const struct mcb_device_id serial_8250_men_mcb_ids[] = {
- { .device = 0x7d },
+ { .device = MEN_UART_ID_Z025 },
+ { .device = MEN_UART_ID_Z057 },
+ { .device = MEN_UART_ID_Z125 },
{ }
};
MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids);
@@ -113,6 +168,8 @@ static struct mcb_driver mcb_driver = {
module_mcb_driver(mcb_driver);
MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MEN 16z125 8250 UART driver");
+MODULE_DESCRIPTION("MEN 8250 UART driver");
MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
MODULE_ALIAS("mcb:16z125");
+MODULE_ALIAS("mcb:16z025");
+MODULE_ALIAS("mcb:16z057");
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index 160b8906d9b9..9835b1c1cbe1 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -316,6 +316,7 @@ static const struct of_device_id of_platform_serial_table[] = {
{ .compatible = "mrvl,mmp-uart",
.data = (void *)PORT_XSCALE, },
{ .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
+ { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, of_platform_serial_table);
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 57f6eba47f44..624b501fd253 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -114,6 +114,7 @@ struct omap8250_priv {
struct uart_8250_dma omap8250_dma;
spinlock_t rx_dma_lock;
bool rx_dma_broken;
+ bool throttled;
};
#ifdef CONFIG_SERIAL_8250_DMA
@@ -692,6 +693,7 @@ static void omap_8250_shutdown(struct uart_port *port)
static void omap_8250_throttle(struct uart_port *port)
{
+ struct omap8250_priv *priv = port->private_data;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
@@ -700,6 +702,7 @@ static void omap_8250_throttle(struct uart_port *port)
spin_lock_irqsave(&port->lock, flags);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
serial_out(up, UART_IER, up->ier);
+ priv->throttled = true;
spin_unlock_irqrestore(&port->lock, flags);
pm_runtime_mark_last_busy(port->dev);
@@ -738,12 +741,16 @@ static int omap_8250_rs485_config(struct uart_port *port,
static void omap_8250_unthrottle(struct uart_port *port)
{
+ struct omap8250_priv *priv = port->private_data;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
pm_runtime_get_sync(port->dev);
spin_lock_irqsave(&port->lock, flags);
+ priv->throttled = false;
+ if (up->dma)
+ up->dma->rx_dma(up);
up->ier |= UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&port->lock, flags);
@@ -788,6 +795,7 @@ unlock:
static void __dma_rx_complete(void *param)
{
struct uart_8250_port *p = param;
+ struct omap8250_priv *priv = p->port.private_data;
struct uart_8250_dma *dma = p->dma;
struct dma_tx_state state;
unsigned long flags;
@@ -805,7 +813,8 @@ static void __dma_rx_complete(void *param)
return;
}
__dma_rx_do_complete(p);
- omap_8250_rx_dma(p);
+ if (!priv->throttled)
+ omap_8250_rx_dma(p);
spin_unlock_irqrestore(&p->port.lock, flags);
}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index a93f77ab3da0..3296a05cda2d 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1685,9 +1685,6 @@ pci_wch_ch38x_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
-#define PCI_VENDOR_ID_SUNIX 0x1fd4
-#define PCI_DEVICE_ID_SUNIX_1999 0x1999
-
#define PCIE_VENDOR_ID_WCH 0x1c00
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 1328c7e70108..95833cbc4338 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -47,6 +47,10 @@
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
#define UART_EXAR_DVID 0x8d /* Device identification */
+/* Nuvoton NPCM timeout register */
+#define UART_NPCM_TOR 7
+#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */
+
/*
* Debugging.
*/
@@ -293,6 +297,15 @@ static const struct serial8250_config uart_config[] = {
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
.flags = UART_CAP_FIFO,
},
+ [PORT_NPCM] = {
+ .name = "Nuvoton 16550",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+ .rxtrig_bytes = {1, 4, 8, 14},
+ .flags = UART_CAP_FIFO,
+ },
};
/* Uart divisor latch read */
@@ -1854,7 +1867,8 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
status = serial_port_in(port, UART_LSR);
- if (status & (UART_LSR_DR | UART_LSR_BI)) {
+ if (status & (UART_LSR_DR | UART_LSR_BI) &&
+ iir & UART_IIR_RDI) {
if (!up->dma || handle_rx_dma(up, iir))
status = serial8250_rx_chars(up, status);
}
@@ -2140,6 +2154,15 @@ int serial8250_do_startup(struct uart_port *port)
UART_DA830_PWREMU_MGMT_FREE);
}
+ if (port->type == PORT_NPCM) {
+ /*
+ * Nuvoton calls the scratch register 'UART_TOR' (timeout
+ * register). Enable it, and set TIOC (timeout interrupt
+ * comparator) to be 0x20 for correct operation.
+ */
+ serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
+ }
+
#ifdef CONFIG_SERIAL_8250_RSA
/*
* If this is an RSA port, see if we can kick it up to t