Merge tag 'tty-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial driver updates from Greg KH:
 "Here is the big tty and serial driver update for 4.4-rc1.

  Lots of serial driver updates and a few small tty core changes.  Full
  details in the shortlog.

  All of these have been in linux-next for a while"

* tag 'tty-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (148 commits)
  tty: Use unbound workqueue for all input workers
  tty: Abstract tty buffer work
  tty: Prevent tty teardown during tty_write_message()
  tty: core: Use correct spinlock flavor in tiocspgrp()
  tty: Combine SIGTTOU/SIGTTIN handling
  serial: amba-pl011: fix incorrect integer size in pl011_fifo_to_tty()
  ttyFDC: Fix build problems due to use of module_{init,exit}
  tty: remove unneeded return statement
  serial: 8250_mid: add support for DMA engine handling from UART MMIO
  dmaengine: hsu: remove platform data
  dmaengine: hsu: introduce stubs for the exported functions
  dmaengine: hsu: make the UART driver in control of selecting this driver
  serial: fix mctrl helper functions
  serial: 8250_pci: Intel MID UART support to its own driver
  serial: fsl_lpuart: add earlycon support
  tty: disable unbind for old 74xx based serial/mpsc console port
  serial: pl011: Spelling s/clocks-names/clock-names/
  n_tty: Remove reader wakeups for TTY_BREAK/TTY_PARITY chars
  tty: synclink, fix indentation
  serial: at91, fix rs485 properties
  ...
diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
index c2d3b3a..02cb7fe 100644
--- a/Documentation/devicetree/bindings/serial/ingenic,uart.txt
+++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
@@ -1,7 +1,8 @@
 * Ingenic SoC UART
 
 Required properties:
-- compatible : "ingenic,jz4740-uart" or "ingenic,jz4780-uart"
+- compatible : "ingenic,jz4740-uart", "ingenic,jz4760-uart",
+	"ingenic,jz4775-uart" or "ingenic,jz4780-uart"
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
 - clocks : phandles to the module & baud clocks.
diff --git a/Documentation/devicetree/bindings/serial/pl011.txt b/Documentation/devicetree/bindings/serial/pl011.txt
index cbae3d9..77863ae 100644
--- a/Documentation/devicetree/bindings/serial/pl011.txt
+++ b/Documentation/devicetree/bindings/serial/pl011.txt
@@ -19,7 +19,7 @@
 	   must correspond to the PCLK clocking the internal logic
 	   of the block. Just listing one clock (the first one) is
 	   deprecated.
-- clocks-names:
+- clock-names:
 	   When present, the first clock listed must be named
 	   "uartclk" and the second clock listed must be named
 	   "apb_pclk"
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt
index a2114c2..182777f 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt
@@ -26,6 +26,12 @@
 Optional properties:
 - dmas: Should contain dma specifiers for transmit and receive channels
 - dma-names: Should contain "tx" for transmit and "rx" for receive channels
+- qcom,tx-crci: Identificator <u32> for Client Rate Control Interface to be
+           used with TX DMA channel. Required when using DMA for transmission
+           with UARTDM v1.3 and bellow.
+- qcom,rx-crci: Identificator <u32> for Client Rate Control Interface to be
+           used with RX DMA channel. Required when using DMA for reception
+           with UARTDM v1.3 and bellow.
 
 Note: Aliases may be defined to ensure the correct ordering of the UARTs.
 The alias serialN will result in the UART being assigned port N.  If any
diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
index e84b13a..73f825e 100644
--- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
+++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
@@ -23,6 +23,8 @@
     - "renesas,scifa-r8a7794" for R8A7794 (R-Car E2) SCIFA compatible UART.
     - "renesas,scifb-r8a7794" for R8A7794 (R-Car E2) SCIFB compatible UART.
     - "renesas,hscif-r8a7794" for R8A7794 (R-Car E2) HSCIF compatible UART.
+    - "renesas,scif-r8a7795" for R8A7795 (R-Car H3) SCIF compatible UART.
+    - "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
     - "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
     - "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART.
     - "renesas,scif" for generic SCIF compatible UART.
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
index 289c40e..12bbe9f 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
@@ -15,6 +15,9 @@
 	Required elements: "baudclk", "apb_pclk"
 
 Optional properties:
+- snps,uart-16550-compatible : reflects the value of UART_16550_COMPATIBLE
+  configuration parameter. Define this if your UART does not implement the busy
+  functionality.
 - resets : phandle to the parent reset controller.
 - reg-shift : quantity to shift the register offsets by.  If this property is
   not present then the register offsets are not shifted.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index c76200a..6263a2d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1024,6 +1024,13 @@
 			serial port must already be setup and configured.
 			Options are not yet supported.
 
+		lpuart,<addr>
+		lpuart32,<addr>
+			Use early console provided by Freescale LP UART driver
+			found on Freescale Vybrid and QorIQ LS1021A processors.
+			A valid base address must be provided, and the serial
+			port must already be setup and configured.
+
 	earlyprintk=	[X86,SH,BLACKFIN,ARM,M68k]
 			earlyprintk=vga
 			earlyprintk=efi
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index c415b0e..379468e 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -439,11 +439,13 @@
 
 Some helpers are provided in order to set/get modem control lines via GPIO.
 
-mctrl_gpio_init(dev, idx):
+mctrl_gpio_init(port, idx):
 	This will get the {cts,rts,...}-gpios from device tree if they are
 	present and request them, set direction etc, and return an
 	allocated structure. devm_* functions are used, so there's no need
 	to call mctrl_gpio_free().
+	As this sets up the irq handling make sure to not handle changes to the
+	gpio input lines in your driver, too.
 
 mctrl_gpio_free(dev, gpios):
 	This will free the requested gpios in mctrl_gpio_init().
@@ -458,3 +460,9 @@
 
 mctrl_gpio_get(gpios, mctrl):
 	This will update mctrl with the gpios values.
+
+mctrl_gpio_enable_ms(gpios):
+	Enables irqs and handling of changes to the ms lines.
+
+mctrl_gpio_disable_ms(gpios):
+	Disables irqs and handling of changes to the ms lines.
diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt
index 973c8ad..bc3842dc 100644
--- a/Documentation/serial/tty.txt
+++ b/Documentation/serial/tty.txt
@@ -39,8 +39,13 @@
 open()		-	Called when the line discipline is attached to
 			the terminal. No other call into the line
 			discipline for this tty will occur until it
-			completes successfully. Returning an error will
-			prevent the ldisc from being attached. Can sleep.
+			completes successfully. Should initialize any
+			state needed by the ldisc, and set receive_room
+			in the tty_struct to the maximum amount of data
+			the line discipline is willing to accept from the
+			driver with a single call to receive_buf().
+			Returning an error will prevent the ldisc from
+			being attached. Can sleep.
 
 close()		-	This is called on a terminal when the line
 			discipline is being unplugged. At the point of
@@ -52,9 +57,16 @@
 			No further calls into the ldisc code will occur.
 			The return value is ignored. Can sleep.
 
-write()		-	A process is writing data through the line
-			discipline.  Multiple write calls are serialized
-			by the tty layer for the ldisc.  May sleep. 
+read()		-	(optional) A process requests reading data from
+			the line. Multiple read calls may occur in parallel
+			and the ldisc must deal with serialization issues.
+			If not defined, the process will receive an EIO
+			error. May sleep.
+
+write()		-	(optional) A process requests writing data to the
+			line. Multiple write calls are serialized by the
+			tty layer for the ldisc. If not defined, the
+			process will receive an EIO error. May sleep.
 
 flush_buffer()	-	(optional) May be called at any point between
 			open and close, and instructs the line discipline
@@ -69,27 +81,33 @@
 			termios semaphore so allowed to sleep. Serialized
 			against itself only.
 
-read()		-	Move data from the line discipline to the user.
-			Multiple read calls may occur in parallel and the
-			ldisc must deal with serialization issues. May 
-			sleep.
+poll()		-	(optional) Check the status for the poll/select
+			calls. Multiple poll calls may occur in parallel.
+			May sleep.
 
-poll()		-	Check the status for the poll/select calls. Multiple
-			poll calls may occur in parallel. May sleep.
+ioctl()		-	(optional) Called when an ioctl is handed to the
+			tty layer that might be for the ldisc. Multiple
+			ioctl calls may occur in parallel. May sleep.
 
-ioctl()		-	Called when an ioctl is handed to the tty layer
-			that might be for the ldisc. Multiple ioctl calls
-			may occur in parallel. May sleep. 
-
-compat_ioctl()	-	Called when a 32 bit ioctl is handed to the tty layer
-			that might be for the ldisc. Multiple ioctl calls
-			may occur in parallel. May sleep.
+compat_ioctl()	-	(optional) Called when a 32 bit ioctl is handed
+			to the tty layer that might be for the ldisc.
+			Multiple ioctl calls may occur in parallel.
+			May sleep.
 
 Driver Side Interfaces:
 
-receive_buf()	-	Hand buffers of bytes from the driver to the ldisc
-			for processing. Semantics currently rather
-			mysterious 8(
+receive_buf()	-	(optional) Called by the low-level driver to hand
+			a buffer of received bytes to the ldisc for
+			processing. The number of bytes is guaranteed not
+			to exceed the current value of tty->receive_room.
+			All bytes must be processed.
+
+receive_buf2()	-	(optional) Called by the low-level driver to hand
+			a buffer of received bytes to the ldisc for
+			processing. Returns the number of bytes processed.
+
+			If both receive_buf() and receive_buf2() are
+			defined, receive_buf2() should be preferred.
 
 write_wakeup()	-	May be called at any point between open and close.
 			The TTY_DO_WRITE_WAKEUP flag indicates if a call
diff --git a/arch/arm64/include/asm/dcc.h b/arch/arm64/include/asm/dcc.h
new file mode 100644
index 0000000..65e0190
--- /dev/null
+++ b/arch/arm64/include/asm/dcc.h
@@ -0,0 +1,55 @@
+/* Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * A call to __dcc_getchar() or __dcc_putchar() is typically followed by
+ * a call to __dcc_getstatus().  We want to make sure that the CPU does
+ * not speculative read the DCC status before executing the read or write
+ * instruction.  That's what the ISBs are for.
+ *
+ * The 'volatile' ensures that the compiler does not cache the status bits,
+ * and instead reads the DCC register every time.
+ */
+#ifndef __ASM_DCC_H
+#define __ASM_DCC_H
+
+#include <asm/barrier.h>
+
+static inline u32 __dcc_getstatus(void)
+{
+	u32 ret;
+
+	asm volatile("mrs %0, mdccsr_el0" : "=r" (ret));
+
+	return ret;
+}
+
+static inline char __dcc_getchar(void)
+{
+	char c;
+
+	asm volatile("mrs %0, dbgdtrrx_el0" : "=r" (c));
+	isb();
+
+	return c;
+}
+
+static inline void __dcc_putchar(char c)
+{
+	/*
+	 * The typecast is to make absolutely certain that 'c' is
+	 * zero-extended.
+	 */
+	asm volatile("msr dbgdtrtx_el0, %0"
+			: : "r" ((unsigned long)(unsigned char)c));
+	isb();
+}
+
+#endif
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 7680d52..45df4bf9 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2507,15 +2507,6 @@
 		printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
 			 __FILE__, __LINE__, tty->driver->name, port->count);
 
-	/* If port is closing, signal caller to try again */
-	if (port->flags & ASYNC_CLOSING){
-		wait_event_interruptible_tty(tty, port->close_wait,
-					     !(port->flags & ASYNC_CLOSING));
-		retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-
 	port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 	spin_lock_irqsave(&info->netlock, flags);
diff --git a/drivers/dma/hsu/Kconfig b/drivers/dma/hsu/Kconfig
index 2810dca7..c708417 100644
--- a/drivers/dma/hsu/Kconfig
+++ b/drivers/dma/hsu/Kconfig
@@ -5,10 +5,5 @@
 	select DMA_VIRTUAL_CHANNELS
 
 config HSU_DMA_PCI
-	tristate "High Speed UART DMA PCI driver"
-	depends on PCI
-	select HSU_DMA
-	help
-	  Support the High Speed UART DMA on the platfroms that
-	  enumerate it as a PCI device. For example, Intel Medfield
-	  has integrated this HSU DMA controller.
+	tristate
+	depends on HSU_DMA && PCI
diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c
index 7669c7d..823ad72 100644
--- a/drivers/dma/hsu/hsu.c
+++ b/drivers/dma/hsu/hsu.c
@@ -146,7 +146,7 @@
 	u32 sr;
 
 	/* Sanity check */
-	if (nr >= chip->pdata->nr_channels)
+	if (nr >= chip->hsu->nr_channels)
 		return IRQ_NONE;
 
 	hsuc = &chip->hsu->chan[nr];
@@ -375,7 +375,6 @@
 int hsu_dma_probe(struct hsu_dma_chip *chip)
 {
 	struct hsu_dma *hsu;
-	struct hsu_dma_platform_data *pdata = chip->pdata;
 	void __iomem *addr = chip->regs + chip->offset;
 	unsigned short i;
 	int ret;
@@ -386,25 +385,16 @@
 
 	chip->hsu = hsu;
 
-	if (!pdata) {
-		pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
-		if (!pdata)
-			return -ENOMEM;
+	/* Calculate nr_channels from the IO space length */
+	hsu->nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH;
 
-		chip->pdata = pdata;
-
-		/* Guess nr_channels from the IO space length */
-		pdata->nr_channels = (chip->length - chip->offset) /
-				     HSU_DMA_CHAN_LENGTH;
-	}
-
-	hsu->chan = devm_kcalloc(chip->dev, pdata->nr_channels,
+	hsu->chan = devm_kcalloc(chip->dev, hsu->nr_channels,
 				 sizeof(*hsu->chan), GFP_KERNEL);
 	if (!hsu->chan)
 		return -ENOMEM;
 
 	INIT_LIST_HEAD(&hsu->dma.channels);
-	for (i = 0; i < pdata->nr_channels; i++) {
+	for (i = 0; i < hsu->nr_channels; i++) {
 		struct hsu_dma_chan *hsuc = &hsu->chan[i];
 
 		hsuc->vchan.desc_free = hsu_dma_desc_free;
@@ -440,7 +430,7 @@
 	if (ret)
 		return ret;
 
-	dev_info(chip->dev, "Found HSU DMA, %d channels\n", pdata->nr_channels);
+	dev_info(chip->dev, "Found HSU DMA, %d channels\n", hsu->nr_channels);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(hsu_dma_probe);
@@ -452,7 +442,7 @@
 
 	dma_async_device_unregister(&hsu->dma);
 
-	for (i = 0; i < chip->pdata->nr_channels; i++) {
+	for (i = 0; i < hsu->nr_channels; i++) {
 		struct hsu_dma_chan *hsuc = &hsu->chan[i];
 
 		tasklet_kill(&hsuc->vchan.task);
diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h
index eeb9fff..f06579c 100644
--- a/drivers/dma/hsu/hsu.h
+++ b/drivers/dma/hsu/hsu.h
@@ -107,6 +107,7 @@
 
 	/* channels */
 	struct hsu_dma_chan		*chan;
+	unsigned short			nr_channels;
 };
 
 static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)
diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c
index 77879e6..e2db76b 100644
--- a/drivers/dma/hsu/pci.c
+++ b/drivers/dma/hsu/pci.c
@@ -31,7 +31,7 @@
 	irqreturn_t ret = IRQ_NONE;
 
 	dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
-	for (i = 0; i < chip->pdata->nr_channels; i++) {
+	for (i = 0; i < chip->hsu->nr_channels; i++) {
 		if (dmaisr & 0x1)
 			ret |= hsu_dma_irq(chip, i);
 		dmaisr >>= 1;
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index bc91261..2175225 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1582,7 +1582,7 @@
 	 * line status register.
 	 */
 	if (port->flags & ASYNC_INITIALIZED) {
-		tty_wait_until_sent_from_close(tty, 3000);	/* 30 seconds timeout */
+		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index 87f6578..d4a1331 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1577,15 +1577,6 @@
 #endif
 
 	/*
-	 * If the port is the middle of closing, bail out now
-	 */
-	if (info->port.flags & ASYNC_CLOSING) {
-		wait_event_interruptible_tty(tty, info->port.close_wait,
-				!(info->port.flags & ASYNC_CLOSING));
-		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
-	}
-
-	/*
 	 * Start up serial port
 	 */
 	retval = cy_startup(info, tty);
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 2509d05..574da15 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -81,7 +81,7 @@
 
 config HVC_DCC
        bool "ARM JTAG DCC console"
-       depends on ARM
+       depends on ARM || ARM64
        select HVC_DRIVER
        help
          This console uses the JTAG DCC on ARM to create a console under the HVC
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 4e9c4cc..e46d628 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/major.h>
 #include <linux/atomic.h>
 #include <linux/sysrq.h>
@@ -418,7 +418,7 @@
 		 * there is no buffered data otherwise sleeps on a wait queue
 		 * waking periodically to check chars_in_buffer().
 		 */
-		tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT);
+		tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
 	} else {
 		if (hp->port.count < 0)
 			printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
@@ -1005,19 +1005,3 @@
 out:
 	return err;
 }
-
-/* This isn't particularly necessary due to this being a console driver
- * but it is nice to be thorough.
- */
-static void __exit hvc_exit(void)
-{
-	if (hvc_driver) {
-		kthread_stop(hvc_task);
-
-		tty_unregister_driver(hvc_driver);
-		/* return tty_struct instances allocated in hvc_init(). */
-		put_tty_driver(hvc_driver);
-		unregister_console(&hvc_console);
-	}
-}
-module_exit(hvc_exit);
diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c
index 809920d..82f240f 100644
--- a/drivers/tty/hvc/hvc_dcc.c
+++ b/drivers/tty/hvc/hvc_dcc.c
@@ -70,20 +70,27 @@
 
 static int __init hvc_dcc_console_init(void)
 {
+	int ret;
+
 	if (!hvc_dcc_check())
 		return -ENODEV;
 
-	hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
-	return 0;
+	/* Returns -1 if error */
+	ret = hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
+
+	return ret < 0 ? -ENODEV : 0;
 }
 console_initcall(hvc_dcc_console_init);
 
 static int __init hvc_dcc_init(void)
 {
+	struct hvc_struct *p;
+
 	if (!hvc_dcc_check())
 		return -ENODEV;
 
-	hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
-	return 0;
+	p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
+
+	return PTR_ERR_OR_ZERO(p);
 }
 device_initcall(hvc_dcc_init);
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index f7ff97c..5997b17 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1230,7 +1230,7 @@
 		irq = hvcsd->vdev->irq;
 		spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-		tty_wait_until_sent_from_close(tty, HVCS_CLOSE_WAIT);
+		tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
 
 		/*
 		 * This line is important because it tells hvcs_open that this
diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c
index a8c8cfd..a119176 100644
--- a/drivers/tty/mips_ejtag_fdc.c
+++ b/drivers/tty/mips_ejtag_fdc.c
@@ -977,7 +977,7 @@
 	/* Try requesting the IRQ */
 	if (priv->irq >= 0) {
 		/*
-		 * IRQF_SHARED, IRQF_NO_SUSPEND: The FDC IRQ may be shared with
+		 * IRQF_SHARED, IRQF_COND_SUSPEND: The FDC IRQ may be shared with
 		 * other local interrupts such as the timer which sets
 		 * IRQF_TIMER (including IRQF_NO_SUSPEND).
 		 *
@@ -987,7 +987,7 @@
 		 */
 		ret = devm_request_irq(priv->dev, priv->irq, mips_ejtag_fdc_isr,
 				       IRQF_PERCPU | IRQF_SHARED |
-				       IRQF_NO_THREAD | IRQF_NO_SUSPEND,
+				       IRQF_NO_THREAD | IRQF_COND_SUSPEND,
 				       priv->fdc_name, priv);
 		if (ret)
 			priv->irq = -1;
@@ -1048,38 +1048,6 @@
 	return ret;
 }
 
-static int mips_ejtag_fdc_tty_remove(struct mips_cdmm_device *dev)
-{
-	struct mips_ejtag_fdc_tty *priv = mips_cdmm_get_drvdata(dev);
-	struct mips_ejtag_fdc_tty_port *dport;
-	int nport;
-	unsigned int cfg;
-
-	if (priv->irq >= 0) {
-		raw_spin_lock_irq(&priv->lock);
-		cfg = mips_ejtag_fdc_read(priv, REG_FDCFG);
-		/* Disable interrupts */
-		cfg &= ~(REG_FDCFG_TXINTTHRES | REG_FDCFG_RXINTTHRES);
-		cfg |= REG_FDCFG_TXINTTHRES_DISABLED;
-		cfg |= REG_FDCFG_RXINTTHRES_DISABLED;
-		mips_ejtag_fdc_write(priv, REG_FDCFG, cfg);
-		raw_spin_unlock_irq(&priv->lock);
-	} else {
-		priv->removing = true;
-		del_timer_sync(&priv->poll_timer);
-	}
-	kthread_stop(priv->thread);
-	if (dev->cpu == 0)
-		mips_ejtag_fdc_con.tty_drv = NULL;
-	tty_unregister_driver(priv->driver);
-	for (nport = 0; nport < NUM_TTY_CHANNELS; nport++) {
-		dport = &priv->ports[nport];
-		tty_port_destroy(&dport->port);
-	}
-	put_tty_driver(priv->driver);
-	return 0;
-}
-
 static int mips_ejtag_fdc_tty_cpu_down(struct mips_cdmm_device *dev)
 {
 	struct mips_ejtag_fdc_tty *priv = mips_cdmm_get_drvdata(dev);
@@ -1152,12 +1120,11 @@
 		.name	= "mips_ejtag_fdc",
 	},
 	.probe		= mips_ejtag_fdc_tty_probe,
-	.remove		= mips_ejtag_fdc_tty_remove,
 	.cpu_down	= mips_ejtag_fdc_tty_cpu_down,
 	.cpu_up		= mips_ejtag_fdc_tty_cpu_up,
 	.id_table	= mips_ejtag_fdc_tty_ids,
 };
-module_mips_cdmm_driver(mips_ejtag_fdc_tty_driver);
+builtin_mips_cdmm_driver(mips_ejtag_fdc_tty_driver);
 
 static int __init mips_ejtag_fdc_init_console(void)
 {
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 8b157d6..3451114 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -276,7 +276,7 @@
 			add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
 				error_code, NULL);
 		}
-		wake_up_interruptible(&pInfo->read_wait);
+		wake_up_interruptible(&pInfo->tty->read_wait);
 	}
 
 	spin_lock_irqsave(&pInfo->lock, flags);
@@ -542,7 +542,7 @@
 				pBlock);
 		}
 	}
-	wake_up_interruptible(&pInfo->read_wait);
+	wake_up_interruptible(&pInfo->tty->read_wait);
 
 	pInfo->state = R3964_IDLE;
 
@@ -978,8 +978,8 @@
 	}
 
 	spin_lock_init(&pInfo->lock);
+	mutex_init(&pInfo->read_lock);
 	pInfo->tty = tty;
-	init_waitqueue_head(&pInfo->read_wait);
 	pInfo->priority = R3964_MASTER;
 	pInfo->rx_first = pInfo->rx_last = NULL;
 	pInfo->tx_first = pInfo->tx_last = NULL;
@@ -1045,7 +1045,6 @@
 	}
 
 	/* Free buffers: */
-	wake_up_interruptible(&pInfo->read_wait);
 	kfree(pInfo->rx_buf);
 	TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf);
 	kfree(pInfo->tx_buf);
@@ -1065,7 +1064,16 @@
 
 	TRACE_L("read()");
 
-	tty_lock(tty);
+	/*
+	 *	Internal serialization of reads.
+	 */
+	if (file->f_flags & O_NONBLOCK) {
+		if (!mutex_trylock(&pInfo->read_lock))
+			return -EAGAIN;
+	} else {
+		if (mutex_lock_interruptible(&pInfo->read_lock))
+			return -ERESTARTSYS;
+	}
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
@@ -1077,7 +1085,7 @@
 				goto unlock;
 			}
 			/* block until there is a message: */
-			wait_event_interruptible_tty(tty, pInfo->read_wait,
+			wait_event_interruptible(tty->read_wait,
 					(pMsg = remove_msg(pInfo, pClient)));
 		}
 
@@ -1107,7 +1115,7 @@
 	}
 	ret = -EPERM;
 unlock:
-	tty_unlock(tty);
+	mutex_unlock(&pInfo->read_lock);
 	return ret;
 }
 
@@ -1156,8 +1164,6 @@
 	pHeader->locks = 0;
 	pHeader->owner = NULL;
 
-	tty_lock(tty);
-
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
 		pHeader->owner = pClient;
@@ -1175,8 +1181,6 @@
 	add_tx_queue(pInfo, pHeader);
 	trigger_transmit(pInfo);
 
-	tty_unlock(tty);
-
 	return 0;
 }
 
@@ -1227,7 +1231,7 @@
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
-		poll_wait(file, &pInfo->read_wait, wait);
+		poll_wait(file, &tty->read_wait, wait);
 		spin_lock_irqsave(&pInfo->lock, flags);
 		pMsg = pClient->first_msg;
 		spin_unlock_irqrestore(&pInfo->lock, flags);
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index b09023b..1384426 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -201,7 +201,7 @@
 		 */
 		WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
 			       "scheduling buffer work for halted ldisc\n");
-		queue_work(system_unbound_wq, &tty->port->buf.work);
+		tty_buffer_restart_work(tty->port);
 	}
 }
 
@@ -1179,8 +1179,6 @@
 		put_tty_queue('\0', ldata);
 	}
 	put_tty_queue('\0', ldata);
-	if (waitqueue_active(&tty->read_wait))
-		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 }
 
 /**
@@ -1237,8 +1235,6 @@
 			put_tty_queue('\0', ldata);
 	} else
 		put_tty_queue(c, ldata);
-	if (waitqueue_active(&tty->read_wait))
-		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 }
 
 static void
@@ -2142,37 +2138,15 @@
 
 static int job_control(struct tty_struct *tty, struct file *file)
 {
-	struct pid *pgrp;
-
 	/* Job control check -- must be done at start and after
 	   every sleep (POSIX.1 7.1.1.4). */
 	/* NOTE: not yet done after every sleep pending a thorough
 	   check of the logic of this change. -- jlc */
 	/* don't stop on /dev/console */
-	if (file->f_op->write == redirected_tty_write ||
-	    current->signal->tty != tty)
+	if (file->f_op->write == redirected_tty_write)
 		return 0;
 
-	rcu_read_lock();
-	pgrp = task_pgrp(current);
-
-	spin_lock_irq(&tty->ctrl_lock);
-	if (!tty->pgrp)
-		printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
-	else if (pgrp != tty->pgrp) {
-		spin_unlock_irq(&tty->ctrl_lock);
-		if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
-			rcu_read_unlock();
-			return -EIO;
-		}
-		kill_pgrp(pgrp, SIGTTIN, 1);
-		rcu_read_unlock();
-		set_thread_flag(TIF_SIGPENDING);
-		return -ERESTARTSYS;
-	}
-	spin_unlock_irq(&tty->ctrl_lock);
-	rcu_read_unlock();
-	return 0;
+	return __tty_check_change(tty, SIGTTIN);
 }
 
 
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 4d5937c..a45660f 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/module.h>
-
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
@@ -501,6 +500,10 @@
 }
 
 static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
