diff options
Diffstat (limited to 'drivers/tty/serial')
23 files changed, 398 insertions, 150 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 45d9117cab68..fc118f649887 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1026,7 +1026,9 @@ int serial8250_register_8250_port(struct uart_8250_port *up) if (up->port.dev) { uart->port.dev = up->port.dev; - uart_get_rs485_mode(uart->port.dev, &uart->port.rs485); + ret = uart_get_rs485_mode(&uart->port); + if (ret) + goto err; } if (up->port.flags & UPF_FIXED_TYPE) @@ -1040,7 +1042,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up) gpios = mctrl_gpio_init(&uart->port, 0); if (IS_ERR(gpios)) { ret = PTR_ERR(gpios); - goto out_unlock; + goto err; } else { uart->gpios = gpios; } @@ -1089,8 +1091,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up) serial8250_apply_quirks(uart); ret = uart_add_one_port(&serial8250_reg, &uart->port); - if (ret == 0) - ret = uart->port.line; + if (ret) + goto err; + + ret = uart->port.line; } else { dev_info(uart->port.dev, "skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n", @@ -1112,10 +1116,14 @@ int serial8250_register_8250_port(struct uart_8250_port *up) } } -out_unlock: mutex_unlock(&serial_mutex); return ret; + +err: + uart->port.dev = NULL; + mutex_unlock(&serial_mutex); + return ret; } EXPORT_SYMBOL(serial8250_register_8250_port); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 59449b6500cd..ddb6aeb76dc5 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -25,13 +25,13 @@ #include "8250.h" -#define PCI_DEVICE_ID_ACCES_COM_2S 0x1052 -#define PCI_DEVICE_ID_ACCES_COM_4S 0x105d -#define PCI_DEVICE_ID_ACCES_COM_8S 0x106c -#define PCI_DEVICE_ID_ACCES_COM232_8 0x10a8 -#define PCI_DEVICE_ID_ACCES_COM_2SM 0x10d2 -#define PCI_DEVICE_ID_ACCES_COM_4SM 0x10db -#define PCI_DEVICE_ID_ACCES_COM_8SM 0x10ea +#define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052 +#define PCI_DEVICE_ID_ACCESSIO_COM_4S 0x105d +#define PCI_DEVICE_ID_ACCESSIO_COM_8S 0x106c +#define PCI_DEVICE_ID_ACCESSIO_COM232_8 0x10a8 +#define PCI_DEVICE_ID_ACCESSIO_COM_2SM 0x10d2 +#define PCI_DEVICE_ID_ACCESSIO_COM_4SM 0x10db +#define PCI_DEVICE_ID_ACCESSIO_COM_8SM 0x10ea #define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002 #define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004 @@ -755,9 +755,7 @@ static const struct exar8250_board pbn_exar_XR17V8358 = { (kernel_ulong_t)&bd \ } -#define EXAR_DEVICE(vend, devid, bd) { \ - PCI_VDEVICE(vend, PCI_DEVICE_ID_##devid), (kernel_ulong_t)&bd \ - } +#define EXAR_DEVICE(vend, devid, bd) { PCI_DEVICE_DATA(vend, devid, &bd) } #define IBM_DEVICE(devid, sdevid, bd) { \ PCI_DEVICE_SUB( \ @@ -769,14 +767,13 @@ static const struct exar8250_board pbn_exar_XR17V8358 = { } static const struct pci_device_id exar_pci_tbl[] = { - EXAR_DEVICE(ACCESSIO, ACCES_COM_2S, acces_com_2x), - EXAR_DEVICE(ACCESSIO, ACCES_COM_4S, acces_com_4x), - EXAR_DEVICE(ACCESSIO, ACCES_COM_8S, acces_com_8x), - EXAR_DEVICE(ACCESSIO, ACCES_COM232_8, acces_com_8x), - EXAR_DEVICE(ACCESSIO, ACCES_COM_2SM, acces_com_2x), - EXAR_DEVICE(ACCESSIO, ACCES_COM_4SM, acces_com_4x), - EXAR_DEVICE(ACCESSIO, ACCES_COM_8SM, acces_com_8x), - + EXAR_DEVICE(ACCESSIO, COM_2S, acces_com_2x), + EXAR_DEVICE(ACCESSIO, COM_4S, acces_com_4x), + EXAR_DEVICE(ACCESSIO, COM_8S, acces_com_8x), + EXAR_DEVICE(ACCESSIO, COM232_8, acces_com_8x), + EXAR_DEVICE(ACCESSIO, COM_2SM, acces_com_2x), + EXAR_DEVICE(ACCESSIO, COM_4SM, acces_com_4x), + EXAR_DEVICE(ACCESSIO, COM_8SM, acces_com_8x), CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect), CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect), @@ -794,24 +791,24 @@ static const struct pci_device_id exar_pci_tbl[] = { IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn), /* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */ - EXAR_DEVICE(EXAR, EXAR_XR17C152, pbn_exar_XR17C15x), - EXAR_DEVICE(EXAR, EXAR_XR17C154, pbn_exar_XR17C15x), - EXAR_DEVICE(EXAR, EXAR_XR17C158, pbn_exar_XR17C15x), + EXAR_DEVICE(EXAR, XR17C152, pbn_exar_XR17C15x), + EXAR_DEVICE(EXAR, XR17C154, pbn_exar_XR17C15x), + EXAR_DEVICE(EXAR, XR17C158, pbn_exar_XR17C15x), /* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs */ - EXAR_DEVICE(EXAR, EXAR_XR17V352, pbn_exar_XR17V35x), - EXAR_DEVICE(EXAR, EXAR_XR17V354, pbn_exar_XR17V35x), - EXAR_DEVICE(EXAR, EXAR_XR17V358, pbn_exar_XR17V35x), - EXAR_DEVICE(EXAR, EXAR_XR17V4358, pbn_exar_XR17V4358), - EXAR_DEVICE(EXAR, EXAR_XR17V8358, pbn_exar_XR17V8358), - EXAR_DEVICE(COMMTECH, COMMTECH_4222PCIE, pbn_exar_XR17V35x), - EXAR_DEVICE(COMMTECH, COMMTECH_4224PCIE, pbn_exar_XR17V35x), - EXAR_DEVICE(COMMTECH, COMMTECH_4228PCIE, pbn_exar_XR17V35x), - - EXAR_DEVICE(COMMTECH, COMMTECH_4222PCI335, pbn_fastcom335_2), - EXAR_DEVICE(COMMTECH, COMMTECH_4224PCI335, pbn_fastcom335_4), - EXAR_DEVICE(COMMTECH, COMMTECH_2324PCI335, pbn_fastcom335_4), - EXAR_DEVICE(COMMTECH, COMMTECH_2328PCI335, pbn_fastcom335_8), + EXAR_DEVICE(EXAR, XR17V352, pbn_exar_XR17V35x), + EXAR_DEVICE(EXAR, XR17V354, pbn_exar_XR17V35x), + EXAR_DEVICE(EXAR, XR17V358, pbn_exar_XR17V35x), + EXAR_DEVICE(EXAR, XR17V4358, pbn_exar_XR17V4358), + EXAR_DEVICE(EXAR, XR17V8358, pbn_exar_XR17V8358), + EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_exar_XR17V35x), + EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_exar_XR17V35x), + EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_exar_XR17V35x), + + EXAR_DEVICE(COMMTECH, 4222PCI335, pbn_fastcom335_2), + EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4), + EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4), + EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8), { 0, } }; MODULE_DEVICE_TABLE(pci, exar_pci_tbl); diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 31c91c2f8c6e..d1d253c4b518 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -19,6 +19,7 @@ #define CHIP_ID2 0x21 #define CHIP_ID_F81865 0x0407 #define CHIP_ID_F81866 0x1010 +#define CHIP_ID_F81966 0x0215 #define CHIP_ID_F81216AD 0x1602 #define CHIP_ID_F81216H 0x0501 #define CHIP_ID_F81216 0x0802 @@ -62,9 +63,9 @@ #define F81216_LDN_HIGH 0x4 /* - * F81866 registers + * F81866/966 registers * - * The IRQ setting mode of F81866 is not the same with F81216 series. + * The IRQ setting mode of F81866/966 is not the same with F81216 series. * Level/Low: IRQ_MODE0:0, IRQ_MODE1:0 * Edge/High: IRQ_MODE0:1, IRQ_MODE1:0 * @@ -155,6 +156,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata) switch (chip) { case CHIP_ID_F81865: case CHIP_ID_F81866: + case CHIP_ID_F81966: case CHIP_ID_F81216AD: case CHIP_ID_F81216H: case CHIP_ID_F81216: @@ -171,6 +173,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, int *max) { switch (pdata->pid) { + case CHIP_ID_F81966: case CHIP_ID_F81865: case CHIP_ID_F81866: *min = F81866_LDN_LOW; @@ -248,6 +251,7 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) sio_write_reg(pdata, LDN, pdata->index); switch (pdata->pid) { + case CHIP_ID_F81966: case CHIP_ID_F81866: sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1, 0); @@ -274,6 +278,7 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) { switch (pdata->pid) { case CHIP_ID_F81216H: /* 128Bytes FIFO */ + case CHIP_ID_F81966: case CHIP_ID_F81866: sio_write_mask_reg(pdata, FIFO_CTRL, FIFO_MODE_MASK | RXFTHR_MODE_MASK, @@ -291,6 +296,7 @@ static void fintek_8250_goto_highspeed(struct uart_8250_port *uart, sio_write_reg(pdata, LDN, pdata->index); switch (pdata->pid) { + case CHIP_ID_F81966: case CHIP_ID_F81866: /* set uart clock for high speed serial mode */ sio_write_mask_reg(pdata, F81866_UART_CLK, F81866_UART_CLK_MASK, @@ -327,6 +333,7 @@ static void fintek_8250_set_termios(struct uart_port *port, case CHIP_ID_F81216H: reg = RS485; break; + case CHIP_ID_F81966: case CHIP_ID_F81866: reg = F81866_UART_CLK; break; @@ -373,6 +380,7 @@ static void fintek_8250_set_termios_handler(struct uart_8250_port *uart) switch (pdata->pid) { case CHIP_ID_F81216H: + case CHIP_ID_F81966: case CHIP_ID_F81866: uart->port.set_termios = fintek_8250_set_termios; break; @@ -443,6 +451,7 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) switch (pdata->pid) { case CHIP_ID_F81216AD: case CHIP_ID_F81216H: + case CHIP_ID_F81966: case CHIP_ID_F81866: case CHIP_ID_F81865: uart->port.rs485_config = fintek_8250_rs485_config; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index f77bf820b7a3..1632f7d25acc 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -681,6 +681,9 @@ int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) memset(rs485->padding, 0, sizeof(rs485->padding)); port->rs485 = *rs485; + gpiod_set_value(port->rs485_term_gpio, + rs485->flags & SER_RS485_TERMINATE_BUS); + /* * Both serial8250_em485_init() and serial8250_em485_destroy() * are idempotent. @@ -1432,7 +1435,7 @@ static void serial8250_stop_rx(struct uart_port *port) /** * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback - * @up: uart 8250 port + * @p: uart 8250 port * * Generic callback usable by 8250 uart drivers to stop rs485 transmission. */ @@ -2615,6 +2618,8 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { + unsigned int tolerance = port->uartclk / 100; + /* * Ask the core to calculate the divisor for us. * Allow 1% tolerance at the upper limit so uart clks marginally @@ -2623,7 +2628,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, */ return uart_get_baud_rate(port, termios, old, port->uartclk / 16 / UART_DIV_MAX, - port->uartclk); + (port->uartclk + tolerance) / 16); } void diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index af0688156dd0..8195a31519ea 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -63,6 +63,7 @@ config SERIAL_8250_PNP config SERIAL_8250_16550A_VARIANTS bool "Support for variants of the 16550A serial port" depends on SERIAL_8250 + default !X86 help The 8250 driver can probe for many variants of the venerable 16550A serial port. Doing so takes additional time at boot. diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index c8186a05a453..e3d10794dbba 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -440,7 +440,7 @@ static int simple_config_check_notpicky(struct pcmcia_device *p_dev, static int simple_config(struct pcmcia_device *link) { struct serial_info *info = link->priv; - int i = -ENODEV, try; + int ret, try; /* * First pass: look for a config entry that looks normal. @@ -472,8 +472,8 @@ found_port: if (info->quirk && info->quirk->config) info->quirk->config(link); - i = pcmcia_enable_device(link); - if (i != 0) + ret = pcmcia_enable_device(link); + if (ret != 0) return -1; return setup_serial(link, info, link->resource[0]->start, link->irq); } diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index adf9e80e7dc9..0282ad9cdaa7 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1034,13 +1034,22 @@ config SERIAL_SIFIVE_CONSOLE boot time.) config SERIAL_LANTIQ - bool "Lantiq serial driver" - depends on LANTIQ + tristate "Lantiq serial driver" + depends on (LANTIQ || X86) || COMPILE_TEST select SERIAL_CORE + help + Support for UART on Lantiq and Intel SoCs. + To compile this driver as a module, select M here. The + module will be called lantiq. + +config SERIAL_LANTIQ_CONSOLE + bool "Console on Lantiq UART" + depends on SERIAL_LANTIQ=y select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON help - Support for console and UART on Lantiq SoCs. + Select this option if you would like to use a Lantiq UART as the + system console. config SERIAL_QE tristate "Freescale QUICC Engine serial port support" @@ -1462,6 +1471,7 @@ config SERIAL_STM32 tristate "STMicroelectronics STM32 serial port support" select SERIAL_CORE depends on ARCH_STM32 || COMPILE_TEST + select SERIAL_MCTRL_GPIO if GPIOLIB help This driver is for the on-chip Serial Controller on STMicroelectronics STM32 MCUs. diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c010f639298d..8efd7c2a34fe 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2607,6 +2607,7 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = index; + spin_lock_init(&uap->port.lock); amba_ports[index] = uap; diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 7e7f1398019f..0c80a79d7442 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -766,8 +766,6 @@ static int ar933x_uart_probe(struct platform_device *pdev) goto err_disable_clk; } - uart_get_rs485_mode(&pdev->dev, &port->rs485); - port->mapbase = mem_res->start; port->line = id; port->irq = irq_res->start; @@ -786,6 +784,10 @@ static int ar933x_uart_probe(struct platform_device *pdev) baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP); up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD); + ret = uart_get_rs485_mode(port); + if (ret) + goto err_disable_clk; + up->gpios = mctrl_gpio_init(port, 0); if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) return PTR_ERR(up->gpios); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 8d7080efad9b..e43471b33710 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2491,8 +2491,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, atmel_init_property(atmel_port, pdev); atmel_set_ops(port); - uart_get_rs485_mode(&mpdev->dev, &port->rs485); - port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; port->ops = &atmel_pops; @@ -2506,6 +2504,10 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); + ret = uart_get_rs485_mode(port); + if (ret) + return ret; + /* for console, the clock could already be configured */ if (!atmel_port->clk) { atmel_port->clk = clk_get(&mpdev->dev, "usart"); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 5d41075964f2..90298c403042 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1231,9 +1231,7 @@ static void lpuart_dma_rx_free(struct uart_port *port) struct lpuart_port, port); struct dma_chan *chan = sport->dma_rx_chan; - if (chan) - dmaengine_terminate_all(chan); - + dmaengine_terminate_all(chan); dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); kfree(sport->rx_ring.buf); sport->rx_ring.tail = 0; @@ -1514,17 +1512,17 @@ static void lpuart_request_dma(struct lpuart_port *sport) { sport->dma_tx_chan = dma_request_chan(sport->port.dev, "tx"); if (IS_ERR(sport->dma_tx_chan)) { - dev_info_once(sport->port.dev, - "DMA tx channel request failed, operating without tx DMA (%ld)\n", - PTR_ERR(sport->dma_tx_chan)); + dev_dbg_once(sport->port.dev, + "DMA tx channel request failed, operating without tx DMA (%ld)\n", + PTR_ERR(sport->dma_tx_chan)); sport->dma_tx_chan = NULL; } sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx"); if (IS_ERR(sport->dma_rx_chan)) { - dev_info_once(sport->port.dev, - "DMA rx channel request failed, operating without rx DMA (%ld)\n", - PTR_ERR(sport->dma_rx_chan)); + dev_dbg_once(sport->port.dev, + "DMA rx channel request failed, operating without rx DMA (%ld)\n", + PTR_ERR(sport->dma_rx_chan)); sport->dma_rx_chan = NULL; } } @@ -2621,7 +2619,9 @@ static int lpuart_probe(struct platform_device *pdev) if (ret) goto failed_attach_port; - uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); + ret = uart_get_rs485_mode(&sport->port); + if (ret) + goto failed_get_rs485; if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); @@ -2634,6 +2634,7 @@ static int lpuart_probe(struct platform_device *pdev) return 0; +failed_get_rs485: failed_attach_port: failed_irq_request: lpuart_disable_clks(sport); @@ -2664,8 +2665,7 @@ static int lpuart_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int lpuart_suspend(struct device *dev) +static int __maybe_unused lpuart_suspend(struct device *dev) { struct lpuart_port *sport = dev_get_drvdata(dev); unsigned long temp; @@ -2723,7 +2723,7 @@ static int lpuart_suspend(struct device *dev) return 0; } -static int lpuart_resume(struct device *dev) +static int __maybe_unused lpuart_resume(struct device *dev) { struct lpuart_port *sport = dev_get_drvdata(dev); bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq)); @@ -2754,7 +2754,6 @@ static int lpuart_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index f4d68109bc8b..1265e8d86d8a 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -909,6 +909,8 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) usr2 &= ~USR2_ORE; if (usr1 & (USR1_RRDY | USR1_AGTIM)) { + imx_uart_writel(sport, USR1_AGTIM, USR1); + __imx_uart_rxint(irq, dev_id); ret = IRQ_HANDLED; } @@ -2252,6 +2254,8 @@ static int imx_uart_probe(struct platform_device *pdev) return PTR_ERR(base); rxirq = platform_get_irq(pdev, 0); + if (rxirq < 0) + return rxirq; txirq = platform_get_irq_optional(pdev, 1); rtsirq = platform_get_irq_optional(pdev, 2); @@ -2302,7 +2306,11 @@ static int imx_uart_probe(struct platform_device *pdev) sport->ucr4 = readl(sport->port.membase + UCR4); sport->ufcr = readl(sport->port.membase + UFCR); - uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); + ret = uart_get_rs485_mode(&sport->port); + if (ret) { + clk_disable_unprepare(sport->clk_ipg); + return ret; + } if (sport->port.rs485.flags & SER_RS485_ENABLED && (!sport->have_rtscts && !sport->have_rtsgpio)) @@ -2398,6 +2406,9 @@ static int imx_uart_probe(struct platform_device *pdev) } } + /* We need to initialize lock even for non-registered console */ + spin_lock_init(&sport->port.lock); + imx_uart_ports[sport->port.line] = sport; platform_set_drvdata(pdev, sport); diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index c5e46ff972e4..62813e421f12 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -15,6 +15,7 @@ #include <linux/io.h> #include <linux/ioport.h> #include <linux/lantiq.h> +#include <linux/module.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> @@ -597,6 +598,7 @@ static const struct uart_ops lqasc_pops = { .verify_port = lqasc_verify_port, }; +#ifdef CONFIG_SERIAL_LANTIQ_CONSOLE static void lqasc_console_putchar(struct uart_port *port, int ch) { @@ -705,6 +707,14 @@ lqasc_serial_early_console_setup(struct earlycon_device *device, OF_EARLYCON_DECLARE(lantiq, "lantiq,asc", lqasc_serial_early_console_setup); OF_EARLYCON_DECLARE(lantiq, "intel,lgm-asc", lqasc_serial_early_console_setup); +#define LANTIQ_SERIAL_CONSOLE (&lqasc_console) + +#else + +#define LANTIQ_SERIAL_CONSOLE NULL + +#endif /* CONFIG_SERIAL_LANTIQ_CONSOLE */ + static struct uart_driver lqasc_reg = { .owner = THIS_MODULE, .driver_name = DRVNAME, @@ -712,7 +722,7 @@ static struct uart_driver lqasc_reg = { .major = 0, .minor = 0, .nr = MAXPORTS, - .cons = &lqasc_console, + .cons = LANTIQ_SERIAL_CONSOLE, }; static int fetch_irq_lantiq(struct device *dev, struct ltq_uart_port *ltq_port) @@ -814,8 +824,7 @@ static void free_irq_intel(struct uart_port *port) free_irq(ltq_port->common_irq, port); } -static int __init -lqasc_probe(struct platform_device *pdev) +static int lqasc_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct ltq_uart_port *ltq_port; @@ -899,6 +908,13 @@ lqasc_probe(struct platform_device *pdev) return ret; } +static int lqasc_remove(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + + return uart_remove_one_port(&lqasc_reg, port); +} + static const struct ltq_soc_data soc_data_lantiq = { .fetch_irq = fetch_irq_lantiq, .request_irq = request_irq_lantiq, @@ -916,8 +932,11 @@ static const struct of_device_id ltq_asc_match[] = { { .compatible = "intel,lgm-asc", .data = &soc_data_intel }, {}, }; +MODULE_DEVICE_TABLE(of, ltq_asc_match); static struct platform_driver lqasc_driver = { + .probe = lqasc_probe, + .remove = lqasc_remove, .driver = { .name = DRVNAME, .of_match_table = ltq_asc_match, @@ -933,10 +952,21 @@ init_lqasc(void) if (ret != 0) return ret; - ret = platform_driver_probe(&lqasc_driver, lqasc_probe); + ret = platform_driver_register(&lqasc_driver); if (ret != 0) uart_unregister_driver(&lqasc_reg); return ret; } -device_initcall(init_lqasc); + +static void __exit exit_lqasc(void) +{ + platform_driver_unregister(&lqasc_driver); + uart_unregister_driver(&lqasc_reg); +} + +module_init(init_lqasc); +module_exit(exit_lqasc); + +MODULE_DESCRIPTION("Serial driver for Lantiq & Intel gateway SoCs"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c index 9a836dcac157..b5898c932036 100644 --- a/drivers/tty/serial/lpc32xx_hs.c +++ b/drivers/tty/serial/lpc32xx_hs.c @@ -23,7 +23,6 @@ #include <linux/nmi.h> #include <linux/io.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/of.h> #include <linux/sizes.h> #include <linux/soc/nxp/lpc32xx-misc.h> diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index f7d6b3c9ea45..8573fc9cb0cd 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -33,8 +33,7 @@ #include <linux/pm_wakeirq.h> #include <linux/of.h> #include <linux/of_irq.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/platform_data/serial-omap.h> #define OMAP_MAX_HSUART_PORTS 10 @@ -153,7 +152,7 @@ struct uart_omap_port { u32 errata; u32 features; - int rts_gpio; + struct gpio_desc *rts_gpiod; struct pm_qos_request pm_qos_request; u32 latency; @@ -303,11 +302,11 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_OMAP_SCR, up->scr); res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; - if (gpio_get_value(up->rts_gpio) != res) { + if (gpiod_get_value(up->rts_gpiod) != res) { if (port->rs485.delay_rts_after_send > 0) mdelay( port->rs485.delay_rts_after_send); - gpio_set_value(up->rts_gpio, res); + gpiod_set_value(up->rts_gpiod, res); } } else { /* We're asked to stop, but there's still stuff in the @@ -412,8 +411,8 @@ static void serial_omap_start_tx(struct uart_port *port) /* if rts not already enabled */ res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; - if (gpio_get_value(up->rts_gpio) != res) { - gpio_set_value(up->rts_gpio, res); + if (gpiod_get_value(up->rts_gpiod) != res) { + gpiod_set_value(up->rts_gpiod, res); if (port->rs485.delay_rts_before_send > 0) mdelay(port->rs485.delay_rts_before_send); } @@ -1414,12 +1413,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) * Just as a precaution, only allow rs485 * to be enabled if the gpio pin is valid */ - if (gpio_is_valid(up->rts_gpio)) { + if (up->rts_gpiod) { /* enable / disable rts */ val = (port->rs485.flags & SER_RS485_ENABLED) ? SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND; val = (port->rs485.flags & val) ? 1 : 0; - gpio_set_value(up->rts_gpio, val); + gpiod_set_value(up->rts_gpiod, val); } else port->rs485.flags &= ~SER_RS485_ENABLED; @@ -1596,18 +1595,22 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev) } static int serial_omap_probe_rs485(struct uart_omap_port *up, - struct device_node *np) + struct device *dev) { struct serial_rs485 *rs485conf = &up->port.rs485; + struct device_node *np = dev->of_node; + enum gpiod_flags gflags; int ret; rs485conf->flags = 0; - up->rts_gpio = -EINVAL; + up->rts_gpiod = NULL; if (!np) return 0; - uart_get_rs485_mode(up->dev, rs485conf); + ret = uart_get_rs485_mode(&up->port); + if (ret) + return ret; if (of_property_read_bool(np, "rs485-rts-active-high")) { rs485conf->flags |= SER_RS485_RTS_ON_SEND; @@ -1618,19 +1621,20 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, } /* check for tx enable gpio */ - 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 = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ? 1 : 0; - ret = gpio_direction_output(up->rts_gpio, ret); - if (ret < 0) + gflags = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ? + GPIOD_OUT_HIGH : GPIOD_OUT_LOW; + up->rts_gpiod = devm_gpiod_get_optional(dev, "rts", gflags); + if (IS_ERR(up->rts_gpiod)) { + ret = PTR_ERR(up->rts_gpiod); + if (ret == -EPROBE_DEFER) return ret; - } else if (up->rts_gpio == -EPROBE_DEFER) { - return -EPROBE_DEFER; + /* + * FIXME: the code historically ignored any other error than + * -EPROBE_DEFER and just went on without GPIO. + */ + up->rts_gpiod = NULL; } else { - up->rts_gpio = -EINVAL; + gpiod_set_consumer_name(up->rts_gpiod, "omap-serial"); } return 0; @@ -1703,7 +1707,7 @@ static int serial_omap_probe(struct platform_device *pdev) dev_info(up->port.dev, "no wakeirq for uart%d\n", up->port.line); - ret = serial_omap_probe_rs485(up, pdev->dev.of_node); + ret = serial_omap_probe_rs485(up, &pdev->dev); if (ret < 0) goto err_rs485; diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 6bace1c6bb09..457c0bf8cbf8 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -141,9 +141,10 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport); static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop); static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200, - 32000000, 48000000, 64000000, 80000000, - 96000000, 100000000, 102400000, - 112000000, 120000000, 128000000}; + 32000000, 48000000, 51200000, 64000000, + 80000000, 96000000, 100000000, + 102400000, 112000000, 120000000, + 128000000}; #define to_dev_port(ptr, member) \ container_of(ptr, struct qcom_geni_serial_port, member) diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 73f951d65b93..d913d9b2762a 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -154,10 +154,33 @@ struct s3c24xx_uart_port { #define portaddrl(port, reg) \ ((unsigned long *)(unsigned long)((port)->membase + (reg))) -#define rd_regb(port, reg) (readb_relaxed(portaddr(port, reg))) +static u32 rd_reg(struct uart_port *port, u32 reg) +{ + switch (port->iotype) { + case UPIO_MEM: + return readb_relaxed(portaddr(port, reg)); + case UPIO_MEM32: + return readl_relaxed(portaddr(port, reg)); + default: + return 0; + } + return 0; +} + #define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg))) -#define wr_regb(port, reg, val) writeb_relaxed(val, portaddr(port, reg)) +static void wr_reg(struct uart_port *port, u32 reg, u32 val) +{ + switch (port->iotype) { + case UPIO_MEM: + writeb_relaxed(val, portaddr(port, reg)); + break; + case UPIO_MEM32: + writel_relaxed(val, portaddr(port, reg)); + break; + } +} + #define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg)) /* Byte-order aware bit setting/clearing functions. */ @@ -714,7 +737,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) fifocnt--; uerstat = rd_regl(port, S3C2410_UERSTAT); - ch = rd_regb(port, S3C2410_URXH); + ch = rd_reg(port, S3C2410_URXH); if (port->flags & UPF_CONS_FLOW) { int txe = s3c24xx_serial_txempty_nofifo(port); @@ -826,7 +849,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) } if (port->x_char) { - wr_regb(port, S3C2410_UTXH, port->x_char); + wr_reg(port, S3C2410_UTXH, port->x_char); port->icount.tx++; port->x_char = 0; goto out; @@ -852,7 +875,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) break; - wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); + wr_reg(port, S3C2410_UTXH, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; count--; @@ -916,7 +939,7 @@ static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) /* no modem control lines */ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) { - unsigned int umstat = rd_regb(port, S3C2410_UMSTAT); + unsigned int umstat = rd_reg(port, S3C2410_UMSTAT); if (umstat & S3C2410_UMSTAT_CTS) return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; @@ -1281,14 +1304,14 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, struct s3c24xx_uart_info *info = ourport->info; struct clk *clk; unsigned long rate; - unsigned int cnt, baud, quot, clk_sel, best_quot = 0; + unsigned int cnt, baud, quot, best_quot = 0; char clkname[MAX_CLK_NAME_LENGTH]; int calc_deviation, deviation = (1 << 30) - 1; - clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel : - ourport->info->def_clk_sel; for (cnt = 0; cnt < info->num_clks; cnt++) { - if (!(clk_sel & (1 << cnt))) + /* Keep selected clock if provided */ + if (ourport->cfg->clk_sel && + !(ourport->cfg->clk_sel & (1 << cnt))) continue; sprintf(clkname, "clk_uart_baud%d", cnt); @@ -1974,7 +1997,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct s3c24xx_uart_port *ourport; int index = probe_index; - int ret; + int ret, prop = 0; if (np) { ret = of_alias_get_id(np, "serial"); @@ -2000,10 +2023,27 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) dev_get_platdata(&pdev->dev) : ourport->drv_data->def_cfg; - if (np) + if (np) { of_property_read_u32(np, "samsung,uart-fifosize", &ourport->port.fifosize); + if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { + switch (prop) { + case 1: + ourport->port.iotype = UPIO_MEM; + break; + case 4: + ourport->port.iotype = UPIO_MEM32; + break; + default: + dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n", + prop); + ret = -EINVAL; + break; + } + } + } + if (ourport->drv_data->fifosize[index]) ourport->port.fifosize = ourport->drv_data->fifosize[index]; else if (ourport->info->fifosize) @@ -2185,7 +2225,7 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port) if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) return NO_POLL_CHAR; - return rd_regb(port, S3C2410_URXH); + return rd_reg(port, S3C2410_URXH); } static void s3c24xx_serial_put_poll_char(struct uart_port *port, @@ -2200,7 +2240,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port, while (!s3c24xx_serial_console_txrdy(port, ufcon)) cpu_relax(); - wr_regb(port, S3C2410_UTXH, c); + wr_reg(port, S3C2410_UTXH, c); } #endif /* CONFIG_CONSOLE_POLL */ @@ -2212,7 +2252,7 @@ s3c24xx_serial_console_putchar(struct uart_port *port, int ch) while (!s3c24xx_serial_console_txrdy(port, ufcon)) cpu_relax(); - wr_regb(port, S3C2410_UTXH, ch); + wr_reg(port, S3C2410_UTXH, ch); } static void @@ -2587,6 +2627,18 @@ module_platform_driver(samsung_serial_driver); * Early console. */ +static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val) +{ + switch (port->iotype) { + case UPIO_MEM: + writeb(val, portaddr(port, reg)); + break; + case UPIO_MEM32: + writel(val, portaddr(port, reg)); + break; + } +} + struct samsung_early_console_data { u32 txfull_mask; }; @@ -2612,7 +2664,7 @@ static void samsung_early_putc(struct uart_port *port, int c) else samsung_early_busyuart(port); - writeb(c, port->membase + S3C2410_UTXH); + wr_reg_barrier(port, S3C2410_UTXH, c); } static void samsung_early_write(struct console *con, const char *s, diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 06e8071d5601..d2e5c6c86643 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -315,6 +315,7 @@ struct sc16is7xx_one { struct kthread_work tx_work; struct kthread_work reg_work; struct sc16is7xx_one_config config; + bool irda_mode; }; struct sc16is7xx_port { @@ -327,7 +328,6 @@ struct sc16is7xx_port { unsigned char buf[SC16IS7XX_FIFO_SIZE]; struct kthread_worker kworker; struct task_struct *kworker_task; - struct kthread_work irq_work; struct mutex efr_lock; struct sc16is7xx_one p[]; }; @@ -710,9 +710,9 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) return true; } -static void sc16is7xx_ist(struct kthread_work *ws) +static irqreturn_t sc16is7xx_irq(int irq, void *dev_id) { - struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work); + struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id; mutex_lock(&s->efr_lock); @@ -727,13 +727,6 @@ static void sc16is7xx_ist(struct kthread_work *ws) } mutex_unlock(&s->efr_lock); -} - -static irqreturn_t sc16is7xx_irq(int irq, void *dev_id) -{ - struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id; - - kthread_queue_work(&s->kworker, &s->irq_work); return IRQ_HANDLED; } @@ -994,6 +987,7 @@ static int sc16is7xx_config_rs485(struct uart_port *port, static int sc16is7xx_startup(struct uart_port *port) { + struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); struct sc16is7xx_port *s = dev_get_drvdata(port->dev); unsigned int val; @@ -1032,6 +1026,13 @@ static int sc16is7xx_startup(struct uart_port *port) /* Now, initialize the UART */ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8); + /* Enable IrDA mode if requested in DT */ + /* This bit must be written with LCR[7] = 0 */ + sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, + SC16IS7XX_MCR_IRDA_BIT, + one->irda_mode ? + SC16IS7XX_MCR_IRDA_BIT : 0); + /* Enable the Rx and Tx FIFO */ sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, SC16IS7XX_EFCR_RXDISABLE_BIT | @@ -1176,10 +1177,11 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, static int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, - struct regmap *regmap, int irq, unsigned long flags) + struct regmap *regmap, int irq) { struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 }; unsigned long freq = 0, *pfreq = dev_get_platdata(dev); + unsigned int val; u32 uartclk = 0; int i, ret; struct sc16is7xx_port *s; @@ -1187,6 +1189,16 @@ static int sc16is7xx_probe(struct device *dev, if (IS_ERR(regmap)) return PTR_ERR(regmap); + /* + * This device does not have an identification register that would + * tell us if we are really connected to the correct device. + * The best we can do is to check if communication is at all possible. + */ + ret = regmap_read(regmap, + SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val); + if (ret < 0) + return ret; + /* Alloc port structure */ s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL); if (!s) { @@ -1221,7 +1233,6 @@ static int sc16is7xx_probe(struct device *dev, mutex_init(&s->efr_lock); kthread_init_worker(&s->kworker); - kthread_init_work(&s->irq_work, sc16is7xx_ist); s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker, "sc16is7xx"); if (IS_ERR(s->kworker_task)) { @@ -1302,9 +1313,33 @@ static int sc16is7xx_probe(struct device *dev, sc16is7xx_power(&s->p[i].port, 0); } - /* Setup interrupt */ - ret = devm_request_irq(dev, irq, sc16is7xx_irq, - flags, dev_name(dev), s); + if (dev->of_node) { + struct property *prop; + const __be32 *p; + u32 u; + + of_property_for_each_u32(dev->of_node, "irda-mode-ports", + prop, p, u) + if (u < devtype->nr_uart) + s->p[u].irda_mode = true; + } + + /* + * Setup interrupt. We first try to acquire the IRQ line as level IRQ. + * If that succeeds, we can allow sharing the interrupt as well. + * In case the interrupt controller doesn't support that, we fall + * back to a non-shared falling-edge trigger. + */ + ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq, + IRQF_TRIGGER_LOW | IRQF_SHARED | + IRQF_ONESHOT, + dev_name(dev), s); + if (!ret) + return 0; + + ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(dev), s); if (!ret) return 0; @@ -1378,7 +1413,6 @@ static struct regmap_config regcfg = { static int sc16is7xx_spi_probe(struct spi_device *spi) { const struct sc16is7xx_devtype *devtype; - unsigned long flags = 0; struct regmap *regmap; int ret; @@ -1399,14 +1433,13 @@ static int sc16is7xx_spi_probe(struct spi_device *spi) const struct spi_device_id *id_entry = spi_get_device_id(spi); devtype = (struct sc16is7xx_devtype *)id_entry->driver_data; - flags = IRQF_TRIGGER_FALLING; } regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) | (devtype->nr_uart - 1); regmap = devm_regmap_init_spi(spi, ®cfg); - return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq, flags); + return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq); } static int sc16is7xx_spi_remove(struct spi_device *spi) @@ -1445,7 +1478,6 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { const struct sc16is7xx_devtype *devtype; - unsigned long flags = 0; struct regmap *regmap; if (i2c->dev.of_node) { @@ -1454,14 +1486,13 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c, return -ENODEV; } else { devtype = (struct sc16is7xx_devtype *)id->driver_data; - flags = IRQF_TRIGGER_FALLING; } regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) | (devtype->nr_uart - 1); regmap = devm_regmap_init_i2c(i2c, ®cfg); - return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq, flags); + return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq); } static int sc16is7xx_i2c_remove(struct i2c_client *client) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 66a5e2faf57e..57840cf90388 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3295,8 +3295,10 @@ EXPORT_SYMBOL(uart_remove_one_port); * This function implements the device tree binding described in * Documentation/devicetree/bindings/serial/rs485.txt. */ -void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) +int uart_get_rs485_mode(struct uart_port *port) { + struct serial_rs485 *rs485conf = &port->rs485; + struct device *dev = port->dev; u32 rs485_delay[2]; int ret; @@ -3315,6 +3317,7 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) * to get to a defined state with the following properties: */ rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED | + SER_RS485_TERMINATE_BUS | SER_RS485_RTS_AFTER_SEND); rs485conf->flags |= SER_RS485_RTS_ON_SEND; @@ -3328,6 +3331,23 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; } + + /* + * Disabling termination by default is the safe choice: Else if many + * bus participants enable it, no communication is possible at all. + * Works fine for short cables and users may enable for longer cables. + */ + port->rs485_term_gpio = devm_gpiod_get_optional(dev, "rs485-term", + GPIOD_OUT_LOW); + if (IS_ERR(port->rs485_term_gpio)) { + ret = PTR_ERR(port->rs485_term_gpio); + port->rs485_term_gpio = NULL; + if (ret != -EPROBE_DEFER) + dev_err(dev, "Cannot get rs485-term-gpios\n"); + return ret; + } + + return 0; } EXPORT_SYMBOL_GPL(uart_get_rs485_mode); diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index 0b9e804e61a9..c0dfe4382898 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -2,7 +2,6 @@ #include <linux/bitops.h> #include <linux/serial_core.h> #include <linux/io.h> -#include <linux/gpio.h> #define SCI_MAJOR 204 #define SCI_MINOR_START 8 diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 5e93e8d40f59..8602ff357321 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -31,6 +31,7 @@ #include <linux/tty_flip.h> #include <linux/tty.h> +#include "serial_mctrl_gpio.h" #include "stm32-usart.h" static void stm32_stop_tx(struct uart_port *port); @@ -158,9 +159,7 @@ static int stm32_init_rs485(struct uart_port *port, if (!pdev->dev.of_node) return -ENODEV; - uart_get_rs485_mode(&pdev->dev, rs485conf); - - return 0; + return uart_get_rs485_mode(port); } static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, @@ -510,12 +509,29 @@ static void stm32_set_mctrl(struct uart_port *port, unsigned int mctrl) stm32_set_bits(port, ofs->cr3, USART_CR3_RTSE); else stm32_clr_bits(port, ofs->cr3, USART_CR3_RTSE); + + mctrl_gpio_set(stm32_port->gpios, mctrl); } static unsigned int stm32_get_mctrl(struct uart_port *port) { + struct stm32_port *stm32_port = to_stm32_port(port); + unsigned int ret; + /* This routine is used to get signals of: DCD, DSR, RI, and CTS */ - return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; + ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; + + return mctrl_gpio_get(stm32_port->gpios, &ret); +} + +static void stm32_enable_ms(struct uart_port *port) +{ + mctrl_gpio_enable_ms(to_stm32_port(port)->gpios); +} + +static void stm32_disable_ms(struct uart_port *port) +{ + mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); } /* Transmit stop */ @@ -626,6 +642,9 @@ static void stm32_shutdown(struct uart_port *port) u32 val, isr; int ret; + /* Disable modem control interrupts */ + stm32_disable_ms(port); + val = USART_CR1_TXEIE | USART_CR1_TE; val |= stm32_port->cr1_irq | USART_CR1_RE; val |= BIT(cfg->uart_enable_bit); @@ -764,6 +783,12 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, cr3 |= USART_CR3_CTSE | USART_CR3_RTSE; } + /* Handle modem control interrupts */ + if (UART_ENABLE_MS(port, termios->c_cflag)) + stm32_enable_ms(port); + else + stm32_disable_ms(port); + usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud); /* @@ -898,6 +923,7 @@ static const struct uart_ops stm32_uart_ops = { .throttle = stm32_throttle, .unthrottle = stm32_unthrottle, .stop_rx = stm32_stop_rx, + .enable_ms = stm32_enable_ms, .break_ctl = stm32_break_ctl, .startup = stm32_startup, .shutdown = stm32_shutdown, @@ -931,7 +957,9 @@ static int stm32_init_port(struct stm32_port *stm32port, port->rs485_config = stm32_config_rs485; - stm32_init_rs485(port, pdev); + ret = stm32_init_rs485(port, pdev); + if (ret) + return ret; if (stm32port->info->cfg.has_wakeup) { stm32port->wakeirq = platform_get_irq(pdev, 1); @@ -960,11 +988,32 @@ static int stm32_init_port(struct stm32_port *stm32port, stm32port->port.uartclk = clk_get_rate(stm32port->clk); if (!stm32port->port.uartclk) { - clk_disable_unprepare(stm32port->clk); ret = -EINVAL; + goto err_clk; + } + + stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0); + if (IS_ERR(stm32port->gpios)) { + ret = PTR_ERR(stm32port->gpios); + goto err_clk; + } + + /* Both CTS/RTS gpios and "st,hw-flow-ctrl" should not be specified */ + if (stm32port->hw_flow_control) { + if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) || + mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) { + dev_err(&pdev->dev, "Conflicting RTS/CTS config\n"); + ret = -EINVAL; + goto err_clk; + } } return ret; + +err_clk: + clk_disable_unprepare(stm32port->clk); + + return ret; } static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) @@ -1375,7 +1424,18 @@ static int __maybe_unused stm32_serial_suspend(struct device *dev) else stm32_serial_enable_wakeup(port, false); - pinctrl_pm_select_sleep_state(dev); + /* + * When "no_console_suspend" is enabled, keep the pinctrl default state + * and rely on bootloader stage to restore this state upon resume. + * Otherwise, apply the idle or sleep states depending on wakeup + * capabilities. + */ + if (console_suspend_enabled || !uart_console(port)) { + if (device_may_wakeup(dev)) + pinctrl_pm_select_idle_state(dev); + else + pinctrl_pm_select_sleep_state(dev); + } return 0; } diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index db8bf0d4982d..d4c916e78d40 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -274,6 +274,7 @@ struct stm32_port { bool fifoen; int wakeirq; int rdr_mask; /* receive data register mask */ + struct mctrl_gpios *gpios; /* modem control gpios */ }; static struct stm32_port stm32_ports[STM32_MAX_PORTS]; diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 35e9e8faf8de..b9d672af8b65 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1235,9 +1235,7 @@ static void cdns_uart_console_write(struct console *co, const char *s, writel(ctrl, port->membase + CDNS_UART_CR); uart_console_write(port, s, count, cdns_uart_console_putchar); - while ((readl(port->membase + CDNS_UART_SR) & - (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE)) != - CDNS_UART_SR_TXEMPTY) + while (cdns_uart_tx_empty(port) != TIOCSER_TEMT) cpu_relax(); /* restore interrupt state */ @@ -1262,6 +1260,7 @@ static int cdns_uart_console_setup(struct console *co, char *options) int bits = 8; int parity = 'n'; int flow = 'n'; + unsigned long time_out; if (!port->membase) { pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n", @@ -1272,6 +1271,13 @@ static int cdns_uart_console_setup(struct console *co, char *options) if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); + /* Wait for tx_empty before setting up the console */ + time_out = jiffies + usecs_to_jiffies(TX_TIMEOUT); + + while (time_before(jiffies, time_out) && + cdns_uart_tx_empty(port) != TIOCSER_TEMT) + cpu_relax(); + return uart_set_options(port, co, baud, parity, bits, flow); } |