diff options
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/Kconfig | 6 | ||||
-rw-r--r-- | drivers/tty/goldfish.c | 2 | ||||
-rw-r--r-- | drivers/tty/isicom.c | 6 | ||||
-rw-r--r-- | drivers/tty/moxa.c | 17 | ||||
-rw-r--r-- | drivers/tty/moxa.h | 2 | ||||
-rw-r--r-- | drivers/tty/n_gsm.c | 2 | ||||
-rw-r--r-- | drivers/tty/serdev/core.c | 31 | ||||
-rw-r--r-- | drivers/tty/serdev/serdev-ttyport.c | 8 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_dw.c | 3 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_omap.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Kconfig | 1 | ||||
-rw-r--r-- | drivers/tty/serial/Kconfig | 14 | ||||
-rw-r--r-- | drivers/tty/serial/amba-pl011.c | 12 | ||||
-rw-r--r-- | drivers/tty/serial/atmel_serial.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/fsl_lpuart.c | 15 | ||||
-rw-r--r-- | drivers/tty/serial/imx.c | 47 | ||||
-rw-r--r-- | drivers/tty/serial/max310x.c | 245 | ||||
-rw-r--r-- | drivers/tty/serial/meson_uart.c | 31 | ||||
-rw-r--r-- | drivers/tty/serial/mxs-auart.c | 8 | ||||
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 11 | ||||
-rw-r--r-- | drivers/tty/serial/serial_core.c | 28 | ||||
-rw-r--r-- | drivers/tty/serial/stm32-usart.h | 2 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 2 | ||||
-rw-r--r-- | drivers/tty/vt/selection.c | 6 |
24 files changed, 303 insertions, 200 deletions
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index cc2b4d9433ed..b811442c5ce6 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 7f657bb5113c..1c1bd0afcd48 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 015686ff4825..bdd3027ef01b 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 68cbc03aab4b..250a19f042d7 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 8ce89fd36c7b..563d2dce80b3 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 5131bdc9e765..48e791d95f76 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2955,7 +2955,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 +2963,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 1bef39828ca7..28133dbd2808 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -132,6 +132,33 @@ void serdev_device_close(struct serdev_device *serdev) } EXPORT_SYMBOL_GPL(serdev_device_close); +static void devm_serdev_device_release(struct device *dev, void *dr) +{ + serdev_device_close(*(struct serdev_device **)dr); +} + +int devm_serdev_device_open(struct device *dev, struct serdev_device *serdev) +{ + struct serdev_device **dr; + int ret; + + dr = devres_alloc(devm_serdev_device_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + ret = serdev_device_open(serdev); + if (ret) { + devres_free(dr); + return ret; + } + + *dr = serdev; + devres_add(dev, dr); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_serdev_device_open); + void serdev_device_write_wakeup(struct serdev_device *serdev) { complete(&serdev->write_comp); @@ -268,8 +295,8 @@ static int serdev_drv_probe(struct device *dev) static int serdev_drv_remove(struct device *dev) { const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver); - - sdrv->remove(to_serdev_device(dev)); + if (sdrv->remove) + sdrv->remove(to_serdev_device(dev)); return 0; } diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 247788a16f0b..a5abb05be67d 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 5bb0c42c88dd..bda75d317d24 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -515,7 +515,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_omap.c b/drivers/tty/serial/8250/8250_omap.c index bd40ba402410..57f6eba47f44 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/Kconfig b/drivers/tty/serial/8250/Kconfig index a5c0ef1e7695..16b1496e6105 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 b788fee54249..3682fd3e960c 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 04af8de8617e..4b40a5b449ee 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 efa25611ca0c..df46a9e88c34 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 1c4d3f387138..8cf112f2efc3 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 e4b3d9123a03..c2b29fd66e8a 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -703,25 +703,6 @@ out: 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 | diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index ecb6513a6505..97576ff791db 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); + } - if (sts & port->ignore_status_mask) - continue; + } 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; + } - uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag); + 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 (uart_handle_sysrq_char(port, ch)) + continue; + + 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; @@ -1089,7 +1162,7 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip, #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 +1242,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 +1293,26 @@ 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.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 +1366,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 +1377,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 +1399,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 daafe60175da..8a842591b37c 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 efb4fd3784ed..5b470406bf9d 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -1721,7 +1721,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 +1735,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 53d59e9b944a..56e683373d6d 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1611,10 +1611,15 @@ 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); @@ -1632,8 +1637,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 854995e1cae7..f57969de2f1c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3013,19 +3013,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 +3036,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 8a5ff54d0f42..2294d0f05872 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 dc60aeea87d8..a6ca634411e1 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1476,6 +1476,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/vt/selection.c b/drivers/tty/vt/selection.c index af4da9507180..7851383fbd6c 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(); |