+/*
+ * not really modular, but the easiest way to keep compat with existing
+ * bootargs behaviour is to continue using module_param here.
+ */
 module_param(legacy_count, int, 0);
 
 /*
@@ -877,4 +880,4 @@
 	unix98_pty_init();
 	return 0;
 }
-module_init(pty_init);
+device_initcall(pty_init);
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index c8dd8dc..802eac7 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -895,14 +895,6 @@
 	if (!page)
 		return -ENOMEM;
 
-	if (port->flags & ASYNC_CLOSING) {
-		retval = wait_for_completion_interruptible(&info->close_wait);
-		free_page(page);
-		if (retval)
-			return retval;
-		return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
-	}
-
 	/*
 	 * We must not sleep from here until the port is marked fully in use.
 	 */
@@ -1057,7 +1049,6 @@
 	mutex_unlock(&port->mutex);
 	tty_port_tty_set(port, NULL);
 
-	wake_up_interruptible(&port->close_wait);
 	complete_all(&info->close_wait);
 	atomic_dec(&rp_num_ports_open);
 
@@ -1511,10 +1502,6 @@
 #endif
 	rp_flush_buffer(tty);
 	spin_lock_irqsave(&info->port.lock, flags);
-	if (info->port.flags & ASYNC_CLOSING) {
-		spin_unlock_irqrestore(&info->port.lock, flags);
-		return;
-	}
 	if (info->port.count)
 		atomic_dec(&rp_num_ports_open);
 	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index 748c18f..0140ba4 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -560,8 +560,8 @@
 	struct m68k_serial *info = &m68k_soft[0];
 	char c;
 
-	if (info == 0) return;
-	if (info->xmit_buf == 0) return;
+	if (info == NULL) return;
+	if (info->xmit_buf == NULL) return;
 
 	local_irq_save(flags);
 	left = info->xmit_cnt;
@@ -1071,7 +1071,6 @@
 		wake_up_interruptible(&port->open_wait);
 	}
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&port->close_wait);
 	local_irq_restore(flags);
 }
 
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 271d121..3912646 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -569,6 +569,9 @@
 	for (i = 0; i < nr_uarts; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 
+		if (up->port.type == PORT_8250_CIR)
+			continue;
+
 		if (up->port.dev)
 			continue;
 
@@ -1027,13 +1030,24 @@
 		if (up->dl_write)
 			uart->dl_write = up->dl_write;
 
-		if (serial8250_isa_config != NULL)
-			serial8250_isa_config(0, &uart->port,
-					&uart->capabilities);
+		if (uart->port.type != PORT_8250_CIR) {
+			if (serial8250_isa_config != NULL)
+				serial8250_isa_config(0, &uart->port,
+						&uart->capabilities);
 
-		ret = uart_add_one_port(&serial8250_reg, &uart->port);
-		if (ret == 0)
-			ret = uart->port.line;
+			ret = uart_add_one_port(&serial8250_reg,
+						&uart->port);
+			if (ret == 0)
+				ret = uart->port.line;
+		} else {
+			dev_info(uart->port.dev,
+				"skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n",
+				uart->port.iobase,
+				(unsigned long long)uart->port.mapbase,
+				uart->port.irq);
+
+			ret = 0;
+		}
 	}
 	mutex_unlock(&serial_mutex);
 
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index e508939..78259d3 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -54,9 +54,6 @@
 	struct dma_tx_state	state;
 	int			count;
 
-	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
-				dma->rx_size, DMA_FROM_DEVICE);
-
 	dma->rx_running = 0;
 	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
 
@@ -152,9 +149,6 @@
 
 	dma->rx_cookie = dmaengine_submit(desc);
 
-	dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
-				   dma->rx_size, DMA_FROM_DEVICE);
-
 	dma_async_issue_pending(dma->rxchan);
 
 	return 0;
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 06324f1..a0cdbf3 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -63,6 +63,9 @@
 	struct clk		*pclk;
 	struct reset_control	*rst;
 	struct uart_8250_dma	dma;
+
+	unsigned int		skip_autocfg:1;
+	unsigned int		uart_16550_compatible:1;
 };
 
 #define BYT_PRV_CLK			0x800
@@ -244,24 +247,77 @@
 	serial8250_do_set_termios(p, termios, old);
 }
 
-static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
+/*
+ * dw8250_fallback_dma_filter will prevent the UART from getting just any free
+ * channel on platforms that have DMA engines, but don't have any channels
+ * assigned to the UART.
+ *
+ * REVISIT: This is a work around for limitation in the DMA Engine API. Once the
+ * core problem is fixed, this function is no longer needed.
+ */
+static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param)
 {
 	return false;
 }
 
-static void dw8250_setup_port(struct uart_8250_port *up)
+static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
 {
-	struct uart_port	*p = &up->port;
-	u32			reg = readl(p->membase + DW_UART_UCV);
+	return param == chan->device->dev->parent;
+}
+
+static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
+{
+	if (p->dev->of_node) {
+		struct device_node *np = p->dev->of_node;
+		int id;
+
+		/* get index of serial line, if found in DT aliases */
+		id = of_alias_get_id(np, "serial");
+		if (id >= 0)
+			p->line = id;
+#ifdef CONFIG_64BIT
+		if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
+			p->serial_in = dw8250_serial_inq;
+			p->serial_out = dw8250_serial_outq;
+			p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+			p->type = PORT_OCTEON;
+			data->usr_reg = 0x27;
+			data->skip_autocfg = true;
+		}
+#endif
+	} else if (has_acpi_companion(p->dev)) {
+		p->iotype = UPIO_MEM32;
+		p->regshift = 2;
+		p->serial_in = dw8250_serial_in32;
+		p->set_termios = dw8250_set_termios;
+		/* So far none of there implement the Busy Functionality */
+		data->uart_16550_compatible = true;
+	}
+
+	/* Platforms with iDMA */
+	if (platform_get_resource_byname(to_platform_device(p->dev),
+					 IORESOURCE_MEM, "lpss_priv")) {
+		p->set_termios = dw8250_set_termios;
+		data->dma.rx_param = p->dev->parent;
+		data->dma.tx_param = p->dev->parent;
+		data->dma.fn = dw8250_idma_filter;
+	}
+}
+
+static void dw8250_setup_port(struct uart_port *p)
+{
+	struct uart_8250_port *up = up_to_u8250p(p);
+	u32 reg;
 
 	/*
 	 * If the Component Version Register returns zero, we know that
 	 * ADDITIONAL_FEATURES are not enabled. No need to go any further.
 	 */
+	reg = readl(p->membase + DW_UART_UCV);
 	if (!reg)
 		return;
 
-	dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
+	dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
 		(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
 
 	reg = readl(p->membase + DW_UART_CPR);
@@ -273,7 +329,6 @@
 		p->type = PORT_16550A;
 		p->flags |= UPF_FIXED_TYPE;
 		p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
-		up->tx_loadsz = p->fifosize;
 		up->capabilities = UART_CAP_FIFO;
 	}
 
@@ -281,131 +336,15 @@
 		up->capabilities |= UART_CAP_AFE;
 }
 
-static int dw8250_probe_of(struct uart_port *p,
-			   struct dw8250_data *data)
-{
-	struct device_node	*np = p->dev->of_node;
-	struct uart_8250_port *up = up_to_u8250p(p);
-	u32			val;
-	bool has_ucv = true;
-	int id;
-
-#ifdef CONFIG_64BIT
-	if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
-		p->serial_in = dw8250_serial_inq;
-		p->serial_out = dw8250_serial_outq;
-		p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
-		p->type = PORT_OCTEON;
-		data->usr_reg = 0x27;
-		has_ucv = false;
-	} else
-#endif
-	if (!of_property_read_u32(np, "reg-io-width", &val)) {
-		switch (val) {
-		case 1:
-			break;
-		case 4:
-			p->iotype = UPIO_MEM32;
-			p->serial_in = dw8250_serial_in32;
-			p->serial_out = dw8250_serial_out32;
-			break;
-		default:
-			dev_err(p->dev, "unsupported reg-io-width (%u)\n", val);
-			return -EINVAL;
-		}
-	}
-	if (has_ucv)
-		dw8250_setup_port(up);
-
-	/* if we have a valid fifosize, try hooking up DMA here */
-	if (p->fifosize) {
-		up->dma = &data->dma;
-
-		up->dma->rxconf.src_maxburst = p->fifosize / 4;
-		up->dma->txconf.dst_maxburst = p->fifosize / 4;
-	}
-
-	if (!of_property_read_u32(np, "reg-shift", &val))
-		p->regshift = val;
-
-	/* get index of serial line, if found in DT aliases */
-	id = of_alias_get_id(np, "serial");
-	if (id >= 0)
-		p->line = id;
-
-	if (of_property_read_bool(np, "dcd-override")) {
-		/* Always report DCD as active */
-		data->msr_mask_on |= UART_MSR_DCD;
-		data->msr_mask_off |= UART_MSR_DDCD;
-	}
-
-	if (of_property_read_bool(np, "dsr-override")) {
-		/* Always report DSR as active */
-		data->msr_mask_on |= UART_MSR_DSR;
-		data->msr_mask_off |= UART_MSR_DDSR;
-	}
-
-	if (of_property_read_bool(np, "cts-override")) {
-		/* Always report CTS as active */
-		data->msr_mask_on |= UART_MSR_CTS;
-		data->msr_mask_off |= UART_MSR_DCTS;
-	}
-
-	if (of_property_read_bool(np, "ri-override")) {
-		/* Always report Ring indicator as inactive */
-		data->msr_mask_off |= UART_MSR_RI;
-		data->msr_mask_off |= UART_MSR_TERI;
-	}
-
-	return 0;
-}
-
-static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
-{
-	struct device *dev = param;
-
-	if (dev != chan->device->dev->parent)
-		return false;
-
-	return true;
-}
-
-static int dw8250_probe_acpi(struct uart_8250_port *up,
-			     struct dw8250_data *data)
-{
-	struct uart_port *p = &up->port;
-
-	dw8250_setup_port(up);
-
-	p->iotype = UPIO_MEM32;
-	p->serial_in = dw8250_serial_in32;
-	p->serial_out = dw8250_serial_out32;
-	p->regshift = 2;
-
-	/* Platforms with iDMA */
-	if (platform_get_resource_byname(to_platform_device(up->port.dev),
-					 IORESOURCE_MEM, "lpss_priv")) {
-		data->dma.rx_param = up->port.dev->parent;
-		data->dma.tx_param = up->port.dev->parent;
-		data->dma.fn = dw8250_idma_filter;
-	}
-
-	up->dma = &data->dma;
-	up->dma->rxconf.src_maxburst = p->fifosize / 4;
-	up->dma->txconf.dst_maxburst = p->fifosize / 4;
-
-	up->port.set_termios = dw8250_set_termios;
-
-	return 0;
-}
-
 static int dw8250_probe(struct platform_device *pdev)
 {
 	struct uart_8250_port uart = {};
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	int irq = platform_get_irq(pdev, 0);
+	struct uart_port *p = &uart.port;
 	struct dw8250_data *data;
 	int err;
+	u32 val;
 
 	if (!regs) {
 		dev_err(&pdev->dev, "no registers defined\n");
@@ -418,29 +357,70 @@
 		return irq;
 	}
 
-	spin_lock_init(&uart.port.lock);
-	uart.port.mapbase = regs->start;
-	uart.port.irq = irq;
-	uart.port.handle_irq = dw8250_handle_irq;
-	uart.port.pm = dw8250_do_pm;
-	uart.port.type = PORT_8250;
-	uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
-	uart.port.dev = &pdev->dev;
+	spin_lock_init(&p->lock);
+	p->mapbase	= regs->start;
+	p->irq		= irq;
+	p->handle_irq	= dw8250_handle_irq;
+	p->pm		= dw8250_do_pm;
+	p->type		= PORT_8250;
+	p->flags	= UPF_SHARE_IRQ | UPF_FIXED_PORT;
+	p->dev		= &pdev->dev;
+	p->iotype	= UPIO_MEM;
+	p->serial_in	= dw8250_serial_in;
+	p->serial_out	= dw8250_serial_out;
 
-	uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
-					 resource_size(regs));
-	if (!uart.port.membase)
+	p->membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+	if (!p->membase)
 		return -ENOMEM;
 
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
+	data->dma.fn = dw8250_fallback_dma_filter;
 	data->usr_reg = DW_UART_USR;
+	p->private_data = data;
+
+	data->uart_16550_compatible = device_property_read_bool(p->dev,
+						"snps,uart-16550-compatible");
+
+	err = device_property_read_u32(p->dev, "reg-shift", &val);
+	if (!err)
+		p->regshift = val;
+
+	err = device_property_read_u32(p->dev, "reg-io-width", &val);
+	if (!err && val == 4) {
+		p->iotype = UPIO_MEM32;
+		p->serial_in = dw8250_serial_in32;
+		p->serial_out = dw8250_serial_out32;
+	}
+
+	if (device_property_read_bool(p->dev, "dcd-override")) {
+		/* Always report DCD as active */
+		data->msr_mask_on |= UART_MSR_DCD;
+		data->msr_mask_off |= UART_MSR_DDCD;
+	}
+
+	if (device_property_read_bool(p->dev, "dsr-override")) {
+		/* Always report DSR as active */
+		data->msr_mask_on |= UART_MSR_DSR;
+		data->msr_mask_off |= UART_MSR_DDSR;
+	}
+
+	if (device_property_read_bool(p->dev, "cts-override")) {
+		/* Always report CTS as active */
+		data->msr_mask_on |= UART_MSR_CTS;
+		data->msr_mask_off |= UART_MSR_DCTS;
+	}
+
+	if (device_property_read_bool(p->dev, "ri-override")) {
+		/* Always report Ring indicator as inactive */
+		data->msr_mask_off |= UART_MSR_RI;
+		data->msr_mask_off |= UART_MSR_TERI;
+	}
 
 	/* Always ask for fixed clock rate from a property. */
-	device_property_read_u32(&pdev->dev, "clock-frequency",
-				 &uart.port.uartclk);
+	device_property_read_u32(p->dev, "clock-frequency", &p->uartclk);
 
 	/* If there is separate baudclk, get the rate from it. */
 	data->clk = devm_clk_get(&pdev->dev, "baudclk");
@@ -454,11 +434,11 @@
 			dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
 				 err);
 		else
-			uart.port.uartclk = clk_get_rate(data->clk);
+			p->uartclk = clk_get_rate(data->clk);
 	}
 
 	/* If no clock rate is defined, fail. */
-	if (!uart.port.uartclk) {
+	if (!p->uartclk) {
 		dev_err(&pdev->dev, "clock rate not defined\n");
 		return -EINVAL;
 	}
@@ -484,26 +464,22 @@
 	if (!IS_ERR(data->rst))
 		reset_control_deassert(data->rst);
 
-	data->dma.rx_param = data;
-	data->dma.tx_param = data;
-	data->dma.fn = dw8250_dma_filter;
+	dw8250_quirks(p, data);
 
-	uart.port.iotype = UPIO_MEM;
-	uart.port.serial_in = dw8250_serial_in;
-	uart.port.serial_out = dw8250_serial_out;
-	uart.port.private_data = data;
+	/* If the Busy Functionality is not implemented, don't handle it */
+	if (data->uart_16550_compatible) {
+		p->serial_out = NULL;
+		p->handle_irq = NULL;
+	}
 
-	if (pdev->dev.of_node) {
-		err = dw8250_probe_of(&uart.port, data);
-		if (err)
-			goto err_reset;
-	} else if (ACPI_HANDLE(&pdev->dev)) {
-		err = dw8250_probe_acpi(&uart, data);
-		if (err)
-			goto err_reset;
-	} else {
-		err = -ENODEV;
-		goto err_reset;
+	if (!data->skip_autocfg)
+		dw8250_setup_port(p);
+
+	/* If we have a valid fifosize, try hooking up DMA */
+	if (p->fifosize) {
+		data->dma.rxconf.src_maxburst = p->fifosize / 4;
+		data->dma.txconf.dst_maxburst = p->fifosize / 4;
+		uart.dma = &data->dma;
 	}
 
 	data->line = serial8250_register_8250_port(&uart);
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index faed05f..ceb8579 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -29,6 +29,8 @@
 #include <linux/tty.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
@@ -152,3 +154,5 @@
 }
 EARLYCON_DECLARE(uart8250, early_serial8250_setup);
 EARLYCON_DECLARE(uart, early_serial8250_setup);
+OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup);
+OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index 7c1e4be..49394b4 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -21,19 +21,33 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 
+#include "8250.h"
+
+/** ingenic_uart_config: SOC specific config data. */
+struct ingenic_uart_config {
+	int tx_loadsz;
+	int fifosize;
+};
+
 struct ingenic_uart_data {
 	struct clk	*clk_module;
 	struct clk	*clk_baud;
 	int		line;
 };
 
+static const struct of_device_id of_match[];
+
 #define UART_FCR_UME	BIT(4)
 
+#define UART_MCR_MDCE	BIT(7)
+#define UART_MCR_FCM	BIT(6)
+
 static struct earlycon_device *early_device;
 
 static uint8_t __init early_in(struct uart_port *port, int offset)
@@ -129,6 +143,8 @@
 
 static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
 {
+	int ier;
+
 	switch (offset) {
 	case UART_FCR:
 		/* UART module enable */
@@ -136,9 +152,22 @@
 		break;
 
 	case UART_IER:
+		/* Enable receive timeout interrupt with the
+		 * receive line status interrupt */
 		value |= (value & 0x4) << 2;
 		break;
 
+	case UART_MCR:
+		/* If we have enabled modem status IRQs we should enable modem
+		 * mode. */
+		ier = p->serial_in(p, UART_IER);
+
+		if (ier & UART_IER_MSI)
+			value |= UART_MCR_MDCE | UART_MCR_FCM;
+		else
+			value &= ~(UART_MCR_MDCE | UART_MCR_FCM);
+		break;
+
 	default:
 		break;
 	}
@@ -146,14 +175,45 @@
 	writeb(value, p->membase + (offset << p->regshift));
 }
 
+static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int value;
+
+	value = readb(p->membase + (offset << p->regshift));
+
+	/* Hide non-16550 compliant bits from higher levels */
+	switch (offset) {
+	case UART_FCR:
+		value &= ~UART_FCR_UME;
+		break;
+
+	case UART_MCR:
+		value &= ~(UART_MCR_MDCE | UART_MCR_FCM);
+		break;
+
+	default:
+		break;
+	}
+	return value;
+}
+
 static int ingenic_uart_probe(struct platform_device *pdev)
 {
 	struct uart_8250_port uart = {};
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	struct ingenic_uart_data *data;
+	const struct ingenic_uart_config *cdata;
+	const struct of_device_id *match;
 	int err, line;
 
+	match = of_match_device(of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		return -ENODEV;
+	}
+	cdata = match->data;
+
 	if (!regs || !irq) {
 		dev_err(&pdev->dev, "no registers/irq defined\n");
 		return -EINVAL;
@@ -164,14 +224,18 @@
 		return -ENOMEM;
 
 	spin_lock_init(&uart.port.lock);
-	uart.port.type = PORT_16550;
+	uart.port.type = PORT_16550A;
 	uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
 	uart.port.iotype = UPIO_MEM;
 	uart.port.mapbase = regs->start;
 	uart.port.regshift = 2;
 	uart.port.serial_out = ingenic_uart_serial_out;
+	uart.port.serial_in = ingenic_uart_serial_in;
 	uart.port.irq = irq->start;
 	uart.port.dev = &pdev->dev;
+	uart.port.fifosize = cdata->fifosize;
+	uart.tx_loadsz = cdata->tx_loadsz;
+	uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE;
 
 	/* Check for a fixed line number */
 	line = of_alias_get_id(pdev->dev.of_node, "serial");
@@ -241,10 +305,26 @@
 	return 0;
 }
 
+static const struct ingenic_uart_config jz4740_uart_config = {
+	.tx_loadsz = 8,
+	.fifosize = 16,
+};
+
+static const struct ingenic_uart_config jz4760_uart_config = {
+	.tx_loadsz = 16,
+	.fifosize = 32,
+};
+
+static const struct ingenic_uart_config jz4780_uart_config = {
+	.tx_loadsz = 32,
+	.fifosize = 64,
+};
+
 static const struct of_device_id of_match[] = {
-	{ .compatible = "ingenic,jz4740-uart" },
-	{ .compatible = "ingenic,jz4775-uart" },
-	{ .compatible = "ingenic,jz4780-uart" },
+	{ .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config },
+	{ .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config },
+	{ .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config },
+	{ .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, of_match);
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
new file mode 100644
index 0000000..88531a3
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -0,0 +1,326 @@
+/*
+ * 8250_mid.c - Driver for UART on Intel Penwell and various other Intel SOCs
+ *
+ * Copyright (C) 2015 Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/rational.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <linux/dma/hsu.h>
+
+#include "8250.h"
+
+#define PCI_DEVICE_ID_INTEL_PNW_UART1	0x081b
+#define PCI_DEVICE_ID_INTEL_PNW_UART2	0x081c
+#define PCI_DEVICE_ID_INTEL_PNW_UART3	0x081d
+#define PCI_DEVICE_ID_INTEL_TNG_UART	0x1191
+#define PCI_DEVICE_ID_INTEL_DNV_UART	0x19d8
+
+/* Intel MID Specific registers */
+#define INTEL_MID_UART_PS		0x30
+#define INTEL_MID_UART_MUL		0x34
+#define INTEL_MID_UART_DIV		0x38
+
+struct mid8250;
+
+struct mid8250_board {
+	unsigned long freq;
+	unsigned int base_baud;
+	int (*setup)(struct mid8250 *, struct uart_port *p);
+	void (*exit)(struct mid8250 *);
+};
+
+struct mid8250 {
+	int line;
+	int dma_index;
+	struct pci_dev *dma_dev;
+	struct uart_8250_dma dma;
+	struct mid8250_board *board;
+	struct hsu_dma_chip dma_chip;
+};
+
+/*****************************************************************************/
+
+static int pnw_setup(struct mid8250 *mid, struct uart_port *p)
+{
+	struct pci_dev *pdev = to_pci_dev(p->dev);
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_PNW_UART1:
+		mid->dma_index = 0;
+		break;
+	case PCI_DEVICE_ID_INTEL_PNW_UART2:
+		mid->dma_index = 1;
+		break;
+	case PCI_DEVICE_ID_INTEL_PNW_UART3:
+		mid->dma_index = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mid->dma_dev = pci_get_slot(pdev->bus,
+				    PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
+	return 0;
+}
+
+static int tng_setup(struct mid8250 *mid, struct uart_port *p)
+{
+	struct pci_dev *pdev = to_pci_dev(p->dev);
+	int index = PCI_FUNC(pdev->devfn);
+
+	/* Currently no support for HSU port0 */
+	if (index-- == 0)
+		return -ENODEV;
+
+	mid->dma_index = index;
+	mid->dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
+	return 0;
+}
+
+static int dnv_handle_irq(struct uart_port *p)
+{
+	struct mid8250 *mid = p->private_data;
+	int ret;
+
+	ret = hsu_dma_irq(&mid->dma_chip, 0);
+	ret |= hsu_dma_irq(&mid->dma_chip, 1);
+
+	/* For now, letting the HW generate separate interrupt for the UART */
+	if (ret)
+		return ret;
+
+	return serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+}
+
+#define DNV_DMA_CHAN_OFFSET 0x80
+
+static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
+{
+	struct hsu_dma_chip *chip = &mid->dma_chip;
+	struct pci_dev *pdev = to_pci_dev(p->dev);
+	int ret;
+
+	chip->dev = &pdev->dev;
+	chip->irq = pdev->irq;
+	chip->regs = p->membase;
+	chip->length = pci_resource_len(pdev, 0);
+	chip->offset = DNV_DMA_CHAN_OFFSET;
+
+	/* Falling back to PIO mode if DMA probing fails */
+	ret = hsu_dma_probe(chip);
+	if (ret)
+		return 0;
+
+	mid->dma_dev = pdev;
+
+	p->handle_irq = dnv_handle_irq;
+	return 0;
+}
+
+static void dnv_exit(struct mid8250 *mid)
+{
+	if (!mid->dma_dev)
+		return;
+	hsu_dma_remove(&mid->dma_chip);
+}
+
+/*****************************************************************************/
+
+static void mid8250_set_termios(struct uart_port *p,
+				struct ktermios *termios,
+				struct ktermios *old)
+{
+	unsigned int baud = tty_termios_baud_rate(termios);
+	struct mid8250 *mid = p->private_data;
+	unsigned short ps = 16;
+	unsigned long fuart = baud * ps;
+	unsigned long w = BIT(24) - 1;
+	unsigned long mul, div;
+
+	if (mid->board->freq < fuart) {
+		/* Find prescaler value that satisfies Fuart < Fref */
+		if (mid->board->freq > baud)
+			ps = mid->board->freq / baud;	/* baud rate too high */
+		else
+			ps = 1;				/* PLL case */
+		fuart = baud * ps;
+	} else {
+		/* Get Fuart closer to Fref */
+		fuart *= rounddown_pow_of_two(mid->board->freq / fuart);
+	}
+
+	rational_best_approximation(fuart, mid->board->freq, w, w, &mul, &div);
+	p->uartclk = fuart * 16 / ps;		/* core uses ps = 16 always */
+
+	writel(ps, p->membase + INTEL_MID_UART_PS);		/* set PS */
+	writel(mul, p->membase + INTEL_MID_UART_MUL);		/* set MUL */
+	writel(div, p->membase + INTEL_MID_UART_DIV);
+
+	serial8250_do_set_termios(p, termios, old);
+}
+
+static bool mid8250_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct hsu_dma_slave *s = param;
+
+	if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
+		return false;
+
+	chan->private = s;
+	return true;
+}
+
+static int mid8250_dma_setup(struct mid8250 *mid, struct uart_8250_port *port)
+{
+	struct uart_8250_dma *dma = &mid->dma;
+	struct device *dev = port->port.dev;
+	struct hsu_dma_slave *rx_param;
+	struct hsu_dma_slave *tx_param;
+
+	if (!mid->dma_dev)
+		return 0;
+
+	rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
+	if (!rx_param)
+		return -ENOMEM;
+
+	tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
+	if (!tx_param)
+		return -ENOMEM;
+
+	rx_param->chan_id = mid->dma_index * 2 + 1;
+	tx_param->chan_id = mid->dma_index * 2;
+
+	dma->rxconf.src_maxburst = 64;
+	dma->txconf.dst_maxburst = 64;
+
+	rx_param->dma_dev = &mid->dma_dev->dev;
+	tx_param->dma_dev = &mid->dma_dev->dev;
+
+	dma->fn = mid8250_dma_filter;
+	dma->rx_param = rx_param;
+	dma->tx_param = tx_param;
+
+	port->dma = dma;
+	return 0;
+}
+
+static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct uart_8250_port uart;
+	struct mid8250 *mid;
+	int ret;
+
+	ret = pcim_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	pci_set_master(pdev);
+
+	mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL);
+	if (!mid)
+		return -ENOMEM;
+
+	mid->board = (struct mid8250_board *)id->driver_data;
+
+	memset(&uart, 0, sizeof(struct uart_8250_port));
+
+	uart.port.dev = &pdev->dev;
+	uart.port.irq = pdev->irq;
+	uart.port.private_data = mid;
+	uart.port.type = PORT_16750;
+	uart.port.iotype = UPIO_MEM;
+	uart.port.uartclk = mid->board->base_baud * 16;
+	uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
+	uart.port.set_termios = mid8250_set_termios;
+
+	uart.port.mapbase = pci_resource_start(pdev, 0);
+	uart.port.membase = pcim_iomap(pdev, 0, 0);
+	if (!uart.port.membase)
+		return -ENOMEM;
+
+	if (mid->board->setup) {
+		ret = mid->board->setup(mid, &uart.port);
+		if (ret)
+			return ret;
+	}
+
+	ret = mid8250_dma_setup(mid, &uart);
+	if (ret)
+		goto err;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0)
+		goto err;
+
+	mid->line = ret;
+
+	pci_set_drvdata(pdev, mid);
+	return 0;
+err:
+	if (mid->board->exit)
+		mid->board->exit(mid);
+	return ret;
+}
+
+static void mid8250_remove(struct pci_dev *pdev)
+{
+	struct mid8250 *mid = pci_get_drvdata(pdev);
+
+	if (mid->board->exit)
+		mid->board->exit(mid);
+
+	serial8250_unregister_port(mid->line);
+}
+
+static const struct mid8250_board pnw_board = {
+	.freq = 50000000,
+	.base_baud = 115200,
+	.setup = pnw_setup,
+};
+
+static const struct mid8250_board tng_board = {
+	.freq = 38400000,
+	.base_baud = 1843200,
+	.setup = tng_setup,
+};
+
+static const struct mid8250_board dnv_board = {
+	.freq = 133333333,
+	.base_baud = 115200,
+	.setup = dnv_setup,
+	.exit = dnv_exit,
+};
+
+#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
+
+static const struct pci_device_id pci_ids[] = {
+	MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART1, pnw_board),
+	MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board),
+	MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board),
+	MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board),
+	MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board),
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver mid8250_pci_driver = {
+	.name           = "8250_mid",
+	.id_table       = pci_ids,
+	.probe          = mid8250_probe,
+	.remove         = mid8250_remove,
+};
+
+module_pci_driver(mid8250_pci_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel MID UART driver");
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 826c5c4..a2c0734 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -439,7 +439,6 @@
 	priv->xoff = termios->c_cc[VSTOP];
 
 	priv->efr = 0;
-	up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY);
 	up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
 
 	if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
