Pārlūkot izejas kodu

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
  ...
Linus Torvalds 9 gadi atpakaļ
vecāks
revīzija
fd0d351de7
82 mainītis faili ar 2734 papildinājumiem un 1941 dzēšanām
  1. 2 1
      Documentation/devicetree/bindings/serial/ingenic,uart.txt
  2. 1 1
      Documentation/devicetree/bindings/serial/pl011.txt
  3. 6 0
      Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt
  4. 2 0
      Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
  5. 3 0
      Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
  6. 7 0
      Documentation/kernel-parameters.txt
  7. 9 1
      Documentation/serial/driver
  8. 39 21
      Documentation/serial/tty.txt
  9. 55 0
      arch/arm64/include/asm/dcc.h
  10. 0 9
      drivers/char/pcmcia/synclink_cs.c
  11. 2 7
      drivers/dma/hsu/Kconfig
  12. 7 17
      drivers/dma/hsu/hsu.c
  13. 1 0
      drivers/dma/hsu/hsu.h
  14. 1 1
      drivers/dma/hsu/pci.c
  15. 1 1
      drivers/isdn/i4l/isdn_tty.c
  16. 0 9
      drivers/tty/cyclades.c
  17. 1 1
      drivers/tty/hvc/Kconfig
  18. 2 18
      drivers/tty/hvc/hvc_console.c
  19. 11 4
      drivers/tty/hvc/hvc_dcc.c
  20. 1 1
      drivers/tty/hvc/hvcs.c
  21. 3 36
      drivers/tty/mips_ejtag_fdc.c
  22. 16 12
      drivers/tty/n_r3964.c
  23. 3 29
      drivers/tty/n_tty.c
  24. 5 2
      drivers/tty/pty.c
  25. 0 13
      drivers/tty/rocket.c
  26. 2 3
      drivers/tty/serial/68328serial.c
  27. 20 6
      drivers/tty/serial/8250/8250_core.c
  28. 0 6
      drivers/tty/serial/8250/8250_dma.c
  29. 132 156
      drivers/tty/serial/8250/8250_dw.c
  30. 4 0
      drivers/tty/serial/8250/8250_early.c
  31. 84 4
      drivers/tty/serial/8250/8250_ingenic.c
  32. 326 0
      drivers/tty/serial/8250/8250_mid.c
  33. 5 3
      drivers/tty/serial/8250/8250_omap.c
  34. 7 222
      drivers/tty/serial/8250/8250_pci.c
  35. 49 37
      drivers/tty/serial/8250/8250_port.c
  36. 18 7
      drivers/tty/serial/8250/Kconfig
  37. 1 0
      drivers/tty/serial/8250/Makefile
  38. 7 5
      drivers/tty/serial/Kconfig
  39. 2 24
      drivers/tty/serial/altera_uart.c
  40. 2 2
      drivers/tty/serial/amba-pl011.c
  41. 1 0
      drivers/tty/serial/apbuart.c
  42. 16 11
      drivers/tty/serial/atmel_serial.c
  43. 1 1
      drivers/tty/serial/clps711x.c
  44. 1 0
      drivers/tty/serial/cpm_uart/cpm_uart_core.c
  45. 1 33
      drivers/tty/serial/crisv10.c
  46. 39 0
      drivers/tty/serial/fsl_lpuart.c
  47. 103 72
      drivers/tty/serial/imx.c
  48. 4 3
      drivers/tty/serial/lpc32xx_hs.c
  49. 15 8
      drivers/tty/serial/men_z135_uart.c
  50. 7 0
      drivers/tty/serial/mpc52xx_uart.c
  51. 6 35
      drivers/tty/serial/mpsc.c
  52. 570 52
      drivers/tty/serial/msm_serial.c
  53. 31 22
      drivers/tty/serial/msm_serial.h
  54. 1 1
      drivers/tty/serial/mxs-auart.c
  55. 10 0
      drivers/tty/serial/of_serial.c
  56. 2 0
      drivers/tty/serial/omap-serial.c
  57. 21 45
      drivers/tty/serial/samsung.c
  58. 6 1
      drivers/tty/serial/sc16is7xx.c
  59. 28 66
      drivers/tty/serial/serial-tegra.c
  60. 6 3
      drivers/tty/serial/serial_core.c
  61. 129 4
      drivers/tty/serial/serial_mctrl_gpio.c
  62. 38 2
      drivers/tty/serial/serial_mctrl_gpio.h
  63. 762 698
      drivers/tty/serial/sh-sci.c
  64. 16 33
      drivers/tty/serial/sh-sci.h
  65. 1 0
      drivers/tty/serial/sprd_serial.c
  66. 1 1
      drivers/tty/serial/st-asc.c
  67. 1 2
      drivers/tty/serial/stm32-usart.c
  68. 5 15
      drivers/tty/synclink.c
  69. 2 12
      drivers/tty/synclink_gt.c
  70. 2 12
      drivers/tty/synclinkmp.c
  71. 5 1
      drivers/tty/sysrq.c
  72. 11 1
      drivers/tty/tty_buffer.c
  73. 29 30
      drivers/tty/tty_io.c
  74. 1 1
      drivers/tty/tty_ldisc.c
  75. 4 24
      drivers/tty/tty_port.c
  76. 4 2
      drivers/usb/gadget/function/u_serial.c
  77. 10 1
      include/linux/dma/hsu.h
  78. 3 5
      include/linux/n_r3964.h
  79. 0 6
      include/linux/platform_data/atmel.h
  80. 0 4
      include/linux/platform_data/dma-hsu.h
  81. 3 45
      include/linux/tty.h
  82. 1 30
      net/irda/ircomm/ircomm_tty.c

+ 2 - 1
Documentation/devicetree/bindings/serial/ingenic,uart.txt

@@ -1,7 +1,8 @@
 * Ingenic SoC UART
 * Ingenic SoC UART
 
 
 Required properties:
 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.
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
 - interrupts : should contain uart interrupt.
 - clocks : phandles to the module & baud clocks.
 - clocks : phandles to the module & baud clocks.

+ 1 - 1
Documentation/devicetree/bindings/serial/pl011.txt

@@ -19,7 +19,7 @@ Optional properties:
 	   must correspond to the PCLK clocking the internal logic
 	   must correspond to the PCLK clocking the internal logic
 	   of the block. Just listing one clock (the first one) is
 	   of the block. Just listing one clock (the first one) is
 	   deprecated.
 	   deprecated.
-- clocks-names:
+- clock-names:
 	   When present, the first clock listed must be named
 	   When present, the first clock listed must be named
 	   "uartclk" and the second clock listed must be named
 	   "uartclk" and the second clock listed must be named
 	   "apb_pclk"
 	   "apb_pclk"

+ 6 - 0
Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt

@@ -26,6 +26,12 @@ Required properties:
 Optional properties:
 Optional properties:
 - dmas: Should contain dma specifiers for transmit and receive channels
 - dmas: Should contain dma specifiers for transmit and receive channels
 - dma-names: Should contain "tx" for transmit and "rx" for 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.
 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
 The alias serialN will result in the UART being assigned port N.  If any

+ 2 - 0
Documentation/devicetree/bindings/serial/renesas,sci-serial.txt

@@ -23,6 +23,8 @@ Required properties:
     - "renesas,scifa-r8a7794" for R8A7794 (R-Car E2) SCIFA compatible UART.
     - "renesas,scifa-r8a7794" for R8A7794 (R-Car E2) SCIFA compatible UART.
     - "renesas,scifb-r8a7794" for R8A7794 (R-Car E2) SCIFB 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,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,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
     - "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART.
     - "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART.
     - "renesas,scif" for generic SCIF compatible UART.
     - "renesas,scif" for generic SCIF compatible UART.

+ 3 - 0
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt

@@ -15,6 +15,9 @@ The supplying peripheral clock can also be handled, needing a second property
 	Required elements: "baudclk", "apb_pclk"
 	Required elements: "baudclk", "apb_pclk"
 
 
 Optional properties:
 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.
 - resets : phandle to the parent reset controller.
 - reg-shift : quantity to shift the register offsets by.  If this property is
 - reg-shift : quantity to shift the register offsets by.  If this property is
   not present then the register offsets are not shifted.
   not present then the register offsets are not shifted.

+ 7 - 0
Documentation/kernel-parameters.txt

@@ -1024,6 +1024,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			serial port must already be setup and configured.
 			serial port must already be setup and configured.
 			Options are not yet supported.
 			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=	[X86,SH,BLACKFIN,ARM,M68k]
 			earlyprintk=vga
 			earlyprintk=vga
 			earlyprintk=efi
 			earlyprintk=efi

+ 9 - 1
Documentation/serial/driver

@@ -439,11 +439,13 @@ Modem control lines via GPIO
 
 
 Some helpers are provided in order to set/get modem control lines via GPIO.
 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
 	This will get the {cts,rts,...}-gpios from device tree if they are
 	present and request them, set direction etc, and return an
 	present and request them, set direction etc, and return an
 	allocated structure. devm_* functions are used, so there's no need
 	allocated structure. devm_* functions are used, so there's no need
 	to call mctrl_gpio_free().
 	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):
 mctrl_gpio_free(dev, gpios):
 	This will free the requested gpios in mctrl_gpio_init().
 	This will free the requested gpios in mctrl_gpio_init().
@@ -458,3 +460,9 @@ mctrl_gpio_set(gpios, mctrl):
 
 
 mctrl_gpio_get(gpios, mctrl):
 mctrl_gpio_get(gpios, mctrl):
 	This will update mctrl with the gpios values.
 	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.

+ 39 - 21
Documentation/serial/tty.txt

@@ -39,8 +39,13 @@ TTY side interfaces:
 open()		-	Called when the line discipline is attached to
 open()		-	Called when the line discipline is attached to
 			the terminal. No other call into the line
 			the terminal. No other call into the line
 			discipline for this tty will occur until it
 			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
 close()		-	This is called on a terminal when the line
 			discipline is being unplugged. At the point of
 			discipline is being unplugged. At the point of
@@ -52,9 +57,16 @@ hangup()	-	Called when the tty line is hung up.
 			No further calls into the ldisc code will occur.
 			No further calls into the ldisc code will occur.
 			The return value is ignored. Can sleep.
 			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
 flush_buffer()	-	(optional) May be called at any point between
 			open and close, and instructs the line discipline
 			open and close, and instructs the line discipline
@@ -69,27 +81,33 @@ set_termios()	-	(optional) Called on termios structure changes.
 			termios semaphore so allowed to sleep. Serialized
 			termios semaphore so allowed to sleep. Serialized
 			against itself only.
 			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()		-	Check the status for the poll/select calls. Multiple
-			poll calls may occur in parallel. May sleep.
+poll()		-	(optional) Check the status for the poll/select
+			calls. Multiple poll 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. 
+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.
 
 
-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:
 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.
 write_wakeup()	-	May be called at any point between open and close.
 			The TTY_DO_WRITE_WAKEUP flag indicates if a call
 			The TTY_DO_WRITE_WAKEUP flag indicates if a call

+ 55 - 0
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

+ 0 - 9
drivers/char/pcmcia/synclink_cs.c

@@ -2507,15 +2507,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
 		printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
 		printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
 			 __FILE__, __LINE__, tty->driver->name, port->count);
 			 __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;
 	port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 
 	spin_lock_irqsave(&info->netlock, flags);
 	spin_lock_irqsave(&info->netlock, flags);

+ 2 - 7
drivers/dma/hsu/Kconfig

@@ -5,10 +5,5 @@ config HSU_DMA
 	select DMA_VIRTUAL_CHANNELS
 	select DMA_VIRTUAL_CHANNELS
 
 
 config HSU_DMA_PCI
 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

+ 7 - 17
drivers/dma/hsu/hsu.c

@@ -146,7 +146,7 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
 	u32 sr;
 	u32 sr;
 
 
 	/* Sanity check */
 	/* Sanity check */
-	if (nr >= chip->pdata->nr_channels)
+	if (nr >= chip->hsu->nr_channels)
 		return IRQ_NONE;
 		return IRQ_NONE;
 
 
 	hsuc = &chip->hsu->chan[nr];
 	hsuc = &chip->hsu->chan[nr];
@@ -375,7 +375,6 @@ static void hsu_dma_free_chan_resources(struct dma_chan *chan)
 int hsu_dma_probe(struct hsu_dma_chip *chip)
 int hsu_dma_probe(struct hsu_dma_chip *chip)
 {
 {
 	struct hsu_dma *hsu;
 	struct hsu_dma *hsu;
-	struct hsu_dma_platform_data *pdata = chip->pdata;
 	void __iomem *addr = chip->regs + chip->offset;
 	void __iomem *addr = chip->regs + chip->offset;
 	unsigned short i;
 	unsigned short i;
 	int ret;
 	int ret;
@@ -386,25 +385,16 @@ int hsu_dma_probe(struct hsu_dma_chip *chip)
 
 
 	chip->hsu = hsu;
 	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);
 				 sizeof(*hsu->chan), GFP_KERNEL);
 	if (!hsu->chan)
 	if (!hsu->chan)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	INIT_LIST_HEAD(&hsu->dma.channels);
 	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];
 		struct hsu_dma_chan *hsuc = &hsu->chan[i];
 
 
 		hsuc->vchan.desc_free = hsu_dma_desc_free;
 		hsuc->vchan.desc_free = hsu_dma_desc_free;
@@ -440,7 +430,7 @@ int hsu_dma_probe(struct hsu_dma_chip *chip)
 	if (ret)
 	if (ret)
 		return 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;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(hsu_dma_probe);
 EXPORT_SYMBOL_GPL(hsu_dma_probe);
@@ -452,7 +442,7 @@ int hsu_dma_remove(struct hsu_dma_chip *chip)
 
 
 	dma_async_device_unregister(&hsu->dma);
 	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];
 		struct hsu_dma_chan *hsuc = &hsu->chan[i];
 
 
 		tasklet_kill(&hsuc->vchan.task);
 		tasklet_kill(&hsuc->vchan.task);

+ 1 - 0
drivers/dma/hsu/hsu.h

@@ -107,6 +107,7 @@ struct hsu_dma {
 
 
 	/* channels */
 	/* channels */
 	struct hsu_dma_chan		*chan;
 	struct hsu_dma_chan		*chan;
+	unsigned short			nr_channels;
 };
 };
 
 
 static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)
 static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)

+ 1 - 1
drivers/dma/hsu/pci.c

@@ -31,7 +31,7 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev)
 	irqreturn_t ret = IRQ_NONE;
 	irqreturn_t ret = IRQ_NONE;
 
 
 	dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
 	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)
 		if (dmaisr & 0x1)
 			ret |= hsu_dma_irq(chip, i);
 			ret |= hsu_dma_irq(chip, i);
 		dmaisr >>= 1;
 		dmaisr >>= 1;

+ 1 - 1
drivers/isdn/i4l/isdn_tty.c

@@ -1582,7 +1582,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
 	 * line status register.
 	 * line status register.
 	 */
 	 */
 	if (port->flags & ASYNC_INITIALIZED) {
 	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
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
 		 * has completely drained; this is especially

+ 0 - 9
drivers/tty/cyclades.c

@@ -1576,15 +1576,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
 		current->pid, info->port.count);
 		current->pid, info->port.count);
 #endif
 #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
 	 * Start up serial port
 	 */
 	 */

+ 1 - 1
drivers/tty/hvc/Kconfig

@@ -81,7 +81,7 @@ config HVC_UDBG
 
 
 config HVC_DCC
 config HVC_DCC
        bool "ARM JTAG DCC console"
        bool "ARM JTAG DCC console"
-       depends on ARM
+       depends on ARM || ARM64
        select HVC_DRIVER
        select HVC_DRIVER
        help
        help
          This console uses the JTAG DCC on ARM to create a console under the HVC
          This console uses the JTAG DCC on ARM to create a console under the HVC

+ 2 - 18
drivers/tty/hvc/hvc_console.c

@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/list.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/major.h>
 #include <linux/major.h>
 #include <linux/atomic.h>
 #include <linux/atomic.h>
 #include <linux/sysrq.h>
 #include <linux/sysrq.h>
@@ -418,7 +418,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 		 * there is no buffered data otherwise sleeps on a wait queue
 		 * there is no buffered data otherwise sleeps on a wait queue
 		 * waking periodically to check chars_in_buffer().
 		 * 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 {
 	} else {
 		if (hp->port.count < 0)
 		if (hp->port.count < 0)
 			printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
 			printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
@@ -1005,19 +1005,3 @@ put_tty:
 out:
 out:
 	return err;
 	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);

+ 11 - 4
drivers/tty/hvc/hvc_dcc.c

@@ -70,20 +70,27 @@ static const struct hv_ops hvc_dcc_get_put_ops = {
 
 
 static int __init hvc_dcc_console_init(void)
 static int __init hvc_dcc_console_init(void)
 {
 {
+	int ret;
+
 	if (!hvc_dcc_check())
 	if (!hvc_dcc_check())
 		return -ENODEV;
 		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);
 console_initcall(hvc_dcc_console_init);
 
 
 static int __init hvc_dcc_init(void)
 static int __init hvc_dcc_init(void)
 {
 {
+	struct hvc_struct *p;
+
 	if (!hvc_dcc_check())
 	if (!hvc_dcc_check())
 		return -ENODEV;
 		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);
 device_initcall(hvc_dcc_init);

+ 1 - 1
drivers/tty/hvc/hvcs.c

@@ -1230,7 +1230,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
 		irq = hvcsd->vdev->irq;
 		irq = hvcsd->vdev->irq;
 		spin_unlock_irqrestore(&hvcsd->lock, flags);
 		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
 		 * This line is important because it tells hvcs_open that this

+ 3 - 36
drivers/tty/mips_ejtag_fdc.c

@@ -977,7 +977,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
 	/* Try requesting the IRQ */
 	/* Try requesting the IRQ */
 	if (priv->irq >= 0) {
 	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
 		 * other local interrupts such as the timer which sets
 		 * IRQF_TIMER (including IRQF_NO_SUSPEND).
 		 * IRQF_TIMER (including IRQF_NO_SUSPEND).
 		 *
 		 *
@@ -987,7 +987,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
 		 */
 		 */
 		ret = devm_request_irq(priv->dev, priv->irq, mips_ejtag_fdc_isr,
 		ret = devm_request_irq(priv->dev, priv->irq, mips_ejtag_fdc_isr,
 				       IRQF_PERCPU | IRQF_SHARED |
 				       IRQF_PERCPU | IRQF_SHARED |
-				       IRQF_NO_THREAD | IRQF_NO_SUSPEND,
+				       IRQF_NO_THREAD | IRQF_COND_SUSPEND,
 				       priv->fdc_name, priv);
 				       priv->fdc_name, priv);
 		if (ret)
 		if (ret)
 			priv->irq = -1;
 			priv->irq = -1;
@@ -1048,38 +1048,6 @@ err_destroy_ports:
 	return ret;
 	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)
 static int mips_ejtag_fdc_tty_cpu_down(struct mips_cdmm_device *dev)
 {
 {
 	struct mips_ejtag_fdc_tty *priv = mips_cdmm_get_drvdata(dev);
 	struct mips_ejtag_fdc_tty *priv = mips_cdmm_get_drvdata(dev);
@@ -1152,12 +1120,11 @@ static struct mips_cdmm_driver mips_ejtag_fdc_tty_driver = {
 		.name	= "mips_ejtag_fdc",
 		.name	= "mips_ejtag_fdc",
 	},
 	},
 	.probe		= mips_ejtag_fdc_tty_probe,
 	.probe		= mips_ejtag_fdc_tty_probe,
-	.remove		= mips_ejtag_fdc_tty_remove,
 	.cpu_down	= mips_ejtag_fdc_tty_cpu_down,
 	.cpu_down	= mips_ejtag_fdc_tty_cpu_down,
 	.cpu_up		= mips_ejtag_fdc_tty_cpu_up,
 	.cpu_up		= mips_ejtag_fdc_tty_cpu_up,
 	.id_table	= mips_ejtag_fdc_tty_ids,
 	.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)
 static int __init mips_ejtag_fdc_init_console(void)
 {
 {

+ 16 - 12
drivers/tty/n_r3964.c

@@ -276,7 +276,7 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
 			add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
 			add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
 				error_code, NULL);
 				error_code, NULL);
 		}
 		}
-		wake_up_interruptible(&pInfo->read_wait);
+		wake_up_interruptible(&pInfo->tty->read_wait);
 	}
 	}
 
 
 	spin_lock_irqsave(&pInfo->lock, flags);
 	spin_lock_irqsave(&pInfo->lock, flags);
@@ -542,7 +542,7 @@ static void on_receive_block(struct r3964_info *pInfo)
 				pBlock);
 				pBlock);
 		}
 		}
 	}
 	}
