diff options
30 files changed, 641 insertions, 143 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-aspeed-vuart b/Documentation/ABI/stable/sysfs-driver-aspeed-vuart new file mode 100644 index 000000000000..8062953ce77b --- /dev/null +++ b/Documentation/ABI/stable/sysfs-driver-aspeed-vuart @@ -0,0 +1,15 @@ +What: /sys/bus/platform/drivers/aspeed-vuart/*/lpc_address +Date: April 2017 +Contact: Jeremy Kerr <jk@ozlabs.org> +Description: Configures which IO port the host side of the UART + will appear on the host <-> BMC LPC bus. +Users: OpenBMC. Proposed changes should be mailed to + openbmc@lists.ozlabs.org + +What: /sys/bus/platform/drivers/aspeed-vuart*/sirq +Date: April 2017 +Contact: Jeremy Kerr <jk@ozlabs.org> +Description: Configures which interrupt number the host side of + the UART will appear on the host <-> BMC LPC bus. +Users: OpenBMC. Proposed changes should be mailed to + openbmc@lists.ozlabs.org diff --git a/Documentation/devicetree/bindings/serial/8250.txt b/Documentation/devicetree/bindings/serial/8250.txt index 10276a46ecef..419ff6c0a47f 100644 --- a/Documentation/devicetree/bindings/serial/8250.txt +++ b/Documentation/devicetree/bindings/serial/8250.txt @@ -20,6 +20,8 @@ Required properties: - "fsl,16550-FIFO64" - "fsl,ns16550" - "ti,da830-uart" + - "aspeed,ast2400-vuart" + - "aspeed,ast2500-vuart" - "serial" if the port type is unknown. - reg : offset and length of the register set for the device. - interrupts : should contain uart interrupt. @@ -45,6 +47,7 @@ Optional properties: property. - tx-threshold: Specify the TX FIFO low water indication for parts with programmable TX FIFO thresholds. +- resets : phandle + reset specifier pairs Note: * fsl,ns16550: diff --git a/Documentation/serial/n_gsm.txt b/Documentation/serial/n_gsm.txt index a5d91126a8f7..875361bb7cb4 100644 --- a/Documentation/serial/n_gsm.txt +++ b/Documentation/serial/n_gsm.txt @@ -77,6 +77,13 @@ for example, it's possible : 6- first close all virtual ports before closing the physical port. +Note that after closing the physical port the modem is still in multiplexing +mode. This may prevent a successful re-opening of the port later. To avoid +this situation either reset the modem if your hardware allows that or send +a disconnect command frame manually before initializing the multiplexing mode +for the second time. The byte sequence for the disconnect command frame is: +0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9. + Additional Documentation ------------------------ More practical details on the protocol and how it's supported by industrial diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index f02becdb3e33..8689279afdf1 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ tty_buffer.o tty_port.o tty_mutex.o \ - tty_ldsem.o tty_baudrate.o tty_jobctrl.o + tty_ldsem.o tty_baudrate.o tty_jobctrl.o \ + n_null.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o obj-$(CONFIG_AUDIT) += tty_audit.o diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 99bb875178d7..423e28ec27fb 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1242,8 +1242,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) free_irq(irq, hvcsd); return; } else if (hvcsd->port.count < 0) { - printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" - " is missmanaged.\n", + printk(KERN_ERR "HVCS: vty-server@%X open_count: %d is mismanaged.\n", hvcsd->vdev->unit_address, hvcsd->port.count); } diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 2667a205a5ab..363a8ca824ad 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2015,6 +2015,33 @@ static void gsm_error(struct gsm_mux *gsm, gsm->io_error++; } +static int gsm_disconnect(struct gsm_mux *gsm) +{ + struct gsm_dlci *dlci = gsm->dlci[0]; + struct gsm_control *gc; + + if (!dlci) + return 0; + + /* In theory disconnecting DLCI 0 is sufficient but for some + modems this is apparently not the case. */ + gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); + if (gc) + gsm_control_wait(gsm, gc); + + del_timer_sync(&gsm->t2_timer); + /* Now we are sure T2 has stopped */ + + gsm_dlci_begin_close(dlci); + wait_event_interruptible(gsm->event, + dlci->state == DLCI_CLOSED); + + if (signal_pending(current)) + return -EINTR; + + return 0; +} + /** * gsm_cleanup_mux - generic GSM protocol cleanup * @gsm: our mux @@ -2029,7 +2056,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm) int i; struct gsm_dlci *dlci = gsm->dlci[0]; struct gsm_msg *txq, *ntxq; - struct gsm_control *gc; gsm->dead = 1; @@ -2045,21 +2071,11 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm) if (i == MAX_MUX) return; - /* In theory disconnecting DLCI 0 is sufficient but for some - modems this is apparently not the case. */ - if (dlci) { - gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); - if (gc) - gsm_control_wait(gsm, gc); - } del_timer_sync(&gsm->t2_timer); /* Now we are sure T2 has stopped */ - if (dlci) { + if (dlci) dlci->dead = 1; - gsm_dlci_begin_close(dlci); - wait_event_interruptible(gsm->event, - dlci->state == DLCI_CLOSED); - } + /* Free up any link layer users */ mutex_lock(&gsm->mutex); for (i = 0; i < NUM_DLCI; i++) @@ -2519,12 +2535,12 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm, */ if (need_close || need_restart) { - gsm_dlci_begin_close(gsm->dlci[0]); - /* This will timeout if the link is down due to N2 expiring */ - wait_event_interruptible(gsm->event, - gsm->dlci[0]->state == DLCI_CLOSED); - if (signal_pending(current)) - return -EINTR; + int ret; + + ret = gsm_disconnect(gsm); + + if (ret) + return ret; } if (need_restart) gsm_cleanup_mux(gsm); diff --git a/drivers/tty/n_null.c b/drivers/tty/n_null.c new file mode 100644 index 000000000000..d63261c36e42 --- /dev/null +++ b/drivers/tty/n_null.c @@ -0,0 +1,80 @@ +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/tty.h> +#include <linux/module.h> + +/* + * n_null.c - Null line discipline used in the failure path + * + * Copyright (C) Intel 2017 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +static int n_null_open(struct tty_struct *tty) +{ + return 0; +} + +static void n_null_close(struct tty_struct *tty) +{ +} + +static ssize_t n_null_read(struct tty_struct *tty, struct file *file, + unsigned char __user * buf, size_t nr) +{ + return -EOPNOTSUPP; +} + +static ssize_t n_null_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) +{ + return -EOPNOTSUPP; +} + +static void n_null_receivebuf(struct tty_struct *tty, + const unsigned char *cp, char *fp, + int cnt) +{ +} + +static struct tty_ldisc_ops null_ldisc = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "n_null", + .open = n_null_open, + .close = n_null_close, + .read = n_null_read, + .write = n_null_write, + .receive_buf = n_null_receivebuf +}; + +static int __init n_null_init(void) +{ + BUG_ON(tty_register_ldisc(N_NULL, &null_ldisc)); + return 0; +} + +static void __exit n_null_exit(void) +{ + tty_unregister_ldisc(N_NULL); +} + +module_init(n_null_init); +module_exit(n_null_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alan Cox"); +MODULE_ALIAS_LDISC(N_NULL); +MODULE_DESCRIPTION("Null ldisc driver"); diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index d0a021c93986..302018d67efa 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -148,7 +148,7 @@ static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigne /* tty_set_termios() return not checked as it is always 0 */ tty_set_termios(tty, &ktermios); - return speed; + return ktermios.c_ospeed; } static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index ce8d4ffcc425..b2bdc35f7495 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -81,6 +81,9 @@ struct serial8250_config { #define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ #define UART_CAP_RPM (1 << 15) /* Runtime PM is active while idle */ #define UART_CAP_IRDA (1 << 16) /* UART supports IrDA line discipline */ +#define UART_CAP_MINI (1 << 17) /* Mini UART on BCM283X family lacks: + * STOP PARITY EPAR SPAR WLEN5 WLEN6 + */ #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c new file mode 100644 index 000000000000..822be4906763 --- /dev/null +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c @@ -0,0 +1,323 @@ +/* + * Serial Port driver for Aspeed VUART device + * + * Copyright (C) 2016 Jeremy Kerr <jk@ozlabs.org>, IBM Corp. + * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. + * + * 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. + */ +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/clk.h> + +#include "8250.h" + +#define ASPEED_VUART_GCRA 0x20 +#define ASPEED_VUART_GCRA_VUART_EN BIT(0) +#define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5) +#define ASPEED_VUART_GCRB 0x24 +#define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4) +#define ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT 4 +#define ASPEED_VUART_ADDRL 0x28 +#define ASPEED_VUART_ADDRH 0x2c + +struct aspeed_vuart { + struct device *dev; + void __iomem *regs; + struct clk *clk; + int line; +}; + +/* + * The VUART is basically two UART 'front ends' connected by their FIFO + * (no actual serial line in between). One is on the BMC side (management + * controller) and one is on the host CPU side. + * + * It allows the BMC to provide to the host a "UART" that pipes into + * the BMC itself and can then be turned by the BMC into a network console + * of some sort for example. + * + * This driver is for the BMC side. The sysfs files allow the BMC + * userspace which owns the system configuration policy, to specify + * at what IO port and interrupt number the host side will appear + * to the host on the Host <-> BMC LPC bus. It could be different on a + * different system (though most of them use 3f8/4). + */ + +static ssize_t lpc_address_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aspeed_vuart *vuart = dev_get_drvdata(dev); + u16 addr; + + addr = (readb(vuart->regs + ASPEED_VUART_ADDRH) << 8) | + (readb(vuart->regs + ASPEED_VUART_ADDRL)); + + return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr); +} + +static ssize_t lpc_address_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aspeed_vuart *vuart = dev_get_drvdata(dev); + unsigned long val; + int err; + + err = kstrtoul(buf, 0, &val); + if (err) + return err; + + writeb(val >> 8, vuart->regs + ASPEED_VUART_ADDRH); + writeb(val >> 0, vuart->regs + ASPEED_VUART_ADDRL); + + return count; +} + +static DEVICE_ATTR_RW(lpc_address); + +static ssize_t sirq_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aspeed_vuart *vuart = dev_get_drvdata(dev); + u8 reg; + + reg = readb(vuart->regs + ASPEED_VUART_GCRB); + reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK; + reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT; + + return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg); +} + +static ssize_t sirq_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aspeed_vuart *vuart = dev_get_drvdata(dev); + unsigned long val; + int err; + u8 reg; + + err = kstrtoul(buf, 0, &val); + if (err) + return err; + + val <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT; + val &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK; + + reg = readb(vuart->regs + ASPEED_VUART_GCRB); + reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK; + reg |= val; + writeb(reg, vuart->regs + ASPEED_VUART_GCRB); + + return count; +} + +static DEVICE_ATTR_RW(sirq); + +static struct attribute *aspeed_vuart_attrs[] = { + &dev_attr_sirq.attr, + &dev_attr_lpc_address.attr, + NULL, +}; + +static const struct attribute_group aspeed_vuart_attr_group = { + .attrs = aspeed_vuart_attrs, +}; + +static void aspeed_vuart_set_enabled(struct aspeed_vuart *vuart, bool enabled) +{ + u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA); + + if (enabled) + reg |= ASPEED_VUART_GCRA_VUART_EN; + else + reg &= ~ASPEED_VUART_GCRA_VUART_EN; + + writeb(reg, vuart->regs + ASPEED_VUART_GCRA); +} + +static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart, + bool discard) +{ + u8 reg; + + reg = readb(vuart->regs + ASPEED_VUART_GCRA); + + /* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */ + if (!discard) + reg |= ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD; + else + reg &= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD; + + writeb(reg, vuart->regs + ASPEED_VUART_GCRA); +} + +static int aspeed_vuart_startup(struct uart_port *uart_port) +{ + struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port); + struct aspeed_vuart *vuart = uart_8250_port->port.private_data; + int rc; + + rc = serial8250_do_startup(uart_port); + if (rc) + return rc; + + aspeed_vuart_set_host_tx_discard(vuart, false); + + return 0; +} + +static void aspeed_vuart_shutdown(struct uart_port *uart_port) +{ + struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port); + struct aspeed_vuart *vuart = uart_8250_port->port.private_data; + + aspeed_vuart_set_host_tx_discard(vuart, true); + + serial8250_do_shutdown(uart_port); +} + +static int aspeed_vuart_probe(struct platform_device *pdev) +{ + struct uart_8250_port port; + struct aspeed_vuart *vuart; + struct device_node *np; + struct resource *res; + u32 clk, prop; + int rc; + + np = pdev->dev.of_node; + + vuart = devm_kzalloc(&pdev->dev, sizeof(*vuart), GFP_KERNEL); + if (!vuart) + return -ENOMEM; + + vuart->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + vuart->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(vuart->regs)) + return PTR_ERR(vuart->regs); + + memset(&port, 0, sizeof(port)); + port.port.private_data = vuart; + port.port.membase = vuart->regs; + port.port.mapbase = res->start; + port.port.mapsize = resource_size(res); + port.port.startup = aspeed_vuart_startup; + port.port.shutdown = aspeed_vuart_shutdown; + port.port.dev = &pdev->dev; + + rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); + if (rc < 0) + return rc; + + if (of_property_read_u32(np, "clock-frequency", &clk)) { + vuart->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(vuart->clk)) { + dev_warn(&pdev->dev, + "clk or clock-frequency not defined\n"); + return PTR_ERR(vuart->clk); + } + + rc = clk_prepare_enable(vuart->clk); + if (rc < 0) + return rc; + + clk = clk_get_rate(vuart->clk); + } + + /* If current-speed was set, then try not to change it. */ + if (of_property_read_u32(np, "current-speed", &prop) == 0) + port.port.custom_divisor = clk / (16 * prop); + + /* Check for shifted address mapping */ + if (of_property_read_u32(np, "reg-offset", &prop) == 0) + port.port.mapbase += prop; + + /* Check for registers offset within the devices address range */ + if (of_property_read_u32(np, "reg-shift", &prop) == 0) + port.port.regshift = prop; + + /* Check for fifo size */ + if (of_property_read_u32(np, "fifo-size", &prop) == 0) + port.port.fifosize = prop; + + /* Check for a fixed line number */ + rc = of_alias_get_id(np, "serial"); + if (rc >= 0) + port.port.line = rc; + + port.port.irq = irq_of_parse_and_map(np, 0); + port.port.irqflags = IRQF_SHARED; + port.port.iotype = UPIO_MEM; + port.port.type = PORT_16550A; + port.port.uartclk = clk; + port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF + | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST; + + if (of_property_read_bool(np, "no-loopback-test")) + port.port.flags |= UPF_SKIP_TEST; + + if (port.port.fifosize) + port.capabilities = UART_CAP_FIFO; + + if (of_property_read_bool(np, "auto-flow-control")) + port.capabilities |= UART_CAP_AFE; + + rc = serial8250_register_8250_port(&port); + if (rc < 0) + goto err_clk_disable; + + vuart->line = rc; + + aspeed_vuart_set_enabled(vuart, true); + aspeed_vuart_set_host_tx_discard(vuart, true); + platform_set_drvdata(pdev, vuart); + + return 0; + +err_clk_disable: + clk_disable_unprepare(vuart->clk); + irq_dispose_mapping(port.port.irq); + return rc; +} + +static int aspeed_vuart_remove(struct platform_device *pdev) +{ + struct aspeed_vuart *vuart = platform_get_drvdata(pdev); + + aspeed_vuart_set_enabled(vuart, false); + serial8250_unregister_port(vuart->line); + sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); + clk_disable_unprepare(vuart->clk); + + return 0; +} + +static const struct of_device_id aspeed_vuart_table[] = { + { .compatible = "aspeed,ast2400-vuart" }, + { .compatible = "aspeed,ast2500-vuart" }, + { }, +}; + +static struct platform_driver aspeed_vuart_driver = { + .driver = { + .name = "aspeed-vuart", + .of_match_table = aspeed_vuart_table, + }, + .probe = aspeed_vuart_probe, + .remove = aspeed_vuart_remove, +}; + +module_platform_driver(aspeed_vuart_driver); + +MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Driver for Aspeed VUART device"); diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index e10f1244409b..a23c7da42ea8 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -39,7 +39,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) /* initialize data */ spin_lock_init(&data->uart.port.lock); - data->uart.capabilities = UART_CAP_FIFO; + data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI; data->uart.port.dev = &pdev->dev; data->uart.port.regshift = 2; data->uart.port.type = PORT_16550; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 1270ff163f63..0a20f7185094 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -109,7 +109,6 @@ pci_fastcom335_setup(struct exar8250 *priv, struct pci_dev *pcidev, u8 __iomem *p; int err; - port->port.flags |= UPF_EXAR_EFR; port->port.uartclk = baud * 16; err = default_setup(priv, pcidev, idx, offset, port); @@ -177,13 +176,13 @@ static void setup_gpio(u8 __iomem *p) writeb(0x00, p + UART_EXAR_MPIOLVL_7_0); writeb(0x00, p + UART_EXAR_MPIO3T_7_0); writeb(0x00, p + UART_EXAR_MPIOINV_7_0); - writeb(0x00, p + UART_EXAR_MPIOSEL_7_0); + writeb(0xff, p + UART_EXAR_MPIOSEL_7_0); writeb(0x00, p + UART_EXAR_MPIOOD_7_0); writeb(0x00, p + UART_EXAR_MPIOINT_15_8); writeb(0x00, p + UART_EXAR_MPIOLVL_15_8); writeb(0x00, p + UART_EXAR_MPIO3T_15_8); writeb(0x00, p + UART_EXAR_MPIOINV_15_8); - writeb(0x00, p + UART_EXAR_MPIOSEL_15_8); + writeb(0xff, p + UART_EXAR_MPIOSEL_15_8); writeb(0x00, p + UART_EXAR_MPIOOD_15_8); } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 1cbadafc6889..0cf95fddccfc 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -19,11 +19,13 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/clk.h> +#include <linux/reset.h> #include "8250.h" struct of_serial_info { struct clk *clk; + struct reset_control *rst; int type; int line; }; @@ -132,6 +134,13 @@ static int of_platform_serial_setup(struct platform_device *ofdev, } } + info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL); + if (IS_ERR(info->rst)) + goto out; + ret = reset_control_deassert(info->rst); + if (ret) + goto out; + port->type = type; port->uartclk = clk; port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP @@ -229,6 +238,7 @@ static int of_platform_serial_remove(struct platform_device *ofdev) serial8250_unregister_port(info->line); + reset_control_assert(info->rst); if (info->clk) clk_disable_unprepare(info->clk); kfree(info); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index e7e64913a748..d81bac98d190 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -613,6 +613,10 @@ static int omap_8250_startup(struct uart_port *port) up->lsr_saved_flags = 0; up->msr_saved_flags = 0; + /* Disable DMA for console UART */ + if (uart_console(port)) + up->dma = NULL; + if (up->dma) { ret = serial8250_request_dma(up); if (ret) { diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 68fd045a7025..4c620bedfbf4 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2228,7 +2228,7 @@ int serial8250_do_startup(struct uart_port *port) } } - if (port->irq) { + if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) { unsigned char iir1; /* * Test for UARTs that do not reassert THRE when the @@ -2585,6 +2585,12 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, unsigned long flags; unsigned int baud, quot, frac = 0; + if (up->capabilities & UART_CAP_MINI) { + termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); + if ((termios->c_cflag & CSIZE) == CS5 || + (termios->c_cflag & CSIZE) == CS6) + termios->c_cflag = (termios->c_cflag & ~CSIZE) | CS7; + } cval = serial8250_compute_lcr(up, termios->c_cflag); baud = serial8250_get_baud_rate(port, termios, old); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 0e3f529d50e9..a1161ec0256f 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -224,6 +224,16 @@ config SERIAL_8250_ACCENT To compile this driver as a module, choose M here: the module will be called 8250_accent. +config SERIAL_8250_ASPEED_VUART + tristate "Aspeed Virtual UART" + depends on SERIAL_8250 + depends on OF + help + If you want to use the virtual UART (VUART) device on Aspeed + BMC platforms, enable this option. This enables the 16550A- + compatible device on the local LPC bus, giving a UART device + with no physical RS232 connections. + config SERIAL_8250_BOCA tristate "Support Boca cards" depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 2f30f9ecdb1b..a44a99a3e623 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_SERIAL_8250_EXAR) += 8250_exar.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index f2f251075109..24180adb1cbb 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -697,6 +697,7 @@ static struct console amba_console = { #define AMBA_CONSOLE NULL #endif +static DEFINE_MUTEX(amba_reg_lock); static struct uart_driver amba_reg = { .owner = THIS_MODULE, .driver_name = "ttyAM", @@ -749,6 +750,19 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id) amba_ports[i] = uap; amba_set_drvdata(dev, uap); + + mutex_lock(&amba_reg_lock); + if (!amba_reg.state) { + ret = uart_register_driver(&amba_reg); + if (ret < 0) { + mutex_unlock(&amba_reg_lock); + dev_err(uap->port.dev, + "Failed to register AMBA-PL010 driver\n"); + return ret; + } + } + mutex_unlock(&amba_reg_lock); + ret = uart_add_one_port(&amba_reg, &uap->port); if (ret) amba_ports[i] = NULL; @@ -760,12 +774,18 @@ static int pl010_remove(struct amba_device *dev) { struct uart_amba_port *uap = amba_get_drvdata(dev); int i; + bool busy = false; uart_remove_one_port(&amba_reg, &uap->port); for (i = 0; i < ARRAY_SIZE(amba_ports); i++) if (amba_ports[i] == uap) amba_ports[i] = NULL; + else if (amba_ports[i]) + busy = true; + + if (!busy) + uart_unregister_driver(&amba_reg); return 0; } @@ -816,23 +836,14 @@ static struct amba_driver pl010_driver = { static int __init pl010_init(void) { - int ret; - printk(KERN_INFO "Serial: AMBA driver\n"); - ret = uart_register_driver(&amba_reg); - if (ret == 0) { - ret = amba_driver_register(&pl010_driver); - if (ret) - uart_unregister_driver(&amba_reg); - } - return ret; + return amba_driver_register(&pl010_driver); } static void __exit pl010_exit(void) { amba_driver_unregister(&pl010_driver); - uart_unregister_driver(&amba_reg); } module_init(pl010_init); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index c355ac9abafc..d25f044158ff 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -46,6 +46,7 @@ #include <linux/err.h> #include <linux/irq.h> #include <linux/suspend.h> +#include <linux/mm.h> #include <asm/io.h> #include <asm/ioctls.h> @@ -959,7 +960,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port) sg_set_page(&atmel_port->sg_tx, virt_to_page(port->state->xmit.buf), UART_XMIT_SIZE, - (unsigned long)port->state->xmit.buf & ~PAGE_MASK); + offset_in_page(port->state->xmit.buf)); nent = dma_map_sg(port->dev, &atmel_port->sg_tx, 1, @@ -1141,7 +1142,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port) sg_set_page(&atmel_port->sg_rx, virt_to_page(ring->buf), sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE, - (unsigned long)ring->buf & ~PAGE_MASK); + offset_in_page(ring->buf)); nent = dma_map_sg(port->dev, &atmel_port->sg_rx, 1, diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index bbefddd92bfe..92606b1e55bd 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1340,29 +1340,13 @@ static int imx_startup(struct uart_port *port) 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. + * 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); - } + imx_disable_rx_int(sport); + start_rx_dma(sport); } spin_unlock_irqrestore(&sport->port.lock, flags); diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 60f16795d16b..c0e34dabadd8 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -286,7 +286,7 @@ static int meson_uart_startup(struct uart_port *port) writel(val, port->membase + AML_UART_MISC); ret = request_irq(port->irq, meson_uart_interrupt, 0, - meson_uart_type(port), port); + port->name, port); return ret; } @@ -298,8 +298,6 @@ static void meson_uart_change_speed(struct uart_port *port, unsigned long baud) while (!meson_uart_tx_empty(port)) cpu_relax(); - val = readl(port->membase + AML_UART_REG5); - val &= ~AML_UART_BAUD_MASK; if (port->uartclk == 24000000) { val = ((port->uartclk / 3) / baud) - 1; val |= AML_UART_BAUD_XTAL; @@ -355,7 +353,7 @@ static void meson_uart_set_termios(struct uart_port *port, if (cflags & CSTOPB) val |= AML_UART_STOP_BIN_2SB; else - val &= ~AML_UART_STOP_BIN_1SB; + val |= AML_UART_STOP_BIN_1SB; if (cflags & CRTSCTS) val &= ~AML_UART_TWO_WIRE_EN; @@ -395,51 +393,25 @@ static int meson_uart_verify_port(struct uart_port *port, return ret; } -static int meson_uart_res_size(struct uart_port *port) -{ - struct platform_device *pdev = to_platform_device(port->dev); - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(port->dev, "cannot obtain I/O memory region"); - return -ENODEV; - } - - return resource_size(res); -} - static void meson_uart_release_port(struct uart_port *port) { - int size = meson_uart_res_size(port); - - if (port->flags & UPF_IOREMAP) { - devm_release_mem_region(port->dev, port->mapbase, size); - devm_iounmap(port->dev, port->membase); - port->membase = NULL; - } + devm_iounmap(port->dev, port->membase); + port->membase = NULL; + devm_release_mem_region(port->dev, port->mapbase, port->mapsize); } static int meson_uart_request_port(struct uart_port *port) { - int size = meson_uart_res_size(port); - - if (size < 0) - return size; - - if (!devm_request_mem_region(port->dev, port->mapbase, size, + if (!devm_request_mem_region(port->dev, port->mapbase, port->mapsize, dev_name(port->dev))) { dev_err(port->dev, "Memory region busy\n"); return -EBUSY; } - if (port->flags & UPF_IOREMAP) { - port->membase = devm_ioremap_nocache(port->dev, - port->mapbase, - size); - if (port->membase == NULL) - return -ENOMEM; - } + port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->mapsize); + if (!port->membase) + return -ENOMEM; return 0; } @@ -470,6 +442,14 @@ static struct uart_ops meson_uart_ops = { }; #ifdef CONFIG_SERIAL_MESON_CONSOLE +static void meson_uart_enable_tx_engine(struct uart_port *port) +{ + u32 val; + + val = readl(port->membase + AML_UART_CONTROL); + val |= AML_UART_TX_EN; + writel(val, port->membase + AML_UART_CONTROL); +} static void meson_console_putchar(struct uart_port *port, int ch) { @@ -499,7 +479,6 @@ static void meson_serial_port_write(struct uart_port *port, const char *s, } val = readl(port->membase + AML_UART_CONTROL); - val |= AML_UART_TX_EN; tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN); writel(tmp, port->membase + AML_UART_CONTROL); @@ -538,6 +517,8 @@ static int meson_serial_console_setup(struct console *co, char *options) if (!port || !port->membase) return -ENODEV; + meson_uart_enable_tx_engine(port); + if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -576,6 +557,7 @@ meson_serial_early_console_setup(struct earlycon_device *device, const char *opt if (!device->port.membase) return -ENODEV; + meson_uart_enable_tx_engine(&device->port); device->con->write = meson_serial_early_console_write; return 0; } @@ -632,8 +614,9 @@ static int meson_uart_probe(struct platform_device *pdev) port->uartclk = clk_get_rate(clk); port->iotype = UPIO_MEM; port->mapbase = res_mem->start; + port->mapsize = resource_size(res_mem); port->irq = res_irq->start; - port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY; + port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY; port->dev = &pdev->dev; port->line = pdev->id; port->type = PORT_MESON; diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 42caccb5e87e..d3796dc26fa9 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -878,8 +878,7 @@ static int dma_handle_rx(struct eg20t_port *priv) sg_dma_len(sg) = priv->trigger_level; sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt), - sg_dma_len(sg), (unsigned long)priv->rx_buf_virt & - ~PAGE_MASK); + sg_dma_len(sg), offset_in_page(priv->rx_buf_virt)); sg_dma_address(sg) = priv->rx_buf_dma; diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index fcf803ffad19..cdd2f942317c 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -884,14 +884,19 @@ static int sccnxp_probe(struct platform_device *pdev) clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { - if (PTR_ERR(clk) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; + ret = PTR_ERR(clk); + if (ret == -EPROBE_DEFER) goto err_out; - } + uartclk = 0; + } else { + clk_prepare_enable(clk); + uartclk = clk_get_rate(clk); + } + + if (!uartclk) { dev_notice(&pdev->dev, "Using default clock frequency\n"); uartclk = s->chip->freq_std; - } else - uartclk = clk_get_rate(clk); + } /* Check input frequency */ if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) { diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 71707e8e6e3f..da5ddfc14778 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1450,8 +1450,7 @@ static struct dma_chan *sci_request_dma_chan(struct uart_port *port, chan = dma_request_slave_channel(port->dev, dir == DMA_MEM_TO_DEV ? "tx" : "rx"); if (!chan) { - dev_warn(port->dev, - "dma_request_slave_channel_compat failed\n"); + dev_warn(port->dev, "dma_request_slave_channel failed\n"); return NULL; } @@ -1558,7 +1557,16 @@ static void sci_free_dma(struct uart_port *port) if (s->chan_rx) sci_rx_dma_release(s, false); } -#else + +static void sci_flush_buffer(struct uart_port *port) +{ + /* + * In uart_flush_buffer(), the xmit circular buffer has just been + * cleared, so we have to reset tx_dma_len accordingly. + */ + to_sci_port(port)->tx_dma_len = 0; +} +#else /* !CONFIG_SERIAL_SH_SCI_DMA */ static inline void sci_request_dma(struct uart_port *port) { } @@ -1566,7 +1574,9 @@ static inline void sci_request_dma(struct uart_port *port) static inline void sci_free_dma(struct uart_port *port) { } -#endif + +#define sci_flush_buffer NULL +#endif /* !CONFIG_SERIAL_SH_SCI_DMA */ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) { @@ -2581,6 +2591,7 @@ static const struct uart_ops sci_uart_ops = { .break_ctl = sci_break_ctl, .startup = sci_startup, .shutdown = sci_shutdown, + .flush_buffer = sci_flush_buffer, .set_termios = sci_set_termios, .pm = sci_pm, .type = sci_type, @@ -2950,6 +2961,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev) static const char banner[] __initconst = "SuperH (H)SCI(F) driver initialized"; +static DEFINE_MUTEX(sci_uart_registration_lock); static struct uart_driver sci_uart_driver = { .owner = THIS_MODULE, .driver_name = "sci", @@ -3078,6 +3090,16 @@ static int sci_probe_single(struct platform_device *dev, return -EINVAL; } + mutex_lock(&sci_uart_registration_lock); + if (!sci_uart_driver.state) { + ret = uart_register_driver(&sci_uart_driver); + if (ret) { + mutex_unlock(&sci_uart_registration_lock); + return ret; + } + } + mutex_unlock(&sci_uart_registration_lock); + ret = sci_init_single(dev, sciport, index, p, false); if (ret) return ret; @@ -3201,24 +3223,17 @@ static struct platform_driver sci_driver = { static int __init sci_init(void) { - int ret; - pr_info("%s\n", banner); - ret = uart_register_driver(&sci_uart_driver); - if (likely(ret == 0)) { - ret = platform_driver_register(&sci_driver); - if (unlikely(ret)) - uart_unregister_driver(&sci_uart_driver); - } - - return ret; + return platform_driver_register(&sci_driver); } static void __exit sci_exit(void) { platform_driver_unregister(&sci_driver); - uart_unregister_driver(&sci_uart_driver); + + if (sci_uart_driver.state) + uart_unregister_driver(&sci_uart_driver); } #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index c0539950f8d7..fde55dcdea5a 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -186,6 +186,7 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); * @pclk: APB clock * @baud: Current baud rate * @clk_rate_change_nb: Notifier block for clock changes + * @quirks: Flags for RXBS support. */ struct cdns_uart { struct uart_port *port; @@ -1587,20 +1588,21 @@ static int cdns_uart_probe(struct platform_device *pdev) if (rc) { dev_err(&pdev->dev, "uart_add_one_port() failed; err=%i\n", rc); - goto err_out_notif_unreg; + goto err_out_pm_disable; } return 0; +err_out_pm_disable: + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); err_out_notif_unreg: #ifdef CONFIG_COMMON_CLK clk_notifier_unregister(cdns_uart_data->uartclk, &cdns_uart_data->clk_rate_change_nb); #endif err_out_clk_disable: - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - pm_runtime_dont_use_autosuspend(&pdev->dev); clk_disable_unprepare(cdns_uart_data->uartclk); err_out_clk_dis_pclk: clk_disable_unprepare(cdns_uart_data->pclk); diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index e4603b09863a..4a04567d9aef 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -492,6 +492,29 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) } /** + * tty_ldisc_failto - helper for ldisc failback + * @tty: tty to open the ldisc on + * @ld: ldisc we are trying to fail back to + * + * Helper to try and recover a tty when switching back to the old + * ldisc fails and we need something attached. + */ + +static int tty_ldisc_failto(struct tty_struct *tty, int ld) +{ + struct tty_ldisc *disc = tty_ldisc_get(tty, ld); + int r; + + if (IS_ERR(disc)) + return PTR_ERR(disc); + tty->ldisc = disc; + tty_set_termios_ldisc(tty, ld); + if ((r = tty_ldisc_open(tty, disc)) < 0) + tty_ldisc_put(disc); + return r; +} + +/** * tty_ldisc_restore - helper for tty ldisc change * @tty: tty to recover * @old: previous ldisc @@ -502,9 +525,6 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) { - struct tty_ldisc *new_ldisc; - int r; - /* There is an outstanding reference here so this is safe */ old = tty_ldisc_get(tty, old->ops->num); WARN_ON(IS_ERR(old)); @@ -512,17 +532,13 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) tty_set_termios_ldisc(tty, old->ops->num); if (tty_ldisc_open(tty, old) < 0) { tty_ldisc_put(old); - /* This driver is always present */ - new_ldisc = tty_ldisc_get(tty, N_TTY); - if (IS_ERR(new_ldisc)) - panic("n_tty: get"); - tty->ldisc = new_ldisc; - tty_set_termios_ldisc(tty, N_TTY); - r = tty_ldisc_open(tty, new_ldisc); - if (r < 0) - panic("Couldn't open N_TTY ldisc for " - "%s --- error %d.", - tty_name(tty), r); + /* The traditional behaviour is to fall back to N_TTY, we + want to avoid falling back to N_NULL unless we have no + choice to avoid the risk of breaking anything */ + if (tty_ldisc_failto(tty, N_TTY) < 0 && + tty_ldisc_failto(tty, N_NULL) < 0) + panic("Couldn't open N_NULL ldisc for %s.", + tty_name(tty)); } } diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 8af8d9542663..f4166263bb3a 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1203,8 +1203,7 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ - (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\ - defined(CONFIG_AVR32) + (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\ ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001)) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 64d892f1e5cd..1775500294bb 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -195,6 +195,7 @@ struct uart_port { #define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15)) #define UPF_MAGIC_MULTIPLIER ((__force upf_t) ASYNC_MAGIC_MULTIPLIER /* 16 */ ) +#define UPF_NO_THRE_TEST ((__force upf_t) (1 << 19)) /* Port has hardware-assisted h/w flow control */ #define UPF_AUTO_CTS ((__force upf_t) (1 << 20)) #define UPF_AUTO_RTS ((__force upf_t) (1 << 21)) diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h index 5d59c3ebf459..d2667ecd54ac 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -122,6 +122,9 @@ struct serial_rs485 { #define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logical level for RTS pin after sent*/ #define SER_RS485_RX_DURING_TX (1 << 4) +#define SER_RS485_TERMINATE_BUS (1 << 5) /* Enable bus + termination + (if supported) */ __u32 delay_rts_before_send; /* Delay before send (milliseconds) */ __u32 delay_rts_after_send; /* Delay after send (milliseconds) */ __u32 padding[5]; /* Memory is cheap, new structs diff --git a/include/uapi/linux/tty.h b/include/uapi/linux/tty.h index 01c4410352ff..cf1455396df0 100644 --- a/include/uapi/linux/tty.h +++ b/include/uapi/linux/tty.h @@ -35,5 +35,7 @@ #define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */ #define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */ #define N_NCI 25 /* NFC NCI UART */ +#define N_SPEAKUP 26 /* Speakup communication with synths */ +#define N_NULL 27 /* Null ldisc used for error handling */ #endif /* _UAPI_LINUX_TTY_H */ |