@@ -726,6 +725,7 @@
 	struct dma_tx_state     state;
 	int                     count;
 	unsigned long		flags;
+	int			ret;
 
 	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
 				dma->rx_size, DMA_FROM_DEVICE);
@@ -741,8 +741,10 @@
 
 	count = dma->rx_size - state.residue;
 
-	tty_insert_flip_string(tty_port, dma->rx_buf, count);
-	p->port.icount.rx += count;
+	ret = tty_insert_flip_string(tty_port, dma->rx_buf, count);
+
+	p->port.icount.rx += ret;
+	p->port.icount.buf_overrun += count - ret;
 unlock:
 	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
 
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 68042dd..4097f3f6 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -28,7 +28,6 @@
 
 #include <linux/dmaengine.h>
 #include <linux/platform_data/dma-dw.h>
-#include <linux/platform_data/dma-hsu.h>
 
 #include "8250.h"
 
@@ -1508,167 +1507,6 @@
 	return ret;
 }
 
-#define INTEL_MID_UART_PS		0x30
-#define INTEL_MID_UART_MUL		0x34
-#define INTEL_MID_UART_DIV		0x38
-
-static void intel_mid_set_termios(struct uart_port *p,
-				  struct ktermios *termios,
-				  struct ktermios *old,
-				  unsigned long fref)
-{
-	unsigned int baud = tty_termios_baud_rate(termios);
-	unsigned short ps = 16;
-	unsigned long fuart = baud * ps;
-	unsigned long w = BIT(24) - 1;
-	unsigned long mul, div;
-
-	if (fref < fuart) {
-		/* Find prescaler value that satisfies Fuart < Fref */
-		if (fref > baud)
-			ps = fref / baud;	/* baud rate too high */
-		else
-			ps = 1;			/* PLL case */
-		fuart = baud * ps;
-	} else {
-		/* Get Fuart closer to Fref */
-		fuart *= rounddown_pow_of_two(fref / fuart);
-	}
-
-	rational_best_approximation(fuart, fref, w, w, &mul, &div);
-	p->uartclk = fuart * 16 / ps;		/* core uses ps = 16 always */
-
-	writel(ps, p->membase + INTEL_MID_UART_PS);		/* set PS */
-	writel(mul, p->membase + INTEL_MID_UART_MUL);		/* set MUL */
-	writel(div, p->membase + INTEL_MID_UART_DIV);
-
-	serial8250_do_set_termios(p, termios, old);
-}
-
-static void intel_mid_set_termios_38_4M(struct uart_port *p,
-					struct ktermios *termios,
-					struct ktermios *old)
-{
-	intel_mid_set_termios(p, termios, old, 38400000);
-}
-
-static void intel_mid_set_termios_50M(struct uart_port *p,
-				      struct ktermios *termios,
-				      struct ktermios *old)
-{
-	/*
-	 * The uart clk is 50Mhz, and the baud rate come from:
-	 *      baud = 50M * MUL / (DIV * PS * DLAB)
-	 */
-	intel_mid_set_termios(p, termios, old, 50000000);
-}
-
-static bool intel_mid_dma_filter(struct dma_chan *chan, void *param)
-{
-	struct hsu_dma_slave *s = param;
-
-	if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
-		return false;
-
-	chan->private = s;
-	return true;
-}
-
-static int intel_mid_serial_setup(struct serial_private *priv,
-				  const struct pciserial_board *board,
-				  struct uart_8250_port *port, int idx,
-				  int index, struct pci_dev *dma_dev)
-{
-	struct device *dev = port->port.dev;
-	struct uart_8250_dma *dma;
-	struct hsu_dma_slave *tx_param, *rx_param;
-
-	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
-	if (!dma)
-		return -ENOMEM;
-
-	tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
-	if (!tx_param)
-		return -ENOMEM;
-
-	rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
-	if (!rx_param)
-		return -ENOMEM;
-
-	rx_param->chan_id = index * 2 + 1;
-	tx_param->chan_id = index * 2;
-
-	dma->rxconf.src_maxburst = 64;
-	dma->txconf.dst_maxburst = 64;
-
-	rx_param->dma_dev = &dma_dev->dev;
-	tx_param->dma_dev = &dma_dev->dev;
-
-	dma->fn = intel_mid_dma_filter;
-	dma->rx_param = rx_param;
-	dma->tx_param = tx_param;
-
-	port->port.type = PORT_16750;
-	port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
-	port->dma = dma;
-
-	return pci_default_setup(priv, board, port, idx);
-}
-
-#define PCI_DEVICE_ID_INTEL_PNW_UART1	0x081b
-#define PCI_DEVICE_ID_INTEL_PNW_UART2	0x081c
-#define PCI_DEVICE_ID_INTEL_PNW_UART3	0x081d
-
-static int pnw_serial_setup(struct serial_private *priv,
-			    const struct pciserial_board *board,
-			    struct uart_8250_port *port, int idx)
-{
-	struct pci_dev *pdev = priv->dev;
-	struct pci_dev *dma_dev;
-	int index;
-
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_INTEL_PNW_UART1:
-		index = 0;
-		break;
-	case PCI_DEVICE_ID_INTEL_PNW_UART2:
-		index = 1;
-		break;
-	case PCI_DEVICE_ID_INTEL_PNW_UART3:
-		index = 2;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
-
-	port->port.set_termios = intel_mid_set_termios_50M;
-
-	return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
-}
-
-#define PCI_DEVICE_ID_INTEL_TNG_UART	0x1191
-
-static int tng_serial_setup(struct serial_private *priv,
-			    const struct pciserial_board *board,
-			    struct uart_8250_port *port, int idx)
-{
-	struct pci_dev *pdev = priv->dev;
-	struct pci_dev *dma_dev;
-	int index = PCI_FUNC(pdev->devfn);
-
-	/* Currently no support for HSU port0 */
-	if (index-- == 0)
-		return -ENODEV;
-
-	dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
-
-	port->port.set_termios = intel_mid_set_termios_38_4M;
-
-	return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
-}
-
 static int
 pci_omegapci_setup(struct serial_private *priv,
 		      const struct pciserial_board *board,
@@ -2212,34 +2050,6 @@
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_PNW_UART1,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pnw_serial_setup,
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_PNW_UART2,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pnw_serial_setup,
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_PNW_UART3,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pnw_serial_setup,
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_TNG_UART,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= tng_serial_setup,
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_BSW_UART1,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
@@ -3119,8 +2929,6 @@
 	pbn_ADDIDATA_PCIe_8_3906250,
 	pbn_ce4100_1_115200,
 	pbn_byt,
-	pbn_pnw,
-	pbn_tng,
 	pbn_qrk,
 	pbn_omegapci,
 	pbn_NETMOS9900_2s_115200,
@@ -3907,16 +3715,6 @@
 		.uart_offset	= 0x80,
 		.reg_shift      = 2,
 	},
-	[pbn_pnw] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 1,
-		.base_baud	= 115200,
-	},
-	[pbn_tng] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 1,
-		.base_baud	= 1843200,
-	},
 	[pbn_qrk] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 1,
@@ -4005,6 +3803,13 @@
 	{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
 	{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
 	{ PCI_DEVICE(0x1c00, 0x3470), }, /* WCH CH384 4S */
+
+	/* Intel platforms with MID UART */
+	{ PCI_VDEVICE(INTEL, 0x081b), },
+	{ PCI_VDEVICE(INTEL, 0x081c), },
+	{ PCI_VDEVICE(INTEL, 0x081d), },
+	{ PCI_VDEVICE(INTEL, 0x1191), },
+	{ PCI_VDEVICE(INTEL, 0x19d8), },
 };
 
 /*
@@ -5702,26 +5507,6 @@
 		pbn_byt },
 
 	/*
-	 * Intel Penwell
-	 */
-	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_pnw},
-	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_pnw},
-	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_pnw},
-
-	/*
-	 * Intel Tangier
-	 */
-	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TNG_UART,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_tng},
-
-	/*
 	 * Intel Quark x1000
 	 */
 	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_UART,
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 0bbf340..52d82d2 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -284,7 +284,7 @@
 	serial_out(up, UART_DLM, value >> 8 & 0xff);
 }
 
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+#ifdef CONFIG_SERIAL_8250_RT288X
 
 /* Au1x00/RT288x UART hardware has a weird register layout */
 static const s8 au_io_in_map[8] = {
@@ -435,7 +435,7 @@
 		p->serial_out = mem32be_serial_out;
 		break;
 
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+#ifdef CONFIG_SERIAL_8250_RT288X
 	case UPIO_AU:
 		p->serial_in = au_serial_in;
 		p->serial_out = au_serial_out;
@@ -1246,6 +1246,9 @@
 		inb_p(ICP);
 	}
 
+	if (uart_console(port))
+		console_lock();
+
 	/* forget possible initially masked and pending IRQ */
 	probe_irq_off(probe_irq_on());
 	save_mcr = serial_in(up, UART_MCR);
@@ -1277,6 +1280,9 @@
 	if (port->flags & UPF_FOURPORT)
 		outb_p(save_ICP, ICP);
 
+	if (uart_console(port))
+		console_unlock();
+
 	port->irq = (irq > 0) ? irq : 0;
 }
 
@@ -1807,9 +1813,6 @@
 	unsigned char lsr, iir;
 	int retval;
 
-	if (port->type == PORT_8250_CIR)
-		return -ENODEV;
-
 	if (!port->fifosize)
 		port->fifosize = uart_config[port->type].fifo_size;
 	if (!up->tx_loadsz)
@@ -2230,6 +2233,23 @@
 		serial_port_out(port, 0x2, quot_frac);
 }
 
+static unsigned int
+serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+			 struct ktermios *old)
+{
+	unsigned int tolerance = port->uartclk / 100;
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 * Allow 1% tolerance at the upper limit so uart clks marginally
+	 * slower than nominal still match standard baud rates without
+	 * causing transmission errors.
+	 */
+	return uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  (port->uartclk + tolerance) / 16);
+}
+
 void
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 		          struct ktermios *old)
@@ -2241,12 +2261,7 @@
 
 	cval = serial8250_compute_lcr(up, termios->c_cflag);
 
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old,
-				  port->uartclk / 16 / 0xffff,
-				  port->uartclk / 16);
+	baud = serial8250_get_baud_rate(port, termios, old);
 	quot = serial8250_get_divisor(up, baud, &frac);
 
 	/*
@@ -2513,14 +2528,8 @@
 static int serial8250_request_port(struct uart_port *port)
 {
 	struct uart_8250_port *up = up_to_u8250p(port);
-	int ret;
 
-	if (port->type == PORT_8250_CIR)
-		return -ENODEV;
-
-	ret = serial8250_request_std_resource(up);
-
-	return ret;
+	return serial8250_request_std_resource(up);
 }
 
 static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
@@ -2668,9 +2677,6 @@
 	struct uart_8250_port *up = up_to_u8250p(port);
 	int ret;
 
-	if (port->type == PORT_8250_CIR)
-		return;
-
 	/*
 	 * Find the region that we can probe for.  This in turn
 	 * tells us whether we can probe for the type of port.
@@ -2805,6 +2811,27 @@
 }
 
 /*
+ *	Restore serial console when h/w power-off detected
+ */
+static void serial8250_console_restore(struct uart_8250_port *up)
+{
+	struct uart_port *port = &up->port;
+	struct ktermios termios;
+	unsigned int baud, quot, frac = 0;
+
+	termios.c_cflag = port->cons->cflag;
+	if (port->state->port.tty && termios.c_cflag == 0)
+		termios.c_cflag = port->state->port.tty->termios.c_cflag;
+
+	baud = serial8250_get_baud_rate(port, &termios, NULL);
+	quot = serial8250_get_divisor(up, baud, &frac);
+
+	serial8250_set_divisor(port, baud, quot, frac);
+	serial_port_out(port, UART_LCR, up->lcr);
+	serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
+}
+
+/*
  *	Print a string to the serial port trying not to disturb
  *	any possible real use of the port...
  *
@@ -2841,22 +2868,7 @@
 
 	/* check scratch reg to see if port powered off during system sleep */
 	if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
-		struct ktermios termios;
-		unsigned int baud, quot, frac = 0;
-
-		termios.c_cflag = port->cons->cflag;
-		if (port->state->port.tty && termios.c_cflag == 0)
-			termios.c_cflag = port->state->port.tty->termios.c_cflag;
-
-		baud = uart_get_baud_rate(port, &termios, NULL,
-					  port->uartclk / 16 / 0xffff,
-					  port->uartclk / 16);
-		quot = serial8250_get_divisor(up, baud, &frac);
-
-		serial8250_set_divisor(port, baud, quot, frac);
-		serial_port_out(port, UART_LCR, up->lcr);
-		serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
-
+		serial8250_console_restore(up);
 		up->canary = 0;
 	}
 
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index e1de118..e6f5e12 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -274,8 +274,8 @@
 
 config SERIAL_8250_FSL
 	bool
-	depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
-	default PPC
+	depends on SERIAL_8250_CONSOLE
+	default PPC || ARM || ARM64
 
 config SERIAL_8250_DW
 	tristate "Support for Synopsys DesignWare 8250 quirks"
@@ -294,11 +294,12 @@
 
 config SERIAL_8250_RT288X
 	bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support"
-	depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620)
+	depends on SERIAL_8250
+	default y if MIPS_ALCHEMY || SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
 	help
-	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
-	  serial port, say Y to this option. The driver can handle up to 2 serial
-	  ports. If unsure, say N.
+	  Selecting this option will add support for the alternate register
+	  layout used by Ralink RT288x/RT305x, Alchemy Au1xxx, and some others.
+	  If unsure, say N.
 
 config SERIAL_8250_OMAP
 	tristate "Support for OMAP internal UART (8250 based driver)"
@@ -337,7 +338,7 @@
 	  through the PNP driver. If unsure, say N.
 
 config SERIAL_8250_LPC18XX
-	bool "NXP LPC18xx/43xx serial port support"
+	tristate "NXP LPC18xx/43xx serial port support"
 	depends on SERIAL_8250 && OF && (ARCH_LPC18XX || COMPILE_TEST)
 	default ARCH_LPC18XX
 	help
@@ -366,3 +367,13 @@
 	help
 	  If you have a system using an Ingenic SoC and wish to make use of
 	  its UARTs, say Y to this option. If unsure, say N.
+
+config SERIAL_8250_MID
+	tristate "Support for serial ports on Intel MID platforms"
+	depends on SERIAL_8250 && PCI
+	select HSU_DMA if SERIAL_8250_DMA
+	select HSU_DMA_PCI if X86_INTEL_MID
+	help
+	  Selecting this option will enable handling of the extra features
+	  present on the UART found on Intel Medfield SOC and various other
+	  Intel platforms.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 39c6d22..e177f86 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -27,5 +27,6 @@
 obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
+obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 687b1ea..1aec440 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -115,9 +115,9 @@
 
 config SERIAL_ATMEL
 	bool "AT91 / AT32 on-chip serial port support"
-	depends on ARCH_AT91 || AVR32
+	depends on ARCH_AT91 || AVR32 || COMPILE_TEST
 	select SERIAL_CORE
-	select SERIAL_MCTRL_GPIO
+	select SERIAL_MCTRL_GPIO if GPIOLIB
 	help
 	  This enables the driver for the on-chip UARTs of the Atmel
 	  AT91 and AT32 processors.
@@ -571,7 +571,7 @@
 
 config SERIAL_IMX
 	tristate "IMX serial port support"
-	depends on ARCH_MXC
+	depends on ARCH_MXC || COMPILE_TEST
 	select SERIAL_CORE
 	select RATIONAL
 	help
@@ -582,6 +582,7 @@
 	bool "Console on IMX serial port"
 	depends on SERIAL_IMX=y
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON if OF
 	help
 	  If you have enabled the serial port on the Freescale IMX
 	  CPU you can make it the console by answering Y to this option.
@@ -743,7 +744,7 @@
 
 config SERIAL_SH_SCI_DMA
 	bool "DMA support"
-	depends on SERIAL_SH_SCI && SH_DMAE
+	depends on SERIAL_SH_SCI && DMA_ENGINE
 
 config SERIAL_PNX8XXX
 	bool "Enable PNX8XXX SoCs' UART Support"
@@ -1408,7 +1409,7 @@
 	  warnings and which allows logins in single user mode).
 
 config SERIAL_MXS_AUART
-	depends on ARCH_MXS
+	depends on ARCH_MXS || COMPILE_TEST
 	tristate "MXS AUART support"
 	select SERIAL_CORE
 	select SERIAL_MCTRL_GPIO if GPIOLIB
@@ -1538,6 +1539,7 @@
 	tristate "Freescale lpuart serial port support"
 	depends on HAS_DMA
 	select SERIAL_CORE
+	select SERIAL_EARLYCON
 	help
 	  Support for the on-chip lpuart on some Freescale SOCs.
 
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index fd87a6f..61b607f 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -508,29 +508,6 @@
 	.cons		= ALTERA_UART_CONSOLE,
 };
 
-#ifdef CONFIG_OF
-static int altera_uart_get_of_uartclk(struct platform_device *pdev,
-				      struct uart_port *port)
-{
-	int len;
-	const __be32 *clk;
-
-	clk = of_get_property(pdev->dev.of_node, "clock-frequency", &len);
-	if (!clk || len < sizeof(__be32))
-		return -ENODEV;
-
-	port->uartclk = be32_to_cpup(clk);
-
-	return 0;
-}
-#else
-static int altera_uart_get_of_uartclk(struct platform_device *pdev,
-				      struct uart_port *port)
-{
-	return -ENODEV;
-}
-#endif /* CONFIG_OF */
-
 static int altera_uart_probe(struct platform_device *pdev)
 {
 	struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
@@ -570,7 +547,8 @@
 	if (platp)
 		port->uartclk = platp->uartclk;
 	else {
-		ret = altera_uart_get_of_uartclk(pdev, port);
+		ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+					   &port->uartclk);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index fd27e98..899a771 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -191,8 +191,8 @@
  */
 static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 {
-	u16 status, ch;
-	unsigned int flag, max_count = 256;
+	u16 status;
+	unsigned int ch, flag, max_count = 256;
 	int fifotaken = 0;
 
 	while (max_count--) {
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index f3af317..75eb083 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -581,6 +581,7 @@
 	 },
 	{},
 };
+MODULE_DEVICE_TABLE(of, apbuart_match);
 
 static struct platform_driver grlib_apbuart_of_driver = {
 	.probe = apbuart_probe,
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 538ea03..9429455 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -112,6 +112,12 @@
 #define ATMEL_SERIAL_RINGSIZE 1024
 
 /*
+ * at91: 6 USARTs and one DBGU port (SAM9260)
+ * avr32: 4
+ */
+#define ATMEL_MAX_UART		7
+
+/*
  * We wrap our port structure around the generic uart_port.
  */
 struct atmel_uart_port {
@@ -921,7 +927,7 @@
 	sg_set_page(&atmel_port->sg_tx,
 			virt_to_page(port->state->xmit.buf),
 			UART_XMIT_SIZE,
-			(int)port->state->xmit.buf & ~PAGE_MASK);
+			(unsigned long)port->state->xmit.buf & ~PAGE_MASK);
 	nent = dma_map_sg(port->dev,
 				&atmel_port->sg_tx,
 				1,
@@ -931,10 +937,10 @@
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		goto chan_err;
 	} else {
-		dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+		dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
 			sg_dma_len(&atmel_port->sg_tx),
 			port->state->xmit.buf,
-			sg_dma_address(&atmel_port->sg_tx));
+			&sg_dma_address(&atmel_port->sg_tx));
 	}
 
 	/* Configure the slave DMA */
@@ -1103,7 +1109,7 @@
 	sg_set_page(&atmel_port->sg_rx,
 		    virt_to_page(ring->buf),
 		    sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
-		    (int)ring->buf & ~PAGE_MASK);
+		    (unsigned long)ring->buf & ~PAGE_MASK);
 	nent = dma_map_sg(port->dev,
 			  &atmel_port->sg_rx,
 			  1,
@@ -1113,10 +1119,10 @@
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		goto chan_err;
 	} else {
-		dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+		dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
 			sg_dma_len(&atmel_port->sg_rx),
 			ring->buf,
-			sg_dma_address(&atmel_port->sg_rx));
+			&sg_dma_address(&atmel_port->sg_rx));
 	}
 
 	/* Configure the slave DMA */
@@ -1676,15 +1682,15 @@
 	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 
 	if (np) {
+		struct serial_rs485 *rs485conf = &port->rs485;
 		u32 rs485_delay[2];
 		/* rs485 properties */
 		if (of_property_read_u32_array(np, "rs485-rts-delay",
 					rs485_delay, 2) == 0) {
-			struct serial_rs485 *rs485conf = &port->rs485;
-
 			rs485conf->delay_rts_before_send = rs485_delay[0];
 			rs485conf->delay_rts_after_send = rs485_delay[1];
 			rs485conf->flags = 0;
+		}
 
 		if (of_get_property(np, "rs485-rx-during-tx", NULL))
 			rs485conf->flags |= SER_RS485_RX_DURING_TX;
@@ -1692,7 +1698,6 @@
 		if (of_get_property(np, "linux,rs485-enabled-at-boot-time",
 								NULL))
 			rs485conf->flags |= SER_RS485_ENABLED;
-		}
 	} else {
 		port->rs485       = pdata->rs485;
 	}
@@ -2296,7 +2301,7 @@
 		ret = -EINVAL;
 	if (port->uartclk / 16 != ser->baud_base)
 		ret = -EINVAL;
-	if ((void *)port->mapbase != ser->iomem_base)
+	if (port->mapbase != (unsigned long)ser->iomem_base)
 		ret = -EINVAL;
 	if (port->iobase != ser->port)
 		ret = -EINVAL;
@@ -2686,7 +2691,7 @@
 	enum mctrl_gpio_idx i;
 	struct gpio_desc *gpiod;
 
-	p->gpios = mctrl_gpio_init(dev, 0);
+	p->gpios = mctrl_gpio_init_noauto(dev, 0);
 	if (IS_ERR(p->gpios))
 		return PTR_ERR(p->gpios);
 
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index d5d2dd7..b3a4e0c 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -500,7 +500,7 @@
 
 	platform_set_drvdata(pdev, s);
 
-	s->gpios = mctrl_gpio_init(&pdev->dev, 0);
+	s->gpios = mctrl_gpio_init_noauto(&pdev->dev, 0);
 	if (IS_ERR(s->gpios))
 	    return PTR_ERR(s->gpios);
 
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 08431ad..d3e3d42 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1450,6 +1450,7 @@
 	},
 	{}
 };
+MODULE_DEVICE_TABLE(of, cpm_uart_match);
 
 static struct platform_driver cpm_uart_driver = {
 	.driver = {
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 3e4470a..f13f2eb 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -3655,7 +3655,6 @@
 		wake_up_interruptible(&info->port.open_wait);
 	}
 	info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&info->port.close_wait);
 	local_irq_restore(flags);
 
 	/* port closed */
