diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index 4cc09e43eea22e65cd10be3503a84379d2f4e4a3..6916d7532ad2ca07117937b388b39a6adc39fed9 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -163,7 +163,7 @@ }; uart0: serial@12000 { - compatible = "snps,dw-apb-uart"; + compatible = "marvell,armada-38x-uart"; reg = <0x12000 0x100>; reg-shift = <2>; interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; @@ -173,7 +173,7 @@ }; uart1: serial@12100 { - compatible = "snps,dw-apb-uart"; + compatible = "marvell,armada-38x-uart"; reg = <0x12100 0x100>; reg-shift = <2>; interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; diff --git a/drivers/tty/ipwireless/network.c b/drivers/tty/ipwireless/network.c index 695439c0314741117c7af75a4fd6b99d10c71665..cf20616340a1a859fb737a8a798e4011cd04caa8 100644 --- a/drivers/tty/ipwireless/network.c +++ b/drivers/tty/ipwireless/network.c @@ -416,7 +416,7 @@ void ipwireless_network_packet_received(struct ipw_network *network, struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) { struct ipw_network *network = - kzalloc(sizeof(struct ipw_network), GFP_ATOMIC); + kzalloc(sizeof(struct ipw_network), GFP_KERNEL); if (!network) return NULL; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 1dbe27c9946c16578a6ad0f82313c4adf797aef0..86b7e20ffd7f1e90f1087f9212a85f201c057287 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2675,7 +2675,7 @@ static inline void muxnet_put(struct gsm_mux_net *mux_net) kref_put(&mux_net->ref, net_free); } -static int gsm_mux_net_start_xmit(struct sk_buff *skb, +static netdev_tx_t gsm_mux_net_start_xmit(struct sk_buff *skb, struct net_device *net) { struct gsm_mux_net *mux_net = netdev_priv(net); diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index b57b35066ebea9463962fee993fc97518e4d4afc..fed820e9ab9d76b92b38cb85031739257c012c27 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -72,19 +72,19 @@ do { \ #define TMP_BUF_MAX 256 -#define DUMP(buf__,len__) \ - do { \ - char tbuf[TMP_BUF_MAX] = {0};\ - if (len__ > 1) {\ - snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\ - if (tbuf[len__-2] == '\r') {\ - tbuf[len__-2] = 'r';\ - } \ - DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\ - } else {\ - DBG1("SENDING: '%s' (%d)", tbuf, len__);\ - } \ -} while (0) +#define DUMP(buf__, len__) \ + do { \ + char tbuf[TMP_BUF_MAX] = {0}; \ + if (len__ > 1) { \ + u32 data_len = min_t(u32, len__, TMP_BUF_MAX); \ + strscpy(tbuf, buf__, data_len); \ + if (tbuf[data_len - 2] == '\r') \ + tbuf[data_len - 2] = 'r'; \ + DBG1("SENDING: '%s' (%d+n)", tbuf, len__); \ + } else { \ + DBG1("SENDING: '%s' (%d)", tbuf, len__); \ + } \ + } while (0) /* Defines */ #define NOZOMI_NAME "nozomi" @@ -102,41 +102,41 @@ do { \ #define RECEIVE_BUF_MAX 4 -#define R_IIR 0x0000 /* Interrupt Identity Register */ -#define R_FCR 0x0000 /* Flow Control Register */ -#define R_IER 0x0004 /* Interrupt Enable Register */ +#define R_IIR 0x0000 /* Interrupt Identity Register */ +#define R_FCR 0x0000 /* Flow Control Register */ +#define R_IER 0x0004 /* Interrupt Enable Register */ #define NOZOMI_CONFIG_MAGIC 0xEFEFFEFE #define TOGGLE_VALID 0x0000 /* Definition of interrupt tokens */ -#define MDM_DL1 0x0001 -#define MDM_UL1 0x0002 -#define MDM_DL2 0x0004 -#define MDM_UL2 0x0008 -#define DIAG_DL1 0x0010 -#define DIAG_DL2 0x0020 -#define DIAG_UL 0x0040 -#define APP1_DL 0x0080 -#define APP1_UL 0x0100 -#define APP2_DL 0x0200 -#define APP2_UL 0x0400 -#define CTRL_DL 0x0800 -#define CTRL_UL 0x1000 -#define RESET 0x8000 - -#define MDM_DL (MDM_DL1 | MDM_DL2) -#define MDM_UL (MDM_UL1 | MDM_UL2) -#define DIAG_DL (DIAG_DL1 | DIAG_DL2) +#define MDM_DL1 0x0001 +#define MDM_UL1 0x0002 +#define MDM_DL2 0x0004 +#define MDM_UL2 0x0008 +#define DIAG_DL1 0x0010 +#define DIAG_DL2 0x0020 +#define DIAG_UL 0x0040 +#define APP1_DL 0x0080 +#define APP1_UL 0x0100 +#define APP2_DL 0x0200 +#define APP2_UL 0x0400 +#define CTRL_DL 0x0800 +#define CTRL_UL 0x1000 +#define RESET 0x8000 + +#define MDM_DL (MDM_DL1 | MDM_DL2) +#define MDM_UL (MDM_UL1 | MDM_UL2) +#define DIAG_DL (DIAG_DL1 | DIAG_DL2) /* modem signal definition */ -#define CTRL_DSR 0x0001 -#define CTRL_DCD 0x0002 -#define CTRL_RI 0x0004 -#define CTRL_CTS 0x0008 +#define CTRL_DSR 0x0001 +#define CTRL_DCD 0x0002 +#define CTRL_RI 0x0004 +#define CTRL_CTS 0x0008 -#define CTRL_DTR 0x0001 -#define CTRL_RTS 0x0002 +#define CTRL_DTR 0x0001 +#define CTRL_RTS 0x0002 #define MAX_PORT 4 #define NOZOMI_MAX_PORTS 5 @@ -155,7 +155,7 @@ enum card_type { /* Initialization states a card can be in */ enum card_state { - NOZOMI_STATE_UKNOWN = 0, + NOZOMI_STATE_UNKNOWN = 0, NOZOMI_STATE_ENABLED = 1, /* pci device enabled */ NOZOMI_STATE_ALLOCATED = 2, /* config setup done */ NOZOMI_STATE_READY = 3, /* flowcontrols received */ @@ -365,7 +365,7 @@ struct buffer { u8 *data; } __attribute__ ((packed)); -/* Global variables */ +/* Global variables */ static const struct pci_device_id nozomi_pci_tbl[] = { {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ {}, @@ -1686,12 +1686,12 @@ static int ntty_tiocmget(struct tty_struct *tty) /* Note: these could change under us but it is not clear this matters if so */ - return (ctrl_ul->RTS ? TIOCM_RTS : 0) | - (ctrl_ul->DTR ? TIOCM_DTR : 0) | - (ctrl_dl->DCD ? TIOCM_CAR : 0) | - (ctrl_dl->RI ? TIOCM_RNG : 0) | - (ctrl_dl->DSR ? TIOCM_DSR : 0) | - (ctrl_dl->CTS ? TIOCM_CTS : 0); + return (ctrl_ul->RTS ? TIOCM_RTS : 0) + | (ctrl_ul->DTR ? TIOCM_DTR : 0) + | (ctrl_dl->DCD ? TIOCM_CAR : 0) + | (ctrl_dl->RI ? TIOCM_RNG : 0) + | (ctrl_dl->DSR ? TIOCM_DSR : 0) + | (ctrl_dl->CTS ? TIOCM_CTS : 0); } /* Sets io controls parameters */ @@ -1722,10 +1722,10 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags, const struct async_icount cnow = port->tty_icount; int ret; - ret = ((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) || - ((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || - ((flags & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || - ((flags & TIOCM_CTS) && (cnow.cts != cprev->cts)); + ret = ((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) + || ((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) + || ((flags & TIOCM_CD) && (cnow.dcd != cprev->dcd)) + || ((flags & TIOCM_CTS) && (cnow.cts != cprev->cts)); *cprev = cnow; diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c index 74a408d9db24c1fc7e2c4466867f3585ee42a067..023db326675765ade9f382c3964c110274ea5da2 100644 --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c @@ -10,6 +10,8 @@ #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> #include <linux/clk.h> #include "8250.h" @@ -28,8 +30,17 @@ struct aspeed_vuart { void __iomem *regs; struct clk *clk; int line; + struct timer_list unthrottle_timer; + struct uart_8250_port *port; }; +/* + * If we fill the tty flip buffers, we throttle the data ready interrupt + * to prevent dropped characters. This timeout defines how long we wait + * to (conditionally, depending on buffer state) unthrottle. + */ +static const int unthrottle_timeout = HZ/10; + /* * The VUART is basically two UART 'front ends' connected by their FIFO * (no actual serial line in between). One is on the BMC side (management @@ -179,6 +190,113 @@ static void aspeed_vuart_shutdown(struct uart_port *uart_port) serial8250_do_shutdown(uart_port); } +static void __aspeed_vuart_set_throttle(struct uart_8250_port *up, + bool throttle) +{ + unsigned char irqs = UART_IER_RLSI | UART_IER_RDI; + + up->ier &= ~irqs; + if (!throttle) + up->ier |= irqs; + serial_out(up, UART_IER, up->ier); +} +static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + __aspeed_vuart_set_throttle(up, throttle); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void aspeed_vuart_throttle(struct uart_port *port) +{ + aspeed_vuart_set_throttle(port, true); +} + +static void aspeed_vuart_unthrottle(struct uart_port *port) +{ + aspeed_vuart_set_throttle(port, false); +} + +static void aspeed_vuart_unthrottle_exp(struct timer_list *timer) +{ + struct aspeed_vuart *vuart = from_timer(vuart, timer, unthrottle_timer); + struct uart_8250_port *up = vuart->port; + + if (!tty_buffer_space_avail(&up->port.state->port)) { + mod_timer(&vuart->unthrottle_timer, unthrottle_timeout); + return; + } + + aspeed_vuart_unthrottle(&up->port); +} + +/* + * Custom interrupt handler to manage finer-grained flow control. Although we + * have throttle/unthrottle callbacks, we've seen that the VUART device can + * deliver characters faster than the ldisc has a chance to check buffer space + * against the throttle threshold. This results in dropped characters before + * the throttle. + * + * We do this by checking for flip buffer space before RX. If we have no space, + * throttle now and schedule an unthrottle for later, once the ldisc has had + * a chance to drain the buffers. + */ +static int aspeed_vuart_handle_irq(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int iir, lsr; + unsigned long flags; + int space, count; + + iir = serial_port_in(port, UART_IIR); + + if (iir & UART_IIR_NO_INT) + return 0; + + spin_lock_irqsave(&port->lock, flags); + + lsr = serial_port_in(port, UART_LSR); + + if (lsr & (UART_LSR_DR | UART_LSR_BI)) { + space = tty_buffer_space_avail(&port->state->port); + + if (!space) { + /* throttle and schedule an unthrottle later */ + struct aspeed_vuart *vuart = port->private_data; + __aspeed_vuart_set_throttle(up, true); + + if (!timer_pending(&vuart->unthrottle_timer)) { + vuart->port = up; + mod_timer(&vuart->unthrottle_timer, + unthrottle_timeout); + } + + } else { + count = min(space, 256); + + do { + serial8250_read_char(up, lsr); + lsr = serial_in(up, UART_LSR); + if (--count == 0) + break; + } while (lsr & (UART_LSR_DR | UART_LSR_BI)); + + tty_flip_buffer_push(&port->state->port); + } + } + + serial8250_modem_status(up); + if (lsr & UART_LSR_THRE) + serial8250_tx_chars(up); + + spin_unlock_irqrestore(&port->lock, flags); + + return 1; +} + static int aspeed_vuart_probe(struct platform_device *pdev) { struct uart_8250_port port; @@ -195,6 +313,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) return -ENOMEM; vuart->dev = &pdev->dev; + timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); vuart->regs = devm_ioremap_resource(&pdev->dev, res); @@ -208,6 +327,9 @@ static int aspeed_vuart_probe(struct platform_device *pdev) port.port.mapsize = resource_size(res); port.port.startup = aspeed_vuart_startup; port.port.shutdown = aspeed_vuart_shutdown; + port.port.throttle = aspeed_vuart_throttle; + port.port.unthrottle = aspeed_vuart_unthrottle; + port.port.status = UPSTAT_SYNC_FIFO; port.port.dev = &pdev->dev; rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); @@ -253,6 +375,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) port.port.irq = irq_of_parse_and_map(np, 0); port.port.irqflags = IRQF_SHARED; + port.port.handle_irq = aspeed_vuart_handle_irq; port.port.iotype = UPIO_MEM; port.port.type = PORT_16550A; port.port.uartclk = clk; @@ -292,6 +415,7 @@ static int aspeed_vuart_remove(struct platform_device *pdev) { struct aspeed_vuart *vuart = platform_get_drvdata(pdev); + del_timer_sync(&vuart->unthrottle_timer); aspeed_vuart_set_enabled(vuart, false); serial8250_unregister_port(vuart->line); sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 6fcdb90f616a75a5296cd8447dcce889a771d5ae..0529b5cc094bc2fba90c295474da3410a185895e 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -121,25 +121,44 @@ static void dw8250_check_lcr(struct uart_port *p, int value) } /* Returns once the transmitter is empty or we run out of retries */ -static void dw8250_tx_wait_empty(struct uart_port *p, int tries) +static void dw8250_tx_wait_empty(struct uart_port *p) { + unsigned int tries = 20000; + unsigned int delay_threshold = tries - 1000; unsigned int lsr; while (tries--) { lsr = readb (p->membase + (UART_LSR << p->regshift)); if (lsr & UART_LSR_TEMT) break; - udelay (10); + + /* The device is first given a chance to empty without delay, + * to avoid slowdowns at high bitrates. If after 1000 tries + * the buffer has still not emptied, allow more time for low- + * speed links. */ + if (tries < delay_threshold) + udelay (1); } } -static void dw8250_serial_out(struct uart_port *p, int offset, int value) +static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; /* Allow the TX to drain before we reconfigure */ if (offset == UART_LCR) - dw8250_tx_wait_empty(p, 1000); + dw8250_tx_wait_empty(p); + + writeb(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); +} + + +static void dw8250_serial_out(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; writeb(value, p->membase + (offset << p->regshift)); @@ -357,6 +376,9 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) p->serial_in = dw8250_serial_in32be; p->serial_out = dw8250_serial_out32be; } + if (of_device_is_compatible(np, "marvell,armada-38x-uart")) + p->serial_out = dw8250_serial_out38x; + } else if (acpi_dev_present("APMC0D08", NULL, -1)) { p->iotype = UPIO_MEM32; p->regshift = 2; @@ -666,6 +688,7 @@ static const struct dev_pm_ops dw8250_pm_ops = { static const struct of_device_id dw8250_of_match[] = { { .compatible = "snps,dw-apb-uart" }, { .compatible = "cavium,octeon-3860-uart" }, + { .compatible = "marvell,armada-38x-uart" }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, dw8250_of_match); diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index ae6a256524d8b618d4116fde8a66518e4e93cce4..5cd8c36c8fcc908b632674b40e7df087b1a7a162 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -122,7 +122,7 @@ static void __init init_port(struct earlycon_device *device) serial8250_early_out(port, UART_FCR, 0); /* no fifo */ serial8250_early_out(port, UART_MCR, 0x3); /* DTR + RTS */ - if (port->uartclk && device->baud) { + if (port->uartclk) { divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud); c = serial8250_early_in(port, UART_LCR); serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB); diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 9835b1c1cbe103516061af7b62291a28d38c714b..3de8d6a412462097cbc845bbd690da18daa09b04 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -149,6 +149,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->uartclk = clk; port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE; + port->irqflags |= IRQF_SHARED; if (of_property_read_bool(np, "no-loopback-test")) port->flags |= UPF_SKIP_TEST; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 624b501fd253b298a5e0f64e78f6ebef5685be49..6aaa84355fd11138c80be0ceedb0cd6a49057958 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1310,8 +1310,17 @@ static void omap8250_complete(struct device *dev) static int omap8250_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); serial8250_suspend_port(priv->line); + + pm_runtime_get_sync(dev); + if (!device_may_wakeup(dev)) + priv->wer = 0; + serial_out(up, UART_OMAP_WER, priv->wer); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + flush_work(&priv->qos_work); return 0; } @@ -1403,6 +1412,8 @@ static int omap8250_runtime_suspend(struct device *dev) /* Restore to UART mode after reset (for wakeup) */ omap8250_update_mdr1(up, priv); + /* Restore wakeup enable register */ + serial_out(up, UART_OMAP_WER, priv->wer); } if (up->dma && up->dma->rxchan) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 95833cbc4338eca2c82c645aabd67b52c44774cf..8fbd5fbeb31854979a2b644910e746546a92cb11 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1680,7 +1680,7 @@ static void serial8250_enable_ms(struct uart_port *port) serial8250_rpm_put(up); } -static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) +void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) { struct uart_port *port = &up->port; unsigned char ch; @@ -1740,6 +1740,7 @@ static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); } +EXPORT_SYMBOL_GPL(serial8250_read_char); /* * serial8250_rx_chars: processes according to the passed in LSR diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 0f058df0b0701fe296e7a482d9aa81342563500f..eca55187539a2750fcd8156c2b972d1cef066dc0 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -115,7 +115,6 @@ config SERIAL_SB1250_DUART_CONSOLE config SERIAL_ATMEL bool "AT91 on-chip serial port support" - depends on HAS_DMA depends on ARCH_AT91 || COMPILE_TEST select SERIAL_CORE select SERIAL_MCTRL_GPIO if GPIOLIB @@ -500,7 +499,6 @@ config SERIAL_SA1100_CONSOLE config SERIAL_IMX tristate "IMX serial port support" - depends on HAS_DMA depends on ARCH_MXC || COMPILE_TEST select SERIAL_CORE select RATIONAL @@ -676,6 +674,8 @@ config SERIAL_SH_SCI config SERIAL_SH_SCI_NR_UARTS int "Maximum number of SCI(F) serial ports" if EXPERT + range 1 64 if 64BIT + range 1 32 if !64BIT depends on SERIAL_SH_SCI default "3" if H8300 default "10" if SUPERH @@ -1262,7 +1262,6 @@ config SERIAL_PCH_UART_CONSOLE config SERIAL_MXS_AUART tristate "MXS AUART support" - depends on HAS_DMA depends on ARCH_MXS || MACH_ASM9260 || COMPILE_TEST select SERIAL_CORE select SERIAL_MCTRL_GPIO if GPIOLIB @@ -1473,7 +1472,6 @@ config SERIAL_SPRD_CONSOLE config SERIAL_STM32 tristate "STMicroelectronics STM32 serial port support" select SERIAL_CORE - depends on HAS_DMA depends on ARCH_STM32 || COMPILE_TEST help This driver is for the on-chip Serial Controller on diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 22683393a0f2c3f7b6054d367823a3f99f4df103..149d0d0da65e73610c1835e7796f4386b1f8969d 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -281,6 +281,10 @@ int __init of_setup_earlycon(const struct earlycon_id *match, if (val) early_console_dev.baud = be32_to_cpu(*val); + val = of_get_flat_dt_prop(node, "clock-frequency", NULL); + if (val) + port->uartclk = be32_to_cpu(*val); + if (options) { early_console_dev.baud = simple_strtoul(options, NULL, 0); strlcpy(early_console_dev.options, options, diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index c2fc6bef7a6f28a6fc3fe9f18782c555bdb35a35..dd573d8ce087c566be636a199028256ca4d94a87 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2425,8 +2425,7 @@ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on) static int imx_uart_suspend_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct imx_port *sport = platform_get_drvdata(pdev); + struct imx_port *sport = dev_get_drvdata(dev); imx_uart_save_context(sport); @@ -2437,8 +2436,7 @@ static int imx_uart_suspend_noirq(struct device *dev) static int imx_uart_resume_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct imx_port *sport = platform_get_drvdata(pdev); + struct imx_port *sport = dev_get_drvdata(dev); int ret; ret = clk_enable(sport->clk_ipg); @@ -2452,8 +2450,7 @@ static int imx_uart_resume_noirq(struct device *dev) static int imx_uart_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct imx_port *sport = platform_get_drvdata(pdev); + struct imx_port *sport = dev_get_drvdata(dev); int ret; uart_suspend_port(&imx_uart_uart_driver, &sport->port); @@ -2471,8 +2468,7 @@ static int imx_uart_suspend(struct device *dev) static int imx_uart_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct imx_port *sport = platform_get_drvdata(pdev); + struct imx_port *sport = dev_get_drvdata(dev); /* disable wakeup from i.MX UART */ imx_uart_enable_wakeup(sport, false); @@ -2487,8 +2483,7 @@ static int imx_uart_resume(struct device *dev) static int imx_uart_freeze(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct imx_port *sport = platform_get_drvdata(pdev); + struct imx_port *sport = dev_get_drvdata(dev); uart_suspend_port(&imx_uart_uart_driver, &sport->port); @@ -2497,8 +2492,7 @@ static int imx_uart_freeze(struct device *dev) static int imx_uart_thaw(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct imx_port *sport = platform_get_drvdata(pdev); + struct imx_port *sport = dev_get_drvdata(dev); uart_resume_port(&imx_uart_uart_driver, &sport->port); diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index ee96cf0d0057b59c478162d6c7335c4c8be6ebf8..33cd6e59ea6965b1ae18407acd18484e25eefb0c 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1812,11 +1812,36 @@ static const struct of_device_id msm_match_table[] = { }; MODULE_DEVICE_TABLE(of, msm_match_table); +#ifdef CONFIG_PM_SLEEP +static int msm_serial_suspend(struct device *dev) +{ + struct msm_port *port = dev_get_drvdata(dev); + + uart_suspend_port(&msm_uart_driver, &port->uart); + + return 0; +} + +static int msm_serial_resume(struct device *dev) +{ + struct msm_port *port = dev_get_drvdata(dev); + + uart_resume_port(&msm_uart_driver, &port->uart); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops msm_serial_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(msm_serial_suspend, msm_serial_resume) +}; + static struct platform_driver msm_platform_driver = { .remove = msm_serial_remove, .probe = msm_serial_probe, .driver = { .name = "msm_serial", + .pm = &msm_serial_dev_pm_ops, .of_match_table = msm_match_table, }, }; diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index f503fab1e2685f2451d540ed18d5f474a71581b4..d04b5eeea3c6989e9313c00d1085bbd801ffe9cd 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -71,6 +71,8 @@ #define UART_BRDV 0x10 #define BRDV_BAUD_MASK 0x3FF +#define UART_OSAMP 0x14 + #define MVEBU_NR_UARTS 2 #define MVEBU_UART_TYPE "mvebu-uart" @@ -108,6 +110,17 @@ struct mvebu_uart_driver_data { struct uart_flags flags; }; +/* Saved registers during suspend */ +struct mvebu_uart_pm_regs { + unsigned int rbr; + unsigned int tsh; + unsigned int ctrl; + unsigned int intr; + unsigned int stat; + unsigned int brdv; + unsigned int osamp; +}; + /* MVEBU UART driver structure */ struct mvebu_uart { struct uart_port *port; @@ -115,6 +128,9 @@ struct mvebu_uart { int irq[UART_IRQ_COUNT]; unsigned char __iomem *nb; struct mvebu_uart_driver_data *data; +#if defined(CONFIG_PM) + struct mvebu_uart_pm_regs pm_regs; +#endif /* CONFIG_PM */ }; static struct mvebu_uart *to_mvuart(struct uart_port *port) @@ -718,6 +734,51 @@ static struct uart_driver mvebu_uart_driver = { #endif }; +#if defined(CONFIG_PM) +static int mvebu_uart_suspend(struct device *dev) +{ + struct mvebu_uart *mvuart = dev_get_drvdata(dev); + struct uart_port *port = mvuart->port; + + uart_suspend_port(&mvebu_uart_driver, port); + + mvuart->pm_regs.rbr = readl(port->membase + UART_RBR(port)); + mvuart->pm_regs.tsh = readl(port->membase + UART_TSH(port)); + mvuart->pm_regs.ctrl = readl(port->membase + UART_CTRL(port)); + mvuart->pm_regs.intr = readl(port->membase + UART_INTR(port)); + mvuart->pm_regs.stat = readl(port->membase + UART_STAT); + mvuart->pm_regs.brdv = readl(port->membase + UART_BRDV); + mvuart->pm_regs.osamp = readl(port->membase + UART_OSAMP); + + device_set_wakeup_enable(dev, true); + + return 0; +} + +static int mvebu_uart_resume(struct device *dev) +{ + struct mvebu_uart *mvuart = dev_get_drvdata(dev); + struct uart_port *port = mvuart->port; + + writel(mvuart->pm_regs.rbr, port->membase + UART_RBR(port)); + writel(mvuart->pm_regs.tsh, port->membase + UART_TSH(port)); + writel(mvuart->pm_regs.ctrl, port->membase + UART_CTRL(port)); + writel(mvuart->pm_regs.intr, port->membase + UART_INTR(port)); + writel(mvuart->pm_regs.stat, port->membase + UART_STAT); + writel(mvuart->pm_regs.brdv, port->membase + UART_BRDV); + writel(mvuart->pm_regs.osamp, port->membase + UART_OSAMP); + + uart_resume_port(&mvebu_uart_driver, port); + + return 0; +} + +static const struct dev_pm_ops mvebu_uart_pm_ops = { + .suspend = mvebu_uart_suspend, + .resume = mvebu_uart_resume, +}; +#endif /* CONFIG_PM */ + static const struct of_device_id mvebu_uart_of_match[]; /* Counter to keep track of each UART port id when not using CONFIG_OF */ @@ -891,6 +952,9 @@ static struct platform_driver mvebu_uart_platform_driver = { .name = "mvebu-uart", .of_match_table = of_match_ptr(mvebu_uart_of_match), .suppress_bind_attrs = true, +#if defined(CONFIG_PM) + .pm = &mvebu_uart_pm_ops, +#endif /* CONFIG_PM */ }, }; diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index a1b3eb04cb32c78f17ccd32698ced4a459091869..c3eb87c028a6a6b9e7d02f23b01ca30b1a70e1c0 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1087,8 +1087,7 @@ static int qcom_geni_serial_remove(struct platform_device *pdev) static int __maybe_unused qcom_geni_serial_sys_suspend_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); + struct qcom_geni_serial_port *port = dev_get_drvdata(dev); struct uart_port *uport = &port->uport; uart_suspend_port(uport->private_data, uport); @@ -1097,8 +1096,7 @@ static int __maybe_unused qcom_geni_serial_sys_suspend_noirq(struct device *dev) static int __maybe_unused qcom_geni_serial_sys_resume_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); + struct qcom_geni_serial_port *port = dev_get_drvdata(dev); struct uart_port *uport = &port->uport; if (console_suspend_enabled && uport->suspended) { diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 65792a3539d0c8ab4bc99455b3db9800d518e392..243c9602505306c3d7581f7e58a5967b680df838 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1168,7 +1168,10 @@ static int sc16is7xx_probe(struct device *dev, else return PTR_ERR(s->clk); } else { - clk_prepare_enable(s->clk); + ret = clk_prepare_enable(s->clk); + if (ret) + return ret; + freq = clk_get_rate(s->clk); } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 0466f9f08a91388caa866bbecbaa51482eeda206..c47158c93202e20bcc4869dcc7d103aee5e9e2cf 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -674,8 +674,8 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) static void uart_throttle(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; + upstat_t mask = UPSTAT_SYNC_FIFO; struct uart_port *port; - upstat_t mask = 0; port = uart_port_ref(state); if (!port) @@ -703,8 +703,8 @@ static void uart_throttle(struct tty_struct *tty) static void uart_unthrottle(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; + upstat_t mask = UPSTAT_SYNC_FIFO; struct uart_port *port; - upstat_t mask = 0; port = uart_port_ref(state); if (!port) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fdbbff547106e42dfa2098c05a90d646f179b4f0..cc0504f30a1db4283a4d7b74c6a63961fbeea87d 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -160,6 +160,7 @@ struct sci_port { #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS static struct sci_port sci_ports[SCI_NPORTS]; +static unsigned long sci_ports_in_use; static struct uart_driver sci_uart_driver; static inline struct sci_port * @@ -2390,6 +2391,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, uart_update_timeout(port, termios->c_cflag, baud); + /* byte size and parity */ + switch (termios->c_cflag & CSIZE) { + case CS5: + bits = 7; + break; + case CS6: + bits = 8; + break; + case CS7: + bits = 9; + break; + default: + bits = 10; + break; + } + + if (termios->c_cflag & CSTOPB) + bits++; + if (termios->c_cflag & PARENB) + bits++; + if (best_clk >= 0) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) switch (srr + 1) { @@ -2406,8 +2428,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, serial_port_out(port, SCSCR, scr_val | s->hscif_tot); serial_port_out(port, SCSMR, smr_val); serial_port_out(port, SCBRR, brr); - if (sci_getreg(port, HSSRR)->size) - serial_port_out(port, HSSRR, srr | HSCIF_SRE); + if (sci_getreg(port, HSSRR)->size) { + unsigned int hssrr = srr | HSCIF_SRE; + /* Calculate deviation from intended rate at the + * center of the last stop bit in sampling clocks. + */ + int last_stop = bits * 2 - 1; + int deviation = min_err * srr * last_stop / 2 / baud; + + if (abs(deviation) >= 2) { + /* At least two sampling clocks off at the + * last stop bit; we can increase the error + * margin by shifting the sampling point. + */ + int shift = min(-8, max(7, deviation / 2)); + + hssrr |= (shift << HSCIF_SRHP_SHIFT) & + HSCIF_SRHP_MASK; + hssrr |= HSCIF_SRDE; + } + serial_port_out(port, HSSRR, hssrr); + } /* Wait one bit interval */ udelay((1000000 + (baud - 1)) / baud); @@ -2474,27 +2515,6 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, * value obtained by this formula is too small. Therefore, if the value * is smaller than 20ms, use 20ms as the timeout value for DMA. */ - /* byte size and parity */ - switch (termios->c_cflag & CSIZE) { - case CS5: - bits = 7; - break; - case CS6: - bits = 8; - break; - case CS7: - bits = 9; - break; - default: - bits = 10; - break; - } - - if (termios->c_cflag & CSTOPB) - bits++; - if (termios->c_cflag & PARENB) - bits++; - s->rx_frame = (10000 * bits) / (baud / 100); #ifdef CONFIG_SERIAL_SH_SCI_DMA s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame; @@ -3026,6 +3046,7 @@ static int sci_remove(struct platform_device *dev) { struct sci_port *port = platform_get_drvdata(dev); + sci_ports_in_use &= ~BIT(port->port.line); uart_remove_one_port(&sci_uart_driver, &port->port); sci_cleanup_single(port); @@ -3107,6 +3128,8 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, /* Get the line number from the aliases node. */ id = of_alias_get_id(np, "serial"); + if (id < 0 && ~sci_ports_in_use) + id = ffz(sci_ports_in_use); if (id < 0) { dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); return NULL; @@ -3141,6 +3164,9 @@ static int sci_probe_single(struct platform_device *dev, dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); return -EINVAL; } + BUILD_BUG_ON(SCI_NPORTS > sizeof(sci_ports_in_use) * 8); + if (sci_ports_in_use & BIT(index)) + return -EBUSY; mutex_lock(&sci_uart_registration_lock); if (!sci_uart_driver.state) { @@ -3239,6 +3265,7 @@ static int sci_probe(struct platform_device *dev) sh_bios_gdb_detach(); #endif + sci_ports_in_use |= BIT(dev_id); return 0; } diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index a5f792fd48d9ca92eb46ed2e54e5aa515f6a60ae..0b9e804e61a9f156f9b3cfbe3d55494010d43280 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -130,6 +130,10 @@ enum { /* HSSRR HSCIF */ #define HSCIF_SRE BIT(15) /* Sampling Rate Register Enable */ +#define HSCIF_SRDE BIT(14) /* Sampling Point Register Enable */ + +#define HSCIF_SRHP_SHIFT 8 +#define HSCIF_SRHP_MASK 0x0f00 /* SCPCR (Serial Port Control Register), SCIFA/SCIFB only */ #define SCPCR_RTSC BIT(4) /* Serial Port RTS# Pin / Output Pin */ diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index 5f9f01fac6dd4e7c95200617df90548360191fa1..7971997cdead772612f566b5df295a616b99f71d 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -842,16 +842,14 @@ static int asc_serial_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int asc_serial_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct uart_port *port = platform_get_drvdata(pdev); + struct uart_port *port = dev_get_drvdata(dev); return uart_suspend_port(&asc_uart_driver, port); } static int asc_serial_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct uart_port *port = platform_get_drvdata(pdev); + struct uart_port *port = dev_get_drvdata(dev); return uart_resume_port(&asc_uart_driver, port); } diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index bd72dd843338dc9a3aecaacaa04dc7b2fc2442db..8a3e34234e981c24a79e4de1902f1e188b7a19f7 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1097,45 +1097,6 @@ static const struct uart_ops cdns_uart_ops = { #endif }; -static struct uart_port cdns_uart_port[CDNS_UART_NR_PORTS]; - -/** - * cdns_uart_get_port - Configure the port from platform device resource info - * @id: Port id - * - * Return: a pointer to a uart_port or NULL for failure - */ -static struct uart_port *cdns_uart_get_port(int id) -{ - struct uart_port *port; - - /* Try the given port id if failed use default method */ - if (id < CDNS_UART_NR_PORTS && cdns_uart_port[id].mapbase != 0) { - /* Find the next unused port */ - for (id = 0; id < CDNS_UART_NR_PORTS; id++) - if (cdns_uart_port[id].mapbase == 0) - break; - } - - if (id >= CDNS_UART_NR_PORTS) - return NULL; - - port = &cdns_uart_port[id]; - - /* At this point, we've got an empty uart_port struct, initialize it */ - spin_lock_init(&port->lock); - port->membase = NULL; - port->irq = 0; - port->type = PORT_UNKNOWN; - port->iotype = UPIO_MEM32; - port->flags = UPF_BOOT_AUTOCONF; - port->ops = &cdns_uart_ops; - port->fifosize = CDNS_UART_FIFO_SIZE; - port->line = id; - port->dev = NULL; - return port; -} - #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE /** * cdns_uart_console_wait_tx - Wait for the TX to be full @@ -1206,6 +1167,10 @@ OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p8", cdns_early_console_setup); OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p12", cdns_early_console_setup); OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup); + +/* Static pointer to console port */ +static struct uart_port *console_port; + /** * cdns_uart_console_write - perform write operation * @co: Console handle @@ -1215,7 +1180,7 @@ OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup); static void cdns_uart_console_write(struct console *co, const char *s, unsigned int count) { - struct uart_port *port = &cdns_uart_port[co->index]; + struct uart_port *port = console_port; unsigned long flags; unsigned int imr, ctrl; int locked = 1; @@ -1261,15 +1226,13 @@ static void cdns_uart_console_write(struct console *co, const char *s, */ static int __init cdns_uart_console_setup(struct console *co, char *options) { - struct uart_port *port = &cdns_uart_port[co->index]; + struct uart_port *port = console_port; + int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; - if (co->index < 0 || co->index >= CDNS_UART_NR_PORTS) - return -EINVAL; - if (!port->membase) { pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n", co->index); @@ -1293,20 +1256,6 @@ static struct console cdns_uart_console = { .index = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */ .data = &cdns_uart_uart_driver, }; - -/** - * cdns_uart_console_init - Initialization call - * - * Return: 0 on success, negative errno otherwise - */ -static int __init cdns_uart_console_init(void) -{ - register_console(&cdns_uart_console); - return 0; -} - -console_initcall(cdns_uart_console_init); - #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ static struct uart_driver cdns_uart_uart_driver = { @@ -1430,8 +1379,7 @@ static int cdns_uart_resume(struct device *device) #endif /* ! CONFIG_PM_SLEEP */ static int __maybe_unused cdns_runtime_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct uart_port *port = platform_get_drvdata(pdev); + struct uart_port *port = dev_get_drvdata(dev); struct cdns_uart *cdns_uart = port->private_data; clk_disable(cdns_uart->uartclk); @@ -1441,8 +1389,7 @@ static int __maybe_unused cdns_runtime_suspend(struct device *dev) static int __maybe_unused cdns_runtime_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct uart_port *port = platform_get_drvdata(pdev); + struct uart_port *port = dev_get_drvdata(dev); struct cdns_uart *cdns_uart = port->private_data; clk_enable(cdns_uart->pclk); @@ -1487,6 +1434,9 @@ static int cdns_uart_probe(struct platform_device *pdev) GFP_KERNEL); if (!cdns_uart_data) return -ENOMEM; + port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); + if (!port) + return -ENOMEM; match = of_match_node(cdns_uart_of_match, pdev->dev.of_node); if (match && match->data) { @@ -1552,15 +1502,24 @@ static int cdns_uart_probe(struct platform_device *pdev) if (id < 0) id = 0; - /* Initialize the port structure */ - port = cdns_uart_get_port(id); - - if (!port) { + if (id >= CDNS_UART_NR_PORTS) { dev_err(&pdev->dev, "Cannot get uart_port structure\n"); rc = -ENODEV; goto err_out_notif_unreg; } + /* At this point, we've got an empty uart_port struct, initialize it */ + spin_lock_init(&port->lock); + port->membase = NULL; + port->irq = 0; + port->type = PORT_UNKNOWN; + port->iotype = UPIO_MEM32; + port->flags = UPF_BOOT_AUTOCONF; + port->ops = &cdns_uart_ops; + port->fifosize = CDNS_UART_FIFO_SIZE; + port->line = id; + port->dev = NULL; + /* * Register the port. * This function also registers this device with the tty layer @@ -1579,6 +1538,17 @@ static int cdns_uart_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); +#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE + /* + * If console hasn't been found yet try to assign this port + * because it is required to be assigned for console setup function. + * If register_console() don't assign value, then console_port pointer + * is cleanup. + */ + if (cdns_uart_uart_driver.cons->index == -1) + console_port = port; +#endif + rc = uart_add_one_port(&cdns_uart_uart_driver, port); if (rc) { dev_err(&pdev->dev, @@ -1586,6 +1556,12 @@ static int cdns_uart_probe(struct platform_device *pdev) goto err_out_pm_disable; } +#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE + /* This is not port which is used for console that's why clean it up */ + if (cdns_uart_uart_driver.cons->index == -1) + console_port = NULL; +#endif + return 0; err_out_pm_disable: diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index a27ef5f56431783f516e039944b8cf4d75c898e3..76b9db71e489bf63f89b6c3cc5fd99689d36412f 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -163,6 +163,7 @@ extern void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); extern int fsl8250_handle_irq(struct uart_port *port); int serial8250_handle_irq(struct uart_port *port, unsigned int iir); unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr); +void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr); void serial8250_tx_chars(struct uart_8250_port *up); unsigned int serial8250_modem_status(struct uart_8250_port *up); void serial8250_init_port(struct uart_8250_port *up); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index b4c9fda9d8335bd3b20611d9684645dce3f8532c..06ea4eeb09abd759dec1bc9740d89220f579584f 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -233,6 +233,7 @@ struct uart_port { #define UPSTAT_AUTORTS ((__force upstat_t) (1 << 2)) #define UPSTAT_AUTOCTS ((__force upstat_t) (1 << 3)) #define UPSTAT_AUTOXOFF ((__force upstat_t) (1 << 4)) +#define UPSTAT_SYNC_FIFO ((__force upstat_t) (1 << 5)) int hw_stopped; /* sw-assisted CTS flow state */ unsigned int mctrl; /* current modem ctrl settings */ @@ -348,7 +349,8 @@ struct earlycon_device { }; struct earlycon_id { - char name[16]; + char name[15]; + char name_term; /* In case compiler didn't '\0' term name */ char compatible[128]; int (*setup)(struct earlycon_device *, const char *options); };