diff options
Diffstat (limited to 'drivers/tty/serial')
25 files changed, 475 insertions, 198 deletions
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index 725a450058f8..7f656fac503f 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -941,7 +941,7 @@ static int brcmuart_probe(struct platform_device *pdev) struct clk *baud_mux_clk; struct uart_8250_port up; struct resource *irq; - void __iomem *membase = 0; + void __iomem *membase = NULL; resource_size_t mapbase = 0; u32 clk_rate = 0; int ret; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 3ffeedc29c83..d502240bbcf2 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -114,6 +114,7 @@ struct exar8250; struct exar8250_platform { int (*rs485_config)(struct uart_port *, struct serial_rs485 *); int (*register_gpio)(struct pci_dev *, struct uart_8250_port *); + void (*unregister_gpio)(struct uart_8250_port *); }; /** @@ -352,9 +353,8 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p) writeb(0x00, p + UART_EXAR_MPIOOD_15_8); } -static void * -__xr17v35x_register_gpio(struct pci_dev *pcidev, - const struct software_node *node) +static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev, + const struct software_node *node) { struct platform_device *pdev; @@ -374,6 +374,12 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev, return pdev; } +static void __xr17v35x_unregister_gpio(struct platform_device *pdev) +{ + device_remove_software_node(&pdev->dev); + platform_device_unregister(pdev); +} + static const struct property_entry exar_gpio_properties[] = { PROPERTY_ENTRY_U32("exar,first-pin", 0), PROPERTY_ENTRY_U32("ngpios", 16), @@ -384,8 +390,7 @@ static const struct software_node exar_gpio_node = { .properties = exar_gpio_properties, }; -static int xr17v35x_register_gpio(struct pci_dev *pcidev, - struct uart_8250_port *port) +static int xr17v35x_register_gpio(struct pci_dev *pcidev, struct uart_8250_port *port) { if (pcidev->vendor == PCI_VENDOR_ID_EXAR) port->port.private_data = @@ -394,6 +399,15 @@ static int xr17v35x_register_gpio(struct pci_dev *pcidev, return 0; } +static void xr17v35x_unregister_gpio(struct uart_8250_port *port) +{ + if (!port->port.private_data) + return; + + __xr17v35x_unregister_gpio(port->port.private_data); + port->port.private_data = NULL; +} + static int generic_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { @@ -419,6 +433,7 @@ static int generic_rs485_config(struct uart_port *port, static const struct exar8250_platform exar8250_default_platform = { .register_gpio = xr17v35x_register_gpio, + .unregister_gpio = xr17v35x_unregister_gpio, .rs485_config = generic_rs485_config, }; @@ -484,6 +499,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev, static const struct exar8250_platform iot2040_platform = { .rs485_config = iot2040_rs485_config, .register_gpio = iot2040_register_gpio, + .unregister_gpio = xr17v35x_unregister_gpio, }; /* @@ -555,17 +571,11 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev, static void pci_xr17v35x_exit(struct pci_dev *pcidev) { + const struct exar8250_platform *platform = exar_get_platform(); struct exar8250 *priv = pci_get_drvdata(pcidev); struct uart_8250_port *port = serial8250_get_port(priv->line[0]); - struct platform_device *pdev; - pdev = port->port.private_data; - if (!pdev) - return; - - device_remove_software_node(&pdev->dev); - platform_device_unregister(pdev); - port->port.private_data = NULL; + platform->unregister_gpio(port); } static inline void exar_misc_clear(struct exar8250 *priv) diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 988bf6bcce42..65402d05eff9 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -209,16 +209,14 @@ static int ingenic_uart_probe(struct platform_device *pdev) struct uart_8250_port uart = {}; struct ingenic_uart_data *data; const struct ingenic_uart_config *cdata; - const struct of_device_id *match; struct resource *regs; int irq, err, line; - match = of_match_device(of_match, &pdev->dev); - if (!match) { + cdata = of_device_get_match_data(&pdev->dev); + if (!cdata) { dev_err(&pdev->dev, "Error: No device match found\n"); return -ENODEV; } - cdata = match->data; irq = platform_get_irq(pdev, 0); if (irq < 0) diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 4dee8a9e0c95..848d81e3838c 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -158,6 +158,16 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port) static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port) { + struct uart_8250_dma *dma = &lpss->data.dma; + struct uart_8250_port *up = up_to_u8250p(port); + + /* + * This simply makes the checks in the 8250_port to try the DMA + * channel request which in turn uses the magic of ACPI tables + * parsing (see drivers/dma/acpi-dma.c for the details) and + * matching with the registered General Purpose DMA controllers. + */ + up->dma = dma; return 0; } diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 79418d4beb48..891fd8345e25 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -538,7 +538,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, static void omap_serial_fill_features_erratas(struct uart_8250_port *up, struct omap8250_priv *priv) { - const struct soc_device_attribute k3_soc_devices[] = { + static const struct soc_device_attribute k3_soc_devices[] = { { .family = "AM65X", }, { .family = "J721E", .revision = "SR1.0" }, { /* sentinel */ } @@ -617,7 +617,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) struct uart_port *port = dev_id; struct omap8250_priv *priv = port->private_data; struct uart_8250_port *up = up_to_u8250p(port); - unsigned int iir; + unsigned int iir, lsr; int ret; #ifdef CONFIG_SERIAL_8250_DMA @@ -628,6 +628,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) #endif serial8250_rpm_get(up); + lsr = serial_port_in(port, UART_LSR); iir = serial_port_in(port, UART_IIR); ret = serial8250_handle_irq(port, iir); @@ -642,6 +643,24 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) serial_port_in(port, UART_RX); } + /* Stop processing interrupts on input overrun */ + if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) { + unsigned long delay; + + up->ier = port->serial_in(port, UART_IER); + if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { + port->ops->stop_rx(port); + } else { + /* Keep restarting the timer until + * the input overrun subsides. + */ + cancel_delayed_work(&up->overrun_backoff); + } + + delay = msecs_to_jiffies(up->overrun_backoff_time_ms); + schedule_delayed_work(&up->overrun_backoff, delay); + } + serial8250_rpm_put(up); return IRQ_RETVAL(ret); @@ -1353,6 +1372,10 @@ static int omap8250_probe(struct platform_device *pdev) } } + if (of_property_read_u32(np, "overrun-throttle-ms", + &up.overrun_backoff_time_ms) != 0) + up.overrun_backoff_time_ms = 0; + priv->wakeirq = irq_of_parse_and_map(np, 1); pdata = of_device_get_match_data(&pdev->dev); diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index a808c283883e..726912b16a55 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -87,7 +87,7 @@ static void moan_device(const char *str, struct pci_dev *dev) static int setup_port(struct serial_private *priv, struct uart_8250_port *port, - int bar, int offset, int regshift) + u8 bar, unsigned int offset, int regshift) { struct pci_dev *dev = priv->dev; diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index de90d681b64c..98e5ee4d0d08 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -13,6 +13,7 @@ #include <linux/pnp.h> #include <linux/string.h> #include <linux/kernel.h> +#include <linux/property.h> #include <linux/serial_core.h> #include <linux/bitops.h> @@ -475,6 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE) uart.port.flags |= UPF_SHARE_IRQ; uart.port.uartclk = 1843200; + device_property_read_u32(&dev->dev, "clock-frequency", &uart.port.uartclk); uart.port.dev = &dev->dev; line = serial8250_register_8250_port(&uart); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1da29a219842..66374704747e 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -122,7 +122,8 @@ static const struct serial8250_config uart_config[] = { .name = "16C950/954", .fifo_size = 128, .tx_loadsz = 128, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01, + .rxtrig_bytes = {16, 32, 112, 120}, /* UART_CAP_EFR breaks billionon CF bluetooth card. */ .flags = UART_CAP_FIFO | UART_CAP_SLEEP, }, diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index d1b3c2373fa4..71ae16de0f90 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -363,7 +363,7 @@ config SERIAL_8250_BCM2835AUX config SERIAL_8250_FSL bool depends on SERIAL_8250_CONSOLE - default PPC || ARM || ARM64 + default PPC || ARM || ARM64 || COMPILE_TEST config SERIAL_8250_DW tristate "Support for Synopsys DesignWare 8250 quirks" @@ -375,7 +375,8 @@ config SERIAL_8250_DW config SERIAL_8250_EM tristate "Support for Emma Mobile integrated serial port" - depends on SERIAL_8250 && ARM && HAVE_CLK + depends on SERIAL_8250 && HAVE_CLK + depends on ARM || COMPILE_TEST help Selecting this option will add support for the integrated serial port hardware found on the Emma Mobile line of processors. @@ -383,7 +384,8 @@ config SERIAL_8250_EM config SERIAL_8250_IOC3 tristate "SGI IOC3 8250 UART support" - depends on SGI_MFD_IOC3 && SERIAL_8250 + depends on SERIAL_8250 + depends on SGI_MFD_IOC3 || COMPILE_TEST select SERIAL_8250_EXTENDED select SERIAL_8250_SHARE_IRQ help @@ -495,7 +497,7 @@ config SERIAL_8250_MID config SERIAL_8250_PXA tristate "PXA serial port support" depends on SERIAL_8250 - depends on ARCH_PXA || ARCH_MMP + depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST help If you have a machine based on an Intel XScale PXA2xx CPU you can enable its onboard serial ports by enabling this option. The option is diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 24282ad99d85..131a6a587acd 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -959,7 +959,7 @@ config SERIAL_VT8500_CONSOLE config SERIAL_OMAP tristate "OMAP serial port support" - depends on ARCH_OMAP2PLUS || COMPILE_TEST + depends on (ARCH_OMAP2PLUS && !SERIAL_8250_OMAP) || COMPILE_TEST select SERIAL_CORE help If you have a machine based on an Texas Instruments OMAP CPU you @@ -1382,7 +1382,7 @@ config SERIAL_ST_ASC select SERIAL_CORE depends on ARM || COMPILE_TEST help - This driver is for the on-chip Asychronous Serial Controller on + This driver is for the on-chip Asynchronous Serial Controller on STMicroelectronics STi SoCs. ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality. It support all industry standard baud rates. diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e14f3378b8a0..d361cd84ff8c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -265,6 +265,8 @@ struct uart_amba_port { unsigned int old_cr; /* state during shutdown */ unsigned int fixed_baud; /* vendor-set fixed baud rate */ char type[12]; + bool rs485_tx_started; + unsigned int rs485_tx_drain_interval; /* usecs */ #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ bool using_tx_dma; @@ -275,6 +277,8 @@ struct uart_amba_port { #endif }; +static unsigned int pl011_tx_empty(struct uart_port *port); + static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap, unsigned int reg) { @@ -1282,6 +1286,42 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) #define pl011_dma_flush_buffer NULL #endif +static void pl011_rs485_tx_stop(struct uart_amba_port *uap) +{ + struct uart_port *port = &uap->port; + int i = 0; + u32 cr; + + /* Wait until hardware tx queue is empty */ + while (!pl011_tx_empty(port)) { + if (i == port->fifosize) { + dev_warn(port->dev, + "timeout while draining hardware tx queue\n"); + break; + } + + udelay(uap->rs485_tx_drain_interval); + i++; + } + + if (port->rs485.delay_rts_after_send) + mdelay(port->rs485.delay_rts_after_send); + + cr = pl011_read(uap, REG_CR); + + if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + cr &= ~UART011_CR_RTS; + else + cr |= UART011_CR_RTS; + + /* Disable the transmitter and reenable the transceiver */ + cr &= ~UART011_CR_TXE; + cr |= UART011_CR_RXE; + pl011_write(cr, uap, REG_CR); + + uap->rs485_tx_started = false; +} + static void pl011_stop_tx(struct uart_port *port) { struct uart_amba_port *uap = @@ -1290,6 +1330,9 @@ static void pl011_stop_tx(struct uart_port *port) uap->im &= ~UART011_TXIM; pl011_write(uap->im, uap, REG_IMSC); pl011_dma_tx_stop(uap); + + if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started) + pl011_rs485_tx_stop(uap); } static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); @@ -1380,6 +1423,32 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, return true; } +static void pl011_rs485_tx_start(struct uart_amba_port *uap) +{ + struct uart_port *port = &uap->port; + u32 cr; + + /* Enable transmitter */ + cr = pl011_read(uap, REG_CR); + cr |= UART011_CR_TXE; + + /* Disable receiver if half-duplex */ + if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) + cr &= ~UART011_CR_RXE; + + if (port->rs485.flags & SER_RS485_RTS_ON_SEND) + cr &= ~UART011_CR_RTS; + else + cr |= UART011_CR_RTS; + + pl011_write(cr, uap, REG_CR); + + if (port->rs485.delay_rts_before_send) + mdelay(port->rs485.delay_rts_before_send); + + uap->rs485_tx_started = true; +} + /* Returns true if tx interrupts have to be (kept) enabled */ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) { @@ -1397,6 +1466,10 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) return false; } + if ((uap->port.rs485.flags & SER_RS485_ENABLED) && + !uap->rs485_tx_started) + pl011_rs485_tx_start(uap); + /* If we are using DMA mode, try to send some characters. */ if (pl011_dma_tx_irq(uap)) return true; @@ -1542,6 +1615,9 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) container_of(port, struct uart_amba_port, port); unsigned int cr; + if (port->rs485.flags & SER_RS485_ENABLED) + mctrl &= ~TIOCM_RTS; + cr = pl011_read(uap, REG_CR); #define TIOCMBIT(tiocmbit, uartbit) \ @@ -1763,7 +1839,17 @@ static int pl011_startup(struct uart_port *port) /* restore RTS and DTR */ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); - cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; + cr |= UART01x_CR_UARTEN | UART011_CR_RXE; + + if (port->rs485.flags & SER_RS485_ENABLED) { + if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + cr &= ~UART011_CR_RTS; + else + cr |= UART011_CR_RTS; + } else { + cr |= UART011_CR_TXE; + } + pl011_write(cr, uap, REG_CR); spin_unlock_irq(&uap->port.lock); @@ -1864,6 +1950,9 @@ static void pl011_shutdown(struct uart_port *port) pl011_dma_shutdown(uap); + if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started) + pl011_rs485_tx_stop(uap); + free_irq(uap->port.irq, uap); pl011_disable_uart(uap); @@ -1941,6 +2030,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, unsigned int lcr_h, old_cr; unsigned long flags; unsigned int baud, quot, clkdiv; + unsigned int bits; if (uap->vendor->oversampling) clkdiv = 8; @@ -1991,6 +2081,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, if (uap->fifosize > 1) lcr_h |= UART01x_LCRH_FEN; + bits = tty_get_frame_size(termios->c_cflag); + spin_lock_irqsave(&port->lock, flags); /* @@ -1998,11 +2090,21 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, */ uart_update_timeout(port, termios->c_cflag, baud); + /* + * Calculate the approximated time it takes to transmit one character + * with the given baud rate. We use this as the poll interval when we + * wait for the tx queue to empty. + */ + uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud; + pl011_setup_status_masks(port, termios); if (UART_ENABLE_MS(port, termios->c_cflag)) pl011_enable_ms(port); + if (port->rs485.flags & SER_RS485_ENABLED) + termios->c_cflag &= ~CRTSCTS; + /* first, disable everything */ old_cr = pl011_read(uap, REG_CR); pl011_write(0, uap, REG_CR); @@ -2124,6 +2226,41 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) return ret; } +static int pl011_rs485_config(struct uart_port *port, + struct serial_rs485 *rs485) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + + /* pick sane settings if the user hasn't */ + if (!(rs485->flags & SER_RS485_RTS_ON_SEND) == + !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { + rs485->flags |= SER_RS485_RTS_ON_SEND; + rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + } + /* clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + memset(rs485->padding, 0, sizeof(rs485->padding)); + + if (port->rs485.flags & SER_RS485_ENABLED) + pl011_rs485_tx_stop(uap); + + /* Set new configuration */ + port->rs485 = *rs485; + + /* Make sure auto RTS is disabled */ + if (port->rs485.flags & SER_RS485_ENABLED) { + u32 cr = pl011_read(uap, REG_CR); + + cr &= ~UART011_CR_RTSEN; + pl011_write(cr, uap, REG_CR); + port->status &= ~UPSTAT_AUTORTS; + } + + return 0; +} + static const struct uart_ops amba_pl011_pops = { .tx_empty = pl011_tx_empty, .set_mctrl = pl011_set_mctrl, @@ -2588,10 +2725,28 @@ static int pl011_find_free_port(void) return -EBUSY; } +static int pl011_get_rs485_mode(struct uart_amba_port *uap) +{ + struct uart_port *port = &uap->port; + struct serial_rs485 *rs485 = &port->rs485; + int ret; + + ret = uart_get_rs485_mode(port); + if (ret) + return ret; + + /* clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + + return 0; +} + static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, struct resource *mmiobase, int index) { void __iomem *base; + int ret; base = devm_ioremap_resource(dev, mmiobase); if (IS_ERR(base)) @@ -2608,6 +2763,10 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = index; + ret = pl011_get_rs485_mode(uap); + if (ret) + return ret; + amba_ports[index] = uap; return 0; @@ -2665,7 +2824,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; uap->port.irq = dev->irq[0]; uap->port.ops = &amba_pl011_pops; - + uap->port.rs485_config = pl011_rs485_config; snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr); diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c index d87048073abe..283757264608 100644 --- a/drivers/tty/serial/fsl_linflexuart.c +++ b/drivers/tty/serial/fsl_linflexuart.c @@ -861,11 +861,7 @@ static int linflex_probe(struct platform_device *pdev) platform_set_drvdata(pdev, sport); - ret = uart_add_one_port(&linflex_reg, sport); - if (ret) - return ret; - - return 0; + return uart_add_one_port(&linflex_reg, sport); } static int linflex_remove(struct platform_device *pdev) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index f0e5da77ed6d..b1e7190ae483 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -7,6 +7,7 @@ #include <linux/clk.h> #include <linux/console.h> +#include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/dmapool.h> @@ -109,6 +110,11 @@ #define UARTSFIFO_TXOF 0x02 #define UARTSFIFO_RXUF 0x01 +/* 32-bit global registers only for i.MX7ULP/i.MX8x + * Used to reset all internal logic and registers, except the Global Register. + */ +#define UART_GLOBAL 0x8 + /* 32-bit register definition */ #define UARTBAUD 0x00 #define UARTSTAT 0x04 @@ -219,6 +225,10 @@ #define UARTWATER_TXWATER_OFF 0 #define UARTWATER_RXWATER_OFF 16 +#define UART_GLOBAL_RST 0x2 +#define GLOBAL_RST_MIN_US 20 +#define GLOBAL_RST_MAX_US 40 + /* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */ #define DMA_RX_TIMEOUT (10) @@ -320,6 +330,11 @@ static inline bool is_layerscape_lpuart(struct lpuart_port *sport) sport->devtype == LS1028A_LPUART); } +static inline bool is_imx7ulp_lpuart(struct lpuart_port *sport) +{ + return sport->devtype == IMX7ULP_LPUART; +} + static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport) { return sport->devtype == IMX8QXP_LPUART; @@ -383,6 +398,33 @@ static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport) #define lpuart_enable_clks(x) __lpuart_enable_clks(x, true) #define lpuart_disable_clks(x) __lpuart_enable_clks(x, false) +static int lpuart_global_reset(struct lpuart_port *sport) +{ + struct uart_port *port = &sport->port; + void __iomem *global_addr; + int ret; + + if (uart_console(port)) + return 0; + + ret = clk_prepare_enable(sport->ipg_clk); + if (ret) { + dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret); + return ret; + } + + if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) { + global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF; + writel(UART_GLOBAL_RST, global_addr); + usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US); + writel(0, global_addr); + usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US); + } + + clk_disable_unprepare(sport->ipg_clk); + return 0; +} + static void lpuart_stop_tx(struct uart_port *port) { unsigned char temp; @@ -479,6 +521,10 @@ static void lpuart_dma_tx_complete(void *arg) unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); + if (!sport->dma_tx_in_progress) { + spin_unlock_irqrestore(&sport->port.lock, flags); + return; + } dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); @@ -2045,11 +2091,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); unsigned long flags; - unsigned long ctrl, old_ctrl, modem; + unsigned long ctrl, old_ctrl, bd, modem; unsigned int baud; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL); + bd = lpuart32_read(&sport->port, UARTBAUD); modem = lpuart32_read(&sport->port, UARTMODIR); /* * only support CS8 and CS7, and for CS7 must enable PE. @@ -2093,7 +2140,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, } if (termios->c_cflag & CSTOPB) - termios->c_cflag &= ~CSTOPB; + bd |= UARTBAUD_SBNS; + else + bd &= ~UARTBAUD_SBNS; /* parity must be enabled when CS7 to match 8-bits format */ if ((termios->c_cflag & CSIZE) == CS7) @@ -2163,6 +2212,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE), UARTCTRL); + lpuart32_write(&sport->port, bd, UARTBAUD); lpuart32_serial_setbrg(sport, baud); lpuart32_write(&sport->port, modem, UARTMODIR); lpuart32_write(&sport->port, ctrl, UARTCTRL); @@ -2611,7 +2661,7 @@ static int lpuart_probe(struct platform_device *pdev) return PTR_ERR(sport->port.membase); sport->port.membase += sdata->reg_off; - sport->port.mapbase = res->start; + sport->port.mapbase = res->start + sdata->reg_off; sport->port.dev = &pdev->dev; sport->port.type = PORT_LPUART; sport->devtype = sdata->devtype; @@ -2691,6 +2741,10 @@ static int lpuart_probe(struct platform_device *pdev) if (ret) goto failed_attach_port; + ret = lpuart_global_reset(sport); + if (ret) + goto failed_reset; + ret = uart_get_rs485_mode(&sport->port); if (ret) goto failed_get_rs485; @@ -2707,6 +2761,8 @@ static int lpuart_probe(struct platform_device *pdev) return 0; failed_get_rs485: +failed_reset: + uart_remove_one_port(&lpuart_reg, &sport->port); failed_attach_port: failed_irq_request: lpuart_disable_clks(sport); diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c index bf0e2a4cb0ce..c6f927a76c3b 100644 --- a/drivers/tty/serial/jsm/jsm_neo.c +++ b/drivers/tty/serial/jsm/jsm_neo.c @@ -815,7 +815,9 @@ static void neo_parse_isr(struct jsm_board *brd, u32 port) /* Parse any modem signal changes */ jsm_dbg(INTR, &ch->ch_bd->pci_dev, "MOD_STAT: sending to parse_modem_sigs\n"); + spin_lock_irqsave(&ch->uart_port.lock, lock_flags); neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); + spin_unlock_irqrestore(&ch->uart_port.lock, lock_flags); } } diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 8e42a7682c63..d74cbbbf33c6 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -187,6 +187,7 @@ static void jsm_tty_break(struct uart_port *port, int break_state) static int jsm_tty_open(struct uart_port *port) { + unsigned long lock_flags; struct jsm_board *brd; struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); @@ -240,6 +241,7 @@ static int jsm_tty_open(struct uart_port *port) channel->ch_cached_lsr = 0; channel->ch_stops_sent = 0; + spin_lock_irqsave(&port->lock, lock_flags); termios = &port->state->port.tty->termios; channel->ch_c_cflag = termios->c_cflag; channel->ch_c_iflag = termios->c_iflag; @@ -259,6 +261,7 @@ static int jsm_tty_open(struct uart_port *port) jsm_carrier(channel); channel->ch_open_count++; + spin_unlock_irqrestore(&port->lock, lock_flags); jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n"); return 0; diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c index 3e7c6ee8e4b3..55c3c9db7462 100644 --- a/drivers/tty/serial/kgdb_nmi.c +++ b/drivers/tty/serial/kgdb_nmi.c @@ -330,17 +330,16 @@ int kgdb_register_nmi_console(void) if (!arch_kgdb_ops.enable_nmi) return 0; - kgdb_nmi_tty_driver = alloc_tty_driver(1); - if (!kgdb_nmi_tty_driver) { + kgdb_nmi_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW); + if (IS_ERR(kgdb_nmi_tty_driver)) { pr_err("%s: cannot allocate tty\n", __func__); - return -ENOMEM; + return PTR_ERR(kgdb_nmi_tty_driver); } kgdb_nmi_tty_driver->driver_name = "ttyNMI"; kgdb_nmi_tty_driver->name = "ttyNMI"; kgdb_nmi_tty_driver->num = 1; kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL; - kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW; kgdb_nmi_tty_driver->init_termios = tty_std_termios; tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios, KGDB_NMI_BAUD, KGDB_NMI_BAUD); @@ -356,7 +355,7 @@ int kgdb_register_nmi_console(void) return 0; err_drv_reg: - put_tty_driver(kgdb_nmi_tty_driver); + tty_driver_kref_put(kgdb_nmi_tty_driver); return ret; } EXPORT_SYMBOL_GPL(kgdb_register_nmi_console); @@ -374,7 +373,7 @@ int kgdb_unregister_nmi_console(void) return ret; tty_unregister_driver(kgdb_nmi_tty_driver); - put_tty_driver(kgdb_nmi_tty_driver); + tty_driver_kref_put(kgdb_nmi_tty_driver); return 0; } diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index ef11860cd69e..3df0788ddeb0 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1271,18 +1271,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty /* Always ask for fixed clock rate from a property. */ device_property_read_u32(dev, "clock-frequency", &uartclk); - s->clk = devm_clk_get_optional(dev, "osc"); + xtal = device_property_match_string(dev, "clock-names", "osc") < 0; + if (xtal) + s->clk = devm_clk_get_optional(dev, "xtal"); + else + s->clk = devm_clk_get_optional(dev, "osc"); if (IS_ERR(s->clk)) return PTR_ERR(s->clk); - if (s->clk) { - xtal = false; - } else { - s->clk = devm_clk_get_optional(dev, "xtal"); - if (IS_ERR(s->clk)) - return PTR_ERR(s->clk); - - xtal = true; - } ret = clk_prepare_enable(s->clk); if (ret) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 9e81b09ba08e..0862941862c8 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -276,11 +276,8 @@ static void serial_omap_enable_ms(struct uart_port *port) dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static void serial_omap_stop_tx(struct uart_port *port) @@ -288,8 +285,6 @@ static void serial_omap_stop_tx(struct uart_port *port) struct uart_omap_port *up = to_uart_omap_port(port); int res; - pm_runtime_get_sync(up->dev); - /* Handle RS-485 */ if (port->rs485.flags & SER_RS485_ENABLED) { if (up->scr & OMAP_UART_SCR_TX_EMPTY) { @@ -330,21 +325,15 @@ static void serial_omap_stop_tx(struct uart_port *port) up->ier &= ~UART_IER_THRI; serial_out(up, UART_IER, up->ier); } - - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static void serial_omap_stop_rx(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - pm_runtime_get_sync(up->dev); up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); up->port.read_status_mask &= ~UART_LSR_DR; serial_out(up, UART_IER, up->ier); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static void transmit_chars(struct uart_omap_port *up, unsigned int lsr) @@ -399,8 +388,6 @@ static void serial_omap_start_tx(struct uart_port *port) struct uart_omap_port *up = to_uart_omap_port(port); int res; - pm_runtime_get_sync(up->dev); - /* Handle RS-485 */ if (port->rs485.flags & SER_RS485_ENABLED) { /* Fire THR interrupts when FIFO is below trigger level */ @@ -421,8 +408,6 @@ static void serial_omap_start_tx(struct uart_port *port) up->rs485_tx_filter_count = 0; serial_omap_enable_ier_thri(up); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static void serial_omap_throttle(struct uart_port *port) @@ -430,13 +415,10 @@ static void serial_omap_throttle(struct uart_port *port) struct uart_omap_port *up = to_uart_omap_port(port); unsigned long flags; - pm_runtime_get_sync(up->dev); spin_lock_irqsave(&up->port.lock, flags); up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); serial_out(up, UART_IER, up->ier); spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static void serial_omap_unthrottle(struct uart_port *port) @@ -444,13 +426,10 @@ static void serial_omap_unthrottle(struct uart_port *port) struct uart_omap_port *up = to_uart_omap_port(port); unsigned long flags; - pm_runtime_get_sync(up->dev); spin_lock_irqsave(&up->port.lock, flags); up->ier |= UART_IER_RLSI | UART_IER_RDI; serial_out(up, UART_IER, up->ier); spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static unsigned int check_modem_status(struct uart_omap_port *up) @@ -576,7 +555,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) int max_count = 256; spin_lock(&up->port.lock); - pm_runtime_get_sync(up->dev); do { iir = serial_in(up, UART_IIR); @@ -616,8 +594,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) tty_flip_buffer_push(&up->port.state->port); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); up->port_activity = jiffies; return ret; @@ -629,13 +605,11 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port) unsigned long flags; unsigned int ret = 0; - pm_runtime_get_sync(up->dev); dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line); spin_lock_irqsave(&up->port.lock, flags); ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + return ret; } @@ -645,10 +619,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port) unsigned int status; unsigned int ret = 0; - pm_runtime_get_sync(up->dev); status = check_modem_status(up); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line); @@ -680,7 +651,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) if (mctrl & TIOCM_LOOP) mcr |= UART_MCR_LOOP; - pm_runtime_get_sync(up->dev); old_mcr = serial_in(up, UART_MCR); old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 | UART_MCR_DTR | UART_MCR_RTS); @@ -696,9 +666,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) up->efr &= ~UART_EFR_RTS; serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, lcr); - - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static void serial_omap_break_ctl(struct uart_port *port, int break_state) @@ -707,7 +674,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) unsigned long flags; dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); spin_lock_irqsave(&up->port.lock, flags); if (break_state == -1) up->lcr |= UART_LCR_SBC; @@ -715,8 +681,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) up->lcr &= ~UART_LCR_SBC; serial_out(up, UART_LCR, up->lcr); spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static int serial_omap_startup(struct uart_port *port) @@ -788,8 +752,6 @@ static int serial_omap_startup(struct uart_port *port) serial_out(up, UART_OMAP_WER, up->wer); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); up->port_activity = jiffies; return 0; } @@ -801,7 +763,6 @@ static void serial_omap_shutdown(struct uart_port *port) dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); /* * Disable interrupts from this port */ @@ -825,8 +786,7 @@ static void serial_omap_shutdown(struct uart_port *port) if (serial_in(up, UART_LSR) & UART_LSR_DR) (void) serial_in(up, UART_RX); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put_sync(up->dev); free_irq(up->port.irq, up); dev_pm_clear_wake_irq(up->dev); } @@ -896,7 +856,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, * Ok, we're now changing the port state. Do it with * interrupts disabled. */ - pm_runtime_get_sync(up->dev); spin_lock_irqsave(&up->port.lock, flags); /* @@ -1096,8 +1055,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, serial_omap_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); } @@ -1110,7 +1067,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state, dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, efr | UART_EFR_ECB); @@ -1120,9 +1076,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state, serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, efr); serial_out(up, UART_LCR, 0); - - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static void serial_omap_release_port(struct uart_port *port) @@ -1202,11 +1155,8 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch) { struct uart_omap_port *up = to_uart_omap_port(port); - pm_runtime_get_sync(up->dev); wait_for_xmitr(up); serial_out(up, UART_TX, ch); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); } static int serial_omap_poll_get_char(struct uart_port *port) @@ -1214,7 +1164,6 @@ static int serial_omap_poll_get_char(struct uart_port *port) struct uart_omap_port *up = to_uart_omap_port(port); unsigned int status; - pm_runtime_get_sync(up->dev); status = serial_in(up, UART_LSR); if (!(status & UART_LSR_DR)) { status = NO_POLL_CHAR; @@ -1224,9 +1173,6 @@ static int serial_omap_poll_get_char(struct uart_port *port) status = serial_in(up, UART_RX); out: - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); - return status; } @@ -1309,8 +1255,6 @@ serial_omap_console_write(struct console *co, const char *s, unsigned int ier; int locked = 1; - pm_runtime_get_sync(up->dev); - local_irq_save(flags); if (up->port.sysrq) locked = 0; @@ -1343,8 +1287,6 @@ serial_omap_console_write(struct console *co, const char *s, if (up->msr_saved_flags) check_modem_status(up); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); if (locked) spin_unlock(&up->port.lock); local_irq_restore(flags); @@ -1403,8 +1345,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) unsigned int mode; int val; - pm_runtime_get_sync(up->dev); - /* Disable interrupts from this port */ mode = up->ier; up->ier = 0; @@ -1438,9 +1378,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) serial_out(up, UART_OMAP_SCR, up->scr); } - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); - return 0; } @@ -1737,11 +1674,7 @@ static int serial_omap_probe(struct platform_device *pdev) omap_up_info->autosuspend_timeout = -1; device_init_wakeup(up->dev, true); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, - omap_up_info->autosuspend_timeout); - pm_runtime_irq_safe(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -1755,12 +1688,9 @@ static int serial_omap_probe(struct platform_device *pdev) if (ret != 0) goto err_add_port; - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); return 0; err_add_port: - pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); cpu_latency_qos_remove_request(&up->pm_qos_request); @@ -1778,7 +1708,6 @@ static int serial_omap_remove(struct platform_device *dev) uart_remove_one_port(&serial_omap_reg, &up->port); - pm_runtime_dont_use_autosuspend(up->dev); pm_runtime_put_sync(up->dev); pm_runtime_disable(up->dev); cpu_latency_qos_remove_request(&up->pm_qos_request); diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 9fbc61151c2e..e2f49863e9c2 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -65,6 +65,7 @@ enum s3c24xx_port_type { struct s3c24xx_uart_info { char *name; enum s3c24xx_port_type type; + unsigned int has_usi; unsigned int port_type; unsigned int fifosize; unsigned long rx_fifomask; @@ -305,8 +306,9 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) dmaengine_pause(dma->tx_chan); dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); dmaengine_terminate_all(dma->tx_chan); - dma_sync_single_for_cpu(ourport->port.dev, - dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE); + dma_sync_single_for_cpu(dma->tx_chan->device->dev, + dma->tx_transfer_addr, dma->tx_size, + DMA_TO_DEVICE); async_tx_ack(dma->tx_desc); count = dma->tx_bytes_requested - state.residue; xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); @@ -338,8 +340,9 @@ static void s3c24xx_serial_tx_dma_complete(void *args) count = dma->tx_bytes_requested - state.residue; async_tx_ack(dma->tx_desc); - dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr, - dma->tx_size, DMA_TO_DEVICE); + dma_sync_single_for_cpu(dma->tx_chan->device->dev, + dma->tx_transfer_addr, dma->tx_size, + DMA_TO_DEVICE); spin_lock_irqsave(&port->lock, flags); @@ -443,8 +446,9 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, dma->tx_size = count & ~(dma_get_cache_alignment() - 1); dma->tx_transfer_addr = dma->tx_addr + xmit->tail; - dma_sync_single_for_device(ourport->port.dev, dma->tx_transfer_addr, - dma->tx_size, DMA_TO_DEVICE); + dma_sync_single_for_device(dma->tx_chan->device->dev, + dma->tx_transfer_addr, dma->tx_size, + DMA_TO_DEVICE); dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan, dma->tx_transfer_addr, dma->tx_size, @@ -515,7 +519,7 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport, if (!count) return; - dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr, + dma_sync_single_for_cpu(dma->rx_chan->device->dev, dma->rx_addr, dma->rx_size, DMA_FROM_DEVICE); ourport->port.icount.rx += count; @@ -636,8 +640,8 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport) { struct s3c24xx_uart_dma *dma = ourport->dma; - dma_sync_single_for_device(ourport->port.dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); + dma_sync_single_for_device(dma->rx_chan->device->dev, dma->rx_addr, + dma->rx_size, DMA_FROM_DEVICE); dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan, dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, @@ -1102,18 +1106,19 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) goto err_release_tx; } - dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf, - dma->rx_size, DMA_FROM_DEVICE); - if (dma_mapping_error(p->port.dev, dma->rx_addr)) { + dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf, + dma->rx_size, DMA_FROM_DEVICE); + if (dma_mapping_error(dma->rx_chan->device->dev, dma->rx_addr)) { reason = "DMA mapping error for RX buffer"; ret = -EIO; goto err_free_rx; } /* TX buffer */ - dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf, - UART_XMIT_SIZE, DMA_TO_DEVICE); - if (dma_mapping_error(p->port.dev, dma->tx_addr)) { + dma->tx_addr = dma_map_single(dma->tx_chan->device->dev, + p->port.state->xmit.buf, UART_XMIT_SIZE, + DMA_TO_DEVICE); + if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) { reason = "DMA mapping error for TX buffer"; ret = -EIO; goto err_unmap_rx; @@ -1122,8 +1127,8 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) return 0; err_unmap_rx: - dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size, - DMA_FROM_DEVICE); + dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr, + dma->rx_size, DMA_FROM_DEVICE); err_free_rx: kfree(dma->rx_buf); err_release_tx: @@ -1142,8 +1147,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) if (dma->rx_chan) { dmaengine_terminate_all(dma->rx_chan); - dma_unmap_single(p->port.dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); + dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr, + dma->rx_size, DMA_FROM_DEVICE); kfree(dma->rx_buf); dma_release_channel(dma->rx_chan); dma->rx_chan = NULL; @@ -1151,8 +1156,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) if (dma->tx_chan) { dmaengine_terminate_all(dma->tx_chan); - dma_unmap_single(p->port.dev, dma->tx_addr, - UART_XMIT_SIZE, DMA_TO_DEVICE); + dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr, + UART_XMIT_SIZE, DMA_TO_DEVICE); dma_release_channel(dma->tx_chan); dma->tx_chan = NULL; } @@ -1352,6 +1357,28 @@ static int apple_s5l_serial_startup(struct uart_port *port) return ret; } +static void exynos_usi_init(struct uart_port *port) +{ + struct s3c24xx_uart_port *ourport = to_ourport(port); + struct s3c24xx_uart_info *info = ourport->info; + unsigned int val; + + if (!info->has_usi) + return; + + /* Clear the software reset of USI block (it's set at startup) */ + val = rd_regl(port, USI_CON); + val &= ~USI_CON_RESET_MASK; + wr_regl(port, USI_CON, val); + udelay(1); + + /* Continuously provide the clock to USI IP w/o gating (for Rx mode) */ + val = rd_regl(port, USI_OPTION); + val &= ~USI_OPTION_HWACG_MASK; + val |= USI_OPTION_HWACG_CLKREQ_ON; + wr_regl(port, USI_OPTION, val); +} + /* power power management control */ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, @@ -1379,6 +1406,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, if (!IS_ERR(ourport->baudclk)) clk_prepare_enable(ourport->baudclk); + exynos_usi_init(port); break; default: dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level); @@ -2102,6 +2130,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, if (ret) pr_warn("uart: failed to enable baudclk\n"); + exynos_usi_init(port); + /* Keep all interrupts masked and cleared */ switch (ourport->info->type) { case TYPE_S3C6400: @@ -2750,10 +2780,11 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { #endif #if defined(CONFIG_ARCH_EXYNOS) -#define EXYNOS_COMMON_SERIAL_DRV_DATA \ +#define EXYNOS_COMMON_SERIAL_DRV_DATA_USI(_has_usi) \ .info = &(struct s3c24xx_uart_info) { \ .name = "Samsung Exynos UART", \ .type = TYPE_S3C6400, \ + .has_usi = _has_usi, \ .port_type = PORT_S3C6400, \ .has_divslot = 1, \ .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ @@ -2773,6 +2804,9 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { .has_fracval = 1, \ } \ +#define EXYNOS_COMMON_SERIAL_DRV_DATA \ + EXYNOS_COMMON_SERIAL_DRV_DATA_USI(0) + static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = { EXYNOS_COMMON_SERIAL_DRV_DATA, .fifosize = { 256, 64, 16, 16 }, @@ -2783,11 +2817,19 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = { .fifosize = { 64, 256, 16, 256 }, }; +static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = { + EXYNOS_COMMON_SERIAL_DRV_DATA_USI(1), + .fifosize = { 256, 64, 64, 64 }, +}; + #define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data) #define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos5433_serial_drv_data) +#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos850_serial_drv_data) + #else -#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL -#define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)NULL) +#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)NULL) +#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)NULL) #endif #ifdef CONFIG_ARCH_APPLE @@ -2843,6 +2885,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = { }, { .name = "s5l-uart", .driver_data = S5L_SERIAL_DRV_DATA, + }, { + .name = "exynos850-uart", + .driver_data = EXYNOS850_SERIAL_DRV_DATA, }, { }, }; @@ -2866,6 +2911,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = { .data = (void *)EXYNOS5433_SERIAL_DRV_DATA }, { .compatible = "apple,s5l-uart", .data = (void *)S5L_SERIAL_DRV_DATA }, + { .compatible = "samsung,exynos850-uart", + .data = (void *)EXYNOS850_SERIAL_DRV_DATA }, {}, }; MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index eba5b9ecba34..45e2e4109acd 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -1568,14 +1568,12 @@ static int tegra_uart_probe(struct platform_device *pdev) struct resource *resource; int ret; const struct tegra_uart_chip_data *cdata; - const struct of_device_id *match; - match = of_match_device(tegra_uart_of_match, &pdev->dev); - if (!match) { + cdata = of_device_get_match_data(&pdev->dev); + if (!cdata) { dev_err(&pdev->dev, "Error: No device match found\n"); return -ENODEV; } - cdata = match->data; tup = devm_kzalloc(&pdev->dev, sizeof(*tup), GFP_KERNEL); if (!tup) { diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 69092deba11f..0e2e35ab64c7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2314,6 +2314,14 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) port->dev ? ": " : "", port->name, address, port->irq, port->uartclk / 16, uart_type(port)); + + /* The magic multiplier feature is a bit obscure, so report it too. */ + if (port->flags & UPF_MAGIC_MULTIPLIER) + pr_info("%s%s%s extra baud rates supported: %d, %d", + port->dev ? dev_name(port->dev) : "", + port->dev ? ": " : "", + port->name, + port->uartclk / 8, port->uartclk / 4); } static void @@ -2522,9 +2530,12 @@ int uart_register_driver(struct uart_driver *drv) if (!drv->state) goto out; - normal = alloc_tty_driver(drv->nr); - if (!normal) + normal = tty_alloc_driver(drv->nr, TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV); + if (IS_ERR(normal)) { + retval = PTR_ERR(normal); goto out_kfree; + } drv->tty_driver = normal; @@ -2537,7 +2548,6 @@ int uart_register_driver(struct uart_driver *drv) normal->init_termios = tty_std_termios; normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; - normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; normal->driver_state = drv; tty_set_operations(normal, &uart_ops); @@ -2558,7 +2568,7 @@ int uart_register_driver(struct uart_driver *drv) for (i = 0; i < drv->nr; i++) tty_port_destroy(&drv->state[i].port); - put_tty_driver(normal); + tty_driver_kref_put(normal); out_kfree: kfree(drv->state); out: @@ -2580,7 +2590,7 @@ void uart_unregister_driver(struct uart_driver *drv) unsigned int i; tty_unregister_driver(p); - put_tty_driver(p); + tty_driver_kref_put(p); for (i = 0; i < drv->nr; i++) tty_port_destroy(&drv->state[i].port); kfree(drv->state); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 07eb56294371..89ee43061d3a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1758,6 +1758,10 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) /* Handle BREAKs */ sci_handle_breaks(port); + + /* drop invalid character received before break was detected */ + serial_port_in(port, SCxRDR); + sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port)); return IRQ_HANDLED; @@ -1837,7 +1841,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) ret = sci_er_interrupt(irq, ptr); /* Break Interrupt */ - if ((ssr_status & SCxSR_BRK(port)) && err_enabled) + if (s->irqs[SCIx_ERI_IRQ] != s->irqs[SCIx_BRI_IRQ] && + (ssr_status & SCxSR_BRK(port)) && err_enabled) ret = sci_br_interrupt(irq, ptr); /* Overrun Interrupt */ diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index ef793b3b4591..8f032e77b954 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -1034,8 +1034,8 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, int ret, irq; irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return irq ? : -ENODEV; + if (irq < 0) + return irq; port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF; @@ -1064,8 +1064,7 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, &stm32port->txftcfg); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->membase = devm_ioremap_resource(&pdev->dev, res); + port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(port->membase)) return PTR_ERR(port->membase); port->mapbase = res->start; @@ -1177,7 +1176,7 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, if (uart_console(port)) return -ENODEV; - stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L, + stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L, &stm32port->rx_dma_buf, GFP_KERNEL); if (!stm32port->rx_buf) @@ -1243,7 +1242,7 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, stm32port->tx_dma_busy = false; - stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L, + stm32port->tx_buf = dma_alloc_coherent(dev, TX_BUF_L, &stm32port->tx_dma_buf, GFP_KERNEL); if (!stm32port->tx_buf) diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index a5f15f22d9ef..dfc1ba4e1572 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -17,11 +17,13 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> #include <linux/of_platform.h> #include <linux/clk.h> +#include <linux/pm_runtime.h> #define ULITE_NAME "ttyUL" #define ULITE_MAJOR 204 @@ -54,6 +56,7 @@ #define ULITE_CONTROL_RST_TX 0x01 #define ULITE_CONTROL_RST_RX 0x02 #define ULITE_CONTROL_IE 0x10 +#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */ /* Static pointer to console port */ #ifdef CONFIG_SERIAL_UARTLITE_CONSOLE @@ -390,12 +393,16 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser) static void ulite_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - struct uartlite_data *pdata = port->private_data; + int ret; - if (!state) - clk_enable(pdata->clk); - else - clk_disable(pdata->clk); + if (!state) { + ret = pm_runtime_get_sync(port->dev); + if (ret < 0) + dev_err(port->dev, "Failed to enable clocks\n"); + } else { + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); + } } #ifdef CONFIG_CONSOLE_POLL @@ -448,24 +455,15 @@ static const struct uart_ops ulite_ops = { static void ulite_console_wait_tx(struct uart_port *port) { u8 val; - unsigned long timeout; /* * Spin waiting for TX fifo to have space available. * When using the Microblaze Debug Module this can take up to 1s */ - timeout = jiffies + msecs_to_jiffies(1000); - while (1) { - val = uart_in32(ULITE_STATUS, port); - if ((val & ULITE_STATUS_TXFULL) == 0) - break; - if (time_after(jiffies, timeout)) { - dev_warn(port->dev, - "timeout waiting for TX buffer empty\n"); - break; - } - cpu_relax(); - } + if (read_poll_timeout_atomic(uart_in32, val, !(val & ULITE_STATUS_TXFULL), + 0, 1000000, false, ULITE_STATUS, port)) + dev_warn(port->dev, + "timeout waiting for TX buffer empty\n"); } static void ulite_console_putchar(struct uart_port *port, int ch) @@ -555,16 +553,15 @@ static void early_uartlite_putc(struct uart_port *port, int c) * This limit is pretty arbitrary, unless we are at about 10 baud * we'll never timeout on a working UART. */ - unsigned retries = 1000000; - /* read status bit - 0x8 offset */ - while (--retries && (readl(port->membase + 8) & (1 << 3))) + + while (--retries && + (readl(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL)) ; /* Only attempt the iowrite if we didn't timeout */ - /* write to TX_FIFO - 0x4 offset */ if (retries) - writel(c & 0xff, port->membase + 4); + writel(c & 0xff, port->membase + ULITE_TX); } static void early_uartlite_write(struct console *console, @@ -719,11 +716,38 @@ static int __maybe_unused ulite_resume(struct device *dev) return 0; } +static int __maybe_unused ulite_runtime_suspend(struct device *dev) +{ + struct uart_port *port = dev_get_drvdata(dev); + struct uartlite_data *pdata = port->private_data; + + clk_disable(pdata->clk); + return 0; +}; + +static int __maybe_unused ulite_runtime_resume(struct device *dev) +{ + struct uart_port *port = dev_get_drvdata(dev); + struct uartlite_data *pdata = port->private_data; + int ret; + + ret = clk_enable(pdata->clk); + if (ret) { + dev_err(dev, "Cannot enable clock.\n"); + return ret; + } + return 0; +} + /* --------------------------------------------------------------------- * Platform bus binding */ -static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume); +static const struct dev_pm_ops ulite_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume) + SET_RUNTIME_PM_OPS(ulite_runtime_suspend, + ulite_runtime_resume, NULL) +}; #if defined(CONFIG_OF) /* Match table for of_platform binding */ @@ -779,18 +803,25 @@ static int ulite_probe(struct platform_device *pdev) return ret; } + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + if (!ulite_uart_driver.state) { dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n"); ret = uart_register_driver(&ulite_uart_driver); if (ret < 0) { dev_err(&pdev->dev, "Failed to register driver\n"); + clk_disable_unprepare(pdata->clk); return ret; } } ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata); - clk_disable(pdata->clk); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); return ret; } @@ -799,9 +830,14 @@ static int ulite_remove(struct platform_device *pdev) { struct uart_port *port = dev_get_drvdata(&pdev->dev); struct uartlite_data *pdata = port->private_data; + int rc; clk_disable_unprepare(pdata->clk); - return ulite_release(&pdev->dev); + rc = ulite_release(&pdev->dev); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + return rc; } /* work with hotplug and coldplug */ diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index c5edd56ff830..e15b2bf69904 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -623,17 +623,14 @@ static int vt8500_serial_probe(struct platform_device *pdev) struct vt8500_port *vt8500_port; struct resource *mmres, *irqres; struct device_node *np = pdev->dev.of_node; - const struct of_device_id *match; const unsigned int *flags; int ret; int port; - match = of_match_device(wmt_dt_ids, &pdev->dev); - if (!match) + flags = of_device_get_match_data(&pdev->dev); + if (!flags) return -EINVAL; - flags = match->data; - mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!mmres || !irqres) |