@@ -3759,23 +3758,6 @@
 	int		do_clocal = 0;
 
 	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (info->port.flags & ASYNC_CLOSING) {
-		wait_event_interruptible_tty(tty, info->port.close_wait,
-			!(info->port.flags & ASYNC_CLOSING));
-#ifdef SERIAL_DO_RESTART
-		if (info->port.flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
 	 * If non-blocking mode is set, or the port is not enabled,
 	 * then make the check up front and then exit.
 	 */
@@ -3825,7 +3807,7 @@
 #endif
 			break;
 		}
-		if (!(info->port.flags & ASYNC_CLOSING) && do_clocal)
+		if (do_clocal)
 			/* && (do_clocal || DCD_IS_ASSERTED) */
 			break;
 		if (signal_pending(current)) {
@@ -3895,20 +3877,6 @@
 	info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY);
 
 	/*
-	 * If the port is in the middle of closing, bail out now
-	 */
-	if (info->port.flags & ASYNC_CLOSING) {
-		wait_event_interruptible_tty(tty, info->port.close_wait,
-			!(info->port.flags & ASYNC_CLOSING));
-#ifdef SERIAL_DO_RESTART
-		return ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
 	 * If DMA is enabled try to allocate the irq's.
 	 */
 	if (info->port.count == 1) {
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 08ce76f..3d79003 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1746,6 +1746,45 @@
 	.data		= &lpuart_reg,
 };
 
+static void lpuart_early_write(struct console *con, const char *s, unsigned n)
+{
+	struct earlycon_device *dev = con->data;
+
+	uart_console_write(&dev->port, s, n, lpuart_console_putchar);
+}
+
+static void lpuart32_early_write(struct console *con, const char *s, unsigned n)
+{
+	struct earlycon_device *dev = con->data;
+
+	uart_console_write(&dev->port, s, n, lpuart32_console_putchar);
+}
+
+static int __init lpuart_early_console_setup(struct earlycon_device *device,
+					  const char *opt)
+{
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->con->write = lpuart_early_write;
+	return 0;
+}
+
+static int __init lpuart32_early_console_setup(struct earlycon_device *device,
+					  const char *opt)
+{
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->con->write = lpuart32_early_write;
+	return 0;
+}
+
+OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
+EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
+EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
+
 #define LPUART_CONSOLE	(&lpuart_console)
 #define LPUART32_CONSOLE	(&lpuart32_console)
 #else
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index d0388a0..016e4be 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -139,6 +139,7 @@
 #define USR1_ESCF	(1<<11) /* Escape seq interrupt flag */
 #define USR1_FRAMERR	(1<<10) /* Frame error interrupt flag */
 #define USR1_RRDY	(1<<9)	 /* Receiver ready interrupt/dma flag */
+#define USR1_AGTIM	(1<<8)	 /* Ageing timer interrupt flag */
 #define USR1_TIMEOUT	(1<<7)	 /* Receive timeout interrupt status */
 #define USR1_RXDS	 (1<<6)	 /* Receiver idle interrupt flag */
 #define USR1_AIRINT	 (1<<5)	 /* Async IR wake interrupt flag */
@@ -728,11 +729,15 @@
 	if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
 		sport->dma_is_rxing = 1;
 
-		/* disable the `Recerver Ready Interrrupt` */
+		/* disable the receiver ready and aging timer interrupts */
 		temp = readl(sport->port.membase + UCR1);
 		temp &= ~(UCR1_RRDYEN);
 		writel(temp, sport->port.membase + UCR1);
 
+		temp = readl(sport->port.membase + UCR2);
+		temp &= ~(UCR2_ATEN);
+		writel(temp, sport->port.membase + UCR2);
+
 		/* tell the DMA to receive the data. */
 		start_rx_dma(sport);
 	}
@@ -749,7 +754,7 @@
 	sts = readl(sport->port.membase + USR1);
 	sts2 = readl(sport->port.membase + USR2);
 
-	if (sts & USR1_RRDY) {
+	if (sts & (USR1_RRDY | USR1_AGTIM)) {
 		if (sport->dma_is_enabled)
 			imx_dma_rxint(sport);
 		else
@@ -852,19 +857,6 @@
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
-#define TXTL 2 /* reset default */
-#define RXTL 1 /* reset default */
-
-static void imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
-{
-	unsigned int val;
-
-	/* set receiver / transmitter trigger level */
-	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
-	val |= TXTL << UFCR_TXTL_SHF | RXTL;
-	writel(val, sport->port.membase + UFCR);
-}
-
 #define RX_BUF_SIZE	(PAGE_SIZE)
 static void imx_rx_dma_done(struct imx_port *sport)
 {
@@ -873,11 +865,15 @@
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	/* Enable this interrupt when the RXFIFO is empty. */
+	/* re-enable interrupts to get notified when new symbols are incoming */
 	temp = readl(sport->port.membase + UCR1);
 	temp |= UCR1_RRDYEN;
 	writel(temp, sport->port.membase + UCR1);
 
+	temp = readl(sport->port.membase + UCR2);
+	temp |= UCR2_ATEN;
+	writel(temp, sport->port.membase + UCR2);
+
 	sport->dma_is_rxing = 0;
 
 	/* Is the shutdown waiting for us? */
@@ -888,14 +884,12 @@
 }
 
 /*
- * There are three kinds of RX DMA interrupts(such as in the MX6Q):
+ * There are two kinds of RX DMA interrupts(such as in the MX6Q):
  *   [1] the RX DMA buffer is full.
- *   [2] the Aging timer expires(wait for 8 bytes long)
- *   [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
+ *   [2] the aging timer expires
  *
- * The [2] is trigger when a character was been sitting in the FIFO
- * meanwhile [3] can wait for 32 bytes long when the RX line is
- * on IDLE state and RxFIFO is empty.
+ * Condition [2] is triggered when a character has been sitting in the FIFO
+ * for at least 8 byte durations.
  */
 static void dma_rx_callback(void *data)
 {
@@ -913,13 +907,6 @@
 	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
 	count = RX_BUF_SIZE - state.residue;
 
-	if (readl(sport->port.membase + USR2) & USR2_IDLE) {
-		/* In condition [3] the SDMA counted up too early */
-		count--;
-
-		writel(USR2_IDLE, sport->port.membase + USR2);
-	}
-
 	dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
 
 	if (count) {
@@ -931,23 +918,21 @@
 				sport->port.icount.buf_overrun++;
 		}
 		tty_flip_buffer_push(port);
-
-		start_rx_dma(sport);
-	} else if (readl(sport->port.membase + USR2) & USR2_RDR) {
-		/*
-		 * start rx_dma directly once data in RXFIFO, more efficient
-		 * than before:
-		 *	1. call imx_rx_dma_done to stop dma if no data received
-		 *	2. wait next  RDR interrupt to start dma transfer.
-		 */
-		start_rx_dma(sport);
-	} else {
-		/*
-		 * stop dma to prevent too many IDLE event trigged if no data
-		 * in RXFIFO
-		 */
-		imx_rx_dma_done(sport);
+		sport->port.icount.rx += count;
 	}
+
+	/*
+	 * Restart RX DMA directly if more data is available in order to skip
+	 * the roundtrip through the IRQ handler. If there is some data already
+	 * in the FIFO, DMA needs to be restarted soon anyways.
+	 *
+	 * Otherwise stop the DMA and reactivate FIFO IRQs to restart DMA once
+	 * data starts to arrive again.
+	 */
+	if (readl(sport->port.membase + USR2) & USR2_RDR)
+		start_rx_dma(sport);
+	else
+		imx_rx_dma_done(sport);
 }
 
 static int start_rx_dma(struct imx_port *sport)
@@ -980,6 +965,22 @@
 	return 0;
 }
 
+#define TXTL_DEFAULT 2 /* reset default */
+#define RXTL_DEFAULT 1 /* reset default */
+#define TXTL_DMA 8 /* DMA burst setting */
+#define RXTL_DMA 9 /* DMA burst setting */
+
+static void imx_setup_ufcr(struct imx_port *sport,
+			  unsigned char txwl, unsigned char rxwl)
+{
+	unsigned int val;
+
+	/* set receiver / transmitter trigger level */
+	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
+	val |= txwl << UFCR_TXTL_SHF | rxwl;
+	writel(val, sport->port.membase + UFCR);
+}
+
 static void imx_uart_dma_exit(struct imx_port *sport)
 {
 	if (sport->dma_chan_rx) {
@@ -1015,7 +1016,8 @@
 	slave_config.direction = DMA_DEV_TO_MEM;
 	slave_config.src_addr = sport->port.mapbase + URXD0;
 	slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-	slave_config.src_maxburst = RXTL;
+	/* one byte less than the watermark level to enable the aging timer */
+	slave_config.src_maxburst = RXTL_DMA - 1;
 	ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
 	if (ret) {
 		dev_err(dev, "error in RX dma configuration.\n");
@@ -1039,7 +1041,7 @@
 	slave_config.direction = DMA_MEM_TO_DEV;
 	slave_config.dst_addr = sport->port.mapbase + URTX0;
 	slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-	slave_config.dst_maxburst = TXTL;
+	slave_config.dst_maxburst = TXTL_DMA;
 	ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
 	if (ret) {
 		dev_err(dev, "error in TX dma configuration.");
@@ -1062,15 +1064,14 @@
 
 	/* set UCR1 */
 	temp = readl(sport->port.membase + UCR1);
-	temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
-		/* wait for 32 idle frames for IDDMA interrupt */
-		UCR1_ICD_REG(3);
+	temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN;
 	writel(temp, sport->port.membase + UCR1);
 
-	/* set UCR4 */
-	temp = readl(sport->port.membase + UCR4);
-	temp |= UCR4_IDDMAEN;
-	writel(temp, sport->port.membase + UCR4);
+	temp = readl(sport->port.membase + UCR2);
+	temp |= UCR2_ATEN;
+	writel(temp, sport->port.membase + UCR2);
+
+	imx_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);
 
 	sport->dma_is_enabled = 1;
 }
@@ -1086,13 +1087,10 @@
 
 	/* clear UCR2 */
 	temp = readl(sport->port.membase + UCR2);
-	temp &= ~(UCR2_CTSC | UCR2_CTS);
+	temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
 	writel(temp, sport->port.membase + UCR2);
 
-	/* clear UCR4 */
-	temp = readl(sport->port.membase + UCR4);
-	temp &= ~UCR4_IDDMAEN;
-	writel(temp, sport->port.membase + UCR4);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	sport->dma_is_enabled = 0;
 }
@@ -1115,7 +1113,7 @@
 		return retval;
 	}
 
-	imx_setup_ufcr(sport, 0);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	/* disable the DREN bit (Data Ready interrupt enable) before
 	 * requesting IRQs
@@ -1128,6 +1126,11 @@
 
 	writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 
+	/* Can we enable the DMA support? */
+	if (is_imx6q_uart(sport) && !uart_console(port) &&
+	    !sport->dma_is_inited)
+		imx_uart_dma_init(sport);
+
 	spin_lock_irqsave(&sport->port.lock, flags);
 	/* Reset fifo's and state machines */
 	i = 100;
@@ -1145,6 +1148,9 @@
 	writel(USR1_RTSD, sport->port.membase + USR1);
 	writel(USR2_ORE, sport->port.membase + USR2);
 
+	if (sport->dma_is_inited && !sport->dma_is_enabled)
+		imx_enable_dma(sport);
+
 	temp = readl(sport->port.membase + UCR1);
 	temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 
@@ -1278,7 +1284,7 @@
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long flags;
-	unsigned int ucr2, old_ucr1, old_txrxen, baud, quot;
+	unsigned int ucr2, old_ucr1, old_ucr2, baud, quot;
 	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
 	unsigned int div, ufcr;
 	unsigned long num, denom;
@@ -1315,11 +1321,6 @@
 			} else {
 				ucr2 |= UCR2_CTSC;
 			}
-
-			/* Can we enable the DMA support? */
-			if (is_imx6q_uart(sport) && !uart_console(port)
-				&& !sport->dma_is_inited)
-				imx_uart_dma_init(sport);
 		} else {
 			termios->c_cflag &= ~CRTSCTS;
 		}
@@ -1387,10 +1388,10 @@
 		barrier();
 
 	/* then, disable everything */
-	old_txrxen = readl(sport->port.membase + UCR2);
-	writel(old_txrxen & ~(UCR2_TXEN | UCR2_RXEN),
+	old_ucr2 = readl(sport->port.membase + UCR2);
+	writel(old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN),
 			sport->port.membase + UCR2);
-	old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
+	old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
 
 	/* custom-baudrate handling */
 	div = sport->port.uartclk / (baud * 16);
@@ -1431,13 +1432,11 @@
 	writel(old_ucr1, sport->port.membase + UCR1);
 
 	/* set the parity, stop bits and data size */
-	writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
+	writel(ucr2 | old_ucr2, sport->port.membase + UCR2);
 
 	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
 		imx_enable_ms(&sport->port);
 
-	if (sport->dma_is_inited && !sport->dma_is_enabled)
-		imx_enable_dma(sport);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
@@ -1503,7 +1502,7 @@
 	if (retval)
 		clk_disable_unprepare(sport->clk_ipg);
 
-	imx_setup_ufcr(sport, 0);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
@@ -1773,7 +1772,7 @@
 	else
 		imx_console_get_options(sport, &baud, &parity, &bits);
 
-	imx_setup_ufcr(sport, 0);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
@@ -1803,6 +1802,38 @@
 };
 
 #define IMX_CONSOLE	&imx_console
+
+#ifdef CONFIG_OF
+static void imx_console_early_putchar(struct uart_port *port, int ch)
+{
+	while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
+		cpu_relax();
+
+	writel_relaxed(ch, port->membase + URTX0);
+}
+
+static void imx_console_early_write(struct console *con, const char *s,
+				    unsigned count)
+{
+	struct earlycon_device *dev = con->data;
+
+	uart_console_write(&dev->port, s, count, imx_console_early_putchar);
+}
+
+static int __init
+imx_console_early_setup(struct earlycon_device *dev, const char *opt)
+{
+	if (!dev->port.membase)
+		return -ENODEV;
+
+	dev->con->write = imx_console_early_write;
+
+	return 0;
+}
+OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
+OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
+#endif
+
 #else
 #define IMX_CONSOLE	NULL
 #endif
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index e92d7eb..7eb04ae 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -691,12 +691,13 @@
 	p->port.mapbase = res->start;
 	p->port.membase = NULL;
 
-	p->port.irq = platform_get_irq(pdev, 0);
-	if (p->port.irq < 0) {
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
 		dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n",
 			uarts_registered);
-		return p->port.irq;
+		return ret;
 	}
+	p->port.irq = ret;
 
 	p->port.iotype = UPIO_MEM32;
 	p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;
diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c
index b90e7b3..3141aa2 100644
--- a/drivers/tty/serial/men_z135_uart.c
+++ b/drivers/tty/serial/men_z135_uart.c
@@ -35,8 +35,6 @@
 #define MEN_Z135_BAUD_REG		0x810
 #define MEN_Z135_TIMEOUT		0x814
 
-#define MEN_Z135_MEM_SIZE		0x818
-
 #define IRQ_ID(x) ((x) & 0x1f)
 
 #define MEN_Z135_IER_RXCIEN BIT(0)		/* RX Space IRQ */
@@ -124,6 +122,7 @@
 struct men_z135_port {
 	struct uart_port port;
 	struct mcb_device *mdev;
+	struct resource *mem;
 	unsigned char *rxbuf;
 	u32 stat_reg;
 	spinlock_t lock;
@@ -734,22 +733,30 @@
 
 static void men_z135_release_port(struct uart_port *port)
 {
+	struct men_z135_port *uart = to_men_z135(port);
+
 	iounmap(port->membase);
 	port->membase = NULL;
 
-	release_mem_region(port->mapbase, MEN_Z135_MEM_SIZE);
+	mcb_release_mem(uart->mem);
 }
 
 static int men_z135_request_port(struct uart_port *port)
 {
-	int size = MEN_Z135_MEM_SIZE;
+	struct men_z135_port *uart = to_men_z135(port);
+	struct mcb_device *mdev = uart->mdev;
+	struct resource *mem;
 
-	if (!request_mem_region(port->mapbase, size, "men_z135_port"))
-		return -EBUSY;
+	mem = mcb_request_mem(uart->mdev, dev_name(&mdev->dev));
+	if (IS_ERR(mem))
+		return PTR_ERR(mem);
 
-	port->membase = ioremap(port->mapbase, MEN_Z135_MEM_SIZE);
+	port->mapbase = mem->start;
+	uart->mem = mem;
+
+	port->membase = ioremap(mem->start, resource_size(mem));
 	if (port->membase == NULL) {
-		release_mem_region(port->mapbase, MEN_Z135_MEM_SIZE);
+		mcb_release_mem(mem);
 		return -ENOMEM;
 	}
 
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 41de374..8c3e513 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1135,6 +1135,13 @@
 	psc_ops->command(port, MPC52xx_PSC_RST_RX);
 	psc_ops->command(port, MPC52xx_PSC_RST_TX);
 
+	/*
+	 * According to Freescale's support the RST_TX command can produce a
+	 * spike on the TX pin. So they recommend to delay "for one character".
+	 * One millisecond should be enough for everyone.
+	 */
+	msleep(1);
+
 	psc_ops->set_sicr(port, 0);	/* UART mode DCD ignored */
 
 	psc_ops->fifo_init(port);
diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c
index 82bb6d1..cadfd1c 100644
--- a/drivers/tty/serial/mpsc.c
+++ b/drivers/tty/serial/mpsc.c
@@ -55,8 +55,6 @@
 #define SUPPORT_SYSRQ
 #endif
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/ioport.h>
@@ -755,7 +753,7 @@
 		pi->port.line);
 
 	if (!pi->dma_region) {
-		if (!dma_supported(pi->port.dev, 0xffffffff)) {
+		if (!dma_set_mask(pi->port.dev, 0xffffffff)) {
 			printk(KERN_ERR "MPSC: Inadequate DMA support\n");
 			rc = -ENXIO;
 		} else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev,
@@ -2108,26 +2106,11 @@
 	return rc;
 }
 
-static int mpsc_drv_remove(struct platform_device *dev)
-{
-	pr_debug("mpsc_drv_exit: Removing MPSC %d\n", dev->id);
-
-	if (dev->id < MPSC_NUM_CTLRS) {
-		uart_remove_one_port(&mpsc_reg, &mpsc_ports[dev->id].port);
-		mpsc_release_port((struct uart_port *)
-				&mpsc_ports[dev->id].port);
-		mpsc_drv_unmap_regs(&mpsc_ports[dev->id]);
-		return 0;
-	} else {
-		return -ENODEV;
-	}
-}
-
 static struct platform_driver mpsc_driver = {
 	.probe	= mpsc_drv_probe,
-	.remove	= mpsc_drv_remove,
 	.driver	= {
-		.name	= MPSC_CTLR_NAME,
+		.name			= MPSC_CTLR_NAME,
+		.suppress_bind_attrs	= true,
 	},
 };
 
@@ -2156,22 +2139,10 @@
 
 	return rc;
 }
+device_initcall(mpsc_drv_init);
 
-static void __exit mpsc_drv_exit(void)
-{
-	platform_driver_unregister(&mpsc_driver);
-	platform_driver_unregister(&mpsc_shared_driver);
-	uart_unregister_driver(&mpsc_reg);
-	memset(mpsc_ports, 0, sizeof(mpsc_ports));
-	memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs));
-}
-
-module_init(mpsc_drv_init);
-module_exit(mpsc_drv_exit);
-
+/*
 MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
 MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver");
-MODULE_VERSION(MPSC_VERSION);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(MPSC_MAJOR);
-MODULE_ALIAS("platform:" MPSC_CTLR_NAME);
+*/
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b73889c..dcde955 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -20,6 +20,8 @@
 #endif
 
 #include <linux/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/hrtimer.h>
 #include <linux/module.h>
 #include <linux/io.h>
@@ -31,6 +33,7 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
@@ -39,6 +42,11 @@
 
 #include "msm_serial.h"
 
+#define UARTDM_BURST_SIZE	16   /* in bytes */
+#define UARTDM_TX_AIGN(x)	((x) & ~0x3) /* valid for > 1p3 */
+#define UARTDM_TX_MAX		256   /* in bytes, valid for <= 1p3 */
+#define UARTDM_RX_SIZE		(UART_XMIT_SIZE / 4)
+
 enum {
 	UARTDM_1P1 = 1,
 	UARTDM_1P2,
@@ -46,6 +54,17 @@
 	UARTDM_1P4,
 };
 
+struct msm_dma {
+	struct dma_chan		*chan;
+	enum dma_data_direction dir;
+	dma_addr_t		phys;
+	unsigned char		*virt;
+	dma_cookie_t		cookie;
+	u32			enable_bit;
+	unsigned int		count;
+	struct dma_async_tx_descriptor	*desc;
+};
+
 struct msm_port {
 	struct uart_port	uart;
 	char			name[16];
@@ -55,9 +74,153 @@
 	int			is_uartdm;
 	unsigned int		old_snap_state;
 	bool			break_detected;
+	struct msm_dma		tx_dma;
+	struct msm_dma		rx_dma;
 };
 
-static inline void wait_for_xmitr(struct uart_port *port)
+static void msm_handle_tx(struct uart_port *port);
+static void msm_start_rx_dma(struct msm_port *msm_port);
+
+void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
+{
+	struct device *dev = port->dev;
+	unsigned int mapped;
+	u32 val;
+
+	mapped = dma->count;
+	dma->count = 0;
+
+	dmaengine_terminate_all(dma->chan);
+
+	/*
+	 * DMA Stall happens if enqueue and flush command happens concurrently.
+	 * For example before changing the baud rate/protocol configuration and
+	 * sending flush command to ADM, disable the channel of UARTDM.
+	 * Note: should not reset the receiver here immediately as it is not
+	 * suggested to do disable/reset or reset/disable at the same time.
+	 */
+	val = msm_read(port, UARTDM_DMEN);
+	val &= ~dma->enable_bit;
+	msm_write(port, val, UARTDM_DMEN);
+
+	if (mapped)
+		dma_unmap_single(dev, dma->phys, mapped, dma->dir);
+}
+
+static void msm_release_dma(struct msm_port *msm_port)
+{
+	struct msm_dma *dma;
+
+	dma = &msm_port->tx_dma;
+	if (dma->chan) {
+		msm_stop_dma(&msm_port->uart, dma);
+		dma_release_channel(dma->chan);
+	}
+
+	memset(dma, 0, sizeof(*dma));
+
+	dma = &msm_port->rx_dma;
+	if (dma->chan) {
+		msm_stop_dma(&msm_port->uart, dma);
+		dma_release_channel(dma->chan);
+		kfree(dma->virt);
+	}
+
+	memset(dma, 0, sizeof(*dma));
+}
+
+static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base)
+{
+	struct device *dev = msm_port->uart.dev;
+	struct dma_slave_config conf;
+	struct msm_dma *dma;
+	u32 crci = 0;
+	int ret;
+
+	dma = &msm_port->tx_dma;
+
+	/* allocate DMA resources, if available */
+	dma->chan = dma_request_slave_channel_reason(dev, "tx");
+	if (IS_ERR(dma->chan))
+		goto no_tx;
+
+	of_property_read_u32(dev->of_node, "qcom,tx-crci", &crci);
+
+	memset(&conf, 0, sizeof(conf));
+	conf.direction = DMA_MEM_TO_DEV;
+	conf.device_fc = true;
+	conf.dst_addr = base + UARTDM_TF;
+	conf.dst_maxburst = UARTDM_BURST_SIZE;
+	conf.slave_id = crci;
+
+	ret = dmaengine_slave_config(dma->chan, &conf);
+	if (ret)
+		goto rel_tx;
+
+	dma->dir = DMA_TO_DEVICE;
+
+	if (msm_port->is_uartdm < UARTDM_1P4)
+		dma->enable_bit = UARTDM_DMEN_TX_DM_ENABLE;
+	else
+		dma->enable_bit = UARTDM_DMEN_TX_BAM_ENABLE;
+
+	return;
+
+rel_tx:
+	dma_release_channel(dma->chan);
+no_tx:
+	memset(dma, 0, sizeof(*dma));
+}
+
+static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
+{
+	struct device *dev = msm_port->uart.dev;
+	struct dma_slave_config conf;
+	struct msm_dma *dma;
+	u32 crci = 0;
+	int ret;
+
+	dma = &msm_port->rx_dma;
+
+	/* allocate DMA resources, if available */
+	dma->chan = dma_request_slave_channel_reason(dev, "rx");
+	if (IS_ERR(dma->chan))
+		goto no_rx;
+
+	of_property_read_u32(dev->of_node, "qcom,rx-crci", &crci);
+
+	dma->virt = kzalloc(UARTDM_RX_SIZE, GFP_KERNEL);
+	if (!dma->virt)
+		goto rel_rx;
+
+	memset(&conf, 0, sizeof(conf));
+	conf.direction = DMA_DEV_TO_MEM;
+	conf.device_fc = true;
+	conf.src_addr = base + UARTDM_RF;
+	conf.src_maxburst = UARTDM_BURST_SIZE;
+	conf.slave_id = crci;
+
+	ret = dmaengine_slave_config(dma->chan, &conf);
+	if (ret)
+		goto err;
+
+	dma->dir = DMA_FROM_DEVICE;
+
+	if (msm_port->is_uartdm < UARTDM_1P4)
+		dma->enable_bit = UARTDM_DMEN_RX_DM_ENABLE;
+	else
+		dma->enable_bit = UARTDM_DMEN_RX_BAM_ENABLE;
+
+	return;
+err:
+	kfree(dma->virt);
+rel_rx:
+	dma_release_channel(dma->chan);
+no_rx:
+	memset(dma, 0, sizeof(*dma));
+}
+
+static inline void msm_wait_for_xmitr(struct uart_port *port)
 {
 	while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
 		if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
@@ -78,17 +241,277 @@
 static void msm_start_tx(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct msm_dma *dma = &msm_port->tx_dma;
+
+	/* Already started in DMA mode */
+	if (dma->count)
+		return;
 
 	msm_port->imr |= UART_IMR_TXLEV;
 	msm_write(port, msm_port->imr, UART_IMR);
 }
 
+static void msm_reset_dm_count(struct uart_port *port, int count)
+{
+	msm_wait_for_xmitr(port);
+	msm_write(port, count, UARTDM_NCF_TX);
+	msm_read(port, UARTDM_NCF_TX);
+}
+
+static void msm_complete_tx_dma(void *args)
+{
+	struct msm_port *msm_port = args;
+	struct uart_port *port = &msm_port->uart;
+	struct circ_buf *xmit = &port->state->xmit;
+	struct msm_dma *dma = &msm_port->tx_dma;
+	struct dma_tx_state state;
+	enum dma_status status;
+	unsigned long flags;
+	unsigned int count;
+	u32 val;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Already stopped */
+	if (!dma->count)
+		goto done;
+
+	status = dmaengine_tx_status(dma->chan, dma->cookie, &state);
+
+	dma_unmap_single(port->dev, dma->phys, dma->count, dma->dir);
+
+	val = msm_read(port, UARTDM_DMEN);
+	val &= ~dma->enable_bit;
+	msm_write(port, val, UARTDM_DMEN);
+
+	if (msm_port->is_uartdm > UARTDM_1P3) {
+		msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
+		msm_write(port, UART_CR_TX_ENABLE, UART_CR);
+	}
+
+	count = dma->count - state.residue;
+	port->icount.tx += count;
+	dma->count = 0;
+
+	xmit->tail += count;
+	xmit->tail &= UART_XMIT_SIZE - 1;
+
+	/* Restore "Tx FIFO below watermark" interrupt */
+	msm_port->imr |= UART_IMR_TXLEV;
+	msm_write(port, msm_port->imr, UART_IMR);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	msm_handle_tx(port);
+done:
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count)
+{
+	struct circ_buf *xmit = &msm_port->uart.state->xmit;
+	struct uart_port *port = &msm_port->uart;
+	struct msm_dma *dma = &msm_port->tx_dma;
+	void *cpu_addr;
+	int ret;
+	u32 val;
+
+	cpu_addr = &xmit->buf[xmit->tail];
+
+	dma->phys = dma_map_single(port->dev, cpu_addr, count, dma->dir);
+	ret = dma_mapping_error(port->dev, dma->phys);
+	if (ret)
+		return ret;
+
+	dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys,
+						count, DMA_MEM_TO_DEV,
+						DMA_PREP_INTERRUPT |
+						DMA_PREP_FENCE);
+	if (!dma->desc) {
+		ret = -EIO;
+		goto unmap;
+	}
+
+	dma->desc->callback = msm_complete_tx_dma;
+	dma->desc->callback_param = msm_port;
+
+	dma->cookie = dmaengine_submit(dma->desc);
+	ret = dma_submit_error(dma->cookie);
+	if (ret)
+		goto unmap;
+
+	/*
+	 * Using DMA complete for Tx FIFO reload, no need for
+	 * "Tx FIFO below watermark" one, disable it
+	 */
+	msm_port->imr &= ~UART_IMR_TXLEV;
+	msm_write(port, msm_port->imr, UART_IMR);
+
+	dma->count = count;
+
+	val = msm_read(port, UARTDM_DMEN);
+	val |= dma->enable_bit;
+
+	if (msm_port->is_uartdm < UARTDM_1P4)
+		msm_write(port, val, UARTDM_DMEN);
+
+	msm_reset_dm_count(port, count);
+
+	if (msm_port->is_uartdm > UARTDM_1P3)
+		msm_write(port, val, UARTDM_DMEN);
+
+	dma_async_issue_pending(dma->chan);
+	return 0;
+unmap:
+	dma_unmap_single(port->dev, dma->phys, count, dma->dir);
+	return ret;
+}
+
+static void msm_complete_rx_dma(void *args)
+{
+	struct msm_port *msm_port = args;
+	struct uart_port *port = &msm_port->uart;
+	struct tty_port *tport = &port->state->port;
+	struct msm_dma *dma = &msm_port->rx_dma;
+	int count = 0, i, sysrq;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Already stopped */
+	if (!dma->count)
+		goto done;
+
+	val = msm_read(port, UARTDM_DMEN);
+	val &= ~dma->enable_bit;
+	msm_write(port, val, UARTDM_DMEN);
+
+	/* Restore interrupts */
+	msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE;
+	msm_write(port, msm_port->imr, UART_IMR);
+
+	if (msm_read(port, UART_SR) & UART_SR_OVERRUN) {
+		port->icount.overrun++;
+		tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+		msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
+	}
+
+	count = msm_read(port, UARTDM_RX_TOTAL_SNAP);
+
+	port->icount.rx += count;
+
+	dma->count = 0;
+
+	dma_unmap_single(port->dev, dma->phys, UARTDM_RX_SIZE, dma->dir);
+
+	for (i = 0; i < count; i++) {
+		char flag = TTY_NORMAL;
+
+		if (msm_port->break_detected && dma->virt[i] == 0) {
+			port->icount.brk++;
+			flag = TTY_BREAK;
+			msm_port->break_detected = false;
+			if (uart_handle_break(port))
+				continue;
+		}
+
+		if (!(port->read_status_mask & UART_SR_RX_BREAK))
+			flag = TTY_NORMAL;
+
+		spin_unlock_irqrestore(&port->lock, flags);
+		sysrq = uart_handle_sysrq_char(port, dma->virt[i]);
+		spin_lock_irqsave(&port->lock, flags);
+		if (!sysrq)
+			tty_insert_flip_char(tport, dma->virt[i], flag);
+	}
+
+	msm_start_rx_dma(msm_port);
+done:
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (count)
+		tty_flip_buffer_push(tport);
+}
+
+static void msm_start_rx_dma(struct msm_port *msm_port)
+{
+	struct msm_dma *dma = &msm_port->rx_dma;
+	struct uart_port *uart = &msm_port->uart;
+	u32 val;
+	int ret;
+
+	if (!dma->chan)
+		return;
+
+	dma->phys = dma_map_single(uart->dev, dma->virt,
+				   UARTDM_RX_SIZE, dma->dir);
+	ret = dma_mapping_error(uart->dev, dma->phys);
+	if (ret)
+		return;
+
+	dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys,
+						UARTDM_RX_SIZE, DMA_DEV_TO_MEM,
+						DMA_PREP_INTERRUPT);
+	if (!dma->desc)
+		goto unmap;
+
+	dma->desc->callback = msm_complete_rx_dma;
+	dma->desc->callback_param = msm_port;
+
+	dma->cookie = dmaengine_submit(dma->desc);
+	ret = dma_submit_error(dma->cookie);
+	if (ret)
+		goto unmap;
+	/*
+	 * Using DMA for FIFO off-load, no need for "Rx FIFO over
+	 * watermark" or "stale" interrupts, disable them
+	 */
+	msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
+
+	/*
+	 * Well, when DMA is ADM3 engine(implied by <= UARTDM v1.3),
+	 * we need RXSTALE to flush input DMA fifo to memory
+	 */
+	if (msm_port->is_uartdm < UARTDM_1P4)
+		msm_port->imr |= UART_IMR_RXSTALE;
+
+	msm_write(uart, msm_port->imr, UART_IMR);
+
+	dma->count = UARTDM_RX_SIZE;
+
+	dma_async_issue_pending(dma->chan);
+
+	msm_write(uart, UART_CR_CMD_RESET_STALE_INT, UART_CR);
+	msm_write(uart, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
+
+	val = msm_read(uart, UARTDM_DMEN);
+	val |= dma->enable_bit;
+
+	if (msm_port->is_uartdm < UARTDM_1P4)
+		msm_write(uart, val, UARTDM_DMEN);
+
+	msm_write(uart, UARTDM_RX_SIZE, UARTDM_DMRX);
+
+	if (msm_port->is_uartdm > UARTDM_1P3)
+		msm_write(uart, val, UARTDM_DMEN);
+
+	return;
+unmap:
+	dma_unmap_single(uart->dev, dma->phys, UARTDM_RX_SIZE, dma->dir);
+}
+
 static void msm_stop_rx(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct msm_dma *dma = &msm_port->rx_dma;
 
 	msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
 	msm_write(port, msm_port->imr, UART_IMR);
+
+	if (dma->chan)
+		msm_stop_dma(port, dma);
 }
 
 static void msm_enable_ms(struct uart_port *port)