-	wake_up_interruptible(&pInfo->read_wait);
+	wake_up_interruptible(&pInfo->tty->read_wait);
 
 
 	pInfo->state = R3964_IDLE;
 	pInfo->state = R3964_IDLE;
 
 
@@ -978,8 +978,8 @@ static int r3964_open(struct tty_struct *tty)
 	}
 	}
 
 
 	spin_lock_init(&pInfo->lock);
 	spin_lock_init(&pInfo->lock);
+	mutex_init(&pInfo->read_lock);
 	pInfo->tty = tty;
 	pInfo->tty = tty;
-	init_waitqueue_head(&pInfo->read_wait);
 	pInfo->priority = R3964_MASTER;
 	pInfo->priority = R3964_MASTER;
 	pInfo->rx_first = pInfo->rx_last = NULL;
 	pInfo->rx_first = pInfo->rx_last = NULL;
 	pInfo->tx_first = pInfo->tx_last = NULL;
 	pInfo->tx_first = pInfo->tx_last = NULL;
@@ -1045,7 +1045,6 @@ static void r3964_close(struct tty_struct *tty)
 	}
 	}
 
 
 	/* Free buffers: */
 	/* Free buffers: */
-	wake_up_interruptible(&pInfo->read_wait);
 	kfree(pInfo->rx_buf);
 	kfree(pInfo->rx_buf);
 	TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf);
 	TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf);
 	kfree(pInfo->tx_buf);
 	kfree(pInfo->tx_buf);
@@ -1065,7 +1064,16 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 
 
 	TRACE_L("read()");
 	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));
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
 	if (pClient) {
@@ -1077,7 +1085,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 				goto unlock;
 				goto unlock;
 			}
 			}
 			/* block until there is a message: */
 			/* 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)));
 					(pMsg = remove_msg(pInfo, pClient)));
 		}
 		}
 
 
@@ -1107,7 +1115,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 	}
 	}
 	ret = -EPERM;
 	ret = -EPERM;
 unlock:
 unlock:
-	tty_unlock(tty);
+	mutex_unlock(&pInfo->read_lock);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -1156,8 +1164,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
 	pHeader->locks = 0;
 	pHeader->locks = 0;
 	pHeader->owner = NULL;
 	pHeader->owner = NULL;
 
 
-	tty_lock(tty);
-
 	pClient = findClient(pInfo, task_pid(current));
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
 	if (pClient) {
 		pHeader->owner = pClient;
 		pHeader->owner = pClient;
@@ -1175,8 +1181,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
 	add_tx_queue(pInfo, pHeader);
 	add_tx_queue(pInfo, pHeader);
 	trigger_transmit(pInfo);
 	trigger_transmit(pInfo);
 
 
-	tty_unlock(tty);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1227,7 +1231,7 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
 
 
 	pClient = findClient(pInfo, task_pid(current));
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
 	if (pClient) {
-		poll_wait(file, &pInfo->read_wait, wait);
+		poll_wait(file, &tty->read_wait, wait);
 		spin_lock_irqsave(&pInfo->lock, flags);
 		spin_lock_irqsave(&pInfo->lock, flags);
 		pMsg = pClient->first_msg;
 		pMsg = pClient->first_msg;
 		spin_unlock_irqrestore(&pInfo->lock, flags);
 		spin_unlock_irqrestore(&pInfo->lock, flags);

+ 3 - 29
drivers/tty/n_tty.c

@@ -201,7 +201,7 @@ static void n_tty_kick_worker(struct tty_struct *tty)
 		 */
 		 */
 		WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
 		WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
 			       "scheduling buffer work for halted ldisc\n");
 			       "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 @@ static void n_tty_receive_break(struct tty_struct *tty)
 		put_tty_queue('\0', ldata);
 		put_tty_queue('\0', ldata);
 	}
 	}
 	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 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
 			put_tty_queue('\0', ldata);
 			put_tty_queue('\0', ldata);
 	} else
 	} else
 		put_tty_queue(c, ldata);
 		put_tty_queue(c, ldata);
-	if (waitqueue_active(&tty->read_wait))
-		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 }
 }
 
 
 static void
 static void
@@ -2142,37 +2138,15 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
 
 
 static int job_control(struct tty_struct *tty, struct file *file)
 static int job_control(struct tty_struct *tty, struct file *file)
 {
 {
-	struct pid *pgrp;
-
 	/* Job control check -- must be done at start and after
 	/* Job control check -- must be done at start and after
 	   every sleep (POSIX.1 7.1.1.4). */
 	   every sleep (POSIX.1 7.1.1.4). */
 	/* NOTE: not yet done after every sleep pending a thorough
 	/* NOTE: not yet done after every sleep pending a thorough
 	   check of the logic of this change. -- jlc */
 	   check of the logic of this change. -- jlc */
 	/* don't stop on /dev/console */
 	/* 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;
 		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);
 }
 }
 
 
 
 

+ 5 - 2
drivers/tty/pty.c

@@ -7,7 +7,6 @@
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
-
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty.h>
@@ -501,6 +500,10 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
 }
 }
 
 
 static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
 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);
 module_param(legacy_count, int, 0);
 
 
 /*
 /*
@@ -877,4 +880,4 @@ static int __init pty_init(void)
 	unix98_pty_init();
 	unix98_pty_init();
 	return 0;
 	return 0;
 }
 }
-module_init(pty_init);
+device_initcall(pty_init);

+ 0 - 13
drivers/tty/rocket.c

@@ -895,14 +895,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
 	if (!page)
 	if (!page)
 		return -ENOMEM;
 		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.
 	 * We must not sleep from here until the port is marked fully in use.
 	 */
 	 */
@@ -1057,7 +1049,6 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
 	mutex_unlock(&port->mutex);
 	mutex_unlock(&port->mutex);
 	tty_port_tty_set(port, NULL);
 	tty_port_tty_set(port, NULL);
 
 
-	wake_up_interruptible(&port->close_wait);
 	complete_all(&info->close_wait);
 	complete_all(&info->close_wait);
 	atomic_dec(&rp_num_ports_open);
 	atomic_dec(&rp_num_ports_open);
 
 
@@ -1511,10 +1502,6 @@ static void rp_hangup(struct tty_struct *tty)
 #endif
 #endif
 	rp_flush_buffer(tty);
 	rp_flush_buffer(tty);
 	spin_lock_irqsave(&info->port.lock, flags);
 	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)
 	if (info->port.count)
 		atomic_dec(&rp_num_ports_open);
 		atomic_dec(&rp_num_ports_open);
 	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
 	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);

+ 2 - 3
drivers/tty/serial/68328serial.c

@@ -560,8 +560,8 @@ static void rs_fair_output(void)
 	struct m68k_serial *info = &m68k_soft[0];
 	struct m68k_serial *info = &m68k_soft[0];
 	char c;
 	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);
 	local_irq_save(flags);
 	left = info->xmit_cnt;
 	left = info->xmit_cnt;
@@ -1071,7 +1071,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 		wake_up_interruptible(&port->open_wait);
 		wake_up_interruptible(&port->open_wait);
 	}
 	}
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&port->close_wait);
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 }
 }
 
 

+ 20 - 6
drivers/tty/serial/8250/8250_core.c

@@ -569,6 +569,9 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 	for (i = 0; i < nr_uarts; i++) {
 	for (i = 0; i < nr_uarts; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 		struct uart_8250_port *up = &serial8250_ports[i];
 
 
+		if (up->port.type == PORT_8250_CIR)
+			continue;
+
 		if (up->port.dev)
 		if (up->port.dev)
 			continue;
 			continue;
 
 
@@ -1027,13 +1030,24 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 		if (up->dl_write)
 		if (up->dl_write)
 			uart->dl_write = 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;
+		} 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 = uart_add_one_port(&serial8250_reg, &uart->port);
-		if (ret == 0)
-			ret = uart->port.line;
+			ret = 0;
+		}
 	}
 	}
 	mutex_unlock(&serial_mutex);
 	mutex_unlock(&serial_mutex);
 
 

+ 0 - 6
drivers/tty/serial/8250/8250_dma.c

@@ -54,9 +54,6 @@ static void __dma_rx_complete(void *param)
 	struct dma_tx_state	state;
 	struct dma_tx_state	state;
 	int			count;
 	int			count;
 
 
-	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
-				dma->rx_size, DMA_FROM_DEVICE);
-
 	dma->rx_running = 0;
 	dma->rx_running = 0;
 	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
 	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
 
 
@@ -152,9 +149,6 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 
 
 	dma->rx_cookie = dmaengine_submit(desc);
 	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);
 	dma_async_issue_pending(dma->rxchan);
 
 
 	return 0;
 	return 0;

+ 132 - 156
drivers/tty/serial/8250/8250_dw.c

@@ -63,6 +63,9 @@ struct dw8250_data {
 	struct clk		*pclk;
 	struct clk		*pclk;
 	struct reset_control	*rst;
 	struct reset_control	*rst;
 	struct uart_8250_dma	dma;
 	struct uart_8250_dma	dma;
+
+	unsigned int		skip_autocfg:1;
+	unsigned int		uart_16550_compatible:1;
 };
 };
 
 
 #define BYT_PRV_CLK			0x800
 #define BYT_PRV_CLK			0x800
@@ -244,24 +247,77 @@ out:
 	serial8250_do_set_termios(p, termios, old);
 	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;
 	return false;
 }
 }
 
 
-static void dw8250_setup_port(struct uart_8250_port *up)
+static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
+{
+	return param == chan->device->dev->parent;
+}
+
+static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
 {
 {
-	struct uart_port	*p = &up->port;
-	u32			reg = readl(p->membase + DW_UART_UCV);
+	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
 	 * If the Component Version Register returns zero, we know that
 	 * ADDITIONAL_FEATURES are not enabled. No need to go any further.
 	 * ADDITIONAL_FEATURES are not enabled. No need to go any further.
 	 */
 	 */
+	reg = readl(p->membase + DW_UART_UCV);
 	if (!reg)
 	if (!reg)
 		return;
 		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 >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
 
 
 	reg = readl(p->membase + DW_UART_CPR);
 	reg = readl(p->membase + DW_UART_CPR);
@@ -273,7 +329,6 @@ static void dw8250_setup_port(struct uart_8250_port *up)
 		p->type = PORT_16550A;
 		p->type = PORT_16550A;
 		p->flags |= UPF_FIXED_TYPE;
 		p->flags |= UPF_FIXED_TYPE;
 		p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
 		p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
-		up->tx_loadsz = p->fifosize;
 		up->capabilities = UART_CAP_FIFO;
 		up->capabilities = UART_CAP_FIFO;
 	}
 	}
 
 
@@ -281,166 +336,91 @@ static void dw8250_setup_port(struct uart_8250_port *up)
 		up->capabilities |= UART_CAP_AFE;
 		up->capabilities |= UART_CAP_AFE;
 }
 }
 
 
-static int dw8250_probe_of(struct uart_port *p,
-			   struct dw8250_data *data)
+static int dw8250_probe(struct platform_device *pdev)
 {
 {
-	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;
+	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;
 
 
-#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 (!regs) {
+		dev_err(&pdev->dev, "no registers defined\n");
+		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 (irq < 0) {
+		if (irq != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "cannot get irq\n");
+		return irq;
 	}
 	}
 
 
-	if (!of_property_read_u32(np, "reg-shift", &val))
+	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;
+
+	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;
 		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;
+	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 (of_property_read_bool(np, "dcd-override")) {
+	if (device_property_read_bool(p->dev, "dcd-override")) {
 		/* Always report DCD as active */
 		/* Always report DCD as active */
 		data->msr_mask_on |= UART_MSR_DCD;
 		data->msr_mask_on |= UART_MSR_DCD;
 		data->msr_mask_off |= UART_MSR_DDCD;
 		data->msr_mask_off |= UART_MSR_DDCD;
 	}
 	}
 
 
-	if (of_property_read_bool(np, "dsr-override")) {
+	if (device_property_read_bool(p->dev, "dsr-override")) {
 		/* Always report DSR as active */
 		/* Always report DSR as active */
 		data->msr_mask_on |= UART_MSR_DSR;
 		data->msr_mask_on |= UART_MSR_DSR;
 		data->msr_mask_off |= UART_MSR_DDSR;
 		data->msr_mask_off |= UART_MSR_DDSR;
 	}
 	}
 
 
-	if (of_property_read_bool(np, "cts-override")) {
+	if (device_property_read_bool(p->dev, "cts-override")) {
 		/* Always report CTS as active */
 		/* Always report CTS as active */
 		data->msr_mask_on |= UART_MSR_CTS;
 		data->msr_mask_on |= UART_MSR_CTS;
 		data->msr_mask_off |= UART_MSR_DCTS;
 		data->msr_mask_off |= UART_MSR_DCTS;
 	}
 	}
 
 
-	if (of_property_read_bool(np, "ri-override")) {
+	if (device_property_read_bool(p->dev, "ri-override")) {
 		/* Always report Ring indicator as inactive */
 		/* Always report Ring indicator as inactive */
 		data->msr_mask_off |= UART_MSR_RI;
 		data->msr_mask_off |= UART_MSR_RI;
 		data->msr_mask_off |= UART_MSR_TERI;
 		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 dw8250_data *data;
-	int err;
-
-	if (!regs) {
-		dev_err(&pdev->dev, "no registers defined\n");
-		return -EINVAL;
-	}
-
-	if (irq < 0) {
-		if (irq != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "cannot get irq\n");
-		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;
-
-	uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
-					 resource_size(regs));
-	if (!uart.port.membase)
-		return -ENOMEM;
-
-	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->usr_reg = DW_UART_USR;
-
 	/* Always ask for fixed clock rate from a property. */
 	/* 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. */
 	/* If there is separate baudclk, get the rate from it. */
 	data->clk = devm_clk_get(&pdev->dev, "baudclk");
 	data->clk = devm_clk_get(&pdev->dev, "baudclk");
@@ -454,11 +434,11 @@ static int dw8250_probe(struct platform_device *pdev)
 			dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
 			dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
 				 err);
 				 err);
 		else
 		else
-			uart.port.uartclk = clk_get_rate(data->clk);
+			p->uartclk = clk_get_rate(data->clk);
 	}
 	}
 
 
 	/* If no clock rate is defined, fail. */
 	/* If no clock rate is defined, fail. */
