diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt index 860a9559839a40dffc7ceb273424abe55df9926b..afcfbc34e24340ab006c0cba6c6de7591888aee6 100644 --- a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt @@ -6,10 +6,10 @@ Required properties: - interrupts : Should contain uart interrupt Optional properties: -- fsl,irda-mode : Indicate the uart supports irda mode - fsl,dte-mode : Indicate the uart works in DTE mode. The uart works in DCE mode by default. -- rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt +- rs485-rts-delay, rs485-rts-active-low, rs485-rx-during-tx, + linux,rs485-enabled-at-boot-time: see rs485.txt Please check Documentation/devicetree/bindings/serial/serial.txt for the complete list of generic properties. diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt index 59567b51cf098bfa963fee4283b63e01d226bb31..6bd3f2e93d61d9818bda71c6c328c407b082a884 100644 --- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt @@ -16,7 +16,8 @@ Required properties: Optional properties: - dmas: A list of two dma specifiers, one for each entry in dma-names. - dma-names: should contain "tx" and "rx". -- rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt +- rs485-rts-delay, rs485-rts-active-low, rs485-rx-during-tx, + linux,rs485-enabled-at-boot-time: see rs485.txt Note: Optional properties for DMA support. Write them both or both not. diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt index 02cb7fe59cb776281ec2cdf150ff661fcab9b4ce..c3c6406d5cfe528fb776b8a4edd4eb37b4ff6f2d 100644 --- a/Documentation/devicetree/bindings/serial/ingenic,uart.txt +++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt @@ -1,8 +1,12 @@ * Ingenic SoC UART Required properties: -- compatible : "ingenic,jz4740-uart", "ingenic,jz4760-uart", - "ingenic,jz4775-uart" or "ingenic,jz4780-uart" +- compatible : One of: + - "ingenic,jz4740-uart", + - "ingenic,jz4760-uart", + - "ingenic,jz4770-uart", + - "ingenic,jz4775-uart", + - "ingenic,jz4780-uart". - reg : offset and length of the register set for the device. - interrupts : should contain uart interrupt. - clocks : phandles to the module & baud clocks. diff --git a/Documentation/devicetree/bindings/serial/maxim,max310x.txt b/Documentation/devicetree/bindings/serial/maxim,max310x.txt index 83a919c241b0dbc713288ade747fefef7fa127da..823f77dd79786b0eec26bc71480dbca460d1ed38 100644 --- a/Documentation/devicetree/bindings/serial/maxim,max310x.txt +++ b/Documentation/devicetree/bindings/serial/maxim,max310x.txt @@ -24,13 +24,27 @@ Optional properties: 1 = active low. Example: + +/ { + clocks { + spi_uart_clk: osc_max14830 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <3686400>; + }; + + }; +}; + +&spi0 { max14830: max14830@0 { compatible = "maxim,max14830"; reg = <0>; - clocks = <&clk20m>; + clocks = <&spi_uart_clk>; clock-names = "osc"; interrupt-parent = <&gpio3>; - interrupts = <7 IRQ_TYPE_EDGE_FALLING>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; gpio-controller; #gpio-cells = <2>; }; +}; diff --git a/Documentation/devicetree/bindings/serial/mvebu-uart.txt b/Documentation/devicetree/bindings/serial/mvebu-uart.txt index d37fabe17bd1215df697757e6622aac5f798061e..2ae2fee7e023c01375f7fa09b9b21f7f812293c1 100644 --- a/Documentation/devicetree/bindings/serial/mvebu-uart.txt +++ b/Documentation/devicetree/bindings/serial/mvebu-uart.txt @@ -1,13 +1,53 @@ -* Marvell UART : Non standard UART used in some of Marvell EBU SoCs (e.g., Armada-3700) +* Marvell UART : Non standard UART used in some of Marvell EBU SoCs + e.g., Armada-3700. Required properties: -- compatible: "marvell,armada-3700-uart" +- compatible: + - "marvell,armada-3700-uart" for the standard variant of the UART + (32 bytes FIFO, no DMA, level interrupts, 8-bit access to the + FIFO, baudrate limited to 230400). + - "marvell,armada-3700-uart-ext" for the extended variant of the + UART (128 bytes FIFO, DMA, front interrupts, 8-bit or 32-bit + accesses to the FIFO, baudrate unlimited by the dividers). - reg: offset and length of the register set for the device. -- interrupts: device interrupt +- clocks: UART reference clock used to derive the baudrate. If no clock + is provided (possible only with the "marvell,armada-3700-uart" + compatible string for backward compatibility), it will only work + if the baudrate was initialized by the bootloader and no baudrate + change will then be possible. +- interrupts: + - Must contain three elements for the standard variant of the IP + (marvell,armada-3700-uart): "uart-sum", "uart-tx" and "uart-rx", + respectively the UART sum interrupt, the UART TX interrupt and + UART RX interrupt. A corresponding interrupt-names property must + be defined. + - Must contain two elements for the extended variant of the IP + (marvell,armada-3700-uart-ext): "uart-tx" and "uart-rx", + respectively the UART TX interrupt and the UART RX interrupt. A + corresponding interrupts-names property must be defined. + - For backward compatibility reasons, a single element interrupts + property is also supported for the standard variant of the IP, + containing only the UART sum interrupt. This form is deprecated + and should no longer be used. Example: - serial@12000 { + uart0: serial@12000 { compatible = "marvell,armada-3700-uart"; reg = <0x12000 0x200>; - interrupts = <43>; + clocks = <&xtalclk>; + interrupts = + , + , + ; + interrupt-names = "uart-sum", "uart-tx", "uart-rx"; + }; + + uart1: serial@12200 { + compatible = "marvell,armada-3700-uart-ext"; + reg = <0x12200 0x30>; + clocks = <&xtalclk>; + interrupts = + , + ; + interrupt-names = "uart-tx", "uart-rx"; }; diff --git a/Documentation/devicetree/bindings/serial/omap_serial.txt b/Documentation/devicetree/bindings/serial/omap_serial.txt index 43eac675f21f5fd58cda23535facab5b82903957..4b0f05adb22811a99850e36d66be1073259b03c1 100644 --- a/Documentation/devicetree/bindings/serial/omap_serial.txt +++ b/Documentation/devicetree/bindings/serial/omap_serial.txt @@ -20,6 +20,7 @@ Optional properties: node and a DMA channel number. - dma-names : "rx" for receive channel, "tx" for transmit channel. - rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt +- rs485-rts-active-high: drive RTS high when sending (default is low). Example: diff --git a/Documentation/devicetree/bindings/serial/rs485.txt b/Documentation/devicetree/bindings/serial/rs485.txt index b8415936dfdbc59cdf8c6027337603579d3e9403..b7c29f74ebb2e0a3bf9cea65e4dc559ed7e3bb5d 100644 --- a/Documentation/devicetree/bindings/serial/rs485.txt +++ b/Documentation/devicetree/bindings/serial/rs485.txt @@ -12,6 +12,7 @@ Optional properties: * b is the delay between end of data sent and rts signal in milliseconds it corresponds to the delay after sending data and actual release of the line. If this property is not specified, <0 0> is assumed. +- rs485-rts-active-low: drive RTS low when sending (default is high). - linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485 feature at boot time. It can be disabled later with proper ioctl. - rs485-rx-during-tx: empty property that enables the receiving of data even diff --git a/MAINTAINERS b/MAINTAINERS index e262e234d76d47222fc2b65d44fbd80ad3d6d6f0..48c7ff07bfdc4e29cfb3d055d1a2b5431487a468 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13181,6 +13181,11 @@ S: Supported F: drivers/reset/reset-axs10x.c F: Documentation/devicetree/bindings/reset/snps,axs10x-reset.txt +SYNOPSYS DESIGNWARE 8250 UART DRIVER +R: Andy Shevchenko +S: Maintained +F: drivers/tty/serial/8250/8250_dw.c + SYNOPSYS DESIGNWARE APB GPIO DRIVER M: Hoan Tran L: linux-gpio@vger.kernel.org diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index cc2b4d9433ed2ccf85406de35f53f69a58404973..b811442c5ce67249305a0b3e9292016bb1a4a719 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -394,10 +394,14 @@ config GOLDFISH_TTY depends on GOLDFISH select SERIAL_CORE select SERIAL_CORE_CONSOLE - select SERIAL_EARLYCON help Console and system TTY driver for the Goldfish virtual platform. +config GOLDFISH_TTY_EARLY_CONSOLE + bool + default y if GOLDFISH_TTY=y + select SERIAL_EARLYCON + config DA_TTY bool "DA TTY" depends on METAG_DA diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index 7f657bb5113c8ff3500e4fdf3613c4a4e8ac3898..1c1bd0afcd489e5eef35d6c4b32a8d018e1cc25c 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -433,6 +433,7 @@ static int goldfish_tty_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE static void gf_early_console_putchar(struct uart_port *port, int ch) { __raw_writel(ch, port->membase); @@ -456,6 +457,7 @@ static int __init gf_earlycon_setup(struct earlycon_device *device, } OF_EARLYCON_DECLARE(early_gf_tty, "google,goldfish-tty", gf_earlycon_setup); +#endif static const struct of_device_id goldfish_tty_of_match[] = { { .compatible = "google,goldfish-tty", }, diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 015686ff48255fedbf0705111f9abc2afd99e63b..bdd3027ef01b6d4dbfdf9cd40f2923410cd82a8f 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -219,13 +219,9 @@ static struct isi_port isi_ports[PORT_COUNT]; static int WaitTillCardIsFree(unsigned long base) { unsigned int count = 0; - unsigned int a = in_atomic(); /* do we run under spinlock? */ while (!(inw(base + 0xe) & 0x1) && count++ < 100) - if (a) - mdelay(1); - else - msleep(1); + mdelay(1); return !(inw(base + 0xe) & 0x1); } diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 68cbc03aab4b86e49a3f1f8904de52ef91f4b5c3..250a19f042d74ce7bf46c21a15addfb34a193d1a 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1487,8 +1487,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term if (ts->c_iflag & IXANY) xany = 1; - /* Clear the features we don't support */ - ts->c_cflag &= ~CMSPAR; MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany); baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty)); if (baud == -1) @@ -1781,10 +1779,17 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, mode |= MX_STOP1; if (termio->c_cflag & PARENB) { - if (termio->c_cflag & PARODD) - mode |= MX_PARODD; - else - mode |= MX_PAREVEN; + if (termio->c_cflag & PARODD) { + if (termio->c_cflag & CMSPAR) + mode |= MX_PARMARK; + else + mode |= MX_PARODD; + } else { + if (termio->c_cflag & CMSPAR) + mode |= MX_PARSPACE; + else + mode |= MX_PAREVEN; + } } else mode |= MX_PARNONE; diff --git a/drivers/tty/moxa.h b/drivers/tty/moxa.h index 8ce89fd36c7bdffbc9861c920a98c12831fa3d5c..563d2dce80b3cd98e7b18a9179c413ca9ac9b70d 100644 --- a/drivers/tty/moxa.h +++ b/drivers/tty/moxa.h @@ -301,5 +301,7 @@ #define MX_PARNONE 0x00 #define MX_PAREVEN 0x40 #define MX_PARODD 0xC0 +#define MX_PARMARK 0xA0 +#define MX_PARSPACE 0x20 #endif diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 0edf4fcfea238673f13b703320c478e62459803b..3b3af7e0ce1c7730463ef356d9569fe81e4522d7 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1451,6 +1451,10 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) * in which case an opening port goes back to closed and a closing port * is simply put into closed state (any further frames from the other * end will get a DM response) + * + * Some control dlci can stay in ADM mode with other dlci working just + * fine. In that case we can just keep the control dlci open after the + * DLCI_OPENING retries time out. */ static void gsm_dlci_t1(struct timer_list *t) @@ -1464,8 +1468,15 @@ static void gsm_dlci_t1(struct timer_list *t) if (dlci->retries) { gsm_command(dlci->gsm, dlci->addr, SABM|PF); mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); - } else + } else if (!dlci->addr && gsm->control == (DM | PF)) { + if (debug & 8) + pr_info("DLCI %d opening in ADM mode.\n", + dlci->addr); + gsm_dlci_open(dlci); + } else { gsm_dlci_close(dlci); + } + break; case DLCI_CLOSING: dlci->retries--; @@ -1483,8 +1494,8 @@ static void gsm_dlci_t1(struct timer_list *t) * @dlci: DLCI to open * * Commence opening a DLCI from the Linux side. We issue SABM messages - * to the modem which should then reply with a UA, at which point we - * will move into open state. Opening is done asynchronously with retry + * to the modem which should then reply with a UA or ADM, at which point + * we will move into open state. Opening is done asynchronously with retry * running off timers and the responses. */ @@ -2955,7 +2966,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) static void gsmtty_close(struct tty_struct *tty, struct file *filp) { struct gsm_dlci *dlci = tty->driver_data; - struct gsm_mux *gsm; if (dlci == NULL) return; @@ -2964,7 +2974,6 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) mutex_lock(&dlci->mutex); gsm_destroy_network(dlci); mutex_unlock(&dlci->mutex); - gsm = dlci->gsm; if (tty_port_close_start(&dlci->port, tty, filp) == 0) return; gsm_dlci_begin_close(dlci); diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 5a135ed46159150769ff25654c8aa0f9f653c01c..f439c72b9e3c165a7068a7ff26e4fd93f2d5266e 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -19,6 +19,38 @@ static bool is_registered; static DEFINE_IDA(ctrl_ida); +static ssize_t modalias_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int len; + + len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); + if (len != -ENODEV) + return len; + + return of_device_modalias(dev, buf, PAGE_SIZE); +} +static DEVICE_ATTR_RO(modalias); + +static struct attribute *serdev_device_attrs[] = { + &dev_attr_modalias.attr, + NULL, +}; +ATTRIBUTE_GROUPS(serdev_device); + +static int serdev_device_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + int rc; + + /* TODO: platform modalias */ + + rc = acpi_device_uevent_modalias(dev, env); + if (rc != -ENODEV) + return rc; + + return of_device_uevent_modalias(dev, env); +} + static void serdev_device_release(struct device *dev) { struct serdev_device *serdev = to_serdev_device(dev); @@ -26,9 +58,16 @@ static void serdev_device_release(struct device *dev) } static const struct device_type serdev_device_type = { + .groups = serdev_device_groups, + .uevent = serdev_device_uevent, .release = serdev_device_release, }; +static bool is_serdev_device(const struct device *dev) +{ + return dev->type == &serdev_device_type; +} + static void serdev_ctrl_release(struct device *dev) { struct serdev_controller *ctrl = to_serdev_controller(dev); @@ -42,6 +81,9 @@ static const struct device_type serdev_ctrl_type = { static int serdev_device_match(struct device *dev, struct device_driver *drv) { + if (!is_serdev_device(dev)) + return 0; + /* TODO: platform matching */ if (acpi_driver_match_device(dev, drv)) return 1; @@ -49,18 +91,6 @@ static int serdev_device_match(struct device *dev, struct device_driver *drv) return of_driver_match_device(dev, drv); } -static int serdev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - int rc; - - /* TODO: platform modalias */ - rc = acpi_device_uevent_modalias(dev, env); - if (rc != -ENODEV) - return rc; - - return of_device_uevent_modalias(dev, env); -} - /** * serdev_device_add() - add a device previously constructed via serdev_device_alloc() * @serdev: serdev_device to be added @@ -312,32 +342,11 @@ static int serdev_drv_remove(struct device *dev) return 0; } -static ssize_t modalias_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int len; - - len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); - if (len != -ENODEV) - return len; - - return of_device_modalias(dev, buf, PAGE_SIZE); -} -DEVICE_ATTR_RO(modalias); - -static struct attribute *serdev_device_attrs[] = { - &dev_attr_modalias.attr, - NULL, -}; -ATTRIBUTE_GROUPS(serdev_device); - static struct bus_type serdev_bus_type = { .name = "serial", .match = serdev_device_match, .probe = serdev_drv_probe, .remove = serdev_drv_remove, - .uevent = serdev_uevent, - .dev_groups = serdev_device_groups, }; /** diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 1bdf2959ac5c672afe91c00c6e30a229616c64fb..fa1672993b4c4421a7776e3b1f5f8cc3ae7a7c75 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -59,7 +59,8 @@ static void ttyport_write_wakeup(struct tty_port *port) test_bit(SERPORT_ACTIVE, &serport->flags)) serdev_controller_write_wakeup(ctrl); - wake_up_interruptible_poll(&tty->write_wait, POLLOUT); + /* Wake up any tty_wait_until_sent() */ + wake_up_interruptible(&tty->write_wait); tty_kref_put(tty); } @@ -122,6 +123,8 @@ static int ttyport_open(struct serdev_controller *ctrl) if (ret) goto err_close; + tty_unlock(serport->tty); + /* Bring the UART into a known 8 bits no parity hw fc state */ ktermios = tty->termios; ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | @@ -131,11 +134,12 @@ static int ttyport_open(struct serdev_controller *ctrl) ktermios.c_cflag &= ~(CSIZE | PARENB); ktermios.c_cflag |= CS8; ktermios.c_cflag |= CRTSCTS; + /* Hangups are not supported so make sure to ignore carrier detect. */ + ktermios.c_cflag |= CLOCAL; tty_set_termios(tty, &ktermios); set_bit(SERPORT_ACTIVE, &serport->flags); - tty_unlock(serport->tty); return 0; err_close: diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 5bb0c42c88ddb7867388044995dc4b5268a5c76c..cd1b94a0f451ca2d033dcf51ee55ce39be274ee6 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -252,31 +252,25 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { unsigned int baud = tty_termios_baud_rate(termios); - unsigned int target_rate, min_rate, max_rate; struct dw8250_data *d = p->private_data; long rate; - int i, ret; + int ret; if (IS_ERR(d->clk) || !old) goto out; - /* Find a clk rate within +/-1.6% of an integer multiple of baudx16 */ - target_rate = baud * 16; - min_rate = target_rate - (target_rate >> 6); - max_rate = target_rate + (target_rate >> 6); - - for (i = 1; i <= UART_DIV_MAX; i++) { - rate = clk_round_rate(d->clk, i * target_rate); - if (rate >= i * min_rate && rate <= i * max_rate) - break; - } - if (i <= UART_DIV_MAX) { - clk_disable_unprepare(d->clk); + clk_disable_unprepare(d->clk); + rate = clk_round_rate(d->clk, baud * 16); + if (rate < 0) + ret = rate; + else if (rate == 0) + ret = -ENOENT; + else ret = clk_set_rate(d->clk, rate); - clk_prepare_enable(d->clk); - if (!ret) - p->uartclk = rate; - } + clk_prepare_enable(d->clk); + + if (!ret) + p->uartclk = rate; out: p->status &= ~UPSTAT_AUTOCTS; @@ -515,7 +509,8 @@ static int dw8250_probe(struct platform_device *pdev) /* If no clock rate is defined, fail. */ if (!p->uartclk) { dev_err(dev, "clock rate not defined\n"); - return -EINVAL; + err = -EINVAL; + goto err_clk; } data->pclk = devm_clk_get(dev, "apb_pclk"); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index a402878c9f30dc4d9377e38c28d514d2a86b8d01..38af306ca0e817c71f38ce90c833b1f1b0fa7191 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -34,6 +34,7 @@ #define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 #define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 +#define UART_EXAR_INT0 0x80 #define UART_EXAR_8XMODE 0x88 /* 8X sampling rate select */ #define UART_EXAR_FCTR 0x08 /* Feature Control Register */ @@ -121,6 +122,7 @@ struct exar8250_board { struct exar8250 { unsigned int nr; struct exar8250_board *board; + void __iomem *virt; int line[0]; }; @@ -131,12 +133,9 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev, const struct exar8250_board *board = priv->board; unsigned int bar = 0; - if (!pcim_iomap_table(pcidev)[bar] && !pcim_iomap(pcidev, bar, 0)) - return -ENOMEM; - port->port.iotype = UPIO_MEM; port->port.mapbase = pci_resource_start(pcidev, bar) + offset; - port->port.membase = pcim_iomap_table(pcidev)[bar] + offset; + port->port.membase = priv->virt + offset; port->port.regshift = board->reg_shift; return 0; @@ -420,6 +419,25 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev) port->port.private_data = NULL; } +/* + * These Exar UARTs have an extra interrupt indicator that could fire for a + * few interrupts that are not presented/cleared through IIR. One of which is + * a wakeup interrupt when coming out of sleep. These interrupts are only + * cleared by reading global INT0 or INT1 registers as interrupts are + * associated with channel 0. The INT[3:0] registers _are_ accessible from each + * channel's address space, but for the sake of bus efficiency we register a + * dedicated handler at the PCI device level to handle them. + */ +static irqreturn_t exar_misc_handler(int irq, void *data) +{ + struct exar8250 *priv = data; + + /* Clear all PCI interrupts by reading INT0. No effect on IIR */ + ioread8(priv->virt + UART_EXAR_INT0); + + return IRQ_HANDLED; +} + static int exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) { @@ -448,6 +466,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) return -ENOMEM; priv->board = board; + priv->virt = pcim_iomap(pcidev, bar, 0); + if (!priv->virt) + return -ENOMEM; pci_set_master(pcidev); @@ -461,6 +482,11 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) uart.port.irq = pci_irq_vector(pcidev, 0); uart.port.dev = &pcidev->dev; + rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler, + IRQF_SHARED, "exar_uart", priv); + if (rc) + return rc; + for (i = 0; i < nr_ports && i < maxnr; i++) { rc = board->setup(priv, pcidev, &uart, i); if (rc) { diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 6af84900870e43b0ee24d68af232e4194bb4c51b..15a8c8dfa92b24a65c97a111f8c8c3c7f8da6b20 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -91,14 +91,22 @@ static int __init ingenic_early_console_setup(struct earlycon_device *dev, const char *opt) { struct uart_port *port = &dev->port; - unsigned int baud, divisor; + unsigned int divisor; + int baud = 115200; if (!dev->port.membase) return -ENODEV; + if (opt) { + unsigned int parity, bits, flow; /* unused for now */ + + uart_parse_options(opt, &baud, &parity, &bits, &flow); + } + ingenic_early_console_setup_clock(dev); - baud = dev->baud ?: 115200; + if (dev->baud) + baud = dev->baud; divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud); early_out(port, UART_IER, 0); @@ -125,6 +133,10 @@ EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup); OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart", ingenic_early_console_setup); +EARLYCON_DECLARE(jz4770_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4770_uart, "ingenic,jz4770-uart", + ingenic_early_console_setup); + EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup); OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart", ingenic_early_console_setup); @@ -319,6 +331,7 @@ static const struct ingenic_uart_config jz4780_uart_config = { static const struct of_device_id of_match[] = { { .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config }, { .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config }, + { .compatible = "ingenic,jz4770-uart", .data = &jz4760_uart_config }, { .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config }, { .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config }, { /* sentinel */ } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 1e67a7e4a5fd32e031ad29db382aa12a9a9929bf..160b8906d9b9cbb47e7f5459b23c604778e5eff5 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -136,8 +136,11 @@ 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)) + if (IS_ERR(info->rst)) { + ret = PTR_ERR(info->rst); goto err_dispose; + } + ret = reset_control_deassert(info->rst); if (ret) goto err_dispose; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index bd40ba4024109ca98edb24dfa71c50fbfa0ab12a..57f6eba47f4419b88453e1415e2b674102fc94d6 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -414,7 +414,7 @@ static void omap_8250_set_termios(struct uart_port *port, /* Up to here it was mostly serial8250_do_set_termios() */ /* - * We enable TRIG_GRANU for RX and TX and additionaly we set + * We enable TRIG_GRANU for RX and TX and additionally we set * SCR_TX_EMPTY bit. The result is the following: * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt. * - less than RX_TRIGGER number of bytes will also cause an interrupt diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 11434551ac0ad735b757cb356e3099eee3156a03..1328c7e7010844ac50a38496df1c816067231afd 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -441,7 +441,6 @@ static void io_serial_out(struct uart_port *p, int offset, int value) } static int serial8250_default_handle_irq(struct uart_port *port); -static int exar_handle_irq(struct uart_port *port); static void set_io_from_upio(struct uart_port *p) { @@ -1883,26 +1882,6 @@ static int serial8250_default_handle_irq(struct uart_port *port) return ret; } -/* - * These Exar UARTs have an extra interrupt indicator that could - * fire for a few unimplemented interrupts. One of which is a - * wakeup event when coming out of sleep. Put this here just - * to be on the safe side that these interrupts don't go unhandled. - */ -static int exar_handle_irq(struct uart_port *port) -{ - unsigned int iir = serial_port_in(port, UART_IIR); - int ret = 0; - - if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) && - serial_port_in(port, UART_EXAR_INT0) != 0) - ret = 1; - - ret |= serial8250_handle_irq(port, iir); - - return ret; -} - /* * Newer 16550 compatible parts such as the SC16C650 & Altera 16550 Soft IP * have a programmable TX threshold that triggers the THRE interrupt in @@ -3067,11 +3046,6 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (port->type == PORT_UNKNOWN) serial8250_release_std_resource(up); - /* Fixme: probably not the best place for this */ - if ((port->type == PORT_XR17V35X) || - (port->type == PORT_XR17D15X)) - port->handle_irq = exar_handle_irq; - register_dev_spec_attr_grp(up); up->fcr = uart_config[up->port.type].fcr; } diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index 45ef506293aebb455a667a70bfb26d8609b175e5..28d88ccf5a0c2da6c399141de475f8c741960e60 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -250,12 +250,13 @@ static int uniphier_uart_probe(struct platform_device *pdev) up.dl_read = uniphier_serial_dl_read; up.dl_write = uniphier_serial_dl_write; - priv->line = serial8250_register_8250_port(&up); - if (priv->line < 0) { + ret = serial8250_register_8250_port(&up); + if (ret < 0) { dev_err(dev, "failed to register 8250 port\n"); clk_disable_unprepare(priv->clk); return ret; } + priv->line = ret; platform_set_drvdata(pdev, priv); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a5c0ef1e7695fedc6e185e09454d9a5a55f358cb..16b1496e61051948ff38ab2f884632c30a7389c7 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -5,6 +5,7 @@ config SERIAL_8250 tristate "8250/16550 and compatible serial support" + depends on !S390 select SERIAL_CORE ---help--- This selects whether you want to include the driver for the standard diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index b788fee54249deff289fe1512e5b87b5b306e51e..3682fd3e960cbd6473ee0203503b29bf8091ebfe 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -761,24 +761,30 @@ config SERIAL_SH_SCI select SERIAL_MCTRL_GPIO if GPIOLIB config SERIAL_SH_SCI_NR_UARTS - int "Maximum number of SCI(F) serial ports" + int "Maximum number of SCI(F) serial ports" if EXPERT depends on SERIAL_SH_SCI + default "3" if H8300 + default "10" if SUPERH + default "18" if ARCH_RENESAS default "2" config SERIAL_SH_SCI_CONSOLE - bool "Support for console on SuperH SCI(F)" + bool "Support for console on SuperH SCI(F)" if EXPERT depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE + default y config SERIAL_SH_SCI_EARLYCON - bool "Support for early console on SuperH SCI(F)" + bool "Support for early console on SuperH SCI(F)" if EXPERT depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON + default ARCH_RENESAS || H8300 config SERIAL_SH_SCI_DMA - bool "DMA support" + bool "DMA support" if EXPERT depends on SERIAL_SH_SCI && DMA_ENGINE + default ARCH_RENESAS config SERIAL_PNX8XXX bool "Enable PNX8XXX SoCs' UART Support" diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 04af8de8617e3b05ef734a9bdc7ef0297faf3b2e..4b40a5b449eeec048c0fc71b253f09c84dc32eb8 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -314,10 +314,9 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap, static int pl011_fifo_to_tty(struct uart_amba_port *uap) { u16 status; - unsigned int ch, flag, max_count = 256; - int fifotaken = 0; + unsigned int ch, flag, fifotaken; - while (max_count--) { + for (fifotaken = 0; fifotaken != 256; fifotaken++) { status = pl011_read(uap, REG_FR); if (status & UART01x_FR_RXFE) break; @@ -326,7 +325,6 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; - fifotaken++; if (unlikely(ch & UART_DR_ERROR)) { if (ch & UART011_DR_BE) { @@ -1482,12 +1480,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id) struct uart_amba_port *uap = dev_id; unsigned long flags; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; - u16 imsc; int handled = 0; spin_lock_irqsave(&uap->port.lock, flags); - imsc = pl011_read(uap, REG_IMSC); - status = pl011_read(uap, REG_RIS) & imsc; + status = pl011_read(uap, REG_RIS) & uap->im; if (status) { do { check_apply_cts_event_workaround(uap); @@ -1511,7 +1507,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (pass_counter-- == 0) break; - status = pl011_read(uap, REG_RIS) & imsc; + status = pl011_read(uap, REG_RIS) & uap->im; } while (status != 0); handled = 1; } diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index efa25611ca0c36eb73c8abc49a3767ebecb77cb3..df46a9e88c34dd89eaa766603fd5738c6d99ac9a 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2345,7 +2345,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, atmel_init_property(atmel_port, pdev); atmel_set_ops(port); - of_get_rs485_mode(pdev->dev.of_node, &port->rs485); + uart_get_rs485_mode(&pdev->dev, &port->rs485); port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 1c4d3f38713863f2ebc2e5e7f13ff5f38ac0715d..8cf112f2efc30707dcbc4ac618363b15ba80fb04 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2206,23 +2206,16 @@ static int lpuart_probe(struct platform_device *pdev) if (ret) goto failed_attach_port; - of_get_rs485_mode(np, &sport->port.rs485); + uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); - if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) { + if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); - return -ENOSYS; - } if (sport->port.rs485.delay_rts_before_send || - sport->port.rs485.delay_rts_after_send) { + sport->port.rs485.delay_rts_after_send) dev_err(&pdev->dev, "driver doesn't support RTS delays\n"); - return -ENOSYS; - } - if (sport->port.rs485.flags & SER_RS485_ENABLED) { - sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND; - writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM); - } + lpuart_config_rs485(&sport->port, &sport->port.rs485); sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx"); if (!sport->dma_tx_chan) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e4b3d9123a03312b3985e8f1db7840e13e6a38e3..1d7ca382bc12b2381eba26cf93eb67ec80853977 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -703,25 +703,6 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) return IRQ_HANDLED; } -static void imx_disable_rx_int(struct imx_port *sport) -{ - unsigned long temp; - - /* disable the receiver ready and aging timer interrupts */ - temp = readl(sport->port.membase + UCR1); - temp &= ~(UCR1_RRDYEN); - writel(temp, sport->port.membase + UCR1); - - temp = readl(sport->port.membase + UCR2); - temp &= ~(UCR2_ATEN); - writel(temp, sport->port.membase + UCR2); - - /* disable the rx errors interrupts */ - temp = readl(sport->port.membase + UCR4); - temp &= ~UCR4_OREN; - writel(temp, sport->port.membase + UCR4); -} - static void clear_rx_errors(struct imx_port *sport); /* @@ -1252,18 +1233,21 @@ static int imx_startup(struct uart_port *port) if (sport->dma_is_inited && !sport->dma_is_enabled) imx_enable_dma(sport); - temp = readl(sport->port.membase + UCR1); - temp |= UCR1_RRDYEN | UCR1_UARTEN; + temp = readl(sport->port.membase + UCR1) & ~UCR1_RRDYEN; + if (!sport->dma_is_enabled) + temp |= UCR1_RRDYEN; + temp |= UCR1_UARTEN; if (sport->have_rtscts) temp |= UCR1_RTSDEN; writel(temp, sport->port.membase + UCR1); - temp = readl(sport->port.membase + UCR4); - temp |= UCR4_OREN; + temp = readl(sport->port.membase + UCR4) & ~UCR4_OREN; + if (!sport->dma_is_enabled) + temp |= UCR4_OREN; writel(temp, sport->port.membase + UCR4); - temp = readl(sport->port.membase + UCR2); + temp = readl(sport->port.membase + UCR2) & ~UCR2_ATEN; temp |= (UCR2_RXEN | UCR2_TXEN); if (!sport->have_rtscts) temp |= UCR2_IRTS; @@ -1297,10 +1281,8 @@ static int imx_startup(struct uart_port *port) * In our iMX53 the average delay for the first reception dropped from * approximately 35000 microseconds to 1000 microseconds. */ - if (sport->dma_is_enabled) { - imx_disable_rx_int(sport); + if (sport->dma_is_enabled) start_rx_dma(sport); - } spin_unlock_irqrestore(&sport->port.lock, flags); @@ -2017,8 +1999,6 @@ static int serial_imx_probe_dt(struct imx_port *sport, if (of_get_property(np, "rts-gpios", NULL)) sport->have_rtsgpio = 1; - of_get_rs485_mode(np, &sport->port.rs485); - return 0; } #else @@ -2080,7 +2060,6 @@ static int serial_imx_probe(struct platform_device *pdev) sport->port.fifosize = 32; sport->port.ops = &imx_pops; sport->port.rs485_config = imx_rs485_config; - sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND; sport->port.flags = UPF_BOOT_AUTOCONF; timer_setup(&sport->timer, imx_timeout, 0); @@ -2111,6 +2090,14 @@ static int serial_imx_probe(struct platform_device *pdev) return ret; } + uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); + + if (sport->port.rs485.flags & SER_RS485_ENABLED && + (!sport->have_rtscts || !sport->have_rtsgpio)) + dev_err(&pdev->dev, "no RTS control, disabling rs485\n"); + + imx_rs485_config(&sport->port, &sport->port.rs485); + /* Disable interrupts before requesting them */ reg = readl_relaxed(sport->port.membase + UCR1); reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | @@ -2232,29 +2219,28 @@ static void serial_imx_enable_wakeup(struct imx_port *sport, bool on) unsigned int val; val = readl(sport->port.membase + UCR3); - if (on) + if (on) { + writel(USR1_AWAKE, sport->port.membase + USR1); val |= UCR3_AWAKEN; + } else val &= ~UCR3_AWAKEN; writel(val, sport->port.membase + UCR3); - val = readl(sport->port.membase + UCR1); - if (on) - val |= UCR1_RTSDEN; - else - val &= ~UCR1_RTSDEN; - writel(val, sport->port.membase + UCR1); + if (sport->have_rtscts) { + val = readl(sport->port.membase + UCR1); + if (on) + val |= UCR1_RTSDEN; + else + val &= ~UCR1_RTSDEN; + writel(val, sport->port.membase + UCR1); + } } static int imx_serial_port_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct imx_port *sport = platform_get_drvdata(pdev); - int ret; - - ret = clk_enable(sport->clk_ipg); - if (ret) - return ret; serial_imx_save_context(sport); @@ -2275,8 +2261,6 @@ static int imx_serial_port_resume_noirq(struct device *dev) serial_imx_restore_context(sport); - clk_disable(sport->clk_ipg); - return 0; } @@ -2284,15 +2268,19 @@ static int imx_serial_port_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct imx_port *sport = platform_get_drvdata(pdev); - - /* enable wakeup from i.MX UART */ - serial_imx_enable_wakeup(sport, true); + int ret; uart_suspend_port(&imx_reg, &sport->port); disable_irq(sport->port.irq); - /* Needed to enable clock in suspend_noirq */ - return clk_prepare(sport->clk_ipg); + ret = clk_prepare_enable(sport->clk_ipg); + if (ret) + return ret; + + /* enable wakeup from i.MX UART */ + serial_imx_enable_wakeup(sport, true); + + return 0; } static int imx_serial_port_resume(struct device *dev) @@ -2306,7 +2294,7 @@ static int imx_serial_port_resume(struct device *dev) uart_resume_port(&imx_reg, &sport->port); enable_irq(sport->port.irq); - clk_unprepare(sport->clk_ipg); + clk_disable_unprepare(sport->clk_ipg); return 0; } @@ -2318,8 +2306,7 @@ static int imx_serial_port_freeze(struct device *dev) uart_suspend_port(&imx_reg, &sport->port); - /* Needed to enable clock in suspend_noirq */ - return clk_prepare(sport->clk_ipg); + return clk_prepare_enable(sport->clk_ipg); } static int imx_serial_port_thaw(struct device *dev) @@ -2329,7 +2316,7 @@ static int imx_serial_port_thaw(struct device *dev) uart_resume_port(&imx_reg, &sport->port); - clk_unprepare(sport->clk_ipg); + clk_disable_unprepare(sport->clk_ipg); return 0; } diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c index 4718560b8fdc93c0ff2796ce5ac582b6a1466396..bf0e2a4cb0cefae7776e48c1c01fd969cde1c3ed 100644 --- a/drivers/tty/serial/jsm/jsm_neo.c +++ b/drivers/tty/serial/jsm/jsm_neo.c @@ -282,9 +282,6 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch) u16 head; u16 tail; - if (!ch) - return; - /* cache head and tail of queue */ head = ch->ch_r_head & RQUEUEMASK; tail = ch->ch_r_tail & RQUEUEMASK; @@ -1175,6 +1172,9 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) continue; ch = brd->channels[port]; + if (!ch) + continue; + neo_copy_data_from_uart_to_queue(ch); /* Call our tty layer to enforce queue flow control if needed. */ diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 469927d37b4116f8e7e937fbd5821abfec4ec81d..b6bd6e15e07bde86062beb2bd7e07b872e28ddc7 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -523,9 +523,6 @@ void jsm_input(struct jsm_channel *ch) jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n"); - if (!ch) - return; - port = &ch->uart_port.state->port; tp = port->tty; @@ -648,11 +645,8 @@ static void jsm_carrier(struct jsm_channel *ch) int phys_carrier = 0; jsm_dbg(CARR, &ch->ch_bd->pci_dev, "start\n"); - if (!ch) - return; bd = ch->ch_bd; - if (!bd) return; diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index ecb6513a65053b2105c78ec300fc905bd424f850..39f635812077ad3848fa910770bac7de0b23f344 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -233,6 +233,7 @@ /* Misc definitions */ #define MAX310X_FIFO_SIZE (128) #define MAX310x_REV_MASK (0xf8) +#define MAX310X_WRITE_BIT 0x80 /* MAX3107 specific */ #define MAX3107_REV_ID (0xa0) @@ -593,57 +594,118 @@ static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq, return (int)bestfreq; } -static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) +static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len) { - unsigned int sts, ch, flag; + u8 header[] = { (port->iobase + MAX310X_THR_REG) | MAX310X_WRITE_BIT }; + struct spi_transfer xfer[] = { + { + .tx_buf = &header, + .len = sizeof(header), + }, { + .tx_buf = txbuf, + .len = len, + } + }; + spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer)); +} - if (unlikely(rxlen >= port->fifosize)) { - dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n"); - port->icount.buf_overrun++; - /* Ensure sanity of RX level */ - rxlen = port->fifosize; - } +static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len) +{ + u8 header[] = { port->iobase + MAX310X_RHR_REG }; + struct spi_transfer xfer[] = { + { + .tx_buf = &header, + .len = sizeof(header), + }, { + .rx_buf = rxbuf, + .len = len, + } + }; + spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer)); +} - while (rxlen--) { - ch = max310x_port_read(port, MAX310X_RHR_REG); - sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); +static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) +{ + unsigned int sts, ch, flag, i; + u8 buf[MAX310X_FIFO_SIZE]; + + if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) { + /* We are just reading, happily ignoring any error conditions. + * Break condition, parity checking, framing errors -- they + * are all ignored. That means that we can do a batch-read. + * + * There is a small opportunity for race if the RX FIFO + * overruns while we're reading the buffer; the datasheets says + * that the LSR register applies to the "current" character. + * That's also the reason why we cannot do batched reads when + * asked to check the individual statuses. + * */ - sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT | - MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT; + sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); + max310x_batch_read(port, buf, rxlen); - port->icount.rx++; + port->icount.rx += rxlen; flag = TTY_NORMAL; + sts &= port->read_status_mask; - if (unlikely(sts)) { - if (sts & MAX310X_LSR_RXBRK_BIT) { - port->icount.brk++; - if (uart_handle_break(port)) - continue; - } else if (sts & MAX310X_LSR_RXPAR_BIT) - port->icount.parity++; - else if (sts & MAX310X_LSR_FRERR_BIT) - port->icount.frame++; - else if (sts & MAX310X_LSR_RXOVR_BIT) - port->icount.overrun++; - - sts &= port->read_status_mask; - if (sts & MAX310X_LSR_RXBRK_BIT) - flag = TTY_BREAK; - else if (sts & MAX310X_LSR_RXPAR_BIT) - flag = TTY_PARITY; - else if (sts & MAX310X_LSR_FRERR_BIT) - flag = TTY_FRAME; - else if (sts & MAX310X_LSR_RXOVR_BIT) - flag = TTY_OVERRUN; + if (sts & MAX310X_LSR_RXOVR_BIT) { + dev_warn_ratelimited(port->dev, "Hardware RX FIFO overrun\n"); + port->icount.overrun++; } - if (uart_handle_sysrq_char(port, ch)) - continue; + for (i = 0; i < rxlen; ++i) { + uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, buf[i], flag); + } + + } else { + if (unlikely(rxlen >= port->fifosize)) { + dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n"); + port->icount.buf_overrun++; + /* Ensure sanity of RX level */ + rxlen = port->fifosize; + } + + while (rxlen--) { + ch = max310x_port_read(port, MAX310X_RHR_REG); + sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); + + sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT | + MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT; + + port->icount.rx++; + flag = TTY_NORMAL; + + if (unlikely(sts)) { + if (sts & MAX310X_LSR_RXBRK_BIT) { + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } else if (sts & MAX310X_LSR_RXPAR_BIT) + port->icount.parity++; + else if (sts & MAX310X_LSR_FRERR_BIT) + port->icount.frame++; + else if (sts & MAX310X_LSR_RXOVR_BIT) + port->icount.overrun++; + + sts &= port->read_status_mask; + if (sts & MAX310X_LSR_RXBRK_BIT) + flag = TTY_BREAK; + else if (sts & MAX310X_LSR_RXPAR_BIT) + flag = TTY_PARITY; + else if (sts & MAX310X_LSR_FRERR_BIT) + flag = TTY_FRAME; + else if (sts & MAX310X_LSR_RXOVR_BIT) + flag = TTY_OVERRUN; + } - if (sts & port->ignore_status_mask) - continue; + if (uart_handle_sysrq_char(port, ch)) + continue; - uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag); + if (sts & port->ignore_status_mask) + continue; + + uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag); + } } tty_flip_buffer_push(&port->state->port); @@ -652,7 +714,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) static void max310x_handle_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; - unsigned int txlen, to_send; + unsigned int txlen, to_send, until_end; if (unlikely(port->x_char)) { max310x_port_write(port, MAX310X_THR_REG, port->x_char); @@ -666,28 +728,43 @@ static void max310x_handle_tx(struct uart_port *port) /* Get length of data pending in circular buffer */ to_send = uart_circ_chars_pending(xmit); + until_end = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (likely(to_send)) { /* Limit to size of TX FIFO */ txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG); txlen = port->fifosize - txlen; to_send = (to_send > txlen) ? txlen : to_send; + if (until_end < to_send) { + /* It's a circ buffer -- wrap around. + * We could do that in one SPI transaction, but meh. */ + max310x_batch_write(port, xmit->buf + xmit->tail, until_end); + max310x_batch_write(port, xmit->buf, to_send - until_end); + } else { + max310x_batch_write(port, xmit->buf + xmit->tail, to_send); + } + /* Add data to send */ port->icount.tx += to_send; - while (to_send--) { - max310x_port_write(port, MAX310X_THR_REG, - xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - } + xmit->tail = (xmit->tail + to_send) & (UART_XMIT_SIZE - 1); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); } -static void max310x_port_irq(struct max310x_port *s, int portno) +static void max310x_start_tx(struct uart_port *port) +{ + struct max310x_one *one = container_of(port, struct max310x_one, port); + + if (!work_pending(&one->tx_work)) + schedule_work(&one->tx_work); +} + +static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno) { struct uart_port *port = &s->p[portno].port; + irqreturn_t res = IRQ_NONE; do { unsigned int ists, lsr, rxlen; @@ -698,6 +775,8 @@ static void max310x_port_irq(struct max310x_port *s, int portno) if (!ists && !rxlen) break; + res = IRQ_HANDLED; + if (ists & MAX310X_IRQ_CTS_BIT) { lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); uart_handle_cts_change(port, @@ -705,17 +784,16 @@ static void max310x_port_irq(struct max310x_port *s, int portno) } if (rxlen) max310x_handle_rx(port, rxlen); - if (ists & MAX310X_IRQ_TXEMPTY_BIT) { - mutex_lock(&s->mutex); - max310x_handle_tx(port); - mutex_unlock(&s->mutex); - } + if (ists & MAX310X_IRQ_TXEMPTY_BIT) + max310x_start_tx(port); } while (1); + return res; } static irqreturn_t max310x_ist(int irq, void *dev_id) { struct max310x_port *s = (struct max310x_port *)dev_id; + bool handled = false; if (s->devtype->nr > 1) { do { @@ -726,12 +804,15 @@ static irqreturn_t max310x_ist(int irq, void *dev_id) val = ((1 << s->devtype->nr) - 1) & ~val; if (!val) break; - max310x_port_irq(s, fls(val) - 1); + if (max310x_port_irq(s, fls(val) - 1) == IRQ_HANDLED) + handled = true; } while (1); - } else - max310x_port_irq(s, 0); + } else { + if (max310x_port_irq(s, 0) == IRQ_HANDLED) + handled = true; + } - return IRQ_HANDLED; + return IRQ_RETVAL(handled); } static void max310x_wq_proc(struct work_struct *ws) @@ -744,14 +825,6 @@ static void max310x_wq_proc(struct work_struct *ws) mutex_unlock(&s->mutex); } -static void max310x_start_tx(struct uart_port *port) -{ - struct max310x_one *one = container_of(port, struct max310x_one, port); - - if (!work_pending(&one->tx_work)) - schedule_work(&one->tx_work); -} - static unsigned int max310x_tx_empty(struct uart_port *port) { unsigned int lvl, sts; @@ -1086,10 +1159,31 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip, return 0; } + +static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + struct max310x_port *s = gpiochip_get_data(chip); + struct uart_port *port = &s->p[offset / 4].port; + + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + max310x_port_update(port, MAX310X_GPIOCFG_REG, + 1 << ((offset % 4) + 4), + 1 << ((offset % 4) + 4)); + return 0; + case PIN_CONFIG_DRIVE_PUSH_PULL: + max310x_port_update(port, MAX310X_GPIOCFG_REG, + 1 << ((offset % 4) + 4), 0); + return 0; + default: + return -ENOTSUPP; + } +} #endif static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, - struct regmap *regmap, int irq, unsigned long flags) + struct regmap *regmap, int irq) { int i, ret, fmin, fmax, freq, uartclk; struct clk *clk_osc, *clk_xtal; @@ -1169,23 +1263,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, uartclk = max310x_set_ref_clk(s, freq, xtal); dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); -#ifdef CONFIG_GPIOLIB - /* Setup GPIO cotroller */ - s->gpio.owner = THIS_MODULE; - s->gpio.parent = dev; - s->gpio.label = dev_name(dev); - s->gpio.direction_input = max310x_gpio_direction_input; - s->gpio.get = max310x_gpio_get; - s->gpio.direction_output= max310x_gpio_direction_output; - s->gpio.set = max310x_gpio_set; - s->gpio.base = -1; - s->gpio.ngpio = devtype->nr * 4; - s->gpio.can_sleep = 1; - ret = devm_gpiochip_add_data(dev, &s->gpio, s); - if (ret) - goto out_clk; -#endif - mutex_init(&s->mutex); for (i = 0; i < devtype->nr; i++) { @@ -1237,9 +1314,27 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, devtype->power(&s->p[i].port, 0); } +#ifdef CONFIG_GPIOLIB + /* Setup GPIO cotroller */ + s->gpio.owner = THIS_MODULE; + s->gpio.parent = dev; + s->gpio.label = dev_name(dev); + s->gpio.direction_input = max310x_gpio_direction_input; + s->gpio.get = max310x_gpio_get; + s->gpio.direction_output= max310x_gpio_direction_output; + s->gpio.set = max310x_gpio_set; + s->gpio.set_config = max310x_gpio_set_config; + s->gpio.base = -1; + s->gpio.ngpio = devtype->nr * 4; + s->gpio.can_sleep = 1; + ret = devm_gpiochip_add_data(dev, &s->gpio, s); + if (ret) + goto out_uart; +#endif + /* Setup interrupt */ ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist, - IRQF_ONESHOT | flags, dev_name(dev), s); + IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), s); if (!ret) return 0; @@ -1293,7 +1388,7 @@ MODULE_DEVICE_TABLE(of, max310x_dt_ids); static struct regmap_config regcfg = { .reg_bits = 8, .val_bits = 8, - .write_flag_mask = 0x80, + .write_flag_mask = MAX310X_WRITE_BIT, .cache_type = REGCACHE_RBTREE, .writeable_reg = max310x_reg_writeable, .volatile_reg = max310x_reg_volatile, @@ -1304,7 +1399,6 @@ static struct regmap_config regcfg = { static int max310x_spi_probe(struct spi_device *spi) { struct max310x_devtype *devtype; - unsigned long flags = 0; struct regmap *regmap; int ret; @@ -1327,11 +1421,10 @@ static int max310x_spi_probe(struct spi_device *spi) devtype = (struct max310x_devtype *)id_entry->driver_data; } - flags = IRQF_TRIGGER_FALLING; regcfg.max_register = devtype->nr * 0x20 - 1; regmap = devm_regmap_init_spi(spi, ®cfg); - return max310x_probe(&spi->dev, devtype, regmap, spi->irq, flags); + return max310x_probe(&spi->dev, devtype, regmap, spi->irq); } static int max310x_spi_remove(struct spi_device *spi) diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index daafe60175da630d4aaa59a241c09e5e4f40d46d..8a842591b37c714f976ab23f39663ced5528508f 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -34,9 +34,15 @@ /* AML_UART_CONTROL bits */ #define AML_UART_TX_EN BIT(12) #define AML_UART_RX_EN BIT(13) +#define AML_UART_TWO_WIRE_EN BIT(15) +#define AML_UART_STOP_BIT_LEN_MASK (0x03 << 16) +#define AML_UART_STOP_BIT_1SB (0x00 << 16) +#define AML_UART_STOP_BIT_2SB (0x01 << 16) +#define AML_UART_PARITY_TYPE BIT(18) +#define AML_UART_PARITY_EN BIT(19) #define AML_UART_TX_RST BIT(22) #define AML_UART_RX_RST BIT(23) -#define AML_UART_CLR_ERR BIT(24) +#define AML_UART_CLEAR_ERR BIT(24) #define AML_UART_RX_INT_EN BIT(27) #define AML_UART_TX_INT_EN BIT(28) #define AML_UART_DATA_LEN_MASK (0x03 << 20) @@ -57,15 +63,6 @@ AML_UART_FRAME_ERR | \ AML_UART_TX_FIFO_WERR) -/* AML_UART_CONTROL bits */ -#define AML_UART_TWO_WIRE_EN BIT(15) -#define AML_UART_PARITY_TYPE BIT(18) -#define AML_UART_PARITY_EN BIT(19) -#define AML_UART_CLEAR_ERR BIT(24) -#define AML_UART_STOP_BIN_LEN_MASK (0x03 << 16) -#define AML_UART_STOP_BIN_1SB (0x00 << 16) -#define AML_UART_STOP_BIN_2SB (0x01 << 16) - /* AML_UART_MISC bits */ #define AML_UART_XMIT_IRQ(c) (((c) & 0xff) << 8) #define AML_UART_RECV_IRQ(c) ((c) & 0xff) @@ -263,10 +260,10 @@ static void meson_uart_reset(struct uart_port *port) u32 val; val = readl(port->membase + AML_UART_CONTROL); - val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); + val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR); writel(val, port->membase + AML_UART_CONTROL); - val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); + val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR); writel(val, port->membase + AML_UART_CONTROL); } @@ -276,9 +273,9 @@ static int meson_uart_startup(struct uart_port *port) int ret = 0; val = readl(port->membase + AML_UART_CONTROL); - val |= AML_UART_CLR_ERR; + val |= AML_UART_CLEAR_ERR; writel(val, port->membase + AML_UART_CONTROL); - val &= ~AML_UART_CLR_ERR; + val &= ~AML_UART_CLEAR_ERR; writel(val, port->membase + AML_UART_CONTROL); val |= (AML_UART_RX_EN | AML_UART_TX_EN); @@ -354,11 +351,11 @@ static void meson_uart_set_termios(struct uart_port *port, else val &= ~AML_UART_PARITY_TYPE; - val &= ~AML_UART_STOP_BIN_LEN_MASK; + val &= ~AML_UART_STOP_BIT_LEN_MASK; if (cflags & CSTOPB) - val |= AML_UART_STOP_BIN_2SB; + val |= AML_UART_STOP_BIT_2SB; else - val |= AML_UART_STOP_BIN_1SB; + val |= AML_UART_STOP_BIT_1SB; if (cflags & CRTSCTS) val &= ~AML_UART_TWO_WIRE_EN; diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index efb4fd3784ed75c1c86948f2e387b2960a22bf68..079dc47aa142d8e17af702132eac08574951a08e 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -40,7 +40,6 @@ #include -#include #include #include #include @@ -1597,7 +1596,7 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev) for (i = 0; i < UART_GPIO_MAX; i++) { gpiod = mctrl_gpio_to_gpiod(s->gpios, i); - if (gpiod && (gpiod_get_direction(gpiod) == GPIOF_DIR_IN)) + if (gpiod && (gpiod_get_direction(gpiod) == 1)) s->gpio_irq[i] = gpiod_to_irq(gpiod); else s->gpio_irq[i] = -EINVAL; @@ -1721,7 +1720,7 @@ static int mxs_auart_probe(struct platform_device *pdev) ret = uart_add_one_port(&auart_driver, &s->port); if (ret) - goto out_free_gpio_irq; + goto out_disable_clks_free_qpio_irq; /* ASM9260 don't have version reg */ if (is_asm9260_auart(s)) { @@ -1735,7 +1734,11 @@ static int mxs_auart_probe(struct platform_device *pdev) return 0; -out_free_gpio_irq: +out_disable_clks_free_qpio_irq: + if (s->clk) + clk_disable_unprepare(s->clk_ahb); + if (s->clk_ahb) + clk_disable_unprepare(s->clk_ahb); mxs_auart_free_gpio_irq(s); auart_port[pdev->id] = NULL; return ret; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 53d59e9b944ad4e71fb6a5137410fbb23fd2a929..6420ae581a802fe3c614591dce7ded443e0610a6 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1602,7 +1602,6 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, struct device_node *np) { struct serial_rs485 *rs485conf = &up->port.rs485; - enum of_gpio_flags flags; int ret; rs485conf->flags = 0; @@ -1611,19 +1610,24 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, if (!np) return 0; - if (of_property_read_bool(np, "rs485-rts-active-high")) + uart_get_rs485_mode(up->dev, rs485conf); + + if (of_property_read_bool(np, "rs485-rts-active-high")) { rs485conf->flags |= SER_RS485_RTS_ON_SEND; - else + rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; + } else { + rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + } /* check for tx enable gpio */ - up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags); + up->rts_gpio = of_get_named_gpio(np, "rts-gpio", 0); if (gpio_is_valid(up->rts_gpio)) { ret = devm_gpio_request(up->dev, up->rts_gpio, "omap-serial"); if (ret < 0) return ret; - ret = gpio_direction_output(up->rts_gpio, - flags & SER_RS485_RTS_AFTER_SEND); + ret = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ? 1 : 0; + ret = gpio_direction_output(up->rts_gpio, ret); if (ret < 0) return ret; } else if (up->rts_gpio == -EPROBE_DEFER) { @@ -1632,8 +1636,6 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, up->rts_gpio = -EINVAL; } - of_get_rs485_mode(np, rs485conf); - return 0; } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 854995e1cae7d0d256d35d4d048836747ad81063..c8dde56b532b2d88fdf15f29f7e81251c39be4ff 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -974,6 +974,8 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, } } else { retval = uart_startup(tty, state, 1); + if (retval == 0) + tty_port_set_initialized(port, true); if (retval > 0) retval = 0; } @@ -1955,9 +1957,10 @@ EXPORT_SYMBOL_GPL(uart_parse_earlycon); * eg: 115200n8r */ void -uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) +uart_parse_options(const char *options, int *baud, int *parity, + int *bits, int *flow) { - char *s = options; + const char *s = options; *baud = simple_strtoul(s, NULL, 10); while (*s >= '0' && *s <= '9') @@ -3013,19 +3016,20 @@ EXPORT_SYMBOL(uart_add_one_port); EXPORT_SYMBOL(uart_remove_one_port); /** - * of_get_rs485_mode() - Implement parsing rs485 properties - * @np: uart node + * uart_get_rs485_mode() - retrieve rs485 properties for given uart + * @dev: uart device * @rs485conf: output parameter * * This function implements the device tree binding described in * Documentation/devicetree/bindings/serial/rs485.txt. */ -void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf) +void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) { u32 rs485_delay[2]; int ret; - ret = of_property_read_u32_array(np, "rs485-rts-delay", rs485_delay, 2); + ret = device_property_read_u32_array(dev, "rs485-rts-delay", + rs485_delay, 2); if (!ret) { rs485conf->delay_rts_before_send = rs485_delay[0]; rs485conf->delay_rts_after_send = rs485_delay[1]; @@ -3035,18 +3039,25 @@ void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf) } /* - * clear full-duplex and enabled flags to get to a defined state with - * the two following properties. + * Clear full-duplex and enabled flags, set RTS polarity to active high + * to get to a defined state with the following properties: */ - rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED); + rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED | + SER_RS485_RTS_AFTER_SEND); + rs485conf->flags |= SER_RS485_RTS_ON_SEND; - if (of_property_read_bool(np, "rs485-rx-during-tx")) + if (device_property_read_bool(dev, "rs485-rx-during-tx")) rs485conf->flags |= SER_RS485_RX_DURING_TX; - if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time")) + if (device_property_read_bool(dev, "linux,rs485-enabled-at-boot-time")) rs485conf->flags |= SER_RS485_ENABLED; + + if (device_property_read_bool(dev, "rs485-rts-active-low")) { + rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; + rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + } } -EXPORT_SYMBOL_GPL(of_get_rs485_mode); +EXPORT_SYMBOL_GPL(uart_get_rs485_mode); MODULE_DESCRIPTION("Serial driver core"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index 8a5ff54d0f42b9801be4032e64029b3e57ac739c..2294d0f0587204e29ac9d5a6685c0a21af9ecbbb 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -236,7 +236,7 @@ struct stm32_usart_info stm32h7_info = { #define USART_ICR_CMCF BIT(17) /* F7 */ #define USART_ICR_WUCF BIT(20) /* H7 */ -#define STM32_SERIAL_NAME "ttyS" +#define STM32_SERIAL_NAME "ttySTM" #define STM32_MAX_PORTS 8 #define RX_BUF_L 200 /* dma rx buffer length */ diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 00d14d6a76bbff4ce46bb45a5cbf2ebdc1358268..6a89835453d3b73668817c7f6c2a04dad89b599c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1323,6 +1323,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) "%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n", __func__, tty->driver->name); + retval = tty_ldisc_lock(tty, 5 * HZ); + if (retval) + goto err_release_lock; tty->port->itty = tty; /* @@ -1333,6 +1336,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) retval = tty_ldisc_setup(tty, tty->link); if (retval) goto err_release_tty; + tty_ldisc_unlock(tty); /* Return the tty locked so that it cannot vanish under the caller */ return tty; @@ -1345,9 +1349,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) /* call the tty release_tty routine to clean out this slot */ err_release_tty: - tty_unlock(tty); + tty_ldisc_unlock(tty); tty_info_ratelimited(tty, "ldisc open failed (%d), clearing slot %d\n", retval, idx); +err_release_lock: + tty_unlock(tty); release_tty(tty, idx); return ERR_PTR(retval); } @@ -1476,6 +1482,8 @@ static void release_tty(struct tty_struct *tty, int idx) if (tty->link) tty->link->port->itty = NULL; tty_buffer_cancel_work(tty->port); + if (tty->link) + tty_buffer_cancel_work(tty->link->port); tty_kref_put(tty->link); tty_kref_put(tty); diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 24ec5c7e6b2091141a7ea113518ba48ea4b6575d..4e7946c0484bf94b7e049d87b28cde6b2dcbccf2 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -337,7 +337,7 @@ static inline void __tty_ldisc_unlock(struct tty_struct *tty) ldsem_up_write(&tty->ldisc_sem); } -static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) +int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { int ret; @@ -348,7 +348,7 @@ static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) return 0; } -static void tty_ldisc_unlock(struct tty_struct *tty) +void tty_ldisc_unlock(struct tty_struct *tty) { clear_bit(TTY_LDISC_HALTED, &tty->flags); __tty_ldisc_unlock(tty); diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index af4da9507180015241e67e82f64cb623e3774970..7851383fbd6c7d7cf567085be5165639b845092a 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -186,11 +186,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t } if (ps > pe) /* make sel_start <= sel_end */ - { - int tmp = ps; - ps = pe; - pe = tmp; - } + swap(ps, pe); if (sel_cons != vc_cons[fg_console].d) { clear_selection(); diff --git a/include/linux/serdev.h b/include/linux/serdev.h index 531031a15cdda723d0df620f2584152b9e519c9b..f153b2c7f0cd65610906f15c083643fba54e527f 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -27,8 +27,10 @@ struct serdev_device; /** * struct serdev_device_ops - Callback operations for a serdev device - * @receive_buf: Function called with data received from device. - * @write_wakeup: Function called when ready to transmit more data. + * @receive_buf: Function called with data received from device; + * returns number of bytes accepted; may sleep. + * @write_wakeup: Function called when ready to transmit more data; must + * not sleep. */ struct serdev_device_ops { int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 37b044e78333ab28b01c6460e5f00484658cc20e..4c310c34ddadd49b9e14b1202522bb493782e8a3 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -387,7 +387,7 @@ struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr, char **options); -void uart_parse_options(char *options, int *baud, int *parity, int *bits, +void uart_parse_options(const char *options, int *baud, int *parity, int *bits, int *flow); int uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow); @@ -501,9 +501,5 @@ static inline int uart_handle_break(struct uart_port *port) (cflag) & CRTSCTS || \ !((cflag) & CLOCAL)) -/* - * Common device tree parsing helpers - */ -void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf); - +void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf); #endif /* LINUX_SERIAL_CORE_H */ diff --git a/include/linux/tty.h b/include/linux/tty.h index 7ac8ba208b1fe27570ba3fa6e2576b90bab64927..0a6c71e0ad01ec4f17845b0496b4a88a94f33949 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -405,6 +405,8 @@ extern const char *tty_name(const struct tty_struct *tty); extern struct tty_struct *tty_kopen(dev_t device); extern void tty_kclose(struct tty_struct *tty); extern int tty_dev_name_to_number(const char *name, dev_t *number); +extern int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout); +extern void tty_ldisc_unlock(struct tty_struct *tty); #else static inline void tty_kref_put(struct tty_struct *tty) { }