@@ -99,7 +522,7 @@
 	msm_write(port, msm_port->imr, UART_IMR);
 }
 
-static void handle_rx_dm(struct uart_port *port, unsigned int misr)
+static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
 {
 	struct tty_port *tport = &port->state->port;
 	unsigned int sr;
@@ -169,9 +592,12 @@
 		msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
 	msm_write(port, 0xFFFFFF, UARTDM_DMRX);
 	msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
+
+	/* Try to use DMA */
+	msm_start_rx_dma(msm_port);
 }
 
-static void handle_rx(struct uart_port *port)
+static void msm_handle_rx(struct uart_port *port)
 {
 	struct tty_port *tport = &port->state->port;
 	unsigned int sr;
@@ -224,18 +650,11 @@
 	spin_lock(&port->lock);
 }
 
-static void reset_dm_count(struct uart_port *port, int count)
-{
-	wait_for_xmitr(port);
-	msm_write(port, count, UARTDM_NCF_TX);
-	msm_read(port, UARTDM_NCF_TX);
-}
-
-static void handle_tx(struct uart_port *port)
+static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count)
 {
 	struct circ_buf *xmit = &port->state->xmit;
 	struct msm_port *msm_port = UART_TO_MSM(port);
-	unsigned int tx_count, num_chars;
+	unsigned int num_chars;
 	unsigned int tf_pointer = 0;
 	void __iomem *tf;
 
@@ -244,20 +663,8 @@
 	else
 		tf = port->membase + UART_TF;
 
-	tx_count = uart_circ_chars_pending(xmit);
-	tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
-			port->fifosize);
-
-	if (port->x_char) {
-		if (msm_port->is_uartdm)
-			reset_dm_count(port, tx_count + 1);
-
-		iowrite8_rep(tf, &port->x_char, 1);
-		port->icount.tx++;
-		port->x_char = 0;
-	} else if (tx_count && msm_port->is_uartdm) {
-		reset_dm_count(port, tx_count);
-	}
+	if (tx_count && msm_port->is_uartdm)
+		msm_reset_dm_count(port, tx_count);
 
 	while (tf_pointer < tx_count) {
 		int i;
@@ -290,20 +697,76 @@
 		uart_write_wakeup(port);
 }
 
-static void handle_delta_cts(struct uart_port *port)
+static void msm_handle_tx(struct uart_port *port)
+{
+	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct circ_buf *xmit = &msm_port->uart.state->xmit;
+	struct msm_dma *dma = &msm_port->tx_dma;
+	unsigned int pio_count, dma_count, dma_min;
+	void __iomem *tf;
+	int err = 0;
+
+	if (port->x_char) {
+		if (msm_port->is_uartdm)
+			tf = port->membase + UARTDM_TF;
+		else
+			tf = port->membase + UART_TF;
+
+		if (msm_port->is_uartdm)
+			msm_reset_dm_count(port, 1);
+
+		iowrite8_rep(tf, &port->x_char, 1);
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		msm_stop_tx(port);
+		return;
+	}
+
+	pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
+	dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+
+	dma_min = 1;	/* Always DMA */
+	if (msm_port->is_uartdm > UARTDM_1P3) {
+		dma_count = UARTDM_TX_AIGN(dma_count);
+		dma_min = UARTDM_BURST_SIZE;
+	} else {
+		if (dma_count > UARTDM_TX_MAX)
+			dma_count = UARTDM_TX_MAX;
+	}
+
+	if (pio_count > port->fifosize)
+		pio_count = port->fifosize;
+
+	if (!dma->chan || dma_count < dma_min)
+		msm_handle_tx_pio(port, pio_count);
+	else
+		err = msm_handle_tx_dma(msm_port, dma_count);
+
+	if (err)	/* fall back to PIO mode */
+		msm_handle_tx_pio(port, pio_count);
+}
+
+static void msm_handle_delta_cts(struct uart_port *port)
 {
 	msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
 	port->icount.cts++;
 	wake_up_interruptible(&port->state->port.delta_msr_wait);
 }
 
-static irqreturn_t msm_irq(int irq, void *dev_id)
+static irqreturn_t msm_uart_irq(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct msm_dma *dma = &msm_port->rx_dma;
+	unsigned long flags;
 	unsigned int misr;
+	u32 val;
 
-	spin_lock(&port->lock);
+	spin_lock_irqsave(&port->lock, flags);
 	misr = msm_read(port, UART_MISR);
 	msm_write(port, 0, UART_IMR); /* disable interrupt */
 
@@ -313,18 +776,29 @@
 	}
 
 	if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) {
-		if (msm_port->is_uartdm)
-			handle_rx_dm(port, misr);
-		else
-			handle_rx(port);
+		if (dma->count) {
+			val = UART_CR_CMD_STALE_EVENT_DISABLE;
+			msm_write(port, val, UART_CR);
+			val = UART_CR_CMD_RESET_STALE_INT;
+			msm_write(port, val, UART_CR);
+			/*
+			 * Flush DMA input fifo to memory, this will also
+			 * trigger DMA RX completion
+			 */
+			dmaengine_terminate_all(dma->chan);
+		} else if (msm_port->is_uartdm) {
+			msm_handle_rx_dm(port, misr);
+		} else {
+			msm_handle_rx(port);
+		}
 	}
 	if (misr & UART_IMR_TXLEV)
-		handle_tx(port);
+		msm_handle_tx(port);
 	if (misr & UART_IMR_DELTA_CTS)
-		handle_delta_cts(port);
+		msm_handle_delta_cts(port);
 
 	msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */
-	spin_unlock(&port->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
 
 	return IRQ_HANDLED;
 }
@@ -408,6 +882,7 @@
 		{    3, 0xdd,  8 },
 		{    2, 0xee, 16 },
 		{    1, 0xff, 31 },
+		{    0, 0xff, 31 },
 	};
 
 	divisor = uart_get_divisor(port, baud);
@@ -419,21 +894,41 @@
 	return entry; /* Default to smallest divider */
 }
 
-static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
+static int msm_set_baud_rate(struct uart_port *port, unsigned int baud,
+			     unsigned long *saved_flags)
 {
-	unsigned int rxstale, watermark;
+	unsigned int rxstale, watermark, mask;
 	struct msm_port *msm_port = UART_TO_MSM(port);
 	const struct msm_baud_map *entry;
+	unsigned long flags;
 
 	entry = msm_find_best_baud(port, baud);
 
 	msm_write(port, entry->code, UART_CSR);
 
+	if (baud > 460800)
+		port->uartclk = baud * 16;
+
+	flags = *saved_flags;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	clk_set_rate(msm_port->clk, port->uartclk);
+
+	spin_lock_irqsave(&port->lock, flags);
+	*saved_flags = flags;
+
 	/* RX stale watermark */
 	rxstale = entry->rxstale;
 	watermark = UART_IPR_STALE_LSB & rxstale;
-	watermark |= UART_IPR_RXSTALE_LAST;
-	watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
+	if (msm_port->is_uartdm) {
+		mask = UART_DM_IPR_STALE_TIMEOUT_MSB;
+	} else {
+		watermark |= UART_IPR_RXSTALE_LAST;
+		mask = UART_IPR_STALE_TIMEOUT_MSB;
+	}
+
+	watermark |= mask & (rxstale << 2);
+
 	msm_write(port, watermark, UART_IPR);
 
 	/* set RX watermark */
@@ -476,13 +971,13 @@
 static int msm_startup(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
-	unsigned int data, rfr_level;
+	unsigned int data, rfr_level, mask;
 	int ret;
 
 	snprintf(msm_port->name, sizeof(msm_port->name),
 		 "msm_serial%d", port->line);
 
-	ret = request_irq(port->irq, msm_irq, IRQF_TRIGGER_HIGH,
+	ret = request_irq(port->irq, msm_uart_irq, IRQF_TRIGGER_HIGH,
 			  msm_port->name, port);
 	if (unlikely(ret))
 		return ret;
@@ -496,11 +991,23 @@
 
 	/* set automatic RFR level */
 	data = msm_read(port, UART_MR1);
-	data &= ~UART_MR1_AUTO_RFR_LEVEL1;
+
+	if (msm_port->is_uartdm)
+		mask = UART_DM_MR1_AUTO_RFR_LEVEL1;
+	else
+		mask = UART_MR1_AUTO_RFR_LEVEL1;
+
+	data &= ~mask;
 	data &= ~UART_MR1_AUTO_RFR_LEVEL0;
-	data |= UART_MR1_AUTO_RFR_LEVEL1 & (rfr_level << 2);
+	data |= mask & (rfr_level << 2);
 	data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level;
 	msm_write(port, data, UART_MR1);
+
+	if (msm_port->is_uartdm) {
+		msm_request_tx_dma(msm_port, msm_port->uart.mapbase);
+		msm_request_rx_dma(msm_port, msm_port->uart.mapbase);
+	}
+
 	return 0;
 }
 
@@ -511,6 +1018,9 @@
 	msm_port->imr = 0;
 	msm_write(port, 0, UART_IMR); /* disable interrupts */
 
+	if (msm_port->is_uartdm)
+		msm_release_dma(msm_port);
+
 	clk_disable_unprepare(msm_port->clk);
 
 	free_irq(port->irq, port);
@@ -519,14 +1029,19 @@
 static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 {
+	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct msm_dma *dma = &msm_port->rx_dma;
 	unsigned long flags;
 	unsigned int baud, mr;
 
 	spin_lock_irqsave(&port->lock, flags);
 
+	if (dma->chan) /* Terminate if any */
+		msm_stop_dma(port, dma);
+
 	/* calculate and set baud rate */
-	baud = uart_get_baud_rate(port, termios, old, 300, 115200);
-	baud = msm_set_baud_rate(port, baud);
+	baud = uart_get_baud_rate(port, termios, old, 300, 4000000);
+	baud = msm_set_baud_rate(port, baud, &flags);
 	if (tty_termios_baud_rate(termios))
 		tty_termios_encode_baud_rate(termios, baud, baud);
 
@@ -588,6 +1103,9 @@
 
 	uart_update_timeout(port, termios->c_cflag, baud);
 
+	/* Try to use DMA */
+	msm_start_rx_dma(msm_port);
+
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -765,7 +1283,7 @@
 	msm_write(port, 0, UART_IMR);
 
 	if (msm_port->is_uartdm)
-		reset_dm_count(port, 1);
+		msm_reset_dm_count(port, 1);
 
 	/* Wait until FIFO is empty */
 	while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
@@ -839,7 +1357,7 @@
 
 #define UART_NR	ARRAY_SIZE(msm_uart_ports)
 
-static inline struct uart_port *get_port_from_line(unsigned int line)
+static inline struct uart_port *msm_get_port_from_line(unsigned int line)
 {
 	return &msm_uart_ports[line].uart;
 }
@@ -866,7 +1384,7 @@
 
 	spin_lock(&port->lock);
 	if (is_uartdm)
-		reset_dm_count(port, count);
+		msm_reset_dm_count(port, count);
 
 	i = 0;
 	while (i < count) {
@@ -911,7 +1429,7 @@
 
 	BUG_ON(co->index < 0 || co->index >= UART_NR);
 
-	port = get_port_from_line(co->index);
+	port = msm_get_port_from_line(co->index);
 	msm_port = UART_TO_MSM(port);
 
 	__msm_console_write(port, s, count, msm_port->is_uartdm);
@@ -928,7 +1446,7 @@
 	if (unlikely(co->index >= UART_NR || co->index < 0))
 		return -ENXIO;
 
-	port = get_port_from_line(co->index);
+	port = msm_get_port_from_line(co->index);
 
 	if (unlikely(!port->membase))
 		return -ENXIO;
@@ -1043,7 +1561,7 @@
 
 	dev_info(&pdev->dev, "msm_serial: detected port #%d\n", line);
 
-	port = get_port_from_line(line);
+	port = msm_get_port_from_line(line);
 	port->dev = &pdev->dev;
 	msm_port = UART_TO_MSM(port);
 
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index 737f69f..1786458 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -20,11 +20,12 @@
 
 #define UART_MR1_AUTO_RFR_LEVEL0	0x3F
 #define UART_MR1_AUTO_RFR_LEVEL1	0x3FF00
-#define UART_MR1_RX_RDY_CTL    		(1 << 7)
-#define UART_MR1_CTS_CTL       		(1 << 6)
+#define UART_DM_MR1_AUTO_RFR_LEVEL1	0xFFFFFF00
+#define UART_MR1_RX_RDY_CTL		BIT(7)
+#define UART_MR1_CTS_CTL		BIT(6)
 
 #define UART_MR2			0x0004
-#define UART_MR2_ERROR_MODE		(1 << 6)
+#define UART_MR2_ERROR_MODE		BIT(6)
 #define UART_MR2_BITS_PER_CHAR		0x30
 #define UART_MR2_BITS_PER_CHAR_5	(0x0 << 4)
 #define UART_MR2_BITS_PER_CHAR_6	(0x1 << 4)
@@ -58,26 +59,28 @@
 #define UART_CR_CMD_SET_RFR		(13 << 4)
 #define UART_CR_CMD_RESET_RFR		(14 << 4)
 #define UART_CR_CMD_PROTECTION_EN	(16 << 4)
+#define UART_CR_CMD_STALE_EVENT_DISABLE	(6 << 8)
 #define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
 #define UART_CR_CMD_FORCE_STALE		(4 << 8)
 #define UART_CR_CMD_RESET_TX_READY	(3 << 8)
-#define UART_CR_TX_DISABLE		(1 << 3)
-#define UART_CR_TX_ENABLE		(1 << 2)
-#define UART_CR_RX_DISABLE		(1 << 1)
-#define UART_CR_RX_ENABLE		(1 << 0)
+#define UART_CR_TX_DISABLE		BIT(3)
+#define UART_CR_TX_ENABLE		BIT(2)
+#define UART_CR_RX_DISABLE		BIT(1)
+#define UART_CR_RX_ENABLE		BIT(0)
 #define UART_CR_CMD_RESET_RXBREAK_START	((1 << 11) | (2 << 4))
 
 #define UART_IMR		0x0014
-#define UART_IMR_TXLEV		(1 << 0)
-#define UART_IMR_RXSTALE	(1 << 3)
-#define UART_IMR_RXLEV		(1 << 4)
-#define UART_IMR_DELTA_CTS	(1 << 5)
-#define UART_IMR_CURRENT_CTS	(1 << 6)
-#define UART_IMR_RXBREAK_START	(1 << 10)
+#define UART_IMR_TXLEV			BIT(0)
+#define UART_IMR_RXSTALE		BIT(3)
+#define UART_IMR_RXLEV			BIT(4)
+#define UART_IMR_DELTA_CTS		BIT(5)
+#define UART_IMR_CURRENT_CTS		BIT(6)
+#define UART_IMR_RXBREAK_START		BIT(10)
 
 #define UART_IPR_RXSTALE_LAST		0x20
 #define UART_IPR_STALE_LSB		0x1F
 #define UART_IPR_STALE_TIMEOUT_MSB	0x3FF80
+#define UART_DM_IPR_STALE_TIMEOUT_MSB	0xFFFFFF80
 
 #define UART_IPR	0x0018
 #define UART_TFWR	0x001C
@@ -96,20 +99,20 @@
 #define UART_TEST_CTRL		0x0050
 
 #define UART_SR			0x0008
-#define UART_SR_HUNT_CHAR	(1 << 7)
-#define UART_SR_RX_BREAK	(1 << 6)
-#define UART_SR_PAR_FRAME_ERR	(1 << 5)
-#define UART_SR_OVERRUN		(1 << 4)
-#define UART_SR_TX_EMPTY	(1 << 3)
-#define UART_SR_TX_READY	(1 << 2)
-#define UART_SR_RX_FULL		(1 << 1)
-#define UART_SR_RX_READY	(1 << 0)
+#define UART_SR_HUNT_CHAR	BIT(7)
+#define UART_SR_RX_BREAK	BIT(6)
+#define UART_SR_PAR_FRAME_ERR	BIT(5)
+#define UART_SR_OVERRUN		BIT(4)
+#define UART_SR_TX_EMPTY	BIT(3)
+#define UART_SR_TX_READY	BIT(2)
+#define UART_SR_RX_FULL		BIT(1)
+#define UART_SR_RX_READY	BIT(0)
 
 #define UART_RF			0x000C
 #define UARTDM_RF		0x0070
 #define UART_MISR		0x0010
 #define UART_ISR		0x0014
-#define UART_ISR_TX_READY	(1 << 7)
+#define UART_ISR_TX_READY	BIT(7)
 
 #define UARTDM_RXFS		0x50
 #define UARTDM_RXFS_BUF_SHIFT	0x7
@@ -119,6 +122,12 @@
 #define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
 #define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
 
+#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2)	/* UARTDM_1P4 */
+#define UARTDM_DMEN_TX_DM_ENABLE  BIT(0)	/* < UARTDM_1P4 */
+
+#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3)	/* UARTDM_1P4 */
+#define UARTDM_DMEN_RX_DM_ENABLE  BIT(1)	/* < UARTDM_1P4 */
+
 #define UARTDM_DMRX		0x34
 #define UARTDM_NCF_TX		0x40
 #define UARTDM_RX_TOTAL_SNAP	0x38
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 7c7f308..cd0414b 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1196,7 +1196,7 @@
 	enum mctrl_gpio_idx i;
 	struct gpio_desc *gpiod;
 
-	s->gpios = mctrl_gpio_init(dev, 0);
+	s->gpios = mctrl_gpio_init_noauto(dev, 0);
 	if (IS_ERR(s->gpios))
 		return PTR_ERR(s->gpios);
 
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 6823df9..de50296 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -21,6 +21,10 @@
 #include <linux/nwpserial.h>
 #include <linux/clk.h>
 
+#ifdef CONFIG_SERIAL_8250_MODULE
+#define CONFIG_SERIAL_8250 CONFIG_SERIAL_8250_MODULE
+#endif
+
 #include "8250/8250.h"
 
 struct of_serial_info {
@@ -150,6 +154,11 @@
 		break;
 	}
 
+	if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) &&
+	    (of_device_is_compatible(np, "fsl,ns16550") ||
+	     of_device_is_compatible(np, "fsl,16550-FIFO64")))
+		port->handle_irq = fsl8250_handle_irq;
+
 	return 0;
 out:
 	if (info->clk)
@@ -350,6 +359,7 @@
 #endif
 	{ /* end of list */ },
 };
+MODULE_DEVICE_TABLE(of, of_platform_serial_table);
 
 static struct platform_driver of_platform_serial_driver = {
 	.driver = {
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 7a2172b..9d4c84f 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -199,6 +199,7 @@
 	serial_out(up, UART_FCR, 0);
 }
 
+#ifdef CONFIG_PM
 static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
 {
 	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
@@ -219,6 +220,7 @@
 
 	pdata->enable_wakeup(up->dev, enable);
 }
+#endif /* CONFIG_PM */
 
 /*
  * Calculate the absolute difference between the desired and actual baud
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 856686d..d72cd73 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -385,32 +385,6 @@
 	}
 }
 
-static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
-				     unsigned long ufstat);
-
-static void uart_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
-{
-	struct uart_port *port = &ourport->port;
-	struct tty_port *tty = &port->state->port;
-	unsigned int ch, ufstat;
-	unsigned int count;
-
-	ufstat = rd_regl(port, S3C2410_UFSTAT);
-	count = s3c24xx_serial_rx_fifocnt(ourport, ufstat);
-
-	if (!count)
-		return;
-
-	while (count-- > 0) {
-		ch = rd_regb(port, S3C2410_URXH);
-
-		ourport->port.icount.rx++;
-		tty_insert_flip_char(tty, ch, TTY_NORMAL);
-	}
-
-	tty_flip_buffer_push(tty);
-}
-
 static void s3c24xx_serial_stop_rx(struct uart_port *port)
 {
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
@@ -573,7 +547,9 @@
 	ourport->rx_mode = S3C24XX_RX_PIO;
 }
 
-static irqreturn_t s3c24xx_serial_rx_chars_dma(int irq, void *dev_id)
+static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
+
+static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
 {
 	unsigned int utrstat, ufstat, received;
 	struct s3c24xx_uart_port *ourport = dev_id;
@@ -606,7 +582,7 @@
 		enable_rx_pio(ourport);
 	}
 
-	uart_rx_drain_fifo(ourport);
+	s3c24xx_serial_rx_drain_fifo(ourport);
 
 	if (tty) {
 		tty_flip_buffer_push(t);
@@ -621,16 +597,12 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
+static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
 {
-	struct s3c24xx_uart_port *ourport = dev_id;
 	struct uart_port *port = &ourport->port;
 	unsigned int ufcon, ch, flag, ufstat, uerstat;
-	unsigned long flags;
 	int max_count = port->fifosize;
 
-	spin_lock_irqsave(&port->lock, flags);
-
 	while (max_count-- > 0) {
 		ufcon = rd_regl(port, S3C2410_UFCON);
 		ufstat = rd_regl(port, S3C2410_UFSTAT);
@@ -654,9 +626,7 @@
 					ufcon |= S3C2410_UFCON_RESETRX;
 					wr_regl(port, S3C2410_UFCON, ufcon);
 					rx_enabled(port) = 1;
-					spin_unlock_irqrestore(&port->lock,
-							flags);
-					goto out;
+					return;
 				}
 				continue;
 			}
@@ -676,7 +646,7 @@
 				dbg("break!\n");
 				port->icount.brk++;
 				if (uart_handle_break(port))
-					goto ignore_char;
+					continue; /* Ignore character */
 			}
 
 			if (uerstat & S3C2410_UERSTAT_FRAME)
@@ -696,19 +666,25 @@
 		}
 
 		if (uart_handle_sysrq_char(port, ch))
-			goto ignore_char;
+			continue; /* Ignore character */
 
 		uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
 				 ch, flag);
-
-ignore_char:
-		continue;
 	}
 
-	spin_unlock_irqrestore(&port->lock, flags);
 	tty_flip_buffer_push(&port->state->port);
+}
 
-out:
+static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
+{
+	struct s3c24xx_uart_port *ourport = dev_id;
+	struct uart_port *port = &ourport->port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	s3c24xx_serial_rx_drain_fifo(ourport);
+	spin_unlock_irqrestore(&port->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
@@ -718,8 +694,8 @@
 	struct s3c24xx_uart_port *ourport = dev_id;
 
 	if (ourport->dma && ourport->dma->rx_chan)
-		return s3c24xx_serial_rx_chars_dma(irq, dev_id);
-	return s3c24xx_serial_rx_chars_pio(irq, dev_id);
+		return s3c24xx_serial_rx_chars_dma(dev_id);
+	return s3c24xx_serial_rx_chars_pio(dev_id);
 }
 
 static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 72ffd0d..1ae8aa6 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1321,6 +1321,9 @@
 		const struct of_device_id *of_id =
 			of_match_device(sc16is7xx_dt_ids, &spi->dev);
 
+		if (!of_id)
+			return -ENODEV;
+
 		devtype = (struct sc16is7xx_devtype *)of_id->data;
 	} else {
 		const struct spi_device_id *id_entry = spi_get_device_id(spi);
@@ -1380,6 +1383,9 @@
 		const struct of_device_id *of_id =
 				of_match_device(sc16is7xx_dt_ids, &i2c->dev);
 
+		if (!of_id)
+			return -ENODEV;
+
 		devtype = (struct sc16is7xx_devtype *)of_id->data;
 	} else {
 		devtype = (struct sc16is7xx_devtype *)id->driver_data;
@@ -1420,7 +1426,6 @@
 	.id_table	= sc16is7xx_i2c_id_table,
 };
 