-	if (!uart.port.uartclk) {
+	if (!p->uartclk) {
 		dev_err(&pdev->dev, "clock rate not defined\n");
 		dev_err(&pdev->dev, "clock rate not defined\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -484,26 +464,22 @@ static int dw8250_probe(struct platform_device *pdev)
 	if (!IS_ERR(data->rst))
 	if (!IS_ERR(data->rst))
 		reset_control_deassert(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);
 	data->line = serial8250_register_8250_port(&uart);

+ 4 - 0
drivers/tty/serial/8250/8250_early.c

@@ -29,6 +29,8 @@
 #include <linux/tty.h>
 #include <linux/tty.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/console.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_8250.h>
@@ -152,3 +154,5 @@ int __init early_serial8250_setup(struct earlycon_device *device,
 }
 }
 EARLYCON_DECLARE(uart8250, early_serial8250_setup);
 EARLYCON_DECLARE(uart8250, early_serial8250_setup);
 EARLYCON_DECLARE(uart, 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);

+ 84 - 4
drivers/tty/serial/8250/8250_ingenic.c

@@ -21,19 +21,33 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_fdt.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.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 ingenic_uart_data {
 	struct clk	*clk_module;
 	struct clk	*clk_module;
 	struct clk	*clk_baud;
 	struct clk	*clk_baud;
 	int		line;
 	int		line;
 };
 };
 
 
+static const struct of_device_id of_match[];
+
 #define UART_FCR_UME	BIT(4)
 #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 struct earlycon_device *early_device;
 
 
 static uint8_t __init early_in(struct uart_port *port, int offset)
 static uint8_t __init early_in(struct uart_port *port, int offset)
@@ -129,6 +143,8 @@ OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
 
 
 static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
 static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
 {
 {
+	int ier;
+
 	switch (offset) {
 	switch (offset) {
 	case UART_FCR:
 	case UART_FCR:
 		/* UART module enable */
 		/* UART module enable */
@@ -136,9 +152,22 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
 		break;
 		break;
 
 
 	case UART_IER:
 	case UART_IER:
+		/* Enable receive timeout interrupt with the
+		 * receive line status interrupt */
 		value |= (value & 0x4) << 2;
 		value |= (value & 0x4) << 2;
 		break;
 		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:
 	default:
 		break;
 		break;
 	}
 	}
@@ -146,14 +175,45 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
 	writeb(value, p->membase + (offset << p->regshift));
 	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)
 static int ingenic_uart_probe(struct platform_device *pdev)
 {
 {
 	struct uart_8250_port uart = {};
 	struct uart_8250_port uart = {};
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	struct ingenic_uart_data *data;
 	struct ingenic_uart_data *data;
+	const struct ingenic_uart_config *cdata;
+	const struct of_device_id *match;
 	int err, line;
 	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) {
 	if (!regs || !irq) {
 		dev_err(&pdev->dev, "no registers/irq defined\n");
 		dev_err(&pdev->dev, "no registers/irq defined\n");
 		return -EINVAL;
 		return -EINVAL;
@@ -164,14 +224,18 @@ static int ingenic_uart_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	spin_lock_init(&uart.port.lock);
 	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.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
 	uart.port.iotype = UPIO_MEM;
 	uart.port.iotype = UPIO_MEM;
 	uart.port.mapbase = regs->start;
 	uart.port.mapbase = regs->start;
 	uart.port.regshift = 2;
 	uart.port.regshift = 2;
 	uart.port.serial_out = ingenic_uart_serial_out;
 	uart.port.serial_out = ingenic_uart_serial_out;
+	uart.port.serial_in = ingenic_uart_serial_in;
 	uart.port.irq = irq->start;
 	uart.port.irq = irq->start;
 	uart.port.dev = &pdev->dev;
 	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 */
 	/* Check for a fixed line number */
 	line = of_alias_get_id(pdev->dev.of_node, "serial");
 	line = of_alias_get_id(pdev->dev.of_node, "serial");
@@ -241,10 +305,26 @@ static int ingenic_uart_remove(struct platform_device *pdev)
 	return 0;
 	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[] = {
 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 */ }
 	{ /* sentinel */ }
 };
 };
 MODULE_DEVICE_TABLE(of, of_match);
 MODULE_DEVICE_TABLE(of, of_match);

+ 326 - 0
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");

+ 5 - 3
drivers/tty/serial/8250/8250_omap.c

@@ -439,7 +439,6 @@ static void omap_8250_set_termios(struct uart_port *port,
 	priv->xoff = termios->c_cc[VSTOP];
 	priv->xoff = termios->c_cc[VSTOP];
 
 
 	priv->efr = 0;
 	priv->efr = 0;
-	up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY);
 	up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
 	up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
 
 
 	if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
 	if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
@@ -726,6 +725,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
 	struct dma_tx_state     state;
 	struct dma_tx_state     state;
 	int                     count;
 	int                     count;
 	unsigned long		flags;
 	unsigned long		flags;
+	int			ret;
 
 
 	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
 	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
 				dma->rx_size, DMA_FROM_DEVICE);
 				dma->rx_size, DMA_FROM_DEVICE);
@@ -741,8 +741,10 @@ static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
 
 
 	count = dma->rx_size - state.residue;
 	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:
 unlock:
 	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
 	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
 
 

+ 7 - 222
drivers/tty/serial/8250/8250_pci.c

@@ -28,7 +28,6 @@
 
 
 #include <linux/dmaengine.h>
 #include <linux/dmaengine.h>
 #include <linux/platform_data/dma-dw.h>
 #include <linux/platform_data/dma-dw.h>
-#include <linux/platform_data/dma-hsu.h>
 
 
 #include "8250.h"
 #include "8250.h"
 
 
@@ -1508,167 +1507,6 @@ byt_serial_setup(struct serial_private *priv,
 	return ret;
 	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
 static int
 pci_omegapci_setup(struct serial_private *priv,
 pci_omegapci_setup(struct serial_private *priv,
 		      const struct pciserial_board *board,
 		      const struct pciserial_board *board,
@@ -2210,34 +2048,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.setup		= byt_serial_setup,
 		.setup		= byt_serial_setup,
 	},
 	},
-	{
-		.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,
 		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_BSW_UART1,
 		.device		= PCI_DEVICE_ID_INTEL_BSW_UART1,
@@ -3119,8 +2929,6 @@ enum pci_board_num_t {
 	pbn_ADDIDATA_PCIe_8_3906250,
 	pbn_ADDIDATA_PCIe_8_3906250,
 	pbn_ce4100_1_115200,
 	pbn_ce4100_1_115200,
 	pbn_byt,
 	pbn_byt,
-	pbn_pnw,
-	pbn_tng,
 	pbn_qrk,
 	pbn_qrk,
 	pbn_omegapci,
 	pbn_omegapci,
 	pbn_NETMOS9900_2s_115200,
 	pbn_NETMOS9900_2s_115200,
@@ -3907,16 +3715,6 @@ static struct pciserial_board pci_boards[] = {
 		.uart_offset	= 0x80,
 		.uart_offset	= 0x80,
 		.reg_shift      = 2,
 		.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] = {
 	[pbn_qrk] = {
 		.flags		= FL_BASE0,
 		.flags		= FL_BASE0,
 		.num_ports	= 1,
 		.num_ports	= 1,
@@ -4005,6 +3803,13 @@ static const struct pci_device_id blacklist[] = {
 	{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
 	{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
 	{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
 	{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
 	{ PCI_DEVICE(0x1c00, 0x3470), }, /* WCH CH384 4S */
 	{ 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), },
 };
 };
 
 
 /*
 /*
@@ -5701,26 +5506,6 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
 		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
 		pbn_byt },
 		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
 	 * Intel Quark x1000
 	 */
 	 */

+ 49 - 37
drivers/tty/serial/8250/8250_port.c

@@ -284,7 +284,7 @@ static void default_serial_dl_write(struct uart_8250_port *up, int value)
 	serial_out(up, UART_DLM, value >> 8 & 0xff);
 	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 */
 /* Au1x00/RT288x UART hardware has a weird register layout */
 static const s8 au_io_in_map[8] = {
 static const s8 au_io_in_map[8] = {
@@ -435,7 +435,7 @@ static void set_io_from_upio(struct uart_port *p)
 		p->serial_out = mem32be_serial_out;
 		p->serial_out = mem32be_serial_out;
 		break;
 		break;
 
 
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+#ifdef CONFIG_SERIAL_8250_RT288X
 	case UPIO_AU:
 	case UPIO_AU:
 		p->serial_in = au_serial_in;
 		p->serial_in = au_serial_in;
 		p->serial_out = au_serial_out;
 		p->serial_out = au_serial_out;
@@ -1246,6 +1246,9 @@ static void autoconfig_irq(struct uart_8250_port *up)
 		inb_p(ICP);
 		inb_p(ICP);
 	}
 	}
 
 
+	if (uart_console(port))
+		console_lock();
+
 	/* forget possible initially masked and pending IRQ */
 	/* forget possible initially masked and pending IRQ */
 	probe_irq_off(probe_irq_on());
 	probe_irq_off(probe_irq_on());
 	save_mcr = serial_in(up, UART_MCR);
 	save_mcr = serial_in(up, UART_MCR);
@@ -1277,6 +1280,9 @@ static void autoconfig_irq(struct uart_8250_port *up)
 	if (port->flags & UPF_FOURPORT)
 	if (port->flags & UPF_FOURPORT)
 		outb_p(save_ICP, ICP);
 		outb_p(save_ICP, ICP);
 
 
+	if (uart_console(port))
+		console_unlock();
+
 	port->irq = (irq > 0) ? irq : 0;
 	port->irq = (irq > 0) ? irq : 0;
 }
 }
 
 
@@ -1807,9 +1813,6 @@ int serial8250_do_startup(struct uart_port *port)
 	unsigned char lsr, iir;
 	unsigned char lsr, iir;
 	int retval;
 	int retval;
 
 
-	if (port->type == PORT_8250_CIR)
-		return -ENODEV;
-
 	if (!port->fifosize)
 	if (!port->fifosize)
 		port->fifosize = uart_config[port->type].fifo_size;
 		port->fifosize = uart_config[port->type].fifo_size;
 	if (!up->tx_loadsz)
 	if (!up->tx_loadsz)
@@ -2230,6 +2233,23 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
 		serial_port_out(port, 0x2, quot_frac);
 		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
 void
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 		          struct ktermios *old)
 		          struct ktermios *old)
@@ -2241,12 +2261,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 
 
 	cval = serial8250_compute_lcr(up, termios->c_cflag);
 	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);
 	quot = serial8250_get_divisor(up, baud, &frac);
 
 
 	/*
 	/*
@@ -2513,14 +2528,8 @@ static void serial8250_release_port(struct uart_port *port)
 static int serial8250_request_port(struct uart_port *port)
 static int serial8250_request_port(struct uart_port *port)
 {
 {
 	struct uart_8250_port *up = up_to_u8250p(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)
 static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
@@ -2668,9 +2677,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
 	struct uart_8250_port *up = up_to_u8250p(port);
 	struct uart_8250_port *up = up_to_u8250p(port);
 	int ret;
 	int ret;
 
 
-	if (port->type == PORT_8250_CIR)
-		return;
-
 	/*
 	/*
 	 * Find the region that we can probe for.  This in turn
 	 * Find the region that we can probe for.  This in turn
 	 * tells us whether we can probe for the type of port.
 	 * tells us whether we can probe for the type of port.
@@ -2804,6 +2810,27 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
 	serial_port_out(port, UART_TX, ch);
 	serial_port_out(port, UART_TX, ch);
 }
 }
 
 
+/*
+ *	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
  *	Print a string to the serial port trying not to disturb
  *	any possible real use of the port...
  *	any possible real use of the port...
@@ -2841,22 +2868,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
 
 
 	/* check scratch reg to see if port powered off during system sleep */
 	/* check scratch reg to see if port powered off during system sleep */
 	if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
 	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;
 		up->canary = 0;
 	}
 	}
 
 

+ 18 - 7
drivers/tty/serial/8250/Kconfig

@@ -274,8 +274,8 @@ config SERIAL_8250_ACORN
 
 
 config SERIAL_8250_FSL
 config SERIAL_8250_FSL
 	bool
 	bool
-	depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
-	default PPC
+	depends on SERIAL_8250_CONSOLE
+	default PPC || ARM || ARM64
 
 
 config SERIAL_8250_DW
 config SERIAL_8250_DW
 	tristate "Support for Synopsys DesignWare 8250 quirks"
 	tristate "Support for Synopsys DesignWare 8250 quirks"
@@ -294,11 +294,12 @@ config SERIAL_8250_EM
 
 
 config SERIAL_8250_RT288X
 config SERIAL_8250_RT288X
 	bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support"
 	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
 	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
 config SERIAL_8250_OMAP
 	tristate "Support for OMAP internal UART (8250 based driver)"
 	tristate "Support for OMAP internal UART (8250 based driver)"
@@ -337,7 +338,7 @@ config SERIAL_8250_FINTEK
 	  through the PNP driver. If unsure, say N.
 	  through the PNP driver. If unsure, say N.
 
 
 config SERIAL_8250_LPC18XX
 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)
 	depends on SERIAL_8250 && OF && (ARCH_LPC18XX || COMPILE_TEST)
 	default ARCH_LPC18XX
 	default ARCH_LPC18XX
 	help
 	help
@@ -366,3 +367,13 @@ config SERIAL_8250_INGENIC
 	help
 	help
 	  If you have a system using an Ingenic SoC and wish to make use of
 	  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.
 	  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.

+ 1 - 0
drivers/tty/serial/8250/Makefile

@@ -27,5 +27,6 @@ obj-$(CONFIG_SERIAL_8250_LPC18XX)	+= 8250_lpc18xx.o
 obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER)	+= 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.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
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt

+ 7 - 5
drivers/tty/serial/Kconfig

@@ -115,9 +115,9 @@ config SERIAL_SB1250_DUART_CONSOLE
 
 
 config SERIAL_ATMEL
 config SERIAL_ATMEL
 	bool "AT91 / AT32 on-chip serial port support"
 	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_CORE
-	select SERIAL_MCTRL_GPIO
+	select SERIAL_MCTRL_GPIO if GPIOLIB
 	help
 	help
 	  This enables the driver for the on-chip UARTs of the Atmel
 	  This enables the driver for the on-chip UARTs of the Atmel
 	  AT91 and AT32 processors.
 	  AT91 and AT32 processors.
@@ -571,7 +571,7 @@ config BFIN_UART3_CTSRTS
 
 
 config SERIAL_IMX
 config SERIAL_IMX
 	tristate "IMX serial port support"
 	tristate "IMX serial port support"
-	depends on ARCH_MXC
+	depends on ARCH_MXC || COMPILE_TEST
 	select SERIAL_CORE
 	select SERIAL_CORE
 	select RATIONAL
 	select RATIONAL
 	help
 	help
@@ -582,6 +582,7 @@ config SERIAL_IMX_CONSOLE
 	bool "Console on IMX serial port"
 	bool "Console on IMX serial port"
 	depends on SERIAL_IMX=y
 	depends on SERIAL_IMX=y
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON if OF
 	help
 	help
 	  If you have enabled the serial port on the Freescale IMX
 	  If you have enabled the serial port on the Freescale IMX
 	  CPU you can make it the console by answering Y to this option.
 	  CPU you can make it the console by answering Y to this option.
@@ -743,7 +744,7 @@ config SERIAL_SH_SCI_CONSOLE
 
 
 config SERIAL_SH_SCI_DMA
 config SERIAL_SH_SCI_DMA
 	bool "DMA support"
 	bool "DMA support"
-	depends on SERIAL_SH_SCI && SH_DMAE
+	depends on SERIAL_SH_SCI && DMA_ENGINE
 
 
 config SERIAL_PNX8XXX
 config SERIAL_PNX8XXX
 	bool "Enable PNX8XXX SoCs' UART Support"
 	bool "Enable PNX8XXX SoCs' UART Support"
@@ -1408,7 +1409,7 @@ config SERIAL_PCH_UART_CONSOLE
 	  warnings and which allows logins in single user mode).
 	  warnings and which allows logins in single user mode).
 
 
 config SERIAL_MXS_AUART
 config SERIAL_MXS_AUART
-	depends on ARCH_MXS
+	depends on ARCH_MXS || COMPILE_TEST
 	tristate "MXS AUART support"
 	tristate "MXS AUART support"
 	select SERIAL_CORE
 	select SERIAL_CORE
 	select SERIAL_MCTRL_GPIO if GPIOLIB
 	select SERIAL_MCTRL_GPIO if GPIOLIB
@@ -1538,6 +1539,7 @@ config SERIAL_FSL_LPUART
 	tristate "Freescale lpuart serial port support"
 	tristate "Freescale lpuart serial port support"
 	depends on HAS_DMA
 	depends on HAS_DMA
 	select SERIAL_CORE
 	select SERIAL_CORE
+	select SERIAL_EARLYCON
 	help
 	help
 	  Support for the on-chip lpuart on some Freescale SOCs.
 	  Support for the on-chip lpuart on some Freescale SOCs.
 
 

+ 2 - 24
drivers/tty/serial/altera_uart.c

@@ -508,29 +508,6 @@ static struct uart_driver altera_uart_driver = {
 	.cons		= ALTERA_UART_CONSOLE,
 	.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)
 static int altera_uart_probe(struct platform_device *pdev)
 {
 {
 	struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
 	struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
@@ -570,7 +547,8 @@ static int altera_uart_probe(struct platform_device *pdev)
 	if (platp)
 	if (platp)
 		port->uartclk = platp->uartclk;
 		port->uartclk = platp->uartclk;
 	else {
 	else {
-		ret = altera_uart_get_of_uartclk(pdev, port);
+		ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+					   &port->uartclk);
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
 	}
 	}

+ 2 - 2
drivers/tty/serial/amba-pl011.c

@@ -191,8 +191,8 @@ struct uart_amba_port {
  */
  */
 static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 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;
 	int fifotaken = 0;
 
 
 	while (max_count--) {
 	while (max_count--) {

+ 1 - 0
drivers/tty/serial/apbuart.c

@@ -581,6 +581,7 @@ static const struct of_device_id apbuart_match[] = {
 	 },
 	 },
 	{},
 	{},
 };
 };
+MODULE_DEVICE_TABLE(of, apbuart_match);
 
 
 static struct platform_driver grlib_apbuart_of_driver = {
 static struct platform_driver grlib_apbuart_of_driver = {
 	.probe = apbuart_probe,
 	.probe = apbuart_probe,

+ 16 - 11
drivers/tty/serial/atmel_serial.c

@@ -111,6 +111,12 @@ struct atmel_uart_char {
 
 
 #define ATMEL_SERIAL_RINGSIZE 1024
 #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.
  * We wrap our port structure around the generic uart_port.
  */
  */
@@ -921,7 +927,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
 	sg_set_page(&atmel_port->sg_tx,
 	sg_set_page(&atmel_port->sg_tx,
 			virt_to_page(port->state->xmit.buf),
 			virt_to_page(port->state->xmit.buf),
 			UART_XMIT_SIZE,
 			UART_XMIT_SIZE,
-			(int)port->state->xmit.buf & ~PAGE_MASK);
+			(unsigned long)port->state->xmit.buf & ~PAGE_MASK);
 	nent = dma_map_sg(port->dev,
 	nent = dma_map_sg(port->dev,
 				&atmel_port->sg_tx,
 				&atmel_port->sg_tx,
 				1,
 				1,
@@ -931,10 +937,10 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		goto chan_err;
 		goto chan_err;
 	} else {
 	} 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),
 			sg_dma_len(&atmel_port->sg_tx),
 			port->state->xmit.buf,
 			port->state->xmit.buf,
-			sg_dma_address(&atmel_port->sg_tx));
+			&sg_dma_address(&atmel_port->sg_tx));
 	}
 	}
 
 
 	/* Configure the slave DMA */
 	/* Configure the slave DMA */
@@ -1103,7 +1109,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
 	sg_set_page(&atmel_port->sg_rx,
 	sg_set_page(&atmel_port->sg_rx,
 		    virt_to_page(ring->buf),
 		    virt_to_page(ring->buf),
 		    sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
 		    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,
 	nent = dma_map_sg(port->dev,
 			  &atmel_port->sg_rx,
 			  &atmel_port->sg_rx,
 			  1,
 			  1,
@@ -1113,10 +1119,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		goto chan_err;
 		goto chan_err;
 	} else {
 	} 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),
 			sg_dma_len(&atmel_port->sg_rx),
 			ring->buf,
 			ring->buf,
-			sg_dma_address(&atmel_port->sg_rx));
+			&sg_dma_address(&atmel_port->sg_rx));
 	}
 	}
 
 
 	/* Configure the slave DMA */
 	/* Configure the slave DMA */
@@ -1676,15 +1682,15 @@ static void atmel_init_rs485(struct uart_port *port,
 	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 
 
 	if (np) {
 	if (np) {
+		struct serial_rs485 *rs485conf = &port->rs485;
 		u32 rs485_delay[2];
 		u32 rs485_delay[2];
 		/* rs485 properties */
 		/* rs485 properties */
 		if (of_property_read_u32_array(np, "rs485-rts-delay",
 		if (of_property_read_u32_array(np, "rs485-rts-delay",
 					rs485_delay, 2) == 0) {
 					rs485_delay, 2) == 0) {
-			struct serial_rs485 *rs485conf = &port->rs485;
-
 			rs485conf->delay_rts_before_send = rs485_delay[0];
 			rs485conf->delay_rts_before_send = rs485_delay[0];
 			rs485conf->delay_rts_after_send = rs485_delay[1];
 			rs485conf->delay_rts_after_send = rs485_delay[1];
 			rs485conf->flags = 0;
 			rs485conf->flags = 0;
+		}
 
 
 		if (of_get_property(np, "rs485-rx-during-tx", NULL))
 		if (of_get_property(np, "rs485-rx-during-tx", NULL))
 			rs485conf->flags |= SER_RS485_RX_DURING_TX;
 			rs485conf->flags |= SER_RS485_RX_DURING_TX;
@@ -1692,7 +1698,6 @@ static void atmel_init_rs485(struct uart_port *port,
 		if (of_get_property(np, "linux,rs485-enabled-at-boot-time",
 		if (of_get_property(np, "linux,rs485-enabled-at-boot-time",
 								NULL))
 								NULL))
 			rs485conf->flags |= SER_RS485_ENABLED;
 			rs485conf->flags |= SER_RS485_ENABLED;
-		}
 	} else {
 	} else {
 		port->rs485       = pdata->rs485;
 		port->rs485       = pdata->rs485;
 	}
 	}
@@ -2296,7 +2301,7 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
 		ret = -EINVAL;
 		ret = -EINVAL;
 	if (port->uartclk / 16 != ser->baud_base)
 	if (port->uartclk / 16 != ser->baud_base)
 		ret = -EINVAL;
 		ret = -EINVAL;
-	if ((void *)port->mapbase != ser->iomem_base)
+	if (port->mapbase != (unsigned long)ser->iomem_base)
 		ret = -EINVAL;
 		ret = -EINVAL;
 	if (port->iobase != ser->port)
 	if (port->iobase != ser->port)
 		ret = -EINVAL;
 		ret = -EINVAL;
@@ -2686,7 +2691,7 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
 	enum mctrl_gpio_idx i;
 	enum mctrl_gpio_idx i;
 	struct gpio_desc *gpiod;
 	struct gpio_desc *gpiod;
 
 
-	p->gpios = mctrl_gpio_init(dev, 0);
+	p->gpios = mctrl_gpio_init_noauto(dev, 0);
 	if (IS_ERR(p->gpios))
 	if (IS_ERR(p->gpios))
 		return PTR_ERR(p->gpios);
 		return PTR_ERR(p->gpios);
 
 

+ 1 - 1
drivers/tty/serial/clps711x.c

@@ -500,7 +500,7 @@ static int uart_clps711x_probe(struct platform_device *pdev)
 
 
 	platform_set_drvdata(pdev, s);
 	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))
 	if (IS_ERR(s->gpios))
 	    return PTR_ERR(s->gpios);
 	    return PTR_ERR(s->gpios);
 
 

+ 1 - 0
drivers/tty/serial/cpm_uart/cpm_uart_core.c

@@ -1450,6 +1450,7 @@ static const struct of_device_id cpm_uart_match[] = {
 	},
 	},
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(of, cpm_uart_match);
 
 
 static struct platform_driver cpm_uart_driver = {
 static struct platform_driver cpm_uart_driver = {
 	.driver = {
 	.driver = {

+ 1 - 33
drivers/tty/serial/crisv10.c

@@ -3655,7 +3655,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
 		wake_up_interruptible(&info->port.open_wait);
 		wake_up_interruptible(&info->port.open_wait);
 	}
 	}
 	info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 	info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&info->port.close_wait);
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 
 
 	/* port closed */
 	/* port closed */
@@ -3758,23 +3757,6 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	int		retval;
 	int		retval;
 	int		do_clocal = 0;
 	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,
 	 * If non-blocking mode is set, or the port is not enabled,
 	 * then make the check up front and then exit.
 	 * then make the check up front and then exit.
@@ -3825,7 +3807,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 #endif
 #endif
 			break;
 			break;
 		}
 		}
-		if (!(info->port.flags & ASYNC_CLOSING) && do_clocal)
+		if (do_clocal)
 			/* && (do_clocal || DCD_IS_ASSERTED) */
 			/* && (do_clocal || DCD_IS_ASSERTED) */
 			break;
 			break;
 		if (signal_pending(current)) {
 		if (signal_pending(current)) {
@@ -3894,20 +3876,6 @@ rs_open(struct tty_struct *tty, struct file * filp)
 
 
 	info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY);
 	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 DMA is enabled try to allocate the irq's.
 	 */
 	 */

+ 39 - 0
drivers/tty/serial/fsl_lpuart.c

@@ -1746,6 +1746,45 @@ static struct console lpuart32_console = {
 	.data		= &lpuart_reg,
 	.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 LPUART_CONSOLE	(&lpuart_console)
 #define LPUART32_CONSOLE	(&lpuart32_console)
 #define LPUART32_CONSOLE	(&lpuart32_console)
 #else
 #else

+ 103 - 72
drivers/tty/serial/imx.c

@@ -139,6 +139,7 @@
 #define USR1_ESCF	(1<<11) /* Escape seq interrupt flag */
 #define USR1_ESCF	(1<<11) /* Escape seq interrupt flag */
 #define USR1_FRAMERR	(1<<10) /* Frame error interrupt flag */
 #define USR1_FRAMERR	(1<<10) /* Frame error interrupt flag */
 #define USR1_RRDY	(1<<9)	 /* Receiver ready interrupt/dma 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_TIMEOUT	(1<<7)	 /* Receive timeout interrupt status */
 #define USR1_RXDS	 (1<<6)	 /* Receiver idle interrupt flag */
 #define USR1_RXDS	 (1<<6)	 /* Receiver idle interrupt flag */
 #define USR1_AIRINT	 (1<<5)	 /* Async IR wake interrupt flag */
 #define USR1_AIRINT	 (1<<5)	 /* Async IR wake interrupt flag */
@@ -728,11 +729,15 @@ static void imx_dma_rxint(struct imx_port *sport)
 	if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
 	if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
 		sport->dma_is_rxing = 1;
 		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 = readl(sport->port.membase + UCR1);
 		temp &= ~(UCR1_RRDYEN);
 		temp &= ~(UCR1_RRDYEN);
 		writel(temp, sport->port.membase + UCR1);
 		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. */
 		/* tell the DMA to receive the data. */
 		start_rx_dma(sport);
 		start_rx_dma(sport);
 	}
 	}
