diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-04 18:43:49 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-04 18:43:49 -0700 |
commit | 9abf8acea297b4c65f5fa3206e2b8e468e730e84 (patch) | |
tree | 03e231d7e785e4cf3ae8849b523cebd1660f57fc /drivers/tty | |
parent | ac9053d2dcb9e8c3fa35ce458dfca8fddc141680 (diff) | |
parent | 4f794097797f551917b68797e39f25fcb17d5b3a (diff) |
Merge tag 'tty-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH:
"Here is the big set of tty and serial driver patches for 4.17-rc1
Not all that big really, most are just small fixes and additions to
existing drivers. There's a bunch of work on the imx serial driver
recently for some reason, and a new embedded serial driver added as
well.
Full details are in the shortlog.
All of these have been in the linux-next tree for a while with no
reported issues"
* tag 'tty-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (66 commits)
serial: expose buf_overrun count through proc interface
serial: mvebu-uart: fix tx lost characters
tty: serial: msm_geni_serial: Fix return value check in qcom_geni_serial_probe()
tty: serial: msm_geni_serial: Add serial driver support for GENI based QUP
8250-men-mcb: add support for 16z025 and 16z057
powerpc: Mark the variable earlycon_acpi_spcr_enable maybe_unused
serial: stm32: fix initialization of RS485 mode
ARM: dts: STi: Remove "console=ttyASN" from bootargs for STi boards
vt: change SGR 21 to follow the standards
serdev: Fix typo in serdev_device_alloc
ARM: dts: STi: Fix aliases property name for STi boards
tty: st-asc: Update tty alias
serial: stm32: add support for RS485 hardware control mode
dt-bindings: serial: stm32: add RS485 optional properties
selftests: add devpts selftests
devpts: comment devpts_mntget()
devpts: resolve devpts bind-mounts
devpts: hoist out check for DEVPTS_SUPER_MAGIC
serial: 8250: Add Nuvoton NPCM UART
serial: mxs-auart: disable clks of Alphascale ASM9260
...
Diffstat (limited to 'drivers/tty')
31 files changed, 2367 insertions, 632 deletions
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 the @@ -2462,6 +2485,15 @@ static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up, return quot_16 >> 4; } +/* Nuvoton NPCM UARTs have a custom divisor calculation */ +static unsigned int npcm_get_divisor(struct uart_8250_port *up, + unsigned int baud) +{ + struct uart_port *port = &up->port; + + return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2; +} + static unsigned int serial8250_get_divisor(struct uart_8250_port *up, unsigned int baud, unsigned int *frac) @@ -2482,6 +2514,8 @@ static unsigned int serial8250_get_divisor(struct uart_8250_port *up, quot = 0x8002; else if (up->port.type == PORT_XR17V35X) quot = xr17v35x_get_divisor(up, baud, frac); + else if (up->port.type == PORT_NPCM) + quot = npcm_get_divisor(up, baud); else quot = uart_get_divisor(port, baud); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 16b1496e6105..f005eaf8bc57 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -157,11 +157,12 @@ config SERIAL_8250_CS If unsure, say N. config SERIAL_8250_MEN_MCB - tristate "MEN Z125 UART device support" + tristate "MEN MCB UART device support" depends on MCB && SERIAL_8250 help This enables support for FPGA based UARTs found on many MEN - boards. This driver enables support for the Z125 UARTs. + boards. This driver enables support for the 16z025, 16z057 + and 16z125 UARTs. To compile this driver as a module, chose M here: the module will be called 8250_men_mcb. diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 736720a8d84f..0f058df0b070 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -989,6 +989,21 @@ config SERIAL_MSM_CONSOLE select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON +config SERIAL_QCOM_GENI + tristate "QCOM on-chip GENI based serial port support" + depends on ARCH_QCOM || COMPILE_TEST + depends on QCOM_GENI_SE + select SERIAL_CORE + +config SERIAL_QCOM_GENI_CONSOLE + bool "QCOM GENI Serial Console support" + depends on SERIAL_QCOM_GENI=y + select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON + help + Serial console driver for Qualcomm Technologies Inc's GENI based + QUP hardware. + config SERIAL_VT8500 bool "VIA VT8500 on-chip serial port support" depends on ARCH_VT8500 diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index b30ee2e5d518..daac675612df 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o +obj-$(CONFIG_SERIAL_QCOM_GENI) += qcom_geni_serial.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index b88b05f8e81e..0e487ce091ac 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -109,6 +109,20 @@ static unsigned int altera_uart_get_mctrl(struct uart_port *port) return sigs; } +static void altera_uart_update_ctrl_reg(struct altera_uart *pp) +{ + unsigned short imr = pp->imr; + + /* + * If the device doesn't have an irq, ensure that the irq bits are + * masked out to keep the irq line inactive. + */ + if (!pp->port.irq) + imr &= ALTERA_UART_CONTROL_TRBK_MSK | ALTERA_UART_CONTROL_RTS_MSK; + + altera_uart_writel(&pp->port, imr, ALTERA_UART_CONTROL_REG); +} + static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) { struct altera_uart *pp = container_of(port, struct altera_uart, port); @@ -118,7 +132,7 @@ static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; else pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; - altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); } static void altera_uart_start_tx(struct uart_port *port) @@ -126,7 +140,7 @@ static void altera_uart_start_tx(struct uart_port *port) struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; - altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); } static void altera_uart_stop_tx(struct uart_port *port) @@ -134,7 +148,7 @@ static void altera_uart_stop_tx(struct uart_port *port) struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; - altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); } static void altera_uart_stop_rx(struct uart_port *port) @@ -142,7 +156,7 @@ static void altera_uart_stop_rx(struct uart_port *port) struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; - altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); } static void altera_uart_break_ctl(struct uart_port *port, int break_state) @@ -155,7 +169,7 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state) pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; else pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; - altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); spin_unlock_irqrestore(&port->lock, flags); } @@ -262,7 +276,7 @@ static void altera_uart_tx_chars(struct altera_uart *pp) if (xmit->head == xmit->tail) { pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; - altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); } } @@ -307,27 +321,27 @@ static int altera_uart_startup(struct uart_port *port) { struct altera_uart *pp = container_of(port, struct altera_uart, port); unsigned long flags; - int ret; if (!port->irq) { timer_setup(&pp->tmr, altera_uart_timer, 0); mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port)); - return 0; - } - - ret = request_irq(port->irq, altera_uart_interrupt, 0, - DRV_NAME, port); - if (ret) { - pr_err(DRV_NAME ": unable to attach Altera UART %d " - "interrupt vector=%d\n", port->line, port->irq); - return ret; + } else { + int ret; + + ret = request_irq(port->irq, altera_uart_interrupt, 0, + DRV_NAME, port); + if (ret) { + pr_err(DRV_NAME ": unable to attach Altera UART %d " + "interrupt vector=%d\n", port->line, port->irq); + return ret; + } } spin_lock_irqsave(&port->lock, flags); /* Enable RX interrupts now */ pp->imr = ALTERA_UART_CONTROL_RRDY_MSK; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); spin_unlock_irqrestore(&port->lock, flags); @@ -343,7 +357,7 @@ static void altera_uart_shutdown(struct uart_port *port) /* Disable all interrupts now */ pp->imr = 0; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_update_ctrl_reg(pp); spin_unlock_irqrestore(&port->lock, flags); @@ -432,7 +446,7 @@ static void altera_uart_console_putc(struct uart_port *port, int c) ALTERA_UART_STATUS_TRDY_MSK)) cpu_relax(); - writel(c, port->membase + ALTERA_UART_TXDATA_REG); + altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG); } static void altera_uart_console_write(struct console *co, const char *s, @@ -502,13 +516,13 @@ static int __init altera_uart_earlycon_setup(struct earlycon_device *dev, return -ENODEV; /* Enable RX interrupts now */ - writel(ALTERA_UART_CONTROL_RRDY_MSK, - port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, ALTERA_UART_CONTROL_RRDY_MSK, + ALTERA_UART_CONTROL_REG); if (dev->baud) { unsigned int baudclk = port->uartclk / dev->baud; - writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG); + altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG); } dev->con->write = altera_uart_earlycon_write; diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 2599f9ecccfe..d904a3a345e7 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -593,6 +593,11 @@ static int arc_serial_probe(struct platform_device *pdev) if (dev_id < 0) dev_id = 0; + if (dev_id >= ARRAY_SIZE(arc_uart_ports)) { + dev_err(&pdev->dev, "serial%d out of range\n", dev_id); + return -EINVAL; + } + uart = &arc_uart_ports[dev_id]; port = &uart->port; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 8cf112f2efc3..51e47a63d61a 100644 --- a/drivers/tty/ser |