-MODULE_ALIAS("i2c:sc16is7xx");
 #endif
 
 static int __init sc16is7xx_init(void)
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index cf0133a..1d6fc60 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -186,7 +186,6 @@
 		tegra_uart_write(tup, mcr, UART_MCR);
 		tup->mcr_shadow = mcr;
 	}
-	return;
 }
 
 static void set_dtr(struct tegra_uart_port *tup, bool active)
@@ -202,7 +201,6 @@
 		tegra_uart_write(tup, mcr, UART_MCR);
 		tup->mcr_shadow = mcr;
 	}
-	return;
 }
 
 static void tegra_uart_set_mctrl(struct uart_port *u, unsigned int mctrl)
@@ -217,7 +215,6 @@
 
 	dtr_enable = !!(mctrl & TIOCM_DTR);
 	set_dtr(tup, dtr_enable);
-	return;
 }
 
 static void tegra_uart_break_ctl(struct uart_port *u, int break_ctl)
@@ -511,7 +508,6 @@
 	async_tx_ack(tup->tx_dma_desc);
 	xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
 	tup->tx_in_progress = 0;
-	return;
 }
 
 static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
@@ -523,7 +519,6 @@
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&tup->uport);
 	tegra_uart_start_next_tx(tup);
-	return;
 }
 
 static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
@@ -545,8 +540,6 @@
 		if (!uart_handle_sysrq_char(&tup->uport, ch) && tty)
 			tty_insert_flip_char(tty, ch, flag);
 	} while (1);
-
-	return;
 }
 
 static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
@@ -576,13 +569,30 @@
 				TEGRA_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
 }
 
+static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup,
+				      unsigned int residue)
+{
+	struct tty_port *port = &tup->uport.state->port;
+	struct tty_struct *tty = tty_port_tty_get(port);
+	unsigned int count;
+
+	async_tx_ack(tup->rx_dma_desc);
+	count = tup->rx_bytes_requested - residue;
+
+	/* If we are here, DMA is stopped */
+	tegra_uart_copy_rx_to_tty(tup, port, count);
+
+	tegra_uart_handle_rx_pio(tup, port);
+	if (tty) {
+		tty_flip_buffer_push(port);
+		tty_kref_put(tty);
+	}
+}
+
 static void tegra_uart_rx_dma_complete(void *args)
 {
 	struct tegra_uart_port *tup = args;
 	struct uart_port *u = &tup->uport;
-	unsigned int count = tup->rx_bytes_requested;
-	struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
-	struct tty_port *port = &u->state->port;
 	unsigned long flags;
 	struct dma_tx_state state;
 	enum dma_status status;
@@ -596,22 +606,11 @@
 		goto done;
 	}
 
-	async_tx_ack(tup->rx_dma_desc);
-
 	/* Deactivate flow control to stop sender */
 	if (tup->rts_active)
 		set_rts(tup, false);
 
-	/* If we are here, DMA is stopped */
-	tegra_uart_copy_rx_to_tty(tup, port, count);
-
-	tegra_uart_handle_rx_pio(tup, port);
-	if (tty) {
-		spin_unlock_irqrestore(&u->lock, flags);
-		tty_flip_buffer_push(port);
-		spin_lock_irqsave(&u->lock, flags);
-		tty_kref_put(tty);
-	}
+	tegra_uart_rx_buffer_push(tup, 0);
 	tegra_uart_start_rx_dma(tup);
 
 	/* Activate flow control to start transfer */
@@ -622,34 +621,17 @@
 	spin_unlock_irqrestore(&u->lock, flags);
 }
 
-static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
-		unsigned long *flags)
+static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup)
 {
 	struct dma_tx_state state;
-	struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
-	struct tty_port *port = &tup->uport.state->port;
-	struct uart_port *u = &tup->uport;
-	unsigned int count;
 
 	/* Deactivate flow control to stop sender */
 	if (tup->rts_active)
 		set_rts(tup, false);
 
 	dmaengine_terminate_all(tup->rx_dma_chan);
-	dmaengine_tx_status(tup->rx_dma_chan,  tup->rx_cookie, &state);
-	async_tx_ack(tup->rx_dma_desc);
-	count = tup->rx_bytes_requested - state.residue;
-
-	/* If we are here, DMA is stopped */
-	tegra_uart_copy_rx_to_tty(tup, port, count);
-
-	tegra_uart_handle_rx_pio(tup, port);
-	if (tty) {
-		spin_unlock_irqrestore(&u->lock, *flags);
-		tty_flip_buffer_push(port);
-		spin_lock_irqsave(&u->lock, *flags);
-		tty_kref_put(tty);
-	}
+	dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
+	tegra_uart_rx_buffer_push(tup, state.residue);
 	tegra_uart_start_rx_dma(tup);
 
 	if (tup->rts_active)
@@ -697,7 +679,6 @@
 	/* Will start/stop_tx accordingly */
 	if (msr & UART_MSR_DCTS)
 		uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS);
-	return;
 }
 
 static irqreturn_t tegra_uart_isr(int irq, void *data)
@@ -714,7 +695,7 @@
 		iir = tegra_uart_read(tup, UART_IIR);
 		if (iir & UART_IIR_NO_INT) {
 			if (is_rx_int) {
-				tegra_uart_handle_rx_dma(tup, &flags);
+				tegra_uart_handle_rx_dma(tup);
 				if (tup->rx_in_progress) {
 					ier = tup->ier_shadow;
 					ier |= (UART_IER_RLSI | UART_IER_RTOIE |
@@ -769,11 +750,8 @@
 static void tegra_uart_stop_rx(struct uart_port *u)
 {
 	struct tegra_uart_port *tup = to_tegra_uport(u);
-	struct tty_struct *tty;
-	struct tty_port *port = &u->state->port;
 	struct dma_tx_state state;
 	unsigned long ier;
-	int count;
 
 	if (tup->rts_active)
 		set_rts(tup, false);
@@ -781,8 +759,6 @@
 	if (!tup->rx_in_progress)
 		return;
 
-	tty = tty_port_tty_get(&tup->uport.state->port);
-
 	tegra_uart_wait_sym_time(tup, 1); /* wait a character interval */
 
 	ier = tup->ier_shadow;
@@ -791,21 +767,9 @@
 	tup->ier_shadow = ier;
 	tegra_uart_write(tup, ier, UART_IER);
 	tup->rx_in_progress = 0;
-	if (tup->rx_dma_chan) {
-		dmaengine_terminate_all(tup->rx_dma_chan);
-		dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
-		async_tx_ack(tup->rx_dma_desc);
-		count = tup->rx_bytes_requested - state.residue;
-		tegra_uart_copy_rx_to_tty(tup, port, count);
-		tegra_uart_handle_rx_pio(tup, port);
-	} else {
-		tegra_uart_handle_rx_pio(tup, port);
-	}
-	if (tty) {
-		tty_flip_buffer_push(port);
-		tty_kref_put(tty);
-	}
-	return;
+	dmaengine_terminate_all(tup->rx_dma_chan);
+	dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
+	tegra_uart_rx_buffer_push(tup, state.residue);
 }
 
 static void tegra_uart_hw_deinit(struct tegra_uart_port *tup)
@@ -1083,7 +1047,6 @@
 	tup->tx_bytes = 0;
 	if (tup->tx_dma_chan)
 		dmaengine_terminate_all(tup->tx_dma_chan);
-	return;
 }
 
 static void tegra_uart_shutdown(struct uart_port *u)
@@ -1223,7 +1186,6 @@
 	tegra_uart_read(tup, UART_IER);
 
 	spin_unlock_irqrestore(&u->lock, flags);
-	return;
 }
 
 static const char *tegra_uart_type(struct uart_port *u)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 603d2cc..def5199 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1437,7 +1437,6 @@
 	clear_bit(ASYNCB_CLOSING, &port->flags);
 	spin_unlock_irq(&port->lock);
 	wake_up_interruptible(&port->open_wait);
-	wake_up_interruptible(&port->close_wait);
 
 	mutex_unlock(&port->mutex);
 
@@ -1819,8 +1818,8 @@
  *	@options: ptr for <options> field; NULL if not present (out)
  *
  *	Decodes earlycon kernel command line parameters of the form
- *	   earlycon=<name>,io|mmio|mmio32|mmio32be,<addr>,<options>
- *	   console=<name>,io|mmio|mmio32|mmio32be,<addr>,<options>
+ *	   earlycon=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
+ *	   console=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
  *
  *	The optional form
  *	   earlycon=<name>,0x<addr>,<options>
@@ -1841,6 +1840,10 @@
 	} else if (strncmp(p, "mmio32be,", 9) == 0) {
 		*iotype = UPIO_MEM32BE;
 		p += 9;
+	} else if (strncmp(p, "mmio32native,", 13) == 0) {
+		*iotype = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
+			UPIO_MEM32BE : UPIO_MEM32;
+		p += 13;
 	} else if (strncmp(p, "io,", 3) == 0) {
 		*iotype = UPIO_PORT;
 		p += 3;
diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c
index 402f7fb..3eb57eb 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.c
+++ b/drivers/tty/serial/serial_mctrl_gpio.c
@@ -12,18 +12,23 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
  */
 
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/irq.h>
 #include <linux/gpio/consumer.h>
 #include <linux/termios.h>
+#include <linux/serial_core.h>
 
 #include "serial_mctrl_gpio.h"
 
 struct mctrl_gpios {
+	struct uart_port *port;
 	struct gpio_desc *gpio[UART_GPIO_MAX];
+	int irq[UART_GPIO_MAX];
+	unsigned int mctrl_prev;
+	bool mctrl_on;
 };
 
 static const struct {
@@ -82,7 +87,7 @@
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_get);
 
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
 {
 	struct mctrl_gpios *gpios;
 	enum mctrl_gpio_idx i;
@@ -110,15 +115,135 @@
 
 	return gpios;
 }
-EXPORT_SYMBOL_GPL(mctrl_gpio_init);
+EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto);
+
+#define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS)
+static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context)
+{
+	struct mctrl_gpios *gpios = context;
+	struct uart_port *port = gpios->port;
+	u32 mctrl = gpios->mctrl_prev;
+	u32 mctrl_diff;
+
+	mctrl_gpio_get(gpios, &mctrl);
+
+	mctrl_diff = mctrl ^ gpios->mctrl_prev;
+	gpios->mctrl_prev = mctrl;
+
+	if (mctrl_diff & MCTRL_ANY_DELTA && port->state != NULL) {
+		if ((mctrl_diff & mctrl) & TIOCM_RI)
+			port->icount.rng++;
+
+		if ((mctrl_diff & mctrl) & TIOCM_DSR)
+			port->icount.dsr++;
+
+		if (mctrl_diff & TIOCM_CD)
+			uart_handle_dcd_change(port, mctrl & TIOCM_CD);
+
+		if (mctrl_diff & TIOCM_CTS)
+			uart_handle_cts_change(port, mctrl & TIOCM_CTS);
+
+		wake_up_interruptible(&port->state->port.delta_msr_wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
+{
+	struct mctrl_gpios *gpios;
+	enum mctrl_gpio_idx i;
+
+	gpios = mctrl_gpio_init_noauto(port->dev, idx);
+	if (IS_ERR(gpios))
+		return gpios;
+
+	gpios->port = port;
+
+	for (i = 0; i < UART_GPIO_MAX; ++i) {
+		int ret;
+
+		if (!gpios->gpio[i] || mctrl_gpios_desc[i].dir_out)
+			continue;
+
+		ret = gpiod_to_irq(gpios->gpio[i]);
+		if (ret <= 0) {
+			dev_err(port->dev,
+				"failed to find corresponding irq for %s (idx=%d, err=%d)\n",
+				mctrl_gpios_desc[i].name, idx, ret);
+			return ERR_PTR(ret);
+		}
+		gpios->irq[i] = ret;
+
+		/* irqs should only be enabled in .enable_ms */
+		irq_set_status_flags(gpios->irq[i], IRQ_NOAUTOEN);
+
+		ret = devm_request_irq(port->dev, gpios->irq[i],
+				       mctrl_gpio_irq_handle,
+				       IRQ_TYPE_EDGE_BOTH, dev_name(port->dev),
+				       gpios);
+		if (ret) {
+			/* alternatively implement polling */
+			dev_err(port->dev,
+				"failed to request irq for %s (idx=%d, err=%d)\n",
+				mctrl_gpios_desc[i].name, idx, ret);
+			return ERR_PTR(ret);
+		}
+	}
+
+	return gpios;
+}
 
 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
 	enum mctrl_gpio_idx i;
 
-	for (i = 0; i < UART_GPIO_MAX; i++)
+	for (i = 0; i < UART_GPIO_MAX; i++) {
+		if (gpios->irq[i])
+			devm_free_irq(gpios->port->dev, gpios->irq[i], gpios);
+
 		if (gpios->gpio[i])
 			devm_gpiod_put(dev, gpios->gpio[i]);
+	}
 	devm_kfree(dev, gpios);
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_free);
+
+void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+{
+	enum mctrl_gpio_idx i;
+
+	/* .enable_ms may be called multiple times */
+	if (gpios->mctrl_on)
+		return;
+
+	gpios->mctrl_on = true;
+
+	/* get initial status of modem lines GPIOs */
+	mctrl_gpio_get(gpios, &gpios->mctrl_prev);
+
+	for (i = 0; i < UART_GPIO_MAX; ++i) {
+		if (!gpios->irq[i])
+			continue;
+
+		enable_irq(gpios->irq[i]);
+	}
+}
+EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms);
+
+void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
+{
+	enum mctrl_gpio_idx i;
+
+	if (!gpios->mctrl_on)
+		return;
+
+	gpios->mctrl_on = false;
+
+	for (i = 0; i < UART_GPIO_MAX; ++i) {
+		if (!gpios->irq[i])
+			continue;
+
+		disable_irq(gpios->irq[i]);
+	}
+}
diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h
index 400ba04..9716db2 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.h
+++ b/drivers/tty/serial/serial_mctrl_gpio.h
@@ -22,6 +22,8 @@
 #include <linux/device.h>
 #include <linux/gpio/consumer.h>
 
+struct uart_port;
+
 enum mctrl_gpio_idx {
 	UART_GPIO_CTS,
 	UART_GPIO_DSR,
@@ -60,12 +62,22 @@
 				      enum mctrl_gpio_idx gidx);
 
 /*
+ * Request and set direction of modem control lines GPIOs and sets up irq
+ * handling.
+ * devm_* functions are used, so there's no need to call mctrl_gpio_free().
+ * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on
+ * allocation error.
+ */
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx);
+
+/*
  * Request and set direction of modem control lines GPIOs.
  * devm_* functions are used, so there's no need to call mctrl_gpio_free().
  * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on
  * allocation error.
  */
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx);
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev,
+					   unsigned int idx);
 
 /*
  * Free the mctrl_gpios structure.
@@ -74,6 +86,16 @@
  */
 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios);
 
+/*
+ * Enable gpio interrupts to report status line changes.
+ */
+void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios);
+
+/*
+ * Disable gpio interrupts to report status line changes.
+ */
+void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios);
+
 #else /* GPIOLIB */
 
 static inline
@@ -95,7 +117,13 @@
 }
 
 static inline
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
 {
 	return ERR_PTR(-ENOSYS);
 }
@@ -105,6 +133,14 @@
 {
 }
 
+static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+{
+}
+
+static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
+{
+}
+
 #endif /* GPIOLIB */
 
 #endif
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 1b2f894..960e50a 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -84,6 +84,7 @@
 	unsigned int		overrun_reg;
 	unsigned int		overrun_mask;
 	unsigned int		error_mask;
+	unsigned int		error_clear;
 	unsigned int		sampling_rate;
 	resource_size_t		reg_size;
 
@@ -103,19 +104,15 @@
 	struct dma_chan			*chan_rx;
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
-	struct dma_async_tx_descriptor	*desc_tx;
-	struct dma_async_tx_descriptor	*desc_rx[2];
 	dma_cookie_t			cookie_tx;
 	dma_cookie_t			cookie_rx[2];
 	dma_cookie_t			active_rx;
-	struct scatterlist		sg_tx;
-	unsigned int			sg_len_tx;
+	dma_addr_t			tx_dma_addr;
+	unsigned int			tx_dma_len;
 	struct scatterlist		sg_rx[2];
+	void				*rx_buf[2];
 	size_t				buf_len_rx;
-	struct sh_dmae_slave		param_tx;
-	struct sh_dmae_slave		param_rx;
 	struct work_struct		work_tx;
-	struct work_struct		work_rx;
 	struct timer_list		rx_timer;
 	unsigned int			rx_timeout;
 #endif
@@ -123,11 +120,6 @@
 	struct notifier_block		freq_transition;
 };
 
-/* Function prototypes */
-static void sci_start_tx(struct uart_port *port);
-static void sci_stop_tx(struct uart_port *port);
-static void sci_start_rx(struct uart_port *port);
-
 #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
 
 static struct sci_port sci_ports[SCI_NPORTS];
@@ -146,7 +138,7 @@
 /* Helper for invalidating specific entries of an inherited map. */
 #define sci_reg_invalid	{ .offset = 0, .size = 0 }
 
-static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
+static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 	[SCIx_PROBE_REGTYPE] = {
 		[0 ... SCIx_NR_REGS - 1] = sci_reg_invalid,
 	},
@@ -399,7 +391,7 @@
  */
 static unsigned int sci_serial_in(struct uart_port *p, int offset)
 {
-	struct plat_sci_reg *reg = sci_getreg(p, offset);
+	const struct plat_sci_reg *reg = sci_getreg(p, offset);
 
 	if (reg->size == 8)
 		return ioread8(p->membase + (reg->offset << p->regshift));
@@ -413,7 +405,7 @@
 
 static void sci_serial_out(struct uart_port *p, int offset, int value)
 {
-	struct plat_sci_reg *reg = sci_getreg(p, offset);
+	const struct plat_sci_reg *reg = sci_getreg(p, offset);
 
 	if (reg->size == 8)
 		iowrite8(value, p->membase + (reg->offset << p->regshift));
@@ -489,6 +481,105 @@
 	pm_runtime_put_sync(sci_port->port.dev);
 }
 
+static inline unsigned long port_rx_irq_mask(struct uart_port *port)
+{
+	/*
+	 * Not all ports (such as SCIFA) will support REIE. Rather than
+	 * special-casing the port type, we check the port initialization
+	 * IRQ enable mask to see whether the IRQ is desired at all. If
+	 * it's unset, it's logically inferred that there's no point in
+	 * testing for it.
+	 */
+	return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE);
+}
+
+static void sci_start_tx(struct uart_port *port)
+{
+	struct sci_port *s = to_sci_port(port);
+	unsigned short ctrl;
+
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+		u16 new, scr = serial_port_in(port, SCSCR);
+		if (s->chan_tx)
+			new = scr | SCSCR_TDRQE;
+		else
+			new = scr & ~SCSCR_TDRQE;
+		if (new != scr)
+			serial_port_out(port, SCSCR, new);
+	}
+
+	if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
+	    dma_submit_error(s->cookie_tx)) {
+		s->cookie_tx = 0;
+		schedule_work(&s->work_tx);
+	}
+#endif
+
+	if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+		/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
+		ctrl = serial_port_in(port, SCSCR);
+		serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
+	}
+}
+
+static void sci_stop_tx(struct uart_port *port)
+{
+	unsigned short ctrl;
+
+	/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
+	ctrl = serial_port_in(port, SCSCR);
+
+	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+		ctrl &= ~SCSCR_TDRQE;
+
+	ctrl &= ~SCSCR_TIE;
+
+	serial_port_out(port, SCSCR, ctrl);
+}
+
+static void sci_start_rx(struct uart_port *port)
+{
+	unsigned short ctrl;
+
+	ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
+
+	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+		ctrl &= ~SCSCR_RDRQE;
+
+	serial_port_out(port, SCSCR, ctrl);
+}
+
+static void sci_stop_rx(struct uart_port *port)
+{
+	unsigned short ctrl;
+
+	ctrl = serial_port_in(port, SCSCR);
+
+	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+		ctrl &= ~SCSCR_RDRQE;
+
+	ctrl &= ~port_rx_irq_mask(port);
+
+	serial_port_out(port, SCSCR, ctrl);
+}
+
+static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
+{
+	if (port->type == PORT_SCI) {
+		/* Just store the mask */
+		serial_port_out(port, SCxSR, mask);
+	} else if (to_sci_port(port)->overrun_mask == SCIFA_ORER) {
+		/* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */
+		/* Only clear the status bits we want to clear */
+		serial_port_out(port, SCxSR,
+				serial_port_in(port, SCxSR) & mask);
+	} else {
+		/* Store the mask, clear parity/framing errors */
+		serial_port_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC));
+	}
+}
+
 #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
 
 #ifdef CONFIG_CONSOLE_POLL
@@ -500,7 +591,7 @@
 	do {
 		status = serial_port_in(port, SCxSR);
 		if (status & SCxSR_ERRORS(port)) {
-			serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+			sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
 			continue;
 		}
 		break;
@@ -513,7 +604,7 @@
 
 	/* Dummy read */
 	serial_port_in(port, SCxSR);
-	serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+	sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
 
 	return c;
 }
@@ -528,14 +619,14 @@
 	} while (!(status & SCxSR_TDxE(port)));
 
 	serial_port_out(port, SCxTDR, c);
-	serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
+	sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
 }
 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
 
 static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 {
 	struct sci_port *s = to_sci_port(port);
-	struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
+	const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
 
 	/*
 	 * Use port-specific handler if provided.
@@ -565,7 +656,7 @@
 
 static int sci_txfill(struct uart_port *port)
 {
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 
 	reg = sci_getreg(port, SCTFDR);
 	if (reg->size)
@@ -585,7 +676,7 @@
 
 static int sci_rxfill(struct uart_port *port)
 {
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 
 	reg = sci_getreg(port, SCRFDR);
 	if (reg->size)
@@ -655,7 +746,7 @@
 		port->icount.tx++;
 	} while (--count > 0);
 
-	serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+	sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(port);
@@ -666,7 +757,7 @@
 
 		if (port->type != PORT_SCI) {
 			serial_port_in(port, SCxSR); /* Dummy read */
-			serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+			sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
 		}
 
 		ctrl |= SCSCR_TIE;
@@ -750,7 +841,7 @@
 		}
 
 		serial_port_in(port, SCxSR); /* dummy read */
-		serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+		sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
 
 		copied += count;
 		port->icount.rx += count;
@@ -761,7 +852,7 @@
 		tty_flip_buffer_push(tport);
 	} else {
 		serial_port_in(port, SCxSR); /* dummy read */
-		serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+		sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
 	}
 }
 