@@ -749,7 +754,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
 	sts = readl(sport->port.membase + USR1);
 	sts = readl(sport->port.membase + USR1);
 	sts2 = readl(sport->port.membase + USR2);
 	sts2 = readl(sport->port.membase + USR2);
 
 
-	if (sts & USR1_RRDY) {
+	if (sts & (USR1_RRDY | USR1_AGTIM)) {
 		if (sport->dma_is_enabled)
 		if (sport->dma_is_enabled)
 			imx_dma_rxint(sport);
 			imx_dma_rxint(sport);
 		else
 		else
@@ -852,19 +857,6 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	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)
 #define RX_BUF_SIZE	(PAGE_SIZE)
 static void imx_rx_dma_done(struct imx_port *sport)
 static void imx_rx_dma_done(struct imx_port *sport)
 {
 {
@@ -873,11 +865,15 @@ static void imx_rx_dma_done(struct imx_port *sport)
 
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 	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 = readl(sport->port.membase + UCR1);
 	temp |= UCR1_RRDYEN;
 	temp |= UCR1_RRDYEN;
 	writel(temp, sport->port.membase + UCR1);
 	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;
 	sport->dma_is_rxing = 0;
 
 
 	/* Is the shutdown waiting for us? */
 	/* Is the shutdown waiting for us? */
@@ -888,14 +884,12 @@ static void imx_rx_dma_done(struct imx_port *sport)
 }
 }
 
 
 /*
 /*
- * 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.
  *   [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)
 static void dma_rx_callback(void *data)
 {
 {
@@ -913,13 +907,6 @@ static void dma_rx_callback(void *data)
 	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
 	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
 	count = RX_BUF_SIZE - state.residue;
 	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);
 	dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
 
 
 	if (count) {
 	if (count) {
@@ -931,23 +918,21 @@ static void dma_rx_callback(void *data)
 				sport->port.icount.buf_overrun++;
 				sport->port.icount.buf_overrun++;
 		}
 		}
 		tty_flip_buffer_push(port);
 		tty_flip_buffer_push(port);
+		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);
 		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
-		 */
+	else
 		imx_rx_dma_done(sport);
 		imx_rx_dma_done(sport);
-	}
 }
 }
 
 
 static int start_rx_dma(struct imx_port *sport)
 static int start_rx_dma(struct imx_port *sport)
@@ -980,6 +965,22 @@ static int start_rx_dma(struct imx_port *sport)
 	return 0;
 	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)
 static void imx_uart_dma_exit(struct imx_port *sport)
 {
 {
 	if (sport->dma_chan_rx) {
 	if (sport->dma_chan_rx) {
@@ -1015,7 +1016,8 @@ static int imx_uart_dma_init(struct imx_port *sport)
 	slave_config.direction = DMA_DEV_TO_MEM;
 	slave_config.direction = DMA_DEV_TO_MEM;
 	slave_config.src_addr = sport->port.mapbase + URXD0;
 	slave_config.src_addr = sport->port.mapbase + URXD0;
 	slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
 	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);
 	ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "error in RX dma configuration.\n");
 		dev_err(dev, "error in RX dma configuration.\n");
@@ -1039,7 +1041,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
 	slave_config.direction = DMA_MEM_TO_DEV;
 	slave_config.direction = DMA_MEM_TO_DEV;
 	slave_config.dst_addr = sport->port.mapbase + URTX0;
 	slave_config.dst_addr = sport->port.mapbase + URTX0;
 	slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
 	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);
 	ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "error in TX dma configuration.");
 		dev_err(dev, "error in TX dma configuration.");
@@ -1062,15 +1064,14 @@ static void imx_enable_dma(struct imx_port *sport)
 
 
 	/* set UCR1 */
 	/* set UCR1 */
 	temp = readl(sport->port.membase + 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);
 	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;
 	sport->dma_is_enabled = 1;
 }
 }
@@ -1086,13 +1087,10 @@ static void imx_disable_dma(struct imx_port *sport)
 
 
 	/* clear UCR2 */
 	/* clear UCR2 */
 	temp = readl(sport->port.membase + 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);
 	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;
 	sport->dma_is_enabled = 0;
 }
 }
@@ -1115,7 +1113,7 @@ static int imx_startup(struct uart_port *port)
 		return retval;
 		return retval;
 	}
 	}
 
 
-	imx_setup_ufcr(sport, 0);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 
 	/* disable the DREN bit (Data Ready interrupt enable) before
 	/* disable the DREN bit (Data Ready interrupt enable) before
 	 * requesting IRQs
 	 * requesting IRQs
@@ -1128,6 +1126,11 @@ static int imx_startup(struct uart_port *port)
 
 
 	writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 	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);
 	spin_lock_irqsave(&sport->port.lock, flags);
 	/* Reset fifo's and state machines */
 	/* Reset fifo's and state machines */
 	i = 100;
 	i = 100;
@@ -1145,6 +1148,9 @@ static int imx_startup(struct uart_port *port)
 	writel(USR1_RTSD, sport->port.membase + USR1);
 	writel(USR1_RTSD, sport->port.membase + USR1);
 	writel(USR2_ORE, sport->port.membase + USR2);
 	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 = readl(sport->port.membase + UCR1);
 	temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 	temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 
 
@@ -1278,7 +1284,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 {
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long flags;
 	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 old_csize = old ? old->c_cflag & CSIZE : CS8;
 	unsigned int div, ufcr;
 	unsigned int div, ufcr;
 	unsigned long num, denom;
 	unsigned long num, denom;
@@ -1315,11 +1321,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 			} else {
 			} else {
 				ucr2 |= UCR2_CTSC;
 				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 {
 		} else {
 			termios->c_cflag &= ~CRTSCTS;
 			termios->c_cflag &= ~CRTSCTS;
 		}
 		}
@@ -1387,10 +1388,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 		barrier();
 		barrier();
 
 
 	/* then, disable everything */
 	/* 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);
 			sport->port.membase + UCR2);
-	old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
+	old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
 
 
 	/* custom-baudrate handling */
 	/* custom-baudrate handling */
 	div = sport->port.uartclk / (baud * 16);
 	div = sport->port.uartclk / (baud * 16);
@@ -1431,13 +1432,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	writel(old_ucr1, sport->port.membase + UCR1);
 	writel(old_ucr1, sport->port.membase + UCR1);
 
 
 	/* set the parity, stop bits and data size */
 	/* 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))
 	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
 		imx_enable_ms(&sport->port);
 		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);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 }
 
 
@@ -1503,7 +1502,7 @@ static int imx_poll_init(struct uart_port *port)
 	if (retval)
 	if (retval)
 		clk_disable_unprepare(sport->clk_ipg);
 		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);
 	spin_lock_irqsave(&sport->port.lock, flags);
 
 
@@ -1773,7 +1772,7 @@ imx_console_setup(struct console *co, char *options)
 	else
 	else
 		imx_console_get_options(sport, &baud, &parity, &bits);
 		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);
 	retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
 
@@ -1803,6 +1802,38 @@ static struct console imx_console = {
 };
 };
 
 
 #define IMX_CONSOLE	&imx_console
 #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
 #else
 #define IMX_CONSOLE	NULL
 #define IMX_CONSOLE	NULL
 #endif
 #endif

+ 4 - 3
drivers/tty/serial/lpc32xx_hs.c

@@ -691,12 +691,13 @@ static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
 	p->port.mapbase = res->start;
 	p->port.mapbase = res->start;
 	p->port.membase = NULL;
 	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",
 		dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n",
 			uarts_registered);
 			uarts_registered);
-		return p->port.irq;
+		return ret;
 	}
 	}
+	p->port.irq = ret;
 
 
 	p->port.iotype = UPIO_MEM32;
 	p->port.iotype = UPIO_MEM32;
 	p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;
 	p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;

+ 15 - 8
drivers/tty/serial/men_z135_uart.c

@@ -35,8 +35,6 @@
 #define MEN_Z135_BAUD_REG		0x810
 #define MEN_Z135_BAUD_REG		0x810
 #define MEN_Z135_TIMEOUT		0x814
 #define MEN_Z135_TIMEOUT		0x814
 
 
-#define MEN_Z135_MEM_SIZE		0x818
-
 #define IRQ_ID(x) ((x) & 0x1f)
 #define IRQ_ID(x) ((x) & 0x1f)
 
 
 #define MEN_Z135_IER_RXCIEN BIT(0)		/* RX Space IRQ */
 #define MEN_Z135_IER_RXCIEN BIT(0)		/* RX Space IRQ */
@@ -124,6 +122,7 @@ MODULE_PARM_DESC(rx_timeout, "RX timeout. "
 struct men_z135_port {
 struct men_z135_port {
 	struct uart_port port;
 	struct uart_port port;
 	struct mcb_device *mdev;
 	struct mcb_device *mdev;
+	struct resource *mem;
 	unsigned char *rxbuf;
 	unsigned char *rxbuf;
 	u32 stat_reg;
 	u32 stat_reg;
 	spinlock_t lock;
 	spinlock_t lock;
@@ -734,22 +733,30 @@ static const char *men_z135_type(struct uart_port *port)
 
 
 static void men_z135_release_port(struct uart_port *port)
 static void men_z135_release_port(struct uart_port *port)
 {
 {
+	struct men_z135_port *uart = to_men_z135(port);
+
 	iounmap(port->membase);
 	iounmap(port->membase);
 	port->membase = NULL;
 	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)
 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;
+
+	mem = mcb_request_mem(uart->mdev, dev_name(&mdev->dev));
+	if (IS_ERR(mem))
+		return PTR_ERR(mem);
 
 
-	if (!request_mem_region(port->mapbase, size, "men_z135_port"))
-		return -EBUSY;
+	port->mapbase = mem->start;
+	uart->mem = mem;
 
 
-	port->membase = ioremap(port->mapbase, MEN_Z135_MEM_SIZE);
+	port->membase = ioremap(mem->start, resource_size(mem));
 	if (port->membase == NULL) {
 	if (port->membase == NULL) {
-		release_mem_region(port->mapbase, MEN_Z135_MEM_SIZE);
+		mcb_release_mem(mem);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 

+ 7 - 0
drivers/tty/serial/mpc52xx_uart.c

@@ -1135,6 +1135,13 @@ mpc52xx_uart_startup(struct uart_port *port)
 	psc_ops->command(port, MPC52xx_PSC_RST_RX);
 	psc_ops->command(port, MPC52xx_PSC_RST_RX);
 	psc_ops->command(port, MPC52xx_PSC_RST_TX);
 	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->set_sicr(port, 0);	/* UART mode DCD ignored */
 
 
 	psc_ops->fifo_init(port);
 	psc_ops->fifo_init(port);

+ 6 - 35
drivers/tty/serial/mpsc.c

@@ -55,8 +55,6 @@
 #define SUPPORT_SYSRQ
 #define SUPPORT_SYSRQ
 #endif
 #endif
 
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/tty.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
@@ -755,7 +753,7 @@ static int mpsc_alloc_ring_mem(struct mpsc_port_info *pi)
 		pi->port.line);
 		pi->port.line);
 
 
 	if (!pi->dma_region) {
 	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");
 			printk(KERN_ERR "MPSC: Inadequate DMA support\n");
 			rc = -ENXIO;
 			rc = -ENXIO;
 		} else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev,
 		} else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev,
@@ -2108,26 +2106,11 @@ static int mpsc_drv_probe(struct platform_device *dev)
 	return rc;
 	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 = {
 static struct platform_driver mpsc_driver = {
 	.probe	= mpsc_drv_probe,
 	.probe	= mpsc_drv_probe,
-	.remove	= mpsc_drv_remove,
 	.driver	= {
 	.driver	= {
-		.name	= MPSC_CTLR_NAME,
+		.name			= MPSC_CTLR_NAME,
+		.suppress_bind_attrs	= true,
 	},
 	},
 };
 };
 
 
@@ -2156,22 +2139,10 @@ static int __init mpsc_drv_init(void)
 
 
 	return rc;
 	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_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
 MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver");
 MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver");
-MODULE_VERSION(MPSC_VERSION);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(MPSC_MAJOR);
-MODULE_ALIAS("platform:" MPSC_CTLR_NAME);
+*/

+ 570 - 52
drivers/tty/serial/msm_serial.c

@@ -20,6 +20,8 @@
 #endif
 #endif
 
 
 #include <linux/atomic.h>
 #include <linux/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/hrtimer.h>
 #include <linux/hrtimer.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/io.h>
@@ -31,6 +33,7 @@
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/serial.h>
+#include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
@@ -39,6 +42,11 @@
 
 
 #include "msm_serial.h"
 #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 {
 enum {
 	UARTDM_1P1 = 1,
 	UARTDM_1P1 = 1,
 	UARTDM_1P2,
 	UARTDM_1P2,
@@ -46,6 +54,17 @@ enum {
 	UARTDM_1P4,
 	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 msm_port {
 	struct uart_port	uart;
 	struct uart_port	uart;
 	char			name[16];
 	char			name[16];
@@ -55,9 +74,153 @@ struct msm_port {
 	int			is_uartdm;
 	int			is_uartdm;
 	unsigned int		old_snap_state;
 	unsigned int		old_snap_state;
 	bool			break_detected;
 	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)) {
 	while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
 		if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
 		if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
@@ -78,17 +241,277 @@ static void msm_stop_tx(struct uart_port *port)
 static void msm_start_tx(struct uart_port *port)
 static void msm_start_tx(struct uart_port *port)
 {
 {
 	struct msm_port *msm_port = UART_TO_MSM(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_port->imr |= UART_IMR_TXLEV;
 	msm_write(port, msm_port->imr, UART_IMR);
 	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)
 static void msm_stop_rx(struct uart_port *port)
 {
 {
 	struct msm_port *msm_port = UART_TO_MSM(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_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
 	msm_write(port, msm_port->imr, UART_IMR);
 	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)
 static void msm_enable_ms(struct uart_port *port)
@@ -99,7 +522,7 @@ static void msm_enable_ms(struct uart_port *port)
 	msm_write(port, msm_port->imr, UART_IMR);
 	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;
 	struct tty_port *tport = &port->state->port;
 	unsigned int sr;
 	unsigned int sr;
@@ -169,9 +592,12 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
 		msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
 		msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
 	msm_write(port, 0xFFFFFF, UARTDM_DMRX);
 	msm_write(port, 0xFFFFFF, UARTDM_DMRX);
 	msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
 	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;
 	struct tty_port *tport = &port->state->port;
 	unsigned int sr;
 	unsigned int sr;
@@ -224,18 +650,11 @@ static void handle_rx(struct uart_port *port)
 	spin_lock(&port->lock);
 	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 circ_buf *xmit = &port->state->xmit;
 	struct msm_port *msm_port = UART_TO_MSM(port);
 	struct msm_port *msm_port = UART_TO_MSM(port);
-	unsigned int tx_count, num_chars;
+	unsigned int num_chars;
 	unsigned int tf_pointer = 0;
 	unsigned int tf_pointer = 0;
 	void __iomem *tf;
 	void __iomem *tf;
 
 
@@ -244,20 +663,8 @@ static void handle_tx(struct uart_port *port)
 	else
 	else
 		tf = port->membase + UART_TF;
 		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) {
 	while (tf_pointer < tx_count) {
 		int i;
 		int i;
@@ -290,20 +697,76 @@ static void handle_tx(struct uart_port *port)
 		uart_write_wakeup(port);
 		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);
 	msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
 	port->icount.cts++;
 	port->icount.cts++;
 	wake_up_interruptible(&port->state->port.delta_msr_wait);
 	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 uart_port *port = dev_id;
 	struct msm_port *msm_port = UART_TO_MSM(port);
 	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct msm_dma *dma = &msm_port->rx_dma;
+	unsigned long flags;
 	unsigned int misr;
 	unsigned int misr;
+	u32 val;
 
 
-	spin_lock(&port->lock);
+	spin_lock_irqsave(&port->lock, flags);
 	misr = msm_read(port, UART_MISR);
 	misr = msm_read(port, UART_MISR);
 	msm_write(port, 0, UART_IMR); /* disable interrupt */
 	msm_write(port, 0, UART_IMR); /* disable interrupt */
 
 
@@ -313,18 +776,29 @@ static irqreturn_t msm_irq(int irq, void *dev_id)
 	}
 	}
 
 
 	if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) {
 	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)
 	if (misr & UART_IMR_TXLEV)
-		handle_tx(port);
+		msm_handle_tx(port);
 	if (misr & UART_IMR_DELTA_CTS)
 	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 */
 	msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */
-	spin_unlock(&port->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
@@ -408,6 +882,7 @@ msm_find_best_baud(struct uart_port *port, unsigned int baud)
 		{    3, 0xdd,  8 },
 		{    3, 0xdd,  8 },
 		{    2, 0xee, 16 },
 		{    2, 0xee, 16 },
 		{    1, 0xff, 31 },
 		{    1, 0xff, 31 },
+		{    0, 0xff, 31 },
 	};
 	};
 
 
 	divisor = uart_get_divisor(port, baud);
 	divisor = uart_get_divisor(port, baud);
@@ -419,21 +894,41 @@ msm_find_best_baud(struct uart_port *port, unsigned int baud)
 	return entry; /* Default to smallest divider */
 	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);
 	struct msm_port *msm_port = UART_TO_MSM(port);
 	const struct msm_baud_map *entry;
 	const struct msm_baud_map *entry;
+	unsigned long flags;
 
 
 	entry = msm_find_best_baud(port, baud);
 	entry = msm_find_best_baud(port, baud);
 
 
 	msm_write(port, entry->code, UART_CSR);
 	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 */
 	/* RX stale watermark */
 	rxstale = entry->rxstale;
 	rxstale = entry->rxstale;
 	watermark = UART_IPR_STALE_LSB & 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);
 	msm_write(port, watermark, UART_IPR);
 
 
 	/* set RX watermark */
 	/* set RX watermark */
@@ -476,13 +971,13 @@ static void msm_init_clock(struct uart_port *port)
 static int msm_startup(struct uart_port *port)
 static int msm_startup(struct uart_port *port)
 {
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 	struct msm_port *msm_port = UART_TO_MSM(port);
-	unsigned int data, rfr_level;
+	unsigned int data, rfr_level, mask;
 	int ret;
 	int ret;
 
 
 	snprintf(msm_port->name, sizeof(msm_port->name),
 	snprintf(msm_port->name, sizeof(msm_port->name),
 		 "msm_serial%d", port->line);
 		 "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);
 			  msm_port->name, port);
 	if (unlikely(ret))
 	if (unlikely(ret))
 		return ret;
 		return ret;
@@ -496,11 +991,23 @@ static int msm_startup(struct uart_port *port)
 
 
 	/* set automatic RFR level */
 	/* set automatic RFR level */
 	data = msm_read(port, UART_MR1);
 	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_LEVEL0;
-	data |= UART_MR1_AUTO_RFR_LEVEL1 & (rfr_level << 2);
+	data |= mask & (rfr_level << 2);
 	data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level;
 	data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level;
 	msm_write(port, data, UART_MR1);
 	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;
 	return 0;
 }
 }
 
 
@@ -511,6 +1018,9 @@ static void msm_shutdown(struct uart_port *port)
 	msm_port->imr = 0;
 	msm_port->imr = 0;
 	msm_write(port, 0, UART_IMR); /* disable interrupts */
 	msm_write(port, 0, UART_IMR); /* disable interrupts */
 
 
+	if (msm_port->is_uartdm)
+		msm_release_dma(msm_port);
+
 	clk_disable_unprepare(msm_port->clk);
 	clk_disable_unprepare(msm_port->clk);
 
 
 	free_irq(port->irq, port);
 	free_irq(port->irq, port);
@@ -519,14 +1029,19 @@ static void msm_shutdown(struct uart_port *port)
 static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
 static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 			    struct ktermios *old)
 {
 {
+	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct msm_dma *dma = &msm_port->rx_dma;
 	unsigned long flags;
 	unsigned long flags;
 	unsigned int baud, mr;
 	unsigned int baud, mr;
 
 
 	spin_lock_irqsave(&port->lock, flags);
 	spin_lock_irqsave(&port->lock, flags);
 
 
+	if (dma->chan) /* Terminate if any */
+		msm_stop_dma(port, dma);
+
 	/* calculate and set baud rate */
 	/* 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))
 	if (tty_termios_baud_rate(termios))
 		tty_termios_encode_baud_rate(termios, baud, baud);
 		tty_termios_encode_baud_rate(termios, baud, baud);
 
 
@@ -588,6 +1103,9 @@ static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
 
 
 	uart_update_timeout(port, termios->c_cflag, baud);
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 
+	/* Try to use DMA */
+	msm_start_rx_dma(msm_port);
+
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 }
 
 
@@ -765,7 +1283,7 @@ static void msm_poll_put_char(struct uart_port *port, unsigned char c)
 	msm_write(port, 0, UART_IMR);
 	msm_write(port, 0, UART_IMR);
 
 
 	if (msm_port->is_uartdm)
 	if (msm_port->is_uartdm)
-		reset_dm_count(port, 1);
+		msm_reset_dm_count(port, 1);
 
 
 	/* Wait until FIFO is empty */
 	/* Wait until FIFO is empty */
 	while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 	while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
@@ -839,7 +1357,7 @@ static struct msm_port msm_uart_ports[] = {
 
 
 #define UART_NR	ARRAY_SIZE(msm_uart_ports)
 #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;
 	return &msm_uart_ports[line].uart;
 }
 }
@@ -866,7 +1384,7 @@ static void __msm_console_write(struct uart_port *port, const char *s,
 
 
 	spin_lock(&port->lock);
 	spin_lock(&port->lock);
 	if (is_uartdm)
 	if (is_uartdm)
-		reset_dm_count(port, count);
+		msm_reset_dm_count(port, count);
 
 
 	i = 0;
 	i = 0;
 	while (i < count) {
 	while (i < count) {
@@ -911,7 +1429,7 @@ static void msm_console_write(struct console *co, const char *s,
 
 
 	BUG_ON(co->index < 0 || co->index >= UART_NR);
 	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_port = UART_TO_MSM(port);
 
 
 	__msm_console_write(port, s, count, msm_port->is_uartdm);
 	__msm_console_write(port, s, count, msm_port->is_uartdm);
@@ -928,7 +1446,7 @@ static int __init msm_console_setup(struct console *co, char *options)
 	if (unlikely(co->index >= UART_NR || co->index < 0))
 	if (unlikely(co->index >= UART_NR || co->index < 0))
 		return -ENXIO;
 		return -ENXIO;
 
 
-	port = get_port_from_line(co->index);
+	port = msm_get_port_from_line(co->index);
 
 
 	if (unlikely(!port->membase))
 	if (unlikely(!port->membase))
 		return -ENXIO;
 		return -ENXIO;
@@ -1043,7 +1561,7 @@ static int msm_serial_probe(struct platform_device *pdev)
 
 
 	dev_info(&pdev->dev, "msm_serial: detected port #%d\n", line);
 	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;
 	port->dev = &pdev->dev;
 	msm_port = UART_TO_MSM(port);
 	msm_port = UART_TO_MSM(port);
 
 

+ 31 - 22
drivers/tty/serial/msm_serial.h

@@ -20,11 +20,12 @@
 
 
 #define UART_MR1_AUTO_RFR_LEVEL0	0x3F
 #define UART_MR1_AUTO_RFR_LEVEL0	0x3F
 #define UART_MR1_AUTO_RFR_LEVEL1	0x3FF00
 #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			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		0x30
 #define UART_MR2_BITS_PER_CHAR_5	(0x0 << 4)
 #define UART_MR2_BITS_PER_CHAR_5	(0x0 << 4)
 #define UART_MR2_BITS_PER_CHAR_6	(0x1 << 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_SET_RFR		(13 << 4)
 #define UART_CR_CMD_RESET_RFR		(14 << 4)
 #define UART_CR_CMD_RESET_RFR		(14 << 4)
 #define UART_CR_CMD_PROTECTION_EN	(16 << 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_STALE_EVENT_ENABLE	(80 << 4)
 #define UART_CR_CMD_FORCE_STALE		(4 << 8)
 #define UART_CR_CMD_FORCE_STALE		(4 << 8)
 #define UART_CR_CMD_RESET_TX_READY	(3 << 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_CR_CMD_RESET_RXBREAK_START	((1 << 11) | (2 << 4))
 
 
 #define UART_IMR		0x0014
 #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_RXSTALE_LAST		0x20
 #define UART_IPR_STALE_LSB		0x1F
 #define UART_IPR_STALE_LSB		0x1F
 #define UART_IPR_STALE_TIMEOUT_MSB	0x3FF80
 #define UART_IPR_STALE_TIMEOUT_MSB	0x3FF80
+#define UART_DM_IPR_STALE_TIMEOUT_MSB	0xFFFFFF80
 
 
 #define UART_IPR	0x0018
 #define UART_IPR	0x0018
 #define UART_TFWR	0x001C
 #define UART_TFWR	0x001C
@@ -96,20 +99,20 @@
 #define UART_TEST_CTRL		0x0050
 #define UART_TEST_CTRL		0x0050
 
 
 #define UART_SR			0x0008
 #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 UART_RF			0x000C
 #define UARTDM_RF		0x0070
 #define UARTDM_RF		0x0070
 #define UART_MISR		0x0010
 #define UART_MISR		0x0010
 #define UART_ISR		0x0014
 #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		0x50
 #define UARTDM_RXFS_BUF_SHIFT	0x7
 #define UARTDM_RXFS_BUF_SHIFT	0x7
@@ -119,6 +122,12 @@
 #define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
 #define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
 #define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
 #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_DMRX		0x34
 #define UARTDM_NCF_TX		0x40
 #define UARTDM_NCF_TX		0x40
 #define UARTDM_RX_TOTAL_SNAP	0x38
 #define UARTDM_RX_TOTAL_SNAP	0x38

+ 1 - 1
drivers/tty/serial/mxs-auart.c

@@ -1196,7 +1196,7 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
 	enum mctrl_gpio_idx i;
 	enum mctrl_gpio_idx i;
 	struct gpio_desc *gpiod;
 	struct gpio_desc *gpiod;
 
 
-	s->gpios = mctrl_gpio_init(dev, 0);
+	s->gpios = mctrl_gpio_init_noauto(dev, 0);
 	if (IS_ERR(s->gpios))
 	if (IS_ERR(s->gpios))
 		return PTR_ERR(s->gpios);
 		return PTR_ERR(s->gpios);
 
 

+ 10 - 0
drivers/tty/serial/of_serial.c

@@ -21,6 +21,10 @@
 #include <linux/nwpserial.h>
 #include <linux/nwpserial.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 
 
+#ifdef CONFIG_SERIAL_8250_MODULE
+#define CONFIG_SERIAL_8250 CONFIG_SERIAL_8250_MODULE
+#endif
+
 #include "8250/8250.h"
 #include "8250/8250.h"
 
 
 struct of_serial_info {
 struct of_serial_info {
@@ -150,6 +154,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 		break;
 		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;
 	return 0;
 out:
 out:
 	if (info->clk)
 	if (info->clk)
@@ -350,6 +359,7 @@ static const struct of_device_id of_platform_serial_table[] = {
 #endif
 #endif
 	{ /* end of list */ },
 	{ /* end of list */ },
 };
 };
+MODULE_DEVICE_TABLE(of, of_platform_serial_table);
 
 
 static struct platform_driver of_platform_serial_driver = {
 static struct platform_driver of_platform_serial_driver = {
 	.driver = {
 	.driver = {

+ 2 - 0
drivers/tty/serial/omap-serial.c

@@ -199,6 +199,7 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
 	serial_out(up, UART_FCR, 0);
 	serial_out(up, UART_FCR, 0);
 }
 }
 
 
+#ifdef CONFIG_PM
 static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
 static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
 {
 {
 	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
 	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
@@ -219,6 +220,7 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
 
 
 	pdata->enable_wakeup(up->dev, enable);
 	pdata->enable_wakeup(up->dev, enable);
 }
 }
+#endif /* CONFIG_PM */
 
 
 /*
 /*
  * Calculate the absolute difference between the desired and actual baud
  * Calculate the absolute difference between the desired and actual baud

+ 21 - 45
drivers/tty/serial/samsung.c

@@ -385,32 +385,6 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
 	}
 	}
 }
 }
 
 
-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)
 static void s3c24xx_serial_stop_rx(struct uart_port *port)
 {
 {
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
@@ -573,7 +547,9 @@ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
 	ourport->rx_mode = S3C24XX_RX_PIO;
 	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;
 	unsigned int utrstat, ufstat, received;
 	struct s3c24xx_uart_port *ourport = dev_id;
 	struct s3c24xx_uart_port *ourport = dev_id;
@@ -606,7 +582,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(int irq, void *dev_id)
 		enable_rx_pio(ourport);
 		enable_rx_pio(ourport);
 	}
 	}
 
 
-	uart_rx_drain_fifo(ourport);
+	s3c24xx_serial_rx_drain_fifo(ourport);
 
 
 	if (tty) {
 	if (tty) {
 		tty_flip_buffer_push(t);
 		tty_flip_buffer_push(t);
@@ -621,16 +597,12 @@ finish:
 	return IRQ_HANDLED;
 	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;
 	struct uart_port *port = &ourport->port;
 	unsigned int ufcon, ch, flag, ufstat, uerstat;
 	unsigned int ufcon, ch, flag, ufstat, uerstat;
-	unsigned long flags;
 	int max_count = port->fifosize;
 	int max_count = port->fifosize;
 
 
-	spin_lock_irqsave(&port->lock, flags);
-
 	while (max_count-- > 0) {
 	while (max_count-- > 0) {
 		ufcon = rd_regl(port, S3C2410_UFCON);
 		ufcon = rd_regl(port, S3C2410_UFCON);
 		ufstat = rd_regl(port, S3C2410_UFSTAT);
 		ufstat = rd_regl(port, S3C2410_UFSTAT);
@@ -654,9 +626,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
 					ufcon |= S3C2410_UFCON_RESETRX;
 					ufcon |= S3C2410_UFCON_RESETRX;
 					wr_regl(port, S3C2410_UFCON, ufcon);
 					wr_regl(port, S3C2410_UFCON, ufcon);
 					rx_enabled(port) = 1;
 					rx_enabled(port) = 1;
-					spin_unlock_irqrestore(&port->lock,
-							flags);
-					goto out;
+					return;
 				}
 				}
 				continue;
 				continue;
 			}
 			}
@@ -676,7 +646,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
 				dbg("break!\n");
 				dbg("break!\n");
 				port->icount.brk++;
 				port->icount.brk++;
 				if (uart_handle_break(port))
 				if (uart_handle_break(port))
-					goto ignore_char;
+					continue; /* Ignore character */
 			}
 			}
 
 
 			if (uerstat & S3C2410_UERSTAT_FRAME)
 			if (uerstat & S3C2410_UERSTAT_FRAME)
@@ -696,19 +666,25 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
 		}
 		}
 
 
 		if (uart_handle_sysrq_char(port, ch))
 		if (uart_handle_sysrq_char(port, ch))
-			goto ignore_char;
+			continue; /* Ignore character */
 
 
 		uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
 		uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
 				 ch, flag);
 				 ch, flag);
-
-ignore_char:
-		continue;
 	}
 	}
 
 
-	spin_unlock_irqrestore(&port->lock, flags);
 	tty_flip_buffer_push(&port->state->port);
 	tty_flip_buffer_push(&port->state->port);
+}
+
+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);
 
 
-out:
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
@@ -718,8 +694,8 @@ static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
 	struct s3c24xx_uart_port *ourport = dev_id;
 	struct s3c24xx_uart_port *ourport = dev_id;
 
 
 	if (ourport->dma && ourport->dma->rx_chan)
 	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)
 static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)

+ 6 - 1
drivers/tty/serial/sc16is7xx.c

@@ -1321,6 +1321,9 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
 		const struct of_device_id *of_id =
 		const struct of_device_id *of_id =
 			of_match_device(sc16is7xx_dt_ids, &spi->dev);
 			of_match_device(sc16is7xx_dt_ids, &spi->dev);
 
 
+		if (!of_id)
+			return -ENODEV;
+
 		devtype = (struct sc16is7xx_devtype *)of_id->data;
 		devtype = (struct sc16is7xx_devtype *)of_id->data;
 	} else {
 	} else {
 		const struct spi_device_id *id_entry = spi_get_device_id(spi);
 		const struct spi_device_id *id_entry = spi_get_device_id(spi);
@@ -1380,6 +1383,9 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
 		const struct of_device_id *of_id =
 		const struct of_device_id *of_id =
 				of_match_device(sc16is7xx_dt_ids, &i2c->dev);
 				of_match_device(sc16is7xx_dt_ids, &i2c->dev);
 
 
+		if (!of_id)
+			return -ENODEV;
+
 		devtype = (struct sc16is7xx_devtype *)of_id->data;
 		devtype = (struct sc16is7xx_devtype *)of_id->data;
 	} else {
 	} else {
 		devtype = (struct sc16is7xx_devtype *)id->driver_data;
 		devtype = (struct sc16is7xx_devtype *)id->driver_data;
@@ -1420,7 +1426,6 @@ static struct i2c_driver sc16is7xx_i2c_uart_driver = {
 	.id_table	= sc16is7xx_i2c_id_table,
 	.id_table	= sc16is7xx_i2c_id_table,
 };
 };
 
 
-MODULE_ALIAS("i2c:sc16is7xx");
 #endif
 #endif
 
 
 static int __init sc16is7xx_init(void)
 static int __init sc16is7xx_init(void)

+ 28 - 66
drivers/tty/serial/serial-tegra.c

@@ -186,7 +186,6 @@ static void set_rts(struct tegra_uart_port *tup, bool active)
 		tegra_uart_write(tup, mcr, UART_MCR);
 		tegra_uart_write(tup, mcr, UART_MCR);
 		tup->mcr_shadow = mcr;
 		tup->mcr_shadow = mcr;
 	}
 	}
-	return;
 }
 }
 
 
 static void set_dtr(struct tegra_uart_port *tup, bool active)
 static void set_dtr(struct tegra_uart_port *tup, bool active)
@@ -202,7 +201,6 @@ static void set_dtr(struct tegra_uart_port *tup, bool active)
 		tegra_uart_write(tup, mcr, UART_MCR);
 		tegra_uart_write(tup, mcr, UART_MCR);
 		tup->mcr_shadow = mcr;
 		tup->mcr_shadow = mcr;
 	}
 	}
-	return;
 }
 }
 
 
 static void tegra_uart_set_mctrl(struct uart_port *u, unsigned int mctrl)
 static void tegra_uart_set_mctrl(struct uart_port *u, unsigned int mctrl)
@@ -217,7 +215,6 @@ static void tegra_uart_set_mctrl(struct uart_port *u, unsigned int mctrl)
 
 
 	dtr_enable = !!(mctrl & TIOCM_DTR);
 	dtr_enable = !!(mctrl & TIOCM_DTR);
 	set_dtr(tup, dtr_enable);
 	set_dtr(tup, dtr_enable);
-	return;
 }
 }
 
 
 static void tegra_uart_break_ctl(struct uart_port *u, int break_ctl)
 static void tegra_uart_break_ctl(struct uart_port *u, int break_ctl)
@@ -511,7 +508,6 @@ static void tegra_uart_stop_tx(struct uart_port *u)
 	async_tx_ack(tup->tx_dma_desc);
 	async_tx_ack(tup->tx_dma_desc);
 	xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
 	xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
 	tup->tx_in_progress = 0;
 	tup->tx_in_progress = 0;
-	return;
 }
 }
 
 
 static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
 static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
@@ -523,7 +519,6 @@ static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&tup->uport);
 		uart_write_wakeup(&tup->uport);
 	tegra_uart_start_next_tx(tup);
 	tegra_uart_start_next_tx(tup);
-	return;
 }
 }
 
 
 static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
 static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
@@ -545,8 +540,6 @@ static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
 		if (!uart_handle_sysrq_char(&tup->uport, ch) && tty)
 		if (!uart_handle_sysrq_char(&tup->uport, ch) && tty)
 			tty_insert_flip_char(tty, ch, flag);
 			tty_insert_flip_char(tty, ch, flag);
 	} while (1);
 	} while (1);
-
-	return;
 }
 }
 
 
 static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
 static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
@@ -576,13 +569,30 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
 				TEGRA_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
 				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)
 static void tegra_uart_rx_dma_complete(void *args)
 {
 {
 	struct tegra_uart_port *tup = args;
 	struct tegra_uart_port *tup = args;
 	struct uart_port *u = &tup->uport;
 	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;
 	unsigned long flags;
 	struct dma_tx_state state;
 	struct dma_tx_state state;
 	enum dma_status status;
 	enum dma_status status;
@@ -596,22 +606,11 @@ static void tegra_uart_rx_dma_complete(void *args)
 		goto done;
 		goto done;
 	}
 	}
 
 
-	async_tx_ack(tup->rx_dma_desc);
-
 	/* Deactivate flow control to stop sender */
 	/* Deactivate flow control to stop sender */
 	if (tup->rts_active)
 	if (tup->rts_active)
 		set_rts(tup, false);
 		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);
 	tegra_uart_start_rx_dma(tup);
 
 
 	/* Activate flow control to start transfer */
 	/* Activate flow control to start transfer */
@@ -622,34 +621,17 @@ done:
 	spin_unlock_irqrestore(&u->lock, flags);
 	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 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 */
 	/* Deactivate flow control to stop sender */
 	if (tup->rts_active)
 	if (tup->rts_active)
 		set_rts(tup, false);
 		set_rts(tup, false);
 
 
 	dmaengine_terminate_all(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;
-
-	/* 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);
 	tegra_uart_start_rx_dma(tup);
 
 
 	if (tup->rts_active)
 	if (tup->rts_active)
@@ -697,7 +679,6 @@ static void tegra_uart_handle_modem_signal_change(struct uart_port *u)
 	/* Will start/stop_tx accordingly */
 	/* Will start/stop_tx accordingly */
 	if (msr & UART_MSR_DCTS)
 	if (msr & UART_MSR_DCTS)
 		uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS);
 		uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS);
-	return;
 }
 }
 
 
 static irqreturn_t tegra_uart_isr(int irq, void *data)
 static irqreturn_t tegra_uart_isr(int irq, void *data)