@@ -866,7 +957,7 @@
 {
 	struct tty_port *tport = &port->state->port;
 	struct sci_port *s = to_sci_port(port);
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 	int copied = 0;
 	u16 status;
 
@@ -924,6 +1015,460 @@
 	return copied;
 }
 
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+static void sci_dma_tx_complete(void *arg)
+{
+	struct sci_port *s = arg;
+	struct uart_port *port = &s->port;
+	struct circ_buf *xmit = &port->state->xmit;
+	unsigned long flags;
+
+	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	xmit->tail += s->tx_dma_len;
+	xmit->tail &= UART_XMIT_SIZE - 1;
+
+	port->icount.tx += s->tx_dma_len;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (!uart_circ_empty(xmit)) {
+		s->cookie_tx = 0;
+		schedule_work(&s->work_tx);
+	} else {
+		s->cookie_tx = -EINVAL;
+		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+			u16 ctrl = serial_port_in(port, SCSCR);
+			serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+		}
+	}
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Locking: called with port lock held */
+static int sci_dma_rx_push(struct sci_port *s, void *buf, size_t count)
+{
+	struct uart_port *port = &s->port;
+	struct tty_port *tport = &port->state->port;
+	int copied;
+
+	copied = tty_insert_flip_string(tport, buf, count);
+	if (copied < count) {
+		dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
+			 count - copied);
+		port->icount.buf_overrun++;
+	}
+
+	port->icount.rx += copied;
+
+	return copied;
+}
+
+static int sci_dma_rx_find_active(struct sci_port *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(s->cookie_rx); i++)
+		if (s->active_rx == s->cookie_rx[i])
+			return i;
+
+	dev_err(s->port.dev, "%s: Rx cookie %d not found!\n", __func__,
+		s->active_rx);
+	return -1;
+}
+
+static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
+{
+	struct dma_chan *chan = s->chan_rx;
+	struct uart_port *port = &s->port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	s->chan_rx = NULL;
+	s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	dmaengine_terminate_all(chan);
+	dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0],
+			  sg_dma_address(&s->sg_rx[0]));
+	dma_release_channel(chan);
+	if (enable_pio)
+		sci_start_rx(port);
+}
+
+static void sci_dma_rx_complete(void *arg)
+{
+	struct sci_port *s = arg;
+	struct dma_chan *chan = s->chan_rx;
+	struct uart_port *port = &s->port;
+	struct dma_async_tx_descriptor *desc;
+	unsigned long flags;
+	int active, count = 0;
+
+	dev_dbg(port->dev, "%s(%d) active cookie %d\n", __func__, port->line,
+		s->active_rx);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	active = sci_dma_rx_find_active(s);
+	if (active >= 0)
+		count = sci_dma_rx_push(s, s->rx_buf[active], s->buf_len_rx);
+
+	mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
+
+	if (count)
+		tty_flip_buffer_push(&port->state->port);
+
+	desc = dmaengine_prep_slave_sg(s->chan_rx, &s->sg_rx[active], 1,
+				       DMA_DEV_TO_MEM,
+				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc)
+		goto fail;
+
+	desc->callback = sci_dma_rx_complete;
+	desc->callback_param = s;
+	s->cookie_rx[active] = dmaengine_submit(desc);
+	if (dma_submit_error(s->cookie_rx[active]))
+		goto fail;
+
+	s->active_rx = s->cookie_rx[!active];
+
+	dma_async_issue_pending(chan);
+
+	dev_dbg(port->dev, "%s: cookie %d #%d, new active cookie %d\n",
+		__func__, s->cookie_rx[active], active, s->active_rx);
+	spin_unlock_irqrestore(&port->lock, flags);
+	return;
+
+fail:
+	spin_unlock_irqrestore(&port->lock, flags);
+	dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
+	sci_rx_dma_release(s, true);
+}
+
+static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
+{
+	struct dma_chan *chan = s->chan_tx;
+	struct uart_port *port = &s->port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	s->chan_tx = NULL;
+	s->cookie_tx = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	dmaengine_terminate_all(chan);
+	dma_unmap_single(chan->device->dev, s->tx_dma_addr, UART_XMIT_SIZE,
+			 DMA_TO_DEVICE);
+	dma_release_channel(chan);
+	if (enable_pio)
+		sci_start_tx(port);
+}
+
+static void sci_submit_rx(struct sci_port *s)
+{
+	struct dma_chan *chan = s->chan_rx;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		struct scatterlist *sg = &s->sg_rx[i];
+		struct dma_async_tx_descriptor *desc;
+
+		desc = dmaengine_prep_slave_sg(chan,
+			sg, 1, DMA_DEV_TO_MEM,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc)
+			goto fail;
+
+		desc->callback = sci_dma_rx_complete;
+		desc->callback_param = s;
+		s->cookie_rx[i] = dmaengine_submit(desc);
+		if (dma_submit_error(s->cookie_rx[i]))
+			goto fail;
+
+		dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
+			s->cookie_rx[i], i);
+	}
+
+	s->active_rx = s->cookie_rx[0];
+
+	dma_async_issue_pending(chan);
+	return;
+
+fail:
+	if (i)
+		dmaengine_terminate_all(chan);
+	for (i = 0; i < 2; i++)
+		s->cookie_rx[i] = -EINVAL;
+	s->active_rx = -EINVAL;
+	dev_warn(s->port.dev, "Failed to re-start Rx DMA, using PIO\n");
+	sci_rx_dma_release(s, true);
+}
+
+static void work_fn_tx(struct work_struct *work)
+{
+	struct sci_port *s = container_of(work, struct sci_port, work_tx);
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *chan = s->chan_tx;
+	struct uart_port *port = &s->port;
+	struct circ_buf *xmit = &port->state->xmit;
+	dma_addr_t buf;
+
+	/*
+	 * DMA is idle now.
+	 * Port xmit buffer is already mapped, and it is one page... Just adjust
+	 * offsets and lengths. Since it is a circular buffer, we have to
+	 * transmit till the end, and then the rest. Take the port lock to get a
+	 * consistent xmit buffer state.
+	 */
+	spin_lock_irq(&port->lock);
+	buf = s->tx_dma_addr + (xmit->tail & (UART_XMIT_SIZE - 1));
+	s->tx_dma_len = min_t(unsigned int,
+		CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
+		CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
+	spin_unlock_irq(&port->lock);
+
+	desc = dmaengine_prep_slave_single(chan, buf, s->tx_dma_len,
+					   DMA_MEM_TO_DEV,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		dev_warn(port->dev, "Failed preparing Tx DMA descriptor\n");
+		/* switch to PIO */
+		sci_tx_dma_release(s, true);
+		return;
+	}
+
+	dma_sync_single_for_device(chan->device->dev, buf, s->tx_dma_len,
+				   DMA_TO_DEVICE);
+
+	spin_lock_irq(&port->lock);
+	desc->callback = sci_dma_tx_complete;
+	desc->callback_param = s;
+	spin_unlock_irq(&port->lock);
+	s->cookie_tx = dmaengine_submit(desc);
+	if (dma_submit_error(s->cookie_tx)) {
+		dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
+		/* switch to PIO */
+		sci_tx_dma_release(s, true);
+		return;
+	}
+
+	dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
+		__func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
+
+	dma_async_issue_pending(chan);
+}
+
+static void rx_timer_fn(unsigned long arg)
+{
+	struct sci_port *s = (struct sci_port *)arg;
+	struct dma_chan *chan = s->chan_rx;
+	struct uart_port *port = &s->port;
+	struct dma_tx_state state;
+	enum dma_status status;
+	unsigned long flags;
+	unsigned int read;
+	int active, count;
+	u16 scr;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	dev_dbg(port->dev, "DMA Rx timed out\n");
+
+	active = sci_dma_rx_find_active(s);
+	if (active < 0) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		return;
+	}
+
+	status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
+	if (status == DMA_COMPLETE) {
+		dev_dbg(port->dev, "Cookie %d #%d has already completed\n",
+			s->active_rx, active);
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		/* Let packet complete handler take care of the packet */
+		return;
+	}
+
+	dmaengine_pause(chan);
+
+	/*
+	 * sometimes DMA transfer doesn't stop even if it is stopped and
+	 * data keeps on coming until transaction is complete so check
+	 * for DMA_COMPLETE again
+	 * Let packet complete handler take care of the packet
+	 */
+	status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
+	if (status == DMA_COMPLETE) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		dev_dbg(port->dev, "Transaction complete after DMA engine was stopped");
+		return;
+	}
+
+	/* Handle incomplete DMA receive */
+	dmaengine_terminate_all(s->chan_rx);
+	read = sg_dma_len(&s->sg_rx[active]) - state.residue;
+	dev_dbg(port->dev, "Read %u bytes with cookie %d\n", read,
+		s->active_rx);
+
+	if (read) {
+		count = sci_dma_rx_push(s, s->rx_buf[active], read);
+		if (count)
+			tty_flip_buffer_push(&port->state->port);
+	}
+
+	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+		sci_submit_rx(s);
+
+	/* Direct new serial port interrupts back to CPU */
+	scr = serial_port_in(port, SCSCR);
+	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+		scr &= ~SCSCR_RDRQE;
+		enable_irq(s->irqs[SCIx_RXI_IRQ]);
+	}
+	serial_port_out(port, SCSCR, scr | SCSCR_RIE);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
+					     enum dma_transfer_direction dir,
+					     unsigned int id)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct dma_slave_config cfg;
+	int ret;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+					(void *)(unsigned long)id, port->dev,
+					dir == DMA_MEM_TO_DEV ? "tx" : "rx");
+	if (!chan) {
+		dev_warn(port->dev,
+			 "dma_request_slave_channel_compat failed\n");
+		return NULL;
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.direction = dir;
+	if (dir == DMA_MEM_TO_DEV) {
+		cfg.dst_addr = port->mapbase +
+			(sci_getreg(port, SCxTDR)->offset << port->regshift);
+		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	} else {
+		cfg.src_addr = port->mapbase +
+			(sci_getreg(port, SCxRDR)->offset << port->regshift);
+		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	}
+
+	ret = dmaengine_slave_config(chan, &cfg);
+	if (ret) {
+		dev_warn(port->dev, "dmaengine_slave_config failed %d\n", ret);
+		dma_release_channel(chan);
+		return NULL;
+	}
+
+	return chan;
+}
+
+static void sci_request_dma(struct uart_port *port)
+{
+	struct sci_port *s = to_sci_port(port);
+	struct dma_chan *chan;
+
+	dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
+
+	if (!port->dev->of_node &&
+	    (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0))
+		return;
+
+	s->cookie_tx = -EINVAL;
+	chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV, s->cfg->dma_slave_tx);
+	dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
+	if (chan) {
+		s->chan_tx = chan;
+		/* UART circular tx buffer is an aligned page. */
+		s->tx_dma_addr = dma_map_single(chan->device->dev,
+						port->state->xmit.buf,
+						UART_XMIT_SIZE,
+						DMA_TO_DEVICE);
+		if (dma_mapping_error(chan->device->dev, s->tx_dma_addr)) {
+			dev_warn(port->dev, "Failed mapping Tx DMA descriptor\n");
+			dma_release_channel(chan);
+			s->chan_tx = NULL;
+		} else {
+			dev_dbg(port->dev, "%s: mapped %lu@%p to %pad\n",
+				__func__, UART_XMIT_SIZE,
+				port->state->xmit.buf, &s->tx_dma_addr);
+		}
+
+		INIT_WORK(&s->work_tx, work_fn_tx);
+	}
+
+	chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM, s->cfg->dma_slave_rx);
+	dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
+	if (chan) {
+		unsigned int i;
+		dma_addr_t dma;
+		void *buf;
+
+		s->chan_rx = chan;
+
+		s->buf_len_rx = 2 * max_t(size_t, 16, port->fifosize);
+		buf = dma_alloc_coherent(chan->device->dev, s->buf_len_rx * 2,
+					 &dma, GFP_KERNEL);
+		if (!buf) {
+			dev_warn(port->dev,
+				 "Failed to allocate Rx dma buffer, using PIO\n");
+			dma_release_channel(chan);
+			s->chan_rx = NULL;
+			return;
+		}
+
+		for (i = 0; i < 2; i++) {
+			struct scatterlist *sg = &s->sg_rx[i];
+
+			sg_init_table(sg, 1);
+			s->rx_buf[i] = buf;
+			sg_dma_address(sg) = dma;
+			sg->length = s->buf_len_rx;
+
+			buf += s->buf_len_rx;
+			dma += s->buf_len_rx;
+		}
+
+		setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
+
+		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+			sci_submit_rx(s);
+	}
+}
+
+static void sci_free_dma(struct uart_port *port)
+{
+	struct sci_port *s = to_sci_port(port);
+
+	if (s->chan_tx)
+		sci_tx_dma_release(s, false);
+	if (s->chan_rx)
+		sci_rx_dma_release(s, false);
+}
+#else
+static inline void sci_request_dma(struct uart_port *port)
+{
+}
+
+static inline void sci_free_dma(struct uart_port *port)
+{
+}
+#endif
+
 static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
 {
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -940,10 +1485,12 @@
 			scr |= SCSCR_RDRQE;
 		} else {
 			scr &= ~SCSCR_RIE;
+			sci_submit_rx(s);
 		}
 		serial_port_out(port, SCSCR, scr);
 		/* Clear current interrupt */
-		serial_port_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
+		serial_port_out(port, SCxSR,
+				ssr & ~(SCIF_DR | SCxSR_RDxF(port)));
 		dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
 			jiffies, s->rx_timeout);
 		mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
@@ -976,23 +1523,26 @@
 static irqreturn_t sci_er_interrupt(int irq, void *ptr)
 {
 	struct uart_port *port = ptr;
+	struct sci_port *s = to_sci_port(port);
 
 	/* Handle errors */
 	if (port->type == PORT_SCI) {
 		if (sci_handle_errors(port)) {
 			/* discard character in rx buffer */
 			serial_port_in(port, SCxSR);
-			serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+			sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
 		}
 	} else {
 		sci_handle_fifo_overrun(port);
-		sci_rx_interrupt(irq, ptr);
+		if (!s->chan_rx)
+			sci_receive_chars(ptr);
 	}
 
-	serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+	sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
 
 	/* Kick the transmission */
-	sci_tx_interrupt(irq, ptr);
+	if (!s->chan_tx)
+		sci_tx_interrupt(irq, ptr);
 
 	return IRQ_HANDLED;
 }
@@ -1003,23 +1553,11 @@
 
 	/* Handle BREAKs */
 	sci_handle_breaks(port);
-	serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
+	sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
 
 	return IRQ_HANDLED;
 }
 
-static inline unsigned long port_rx_irq_mask(struct uart_port *port)
-{
-	/*
-	 * Not all ports (such as SCIFA) will support REIE. Rather than
-	 * special-casing the port type, we check the port initialization
-	 * IRQ enable mask to see whether the IRQ is desired at all. If
-	 * it's unset, it's logically inferred that there's no point in
-	 * testing for it.
-	 */
-	return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE);
-}
-
 static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 {
 	unsigned short ssr_status, scr_status, err_enabled, orer_status = 0;
@@ -1048,11 +1586,8 @@
 	 * DR flags
 	 */
 	if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
-	    (scr_status & SCSCR_RIE)) {
-		if (port->type == PORT_SCIF || port->type == PORT_HSCIF)
-			sci_handle_fifo_overrun(port);
+	    (scr_status & SCSCR_RIE))
 		ret = sci_rx_interrupt(irq, ptr);
-	}
 
 	/* Error Interrupt */
 	if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
@@ -1063,8 +1598,10 @@
 		ret = sci_br_interrupt(irq, ptr);
 
 	/* Overrun Interrupt */
-	if (orer_status & s->overrun_mask)
+	if (orer_status & s->overrun_mask) {
 		sci_handle_fifo_overrun(port);
+		ret = IRQ_HANDLED;
+	}
 
 	return ret;
 }
@@ -1092,7 +1629,7 @@
 	return NOTIFY_OK;
 }
 
-static struct sci_irq_desc {
+static const struct sci_irq_desc {
 	const char	*desc;
 	irq_handler_t	handler;
 } sci_irq_desc[] = {
@@ -1134,7 +1671,7 @@
 	int i, j, ret = 0;
 
 	for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
-		struct sci_irq_desc *desc;
+		const struct sci_irq_desc *desc;
 		int irq;
 
 		if (SCIx_IRQ_IS_MUXED(port)) {
@@ -1154,11 +1691,8 @@
 		desc = sci_irq_desc + i;
 		port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
 					    dev_name(up->dev), desc->desc);
-		if (!port->irqstr[j]) {
-			dev_err(up->dev, "Failed to allocate %s IRQ string\n",
-				desc->desc);
+		if (!port->irqstr[j])
 			goto out_nomem;
-		}
 
 		ret = request_irq(irq, desc->handler, up->irqflags,
 				  port->irqstr[j], port);
@@ -1232,7 +1766,7 @@
 static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	if (mctrl & TIOCM_LOOP) {
-		struct plat_sci_reg *reg;
+		const struct plat_sci_reg *reg;
 
 		/*
 		 * Standard loopback mode for SCFCR ports.
@@ -1254,356 +1788,10 @@
 	return TIOCM_DSR | TIOCM_CAR;
 }
 
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-static void sci_dma_tx_complete(void *arg)
-{
-	struct sci_port *s = arg;
-	struct uart_port *port = &s->port;
-	struct circ_buf *xmit = &port->state->xmit;
-	unsigned long flags;
-
-	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
-
-	spin_lock_irqsave(&port->lock, flags);
-
-	xmit->tail += sg_dma_len(&s->sg_tx);
-	xmit->tail &= UART_XMIT_SIZE - 1;
-
-	port->icount.tx += sg_dma_len(&s->sg_tx);
-
-	async_tx_ack(s->desc_tx);
-	s->desc_tx = NULL;
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(port);
-
-	if (!uart_circ_empty(xmit)) {
-		s->cookie_tx = 0;
-		schedule_work(&s->work_tx);
-	} else {
-		s->cookie_tx = -EINVAL;
-		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-			u16 ctrl = serial_port_in(port, SCSCR);
-			serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
-		}
-	}
-
-	spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/* Locking: called with port lock held */
-static int sci_dma_rx_push(struct sci_port *s, size_t count)
-{
-	struct uart_port *port = &s->port;
-	struct tty_port *tport = &port->state->port;
-	int i, active, room;
-
-	room = tty_buffer_request_room(tport, count);
-
-	if (s->active_rx == s->cookie_rx[0]) {
-		active = 0;
-	} else if (s->active_rx == s->cookie_rx[1]) {
-		active = 1;
-	} else {
-		dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
-		return 0;
-	}
-
-	if (room < count)
-		dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
-			 count - room);
-	if (!room)
-		return room;
-
-	for (i = 0; i < room; i++)
-		tty_insert_flip_char(tport, ((u8 *)sg_virt(&s->sg_rx[active]))[i],
-				     TTY_NORMAL);
-
-	port->icount.rx += room;
-
-	return room;
-}
-
-static void sci_dma_rx_complete(void *arg)
-{
-	struct sci_port *s = arg;
-	struct uart_port *port = &s->port;
-	unsigned long flags;
-	int count;
-
-	dev_dbg(port->dev, "%s(%d) active #%d\n",
-		__func__, port->line, s->active_rx);
-
-	spin_lock_irqsave(&port->lock, flags);
-
-	count = sci_dma_rx_push(s, s->buf_len_rx);
-
-	mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
-
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	if (count)
-		tty_flip_buffer_push(&port->state->port);
-
-	schedule_work(&s->work_rx);
-}
-
-static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
-{
-	struct dma_chan *chan = s->chan_rx;
-	struct uart_port *port = &s->port;
-
-	s->chan_rx = NULL;
-	s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
-	dma_release_channel(chan);
-	if (sg_dma_address(&s->sg_rx[0]))
-		dma_free_coherent(port->dev, s->buf_len_rx * 2,
-				  sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
-	if (enable_pio)
-		sci_start_rx(port);
-}
-
-static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
-{
-	struct dma_chan *chan = s->chan_tx;
-	struct uart_port *port = &s->port;
-
-	s->chan_tx = NULL;
-	s->cookie_tx = -EINVAL;
-	dma_release_channel(chan);
-	if (enable_pio)
-		sci_start_tx(port);
-}
-
-static void sci_submit_rx(struct sci_port *s)
-{
-	struct dma_chan *chan = s->chan_rx;
-	int i;
-
-	for (i = 0; i < 2; i++) {
-		struct scatterlist *sg = &s->sg_rx[i];
-		struct dma_async_tx_descriptor *desc;
-
-		desc = dmaengine_prep_slave_sg(chan,
-			sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
-
-		if (desc) {
-			s->desc_rx[i] = desc;
-			desc->callback = sci_dma_rx_complete;
-			desc->callback_param = s;
-			s->cookie_rx[i] = desc->tx_submit(desc);
-		}
-
-		if (!desc || s->cookie_rx[i] < 0) {
-			if (i) {
-				async_tx_ack(s->desc_rx[0]);
-				s->cookie_rx[0] = -EINVAL;
-			}
-			if (desc) {
-				async_tx_ack(desc);
-				s->cookie_rx[i] = -EINVAL;
-			}
-			dev_warn(s->port.dev,
-				 "failed to re-start DMA, using PIO\n");
-			sci_rx_dma_release(s, true);
-			return;
-		}
-		dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n",
-			__func__, s->cookie_rx[i], i);
-	}
-
-	s->active_rx = s->cookie_rx[0];
-
-	dma_async_issue_pending(chan);
-}
-
-static void work_fn_rx(struct work_struct *work)
-{
-	struct sci_port *s = container_of(work, struct sci_port, work_rx);
-	struct uart_port *port = &s->port;
-	struct dma_async_tx_descriptor *desc;
-	int new;
-
-	if (s->active_rx == s->cookie_rx[0]) {
-		new = 0;
-	} else if (s->active_rx == s->cookie_rx[1]) {
-		new = 1;
-	} else {
-		dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
-		return;
-	}
-	desc = s->desc_rx[new];
-
-	if (dma_async_is_tx_complete(s->chan_rx, s->active_rx, NULL, NULL) !=
-	    DMA_COMPLETE) {
-		/* Handle incomplete DMA receive */
-		struct dma_chan *chan = s->chan_rx;
-		struct shdma_desc *sh_desc = container_of(desc,
-					struct shdma_desc, async_tx);
-		unsigned long flags;
-		int count;
-
-		dmaengine_terminate_all(chan);
-		dev_dbg(port->dev, "Read %zu bytes with cookie %d\n",
-			sh_desc->partial, sh_desc->cookie);
-
-		spin_lock_irqsave(&port->lock, flags);
-		count = sci_dma_rx_push(s, sh_desc->partial);
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		if (count)
-			tty_flip_buffer_push(&port->state->port);
-
-		sci_submit_rx(s);
-
-		return;
-	}
-
-	s->cookie_rx[new] = desc->tx_submit(desc);
-	if (s->cookie_rx[new] < 0) {
-		dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
-		sci_rx_dma_release(s, true);
-		return;
-	}
-
-	s->active_rx = s->cookie_rx[!new];
-
-	dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n",
-		__func__, s->cookie_rx[new], new, s->active_rx);
-}
-
-static void work_fn_tx(struct work_struct *work)
-{
-	struct sci_port *s = container_of(work, struct sci_port, work_tx);
-	struct dma_async_tx_descriptor *desc;
-	struct dma_chan *chan = s->chan_tx;
-	struct uart_port *port = &s->port;
-	struct circ_buf *xmit = &port->state->xmit;
-	struct scatterlist *sg = &s->sg_tx;
-
-	/*
-	 * DMA is idle now.
-	 * Port xmit buffer is already mapped, and it is one page... Just adjust
-	 * offsets and lengths. Since it is a circular buffer, we have to
-	 * transmit till the end, and then the rest. Take the port lock to get a
-	 * consistent xmit buffer state.
-	 */
-	spin_lock_irq(&port->lock);
-	sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
-	sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
-		sg->offset;
-	sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
-		CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
-	spin_unlock_irq(&port->lock);
-
-	BUG_ON(!sg_dma_len(sg));
-
-	desc = dmaengine_prep_slave_sg(chan,
-			sg, s->sg_len_tx, DMA_MEM_TO_DEV,
-			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	if (!desc) {
-		/* switch to PIO */
-		sci_tx_dma_release(s, true);
-		return;
-	}
-
-	dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
-
-	spin_lock_irq(&port->lock);
-	s->desc_tx = desc;
-	desc->callback = sci_dma_tx_complete;
-	desc->callback_param = s;
-	spin_unlock_irq(&port->lock);
-	s->cookie_tx = desc->tx_submit(desc);
-	if (s->cookie_tx < 0) {
-		dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
-		/* switch to PIO */
-		sci_tx_dma_release(s, true);
-		return;
-	}
-
-	dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
-		__func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
-
-	dma_async_issue_pending(chan);
-}
-#endif
-
-static void sci_start_tx(struct uart_port *port)
-{
-	struct sci_port *s = to_sci_port(port);
-	unsigned short ctrl;
-
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-		u16 new, scr = serial_port_in(port, SCSCR);
-		if (s->chan_tx)
-			new = scr | SCSCR_TDRQE;
-		else
-			new = scr & ~SCSCR_TDRQE;
-		if (new != scr)
-			serial_port_out(port, SCSCR, new);
-	}
-
-	if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
-	    s->cookie_tx < 0) {
-		s->cookie_tx = 0;
-		schedule_work(&s->work_tx);
-	}
-#endif
-
-	if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-		/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
-		ctrl = serial_port_in(port, SCSCR);
-		serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
-	}
-}
-
-static void sci_stop_tx(struct uart_port *port)
-{
-	unsigned short ctrl;
-
-	/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
-	ctrl = serial_port_in(port, SCSCR);
-
-	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
-		ctrl &= ~SCSCR_TDRQE;
-
-	ctrl &= ~SCSCR_TIE;
-
-	serial_port_out(port, SCSCR, ctrl);
-}
-
-static void sci_start_rx(struct uart_port *port)
-{
-	unsigned short ctrl;
-
-	ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
-
-	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
-		ctrl &= ~SCSCR_RDRQE;
-
-	serial_port_out(port, SCSCR, ctrl);
-}
-
-static void sci_stop_rx(struct uart_port *port)
-{
-	unsigned short ctrl;
-
-	ctrl = serial_port_in(port, SCSCR);
-
-	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
-		ctrl &= ~SCSCR_RDRQE;
-
-	ctrl &= ~port_rx_irq_mask(port);
-
-	serial_port_out(port, SCSCR, ctrl);
-}
-
 static void sci_break_ctl(struct uart_port *port, int break_state)
 {
 	struct sci_port *s = to_sci_port(port);
-	struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
+	const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
 	unsigned short scscr, scsptr;
 
 	/* check wheter the port has SCSPTR */
@@ -1630,142 +1818,6 @@
 	serial_port_out(port, SCSCR, scscr);
 }
 
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-static bool filter(struct dma_chan *chan, void *slave)
-{
-	struct sh_dmae_slave *param = slave;
-
-	dev_dbg(chan->device->dev, "%s: slave ID %d\n",
-		__func__, param->shdma_slave.slave_id);
-
-	chan->private = &param->shdma_slave;
-	return true;
-}
-
-static void rx_timer_fn(unsigned long arg)
-{
-	struct sci_port *s = (struct sci_port *)arg;
-	struct uart_port *port = &s->port;
-	u16 scr = serial_port_in(port, SCSCR);
-
-	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-		scr &= ~SCSCR_RDRQE;
-		enable_irq(s->irqs[SCIx_RXI_IRQ]);
-	}
-	serial_port_out(port, SCSCR, scr | SCSCR_RIE);
-	dev_dbg(port->dev, "DMA Rx timed out\n");
-	schedule_work(&s->work_rx);
-}
-
-static void sci_request_dma(struct uart_port *port)
-{
-	struct sci_port *s = to_sci_port(port);
-	struct sh_dmae_slave *param;
-	struct dma_chan *chan;
-	dma_cap_mask_t mask;
-	int nent;
-
-	dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
-
-	if (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0)
-		return;
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	param = &s->param_tx;
-
-	/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
-	param->shdma_slave.slave_id = s->cfg->dma_slave_tx;
-
-	s->cookie_tx = -EINVAL;
-	chan = dma_request_channel(mask, filter, param);
-	dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
-	if (chan) {
-		s->chan_tx = chan;
-		sg_init_table(&s->sg_tx, 1);
-		/* UART circular tx buffer is an aligned page. */
-		BUG_ON((uintptr_t)port->state->xmit.buf & ~PAGE_MASK);
-		sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
-			    UART_XMIT_SIZE,
-			    (uintptr_t)port->state->xmit.buf & ~PAGE_MASK);
-		nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
-		if (!nent)
-			sci_tx_dma_release(s, false);
-		else
-			dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n",
-				__func__,
-				sg_dma_len(&s->sg_tx), port->state->xmit.buf,
-				&sg_dma_address(&s->sg_tx));
-
-		s->sg_len_tx = nent;
-
-		INIT_WORK(&s->work_tx, work_fn_tx);
-	}
-
-	param = &s->param_rx;
-
-	/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
-	param->shdma_slave.slave_id = s->cfg->dma_slave_rx;
-
-	chan = dma_request_channel(mask, filter, param);
-	dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
-	if (chan) {
-		dma_addr_t dma[2];
-		void *buf[2];
-		int i;
-
-		s->chan_rx = chan;
-
-		s->buf_len_rx = 2 * max(16, (int)port->fifosize);
-		buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2,
-					    &dma[0], GFP_KERNEL);
-
-		if (!buf[0]) {
-			dev_warn(port->dev,
-				 "failed to allocate dma buffer, using PIO\n");
-			sci_rx_dma_release(s, true);
-			return;
-		}
-
-		buf[1] = buf[0] + s->buf_len_rx;
-		dma[1] = dma[0] + s->buf_len_rx;
-
-		for (i = 0; i < 2; i++) {
-			struct scatterlist *sg = &s->sg_rx[i];
-
-			sg_init_table(sg, 1);
-			sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
-				    (uintptr_t)buf[i] & ~PAGE_MASK);
-			sg_dma_address(sg) = dma[i];
-		}
-
-		INIT_WORK(&s->work_rx, work_fn_rx);
-		setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
-
-		sci_submit_rx(s);
-	}
-}
-
-static void sci_free_dma(struct uart_port *port)
-{
-	struct sci_port *s = to_sci_port(port);
-
-	if (s->chan_tx)
-		sci_tx_dma_release(s, false);
-	if (s->chan_rx)
-		sci_rx_dma_release(s, false);
-}
-#else
-static inline void sci_request_dma(struct uart_port *port)
-{
-}
-
-static inline void sci_free_dma(struct uart_port *port)
-{
-}
-#endif
-
 static int sci_startup(struct uart_port *port)
 {
 	struct sci_port *s = to_sci_port(port);
@@ -1800,6 +1852,14 @@
 	sci_stop_tx(port);
 	spin_unlock_irqrestore(&port->lock, flags);
 
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	if (s->chan_rx) {
+		dev_dbg(port->dev, "%s(%d) deleting rx_timer\n", __func__,
+			port->line);
+		del_timer_sync(&s->rx_timer);
+	}
+#endif
+
 	sci_free_dma(port);
 	sci_free_irq(s);
 }