@@ -714,7 +695,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
 		iir = tegra_uart_read(tup, UART_IIR);
 		iir = tegra_uart_read(tup, UART_IIR);
 		if (iir & UART_IIR_NO_INT) {
 		if (iir & UART_IIR_NO_INT) {
 			if (is_rx_int) {
 			if (is_rx_int) {
-				tegra_uart_handle_rx_dma(tup, &flags);
+				tegra_uart_handle_rx_dma(tup);
 				if (tup->rx_in_progress) {
 				if (tup->rx_in_progress) {
 					ier = tup->ier_shadow;
 					ier = tup->ier_shadow;
 					ier |= (UART_IER_RLSI | UART_IER_RTOIE |
 					ier |= (UART_IER_RLSI | UART_IER_RTOIE |
@@ -769,11 +750,8 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
 static void tegra_uart_stop_rx(struct uart_port *u)
 static void tegra_uart_stop_rx(struct uart_port *u)
 {
 {
 	struct tegra_uart_port *tup = to_tegra_uport(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;
 	struct dma_tx_state state;
 	unsigned long ier;
 	unsigned long ier;
-	int count;
 
 
 	if (tup->rts_active)
 	if (tup->rts_active)
 		set_rts(tup, false);
 		set_rts(tup, false);
@@ -781,8 +759,6 @@ static void tegra_uart_stop_rx(struct uart_port *u)
 	if (!tup->rx_in_progress)
 	if (!tup->rx_in_progress)
 		return;
 		return;
 
 
-	tty = tty_port_tty_get(&tup->uport.state->port);
-
 	tegra_uart_wait_sym_time(tup, 1); /* wait a character interval */
 	tegra_uart_wait_sym_time(tup, 1); /* wait a character interval */
 
 
 	ier = tup->ier_shadow;
 	ier = tup->ier_shadow;
@@ -791,21 +767,9 @@ static void tegra_uart_stop_rx(struct uart_port *u)
 	tup->ier_shadow = ier;
 	tup->ier_shadow = ier;
 	tegra_uart_write(tup, ier, UART_IER);
 	tegra_uart_write(tup, ier, UART_IER);
 	tup->rx_in_progress = 0;
 	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)
 static void tegra_uart_hw_deinit(struct tegra_uart_port *tup)
@@ -1083,7 +1047,6 @@ static void tegra_uart_flush_buffer(struct uart_port *u)
 	tup->tx_bytes = 0;
 	tup->tx_bytes = 0;
 	if (tup->tx_dma_chan)
 	if (tup->tx_dma_chan)
 		dmaengine_terminate_all(tup->tx_dma_chan);
 		dmaengine_terminate_all(tup->tx_dma_chan);
-	return;
 }
 }
 
 
 static void tegra_uart_shutdown(struct uart_port *u)
 static void tegra_uart_shutdown(struct uart_port *u)
@@ -1223,7 +1186,6 @@ static void tegra_uart_set_termios(struct uart_port *u,
 	tegra_uart_read(tup, UART_IER);
 	tegra_uart_read(tup, UART_IER);
 
 
 	spin_unlock_irqrestore(&u->lock, flags);
 	spin_unlock_irqrestore(&u->lock, flags);
-	return;
 }
 }
 
 
 static const char *tegra_uart_type(struct uart_port *u)
 static const char *tegra_uart_type(struct uart_port *u)

+ 6 - 3
drivers/tty/serial/serial_core.c

@@ -1437,7 +1437,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 	clear_bit(ASYNCB_CLOSING, &port->flags);
 	clear_bit(ASYNCB_CLOSING, &port->flags);
 	spin_unlock_irq(&port->lock);
 	spin_unlock_irq(&port->lock);
 	wake_up_interruptible(&port->open_wait);
 	wake_up_interruptible(&port->open_wait);
-	wake_up_interruptible(&port->close_wait);
 
 
 	mutex_unlock(&port->mutex);
 	mutex_unlock(&port->mutex);
 
 
@@ -1819,8 +1818,8 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
  *	@options: ptr for <options> field; NULL if not present (out)
  *	@options: ptr for <options> field; NULL if not present (out)
  *
  *
  *	Decodes earlycon kernel command line parameters of the form
  *	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
  *	The optional form
  *	   earlycon=<name>,0x<addr>,<options>
  *	   earlycon=<name>,0x<addr>,<options>
@@ -1841,6 +1840,10 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
 	} else if (strncmp(p, "mmio32be,", 9) == 0) {
 	} else if (strncmp(p, "mmio32be,", 9) == 0) {
 		*iotype = UPIO_MEM32BE;
 		*iotype = UPIO_MEM32BE;
 		p += 9;
 		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) {
 	} else if (strncmp(p, "io,", 3) == 0) {
 		*iotype = UPIO_PORT;
 		*iotype = UPIO_PORT;
 		p += 3;
 		p += 3;

+ 129 - 4
drivers/tty/serial/serial_mctrl_gpio.c

@@ -12,18 +12,23 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * GNU General Public License for more details.
- *
  */
  */
 
 
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/irq.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/consumer.h>
 #include <linux/termios.h>
 #include <linux/termios.h>
+#include <linux/serial_core.h>
 
 
 #include "serial_mctrl_gpio.h"
 #include "serial_mctrl_gpio.h"
 
 
 struct mctrl_gpios {
 struct mctrl_gpios {
+	struct uart_port *port;
 	struct gpio_desc *gpio[UART_GPIO_MAX];
 	struct gpio_desc *gpio[UART_GPIO_MAX];
+	int irq[UART_GPIO_MAX];
+	unsigned int mctrl_prev;
+	bool mctrl_on;
 };
 };
 
 
 static const struct {
 static const struct {
@@ -82,7 +87,7 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
 }
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_get);
 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;
 	struct mctrl_gpios *gpios;
 	enum mctrl_gpio_idx i;
 	enum mctrl_gpio_idx i;
@@ -110,15 +115,135 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
 
 
 	return gpios;
 	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)
 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
 {
 	enum mctrl_gpio_idx i;
 	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])
 		if (gpios->gpio[i])
 			devm_gpiod_put(dev, gpios->gpio[i]);
 			devm_gpiod_put(dev, gpios->gpio[i]);
+	}
 	devm_kfree(dev, gpios);
 	devm_kfree(dev, gpios);
 }
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_free);
 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]);
+	}
+}

+ 38 - 2
drivers/tty/serial/serial_mctrl_gpio.h

@@ -22,6 +22,8 @@
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/consumer.h>
 
 
+struct uart_port;
+
 enum mctrl_gpio_idx {
 enum mctrl_gpio_idx {
 	UART_GPIO_CTS,
 	UART_GPIO_CTS,
 	UART_GPIO_DSR,
 	UART_GPIO_DSR,
@@ -59,13 +61,23 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl);
 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
 				      enum mctrl_gpio_idx gidx);
 				      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.
  * Request and set direction of modem control lines GPIOs.
  * devm_* functions are used, so there's no need to call mctrl_gpio_free().
  * 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
  * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on
  * allocation error.
  * 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.
  * Free the mctrl_gpios structure.
@@ -74,6 +86,16 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx);
  */
  */
 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios);
 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 */
 #else /* GPIOLIB */
 
 
 static inline
 static inline
@@ -95,7 +117,13 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
 }
 }
 
 
 static inline
 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);
 	return ERR_PTR(-ENOSYS);
 }
 }
@@ -105,6 +133,14 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
 {
 }
 }
 
 
+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 /* GPIOLIB */
 
 
 #endif
 #endif

+ 762 - 698
drivers/tty/serial/sh-sci.c

@@ -84,6 +84,7 @@ struct sci_port {
 	unsigned int		overrun_reg;
 	unsigned int		overrun_reg;
 	unsigned int		overrun_mask;
 	unsigned int		overrun_mask;
 	unsigned int		error_mask;
 	unsigned int		error_mask;
+	unsigned int		error_clear;
 	unsigned int		sampling_rate;
 	unsigned int		sampling_rate;
 	resource_size_t		reg_size;
 	resource_size_t		reg_size;
 
 
@@ -103,19 +104,15 @@ struct sci_port {
 	struct dma_chan			*chan_rx;
 	struct dma_chan			*chan_rx;
 
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 #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_tx;
 	dma_cookie_t			cookie_rx[2];
 	dma_cookie_t			cookie_rx[2];
 	dma_cookie_t			active_rx;
 	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];
 	struct scatterlist		sg_rx[2];
+	void				*rx_buf[2];
 	size_t				buf_len_rx;
 	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_tx;
-	struct work_struct		work_rx;
 	struct timer_list		rx_timer;
 	struct timer_list		rx_timer;
 	unsigned int			rx_timeout;
 	unsigned int			rx_timeout;
 #endif
 #endif
@@ -123,11 +120,6 @@ struct sci_port {
 	struct notifier_block		freq_transition;
 	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
 #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
 
 
 static struct sci_port sci_ports[SCI_NPORTS];
 static struct sci_port sci_ports[SCI_NPORTS];
@@ -146,7 +138,7 @@ struct plat_sci_reg {
 /* Helper for invalidating specific entries of an inherited map. */
 /* Helper for invalidating specific entries of an inherited map. */
 #define sci_reg_invalid	{ .offset = 0, .size = 0 }
 #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] = {
 	[SCIx_PROBE_REGTYPE] = {
 		[0 ... SCIx_NR_REGS - 1] = sci_reg_invalid,
 		[0 ... SCIx_NR_REGS - 1] = sci_reg_invalid,
 	},
 	},
@@ -399,7 +391,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
  */
  */
 static unsigned int sci_serial_in(struct uart_port *p, int offset)
 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)
 	if (reg->size == 8)
 		return ioread8(p->membase + (reg->offset << p->regshift));
 		return ioread8(p->membase + (reg->offset << p->regshift));
@@ -413,7 +405,7 @@ static unsigned int sci_serial_in(struct uart_port *p, int offset)
 
 
 static void sci_serial_out(struct uart_port *p, int offset, int value)
 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)
 	if (reg->size == 8)
 		iowrite8(value, p->membase + (reg->offset << p->regshift));
 		iowrite8(value, p->membase + (reg->offset << p->regshift));
@@ -489,6 +481,105 @@ static void sci_port_disable(struct sci_port *sci_port)
 	pm_runtime_put_sync(sci_port->port.dev);
 	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)
 #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
 
 
 #ifdef CONFIG_CONSOLE_POLL
 #ifdef CONFIG_CONSOLE_POLL
@@ -500,7 +591,7 @@ static int sci_poll_get_char(struct uart_port *port)
 	do {
 	do {
 		status = serial_port_in(port, SCxSR);
 		status = serial_port_in(port, SCxSR);
 		if (status & SCxSR_ERRORS(port)) {
 		if (status & SCxSR_ERRORS(port)) {
-			serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+			sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
 			continue;
 			continue;
 		}
 		}
 		break;
 		break;
@@ -513,7 +604,7 @@ static int sci_poll_get_char(struct uart_port *port)
 
 
 	/* Dummy read */
 	/* Dummy read */
 	serial_port_in(port, SCxSR);
 	serial_port_in(port, SCxSR);
-	serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+	sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
 
 
 	return c;
 	return c;
 }
 }
@@ -528,14 +619,14 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
 	} while (!(status & SCxSR_TDxE(port)));
 	} while (!(status & SCxSR_TDxE(port)));
 
 
 	serial_port_out(port, SCxTDR, c);
 	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 */
 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
 
 
 static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 {
 {
 	struct sci_port *s = to_sci_port(port);
 	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.
 	 * Use port-specific handler if provided.
@@ -565,7 +656,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 
 
 static int sci_txfill(struct uart_port *port)
 static int sci_txfill(struct uart_port *port)
 {
 {
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 
 
 	reg = sci_getreg(port, SCTFDR);
 	reg = sci_getreg(port, SCTFDR);
 	if (reg->size)
 	if (reg->size)
@@ -585,7 +676,7 @@ static int sci_txroom(struct uart_port *port)
 
 
 static int sci_rxfill(struct uart_port *port)
 static int sci_rxfill(struct uart_port *port)
 {
 {
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 
 
 	reg = sci_getreg(port, SCRFDR);
 	reg = sci_getreg(port, SCRFDR);
 	if (reg->size)
 	if (reg->size)
@@ -655,7 +746,7 @@ static void sci_transmit_chars(struct uart_port *port)
 		port->icount.tx++;
 		port->icount.tx++;
 	} while (--count > 0);
 	} 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)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(port);
 		uart_write_wakeup(port);
@@ -666,7 +757,7 @@ static void sci_transmit_chars(struct uart_port *port)
 
 
 		if (port->type != PORT_SCI) {
 		if (port->type != PORT_SCI) {
 			serial_port_in(port, SCxSR); /* Dummy read */
 			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;
 		ctrl |= SCSCR_TIE;
@@ -750,7 +841,7 @@ static void sci_receive_chars(struct uart_port *port)
 		}
 		}
 
 
 		serial_port_in(port, SCxSR); /* dummy read */
 		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;
 		copied += count;
 		port->icount.rx += count;
 		port->icount.rx += count;
@@ -761,7 +852,7 @@ static void sci_receive_chars(struct uart_port *port)
 		tty_flip_buffer_push(tport);
 		tty_flip_buffer_push(tport);
 	} else {
 	} else {
 		serial_port_in(port, SCxSR); /* dummy read */
 		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 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
 {
 {
 	struct tty_port *tport = &port->state->port;
 	struct tty_port *tport = &port->state->port;
 	struct sci_port *s = to_sci_port(port);
 	struct sci_port *s = to_sci_port(port);
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 	int copied = 0;
 	int copied = 0;
 	u16 status;
 	u16 status;
 
 
@@ -924,686 +1015,783 @@ static int sci_handle_breaks(struct uart_port *port)
 	return copied;
 	return copied;
 }
 }
 
 
-static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
-{
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
-	struct uart_port *port = ptr;
-	struct sci_port *s = to_sci_port(port);
+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;
 
 
-	if (s->chan_rx) {
-		u16 scr = serial_port_in(port, SCSCR);
-		u16 ssr = serial_port_in(port, SCxSR);
+	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
 
-		/* Disable future Rx interrupts */
-		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-			disable_irq_nosync(irq);
-			scr |= SCSCR_RDRQE;
-		} else {
-			scr &= ~SCSCR_RIE;
-		}
-		serial_port_out(port, SCSCR, scr);
-		/* Clear current interrupt */
-		serial_port_out(port, SCxSR, ssr & ~(1 | 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);
+	spin_lock_irqsave(&port->lock, flags);
 
 
-		return IRQ_HANDLED;
-	}
-#endif
+	xmit->tail += s->tx_dma_len;
+	xmit->tail &= UART_XMIT_SIZE - 1;
 
 
-	/* I think sci_receive_chars has to be called irrespective
-	 * of whether the I_IXOFF is set, otherwise, how is the interrupt
-	 * to be disabled?
-	 */
-	sci_receive_chars(ptr);
+	port->icount.tx += s->tx_dma_len;
 
 
-	return IRQ_HANDLED;
-}
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
 
 
-static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
-{
-	struct uart_port *port = ptr;
-	unsigned long flags;
+	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_lock_irqsave(&port->lock, flags);
-	sci_transmit_chars(port);
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
-
-	return IRQ_HANDLED;
 }
 }
 
 
-static irqreturn_t sci_er_interrupt(int irq, void *ptr)
+/* 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 = ptr;
+	struct uart_port *port = &s->port;
+	struct tty_port *tport = &port->state->port;
+	int copied;
 
 
-	/* 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));
-		}
-	} else {
-		sci_handle_fifo_overrun(port);
-		sci_rx_interrupt(irq, ptr);
+	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++;
 	}
 	}
 
 
-	serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
-
-	/* Kick the transmission */
-	sci_tx_interrupt(irq, ptr);
+	port->icount.rx += copied;
 
 
-	return IRQ_HANDLED;
+	return copied;
 }
 }
 
 
-static irqreturn_t sci_br_interrupt(int irq, void *ptr)
+static int sci_dma_rx_find_active(struct sci_port *s)
 {
 {
-	struct uart_port *port = ptr;
+	unsigned int i;
 
 
-	/* Handle BREAKs */
-	sci_handle_breaks(port);
-	serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
+	for (i = 0; i < ARRAY_SIZE(s->cookie_rx); i++)
+		if (s->active_rx == s->cookie_rx[i])
+			return i;
 
 
-	return IRQ_HANDLED;
+	dev_err(s->port.dev, "%s: Rx cookie %d not found!\n", __func__,
+		s->active_rx);
+	return -1;
 }
 }
 
 
-static inline unsigned long port_rx_irq_mask(struct uart_port *port)
+static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
 {
 {
-	/*
-	 * 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);
+	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 irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
+static void sci_dma_rx_complete(void *arg)
 {
 {
-	unsigned short ssr_status, scr_status, err_enabled, orer_status = 0;
-	struct uart_port *port = ptr;
-	struct sci_port *s = to_sci_port(port);
-	irqreturn_t ret = IRQ_NONE;
+	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;
 
 
-	ssr_status = serial_port_in(port, SCxSR);
-	scr_status = serial_port_in(port, SCSCR);
-	if (s->overrun_reg == SCxSR)
-		orer_status = ssr_status;
-	else {
-		if (sci_getreg(port, s->overrun_reg)->size)
-			orer_status = serial_port_in(port, s->overrun_reg);
-	}
+	dev_dbg(port->dev, "%s(%d) active cookie %d\n", __func__, port->line,
+		s->active_rx);
 
 
-	err_enabled = scr_status & port_rx_irq_mask(port);
+	spin_lock_irqsave(&port->lock, flags);
 
 
-	/* Tx Interrupt */
-	if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCSCR_TIE) &&
-	    !s->chan_tx)
-		ret = sci_tx_interrupt(irq, ptr);
+	active = sci_dma_rx_find_active(s);
+	if (active >= 0)
+		count = sci_dma_rx_push(s, s->rx_buf[active], s->buf_len_rx);
 
 
-	/*
-	 * Rx Interrupt: if we're using DMA, the DMA controller clears RDF /
-	 * 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);
-		ret = sci_rx_interrupt(irq, ptr);
-	}
+	mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
 
 
-	/* Error Interrupt */
-	if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
-		ret = sci_er_interrupt(irq, ptr);
+	if (count)
+		tty_flip_buffer_push(&port->state->port);
 
 
-	/* Break Interrupt */
-	if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
-		ret = sci_br_interrupt(irq, ptr);
+	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;
 
 
-	/* Overrun Interrupt */
-	if (orer_status & s->overrun_mask)
-		sci_handle_fifo_overrun(port);
+	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;
 
 
-	return ret;
+	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);
 }
 }
 
 
-/*
- * Here we define a transition notifier so that we can update all of our
- * ports' baud rate when the peripheral clock changes.
- */
-static int sci_notifier(struct notifier_block *self,
-			unsigned long phase, void *p)
+static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
 {
 {
-	struct sci_port *sci_port;
+	struct dma_chan *chan = s->chan_tx;
+	struct uart_port *port = &s->port;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	sci_port = container_of(self, struct sci_port, freq_transition);
-
-	if (phase == CPUFREQ_POSTCHANGE) {
-		struct uart_port *port = &sci_port->port;
+	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);
+}
 
 
-		spin_lock_irqsave(&port->lock, flags);
-		port->uartclk = clk_get_rate(sci_port->iclk);
-		spin_unlock_irqrestore(&port->lock, flags);
+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);
 	}
 	}
 
 
-	return NOTIFY_OK;
+	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 struct sci_irq_desc {
-	const char	*desc;
-	irq_handler_t	handler;
-} sci_irq_desc[] = {
+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;
+
 	/*
 	/*
-	 * Split out handlers, the default case.
+	 * 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.
 	 */
 	 */
-	[SCIx_ERI_IRQ] = {
-		.desc = "rx err",
-		.handler = sci_er_interrupt,
-	},
+	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);
 
 
-	[SCIx_RXI_IRQ] = {
-		.desc = "rx full",
-		.handler = sci_rx_interrupt,
-	},
+	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;
+	}
 
 
-	[SCIx_TXI_IRQ] = {
-		.desc = "tx empty",
-		.handler = sci_tx_interrupt,
-	},
+	dma_sync_single_for_device(chan->device->dev, buf, s->tx_dma_len,
+				   DMA_TO_DEVICE);
 
 
-	[SCIx_BRI_IRQ] = {
-		.desc = "break",
-		.handler = sci_br_interrupt,
-	},
+	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;
+	}
 
 
-	/*
-	 * Special muxed handler.
-	 */
-	[SCIx_MUX_IRQ] = {
-		.desc = "mux",
-		.handler = sci_mpxed_interrupt,
-	},
-};
+	dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
+		__func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
 
 
-static int sci_request_irq(struct sci_port *port)
+	dma_async_issue_pending(chan);
+}
+
+static void rx_timer_fn(unsigned long arg)
 {
 {
-	struct uart_port *up = &port->port;
-	int i, j, ret = 0;
+	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;
 
 
-	for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
-		struct sci_irq_desc *desc;
-		int irq;
+	spin_lock_irqsave(&port->lock, flags);
 
 
-		if (SCIx_IRQ_IS_MUXED(port)) {
-			i = SCIx_MUX_IRQ;
-			irq = up->irq;
-		} else {
-			irq = port->irqs[i];
+	dev_dbg(port->dev, "DMA Rx timed out\n");
 
 
-			/*
-			 * Certain port types won't support all of the
-			 * available interrupt sources.
-			 */
-			if (unlikely(irq < 0))
-				continue;
-		}
+	active = sci_dma_rx_find_active(s);
+	if (active < 0) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		return;
+	}
 
 
-		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);
-			goto out_nomem;
-		}
+	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);
 
 
-		ret = request_irq(irq, desc->handler, up->irqflags,
-				  port->irqstr[j], port);
-		if (unlikely(ret)) {
-			dev_err(up->dev, "Can't allocate %s IRQ\n", desc->desc);
-			goto out_noirq;
-		}
+		/* Let packet complete handler take care of the packet */
+		return;
 	}
 	}
 
 
-	return 0;
+	dmaengine_pause(chan);
 
 
-out_noirq:
-	while (--i >= 0)
-		free_irq(port->irqs[i], port);
+	/*
+	 * 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;
+	}
 
 
-out_nomem:
-	while (--j >= 0)
-		kfree(port->irqstr[j]);
+	/* 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);
 
 
-	return ret;
+	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 void sci_free_irq(struct sci_port *port)
+static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
+					     enum dma_transfer_direction dir,
+					     unsigned int id)
 {
 {
-	int i;
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct dma_slave_config cfg;
+	int ret;
 
 
-	/*
-	 * Intentionally in reverse order so we iterate over the muxed
-	 * IRQ first.
-	 */
-	for (i = 0; i < SCIx_NR_IRQS; i++) {
-		int irq = port->irqs[i];
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
 
 
-		/*
-		 * Certain port types won't support all of the available
-		 * interrupt sources.
-		 */
-		if (unlikely(irq < 0))
-			continue;
+	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;
+	}
 
 
-		free_irq(port->irqs[i], port);
-		kfree(port->irqstr[i]);
+	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;
+	}
 
 
-		if (SCIx_IRQ_IS_MUXED(port)) {
-			/* If there's only one IRQ, we're done. */
-			return;
-		}
+	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 unsigned int sci_tx_empty(struct uart_port *port)
+static void sci_request_dma(struct uart_port *port)
 {
 {
-	unsigned short status = serial_port_in(port, SCxSR);
-	unsigned short in_tx_fifo = sci_txfill(port);
+	struct sci_port *s = to_sci_port(port);
+	struct dma_chan *chan;
 
 
-	return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
-}
+	dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
 
 
-/*
- * Modem control is a bit of a mixed bag for SCI(F) ports. Generally
- * CTS/RTS is supported in hardware by at least one port and controlled
- * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently
- * handled via the ->init_pins() op, which is a bit of a one-way street,
- * lacking any ability to defer pin control -- this will later be
- * converted over to the GPIO framework).
- *
- * Other modes (such as loopback) are supported generically on certain
- * port types, but not others. For these it's sufficient to test for the
- * existence of the support register and simply ignore the port type.
- */
-static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	if (mctrl & TIOCM_LOOP) {
-		struct plat_sci_reg *reg;
+	if (!port->dev->of_node &&
+	    (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0))
+		return;
 
 
-		/*
-		 * Standard loopback mode for SCFCR ports.
-		 */
-		reg = sci_getreg(port, SCFCR);
-		if (reg->size)
-			serial_port_out(port, SCFCR,
-					serial_port_in(port, SCFCR) |
-					SCFCR_LOOP);
-	}
-}
+	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);
+		}
 
 
-static unsigned int sci_get_mctrl(struct uart_port *port)
-{
-	/*
-	 * CTS/RTS is handled in hardware when supported, while nothing
-	 * else is wired up. Keep it simple and simply assert DSR/CAR.
-	 */
-	return TIOCM_DSR | TIOCM_CAR;
-}
+		INIT_WORK(&s->work_tx, work_fn_tx);
+	}
 
 
-#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;
+	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;
 
 
-	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+		s->chan_rx = chan;
 
 
-	spin_lock_irqsave(&port->lock, flags);
+		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;
+		}
 
 
-	xmit->tail += sg_dma_len(&s->sg_tx);
-	xmit->tail &= UART_XMIT_SIZE - 1;
+		for (i = 0; i < 2; i++) {
+			struct scatterlist *sg = &s->sg_rx[i];
 
 
-	port->icount.tx += sg_dma_len(&s->sg_tx);
+			sg_init_table(sg, 1);
+			s->rx_buf[i] = buf;
+			sg_dma_address(sg) = dma;
+			sg->length = s->buf_len_rx;
 
 
-	async_tx_ack(s->desc_tx);
-	s->desc_tx = NULL;
+			buf += s->buf_len_rx;
+			dma += s->buf_len_rx;
+		}
 
 
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(port);
+		setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
 
 
-	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);
-		}
+		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+			sci_submit_rx(s);
 	}
 	}
+}
 
 
-	spin_unlock_irqrestore(&port->lock, flags);
+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)
+{
 }
 }
 
 
-/* Locking: called with port lock held */
-static int sci_dma_rx_push(struct sci_port *s, size_t count)
+static inline void sci_free_dma(struct uart_port *port)
 {
 {
-	struct uart_port *port = &s->port;
-	struct tty_port *tport = &port->state->port;
-	int i, active, room;
+}
+#endif
 
 
-	room = tty_buffer_request_room(tport, count);
+static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
+{
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	struct uart_port *port = ptr;
+	struct sci_port *s = to_sci_port(port);
 
 
-	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 (s->chan_rx) {
+		u16 scr = serial_port_in(port, SCSCR);
+		u16 ssr = serial_port_in(port, SCxSR);
 
 
-	if (room < count)
-		dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
-			 count - room);
-	if (!room)
-		return room;
+		/* Disable future Rx interrupts */
+		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+			disable_irq_nosync(irq);
+			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 & ~(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);
 
 
-	for (i = 0; i < room; i++)
-		tty_insert_flip_char(tport, ((u8 *)sg_virt(&s->sg_rx[active]))[i],
-				     TTY_NORMAL);
+		return IRQ_HANDLED;
+	}
+#endif
 
 
-	port->icount.rx += room;
+	/* I think sci_receive_chars has to be called irrespective
+	 * of whether the I_IXOFF is set, otherwise, how is the interrupt
+	 * to be disabled?
+	 */
+	sci_receive_chars(ptr);
 
 
-	return room;
+	return IRQ_HANDLED;
 }
 }
 
 
-static void sci_dma_rx_complete(void *arg)
+static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
 {
 {
-	struct sci_port *s = arg;
-	struct uart_port *port = &s->port;
+	struct uart_port *port = ptr;
 	unsigned long flags;
 	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);
 	spin_lock_irqsave(&port->lock, flags);
+	sci_transmit_chars(port);
+	spin_unlock_irqrestore(&port->lock, flags);
 
 
-	count = sci_dma_rx_push(s, s->buf_len_rx);
+	return IRQ_HANDLED;
+}
 
 
-	mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
+static irqreturn_t sci_er_interrupt(int irq, void *ptr)
+{
+	struct uart_port *port = ptr;
+	struct sci_port *s = to_sci_port(port);
 
 
-	spin_unlock_irqrestore(&port->lock, flags);
+	/* Handle errors */
+	if (port->type == PORT_SCI) {
+		if (sci_handle_errors(port)) {
+			/* discard character in rx buffer */
+			serial_port_in(port, SCxSR);
+			sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
+		}
+	} else {
+		sci_handle_fifo_overrun(port);
+		if (!s->chan_rx)
+			sci_receive_chars(ptr);
+	}
 
 
-	if (count)
-		tty_flip_buffer_push(&port->state->port);
+	sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
+
+	/* Kick the transmission */
+	if (!s->chan_tx)
+		sci_tx_interrupt(irq, ptr);
 
 
-	schedule_work(&s->work_rx);
+	return IRQ_HANDLED;
 }
 }
 
 
-static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
+static irqreturn_t sci_br_interrupt(int irq, void *ptr)
 {
 {
-	struct dma_chan *chan = s->chan_rx;
-	struct uart_port *port = &s->port;
+	struct uart_port *port = ptr;
 
 
-	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);
+	/* Handle BREAKs */
+	sci_handle_breaks(port);
+	sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
+
+	return IRQ_HANDLED;
 }
 }
 
 
-static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
+static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 {
 {
-	struct dma_chan *chan = s->chan_tx;
-	struct uart_port *port = &s->port;
+	unsigned short ssr_status, scr_status, err_enabled, orer_status = 0;
+	struct uart_port *port = ptr;
+	struct sci_port *s = to_sci_port(port);
+	irqreturn_t ret = IRQ_NONE;
 
 
-	s->chan_tx = NULL;
-	s->cookie_tx = -EINVAL;
-	dma_release_channel(chan);
-	if (enable_pio)
-		sci_start_tx(port);
-}
+	ssr_status = serial_port_in(port, SCxSR);
+	scr_status = serial_port_in(port, SCSCR);
+	if (s->overrun_reg == SCxSR)
+		orer_status = ssr_status;
+	else {
+		if (sci_getreg(port, s->overrun_reg)->size)
+			orer_status = serial_port_in(port, s->overrun_reg);
+	}
 
 
-static void sci_submit_rx(struct sci_port *s)
-{
-	struct dma_chan *chan = s->chan_rx;
-	int i;
+	err_enabled = scr_status & port_rx_irq_mask(port);
 
 
-	for (i = 0; i < 2; i++) {
-		struct scatterlist *sg = &s->sg_rx[i];
-		struct dma_async_tx_descriptor *desc;
+	/* Tx Interrupt */
+	if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCSCR_TIE) &&
+	    !s->chan_tx)
+		ret = sci_tx_interrupt(irq, ptr);
 
 
-		desc = dmaengine_prep_slave_sg(chan,
-			sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+	/*
+	 * Rx Interrupt: if we're using DMA, the DMA controller clears RDF /
+	 * DR flags
+	 */
+	if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
+	    (scr_status & SCSCR_RIE))
+		ret = sci_rx_interrupt(irq, ptr);
 
 
-		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);
-		}
+	/* Error Interrupt */
+	if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
+		ret = sci_er_interrupt(irq, ptr);
 
 
-		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);
-	}
+	/* Break Interrupt */
+	if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
+		ret = sci_br_interrupt(irq, ptr);
 
 
-	s->active_rx = s->cookie_rx[0];
+	/* Overrun Interrupt */
+	if (orer_status & s->overrun_mask) {
+		sci_handle_fifo_overrun(port);
+		ret = IRQ_HANDLED;
+	}
 
 
-	dma_async_issue_pending(chan);
+	return ret;
 }
 }
 
 
-static void work_fn_rx(struct work_struct *work)
+/*
+ * Here we define a transition notifier so that we can update all of our
+ * ports' baud rate when the peripheral clock changes.
+ */
+static int sci_notifier(struct notifier_block *self,
+			unsigned long phase, void *p)
 {
 {
-	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];
+	struct sci_port *sci_port;
+	unsigned long flags;
 
 
-	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;
+	sci_port = container_of(self, struct sci_port, freq_transition);
 
 
-		dmaengine_terminate_all(chan);
-		dev_dbg(port->dev, "Read %zu bytes with cookie %d\n",
-			sh_desc->partial, sh_desc->cookie);
+	if (phase == CPUFREQ_POSTCHANGE) {
+		struct uart_port *port = &sci_port->port;
 
 
 		spin_lock_irqsave(&port->lock, flags);
 		spin_lock_irqsave(&port->lock, flags);
-		count = sci_dma_rx_push(s, sh_desc->partial);
+		port->uartclk = clk_get_rate(sci_port->iclk);
 		spin_unlock_irqrestore(&port->lock, flags);
 		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);
+	return NOTIFY_OK;
 }
 }
 
 
-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;
-
+static const struct sci_irq_desc {
+	const char	*desc;
+	irq_handler_t	handler;
+} sci_irq_desc[] = {
 	/*
 	/*
-	 * 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.
+	 * Split out handlers, the default case.
 	 */
 	 */
-	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);
+	[SCIx_ERI_IRQ] = {
+		.desc = "rx err",
+		.handler = sci_er_interrupt,
+	},
 
 
-	BUG_ON(!sg_dma_len(sg));
+	[SCIx_RXI_IRQ] = {
+		.desc = "rx full",
+		.handler = sci_rx_interrupt,
+	},
 
 
-	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;
-	}
+	[SCIx_TXI_IRQ] = {
+		.desc = "tx empty",
+		.handler = sci_tx_interrupt,
+	},
+
+	[SCIx_BRI_IRQ] = {
+		.desc = "break",
+		.handler = sci_br_interrupt,
+	},
+
+	/*
+	 * Special muxed handler.
+	 */
+	[SCIx_MUX_IRQ] = {
+		.desc = "mux",
+		.handler = sci_mpxed_interrupt,
+	},
+};
 
 
-	dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+static int sci_request_irq(struct sci_port *port)
+{
+	struct uart_port *up = &port->port;
+	int i, j, ret = 0;
 
 
-	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;
-	}
+	for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
+		const struct sci_irq_desc *desc;
+		int irq;
 
 
-	dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
-		__func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
+		if (SCIx_IRQ_IS_MUXED(port)) {
+			i = SCIx_MUX_IRQ;
+			irq = up->irq;
+		} else {
+			irq = port->irqs[i];
 
 
-	dma_async_issue_pending(chan);
-}
-#endif
+			/*
+			 * Certain port types won't support all of the
+			 * available interrupt sources.
+			 */
+			if (unlikely(irq < 0))
+				continue;
+		}
 
 
-static void sci_start_tx(struct uart_port *port)
-{
-	struct sci_port *s = to_sci_port(port);
-	unsigned short ctrl;
+		desc = sci_irq_desc + i;
+		port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
+					    dev_name(up->dev), desc->desc);
+		if (!port->irqstr[j])
+			goto out_nomem;
 
 
-#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);
+		ret = request_irq(irq, desc->handler, up->irqflags,
+				  port->irqstr[j], port);
+		if (unlikely(ret)) {
+			dev_err(up->dev, "Can't allocate %s IRQ\n", desc->desc);
+			goto out_noirq;
+		}
 	}
 	}
 
 
-	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
+	return 0;
 
 
-	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);
-	}
+out_noirq:
+	while (--i >= 0)
+		free_irq(port->irqs[i], port);
+
+out_nomem:
+	while (--j >= 0)
+		kfree(port->irqstr[j]);
+
+	return ret;
 }
 }
 
 
-static void sci_stop_tx(struct uart_port *port)
+static void sci_free_irq(struct sci_port *port)
 {
 {
-	unsigned short ctrl;
+	int i;
 
 
-	/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
-	ctrl = serial_port_in(port, SCSCR);
+	/*
+	 * Intentionally in reverse order so we iterate over the muxed
+	 * IRQ first.
+	 */
+	for (i = 0; i < SCIx_NR_IRQS; i++) {
+		int irq = port->irqs[i];
 
 
-	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
-		ctrl &= ~SCSCR_TDRQE;
+		/*
+		 * Certain port types won't support all of the available
+		 * interrupt sources.
+		 */
+		if (unlikely(irq < 0))
+			continue;
 
 
-	ctrl &= ~SCSCR_TIE;
+		free_irq(port->irqs[i], port);
+		kfree(port->irqstr[i]);
 
 
-	serial_port_out(port, SCSCR, ctrl);
+		if (SCIx_IRQ_IS_MUXED(port)) {
+			/* If there's only one IRQ, we're done. */
+			return;
+		}
+	}
 }
 }
 
 
-static void sci_start_rx(struct uart_port *port)
+static unsigned int sci_tx_empty(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;
+	unsigned short status = serial_port_in(port, SCxSR);
+	unsigned short in_tx_fifo = sci_txfill(port);
 
 
-	serial_port_out(port, SCSCR, ctrl);
+	return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
 }
 }
 
 