@@ -1892,7 +1952,7 @@
 
 static void sci_reset(struct uart_port *port)
 {
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 	unsigned int status;
 
 	do {
@@ -1910,7 +1970,7 @@
 			    struct ktermios *old)
 {
 	struct sci_port *s = to_sci_port(port);
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 	unsigned int baud, smr_val = 0, max_baud, cks = 0;
 	int t = -1;
 	unsigned int srr = 15;
@@ -1951,7 +2011,7 @@
 
 	sci_reset(port);
 
-	smr_val |= serial_port_in(port, SCSMR) & 3;
+	smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
 
 	uart_update_timeout(port, termios->c_cflag, baud);
 
@@ -1996,13 +2056,13 @@
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 	/*
 	 * Calculate delay for 2 DMA buffers (4 FIFO).
-	 * See drivers/serial/serial_core.c::uart_update_timeout(). With 10
-	 * bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
-	 * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)."
-	 * Then below we calculate 5 jiffies (20ms) for 2 DMA buffers (4 FIFO
-	 * sizes), but when performing a faster transfer, value obtained by
-	 * this formula is may not enough. Therefore, if value is smaller than
-	 * 20msec, this sets 20msec as timeout of DMA.
+	 * See serial_core.c::uart_update_timeout().
+	 * With 10 bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above
+	 * function calculates 1 jiffie for the data plus 5 jiffies for the
+	 * "slop(e)." Then below we calculate 5 jiffies (20ms) for 2 DMA
+	 * buffers (4 FIFO sizes), but when performing a faster transfer, the
+	 * value obtained by this formula is too small. Therefore, if the value
+	 * is smaller than 20ms, use 20ms as the timeout value for DMA.
 	 */
 	if (s->chan_rx) {
 		unsigned int bits;
@@ -2187,7 +2247,6 @@
 {
 	struct uart_port *port = &sci_port->port;
 	const struct resource *res;
-	unsigned int sampling_rate;
 	unsigned int i;
 	int ret;
 
@@ -2232,37 +2291,37 @@
 		port->fifosize = 256;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sampling_rate = 16;
+		sci_port->sampling_rate = 16;
 		break;
 	case PORT_HSCIF:
 		port->fifosize = 128;
-		sampling_rate = 0;
 		sci_port->overrun_reg = SCLSR;
 		sci_port->overrun_mask = SCLSR_ORER;
+		sci_port->sampling_rate = 0;
 		break;
 	case PORT_SCIFA:
 		port->fifosize = 64;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sampling_rate = 16;
+		sci_port->sampling_rate = 16;
 		break;
 	case PORT_SCIF:
 		port->fifosize = 16;
 		if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
 			sci_port->overrun_reg = SCxSR;
 			sci_port->overrun_mask = SCIFA_ORER;
-			sampling_rate = 16;
+			sci_port->sampling_rate = 16;
 		} else {
 			sci_port->overrun_reg = SCLSR;
 			sci_port->overrun_mask = SCLSR_ORER;
-			sampling_rate = 32;
+			sci_port->sampling_rate = 32;
 		}
 		break;
 	default:
 		port->fifosize = 1;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCI_ORER;
-		sampling_rate = 32;
+		sci_port->sampling_rate = 32;
 		break;
 	}
 
@@ -2270,8 +2329,8 @@
 	 * match the SoC datasheet, this should be investigated. Let platform
 	 * data override the sampling rate for now.
 	 */
-	sci_port->sampling_rate = p->sampling_rate ? p->sampling_rate
-				: sampling_rate;
+	if (p->sampling_rate)
+		sci_port->sampling_rate = p->sampling_rate;
 
 	if (!early) {
 		sci_port->iclk = clk_get(&dev->dev, "sci_ick");
@@ -2303,15 +2362,22 @@
 	/*
 	 * Establish some sensible defaults for the error detection.
 	 */
-	sci_port->error_mask = (p->type == PORT_SCI) ?
-			SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK;
+	if (p->type == PORT_SCI) {
+		sci_port->error_mask = SCI_DEFAULT_ERROR_MASK;
+		sci_port->error_clear = SCI_ERROR_CLEAR;
+	} else {
+		sci_port->error_mask = SCIF_DEFAULT_ERROR_MASK;
+		sci_port->error_clear = SCIF_ERROR_CLEAR;
+	}
 
 	/*
 	 * Make the error mask inclusive of overrun detection, if
 	 * supported.
 	 */
-	if (sci_port->overrun_reg == SCxSR)
+	if (sci_port->overrun_reg == SCxSR) {
 		sci_port->error_mask |= sci_port->overrun_mask;
+		sci_port->error_clear &= ~sci_port->overrun_mask;
+	}
 
 	port->type		= p->type;
 	port->flags		= UPF_FIXED_PORT | p->flags;
@@ -2564,10 +2630,8 @@
 	info = match->data;
 
 	p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
-	if (!p) {
-		dev_err(&pdev->dev, "failed to allocate DT config data\n");
+	if (!p)
 		return NULL;
-	}
 
 	/* Get the line number for the aliases node. */
 	id = of_alias_get_id(np, "serial");
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index 3393f67..bf69bbd 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -54,10 +54,10 @@
 
 #define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
 
-#define SCI_RDxF_CLEAR	~(SCI_RESERVED | SCI_RDRF)
-#define SCI_ERROR_CLEAR	~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER)
-#define SCI_TDxE_CLEAR	~(SCI_RESERVED | SCI_TEND | SCI_TDRE)
-#define SCI_BREAK_CLEAR	~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER)
+#define SCI_RDxF_CLEAR	(u32)(~(SCI_RESERVED | SCI_RDRF))
+#define SCI_ERROR_CLEAR	(u32)(~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER))
+#define SCI_TDxE_CLEAR	(u32)(~(SCI_RESERVED | SCI_TEND | SCI_TDRE))
+#define SCI_BREAK_CLEAR	(u32)(~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER))
 
 /* SCxSR (Serial Status Register) on SCIF, SCIFA, SCIFB, HSCIF */
 #define SCIF_ER		BIT(7)	/* Receive Error */
@@ -76,10 +76,10 @@
 
 #define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_BRK | SCIF_ER)
 
-#define SCIF_RDxF_CLEAR		~(SCIF_DR | SCIF_RDF)
-#define SCIF_ERROR_CLEAR	~(SCIFA_ORER | SCIF_PER | SCIF_FER | SCIF_ER)
-#define SCIF_TDxE_CLEAR		~(SCIF_TDFE)
-#define SCIF_BREAK_CLEAR	~(SCIF_PER | SCIF_FER | SCIF_BRK)
+#define SCIF_RDxF_CLEAR		(u32)(~(SCIF_DR | SCIF_RDF))
+#define SCIF_ERROR_CLEAR	(u32)(~(SCIF_PER | SCIF_FER | SCIF_ER))
+#define SCIF_TDxE_CLEAR		(u32)(~(SCIF_TDFE))
+#define SCIF_BREAK_CLEAR	(u32)(~(SCIF_PER | SCIF_FER | SCIF_BRK))
 
 /* SCFCR (FIFO Control Register) */
 #define SCFCR_MCE	BIT(3)	/* Modem Control Enable */
@@ -119,28 +119,11 @@
 
 #define SCxSR_ERRORS(port)	(to_sci_port(port)->error_mask)
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_R8A7740)
-
-# define SCxSR_RDxF_CLEAR(port) \
-	(serial_port_in(port, SCxSR) & SCIF_RDxF_CLEAR)
-# define SCxSR_ERROR_CLEAR(port) \
-	(serial_port_in(port, SCxSR) & SCIF_ERROR_CLEAR)
-# define SCxSR_TDxE_CLEAR(port) \
-	(serial_port_in(port, SCxSR) & SCIF_TDxE_CLEAR)
-# define SCxSR_BREAK_CLEAR(port) \
-	(serial_port_in(port, SCxSR) & SCIF_BREAK_CLEAR)
-#else
-# define SCxSR_RDxF_CLEAR(port) \
-	((((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR) & 0xff)
-# define SCxSR_ERROR_CLEAR(port) \
-	((((port)->type == PORT_SCI) ? SCI_ERROR_CLEAR : SCIF_ERROR_CLEAR) & 0xff)
-# define SCxSR_TDxE_CLEAR(port) \
-	((((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR) & 0xff)
-# define SCxSR_BREAK_CLEAR(port) \
-	((((port)->type == PORT_SCI) ? SCI_BREAK_CLEAR : SCIF_BREAK_CLEAR) & 0xff)
-#endif
-
+#define SCxSR_RDxF_CLEAR(port) \
+	(((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR)
+#define SCxSR_ERROR_CLEAR(port) \
+	(to_sci_port(port)->error_clear)
+#define SCxSR_TDxE_CLEAR(port) \
+	(((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR)
+#define SCxSR_BREAK_CLEAR(port) \
+	(((port)->type == PORT_SCI) ? SCI_BREAK_CLEAR : SCIF_BREAK_CLEAR)
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 3866516..9dbae01 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -782,6 +782,7 @@
 	{.compatible = "sprd,sc9836-uart",},
 	{}
 };
+MODULE_DEVICE_TABLE(of, serial_ids);
 
 static struct platform_driver sprd_platform_driver = {
 	.probe		= sprd_probe,
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index d625664..2d78cb3 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -430,7 +430,7 @@
  */
 static int asc_startup(struct uart_port *port)
 {
-	if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND,
+	if (request_irq(port->irq, asc_interrupt, 0,
 			asc_port_name(port), port)) {
 		dev_err(port->dev, "cannot allocate irq.\n");
 		return -ENODEV;
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index e3de9c6..f89d1f7 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -322,8 +322,7 @@
 	u32 val;
 	int ret;
 
-	ret = request_irq(port->irq, stm32_interrupt, IRQF_NO_SUSPEND,
-			  name, port);
+	ret = request_irq(port->irq, stm32_interrupt, 0, name, port);
 	if (ret)
 		return ret;
 
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 2fac712..6188059 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3314,12 +3314,11 @@
 					-EAGAIN : -ERESTARTSYS;
 			break;
 		}
-		
+
 		dcd = tty_port_carrier_raised(&info->port);
-		
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
- 			break;
-			
+		if (do_clocal || dcd)
+			break;
+
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			break;
@@ -3398,15 +3397,6 @@
 		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 
-	/* If port is closing, signal caller to try again */
-	if (info->port.flags & ASYNC_CLOSING){
-		wait_event_interruptible_tty(tty, info->port.close_wait,
-				     !(info->port.flags & ASYNC_CLOSING));
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-	
 	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 	spin_lock_irqsave(&info->netlock, flags);
@@ -6635,7 +6625,7 @@
 			unsigned char *ptmp = info->intermediate_rxbuffer;
 
 			if ( !(status & RXSTATUS_CRC_ERROR))
-			info->icount.rxok++;
+				info->icount.rxok++;
 			
 			while(copy_count) {
 				int partial_count;
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 0ea8eee..6fc39fb 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -672,15 +672,6 @@
 
 	DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
 
-	/* If port is closing, signal caller to try again */
-	if (info->port.flags & ASYNC_CLOSING){
-		wait_event_interruptible_tty(tty, info->port.close_wait,
-					     !(info->port.flags & ASYNC_CLOSING));
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-
 	mutex_lock(&info->port.mutex);
 	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
@@ -3320,9 +3311,8 @@
 		}
 
 		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
- 			break;
+		if (do_clocal || cd)
+			break;
 
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index 08633a8..fb00a06 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -752,15 +752,6 @@
 		printk("%s(%d):%s open(), old ref count = %d\n",
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 
-	/* If port is closing, signal caller to try again */
-	if (info->port.flags & ASYNC_CLOSING){
-		wait_event_interruptible_tty(tty, info->port.close_wait,
-					     !(info->port.flags & ASYNC_CLOSING));
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-
 	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 	spin_lock_irqsave(&info->netlock, flags);
@@ -3341,9 +3332,8 @@
 		}
 
 		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
- 			break;
+		if (do_clocal || cd)
+			break;
 
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 95b330a..5381a72 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -1003,6 +1003,10 @@
 #define param_check_sysrq_reset_seq(name, p)	\
 	__param_check(name, p, unsigned short)
 
+/*
+ * not really modular, but the easiest way to keep compat with existing
+ * bootargs behaviour is to continue using module_param here.
+ */
 module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq,
 			 &sysrq_reset_seq_len, 0644);
 
@@ -1119,4 +1123,4 @@
 
 	return 0;
 }
-module_init(sysrq_init);
+device_initcall(sysrq_init);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index a660ab1..9a479e6 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -403,7 +403,7 @@
 	 * flush_to_ldisc() sees buffer data.
 	 */
 	smp_store_release(&buf->tail->commit, buf->tail->used);
-	schedule_work(&buf->work);
+	queue_work(system_unbound_wq, &buf->work);
 }
 EXPORT_SYMBOL(tty_schedule_flip);
 
@@ -587,3 +587,13 @@
 {
 	lockdep_set_subclass(&port->buf.lock, TTY_LOCK_SLAVE);
 }
+
+bool tty_buffer_restart_work(struct tty_port *port)
+{
+	return queue_work(system_unbound_wq, &port->buf.work);
+}
+
+bool tty_buffer_cancel_work(struct tty_port *port)
+{
+	return cancel_work_sync(&port->buf.work);
+}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 2eefaa6..0c41dbc 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -390,10 +390,10 @@
  *	Locking: ctrl_lock
  */
 
-int tty_check_change(struct tty_struct *tty)
+int __tty_check_change(struct tty_struct *tty, int sig)
 {
 	unsigned long flags;
-	struct pid *pgrp;
+	struct pid *pgrp, *tty_pgrp;
 	int ret = 0;
 
 	if (current->signal->tty != tty)
@@ -403,33 +403,35 @@
 	pgrp = task_pgrp(current);
 
 	spin_lock_irqsave(&tty->ctrl_lock, flags);
-
-	if (!tty->pgrp) {
-		printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
-		goto out_unlock;
-	}
-	if (pgrp == tty->pgrp)
-		goto out_unlock;
+	tty_pgrp = tty->pgrp;
 	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 
-	if (is_ignored(SIGTTOU))
-		goto out_rcuunlock;
-	if (is_current_pgrp_orphaned()) {
-		ret = -EIO;
-		goto out_rcuunlock;
+	if (tty_pgrp && pgrp != tty->pgrp) {
+		if (is_ignored(sig)) {
+			if (sig == SIGTTIN)
+				ret = -EIO;
+		} else if (is_current_pgrp_orphaned())
+			ret = -EIO;
+		else {
+			kill_pgrp(pgrp, sig, 1);
+			set_thread_flag(TIF_SIGPENDING);
+			ret = -ERESTARTSYS;
+		}
 	}
-	kill_pgrp(pgrp, SIGTTOU, 1);
 	rcu_read_unlock();
-	set_thread_flag(TIF_SIGPENDING);
-	ret = -ERESTARTSYS;
-	return ret;
-out_unlock:
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-out_rcuunlock:
-	rcu_read_unlock();
+
+	if (!tty_pgrp) {
+		pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n",
+			tty_name(tty), sig);
+	}
+
 	return ret;
 }
 
+int tty_check_change(struct tty_struct *tty)
+{
+	return __tty_check_change(tty, SIGTTOU);
+}
 EXPORT_SYMBOL(tty_check_change);
 
 static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
@@ -1198,11 +1200,9 @@
 	if (tty) {
 		mutex_lock(&tty->atomic_write_lock);
 		tty_lock(tty);
-		if (tty->ops->write && tty->count > 0) {
-			tty_unlock(tty);
+		if (tty->ops->write && tty->count > 0)
 			tty->ops->write(tty, msg, strlen(msg));
-		} else
-			tty_unlock(tty);
+		tty_unlock(tty);
 		tty_write_unlock(tty);
 	}
 	return;
@@ -1689,7 +1689,7 @@
 	tty->port->itty = NULL;
 	if (tty->link)
 		tty->link->port->itty = NULL;
-	cancel_work_sync(&tty->port->buf.work);
+	tty_buffer_cancel_work(tty->port);
 
 	tty_kref_put(tty->link);
 	tty_kref_put(tty);
@@ -2569,7 +2569,6 @@
 	struct pid *pgrp;
 	pid_t pgrp_nr;
 	int retval = tty_check_change(real_tty);
-	unsigned long flags;
 
 	if (retval == -EIO)
 		return -ENOTTY;
@@ -2592,10 +2591,10 @@
 	if (session_of_pgrp(pgrp) != task_session(current))
 		goto out_unlock;
 	retval = 0;
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
+	spin_lock_irq(&tty->ctrl_lock);
 	put_pid(real_tty->pgrp);
 	real_tty->pgrp = get_pid(pgrp);
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+	spin_unlock_irq(&tty->ctrl_lock);
 out_unlock:
 	rcu_read_unlock();
 	return retval;
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 71750cb..5af8f18 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -319,7 +319,7 @@
 
 static inline void __tty_ldisc_unlock(struct tty_struct *tty)
 {
-	return ldsem_up_write(&tty->ldisc_sem);
+	ldsem_up_write(&tty->ldisc_sem);
 }
 
 static int __lockfunc
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 40b3183..482f33f 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -22,7 +22,6 @@
 	memset(port, 0, sizeof(*port));
 	tty_buffer_init(port);
 	init_waitqueue_head(&port->open_wait);
-	init_waitqueue_head(&port->close_wait);
 	init_waitqueue_head(&port->delta_msr_wait);
 	mutex_init(&port->mutex);
 	mutex_init(&port->buf_mutex);
@@ -131,7 +130,7 @@
  */
 void tty_port_destroy(struct tty_port *port)
 {
-	cancel_work_sync(&port->buf.work);
+	tty_buffer_cancel_work(port);
 	tty_buffer_free_all(port);
 }
 EXPORT_SYMBOL(tty_port_destroy);
@@ -363,16 +362,6 @@
 	unsigned long flags;
 	DEFINE_WAIT(wait);
 
-	/* block if port is in the process of being closed */
-	if (port->flags & ASYNC_CLOSING) {
-		wait_event_interruptible_tty(tty, port->close_wait,
-				!(port->flags & ASYNC_CLOSING));
-		if (port->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-	}
-
 	/* if non-blocking mode is set we can pass directly to open unless
 	   the port has just hung up or is in another error state */
 	if (tty->flags & (1 << TTY_IO_ERROR)) {
@@ -423,8 +412,7 @@
 		 * Never ask drivers if CLOCAL is set, this causes troubles
 		 * on some hardware.
 		 */
-		if (!(port->flags & ASYNC_CLOSING) &&
-				(do_clocal || tty_port_carrier_raised(port)))
+		if (do_clocal || tty_port_carrier_raised(port))
 			break;
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
@@ -463,10 +451,7 @@
 	schedule_timeout_interruptible(timeout);
 }
 
-/* Caller holds tty lock.
- * NB: may drop and reacquire tty lock (in tty_wait_until_sent_from_close())
- * so tty and tty port may have changed state (but not hung up or reopened).
- */
+/* Caller holds tty lock. */
 int tty_port_close_start(struct tty_port *port,
 				struct tty_struct *tty, struct file *filp)
 {
@@ -502,7 +487,7 @@
 		if (tty->flow_stopped)
 			tty_driver_flush_buffer(tty);
 		if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-			tty_wait_until_sent_from_close(tty, port->closing_wait);
+			tty_wait_until_sent(tty, port->closing_wait);
 		if (port->drain_delay)
 			tty_port_drain_delay(port, tty);
 	}
@@ -534,7 +519,6 @@
 		wake_up_interruptible(&port->open_wait);
 	}
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-	wake_up_interruptible(&port->close_wait);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 EXPORT_SYMBOL(tty_port_close_end);
@@ -543,10 +527,6 @@
  * tty_port_close
  *
  * Caller holds tty lock
- *
- * NB: may drop and reacquire tty lock (in tty_port_close_start()->
- * tty_wait_until_sent_from_close()) so tty and tty_port may have changed
- * state (but not hung up or reopened).
  */
 void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 							struct file *filp)
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 9cc6a13..f7771d8 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -114,6 +114,7 @@
 	struct gs_buf		port_write_buf;
 	wait_queue_head_t	drain_wait;	/* wait while writes drain */
 	bool                    write_busy;
+	wait_queue_head_t	close_wait;
 
 	/* REVISIT this state ... */
 	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
@@ -883,7 +884,7 @@
 	pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
 			port->port_num, tty, file);
 
-	wake_up(&port->port.close_wait);
+	wake_up(&port->close_wait);
 exit:
 	spin_unlock_irq(&port->port_lock);
 }
@@ -1043,6 +1044,7 @@
 	tty_port_init(&port->port);
 	spin_lock_init(&port->port_lock);
 	init_waitqueue_head(&port->drain_wait);
+	init_waitqueue_head(&port->close_wait);
 
 	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
 
@@ -1073,7 +1075,7 @@
 {
 	tasklet_kill(&port->push);
 	/* wait for old opens to finish */
-	wait_event(port->port.close_wait, gs_closed(port));
+	wait_event(port->close_wait, gs_closed(port));
 	WARN_ON(port->port_usb != NULL);
 	tty_port_destroy(&port->port);
 	kfree(port);
diff --git a/include/linux/dma/hsu.h b/include/linux/dma/hsu.h
index 234393a..79df69d 100644
--- a/include/linux/dma/hsu.h
+++ b/include/linux/dma/hsu.h
@@ -35,14 +35,23 @@
 	unsigned int			length;
 	unsigned int			offset;
 	struct hsu_dma			*hsu;
-	struct hsu_dma_platform_data	*pdata;
 };
 
+#if IS_ENABLED(CONFIG_HSU_DMA)
 /* Export to the internal users */
 irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
 
 /* Export to the platform drivers */
 int hsu_dma_probe(struct hsu_dma_chip *chip);
 int hsu_dma_remove(struct hsu_dma_chip *chip);
+#else
+static inline irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip,
+				      unsigned short nr)
+{
+	return IRQ_NONE;
+}
+static inline int hsu_dma_probe(struct hsu_dma_chip *chip) { return -ENODEV; }
+static inline int hsu_dma_remove(struct hsu_dma_chip *chip) { return 0; }
+#endif /* CONFIG_HSU_DMA */
 
 #endif /* _DMA_HSU_H */
diff --git a/include/linux/n_r3964.h b/include/linux/n_r3964.h
index 5d0b2a1..90a803a 100644
--- a/include/linux/n_r3964.h
+++ b/include/linux/n_r3964.h
@@ -152,9 +152,6 @@
 	unsigned char *rx_buf;            /* ring buffer */
 	unsigned char *tx_buf;
 
-	wait_queue_head_t read_wait;
-	//struct wait_queue *read_wait;
-
 	struct r3964_block_header *rx_first;
 	struct r3964_block_header *rx_last;
 	struct r3964_block_header *tx_first;
@@ -164,8 +161,9 @@
 	unsigned char last_rx;
 	unsigned char bcc;
         unsigned int  blocks_in_rx_queue;
-	  
-	
+
+	struct mutex read_lock;		/* serialize r3964_read */
+
 	struct r3964_client_info *firstClient;
 	unsigned int state;
 	unsigned int flags;
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index bdc0ee8..91b16ad 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -19,12 +19,6 @@
 #include <linux/serial.h>
 #include <linux/platform_data/macb.h>
 
-/*
- * at91: 6 USARTs and one DBGU port (SAM9260)
- * avr32: 4
- */
-#define ATMEL_MAX_UART	7
-
  /* Compact Flash */
 struct at91_cf_data {
 	int	irq_pin;		/* I/O IRQ */
diff --git a/include/linux/platform_data/dma-hsu.h b/include/linux/platform_data/dma-hsu.h
index 8a1f6a4..3453fa6 100644
--- a/include/linux/platform_data/dma-hsu.h
+++ b/include/linux/platform_data/dma-hsu.h
@@ -18,8 +18,4 @@
 	int		chan_id;
 };
 
-struct hsu_dma_platform_data {
-	unsigned short	nr_channels;
-};
-
 #endif /* _PLATFORM_DATA_DMA_HSU_H */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index d072ded..5b04b0a 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -227,7 +227,6 @@
 	int			blocked_open;	/* Waiting to open */
 	int			count;		/* Usage count */
 	wait_queue_head_t	open_wait;	/* Open waiters */
-	wait_queue_head_t	close_wait;	/* Close waiters */
 	wait_queue_head_t	delta_msr_wait;	/* Modem status change */
 	unsigned long		flags;		/* TTY flags ASY_*/
 	unsigned char		console:1,	/* port is a console */
@@ -424,6 +423,7 @@
 			      const char *routine);
 extern const char *tty_name(const struct tty_struct *tty);
 extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
+extern int __tty_check_change(struct tty_struct *tty, int sig);
 extern int tty_check_change(struct tty_struct *tty);
 extern void __stop_tty(struct tty_struct *tty);
 extern void stop_tty(struct tty_struct *tty);
@@ -467,6 +467,8 @@
 extern void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
 extern void tty_buffer_init(struct tty_port *port);
 extern void tty_buffer_set_lock_subclass(struct tty_port *port);
+extern bool tty_buffer_restart_work(struct tty_port *port);
+extern bool tty_buffer_cancel_work(struct tty_port *port);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
 extern void tty_termios_encode_baud_rate(struct ktermios *termios,
@@ -656,50 +658,6 @@
 extern void __lockfunc tty_lock_slave(struct tty_struct *tty);
 extern void __lockfunc tty_unlock_slave(struct tty_struct *tty);
 extern void tty_set_lock_subclass(struct tty_struct *tty);
-/*
- * this shall be called only from where BTM is held (like close)
- *
- * We need this to ensure nobody waits for us to finish while we are waiting.
- * Without this we were encountering system stalls.
- *
- * This should be indeed removed with BTM removal later.
- *
- * Locking: BTM required. Nobody is allowed to hold port->mutex.
- */
-static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
-		long timeout)
-{
-	tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */
-	tty_wait_until_sent(tty, timeout);
-	tty_lock(tty);
-}
-
-/*
- * wait_event_interruptible_tty -- wait for a condition with the tty lock held
- *
- * The condition we are waiting for might take a long time to
- * become true, or might depend on another thread taking the
- * BTM. In either case, we need to drop the BTM to guarantee
- * forward progress. This is a leftover from the conversion
- * from the BKL and should eventually get removed as the BTM
- * falls out of use.
- *
- * Do not use in new code.
- */
-#define wait_event_interruptible_tty(tty, wq, condition)		\
-({									\
-	int __ret = 0;							\
-	if (!(condition))						\
-		__ret = __wait_event_interruptible_tty(tty, wq,		\
-						       condition);	\
-	__ret;								\
-})
-
-#define __wait_event_interruptible_tty(tty, wq, condition)		\
-	___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,		\
-			tty_unlock(tty);				\
-			schedule();					\
-			tty_lock(tty))
 
 #ifdef CONFIG_PROC_FS
 extern void proc_tty_register_driver(struct tty_driver *);
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 683346d..a423770 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -335,8 +335,7 @@
 		 * specified, we cannot return before the IrCOMM link is
 		 * ready
 		 */
-		if (!test_bit(ASYNCB_CLOSING, &port->flags) &&
-		    (do_clocal || tty_port_carrier_raised(port)) &&
+		if ((do_clocal || tty_port_carrier_raised(port)) &&
 		    self->state == IRCOMM_TTY_READY)
 		{
 			break;
@@ -443,34 +442,6 @@
 	/* Not really used by us, but lets do it anyway */
 	self->port.low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
-	/*
-	 * If the port is the middle of closing, bail out now
-	 */
-	if (test_bit(ASYNCB_CLOSING, &self->port.flags)) {
-
-		/* Hm, why are we blocking on ASYNC_CLOSING if we
-		 * do return -EAGAIN/-ERESTARTSYS below anyway?
-		 * IMHO it's either not needed in the first place
-		 * or for some reason we need to make sure the async
-		 * closing has been finished - if so, wouldn't we
-		 * probably better sleep uninterruptible?
-		 */
-
-		if (wait_event_interruptible(self->port.close_wait,
-				!test_bit(ASYNCB_CLOSING, &self->port.flags))) {
-			net_warn_ratelimited("%s - got signal while blocking on ASYNC_CLOSING!\n",
-					     __func__);
-			return -ERESTARTSYS;
-		}
-
-#ifdef SERIAL_DO_RESTART
-		return (self->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-
 	/* Check if this is a "normal" ircomm device, or an irlpt device */
 	if (self->line < 0x10) {
 		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;