-static void sci_stop_rx(struct uart_port *port)
+/*
+ * Modem control is a bit of a mixed bag for SCI(F) ports. Generally
+ * CTS/RTS is supported in hardware by at least one port and controlled
+ * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently
+ * handled via the ->init_pins() op, which is a bit of a one-way street,
+ * lacking any ability to defer pin control -- this will later be
+ * converted over to the GPIO framework).
+ *
+ * Other modes (such as loopback) are supported generically on certain
+ * port types, but not others. For these it's sufficient to test for the
+ * existence of the support register and simply ignore the port type.
+ */
+static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 {
-	unsigned short ctrl;
-
-	ctrl = serial_port_in(port, SCSCR);
-
-	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
-		ctrl &= ~SCSCR_RDRQE;
+	if (mctrl & TIOCM_LOOP) {
+		const struct plat_sci_reg *reg;
 
 
-	ctrl &= ~port_rx_irq_mask(port);
+		/*
+		 * Standard loopback mode for SCFCR ports.
+		 */
+		reg = sci_getreg(port, SCFCR);
+		if (reg->size)
+			serial_port_out(port, SCFCR,
+					serial_port_in(port, SCFCR) |
+					SCFCR_LOOP);
+	}
+}
 
 
-	serial_port_out(port, SCSCR, ctrl);
+static unsigned int sci_get_mctrl(struct uart_port *port)
+{
+	/*
+	 * CTS/RTS is handled in hardware when supported, while nothing
+	 * else is wired up. Keep it simple and simply assert DSR/CAR.
+	 */
+	return TIOCM_DSR | TIOCM_CAR;
 }
 }
 
 
 static void sci_break_ctl(struct uart_port *port, int break_state)
 static void sci_break_ctl(struct uart_port *port, int break_state)
 {
 {
 	struct sci_port *s = to_sci_port(port);
 	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;
 	unsigned short scscr, scsptr;
 
 
 	/* check wheter the port has SCSPTR */
 	/* check wheter the port has SCSPTR */
@@ -1630,142 +1818,6 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
 	serial_port_out(port, SCSCR, scscr);
 	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)
 static int sci_startup(struct uart_port *port)
 {
 {
 	struct sci_port *s = to_sci_port(port);
 	struct sci_port *s = to_sci_port(port);
@@ -1800,6 +1852,14 @@ static void sci_shutdown(struct uart_port *port)
 	sci_stop_tx(port);
 	sci_stop_tx(port);
 	spin_unlock_irqrestore(&port->lock, flags);
 	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_dma(port);
 	sci_free_irq(s);
 	sci_free_irq(s);
 }
 }
@@ -1892,7 +1952,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
 
 
 static void sci_reset(struct uart_port *port)
 static void sci_reset(struct uart_port *port)
 {
 {
-	struct plat_sci_reg *reg;
+	const struct plat_sci_reg *reg;
 	unsigned int status;
 	unsigned int status;
 
 
 	do {
 	do {
@@ -1910,7 +1970,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 			    struct ktermios *old)
 {
 {
 	struct sci_port *s = to_sci_port(port);
 	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;
 	unsigned int baud, smr_val = 0, max_baud, cks = 0;
 	int t = -1;
 	int t = -1;
 	unsigned int srr = 15;
 	unsigned int srr = 15;
@@ -1951,7 +2011,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 
 	sci_reset(port);
 	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);
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 
@@ -1996,13 +2056,13 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 	/*
 	/*
 	 * Calculate delay for 2 DMA buffers (4 FIFO).
 	 * 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) {
 	if (s->chan_rx) {
 		unsigned int bits;
 		unsigned int bits;
@@ -2187,7 +2247,6 @@ static int sci_init_single(struct platform_device *dev,
 {
 {
 	struct uart_port *port = &sci_port->port;
 	struct uart_port *port = &sci_port->port;
 	const struct resource *res;
 	const struct resource *res;
-	unsigned int sampling_rate;
 	unsigned int i;
 	unsigned int i;
 	int ret;
 	int ret;
 
 
@@ -2232,37 +2291,37 @@ static int sci_init_single(struct platform_device *dev,
 		port->fifosize = 256;
 		port->fifosize = 256;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sampling_rate = 16;
+		sci_port->sampling_rate = 16;
 		break;
 		break;
 	case PORT_HSCIF:
 	case PORT_HSCIF:
 		port->fifosize = 128;
 		port->fifosize = 128;
-		sampling_rate = 0;
 		sci_port->overrun_reg = SCLSR;
 		sci_port->overrun_reg = SCLSR;
 		sci_port->overrun_mask = SCLSR_ORER;
 		sci_port->overrun_mask = SCLSR_ORER;
+		sci_port->sampling_rate = 0;
 		break;
 		break;
 	case PORT_SCIFA:
 	case PORT_SCIFA:
 		port->fifosize = 64;
 		port->fifosize = 64;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sampling_rate = 16;
+		sci_port->sampling_rate = 16;
 		break;
 		break;
 	case PORT_SCIF:
 	case PORT_SCIF:
 		port->fifosize = 16;
 		port->fifosize = 16;
 		if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
 		if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
 			sci_port->overrun_reg = SCxSR;
 			sci_port->overrun_reg = SCxSR;
 			sci_port->overrun_mask = SCIFA_ORER;
 			sci_port->overrun_mask = SCIFA_ORER;
-			sampling_rate = 16;
+			sci_port->sampling_rate = 16;
 		} else {
 		} else {
 			sci_port->overrun_reg = SCLSR;
 			sci_port->overrun_reg = SCLSR;
 			sci_port->overrun_mask = SCLSR_ORER;
 			sci_port->overrun_mask = SCLSR_ORER;
-			sampling_rate = 32;
+			sci_port->sampling_rate = 32;
 		}
 		}
 		break;
 		break;
 	default:
 	default:
 		port->fifosize = 1;
 		port->fifosize = 1;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCI_ORER;
 		sci_port->overrun_mask = SCI_ORER;
-		sampling_rate = 32;
+		sci_port->sampling_rate = 32;
 		break;
 		break;
 	}
 	}
 
 
@@ -2270,8 +2329,8 @@ static int sci_init_single(struct platform_device *dev,
 	 * match the SoC datasheet, this should be investigated. Let platform
 	 * match the SoC datasheet, this should be investigated. Let platform
 	 * data override the sampling rate for now.
 	 * 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) {
 	if (!early) {
 		sci_port->iclk = clk_get(&dev->dev, "sci_ick");
 		sci_port->iclk = clk_get(&dev->dev, "sci_ick");
@@ -2303,15 +2362,22 @@ static int sci_init_single(struct platform_device *dev,
 	/*
 	/*
 	 * Establish some sensible defaults for the error detection.
 	 * 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
 	 * Make the error mask inclusive of overrun detection, if
 	 * supported.
 	 * supported.
 	 */
 	 */
-	if (sci_port->overrun_reg == SCxSR)
+	if (sci_port->overrun_reg == SCxSR) {
 		sci_port->error_mask |= sci_port->overrun_mask;
 		sci_port->error_mask |= sci_port->overrun_mask;
+		sci_port->error_clear &= ~sci_port->overrun_mask;
+	}
 
 
 	port->type		= p->type;
 	port->type		= p->type;
 	port->flags		= UPF_FIXED_PORT | p->flags;
 	port->flags		= UPF_FIXED_PORT | p->flags;
@@ -2564,10 +2630,8 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
 	info = match->data;
 	info = match->data;
 
 
 	p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
 	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;
 		return NULL;
-	}
 
 
 	/* Get the line number for the aliases node. */
 	/* Get the line number for the aliases node. */
 	id = of_alias_get_id(np, "serial");
 	id = of_alias_get_id(np, "serial");

+ 16 - 33
drivers/tty/serial/sh-sci.h

@@ -54,10 +54,10 @@ enum {
 
 
 #define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
 #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 */
 /* SCxSR (Serial Status Register) on SCIF, SCIFA, SCIFB, HSCIF */
 #define SCIF_ER		BIT(7)	/* Receive Error */
 #define SCIF_ER		BIT(7)	/* Receive Error */
@@ -76,10 +76,10 @@ enum {
 
 
 #define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_BRK | SCIF_ER)
 #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) */
 /* SCFCR (FIFO Control Register) */
 #define SCFCR_MCE	BIT(3)	/* Modem Control Enable */
 #define SCFCR_MCE	BIT(3)	/* Modem Control Enable */
@@ -119,28 +119,11 @@ enum {
 
 
 #define SCxSR_ERRORS(port)	(to_sci_port(port)->error_mask)
 #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)

+ 1 - 0
drivers/tty/serial/sprd_serial.c

@@ -782,6 +782,7 @@ static const struct of_device_id serial_ids[] = {
 	{.compatible = "sprd,sc9836-uart",},
 	{.compatible = "sprd,sc9836-uart",},
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(of, serial_ids);
 
 
 static struct platform_driver sprd_platform_driver = {
 static struct platform_driver sprd_platform_driver = {
 	.probe		= sprd_probe,
 	.probe		= sprd_probe,

+ 1 - 1
drivers/tty/serial/st-asc.c

@@ -430,7 +430,7 @@ static void asc_break_ctl(struct uart_port *port, int break_state)
  */
  */
 static int asc_startup(struct uart_port *port)
 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)) {
 			asc_port_name(port), port)) {
 		dev_err(port->dev, "cannot allocate irq.\n");
 		dev_err(port->dev, "cannot allocate irq.\n");
 		return -ENODEV;
 		return -ENODEV;

+ 1 - 2
drivers/tty/serial/stm32-usart.c

@@ -322,8 +322,7 @@ static int stm32_startup(struct uart_port *port)
 	u32 val;
 	u32 val;
 	int ret;
 	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)
 	if (ret)
 		return ret;
 		return ret;
 
 

+ 5 - 15
drivers/tty/synclink.c

@@ -3314,12 +3314,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 					-EAGAIN : -ERESTARTSYS;
 					-EAGAIN : -ERESTARTSYS;
 			break;
 			break;
 		}
 		}
-		
+
 		dcd = tty_port_carrier_raised(&info->port);
 		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)) {
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			retval = -ERESTARTSYS;
 			break;
 			break;
@@ -3398,15 +3397,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
 		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
 		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 			 __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;
 	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 
 	spin_lock_irqsave(&info->netlock, flags);
 	spin_lock_irqsave(&info->netlock, flags);
@@ -6635,7 +6625,7 @@ static bool mgsl_get_rx_frame(struct mgsl_struct *info)
 			unsigned char *ptmp = info->intermediate_rxbuffer;
 			unsigned char *ptmp = info->intermediate_rxbuffer;
 
 
 			if ( !(status & RXSTATUS_CRC_ERROR))
 			if ( !(status & RXSTATUS_CRC_ERROR))
-			info->icount.rxok++;
+				info->icount.rxok++;
 			
 			
 			while(copy_count) {
 			while(copy_count) {
 				int partial_count;
 				int partial_count;

+ 2 - 12
drivers/tty/synclink_gt.c

@@ -672,15 +672,6 @@ static int open(struct tty_struct *tty, struct file *filp)
 
 
 	DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
 	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);
 	mutex_lock(&info->port.mutex);
 	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 
@@ -3320,9 +3311,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 		}
 		}
 
 
 		cd = tty_port_carrier_raised(port);
 		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
- 			break;
+		if (do_clocal || cd)
+			break;
 
 
 		if (signal_pending(current)) {
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			retval = -ERESTARTSYS;

+ 2 - 12
drivers/tty/synclinkmp.c

@@ -752,15 +752,6 @@ static int open(struct tty_struct *tty, struct file *filp)
 		printk("%s(%d):%s open(), old ref count = %d\n",
 		printk("%s(%d):%s open(), old ref count = %d\n",
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 			 __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;
 	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 
 	spin_lock_irqsave(&info->netlock, flags);
 	spin_lock_irqsave(&info->netlock, flags);
@@ -3341,9 +3332,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 		}
 		}
 
 
 		cd = tty_port_carrier_raised(port);
 		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
- 			break;
+		if (do_clocal || cd)
+			break;
 
 
 		if (signal_pending(current)) {
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			retval = -ERESTARTSYS;

+ 5 - 1
drivers/tty/sysrq.c

@@ -1003,6 +1003,10 @@ static const struct kernel_param_ops param_ops_sysrq_reset_seq = {
 #define param_check_sysrq_reset_seq(name, p)	\
 #define param_check_sysrq_reset_seq(name, p)	\
 	__param_check(name, p, unsigned short)
 	__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,
 module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq,
 			 &sysrq_reset_seq_len, 0644);
 			 &sysrq_reset_seq_len, 0644);
 
 
@@ -1119,4 +1123,4 @@ static int __init sysrq_init(void)
 
 
 	return 0;
 	return 0;
 }
 }
-module_init(sysrq_init);
+device_initcall(sysrq_init);

+ 11 - 1
drivers/tty/tty_buffer.c

@@ -403,7 +403,7 @@ void tty_schedule_flip(struct tty_port *port)
 	 * flush_to_ldisc() sees buffer data.
 	 * flush_to_ldisc() sees buffer data.
 	 */
 	 */
 	smp_store_release(&buf->tail->commit, buf->tail->used);
 	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);
 EXPORT_SYMBOL(tty_schedule_flip);
 
 
@@ -587,3 +587,13 @@ void tty_buffer_set_lock_subclass(struct tty_port *port)
 {
 {
 	lockdep_set_subclass(&port->buf.lock, TTY_LOCK_SLAVE);
 	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);
+}

+ 29 - 30
drivers/tty/tty_io.c

@@ -390,10 +390,10 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
  *	Locking: ctrl_lock
  *	Locking: ctrl_lock
  */
  */
 
 
-int tty_check_change(struct tty_struct *tty)
+int __tty_check_change(struct tty_struct *tty, int sig)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
-	struct pid *pgrp;
+	struct pid *pgrp, *tty_pgrp;
 	int ret = 0;
 	int ret = 0;
 
 
 	if (current->signal->tty != tty)
 	if (current->signal->tty != tty)
@@ -403,33 +403,35 @@ int tty_check_change(struct tty_struct *tty)
 	pgrp = task_pgrp(current);
 	pgrp = task_pgrp(current);
 
 
 	spin_lock_irqsave(&tty->ctrl_lock, flags);
 	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);
 	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();
 	rcu_read_unlock();
+
+	if (!tty_pgrp) {
+		pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n",
+			tty_name(tty), sig);
+	}
+
 	return ret;
 	return ret;
 }
 }
 
 
+int tty_check_change(struct tty_struct *tty)
+{
+	return __tty_check_change(tty, SIGTTOU);
+}
 EXPORT_SYMBOL(tty_check_change);
 EXPORT_SYMBOL(tty_check_change);
 
 
 static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
 static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
@@ -1198,11 +1200,9 @@ void tty_write_message(struct tty_struct *tty, char *msg)
 	if (tty) {
 	if (tty) {
 		mutex_lock(&tty->atomic_write_lock);
 		mutex_lock(&tty->atomic_write_lock);
 		tty_lock(tty);
 		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));
 			tty->ops->write(tty, msg, strlen(msg));
-		} else
-			tty_unlock(tty);
+		tty_unlock(tty);
 		tty_write_unlock(tty);
 		tty_write_unlock(tty);
 	}
 	}
 	return;
 	return;
@@ -1689,7 +1689,7 @@ static void release_tty(struct tty_struct *tty, int idx)
 	tty->port->itty = NULL;
 	tty->port->itty = NULL;
 	if (tty->link)
 	if (tty->link)
 		tty->link->port->itty = NULL;
 		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->link);
 	tty_kref_put(tty);
 	tty_kref_put(tty);
@@ -2569,7 +2569,6 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
 	struct pid *pgrp;
 	struct pid *pgrp;
 	pid_t pgrp_nr;
 	pid_t pgrp_nr;
 	int retval = tty_check_change(real_tty);
 	int retval = tty_check_change(real_tty);
-	unsigned long flags;
 
 
 	if (retval == -EIO)
 	if (retval == -EIO)
 		return -ENOTTY;
 		return -ENOTTY;
@@ -2592,10 +2591,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
 	if (session_of_pgrp(pgrp) != task_session(current))
 	if (session_of_pgrp(pgrp) != task_session(current))
 		goto out_unlock;
 		goto out_unlock;
 	retval = 0;
 	retval = 0;
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
+	spin_lock_irq(&tty->ctrl_lock);
 	put_pid(real_tty->pgrp);
 	put_pid(real_tty->pgrp);
 	real_tty->pgrp = get_pid(pgrp);
 	real_tty->pgrp = get_pid(pgrp);
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+	spin_unlock_irq(&tty->ctrl_lock);
 out_unlock:
 out_unlock:
 	rcu_read_unlock();
 	rcu_read_unlock();
 	return retval;
 	return retval;

+ 1 - 1
drivers/tty/tty_ldisc.c

@@ -319,7 +319,7 @@ __tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout)
 
 
 static inline void __tty_ldisc_unlock(struct tty_struct *tty)
 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
 static int __lockfunc

+ 4 - 24
drivers/tty/tty_port.c

@@ -22,7 +22,6 @@ void tty_port_init(struct tty_port *port)
 	memset(port, 0, sizeof(*port));
 	memset(port, 0, sizeof(*port));
 	tty_buffer_init(port);
 	tty_buffer_init(port);
 	init_waitqueue_head(&port->open_wait);
 	init_waitqueue_head(&port->open_wait);
-	init_waitqueue_head(&port->close_wait);
 	init_waitqueue_head(&port->delta_msr_wait);
 	init_waitqueue_head(&port->delta_msr_wait);
 	mutex_init(&port->mutex);
 	mutex_init(&port->mutex);
 	mutex_init(&port->buf_mutex);
 	mutex_init(&port->buf_mutex);
@@ -131,7 +130,7 @@ EXPORT_SYMBOL(tty_port_free_xmit_buf);
  */
  */
 void tty_port_destroy(struct tty_port *port)
 void tty_port_destroy(struct tty_port *port)
 {
 {
-	cancel_work_sync(&port->buf.work);
+	tty_buffer_cancel_work(port);
 	tty_buffer_free_all(port);
 	tty_buffer_free_all(port);
 }
 }
 EXPORT_SYMBOL(tty_port_destroy);
 EXPORT_SYMBOL(tty_port_destroy);
@@ -363,16 +362,6 @@ int tty_port_block_til_ready(struct tty_port *port,
 	unsigned long flags;
 	unsigned long flags;
 	DEFINE_WAIT(wait);
 	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
 	/* 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 */
 	   the port has just hung up or is in another error state */
 	if (tty->flags & (1 << TTY_IO_ERROR)) {
 	if (tty->flags & (1 << TTY_IO_ERROR)) {
@@ -423,8 +412,7 @@ int tty_port_block_til_ready(struct tty_port *port,
 		 * Never ask drivers if CLOCAL is set, this causes troubles
 		 * Never ask drivers if CLOCAL is set, this causes troubles
 		 * on some hardware.
 		 * on some hardware.
 		 */
 		 */
-		if (!(port->flags & ASYNC_CLOSING) &&
-				(do_clocal || tty_port_carrier_raised(port)))
+		if (do_clocal || tty_port_carrier_raised(port))
 			break;
 			break;
 		if (signal_pending(current)) {
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			retval = -ERESTARTSYS;
@@ -463,10 +451,7 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
 	schedule_timeout_interruptible(timeout);
 	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,
 int tty_port_close_start(struct tty_port *port,
 				struct tty_struct *tty, struct file *filp)
 				struct tty_struct *tty, struct file *filp)
 {
 {
@@ -502,7 +487,7 @@ int tty_port_close_start(struct tty_port *port,
 		if (tty->flow_stopped)
 		if (tty->flow_stopped)
 			tty_driver_flush_buffer(tty);
 			tty_driver_flush_buffer(tty);
 		if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		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)
 		if (port->drain_delay)
 			tty_port_drain_delay(port, tty);
 			tty_port_drain_delay(port, tty);
 	}
 	}
@@ -534,7 +519,6 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 		wake_up_interruptible(&port->open_wait);
 		wake_up_interruptible(&port->open_wait);
 	}
 	}
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-	wake_up_interruptible(&port->close_wait);
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 }
 EXPORT_SYMBOL(tty_port_close_end);
 EXPORT_SYMBOL(tty_port_close_end);
@@ -543,10 +527,6 @@ EXPORT_SYMBOL(tty_port_close_end);
  * tty_port_close
  * tty_port_close
  *
  *
  * Caller holds tty lock
  * 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,
 void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 							struct file *filp)
 							struct file *filp)

+ 4 - 2
drivers/usb/gadget/function/u_serial.c

@@ -114,6 +114,7 @@ struct gs_port {
 	struct gs_buf		port_write_buf;
 	struct gs_buf		port_write_buf;
 	wait_queue_head_t	drain_wait;	/* wait while writes drain */
 	wait_queue_head_t	drain_wait;	/* wait while writes drain */
 	bool                    write_busy;
 	bool                    write_busy;
+	wait_queue_head_t	close_wait;
 
 
 	/* REVISIT this state ... */
 	/* REVISIT this state ... */
 	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
 	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
@@ -883,7 +884,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
 	pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
 	pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
 			port->port_num, tty, file);
 			port->port_num, tty, file);
 
 
-	wake_up(&port->port.close_wait);
+	wake_up(&port->close_wait);
 exit:
 exit:
 	spin_unlock_irq(&port->port_lock);
 	spin_unlock_irq(&port->port_lock);
 }
 }
@@ -1043,6 +1044,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
 	tty_port_init(&port->port);
 	tty_port_init(&port->port);
 	spin_lock_init(&port->port_lock);
 	spin_lock_init(&port->port_lock);
 	init_waitqueue_head(&port->drain_wait);
 	init_waitqueue_head(&port->drain_wait);
+	init_waitqueue_head(&port->close_wait);
 
 
 	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
 	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
 
 
@@ -1073,7 +1075,7 @@ static void gserial_free_port(struct gs_port *port)
 {
 {
 	tasklet_kill(&port->push);
 	tasklet_kill(&port->push);
 	/* wait for old opens to finish */
 	/* 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);
 	WARN_ON(port->port_usb != NULL);
 	tty_port_destroy(&port->port);
 	tty_port_destroy(&port->port);
 	kfree(port);
 	kfree(port);

+ 10 - 1
include/linux/dma/hsu.h

@@ -35,14 +35,23 @@ struct hsu_dma_chip {
 	unsigned int			length;
 	unsigned int			length;
 	unsigned int			offset;
 	unsigned int			offset;
 	struct hsu_dma			*hsu;
 	struct hsu_dma			*hsu;
-	struct hsu_dma_platform_data	*pdata;
 };
 };
 
 
+#if IS_ENABLED(CONFIG_HSU_DMA)
 /* Export to the internal users */
 /* Export to the internal users */
 irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
 irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
 
 
 /* Export to the platform drivers */
 /* Export to the platform drivers */
 int hsu_dma_probe(struct hsu_dma_chip *chip);
 int hsu_dma_probe(struct hsu_dma_chip *chip);
 int hsu_dma_remove(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 */
 #endif /* _DMA_HSU_H */

+ 3 - 5
include/linux/n_r3964.h

@@ -152,9 +152,6 @@ struct r3964_info {
 	unsigned char *rx_buf;            /* ring buffer */
 	unsigned char *rx_buf;            /* ring buffer */
 	unsigned char *tx_buf;
 	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_first;
 	struct r3964_block_header *rx_last;
 	struct r3964_block_header *rx_last;
 	struct r3964_block_header *tx_first;
 	struct r3964_block_header *tx_first;
@@ -164,8 +161,9 @@ struct r3964_info {
 	unsigned char last_rx;
 	unsigned char last_rx;
 	unsigned char bcc;
 	unsigned char bcc;
         unsigned int  blocks_in_rx_queue;
         unsigned int  blocks_in_rx_queue;
-	  
-	
+
+	struct mutex read_lock;		/* serialize r3964_read */
+
 	struct r3964_client_info *firstClient;
 	struct r3964_client_info *firstClient;
 	unsigned int state;
 	unsigned int state;
 	unsigned int flags;
 	unsigned int flags;

+ 0 - 6
include/linux/platform_data/atmel.h

@@ -19,12 +19,6 @@
 #include <linux/serial.h>
 #include <linux/serial.h>
 #include <linux/platform_data/macb.h>
 #include <linux/platform_data/macb.h>
 
 
-/*
- * at91: 6 USARTs and one DBGU port (SAM9260)
- * avr32: 4
- */
-#define ATMEL_MAX_UART	7
-
  /* Compact Flash */
  /* Compact Flash */
 struct at91_cf_data {
 struct at91_cf_data {
 	int	irq_pin;		/* I/O IRQ */
 	int	irq_pin;		/* I/O IRQ */

+ 0 - 4
include/linux/platform_data/dma-hsu.h

@@ -18,8 +18,4 @@ struct hsu_dma_slave {
 	int		chan_id;
 	int		chan_id;
 };
 };
 
 
-struct hsu_dma_platform_data {
-	unsigned short	nr_channels;
-};
-
 #endif /* _PLATFORM_DATA_DMA_HSU_H */
 #endif /* _PLATFORM_DATA_DMA_HSU_H */

+ 3 - 45
include/linux/tty.h

@@ -227,7 +227,6 @@ struct tty_port {
 	int			blocked_open;	/* Waiting to open */
 	int			blocked_open;	/* Waiting to open */
 	int			count;		/* Usage count */
 	int			count;		/* Usage count */
 	wait_queue_head_t	open_wait;	/* Open waiters */
 	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 */
 	wait_queue_head_t	delta_msr_wait;	/* Modem status change */
 	unsigned long		flags;		/* TTY flags ASY_*/
 	unsigned long		flags;		/* TTY flags ASY_*/
 	unsigned char		console:1,	/* port is a console */
 	unsigned char		console:1,	/* port is a console */
@@ -424,6 +423,7 @@ extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
 			      const char *routine);
 			      const char *routine);
 extern const char *tty_name(const struct tty_struct *tty);
 extern const char *tty_name(const struct tty_struct *tty);
 extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
 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 int tty_check_change(struct tty_struct *tty);
 extern void __stop_tty(struct tty_struct *tty);
 extern void __stop_tty(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_free_all(struct tty_port *port);
 extern void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
 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_init(struct tty_port *port);
 extern void tty_buffer_set_lock_subclass(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_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_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,
 extern void tty_termios_encode_baud_rate(struct ktermios *termios,
@@ -656,50 +658,6 @@ extern void __lockfunc tty_unlock(struct tty_struct *tty);
 extern void __lockfunc tty_lock_slave(struct tty_struct *tty);
 extern void __lockfunc tty_lock_slave(struct tty_struct *tty);
 extern void __lockfunc tty_unlock_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);
 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
 #ifdef CONFIG_PROC_FS
 extern void proc_tty_register_driver(struct tty_driver *);
 extern void proc_tty_register_driver(struct tty_driver *);

+ 1 - 30
net/irda/ircomm/ircomm_tty.c

@@ -335,8 +335,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
 		 * specified, we cannot return before the IrCOMM link is
 		 * specified, we cannot return before the IrCOMM link is
 		 * ready
 		 * 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)
 		    self->state == IRCOMM_TTY_READY)
 		{
 		{
 			break;
 			break;
@@ -443,34 +442,6 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
 	/* Not really used by us, but lets do it anyway */
 	/* Not really used by us, but lets do it anyway */
 	self->port.low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 	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 */
 	/* Check if this is a "normal" ircomm device, or an irlpt device */
 	if (self->line < 0x10) {
 	if (self->line < 0x10) {
 		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
 		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;