Просмотр исходного кода

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

Pull tty/serial driver updates from Greg KH:
 "Here's the tty and serial driver patches for 4.2-rc1.

  A number of individual driver updates, some code cleanups, and other
  minor things, full details in the shortlog.

  All have been in linux-next for a while with no reported issues"

* tag 'tty-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (152 commits)
  Doc: serial-rs485.txt: update RS485 driver interface
  Doc: tty.txt: remove mention of the BKL
  MAINTAINERS: tty: add serial docs directory
  serial: sprd: check for NULL after calling devm_clk_get
  serial: 8250_pci: Correct uartclk for xr17v35x expansion chips
  serial: 8250_pci: Add support for 12 port Exar boards
  serial: 8250_uniphier: add bindings document for UniPhier UART
  serial: core: cleanup in uart_get_baud_rate()
  serial: stm32-usart: Add STM32 USART Driver
  tty/serial: kill off set_irq_flags usage
  tty: move linux/gsmmux.h to uapi
  doc: dt: add documentation for nxp,lpc1850-uart
  serial: 8250: add LPC18xx/43xx UART driver
  serial: 8250_uniphier: add UniPhier serial driver
  serial: 8250_dw: support ACPI platforms with integrated DMA engine
  serial: of_serial: check the return value of clk_prepare_enable()
  serial: of_serial: use devm_clk_get() instead of clk_get()
  serial: earlycon: Add support for big-endian MMIO accesses
  serial: sirf: use hrtimer for data rx
  serial: sirf: correct the fifo empty_bit
  ...
Linus Torvalds 10 лет назад
Родитель
Сommit
8c7febe839
97 измененных файлов с 3233 добавлено и 1802 удалено
  1. 10 0
      Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt
  2. 10 2
      Documentation/devicetree/bindings/serial/mtk-uart.txt
  3. 28 0
      Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt
  4. 37 0
      Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt
  5. 7 0
      Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
  6. 1 14
      Documentation/devicetree/bindings/serial/sirf-uart.txt
  7. 23 0
      Documentation/devicetree/bindings/serial/uniphier-uart.txt
  8. 5 4
      Documentation/kernel-parameters.txt
  9. 5 45
      Documentation/serial/serial-rs485.txt
  10. 0 3
      Documentation/serial/tty.txt
  11. 1 0
      MAINTAINERS
  12. 1 1
      arch/alpha/include/asm/serial.h
  13. 3 0
      arch/arm/common/edma.c
  14. 4 4
      arch/blackfin/include/asm/bfin_serial.h
  15. 1 1
      arch/m68k/include/asm/serial.h
  16. 2 2
      arch/mn10300/include/asm/serial.h
  17. 1 1
      arch/x86/include/asm/serial.h
  18. 1 6
      drivers/dma/edma.c
  19. 2 3
      drivers/input/serio/serport.c
  20. 4 7
      drivers/tty/amiserial.c
  21. 2 6
      drivers/tty/cyclades.c
  22. 0 7
      drivers/tty/hvc/Kconfig
  23. 0 1
      drivers/tty/hvc/Makefile
  24. 0 134
      drivers/tty/hvc/hvc_beat.c
  25. 2 1
      drivers/tty/hvc/hvc_console.c
  26. 2 2
      drivers/tty/hvc/hvcs.c
  27. 2 3
      drivers/tty/n_gsm.c
  28. 2 5
      drivers/tty/n_tty.c
  29. 4 4
      drivers/tty/nozomi.c
  30. 1 1
      drivers/tty/rocket.h
  31. 2 1
      drivers/tty/serial/68328serial.c
  32. 10 17
      drivers/tty/serial/8250/8250_core.c
  33. 18 1
      drivers/tty/serial/8250/8250_dw.c
  34. 1 1
      drivers/tty/serial/8250/8250_early.c
  35. 230 0
      drivers/tty/serial/8250/8250_lpc18xx.c
  36. 75 44
      drivers/tty/serial/8250/8250_mtk.c
  37. 49 16
      drivers/tty/serial/8250/8250_omap.c
  38. 39 2
      drivers/tty/serial/8250/8250_pci.c
  39. 257 0
      drivers/tty/serial/8250/8250_uniphier.c
  40. 15 0
      drivers/tty/serial/8250/Kconfig
  41. 2 0
      drivers/tty/serial/8250/Makefile
  42. 54 18
      drivers/tty/serial/Kconfig
  43. 2 2
      drivers/tty/serial/Makefile
  44. 1 1
      drivers/tty/serial/altera_jtaguart.c
  45. 1 1
      drivers/tty/serial/altera_uart.c
  46. 419 232
      drivers/tty/serial/amba-pl011.c
  47. 10 12
      drivers/tty/serial/atmel_serial.c
  48. 12 12
      drivers/tty/serial/bfin_uart.c
  49. 14 92
      drivers/tty/serial/crisv10.c
  50. 6 3
      drivers/tty/serial/earlycon.c
  51. 6 5
      drivers/tty/serial/icom.c
  52. 9 10
      drivers/tty/serial/ifx6x60.c
  53. 8 10
      drivers/tty/serial/imx.c
  54. 2 1
      drivers/tty/serial/ioc3_serial.c
  55. 6 3
      drivers/tty/serial/ioc4_serial.c
  56. 3 3
      drivers/tty/serial/kgdb_nmi.c
  57. 1 1
      drivers/tty/serial/mcf.c
  58. 1 1
      drivers/tty/serial/meson_uart.c
  59. 1 1
      drivers/tty/serial/mpc52xx_uart.c
  60. 16 9
      drivers/tty/serial/mpsc.c
  61. 0 232
      drivers/tty/serial/msm_smd_tty.c
  62. 1 1
      drivers/tty/serial/mxs-auart.c
  63. 5 3
      drivers/tty/serial/of_serial.c
  64. 2 2
      drivers/tty/serial/samsung.c
  65. 243 85
      drivers/tty/serial/sc16is7xx.c
  66. 97 61
      drivers/tty/serial/serial-tegra.c
  67. 22 10
      drivers/tty/serial/serial_core.c
  68. 1 1
      drivers/tty/serial/serial_ks8695.c
  69. 2 3
      drivers/tty/serial/serial_mctrl_gpio.c
  70. 51 45
      drivers/tty/serial/sh-sci.c
  71. 124 16
      drivers/tty/serial/sh-sci.h
  72. 281 341
      drivers/tty/serial/sirfsoc_uart.c
  73. 54 66
      drivers/tty/serial/sirfsoc_uart.h
  74. 1 1
      drivers/tty/serial/sprd_serial.c
  75. 739 0
      drivers/tty/serial/stm32-usart.c
  76. 2 1
      drivers/tty/serial/xilinx_uartps.c
  77. 10 5
      drivers/tty/synclink.c
  78. 10 5
      drivers/tty/synclink_gt.c
  79. 8 4
      drivers/tty/synclinkmp.c
  80. 2 1
      drivers/tty/tty_buffer.c
  81. 13 21
      drivers/tty/tty_io.c
  82. 1 3
      drivers/tty/tty_ioctl.c
  83. 3 5
      drivers/tty/tty_ldisc.c
  84. 2 1
      drivers/tty/tty_ldsem.c
  85. 37 23
      drivers/tty/vt/consolemap.c
  86. 62 30
      drivers/tty/vt/vt.c
  87. 3 2
      drivers/video/console/fbcon.c
  88. 1 0
      drivers/video/console/fbcon.h
  89. 1 0
      include/linux/console_struct.h
  90. 3 0
      include/linux/serial_8250.h
  91. 1 1
      include/linux/serial_core.h
  92. 11 75
      include/linux/serial_sci.h
  93. 1 1
      include/linux/tty.h
  94. 1 0
      include/uapi/linux/Kbuild
  95. 3 0
      include/uapi/linux/gsmmux.h
  96. 3 0
      include/uapi/linux/serial_core.h
  97. 1 1
      include/uapi/linux/tty_flags.h

+ 10 - 0
Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt

@@ -0,0 +1,10 @@
+* ARM SBSA defined generic UART
+This UART uses a subset of the PL011 registers and consequently lives
+in the PL011 driver. It's baudrate and other communication parameters
+cannot be adjusted at runtime, so it lacks a clock specifier here.
+
+Required properties:
+- compatible: must be "arm,sbsa-uart"
+- reg: exactly one register range
+- interrupts: exactly one interrupt specifier
+- current-speed: the (fixed) baud rate set by the firmware

+ 10 - 2
Documentation/devicetree/bindings/serial/mtk-uart.txt

@@ -14,7 +14,14 @@ Required properties:
 
 
 - interrupts: A single interrupt specifier.
 - interrupts: A single interrupt specifier.
 
 
-- clocks: Clock driving the hardware.
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names:
+  - "baud": The clock the baudrate is derived from
+  - "bus": The bus clock for register accesses (optional)
+
+For compatibility with older device trees an unnamed clock is used for the
+baud clock if the baudclk does not exist. Do not use this for new designs.
 
 
 Example:
 Example:
 
 
@@ -22,5 +29,6 @@ Example:
 		compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
 		compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
 		reg = <0x11006000 0x400>;
 		reg = <0x11006000 0x400>;
 		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
 		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&uart_clk>, <&bus_clk>;
+		clock-names = "baud", "bus";
 	};
 	};

+ 28 - 0
Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt

@@ -0,0 +1,28 @@
+* NXP LPC1850 UART
+
+Required properties:
+- compatible	: "nxp,lpc1850-uart", "ns16550a".
+- reg		: offset and length of the register set for the device.
+- interrupts	: should contain uart interrupt.
+- clocks	: phandle to the input clocks.
+- clock-names	: required elements: "uartclk", "reg".
+
+Optional properties:
+- dmas		: Two or more DMA channel specifiers following the
+		  convention outlined in bindings/dma/dma.txt
+- dma-names	: Names for the dma channels, if present. There must
+		  be at least one channel named "tx" for transmit
+		  and named "rx" for receive.
+
+Since it's also possible to also use the of_serial.c driver all
+parameters from 8250.txt also apply but are optional.
+
+Example:
+uart0: serial@40081000 {
+	compatible = "nxp,lpc1850-uart", "ns16550a";
+	reg = <0x40081000 0x1000>;
+	reg-shift = <2>;
+	interrupts = <24>;
+	clocks = <&ccu2 CLK_APB0_UART0>, <&ccu1 CLK_CPU_UART0>;
+	clock-names = "uartclk", "reg";
+};

+ 37 - 0
Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt

@@ -1,4 +1,5 @@
 * NXP SC16IS7xx advanced Universal Asynchronous Receiver-Transmitter (UART)
 * NXP SC16IS7xx advanced Universal Asynchronous Receiver-Transmitter (UART)
+* i2c as bus
 
 
 Required properties:
 Required properties:
 - compatible: Should be one of the following:
 - compatible: Should be one of the following:
@@ -31,3 +32,39 @@ Example:
                 gpio-controller;
                 gpio-controller;
                 #gpio-cells = <2>;
                 #gpio-cells = <2>;
         };
         };
+
+* spi as bus
+
+Required properties:
+- compatible: Should be one of the following:
+  - "nxp,sc16is740" for NXP SC16IS740,
+  - "nxp,sc16is741" for NXP SC16IS741,
+  - "nxp,sc16is750" for NXP SC16IS750,
+  - "nxp,sc16is752" for NXP SC16IS752,
+  - "nxp,sc16is760" for NXP SC16IS760,
+  - "nxp,sc16is762" for NXP SC16IS762.
+- reg: SPI chip select number.
+- interrupt-parent: The phandle for the interrupt controller that
+  services interrupts for this IC.
+- interrupts: Specifies the interrupt source of the parent interrupt
+  controller. The format of the interrupt specifier depends on the
+  parent interrupt controller.
+- clocks: phandle to the IC source clock.
+
+Optional properties:
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells: Should be two. The first cell is the GPIO number and
+  the second cell is used to specify the GPIO polarity:
+    0 = active high,
+    1 = active low.
+
+Example:
+	sc16is750: sc16is750@0 {
+		compatible = "nxp,sc16is750";
+		reg = <0>;
+		clocks = <&clk20m>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};

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

@@ -45,6 +45,11 @@ Required properties:
 Note: Each enabled SCIx UART should have an alias correctly numbered in the
 Note: Each enabled SCIx UART should have an alias correctly numbered in the
 "aliases" node.
 "aliases" node.
 
 
+Optional properties:
+  - dmas: Must contain a list of two references to DMA specifiers, one for
+	  transmission, and one for reception.
+  - dma-names: Must contain a list of two DMA names, "tx" and "rx".
+
 Example:
 Example:
 	aliases {
 	aliases {
 		serial0 = &scifa0;
 		serial0 = &scifa0;
@@ -57,4 +62,6 @@ Example:
 		interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
 		interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
 		clock-names = "sci_ick";
 		clock-names = "sci_ick";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
+		dma-names = "tx", "rx";
 	};
 	};

+ 1 - 14
Documentation/devicetree/bindings/serial/sirf-uart.txt

@@ -2,8 +2,7 @@
 
 
 Required properties:
 Required properties:
 - compatible : Should be "sirf,prima2-uart", "sirf, prima2-usp-uart",
 - compatible : Should be "sirf,prima2-uart", "sirf, prima2-usp-uart",
-		"sirf,atlas7-uart" or "sirf,atlas7-bt-uart" which means
-		uart located in BT module and used for BT.
+		"sirf,atlas7-uart" or "sirf,atlas7-usp-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
 - fifosize : Should define hardware rx/tx fifo size
 - fifosize : Should define hardware rx/tx fifo size
@@ -33,15 +32,3 @@ usp@b0090000 {
 	rts-gpios = <&gpio 15 0>;
 	rts-gpios = <&gpio 15 0>;
 	cts-gpios = <&gpio 46 0>;
 	cts-gpios = <&gpio 46 0>;
 };
 };
-
-for uart use in BT module,
-uart6: uart@11000000 {
-	cell-index = <6>;
-	compatible = "sirf,atlas7-bt-uart", "sirf,atlas7-uart";
-	reg = <0x11000000 0x1000>;
-	interrupts = <0 100 0>;
-	clocks = <&clks 138>, <&clks 140>, <&clks 141>;
-	clock-names = "uart", "general", "noc";
-	fifosize = <128>;
-	status = "disabled";
-}

+ 23 - 0
Documentation/devicetree/bindings/serial/uniphier-uart.txt

@@ -0,0 +1,23 @@
+UniPhier UART controller
+
+Required properties:
+- compatible: should be "socionext,uniphier-uart".
+- reg: offset and length of the register set for the device.
+- interrupts: a single interrupt specifier.
+- clocks: phandle to the input clock.
+
+Optional properties:
+- fifo-size: the RX/TX FIFO size.  Defaults to 64 if not specified.
+
+Example:
+	aliases {
+		serial0 = &serial0;
+	};
+
+	serial0: serial@54006800 {
+		compatible = "socionext,uniphier-uart";
+		reg = <0x54006800 0x40>;
+		interrupts = <0 33 4>;
+		clocks = <&uart_clk>;
+		fifo-size = <64>;
+	};

+ 5 - 4
Documentation/kernel-parameters.txt

@@ -972,14 +972,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 		uart[8250],io,<addr>[,options]
 		uart[8250],io,<addr>[,options]
 		uart[8250],mmio,<addr>[,options]
 		uart[8250],mmio,<addr>[,options]
 		uart[8250],mmio32,<addr>[,options]
 		uart[8250],mmio32,<addr>[,options]
+		uart[8250],mmio32be,<addr>[,options]
 		uart[8250],0x<addr>[,options]
 		uart[8250],0x<addr>[,options]
 			Start an early, polled-mode console on the 8250/16550
 			Start an early, polled-mode console on the 8250/16550
 			UART at the specified I/O port or MMIO address.
 			UART at the specified I/O port or MMIO address.
 			MMIO inter-register address stride is either 8-bit
 			MMIO inter-register address stride is either 8-bit
-			(mmio) or 32-bit (mmio32).
-			If none of [io|mmio|mmio32], <addr> is assumed to be
-			equivalent to 'mmio'. 'options' are specified in the
-			same format described for "console=ttyS<n>"; if
+			(mmio) or 32-bit (mmio32 or mmio32be).
+			If none of [io|mmio|mmio32|mmio32be], <addr> is assumed
+			to be equivalent to 'mmio'. 'options' are specified
+			in the same format described for "console=ttyS<n>"; if
 			unspecified, the h/w is not initialized.
 			unspecified, the h/w is not initialized.
 
 
 		pl011,<addr>
 		pl011,<addr>

+ 5 - 45
Documentation/serial/serial-rs485.txt

@@ -33,50 +33,10 @@
    the values given by the device tree.
    the values given by the device tree.
 
 
    Any driver for devices capable of working both as RS232 and RS485 should
    Any driver for devices capable of working both as RS232 and RS485 should
-   provide at least the following ioctls:
-
-    - TIOCSRS485 (typically associated with number 0x542F). This ioctl is used
-      to enable/disable RS485 mode from user-space
-
-    - TIOCGRS485 (typically associated with number 0x542E). This ioctl is used
-      to get RS485 mode from kernel-space (i.e., driver) to user-space.
-
-   In other words, the serial driver should contain a code similar to the next
-   one:
-
-	static struct uart_ops atmel_pops = {
-		/* ... */
-		.ioctl		= handle_ioctl,
-	};
-
-	static int handle_ioctl(struct uart_port *port,
-		unsigned int cmd,
-		unsigned long arg)
-	{
-		struct serial_rs485 rs485conf;
-
-		switch (cmd) {
-		case TIOCSRS485:
-			if (copy_from_user(&rs485conf,
-				(struct serial_rs485 *) arg,
-				sizeof(rs485conf)))
-					return -EFAULT;
-
-			/* ... */
-			break;
-
-		case TIOCGRS485:
-			if (copy_to_user((struct serial_rs485 *) arg,
-				...,
-				sizeof(rs485conf)))
-					return -EFAULT;
-			/* ... */
-			break;
-
-		/* ... */
-		}
-	}
-
+   implement the rs485_config callback in the uart_port structure. The
+   serial_core calls rs485_config to do the device specific part in response
+   to TIOCSRS485 and TIOCGRS485 ioctls (see below). The rs485_config callback
+   receives a pointer to struct serial_rs485.
 
 
 4. USAGE FROM USER-LEVEL
 4. USAGE FROM USER-LEVEL
 
 
@@ -85,7 +45,7 @@
 
 
 	#include <linux/serial.h>
 	#include <linux/serial.h>
 
 
-	/* Driver-specific ioctls: */
+	/* RS485 ioctls: */
 	#define TIOCGRS485      0x542E
 	#define TIOCGRS485      0x542E
 	#define TIOCSRS485      0x542F
 	#define TIOCSRS485      0x542F
 
 

+ 0 - 3
Documentation/serial/tty.txt

@@ -4,9 +4,6 @@
 Your guide to the ancient and twisted locking policies of the tty layer and
 Your guide to the ancient and twisted locking policies of the tty layer and
 the warped logic behind them. Beware all ye who read on.
 the warped logic behind them. Beware all ye who read on.
 
 
-FIXME: still need to work out the full set of BKL assumptions and document
-them so they can eventually be killed off.
-
 
 
 Line Discipline
 Line Discipline
 ---------------
 ---------------

+ 1 - 0
MAINTAINERS

@@ -10316,6 +10316,7 @@ M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 M:	Jiri Slaby <jslaby@suse.cz>
 M:	Jiri Slaby <jslaby@suse.cz>
 S:	Supported
 S:	Supported
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
+F:	Documentation/serial/
 F:	drivers/tty/
 F:	drivers/tty/
 F:	drivers/tty/serial/serial_core.c
 F:	drivers/tty/serial/serial_core.c
 F:	include/linux/serial_core.h
 F:	include/linux/serial_core.h

+ 1 - 1
arch/alpha/include/asm/serial.h

@@ -13,7 +13,7 @@
 #define BASE_BAUD ( 1843200 / 16 )
 #define BASE_BAUD ( 1843200 / 16 )
 
 
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
 #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
 #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
 #else
 #else

+ 3 - 0
arch/arm/common/edma.c

@@ -1350,6 +1350,9 @@ void edma_stop(unsigned channel)
 		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
 		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
 		edma_write_array(ctlr, EDMA_EMCR, j, mask);
 		edma_write_array(ctlr, EDMA_EMCR, j, mask);
 
 
+		/* clear possibly pending completion interrupt */
+		edma_shadow0_write_array(ctlr, SH_ICR, j, mask);
+
 		pr_debug("EDMA: EER%d %08x\n", j,
 		pr_debug("EDMA: EER%d %08x\n", j,
 				edma_shadow0_read_array(ctlr, SH_EER, j));
 				edma_shadow0_read_array(ctlr, SH_EER, j));
 
 

+ 4 - 4
arch/blackfin/include/asm/bfin_serial.h

@@ -22,9 +22,9 @@
     defined(CONFIG_BFIN_UART2_CTSRTS) || \
     defined(CONFIG_BFIN_UART2_CTSRTS) || \
     defined(CONFIG_BFIN_UART3_CTSRTS)
     defined(CONFIG_BFIN_UART3_CTSRTS)
 # if defined(BFIN_UART_BF54X_STYLE) || defined(BFIN_UART_BF60X_STYLE)
 # if defined(BFIN_UART_BF54X_STYLE) || defined(BFIN_UART_BF60X_STYLE)
-#  define CONFIG_SERIAL_BFIN_HARD_CTSRTS
+#  define SERIAL_BFIN_HARD_CTSRTS
 # else
 # else
-#  define CONFIG_SERIAL_BFIN_CTSRTS
+#  define SERIAL_BFIN_CTSRTS
 # endif
 # endif
 #endif
 #endif
 
 
@@ -50,8 +50,8 @@ struct bfin_serial_port {
 #elif ANOMALY_05000363
 #elif ANOMALY_05000363
 	unsigned int anomaly_threshold;
 	unsigned int anomaly_threshold;
 #endif
 #endif
-#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
-	defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
+#if defined(SERIAL_BFIN_CTSRTS) || \
+	defined(SERIAL_BFIN_HARD_CTSRTS)
 	int cts_pin;
 	int cts_pin;
 	int rts_pin;
 	int rts_pin;
 #endif
 #endif

+ 1 - 1
arch/m68k/include/asm/serial.h

@@ -17,7 +17,7 @@
 #define BASE_BAUD ( 1843200 / 16 )
 #define BASE_BAUD ( 1843200 / 16 )
 
 
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
 #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
 #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
 #else
 #else

+ 2 - 2
arch/mn10300/include/asm/serial.h

@@ -13,7 +13,7 @@
 #define _ASM_SERIAL_H
 #define _ASM_SERIAL_H
 
 
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
 #define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
 #define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
 #define STD_COM4_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
 #define STD_COM4_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
 #else
 #else
@@ -21,7 +21,7 @@
 #define STD_COM4_FLAGS	ASYNC_BOOT_AUTOCONF
 #define STD_COM4_FLAGS	ASYNC_BOOT_AUTOCONF
 #endif
 #endif
 
 
-#ifdef CONFIG_SERIAL_MANY_PORTS
+#ifdef CONFIG_SERIAL_8250_MANY_PORTS
 #define FOURPORT_FLAGS	ASYNC_FOURPORT
 #define FOURPORT_FLAGS	ASYNC_FOURPORT
 #define ACCENT_FLAGS	0
 #define ACCENT_FLAGS	0
 #define BOCA_FLAGS	0
 #define BOCA_FLAGS	0

+ 1 - 1
arch/x86/include/asm/serial.h

@@ -11,7 +11,7 @@
 #define BASE_BAUD (1843200/16)
 #define BASE_BAUD (1843200/16)
 
 
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
 # define STD_COMX_FLAGS	(UPF_BOOT_AUTOCONF |	UPF_SKIP_TEST	| UPF_AUTO_IRQ)
 # define STD_COMX_FLAGS	(UPF_BOOT_AUTOCONF |	UPF_SKIP_TEST	| UPF_AUTO_IRQ)
 # define STD_COM4_FLAGS	(UPF_BOOT_AUTOCONF |	0		| UPF_AUTO_IRQ)
 # define STD_COM4_FLAGS	(UPF_BOOT_AUTOCONF |	0		| UPF_AUTO_IRQ)
 #else
 #else

+ 1 - 6
drivers/dma/edma.c

@@ -300,8 +300,7 @@ static int edma_dma_pause(struct dma_chan *chan)
 {
 {
 	struct edma_chan *echan = to_edma_chan(chan);
 	struct edma_chan *echan = to_edma_chan(chan);
 
 
-	/* Pause/Resume only allowed with cyclic mode */
-	if (!echan->edesc || !echan->edesc->cyclic)
+	if (!echan->edesc)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	edma_pause(echan->ch_num);
 	edma_pause(echan->ch_num);
@@ -312,10 +311,6 @@ static int edma_dma_resume(struct dma_chan *chan)
 {
 {
 	struct edma_chan *echan = to_edma_chan(chan);
 	struct edma_chan *echan = to_edma_chan(chan);
 
 
-	/* Pause/Resume only allowed with cyclic mode */
-	if (!echan->edesc->cyclic)
-		return -EINVAL;
-
 	edma_resume(echan->ch_num);
 	edma_resume(echan->ch_num);
 	return 0;
 	return 0;
 }
 }

+ 2 - 3
drivers/input/serio/serport.c

@@ -167,7 +167,6 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
 {
 {
 	struct serport *serport = (struct serport*) tty->disc_data;
 	struct serport *serport = (struct serport*) tty->disc_data;
 	struct serio *serio;
 	struct serio *serio;
-	char name[64];
 
 
 	if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
 	if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
 		return -EBUSY;
 		return -EBUSY;
@@ -177,7 +176,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	strlcpy(serio->name, "Serial port", sizeof(serio->name));
 	strlcpy(serio->name, "Serial port", sizeof(serio->name));
-	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
+	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty));
 	serio->id = serport->id;
 	serio->id = serport->id;
 	serio->id.type = SERIO_RS232;
 	serio->id.type = SERIO_RS232;
 	serio->write = serport_serio_write;
 	serio->write = serport_serio_write;
@@ -187,7 +186,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
 	serio->dev.parent = tty->dev;
 	serio->dev.parent = tty->dev;
 
 
 	serio_register_port(serport->serio);
 	serio_register_port(serport->serio);
-	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
+	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty));
 
 
 	wait_event_interruptible(serport->wait, test_bit(SERPORT_DEAD, &serport->flags));
 	wait_event_interruptible(serport->wait, test_bit(SERPORT_DEAD, &serport->flags));
 	serio_unregister_port(serport->serio);
 	serio_unregister_port(serport->serio);

+ 4 - 7
drivers/tty/amiserial.c

@@ -966,9 +966,7 @@ static void rs_throttle(struct tty_struct * tty)
 	struct serial_state *info = tty->driver_data;
 	struct serial_state *info = tty->driver_data;
 	unsigned long flags;
 	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
 #ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	printk("throttle %s: %d....\n", tty_name(tty),
 	       tty->ldisc.chars_in_buffer(tty));
 	       tty->ldisc.chars_in_buffer(tty));
 #endif
 #endif
 
 
@@ -991,9 +989,7 @@ static void rs_unthrottle(struct tty_struct * tty)
 	struct serial_state *info = tty->driver_data;
 	struct serial_state *info = tty->driver_data;
 	unsigned long flags;
 	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
 #ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("unthrottle %s: %d....\n", tty_name(tty, buf),
+	printk("unthrottle %s: %d....\n", tty_name(tty),
 	       tty->ldisc.chars_in_buffer(tty));
 	       tty->ldisc.chars_in_buffer(tty));
 #endif
 #endif
 
 
@@ -1786,7 +1782,8 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
 	struct serial_state *state = platform_get_drvdata(pdev);
 	struct serial_state *state = platform_get_drvdata(pdev);
 
 
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
-	if ((error = tty_unregister_driver(serial_driver)))
+	error = tty_unregister_driver(serial_driver);
+	if (error)
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       error);
 		       error);
 	put_tty_driver(serial_driver);
 	put_tty_driver(serial_driver);

+ 2 - 6
drivers/tty/cyclades.c

@@ -2861,9 +2861,7 @@ static void cy_throttle(struct tty_struct *tty)
 	unsigned long flags;
 	unsigned long flags;
 
 
 #ifdef CY_DEBUG_THROTTLE
 #ifdef CY_DEBUG_THROTTLE
-	char buf[64];
-
-	printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf),
+	printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty),
 			tty->ldisc.chars_in_buffer(tty), info->line);
 			tty->ldisc.chars_in_buffer(tty), info->line);
 #endif
 #endif
 
 
@@ -2902,10 +2900,8 @@ static void cy_unthrottle(struct tty_struct *tty)
 	unsigned long flags;
 	unsigned long flags;
 
 
 #ifdef CY_DEBUG_THROTTLE
 #ifdef CY_DEBUG_THROTTLE
-	char buf[64];
-
 	printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
 	printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
-		tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
+		tty_name(tty), tty_chars_in_buffer(tty), info->line);
 #endif
 #endif
 
 
 	if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
 	if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))

+ 0 - 7
drivers/tty/hvc/Kconfig

@@ -42,13 +42,6 @@ config HVC_RTAS
 	help
 	help
 	  IBM Console device driver which makes use of RTAS
 	  IBM Console device driver which makes use of RTAS
 
 
-config HVC_BEAT
-	bool "Toshiba's Beat Hypervisor Console support"
-	depends on PPC_CELLEB
-	select HVC_DRIVER
-	help
-	  Toshiba's Cell Reference Set Beat Console device driver
-
 config HVC_IUCV
 config HVC_IUCV
 	bool "z/VM IUCV Hypervisor console support (VM only)"
 	bool "z/VM IUCV Hypervisor console support (VM only)"
 	depends on S390
 	depends on S390

+ 0 - 1
drivers/tty/hvc/Makefile

@@ -4,7 +4,6 @@ obj-$(CONFIG_HVC_OLD_HVSI)	+= hvsi.o
 obj-$(CONFIG_HVC_RTAS)		+= hvc_rtas.o
 obj-$(CONFIG_HVC_RTAS)		+= hvc_rtas.o
 obj-$(CONFIG_HVC_TILE)		+= hvc_tile.o
 obj-$(CONFIG_HVC_TILE)		+= hvc_tile.o
 obj-$(CONFIG_HVC_DCC)		+= hvc_dcc.o
 obj-$(CONFIG_HVC_DCC)		+= hvc_dcc.o
-obj-$(CONFIG_HVC_BEAT)		+= hvc_beat.o
 obj-$(CONFIG_HVC_DRIVER)	+= hvc_console.o
 obj-$(CONFIG_HVC_DRIVER)	+= hvc_console.o
 obj-$(CONFIG_HVC_IRQ)		+= hvc_irq.o
 obj-$(CONFIG_HVC_IRQ)		+= hvc_irq.o
 obj-$(CONFIG_HVC_XEN)		+= hvc_xen.o
 obj-$(CONFIG_HVC_XEN)		+= hvc_xen.o

+ 0 - 134
drivers/tty/hvc/hvc_beat.c

@@ -1,134 +0,0 @@
-/*
- * Beat hypervisor console driver
- *
- * (C) Copyright 2006 TOSHIBA CORPORATION
- *
- * This code is based on drivers/char/hvc_rtas.c:
- * (C) Copyright IBM Corporation 2001-2005
- * (C) Copyright Red Hat, Inc. 2005
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/console.h>
-#include <asm/prom.h>
-#include <asm/hvconsole.h>
-#include <asm/firmware.h>
-
-#include "hvc_console.h"
-
-extern int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *);
-extern int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t);
-
-struct hvc_struct *hvc_beat_dev = NULL;
-
-/* bug: only one queue is available regardless of vtermno */
-static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt)
-{
-	static unsigned char q[sizeof(unsigned long) * 2]
-		__attribute__((aligned(sizeof(unsigned long))));
-	static int qlen = 0;
-	u64 got;
-
-again:
-	if (qlen) {
-		if (qlen > cnt) {
-			memcpy(buf, q, cnt);
-			qlen -= cnt;
-			memmove(q + cnt, q, qlen);
-			return cnt;
-		} else {	/* qlen <= cnt */
-			int	r;
-
-			memcpy(buf, q, qlen);
-			r = qlen;
-			qlen = 0;
-			return r;
-		}
-	}
-	if (beat_get_term_char(vtermno, &got,
-		((u64 *)q), ((u64 *)q) + 1) == 0) {
-		qlen = got;
-		goto again;
-	}
-	return 0;
-}
-
-static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt)
-{
-	unsigned long kb[2];
-	int rest, nlen;
-
-	for (rest = cnt; rest > 0; rest -= nlen) {
-		nlen = (rest > 16) ? 16 : rest;
-		memcpy(kb, buf, nlen);
-		beat_put_term_char(vtermno, nlen, kb[0], kb[1]);
-		buf += nlen;
-	}
-	return cnt;
-}
-
-static const struct hv_ops hvc_beat_get_put_ops = {
-	.get_chars = hvc_beat_get_chars,
-	.put_chars = hvc_beat_put_chars,
-};
-
-static int hvc_beat_useit = 1;
-
-static int hvc_beat_config(char *p)
-{
-	hvc_beat_useit = simple_strtoul(p, NULL, 0);
-	return 0;
-}
-
-static int __init hvc_beat_console_init(void)
-{
-	if (hvc_beat_useit && of_machine_is_compatible("Beat")) {
-		hvc_instantiate(0, 0, &hvc_beat_get_put_ops);
-	}
-	return 0;
-}
-
-/* temp */
-static int __init hvc_beat_init(void)
-{
-	struct hvc_struct *hp;
-
-	if (!firmware_has_feature(FW_FEATURE_BEAT))
-		return -ENODEV;
-
-	hp = hvc_alloc(0, 0, &hvc_beat_get_put_ops, 16);
-	if (IS_ERR(hp))
-		return PTR_ERR(hp);
-	hvc_beat_dev = hp;
-	return 0;
-}
-
-static void __exit hvc_beat_exit(void)
-{
-	if (hvc_beat_dev)
-		hvc_remove(hvc_beat_dev);
-}
-
-module_init(hvc_beat_init);
-module_exit(hvc_beat_exit);
-
-__setup("hvc_beat=", hvc_beat_config);
-
-console_initcall(hvc_beat_console_init);

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

@@ -319,7 +319,8 @@ static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
 	int rc;
 	int rc;
 
 
 	/* Auto increments kref reference if found. */
 	/* Auto increments kref reference if found. */
-	if (!(hp = hvc_get_by_index(tty->index)))
+	hp = hvc_get_by_index(tty->index);
+	if (!hp)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	tty->driver_data = hp;
 	tty->driver_data = hp;

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

@@ -1044,8 +1044,8 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
 	 * It is possible that the vty-server was removed between the time that
 	 * It is possible that the vty-server was removed between the time that
 	 * the conn was registered and now.
 	 * the conn was registered and now.
 	 */
 	 */
-	if (!(rc = request_irq(irq, &hvcs_handle_interrupt,
-				0, "ibmhvcs", hvcsd))) {
+	rc = request_irq(irq, &hvcs_handle_interrupt, 0, "ibmhvcs", hvcsd);
+	if (!rc) {
 		/*
 		/*
 		 * It is possible the vty-server was removed after the irq was
 		 * It is possible the vty-server was removed after the irq was
 		 * requested but before we have time to enable interrupts.
 		 * requested but before we have time to enable interrupts.

+ 2 - 3
drivers/tty/n_gsm.c

@@ -161,7 +161,7 @@ struct gsm_dlci {
 	struct net_device *net; /* network interface, if created */
 	struct net_device *net; /* network interface, if created */
 };
 };
 
 
-/* DLCI 0, 62/63 are special or reseved see gsmtty_open */
+/* DLCI 0, 62/63 are special or reserved see gsmtty_open */
 
 
 #define NUM_DLCI		64
 #define NUM_DLCI		64
 
 
@@ -2274,7 +2274,6 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 	const unsigned char *dp;
 	const unsigned char *dp;
 	char *f;
 	char *f;
 	int i;
 	int i;
-	char buf[64];
 	char flags = TTY_NORMAL;
 	char flags = TTY_NORMAL;
 
 
 	if (debug & 4)
 	if (debug & 4)
@@ -2296,7 +2295,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			break;
 			break;
 		default:
 		default:
 			WARN_ONCE(1, "%s: unknown flag %d\n",
 			WARN_ONCE(1, "%s: unknown flag %d\n",
-			       tty_name(tty, buf), flags);
+			       tty_name(tty), flags);
 			break;
 			break;
 		}
 		}
 	}
 	}

+ 2 - 5
drivers/tty/n_tty.c

@@ -1190,13 +1190,12 @@ static void n_tty_receive_break(struct tty_struct *tty)
 static void n_tty_receive_overrun(struct tty_struct *tty)
 static void n_tty_receive_overrun(struct tty_struct *tty)
 {
 {
 	struct n_tty_data *ldata = tty->disc_data;
 	struct n_tty_data *ldata = tty->disc_data;
-	char buf[64];
 
 
 	ldata->num_overrun++;
 	ldata->num_overrun++;
 	if (time_after(jiffies, ldata->overrun_time + HZ) ||
 	if (time_after(jiffies, ldata->overrun_time + HZ) ||
 			time_after(ldata->overrun_time, jiffies)) {
 			time_after(ldata->overrun_time, jiffies)) {
 		printk(KERN_WARNING "%s: %d input overrun(s)\n",
 		printk(KERN_WARNING "%s: %d input overrun(s)\n",
-			tty_name(tty, buf),
+			tty_name(tty),
 			ldata->num_overrun);
 			ldata->num_overrun);
 		ldata->overrun_time = jiffies;
 		ldata->overrun_time = jiffies;
 		ldata->num_overrun = 0;
 		ldata->num_overrun = 0;
@@ -1471,8 +1470,6 @@ static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
 static void
 static void
 n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag)
 n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag)
 {
 {
-	char buf[64];
-
 	switch (flag) {
 	switch (flag) {
 	case TTY_BREAK:
 	case TTY_BREAK:
 		n_tty_receive_break(tty);
 		n_tty_receive_break(tty);
@@ -1486,7 +1483,7 @@ n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag)
 		break;
 		break;
 	default:
 	default:
 		printk(KERN_ERR "%s: unknown flag %d\n",
 		printk(KERN_ERR "%s: unknown flag %d\n",
-		       tty_name(tty, buf), flag);
+		       tty_name(tty), flag);
 		break;
 		break;
 	}
 	}
 }
 }

+ 4 - 4
drivers/tty/nozomi.c

@@ -140,8 +140,8 @@ static int debug;
 #define R_FCR		0x0000	/* Flow Control Register */
 #define R_FCR		0x0000	/* Flow Control Register */
 #define R_IER		0x0004	/* Interrupt Enable Register */
 #define R_IER		0x0004	/* Interrupt Enable Register */
 
 
-#define CONFIG_MAGIC	0xEFEFFEFE
-#define TOGGLE_VALID	0x0000
+#define NOZOMI_CONFIG_MAGIC	0xEFEFFEFE
+#define TOGGLE_VALID		0x0000
 
 
 /* Definition of interrupt tokens */
 /* Definition of interrupt tokens */
 #define MDM_DL1		0x0001
 #define MDM_DL1		0x0001
@@ -660,9 +660,9 @@ static int nozomi_read_config_table(struct nozomi *dc)
 	read_mem32((u32 *) &dc->config_table, dc->base_addr + 0,
 	read_mem32((u32 *) &dc->config_table, dc->base_addr + 0,
 						sizeof(struct config_table));
 						sizeof(struct config_table));
 
 
-	if (dc->config_table.signature != CONFIG_MAGIC) {
+	if (dc->config_table.signature != NOZOMI_CONFIG_MAGIC) {
 		dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n",
 		dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n",
-			dc->config_table.signature, CONFIG_MAGIC);
+			dc->config_table.signature, NOZOMI_CONFIG_MAGIC);
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 1 - 1
drivers/tty/rocket.h

@@ -44,7 +44,7 @@ struct rocket_version {
 #define ROCKET_HUP_NOTIFY	0x00000004
 #define ROCKET_HUP_NOTIFY	0x00000004
 #define ROCKET_SPLIT_TERMIOS	0x00000008
 #define ROCKET_SPLIT_TERMIOS	0x00000008
 #define ROCKET_SPD_MASK		0x00000070
 #define ROCKET_SPD_MASK		0x00000070
-#define ROCKET_SPD_HI		0x00000010	/* Use 56000 instead of 38400 bps */
+#define ROCKET_SPD_HI		0x00000010	/* Use 57600 instead of 38400 bps */
 #define ROCKET_SPD_VHI		0x00000020	/* Use 115200 instead of 38400 bps */
 #define ROCKET_SPD_VHI		0x00000020	/* Use 115200 instead of 38400 bps */
 #define ROCKET_SPD_SHI		0x00000030	/* Use 230400 instead of 38400 bps */
 #define ROCKET_SPD_SHI		0x00000030	/* Use 230400 instead of 38400 bps */
 #define ROCKET_SPD_WARP	        0x00000040	/* Use 460800 instead of 38400 bps */
 #define ROCKET_SPD_WARP	        0x00000040	/* Use 460800 instead of 38400 bps */

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

@@ -508,7 +508,8 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty)
 	int	i;
 	int	i;
 
 
 	cflag = tty->termios.c_cflag;
 	cflag = tty->termios.c_cflag;
-	if (!(port = info->port))
+	port = info->port;
+	if (!port)
 		return;
 		return;
 
 
 	ustcnt = uart->ustcnt;
 	ustcnt = uart->ustcnt;

+ 10 - 17
drivers/tty/serial/8250/8250_core.c

@@ -85,19 +85,6 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */
 #define BOTH_EMPTY 	(UART_LSR_TEMT | UART_LSR_THRE)
 #define BOTH_EMPTY 	(UART_LSR_TEMT | UART_LSR_THRE)
 
 
 
 
-#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-#define CONFIG_SERIAL_DETECT_IRQ 1
-#endif
-#ifdef CONFIG_SERIAL_8250_MANY_PORTS
-#define CONFIG_SERIAL_MANY_PORTS 1
-#endif
-
-/*
- * HUB6 is always on.  This will be removed once the header
- * files have been cleaned.
- */
-#define CONFIG_HUB6 1
-
 #include <asm/serial.h>
 #include <asm/serial.h>
 /*
 /*
  * SERIAL_PORT_DFNS tells us about built-in ports that have no
  * SERIAL_PORT_DFNS tells us about built-in ports that have no
@@ -2019,8 +2006,9 @@ EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
 static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 {
 	if (port->set_mctrl)
 	if (port->set_mctrl)
-		return port->set_mctrl(port, mctrl);
-	return serial8250_do_set_mctrl(port, mctrl);
+		port->set_mctrl(port, mctrl);
+	else
+		serial8250_do_set_mctrl(port, mctrl);
 }
 }
 
 
 static void serial8250_break_ctl(struct uart_port *port, int break_state)
 static void serial8250_break_ctl(struct uart_port *port, int break_state)
@@ -3548,6 +3536,9 @@ static struct console univ8250_console = {
 
 
 static int __init univ8250_console_init(void)
 static int __init univ8250_console_init(void)
 {
 {
+	if (nr_uarts == 0)
+		return -ENODEV;
+
 	serial8250_isa_init_ports();
 	serial8250_isa_init_ports();
 	register_console(&univ8250_console);
 	register_console(&univ8250_console);
 	return 0;
 	return 0;
@@ -3578,7 +3569,7 @@ int __init early_serial_setup(struct uart_port *port)
 {
 {
 	struct uart_port *p;
 	struct uart_port *p;
 
 
-	if (port->line >= ARRAY_SIZE(serial8250_ports))
+	if (port->line >= ARRAY_SIZE(serial8250_ports) || nr_uarts == 0)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	serial8250_isa_init_ports();
 	serial8250_isa_init_ports();
@@ -3850,7 +3841,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 		uart->port.mapbase      = up->port.mapbase;
 		uart->port.mapbase      = up->port.mapbase;
 		uart->port.mapsize      = up->port.mapsize;
 		uart->port.mapsize      = up->port.mapsize;
 		uart->port.private_data = up->port.private_data;
 		uart->port.private_data = up->port.private_data;
-		uart->port.fifosize	= up->port.fifosize;
 		uart->tx_loadsz		= up->tx_loadsz;
 		uart->tx_loadsz		= up->tx_loadsz;
 		uart->capabilities	= up->capabilities;
 		uart->capabilities	= up->capabilities;
 		uart->port.throttle	= up->port.throttle;
 		uart->port.throttle	= up->port.throttle;
@@ -3945,6 +3935,9 @@ static int __init serial8250_init(void)
 {
 {
 	int ret;
 	int ret;
 
 
+	if (nr_uarts == 0)
+		return -ENODEV;
+
 	serial8250_isa_init_ports();
 	serial8250_isa_init_ports();
 
 
 	printk(KERN_INFO "Serial: 8250/16550 driver, "
 	printk(KERN_INFO "Serial: 8250/16550 driver, "

+ 18 - 1
drivers/tty/serial/8250/8250_dw.c

@@ -377,6 +377,16 @@ static int dw8250_probe_of(struct uart_port *p,
 	return 0;
 	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,
 static int dw8250_probe_acpi(struct uart_8250_port *up,
 			     struct dw8250_data *data)
 			     struct dw8250_data *data)
 {
 {
@@ -389,8 +399,15 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
 	p->serial_out = dw8250_serial_out32;
 	p->serial_out = dw8250_serial_out32;
 	p->regshift = 2;
 	p->regshift = 2;
 
 
-	up->dma = &data->dma;
+	/* 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->rxconf.src_maxburst = p->fifosize / 4;
 	up->dma->txconf.dst_maxburst = p->fifosize / 4;
 	up->dma->txconf.dst_maxburst = p->fifosize / 4;
 
 

+ 1 - 1
drivers/tty/serial/8250/8250_early.c

@@ -131,7 +131,7 @@ static void __init init_port(struct earlycon_device *device)
 	serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 	serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 }
 
 
-static int __init early_serial8250_setup(struct earlycon_device *device,
+int __init early_serial8250_setup(struct earlycon_device *device,
 					 const char *options)
 					 const char *options)
 {
 {
 	if (!(device->port.membase || device->port.iobase))
 	if (!(device->port.membase || device->port.iobase))

+ 230 - 0
drivers/tty/serial/8250/8250_lpc18xx.c

@@ -0,0 +1,230 @@
+/*
+ * Serial port driver for NXP LPC18xx/43xx UART
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Based on 8250_mtk.c:
+ * Copyright (c) 2014 MundoReader S.L.
+ * Matthias Brugger <matthias.bgg@gmail.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/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "8250.h"
+
+/* Additional LPC18xx/43xx 8250 registers and bits */
+#define LPC18XX_UART_RS485CTRL		(0x04c / sizeof(u32))
+#define  LPC18XX_UART_RS485CTRL_NMMEN	BIT(0)
+#define  LPC18XX_UART_RS485CTRL_DCTRL	BIT(4)
+#define  LPC18XX_UART_RS485CTRL_OINV	BIT(5)
+#define LPC18XX_UART_RS485DLY		(0x054 / sizeof(u32))
+#define LPC18XX_UART_RS485DLY_MAX	255
+
+struct lpc18xx_uart_data {
+	struct uart_8250_dma dma;
+	struct clk *clk_uart;
+	struct clk *clk_reg;
+	int line;
+};
+
+static int lpc18xx_rs485_config(struct uart_port *port,
+				struct serial_rs485 *rs485)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
+	u32 rs485_ctrl_reg = 0;
+	u32 rs485_dly_reg = 0;
+	unsigned baud_clk;
+
+	if (rs485->flags & SER_RS485_ENABLED)
+		memset(rs485->padding, 0, sizeof(rs485->padding));
+	else
+		memset(rs485, 0, sizeof(*rs485));
+
+	rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
+			SER_RS485_RTS_AFTER_SEND;
+
+	if (rs485->flags & SER_RS485_ENABLED) {
+		rs485_ctrl_reg |= LPC18XX_UART_RS485CTRL_NMMEN |
+				  LPC18XX_UART_RS485CTRL_DCTRL;
+
+		if (rs485->flags & SER_RS485_RTS_ON_SEND) {
+			rs485_ctrl_reg |= LPC18XX_UART_RS485CTRL_OINV;
+			rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
+		} else {
+			rs485->flags |= SER_RS485_RTS_AFTER_SEND;
+		}
+	}
+
+	if (rs485->delay_rts_after_send) {
+		baud_clk = port->uartclk / up->dl_read(up);
+		rs485_dly_reg = DIV_ROUND_UP(rs485->delay_rts_after_send
+						* baud_clk, MSEC_PER_SEC);
+
+		if (rs485_dly_reg > LPC18XX_UART_RS485DLY_MAX)
+			rs485_dly_reg = LPC18XX_UART_RS485DLY_MAX;
+
+		/* Calculate the resulting delay in ms */
+		rs485->delay_rts_after_send = (rs485_dly_reg * MSEC_PER_SEC)
+						/ baud_clk;
+	}
+
+	/* Delay RTS before send not supported */
+	rs485->delay_rts_before_send = 0;
+
+	serial_out(up, LPC18XX_UART_RS485CTRL, rs485_ctrl_reg);
+	serial_out(up, LPC18XX_UART_RS485DLY, rs485_dly_reg);
+
+	port->rs485 = *rs485;
+
+	return 0;
+}
+
+static void lpc18xx_uart_serial_out(struct uart_port *p, int offset, int value)
+{
+	/*
+	 * For DMA mode one must ensure that the UART_FCR_DMA_SELECT
+	 * bit is set when FIFO is enabled. Even if DMA is not used
+	 * setting this bit doesn't seem to affect anything.
+	 */
+	if (offset == UART_FCR && (value & UART_FCR_ENABLE_FIFO))
+		value |= UART_FCR_DMA_SELECT;
+
+	offset = offset << p->regshift;
+	writel(value, p->membase + offset);
+}
+
+static int lpc18xx_serial_probe(struct platform_device *pdev)
+{
+	struct lpc18xx_uart_data *data;
+	struct uart_8250_port uart;
+	struct resource *res;
+	int irq, ret;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "irq not found");
+		return irq;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "memory resource not found");
+		return -EINVAL;
+	}
+
+	memset(&uart, 0, sizeof(uart));
+
+	uart.port.membase = devm_ioremap(&pdev->dev, res->start,
+					 resource_size(res));
+	if (!uart.port.membase)
+		return -ENOMEM;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk_uart = devm_clk_get(&pdev->dev, "uartclk");
+	if (IS_ERR(data->clk_uart)) {
+		dev_err(&pdev->dev, "uart clock not found\n");
+		return PTR_ERR(data->clk_uart);
+	}
+
+	data->clk_reg = devm_clk_get(&pdev->dev, "reg");
+	if (IS_ERR(data->clk_reg)) {
+		dev_err(&pdev->dev, "reg clock not found\n");
+		return PTR_ERR(data->clk_reg);
+	}
+
+	ret = clk_prepare_enable(data->clk_reg);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable reg clock\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(data->clk_uart);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable uart clock\n");
+		goto dis_clk_reg;
+	}
+
+	ret = of_alias_get_id(pdev->dev.of_node, "serial");
+	if (ret >= 0)
+		uart.port.line = ret;
+
+	data->dma.rx_param = data;
+	data->dma.tx_param = data;
+
+	spin_lock_init(&uart.port.lock);
+	uart.port.dev = &pdev->dev;
+	uart.port.irq = irq;
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.mapbase = res->start;
+	uart.port.regshift = 2;
+	uart.port.type = PORT_16550A;
+	uart.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST;
+	uart.port.uartclk = clk_get_rate(data->clk_uart);
+	uart.port.private_data = data;
+	uart.port.rs485_config = lpc18xx_rs485_config;
+	uart.port.serial_out = lpc18xx_uart_serial_out;
+
+	uart.dma = &data->dma;
+	uart.dma->rxconf.src_maxburst = 1;
+	uart.dma->txconf.dst_maxburst = 1;
+
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to register 8250 port\n");
+		goto dis_uart_clk;
+	}
+
+	data->line = ret;
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+
+dis_uart_clk:
+	clk_disable_unprepare(data->clk_uart);
+dis_clk_reg:
+	clk_disable_unprepare(data->clk_reg);
+	return ret;
+}
+
+static int lpc18xx_serial_remove(struct platform_device *pdev)
+{
+	struct lpc18xx_uart_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+	clk_disable_unprepare(data->clk_uart);
+	clk_disable_unprepare(data->clk_reg);
+
+	return 0;
+}
+
+static const struct of_device_id lpc18xx_serial_match[] = {
+	{ .compatible = "nxp,lpc1850-uart" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_serial_match);
+
+static struct platform_driver lpc18xx_serial_driver = {
+	.probe  = lpc18xx_serial_probe,
+	.remove = lpc18xx_serial_remove,
+	.driver = {
+		.name = "lpc18xx-uart",
+		.of_match_table = lpc18xx_serial_match,
+	},
+};
+module_platform_driver(lpc18xx_serial_driver);
+
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_DESCRIPTION("Serial port driver NXP LPC18xx/43xx devices");
+MODULE_LICENSE("GPL v2");

+ 75 - 44
drivers/tty/serial/8250/8250_mtk.c

@@ -34,6 +34,7 @@
 struct mtk8250_data {
 struct mtk8250_data {
 	int			line;
 	int			line;
 	struct clk		*uart_clk;
 	struct clk		*uart_clk;
+	struct clk		*bus_clk;
 };
 };
 
 
 static void
 static void
@@ -115,6 +116,36 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
 		tty_termios_encode_baud_rate(termios, baud, baud);
 		tty_termios_encode_baud_rate(termios, baud, baud);
 }
 }
 
 
+static int mtk8250_runtime_suspend(struct device *dev)
+{
+	struct mtk8250_data *data = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(data->uart_clk);
+	clk_disable_unprepare(data->bus_clk);
+
+	return 0;
+}
+
+static int mtk8250_runtime_resume(struct device *dev)
+{
+	struct mtk8250_data *data = dev_get_drvdata(dev);
+	int err;
+
+	err = clk_prepare_enable(data->uart_clk);
+	if (err) {
+		dev_warn(dev, "Can't enable clock\n");
+		return err;
+	}
+
+	err = clk_prepare_enable(data->bus_clk);
+	if (err) {
+		dev_warn(dev, "Can't enable bus clock\n");
+		return err;
+	}
+
+	return 0;
+}
+
 static void
 static void
 mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 {
 {
@@ -130,22 +161,24 @@ mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
 			   struct mtk8250_data *data)
 			   struct mtk8250_data *data)
 {
 {
-	int err;
-	struct device_node *np = pdev->dev.of_node;
-
-	data->uart_clk = of_clk_get(np, 0);
+	data->uart_clk = devm_clk_get(&pdev->dev, "baud");
 	if (IS_ERR(data->uart_clk)) {
 	if (IS_ERR(data->uart_clk)) {
-		dev_warn(&pdev->dev, "Can't get timer clock\n");
-		return PTR_ERR(data->uart_clk);
+		/*
+		 * For compatibility with older device trees try unnamed
+		 * clk when no baud clk can be found.
+		 */
+		data->uart_clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(data->uart_clk)) {
+			dev_warn(&pdev->dev, "Can't get uart clock\n");
+			return PTR_ERR(data->uart_clk);
+		}
+
+		return 0;
 	}
 	}
 
 
-	err = clk_prepare_enable(data->uart_clk);
-	if (err) {
-		dev_warn(&pdev->dev, "Can't prepare clock\n");
-		clk_put(data->uart_clk);
-		return err;
-	}
-	p->uartclk = clk_get_rate(data->uart_clk);
+	data->bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(data->bus_clk))
+		return PTR_ERR(data->bus_clk);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -190,19 +223,24 @@ static int mtk8250_probe(struct platform_device *pdev)
 	uart.port.regshift = 2;
 	uart.port.regshift = 2;
 	uart.port.private_data = data;
 	uart.port.private_data = data;
 	uart.port.set_termios = mtk8250_set_termios;
 	uart.port.set_termios = mtk8250_set_termios;
+	uart.port.uartclk = clk_get_rate(data->uart_clk);
 
 
 	/* Disable Rate Fix function */
 	/* Disable Rate Fix function */
 	writel(0x0, uart.port.membase +
 	writel(0x0, uart.port.membase +
 			(MTK_UART_RATE_FIX << uart.port.regshift));
 			(MTK_UART_RATE_FIX << uart.port.regshift));
 
 
-	data->line = serial8250_register_8250_port(&uart);
-	if (data->line < 0)
-		return data->line;
-
 	platform_set_drvdata(pdev, data);
 	platform_set_drvdata(pdev, data);
 
 
-	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		err = mtk8250_runtime_resume(&pdev->dev);
+		if (err)
+			return err;
+	}
+
+	data->line = serial8250_register_8250_port(&uart);
+	if (data->line < 0)
+		return data->line;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -214,13 +252,13 @@ static int mtk8250_remove(struct platform_device *pdev)
 	pm_runtime_get_sync(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
 
 	serial8250_unregister_port(data->line);
 	serial8250_unregister_port(data->line);
-	if (!IS_ERR(data->uart_clk)) {
-		clk_disable_unprepare(data->uart_clk);
-		clk_put(data->uart_clk);
-	}
 
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
+
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		mtk8250_runtime_suspend(&pdev->dev);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -244,28 +282,6 @@ static int mtk8250_resume(struct device *dev)
 }
 }
 #endif /* CONFIG_PM_SLEEP */
 #endif /* CONFIG_PM_SLEEP */
 
 
-#ifdef CONFIG_PM
-static int mtk8250_runtime_suspend(struct device *dev)
-{
-	struct mtk8250_data *data = dev_get_drvdata(dev);
-
-	if (!IS_ERR(data->uart_clk))
-		clk_disable_unprepare(data->uart_clk);
-
-	return 0;
-}
-
-static int mtk8250_runtime_resume(struct device *dev)
-{
-	struct mtk8250_data *data = dev_get_drvdata(dev);
-
-	if (!IS_ERR(data->uart_clk))
-		clk_prepare_enable(data->uart_clk);
-
-	return 0;
-}
-#endif
-
 static const struct dev_pm_ops mtk8250_pm_ops = {
 static const struct dev_pm_ops mtk8250_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(mtk8250_suspend, mtk8250_resume)
 	SET_SYSTEM_SLEEP_PM_OPS(mtk8250_suspend, mtk8250_resume)
 	SET_RUNTIME_PM_OPS(mtk8250_runtime_suspend, mtk8250_runtime_resume,
 	SET_RUNTIME_PM_OPS(mtk8250_runtime_suspend, mtk8250_runtime_resume,
@@ -289,6 +305,21 @@ static struct platform_driver mtk8250_platform_driver = {
 };
 };
 module_platform_driver(mtk8250_platform_driver);
 module_platform_driver(mtk8250_platform_driver);
 
 
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static int __init early_mtk8250_setup(struct earlycon_device *device,
+					const char *options)
+{
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->port.iotype = UPIO_MEM32;
+
+	return early_serial8250_setup(device, NULL);
+}
+
+OF_EARLYCON_DECLARE(mtk8250, "mediatek,mt6577-uart", early_mtk8250_setup);
+#endif
+
 MODULE_AUTHOR("Matthias Brugger");
 MODULE_AUTHOR("Matthias Brugger");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Mediatek 8250 serial port driver");
 MODULE_DESCRIPTION("Mediatek 8250 serial port driver");

+ 49 - 16
drivers/tty/serial/8250/8250_omap.c

@@ -98,6 +98,7 @@ struct omap8250_priv {
 	struct pm_qos_request pm_qos_request;
 	struct pm_qos_request pm_qos_request;
 	struct work_struct qos_work;
 	struct work_struct qos_work;
 	struct uart_8250_dma omap8250_dma;
 	struct uart_8250_dma omap8250_dma;
+	spinlock_t rx_dma_lock;
 };
 };
 
 
 static u32 uart_read(struct uart_8250_port *up, u32 reg)
 static u32 uart_read(struct uart_8250_port *up, u32 reg)
@@ -726,14 +727,21 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir);
 
 
 static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
 static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
 {
 {
+	struct omap8250_priv	*priv = p->port.private_data;
 	struct uart_8250_dma    *dma = p->dma;
 	struct uart_8250_dma    *dma = p->dma;
 	struct tty_port         *tty_port = &p->port.state->port;
 	struct tty_port         *tty_port = &p->port.state->port;
 	struct dma_tx_state     state;
 	struct dma_tx_state     state;
 	int                     count;
 	int                     count;
+	unsigned long		flags;
 
 
 	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);
 
 
+	spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
+	if (!dma->rx_running)
+		goto unlock;
+
 	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);
 	dmaengine_terminate_all(dma->rxchan);
 	dmaengine_terminate_all(dma->rxchan);
@@ -742,6 +750,9 @@ static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
 
 
 	tty_insert_flip_string(tty_port, dma->rx_buf, count);
 	tty_insert_flip_string(tty_port, dma->rx_buf, count);
 	p->port.icount.rx += count;
 	p->port.icount.rx += count;
+unlock:
+	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+
 	if (!error)
 	if (!error)
 		omap_8250_rx_dma(p, 0);
 		omap_8250_rx_dma(p, 0);
 
 
@@ -753,28 +764,45 @@ static void __dma_rx_complete(void *param)
 	__dma_rx_do_complete(param, false);
 	__dma_rx_do_complete(param, false);
 }
 }
 
 
+static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
+{
+	struct omap8250_priv	*priv = p->port.private_data;
+	struct uart_8250_dma	*dma = p->dma;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
+	if (!dma->rx_running) {
+		spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+		return;
+	}
+
+	dmaengine_pause(dma->rxchan);
+
+	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+
+	__dma_rx_do_complete(p, true);
+}
+
 static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 {
 {
+	struct omap8250_priv		*priv = p->port.private_data;
 	struct uart_8250_dma            *dma = p->dma;
 	struct uart_8250_dma            *dma = p->dma;
+	int				err = 0;
 	struct dma_async_tx_descriptor  *desc;
 	struct dma_async_tx_descriptor  *desc;
+	unsigned long			flags;
 
 
 	switch (iir & 0x3f) {
 	switch (iir & 0x3f) {
 	case UART_IIR_RLSI:
 	case UART_IIR_RLSI:
 		/* 8250_core handles errors and break interrupts */
 		/* 8250_core handles errors and break interrupts */
-		if (dma->rx_running) {
-			dmaengine_pause(dma->rxchan);
-			__dma_rx_do_complete(p, true);
-		}
+		omap_8250_rx_dma_flush(p);
 		return -EIO;
 		return -EIO;
 	case UART_IIR_RX_TIMEOUT:
 	case UART_IIR_RX_TIMEOUT:
 		/*
 		/*
 		 * If RCVR FIFO trigger level was not reached, complete the
 		 * If RCVR FIFO trigger level was not reached, complete the
 		 * transfer and let 8250_core copy the remaining data.
 		 * transfer and let 8250_core copy the remaining data.
 		 */
 		 */
-		if (dma->rx_running) {
-			dmaengine_pause(dma->rxchan);
-			__dma_rx_do_complete(p, true);
-		}
+		omap_8250_rx_dma_flush(p);
 		return -ETIMEDOUT;
 		return -ETIMEDOUT;
 	case UART_IIR_RDI:
 	case UART_IIR_RDI:
 		/*
 		/*
@@ -786,24 +814,25 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 		 * the DMA won't do anything soon so we have to cancel the DMA
 		 * the DMA won't do anything soon so we have to cancel the DMA
 		 * transfer and purge the FIFO manually.
 		 * transfer and purge the FIFO manually.
 		 */
 		 */
-		if (dma->rx_running) {
-			dmaengine_pause(dma->rxchan);
-			__dma_rx_do_complete(p, true);
-		}
+		omap_8250_rx_dma_flush(p);
 		return -ETIMEDOUT;
 		return -ETIMEDOUT;
 
 
 	default:
 	default:
 		break;
 		break;
 	}
 	}
 
 
+	spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
 	if (dma->rx_running)
 	if (dma->rx_running)
-		return 0;
+		goto out;
 
 
 	desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
 	desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
 					   dma->rx_size, DMA_DEV_TO_MEM,
 					   dma->rx_size, DMA_DEV_TO_MEM,
 					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	if (!desc)
-		return -EBUSY;
+	if (!desc) {
+		err = -EBUSY;
+		goto out;
+	}
 
 
 	dma->rx_running = 1;
 	dma->rx_running = 1;
 	desc->callback = __dma_rx_complete;
 	desc->callback = __dma_rx_complete;
@@ -815,7 +844,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 				   dma->rx_size, DMA_FROM_DEVICE);
 				   dma->rx_size, DMA_FROM_DEVICE);
 
 
 	dma_async_issue_pending(dma->rxchan);
 	dma_async_issue_pending(dma->rxchan);
-	return 0;
+out:
+	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+	return err;
 }
 }
 
 
 static int omap_8250_tx_dma(struct uart_8250_port *p);
 static int omap_8250_tx_dma(struct uart_8250_port *p);
@@ -1129,6 +1160,8 @@ static int omap8250_probe(struct platform_device *pdev)
 			   priv->latency);
 			   priv->latency);
 	INIT_WORK(&priv->qos_work, omap8250_uart_qos_work);
 	INIT_WORK(&priv->qos_work, omap8250_uart_qos_work);
 
 
+	spin_lock_init(&priv->rx_dma_lock);
+
 	device_init_wakeup(&pdev->dev, true);
 	device_init_wakeup(&pdev->dev, true);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, -1);

+ 39 - 2
drivers/tty/serial/8250/8250_pci.c

@@ -1823,6 +1823,9 @@ static int pci_eg20t_init(struct pci_dev *dev)
 #endif
 #endif
 }
 }
 
 
+#define PCI_DEVICE_ID_EXAR_XR17V4358	0x4358
+#define PCI_DEVICE_ID_EXAR_XR17V8358	0x8358
+
 static int
 static int
 pci_xr17c154_setup(struct serial_private *priv,
 pci_xr17c154_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
 		  const struct pciserial_board *board,
@@ -1832,6 +1835,15 @@ pci_xr17c154_setup(struct serial_private *priv,
 	return pci_default_setup(priv, board, port, idx);
 	return pci_default_setup(priv, board, port, idx);
 }
 }
 
 
+static inline int
+xr17v35x_has_slave(struct serial_private *priv)
+{
+	const int dev_id = priv->dev->device;
+
+	return ((dev_id == PCI_DEVICE_ID_EXAR_XR17V4358) ||
+	        (dev_id == PCI_DEVICE_ID_EXAR_XR17V8358));
+}
+
 static int
 static int
 pci_xr17v35x_setup(struct serial_private *priv,
 pci_xr17v35x_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
 		  const struct pciserial_board *board,
@@ -1845,6 +1857,13 @@ pci_xr17v35x_setup(struct serial_private *priv,
 
 
 	port->port.flags |= UPF_EXAR_EFR;
 	port->port.flags |= UPF_EXAR_EFR;
 
 
+	/*
+	 * Setup the uart clock for the devices on expansion slot to
+	 * half the clock speed of the main chip (which is 125MHz)
+	 */
+	if (xr17v35x_has_slave(priv) && idx >= 8)
+		port->port.uartclk = (7812500 * 16 / 2);
+
 	/*
 	/*
 	 * Setup Multipurpose Input/Output pins.
 	 * Setup Multipurpose Input/Output pins.
 	 */
 	 */
@@ -1998,8 +2017,6 @@ pci_wch_ch38x_setup(struct serial_private *priv,
 #define PCIE_DEVICE_ID_WCH_CH382_2S1P	0x3250
 #define PCIE_DEVICE_ID_WCH_CH382_2S1P	0x3250
 #define PCIE_DEVICE_ID_WCH_CH384_4S	0x3470
 #define PCIE_DEVICE_ID_WCH_CH384_4S	0x3470
 
 
-#define PCI_DEVICE_ID_EXAR_XR17V8358	0x8358
-
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584	0x1584
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584	0x1584
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588	0x1588
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588	0x1588
@@ -2522,6 +2539,13 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.setup		= pci_xr17v35x_setup,
 		.setup		= pci_xr17v35x_setup,
 	},
 	},
+	{
+		.vendor = PCI_VENDOR_ID_EXAR,
+		.device = PCI_DEVICE_ID_EXAR_XR17V4358,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_xr17v35x_setup,
+	},
 	{
 	{
 		.vendor = PCI_VENDOR_ID_EXAR,
 		.vendor = PCI_VENDOR_ID_EXAR,
 		.device = PCI_DEVICE_ID_EXAR_XR17V8358,
 		.device = PCI_DEVICE_ID_EXAR_XR17V8358,
@@ -3008,6 +3032,7 @@ enum pci_board_num_t {
 	pbn_exar_XR17V352,
 	pbn_exar_XR17V352,
 	pbn_exar_XR17V354,
 	pbn_exar_XR17V354,
 	pbn_exar_XR17V358,
 	pbn_exar_XR17V358,
+	pbn_exar_XR17V4358,
 	pbn_exar_XR17V8358,
 	pbn_exar_XR17V8358,
 	pbn_exar_ibm_saturn,
 	pbn_exar_ibm_saturn,
 	pbn_pasemi_1682M,
 	pbn_pasemi_1682M,
@@ -3695,6 +3720,14 @@ static struct pciserial_board pci_boards[] = {
 		.reg_shift	= 0,
 		.reg_shift	= 0,
 		.first_offset	= 0,
 		.first_offset	= 0,
 	},
 	},
+	[pbn_exar_XR17V4358] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 12,
+		.base_baud	= 7812500,
+		.uart_offset	= 0x400,
+		.reg_shift	= 0,
+		.first_offset	= 0,
+	},
 	[pbn_exar_XR17V8358] = {
 	[pbn_exar_XR17V8358] = {
 		.flags		= FL_BASE0,
 		.flags		= FL_BASE0,
 		.num_ports	= 16,
 		.num_ports	= 16,
@@ -5112,6 +5145,10 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_ANY_ID, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
 		0,
 		0,
 		0, pbn_exar_XR17V358 },
 		0, pbn_exar_XR17V358 },
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V4358,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17V4358 },
 	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V8358,
 	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V8358,
 		PCI_ANY_ID, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
 		0,
 		0,

+ 257 - 0
drivers/tty/serial/8250/8250_uniphier.c

@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "8250.h"
+
+/* Most (but not all) of UniPhier UART devices have 64-depth FIFO. */
+#define UNIPHIER_UART_DEFAULT_FIFO_SIZE	64
+
+#define UNIPHIER_UART_CHAR_FCR	3	/* Character / FIFO Control Register */
+#define UNIPHIER_UART_LCR_MCR	4	/* Line/Modem Control Register */
+#define   UNIPHIER_UART_LCR_SHIFT	8
+#define UNIPHIER_UART_DLR	9	/* Divisor Latch Register */
+
+struct uniphier8250_priv {
+	int line;
+	struct clk *clk;
+	spinlock_t atomic_write_lock;
+};
+
+/*
+ * The register map is slightly different from that of 8250.
+ * IO callbacks must be overridden for correct access to FCR, LCR, and MCR.
+ */
+static unsigned int uniphier_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int valshift = 0;
+
+	switch (offset) {
+	case UART_LCR:
+		valshift = UNIPHIER_UART_LCR_SHIFT;
+		/* fall through */
+	case UART_MCR:
+		offset = UNIPHIER_UART_LCR_MCR;
+		break;
+	default:
+		break;
+	}
+
+	offset <<= p->regshift;
+
+	/*
+	 * The return value must be masked with 0xff because LCR and MCR reside
+	 * in the same register that must be accessed by 32-bit write/read.
+	 * 8 or 16 bit access to this hardware result in unexpected behavior.
+	 */
+	return (readl(p->membase + offset) >> valshift) & 0xff;
+}
+
+static void uniphier_serial_out(struct uart_port *p, int offset, int value)
+{
+	unsigned int valshift = 0;
+	bool normal = false;
+
+	switch (offset) {
+	case UART_FCR:
+		offset = UNIPHIER_UART_CHAR_FCR;
+		break;
+	case UART_LCR:
+		valshift = UNIPHIER_UART_LCR_SHIFT;
+		/* Divisor latch access bit does not exist. */
+		value &= ~(UART_LCR_DLAB << valshift);
+		/* fall through */
+	case UART_MCR:
+		offset = UNIPHIER_UART_LCR_MCR;
+		break;
+	default:
+		normal = true;
+		break;
+	}
+
+	offset <<= p->regshift;
+
+	if (normal) {
+		writel(value, p->membase + offset);
+	} else {
+		/*
+		 * Special case: two registers share the same address that
+		 * must be 32-bit accessed.  As this is not longer atomic safe,
+		 * take a lock just in case.
+		 */
+		struct uniphier8250_priv *priv = p->private_data;
+		unsigned long flags;
+		u32 tmp;
+
+		spin_lock_irqsave(&priv->atomic_write_lock, flags);
+		tmp = readl(p->membase + offset);
+		tmp &= ~(0xff << valshift);
+		tmp |= value << valshift;
+		writel(tmp, p->membase + offset);
+		spin_unlock_irqrestore(&priv->atomic_write_lock, flags);
+	}
+}
+
+/*
+ * This hardware does not have the divisor latch access bit.
+ * The divisor latch register exists at different address.
+ * Override dl_read/write callbacks.
+ */
+static int uniphier_serial_dl_read(struct uart_8250_port *up)
+{
+	return readl(up->port.membase + UNIPHIER_UART_DLR);
+}
+
+static void uniphier_serial_dl_write(struct uart_8250_port *up, int value)
+{
+	writel(value, up->port.membase + UNIPHIER_UART_DLR);
+}
+
+static int uniphier_of_serial_setup(struct device *dev, struct uart_port *port,
+				    struct uniphier8250_priv *priv)
+{
+	int ret;
+	u32 prop;
+	struct device_node *np = dev->of_node;
+
+	ret = of_alias_get_id(np, "serial");
+	if (ret < 0) {
+		dev_err(dev, "failed to get alias id\n");
+		return ret;
+	}
+	port->line = priv->line = ret;
+
+	/* Get clk rate through clk driver */
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "failed to get clock\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret < 0)
+		return ret;
+
+	port->uartclk = clk_get_rate(priv->clk);
+
+	/* Check for fifo size */
+	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
+		port->fifosize = prop;
+	else
+		port->fifosize = UNIPHIER_UART_DEFAULT_FIFO_SIZE;
+
+	return 0;
+}
+
+static int uniphier_uart_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct uart_8250_port up;
+	struct uniphier8250_priv *priv;
+	struct resource *regs;
+	void __iomem *membase;
+	int irq;
+	int ret;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_err(dev, "failed to get memory resource");
+		return -EINVAL;
+	}
+
+	membase = devm_ioremap(dev, regs->start, resource_size(regs));
+	if (!membase)
+		return -ENOMEM;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "failed to get IRQ number");
+		return irq;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	memset(&up, 0, sizeof(up));
+
+	ret = uniphier_of_serial_setup(dev, &up.port, priv);
+	if (ret < 0)
+		return ret;
+
+	spin_lock_init(&priv->atomic_write_lock);
+
+	up.port.dev = dev;
+	up.port.private_data = priv;
+	up.port.mapbase = regs->start;
+	up.port.mapsize = resource_size(regs);
+	up.port.membase = membase;
+	up.port.irq = irq;
+
+	up.port.type = PORT_16550A;
+	up.port.iotype = UPIO_MEM32;
+	up.port.regshift = 2;
+	up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE;
+	up.capabilities = UART_CAP_FIFO;
+
+	up.port.serial_in = uniphier_serial_in;
+	up.port.serial_out = uniphier_serial_out;
+	up.dl_read = uniphier_serial_dl_read;
+	up.dl_write = uniphier_serial_dl_write;
+
+	ret = serial8250_register_8250_port(&up);
+	if (ret < 0) {
+		dev_err(dev, "failed to register 8250 port\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static int uniphier_uart_remove(struct platform_device *pdev)
+{
+	struct uniphier8250_priv *priv = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(priv->line);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static const struct of_device_id uniphier_uart_match[] = {
+	{ .compatible = "socionext,uniphier-uart" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_uart_match);
+
+static struct platform_driver uniphier_uart_platform_driver = {
+	.probe		= uniphier_uart_probe,
+	.remove		= uniphier_uart_remove,
+	.driver = {
+		.name	= "uniphier-uart",
+		.of_match_table = uniphier_uart_match,
+	},
+};
+module_platform_driver(uniphier_uart_platform_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier UART driver");
+MODULE_LICENSE("GPL");

+ 15 - 0
drivers/tty/serial/8250/Kconfig

@@ -336,9 +336,24 @@ config SERIAL_8250_FINTEK
 	  LPC to 4 UART. This device has some RS485 functionality not available
 	  LPC to 4 UART. This device has some RS485 functionality not available
 	  through the PNP driver. If unsure, say N.
 	  through the PNP driver. If unsure, say N.
 
 
+config SERIAL_8250_LPC18XX
+	bool "NXP LPC18xx/43xx serial port support"
+	depends on SERIAL_8250 && OF && (ARCH_LPC18XX || COMPILE_TEST)
+	default ARCH_LPC18XX
+	help
+	  If you have a LPC18xx/43xx based board and want to use the
+	  serial port, say Y to this option. If unsure, say Y.
+
 config SERIAL_8250_MT6577
 config SERIAL_8250_MT6577
 	bool "Mediatek serial port support"
 	bool "Mediatek serial port support"
 	depends on SERIAL_8250 && ARCH_MEDIATEK
 	depends on SERIAL_8250 && ARCH_MEDIATEK
 	help
 	help
 	  If you have a Mediatek based board and want to use the
 	  If you have a Mediatek based board and want to use the
 	  serial port, say Y to this option. If unsure, say N.
 	  serial port, say Y to this option. If unsure, say N.
+
+config SERIAL_8250_UNIPHIER
+	tristate "Support for UniPhier on-chip UART"
+	depends on SERIAL_8250 && ARCH_UNIPHIER
+	help
+	  If you have a UniPhier based board and want to use the on-chip
+	  serial ports, say Y to this option. If unsure, say N.

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

@@ -22,4 +22,6 @@ obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
 obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
 obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
 obj-$(CONFIG_SERIAL_8250_FINTEK)	+= 8250_fintek.o
 obj-$(CONFIG_SERIAL_8250_FINTEK)	+= 8250_fintek.o
+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

+ 54 - 18
drivers/tty/serial/Kconfig

@@ -241,7 +241,6 @@ config SERIAL_SAMSUNG
 	tristate "Samsung SoC serial support"
 	tristate "Samsung SoC serial support"
 	depends on PLAT_SAMSUNG || ARCH_EXYNOS
 	depends on PLAT_SAMSUNG || ARCH_EXYNOS
 	select SERIAL_CORE
 	select SERIAL_CORE
-	select SERIAL_EARLYCON
 	help
 	help
 	  Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
 	  Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
 	  providing /dev/ttySAC0, 1 and 2 (note, some machines may not
 	  providing /dev/ttySAC0, 1 and 2 (note, some machines may not
@@ -277,6 +276,7 @@ config SERIAL_SAMSUNG_CONSOLE
 	bool "Support for console on Samsung SoC serial port"
 	bool "Support for console on Samsung SoC serial port"
 	depends on SERIAL_SAMSUNG=y
 	depends on SERIAL_SAMSUNG=y
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
 	help
 	help
 	  Allow selection of the S3C24XX on-board serial ports for use as
 	  Allow selection of the S3C24XX on-board serial ports for use as
 	  an virtual console.
 	  an virtual console.
@@ -1179,15 +1179,42 @@ config SERIAL_SCCNXP_CONSOLE
 	help
 	help
 	  Support for console on SCCNXP serial ports.
 	  Support for console on SCCNXP serial ports.
 
 
+config SERIAL_SC16IS7XX_CORE
+        tristate
+
 config SERIAL_SC16IS7XX
 config SERIAL_SC16IS7XX
-	tristate "SC16IS7xx serial support"
-	depends on I2C
-	select SERIAL_CORE
-	select REGMAP_I2C if I2C
-	help
-	  This selects support for SC16IS7xx serial ports.
-	  Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
-	  SC16IS760 and SC16IS762.
+        tristate "SC16IS7xx serial support"
+        select SERIAL_CORE
+        depends on I2C || SPI_MASTER
+        help
+          This selects support for SC16IS7xx serial ports.
+          Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
+          SC16IS760 and SC16IS762. Select supported buses using options below.
+
+config SERIAL_SC16IS7XX_I2C
+        bool "SC16IS7xx for I2C interface"
+        depends on SERIAL_SC16IS7XX
+        depends on I2C
+        select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX
+        select REGMAP_I2C if I2C
+        default y
+        help
+          Enable SC16IS7xx driver on I2C bus,
+          If required say y, and say n to i2c if not required,
+          Enabled by default to support oldconfig.
+          You must select at least one bus for the driver to be built.
+
+config SERIAL_SC16IS7XX_SPI
+        bool "SC16IS7xx for spi interface"
+        depends on SERIAL_SC16IS7XX
+        depends on SPI_MASTER
+        select SERIAL_SC16IS7XX_CORE if SERIAL_SC16IS7XX
+        select REGMAP_SPI if SPI_MASTER
+        help
+          Enable SC16IS7xx driver on SPI bus,
+          If required say y, and say n to spi if not required,
+          This is additional support to exsisting driver.
+          You must select at least one bus for the driver to be built.
 
 
 config SERIAL_BFIN_SPORT
 config SERIAL_BFIN_SPORT
 	tristate "Blackfin SPORT emulate UART"
 	tristate "Blackfin SPORT emulate UART"
@@ -1349,7 +1376,7 @@ config SERIAL_ALTERA_UART_CONSOLE
 
 
 config SERIAL_IFX6X60
 config SERIAL_IFX6X60
         tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
         tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
-	depends on GPIOLIB && SPI
+	depends on GPIOLIB && SPI && HAS_DMA
 	help
 	help
 	  Support for the IFX6x60 modem devices on Intel MID platforms.
 	  Support for the IFX6x60 modem devices on Intel MID platforms.
 
 
@@ -1378,14 +1405,6 @@ config SERIAL_PCH_UART_CONSOLE
 	  (the system  console is the device which receives all kernel messages and
 	  (the system  console is the device which receives all kernel messages and
 	  warnings and which allows logins in single user mode).
 	  warnings and which allows logins in single user mode).
 
 
-config SERIAL_MSM_SMD
-	bool "Enable tty device interface for some SMD ports"
-	default n
-	depends on MSM_SMD
-	help
-	  Enables userspace clients to read and write to some streaming SMD
-	  ports via tty device interface for MSM chipset.
-
 config SERIAL_MXS_AUART
 config SERIAL_MXS_AUART
 	depends on ARCH_MXS
 	depends on ARCH_MXS
 	tristate "MXS AUART support"
 	tristate "MXS AUART support"
@@ -1589,6 +1608,23 @@ config SERIAL_SPRD_CONSOLE
 	  with "earlycon" on the kernel command line. The console is
 	  with "earlycon" on the kernel command line. The console is
 	  enabled when early_param is processed.
 	  enabled when early_param is processed.
 
 
+config SERIAL_STM32
+	tristate "STMicroelectronics STM32 serial port support"
+	select SERIAL_CORE
+	depends on ARM || COMPILE_TEST
+	help
+	  This driver is for the on-chip Serial Controller on
+	  STMicroelectronics STM32 MCUs.
+	  USART supports Rx & Tx functionality.
+	  It support all industry standard baud rates.
+
+	  If unsure, say N.
+
+config SERIAL_STM32_CONSOLE
+	bool "Support for console on STM32"
+	depends on SERIAL_STM32=y
+	select SERIAL_CORE_CONSOLE
+
 endmenu
 endmenu
 
 
 config SERIAL_MCTRL_GPIO
 config SERIAL_MCTRL_GPIO

+ 2 - 2
drivers/tty/serial/Makefile

@@ -53,7 +53,7 @@ obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_ETRAXFS) += etraxfs-uart.o
 obj-$(CONFIG_SERIAL_ETRAXFS) += etraxfs-uart.o
 obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
 obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
-obj-$(CONFIG_SERIAL_SC16IS7XX) += sc16is7xx.o
+obj-$(CONFIG_SERIAL_SC16IS7XX_CORE) += sc16is7xx.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
@@ -79,7 +79,6 @@ obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
 obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
 obj-$(CONFIG_SERIAL_IFX6X60)  	+= ifx6x60.o
 obj-$(CONFIG_SERIAL_IFX6X60)  	+= ifx6x60.o
 obj-$(CONFIG_SERIAL_PCH_UART)	+= pch_uart.o
 obj-$(CONFIG_SERIAL_PCH_UART)	+= pch_uart.o
-obj-$(CONFIG_SERIAL_MSM_SMD)	+= msm_smd_tty.o
 obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
 obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
 obj-$(CONFIG_SERIAL_LANTIQ)	+= lantiq.o
 obj-$(CONFIG_SERIAL_LANTIQ)	+= lantiq.o
 obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
 obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
@@ -93,6 +92,7 @@ obj-$(CONFIG_SERIAL_FSL_LPUART)	+= fsl_lpuart.o
 obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR)	+= digicolor-usart.o
 obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR)	+= digicolor-usart.o
 obj-$(CONFIG_SERIAL_MEN_Z135)	+= men_z135_uart.o
 obj-$(CONFIG_SERIAL_MEN_Z135)	+= men_z135_uart.o
 obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
 obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
+obj-$(CONFIG_SERIAL_STM32)	+= stm32-usart.o
 
 
 # GPIOLIB helpers for modem control lines
 # GPIOLIB helpers for modem control lines
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o

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

@@ -387,7 +387,7 @@ console_initcall(altera_jtaguart_console_init);
 
 
 #define	ALTERA_JTAGUART_CONSOLE	NULL
 #define	ALTERA_JTAGUART_CONSOLE	NULL
 
 
-#endif /* CONFIG_ALTERA_JTAGUART_CONSOLE */
+#endif /* CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE */
 
 
 static struct uart_driver altera_jtaguart_driver = {
 static struct uart_driver altera_jtaguart_driver = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,

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

@@ -493,7 +493,7 @@ console_initcall(altera_uart_console_init);
 
 
 #define	ALTERA_UART_CONSOLE	NULL
 #define	ALTERA_UART_CONSOLE	NULL
 
 
-#endif /* CONFIG_ALTERA_UART_CONSOLE */
+#endif /* CONFIG_SERIAL_ALTERA_UART_CONSOLE */
 
 
 /*
 /*
  *	Define the altera_uart UART driver structure.
  *	Define the altera_uart UART driver structure.

+ 419 - 232
drivers/tty/serial/amba-pl011.c

@@ -58,7 +58,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/sizes.h>
 #include <linux/sizes.h>
 #include <linux/io.h>
 #include <linux/io.h>
-#include <linux/workqueue.h>
+#include <linux/acpi.h>
 
 
 #define UART_NR			14
 #define UART_NR			14
 
 
@@ -79,6 +79,8 @@ struct vendor_data {
 	bool			oversampling;
 	bool			oversampling;
 	bool			dma_threshold;
 	bool			dma_threshold;
 	bool			cts_event_workaround;
 	bool			cts_event_workaround;
+	bool			always_enabled;
+	bool			fixed_options;
 
 
 	unsigned int (*get_fifosize)(struct amba_device *dev);
 	unsigned int (*get_fifosize)(struct amba_device *dev);
 };
 };
@@ -95,9 +97,19 @@ static struct vendor_data vendor_arm = {
 	.oversampling		= false,
 	.oversampling		= false,
 	.dma_threshold		= false,
 	.dma_threshold		= false,
 	.cts_event_workaround	= false,
 	.cts_event_workaround	= false,
+	.always_enabled		= false,
+	.fixed_options		= false,
 	.get_fifosize		= get_fifosize_arm,
 	.get_fifosize		= get_fifosize_arm,
 };
 };
 
 
+static struct vendor_data vendor_sbsa = {
+	.oversampling		= false,
+	.dma_threshold		= false,
+	.cts_event_workaround	= false,
+	.always_enabled		= true,
+	.fixed_options		= true,
+};
+
 static unsigned int get_fifosize_st(struct amba_device *dev)
 static unsigned int get_fifosize_st(struct amba_device *dev)
 {
 {
 	return 64;
 	return 64;
@@ -110,6 +122,8 @@ static struct vendor_data vendor_st = {
 	.oversampling		= true,
 	.oversampling		= true,
 	.dma_threshold		= true,
 	.dma_threshold		= true,
 	.cts_event_workaround	= true,
 	.cts_event_workaround	= true,
+	.always_enabled		= false,
+	.fixed_options		= false,
 	.get_fifosize		= get_fifosize_st,
 	.get_fifosize		= get_fifosize_st,
 };
 };
 
 
@@ -157,9 +171,8 @@ struct uart_amba_port {
 	unsigned int		lcrh_tx;	/* vendor-specific */
 	unsigned int		lcrh_tx;	/* vendor-specific */
 	unsigned int		lcrh_rx;	/* vendor-specific */
 	unsigned int		lcrh_rx;	/* vendor-specific */
 	unsigned int		old_cr;		/* state during shutdown */
 	unsigned int		old_cr;		/* state during shutdown */
-	struct delayed_work	tx_softirq_work;
 	bool			autorts;
 	bool			autorts;
-	unsigned int		tx_irq_seen;	/* 0=none, 1=1, 2=2 or more */
+	unsigned int		fixed_baud;	/* vendor-set fixed baud rate */
 	char			type[12];
 	char			type[12];
 #ifdef CONFIG_DMA_ENGINE
 #ifdef CONFIG_DMA_ENGINE
 	/* DMA stuff */
 	/* DMA stuff */
@@ -1172,15 +1185,14 @@ static void pl011_stop_tx(struct uart_port *port)
 	pl011_dma_tx_stop(uap);
 	pl011_dma_tx_stop(uap);
 }
 }
 
 
-static bool pl011_tx_chars(struct uart_amba_port *uap);
+static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 
 
 /* Start TX with programmed I/O only (no DMA) */
 /* Start TX with programmed I/O only (no DMA) */
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 {
 	uap->im |= UART011_TXIM;
 	uap->im |= UART011_TXIM;
 	writew(uap->im, uap->port.membase + UART011_IMSC);
 	writew(uap->im, uap->port.membase + UART011_IMSC);
-	if (!uap->tx_irq_seen)
-		pl011_tx_chars(uap);
+	pl011_tx_chars(uap, false);
 }
 }
 
 
 static void pl011_start_tx(struct uart_port *port)
 static void pl011_start_tx(struct uart_port *port)
@@ -1247,15 +1259,11 @@ __acquires(&uap->port.lock)
 	spin_lock(&uap->port.lock);
 	spin_lock(&uap->port.lock);
 }
 }
 
 
-/*
- * Transmit a character
- *
- * Returns true if the character was successfully queued to the FIFO.
- * Returns false otherwise.
- */
-static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
+static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
+			  bool from_irq)
 {
 {
-	if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+	if (unlikely(!from_irq) &&
+	    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 		return false; /* unable to transmit character */
 
 
 	writew(c, uap->port.membase + UART01x_DR);
 	writew(c, uap->port.membase + UART01x_DR);
@@ -1264,70 +1272,41 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
 	return true;
 	return true;
 }
 }
 
 
-static bool pl011_tx_chars(struct uart_amba_port *uap)
+static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
 {
 {
 	struct circ_buf *xmit = &uap->port.state->xmit;
 	struct circ_buf *xmit = &uap->port.state->xmit;
-	int count;
-
-	if (unlikely(uap->tx_irq_seen < 2))
-		/*
-		 * Initial FIFO fill level unknown: we must check TXFF
-		 * after each write, so just try to fill up the FIFO.
-		 */
-		count = uap->fifosize;
-	else /* tx_irq_seen >= 2 */
-		/*
-		 * FIFO initially at least half-empty, so we can simply
-		 * write half the FIFO without polling TXFF.
-
-		 * Note: the *first* TX IRQ can still race with
-		 * pl011_start_tx_pio(), which can result in the FIFO
-		 * being fuller than expected in that case.
-		 */
-		count = uap->fifosize >> 1;
-
-	/*
-	 * If the FIFO is full we're guaranteed a TX IRQ at some later point,
-	 * and can't transmit immediately in any case:
-	 */
-	if (unlikely(uap->tx_irq_seen < 2 &&
-		     readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF))
-		return false;
+	int count = uap->fifosize >> 1;
 
 
 	if (uap->port.x_char) {
 	if (uap->port.x_char) {
-		if (!pl011_tx_char(uap, uap->port.x_char))
-			goto done;
+		if (!pl011_tx_char(uap, uap->port.x_char, from_irq))
+			return;
 		uap->port.x_char = 0;
 		uap->port.x_char = 0;
 		--count;
 		--count;
 	}
 	}
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
 		pl011_stop_tx(&uap->port);
 		pl011_stop_tx(&uap->port);
-		goto done;
+		return;
 	}
 	}
 
 
 	/* If we are using DMA mode, try to send some characters. */
 	/* If we are using DMA mode, try to send some characters. */
 	if (pl011_dma_tx_irq(uap))
 	if (pl011_dma_tx_irq(uap))
-		goto done;
+		return;
 
 
-	while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) {
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		if (uart_circ_empty(xmit))
+	do {
+		if (likely(from_irq) && count-- == 0)
 			break;
 			break;
-	}
+
+		if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq))
+			break;
+
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+	} while (!uart_circ_empty(xmit));
 
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&uap->port);
 		uart_write_wakeup(&uap->port);
 
 
-	if (uart_circ_empty(xmit)) {
+	if (uart_circ_empty(xmit))
 		pl011_stop_tx(&uap->port);
 		pl011_stop_tx(&uap->port);
-		goto done;
-	}
-
-	if (unlikely(!uap->tx_irq_seen))
-		schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout);
-
-done:
-	return false;
 }
 }
 
 
 static void pl011_modem_status(struct uart_amba_port *uap)
 static void pl011_modem_status(struct uart_amba_port *uap)
@@ -1354,26 +1333,23 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 	wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 	wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 }
 }
 
 
-static void pl011_tx_softirq(struct work_struct *work)
+static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 {
 {
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct uart_amba_port *uap =
-		container_of(dwork, struct uart_amba_port, tx_softirq_work);
-
-	spin_lock(&uap->port.lock);
-	while (pl011_tx_chars(uap)) ;
-	spin_unlock(&uap->port.lock);
-}
+	unsigned int dummy_read;
 
 
-static void pl011_tx_irq_seen(struct uart_amba_port *uap)
-{
-	if (likely(uap->tx_irq_seen > 1))
+	if (!uap->vendor->cts_event_workaround)
 		return;
 		return;
 
 
-	uap->tx_irq_seen++;
-	if (uap->tx_irq_seen < 2)
-		/* first TX IRQ */
-		cancel_delayed_work(&uap->tx_softirq_work);
+	/* workaround to make sure that all bits are unlocked.. */
+	writew(0x00, uap->port.membase + UART011_ICR);
+
+	/*
+	 * WA: introduce 26ns(1 uart clk) delay before W1C;
+	 * single apb access will incur 2 pclk(133.12Mhz) delay,
+	 * so add 2 dummy reads
+	 */
+	dummy_read = readw(uap->port.membase + UART011_ICR);
+	dummy_read = readw(uap->port.membase + UART011_ICR);
 }
 }
 
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1381,25 +1357,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	struct uart_amba_port *uap = dev_id;
 	struct uart_amba_port *uap = dev_id;
 	unsigned long flags;
 	unsigned long flags;
 	unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
 	unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
+	u16 imsc;
 	int handled = 0;
 	int handled = 0;
-	unsigned int dummy_read;
 
 
 	spin_lock_irqsave(&uap->port.lock, flags);
 	spin_lock_irqsave(&uap->port.lock, flags);
-	status = readw(uap->port.membase + UART011_MIS);
+	imsc = readw(uap->port.membase + UART011_IMSC);
+	status = readw(uap->port.membase + UART011_RIS) & imsc;
 	if (status) {
 	if (status) {
 		do {
 		do {
-			if (uap->vendor->cts_event_workaround) {
-				/* workaround to make sure that all bits are unlocked.. */
-				writew(0x00, uap->port.membase + UART011_ICR);
-
-				/*
-				 * WA: introduce 26ns(1 uart clk) delay before W1C;
-				 * single apb access will incur 2 pclk(133.12Mhz) delay,
-				 * so add 2 dummy reads
-				 */
-				dummy_read = readw(uap->port.membase + UART011_ICR);
-				dummy_read = readw(uap->port.membase + UART011_ICR);
-			}
+			check_apply_cts_event_workaround(uap);
 
 
 			writew(status & ~(UART011_TXIS|UART011_RTIS|
 			writew(status & ~(UART011_TXIS|UART011_RTIS|
 					  UART011_RXIS),
 					  UART011_RXIS),
@@ -1414,15 +1380,13 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (status & (UART011_DSRMIS|UART011_DCDMIS|
 			if (status & (UART011_DSRMIS|UART011_DCDMIS|
 				      UART011_CTSMIS|UART011_RIMIS))
 				      UART011_CTSMIS|UART011_RIMIS))
 				pl011_modem_status(uap);
 				pl011_modem_status(uap);
-			if (status & UART011_TXIS) {
-				pl011_tx_irq_seen(uap);
-				pl011_tx_chars(uap);
-			}
+			if (status & UART011_TXIS)
+				pl011_tx_chars(uap, true);
 
 
 			if (pass_counter-- == 0)
 			if (pass_counter-- == 0)
 				break;
 				break;
 
 
-			status = readw(uap->port.membase + UART011_MIS);
+			status = readw(uap->port.membase + UART011_RIS) & imsc;
 		} while (status != 0);
 		} while (status != 0);
 		handled = 1;
 		handled = 1;
 	}
 	}
@@ -1617,6 +1581,32 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 	}
 	}
 }
 }
 
 
+static int pl011_allocate_irq(struct uart_amba_port *uap)
+{
+	writew(uap->im, uap->port.membase + UART011_IMSC);
+
+	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
+}
+
+/*
+ * Enable interrupts, only timeouts when using DMA
+ * if initial RX DMA job failed, start in interrupt mode
+ * as well.
+ */
+static void pl011_enable_interrupts(struct uart_amba_port *uap)
+{
+	spin_lock_irq(&uap->port.lock);
+
+	/* Clear out any spuriously appearing RX interrupts */
+	writew(UART011_RTIS | UART011_RXIS,
+	       uap->port.membase + UART011_ICR);
+	uap->im = UART011_RTIM;
+	if (!pl011_dma_rx_running(uap))
+		uap->im |= UART011_RXIM;
+	writew(uap->im, uap->port.membase + UART011_IMSC);
+	spin_unlock_irq(&uap->port.lock);
+}
+
 static int pl011_startup(struct uart_port *port)
 static int pl011_startup(struct uart_port *port)
 {
 {
 	struct uart_amba_port *uap =
 	struct uart_amba_port *uap =
@@ -1628,20 +1618,12 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 	if (retval)
 		goto clk_dis;
 		goto clk_dis;
 
 
-	writew(uap->im, uap->port.membase + UART011_IMSC);
-
-	/*
-	 * Allocate the IRQ
-	 */
-	retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
+	retval = pl011_allocate_irq(uap);
 	if (retval)
 	if (retval)
 		goto clk_dis;
 		goto clk_dis;
 
 
 	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
 	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
 
 
-	/* Assume that TX IRQ doesn't work until we see one: */
-	uap->tx_irq_seen = 0;
-
 	spin_lock_irq(&uap->port.lock);
 	spin_lock_irq(&uap->port.lock);
 
 
 	/* restore RTS and DTR */
 	/* restore RTS and DTR */
@@ -1659,20 +1641,7 @@ static int pl011_startup(struct uart_port *port)
 	/* Startup DMA */
 	/* Startup DMA */
 	pl011_dma_startup(uap);
 	pl011_dma_startup(uap);
 
 
-	/*
-	 * Finally, enable interrupts, only timeouts when using DMA
-	 * if initial RX DMA job failed, start in interrupt mode
-	 * as well.
-	 */
-	spin_lock_irq(&uap->port.lock);
-	/* Clear out any spuriously appearing RX interrupts */
-	 writew(UART011_RTIS | UART011_RXIS,
-		uap->port.membase + UART011_ICR);
-	uap->im = UART011_RTIM;
-	if (!pl011_dma_rx_running(uap))
-		uap->im |= UART011_RXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
-	spin_unlock_irq(&uap->port.lock);
+	pl011_enable_interrupts(uap);
 
 
 	return 0;
 	return 0;
 
 
@@ -1681,6 +1650,28 @@ static int pl011_startup(struct uart_port *port)
 	return retval;
 	return retval;
 }
 }
 
 
+static int sbsa_uart_startup(struct uart_port *port)
+{
+	struct uart_amba_port *uap =
+		container_of(port, struct uart_amba_port, port);
+	int retval;
+
+	retval = pl011_hwinit(port);
+	if (retval)
+		return retval;
+
+	retval = pl011_allocate_irq(uap);
+	if (retval)
+		return retval;
+
+	/* The SBSA UART does not support any modem status lines. */
+	uap->old_status = 0;
+
+	pl011_enable_interrupts(uap);
+
+	return 0;
+}
+
 static void pl011_shutdown_channel(struct uart_amba_port *uap,
 static void pl011_shutdown_channel(struct uart_amba_port *uap,
 					unsigned int lcrh)
 					unsigned int lcrh)
 {
 {
@@ -1691,36 +1682,15 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
       writew(val, uap->port.membase + lcrh);
       writew(val, uap->port.membase + lcrh);
 }
 }
 
 
-static void pl011_shutdown(struct uart_port *port)
+/*
+ * disable the port. It should not disable RTS and DTR.
+ * Also RTS and DTR state should be preserved to restore
+ * it during startup().
+ */
+static void pl011_disable_uart(struct uart_amba_port *uap)
 {
 {
-	struct uart_amba_port *uap =
-	    container_of(port, struct uart_amba_port, port);
 	unsigned int cr;
 	unsigned int cr;
 
 
-	cancel_delayed_work_sync(&uap->tx_softirq_work);
-
-	/*
-	 * disable all interrupts
-	 */
-	spin_lock_irq(&uap->port.lock);
-	uap->im = 0;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
-	spin_unlock_irq(&uap->port.lock);
-
-	pl011_dma_shutdown(uap);
-
-	/*
-	 * Free the interrupt
-	 */
-	free_irq(uap->port.irq, uap);
-
-	/*
-	 * disable the port
-	 * disable the port. It should not disable RTS and DTR.
-	 * Also RTS and DTR state should be preserved to restore
-	 * it during startup().
-	 */
 	uap->autorts = false;
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
 	spin_lock_irq(&uap->port.lock);
 	cr = readw(uap->port.membase + UART011_CR);
 	cr = readw(uap->port.membase + UART011_CR);
@@ -1736,6 +1706,32 @@ static void pl011_shutdown(struct uart_port *port)
 	pl011_shutdown_channel(uap, uap->lcrh_rx);
 	pl011_shutdown_channel(uap, uap->lcrh_rx);
 	if (uap->lcrh_rx != uap->lcrh_tx)
 	if (uap->lcrh_rx != uap->lcrh_tx)
 		pl011_shutdown_channel(uap, uap->lcrh_tx);
 		pl011_shutdown_channel(uap, uap->lcrh_tx);
+}
+
+static void pl011_disable_interrupts(struct uart_amba_port *uap)
+{
+	spin_lock_irq(&uap->port.lock);
+
+	/* mask all interrupts and clear all pending ones */
+	uap->im = 0;
+	writew(uap->im, uap->port.membase + UART011_IMSC);
+	writew(0xffff, uap->port.membase + UART011_ICR);
+
+	spin_unlock_irq(&uap->port.lock);
+}
+
+static void pl011_shutdown(struct uart_port *port)
+{
+	struct uart_amba_port *uap =
+		container_of(port, struct uart_amba_port, port);
+
+	pl011_disable_interrupts(uap);
+
+	pl011_dma_shutdown(uap);
+
+	free_irq(uap->port.irq, uap);
+
+	pl011_disable_uart(uap);
 
 
 	/*
 	/*
 	 * Shut down the clock producer
 	 * Shut down the clock producer
@@ -1756,6 +1752,51 @@ static void pl011_shutdown(struct uart_port *port)
 		uap->port.ops->flush_buffer(port);
 		uap->port.ops->flush_buffer(port);
 }
 }
 
 
+static void sbsa_uart_shutdown(struct uart_port *port)
+{
+	struct uart_amba_port *uap =
+		container_of(port, struct uart_amba_port, port);
+
+	pl011_disable_interrupts(uap);
+
+	free_irq(uap->port.irq, uap);
+
+	if (uap->port.ops->flush_buffer)
+		uap->port.ops->flush_buffer(port);
+}
+
+static void
+pl011_setup_status_masks(struct uart_port *port, struct ktermios *termios)
+{
+	port->read_status_mask = UART011_DR_OE | 255;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= UART011_DR_FE | UART011_DR_PE;
+	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+		port->read_status_mask |= UART011_DR_BE;
+
+	/*
+	 * Characters to ignore
+	 */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= UART011_DR_FE | UART011_DR_PE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= UART011_DR_BE;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= UART011_DR_OE;
+	}
+
+	/*
+	 * Ignore all characters if CREAD is not set.
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		port->ignore_status_mask |= UART_DUMMY_DR_RX;
+}
+
 static void
 static void
 pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 		     struct ktermios *old)
 		     struct ktermios *old)
@@ -1820,33 +1861,7 @@ pl011_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);
 
 
-	port->read_status_mask = UART011_DR_OE | 255;
-	if (termios->c_iflag & INPCK)
-		port->read_status_mask |= UART011_DR_FE | UART011_DR_PE;
-	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-		port->read_status_mask |= UART011_DR_BE;
-
-	/*
-	 * Characters to ignore
-	 */
-	port->ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		port->ignore_status_mask |= UART011_DR_FE | UART011_DR_PE;
-	if (termios->c_iflag & IGNBRK) {
-		port->ignore_status_mask |= UART011_DR_BE;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			port->ignore_status_mask |= UART011_DR_OE;
-	}
-
-	/*
-	 * Ignore all characters if CREAD is not set.
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		port->ignore_status_mask |= UART_DUMMY_DR_RX;
+	pl011_setup_status_masks(port, termios);
 
 
 	if (UART_ENABLE_MS(port, termios->c_cflag))
 	if (UART_ENABLE_MS(port, termios->c_cflag))
 		pl011_enable_ms(port);
 		pl011_enable_ms(port);
@@ -1901,6 +1916,27 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 }
 
 
+static void
+sbsa_uart_set_termios(struct uart_port *port, struct ktermios *termios,
+		      struct ktermios *old)
+{
+	struct uart_amba_port *uap =
+	    container_of(port, struct uart_amba_port, port);
+	unsigned long flags;
+
+	tty_termios_encode_baud_rate(termios, uap->fixed_baud, uap->fixed_baud);
+
+	/* The SBSA UART only supports 8n1 without hardware flow control. */
+	termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
+	termios->c_cflag &= ~(CMSPAR | CRTSCTS);
+	termios->c_cflag |= CS8 | CLOCAL;
+
+	spin_lock_irqsave(&port->lock, flags);
+	uart_update_timeout(port, CS8, uap->fixed_baud);
+	pl011_setup_status_masks(port, termios);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
 static const char *pl011_type(struct uart_port *port)
 static const char *pl011_type(struct uart_port *port)
 {
 {
 	struct uart_amba_port *uap =
 	struct uart_amba_port *uap =
@@ -1976,6 +2012,37 @@ static struct uart_ops amba_pl011_pops = {
 #endif
 #endif
 };
 };
 
 
+static void sbsa_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static unsigned int sbsa_uart_get_mctrl(struct uart_port *port)
+{
+	return 0;
+}
+
+static const struct uart_ops sbsa_uart_pops = {
+	.tx_empty	= pl011_tx_empty,
+	.set_mctrl	= sbsa_uart_set_mctrl,
+	.get_mctrl	= sbsa_uart_get_mctrl,
+	.stop_tx	= pl011_stop_tx,
+	.start_tx	= pl011_start_tx,
+	.stop_rx	= pl011_stop_rx,
+	.startup	= sbsa_uart_startup,
+	.shutdown	= sbsa_uart_shutdown,
+	.set_termios	= sbsa_uart_set_termios,
+	.type		= pl011_type,
+	.release_port	= pl011_release_port,
+	.request_port	= pl011_request_port,
+	.config_port	= pl011_config_port,
+	.verify_port	= pl011_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_init     = pl011_hwinit,
+	.poll_get_char = pl011_get_poll_char,
+	.poll_put_char = pl011_put_poll_char,
+#endif
+};
+
 static struct uart_amba_port *amba_ports[UART_NR];
 static struct uart_amba_port *amba_ports[UART_NR];
 
 
 #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
 #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
@@ -1994,7 +2061,7 @@ static void
 pl011_console_write(struct console *co, const char *s, unsigned int count)
 pl011_console_write(struct console *co, const char *s, unsigned int count)
 {
 {
 	struct uart_amba_port *uap = amba_ports[co->index];
 	struct uart_amba_port *uap = amba_ports[co->index];
-	unsigned int status, old_cr, new_cr;
+	unsigned int status, old_cr = 0, new_cr;
 	unsigned long flags;
 	unsigned long flags;
 	int locked = 1;
 	int locked = 1;
 
 
@@ -2011,10 +2078,12 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	/*
 	/*
 	 *	First save the CR then disable the interrupts
 	 *	First save the CR then disable the interrupts
 	 */
 	 */
-	old_cr = readw(uap->port.membase + UART011_CR);
-	new_cr = old_cr & ~UART011_CR_CTSEN;
-	new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-	writew(new_cr, uap->port.membase + UART011_CR);
+	if (!uap->vendor->always_enabled) {
+		old_cr = readw(uap->port.membase + UART011_CR);
+		new_cr = old_cr & ~UART011_CR_CTSEN;
+		new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
+		writew(new_cr, uap->port.membase + UART011_CR);
+	}
 
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
 
 
@@ -2025,7 +2094,8 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	do {
 	do {
 		status = readw(uap->port.membase + UART01x_FR);
 		status = readw(uap->port.membase + UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	} while (status & UART01x_FR_BUSY);
-	writew(old_cr, uap->port.membase + UART011_CR);
+	if (!uap->vendor->always_enabled)
+		writew(old_cr, uap->port.membase + UART011_CR);
 
 
 	if (locked)
 	if (locked)
 		spin_unlock(&uap->port.lock);
 		spin_unlock(&uap->port.lock);
@@ -2106,10 +2176,15 @@ static int __init pl011_console_setup(struct console *co, char *options)
 
 
 	uap->port.uartclk = clk_get_rate(uap->clk);
 	uap->port.uartclk = clk_get_rate(uap->clk);
 
 
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-	else
-		pl011_console_get_options(uap, &baud, &parity, &bits);
+	if (uap->vendor->fixed_options) {
+		baud = uap->fixed_baud;
+	} else {
+		if (options)
+			uart_parse_options(options,
+					   &baud, &parity, &bits, &flow);
+		else
+			pl011_console_get_options(uap, &baud, &parity, &bits);
+	}
 
 
 	return uart_set_options(&uap->port, co, baud, parity, bits, flow);
 	return uart_set_options(&uap->port, co, baud, parity, bits, flow);
 }
 }
@@ -2201,97 +2276,126 @@ static int pl011_probe_dt_alias(int index, struct device *dev)
 	return ret;
 	return ret;
 }
 }
 
 
-static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
+/* unregisters the driver also if no more ports are left */
+static void pl011_unregister_port(struct uart_amba_port *uap)
 {
 {
-	struct uart_amba_port *uap;
-	struct vendor_data *vendor = id->data;
-	void __iomem *base;
-	int i, ret;
+	int i;
+	bool busy = false;
+
+	for (i = 0; i < ARRAY_SIZE(amba_ports); i++) {
+		if (amba_ports[i] == uap)
+			amba_ports[i] = NULL;
+		else if (amba_ports[i])
+			busy = true;
+	}
+	pl011_dma_remove(uap);
+	if (!busy)
+		uart_unregister_driver(&amba_reg);
+}
+
+static int pl011_find_free_port(void)
+{
+	int i;
 
 
 	for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
 	for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
 		if (amba_ports[i] == NULL)
 		if (amba_ports[i] == NULL)
-			break;
-
-	if (i == ARRAY_SIZE(amba_ports))
-		return -EBUSY;
+			return i;
 
 
-	uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
-			   GFP_KERNEL);
-	if (uap == NULL)
-		return -ENOMEM;
+	return -EBUSY;
+}
 
 
-	i = pl011_probe_dt_alias(i, &dev->dev);
+static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
+			    struct resource *mmiobase, int index)
+{
+	void __iomem *base;
 
 
-	base = devm_ioremap(&dev->dev, dev->res.start,
-			    resource_size(&dev->res));
+	base = devm_ioremap_resource(dev, mmiobase);
 	if (!base)
 	if (!base)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	uap->clk = devm_clk_get(&dev->dev, NULL);
-	if (IS_ERR(uap->clk))
-		return PTR_ERR(uap->clk);
+	index = pl011_probe_dt_alias(index, dev);
 
 
-	uap->vendor = vendor;
-	uap->lcrh_rx = vendor->lcrh_rx;
-	uap->lcrh_tx = vendor->lcrh_tx;
 	uap->old_cr = 0;
 	uap->old_cr = 0;
-	uap->fifosize = vendor->get_fifosize(dev);
-	uap->port.dev = &dev->dev;
-	uap->port.mapbase = dev->res.start;
+	uap->port.dev = dev;
+	uap->port.mapbase = mmiobase->start;
 	uap->port.membase = base;
 	uap->port.membase = base;
 	uap->port.iotype = UPIO_MEM;
 	uap->port.iotype = UPIO_MEM;
-	uap->port.irq = dev->irq[0];
 	uap->port.fifosize = uap->fifosize;
 	uap->port.fifosize = uap->fifosize;
-	uap->port.ops = &amba_pl011_pops;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
-	uap->port.line = i;
-	INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq);
+	uap->port.line = index;
 
 
-	/* Ensure interrupts from this UART are masked and cleared */
-	writew(0, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	amba_ports[index] = uap;
 
 
-	snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
+	return 0;
+}
 
 
-	amba_ports[i] = uap;
+static int pl011_register_port(struct uart_amba_port *uap)
+{
+	int ret;
 
 
-	amba_set_drvdata(dev, uap);
+	/* Ensure interrupts from this UART are masked and cleared */
+	writew(0, uap->port.membase + UART011_IMSC);
+	writew(0xffff, uap->port.membase + UART011_ICR);
 
 
 	if (!amba_reg.state) {
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
 		ret = uart_register_driver(&amba_reg);
 		if (ret < 0) {
 		if (ret < 0) {
-			dev_err(&dev->dev,
+			dev_err(uap->port.dev,
 				"Failed to register AMBA-PL011 driver\n");
 				"Failed to register AMBA-PL011 driver\n");
 			return ret;
 			return ret;
 		}
 		}
 	}
 	}
 
 
 	ret = uart_add_one_port(&amba_reg, &uap->port);
 	ret = uart_add_one_port(&amba_reg, &uap->port);
-	if (ret) {
-		amba_ports[i] = NULL;
-		uart_unregister_driver(&amba_reg);
-	}
+	if (ret)
+		pl011_unregister_port(uap);
 
 
 	return ret;
 	return ret;
 }
 }
 
 
+static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
+{
+	struct uart_amba_port *uap;
+	struct vendor_data *vendor = id->data;
+	int portnr, ret;
+
+	portnr = pl011_find_free_port();
+	if (portnr < 0)
+		return portnr;
+
+	uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
+			   GFP_KERNEL);
+	if (!uap)
+		return -ENOMEM;
+
+	uap->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(uap->clk))
+		return PTR_ERR(uap->clk);
+
+	uap->vendor = vendor;
+	uap->lcrh_rx = vendor->lcrh_rx;
+	uap->lcrh_tx = vendor->lcrh_tx;
+	uap->fifosize = vendor->get_fifosize(dev);
+	uap->port.irq = dev->irq[0];
+	uap->port.ops = &amba_pl011_pops;
+
+	snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
+
+	ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);
+	if (ret)
+		return ret;
+
+	amba_set_drvdata(dev, uap);
+
+	return pl011_register_port(uap);
+}
+
 static int pl011_remove(struct amba_device *dev)
 static int pl011_remove(struct amba_device *dev)
 {
 {
 	struct uart_amba_port *uap = amba_get_drvdata(dev);
 	struct uart_amba_port *uap = amba_get_drvdata(dev);
-	bool busy = false;
-	int i;
 
 
 	uart_remove_one_port(&amba_reg, &uap->port);
 	uart_remove_one_port(&amba_reg, &uap->port);
-
-	for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
-		if (amba_ports[i] == uap)
-			amba_ports[i] = NULL;
-		else if (amba_ports[i])
-			busy = true;
-
-	pl011_dma_remove(uap);
-	if (!busy)
-		uart_unregister_driver(&amba_reg);
+	pl011_unregister_port(uap);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2319,6 +2423,86 @@ static int pl011_resume(struct device *dev)
 
 
 static SIMPLE_DEV_PM_OPS(pl011_dev_pm_ops, pl011_suspend, pl011_resume);
 static SIMPLE_DEV_PM_OPS(pl011_dev_pm_ops, pl011_suspend, pl011_resume);
 
 
+static int sbsa_uart_probe(struct platform_device *pdev)
+{
+	struct uart_amba_port *uap;
+	struct resource *r;
+	int portnr, ret;
+	int baudrate;
+
+	/*
+	 * Check the mandatory baud rate parameter in the DT node early
+	 * so that we can easily exit with the error.
+	 */
+	if (pdev->dev.of_node) {
+		struct device_node *np = pdev->dev.of_node;
+
+		ret = of_property_read_u32(np, "current-speed", &baudrate);
+		if (ret)
+			return ret;
+	} else {
+		baudrate = 115200;
+	}
+
+	portnr = pl011_find_free_port();
+	if (portnr < 0)
+		return portnr;
+
+	uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port),
+			   GFP_KERNEL);
+	if (!uap)
+		return -ENOMEM;
+
+	uap->vendor	= &vendor_sbsa;
+	uap->fifosize	= 32;
+	uap->port.irq	= platform_get_irq(pdev, 0);
+	uap->port.ops	= &sbsa_uart_pops;
+	uap->fixed_baud = baudrate;
+
+	snprintf(uap->type, sizeof(uap->type), "SBSA");
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	ret = pl011_setup_port(&pdev->dev, uap, r, portnr);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, uap);
+
+	return pl011_register_port(uap);
+}
+
+static int sbsa_uart_remove(struct platform_device *pdev)
+{
+	struct uart_amba_port *uap = platform_get_drvdata(pdev);
+
+	uart_remove_one_port(&amba_reg, &uap->port);
+	pl011_unregister_port(uap);
+	return 0;
+}
+
+static const struct of_device_id sbsa_uart_of_match[] = {
+	{ .compatible = "arm,sbsa-uart", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sbsa_uart_of_match);
+
+static const struct acpi_device_id sbsa_uart_acpi_match[] = {
+	{ "ARMH0011", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match);
+
+static struct platform_driver arm_sbsa_uart_platform_driver = {
+	.probe		= sbsa_uart_probe,
+	.remove		= sbsa_uart_remove,
+	.driver	= {
+		.name	= "sbsa-uart",
+		.of_match_table = of_match_ptr(sbsa_uart_of_match),
+		.acpi_match_table = ACPI_PTR(sbsa_uart_acpi_match),
+	},
+};
+
 static struct amba_id pl011_ids[] = {
 static struct amba_id pl011_ids[] = {
 	{
 	{
 		.id	= 0x00041011,
 		.id	= 0x00041011,
@@ -2349,11 +2533,14 @@ static int __init pl011_init(void)
 {
 {
 	printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
 	printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
 
 
+	if (platform_driver_register(&arm_sbsa_uart_platform_driver))
+		pr_warn("could not register SBSA UART platform driver\n");
 	return amba_driver_register(&pl011_driver);
 	return amba_driver_register(&pl011_driver);
 }
 }
 
 
 static void __exit pl011_exit(void)
 static void __exit pl011_exit(void)
 {
 {
+	platform_driver_unregister(&arm_sbsa_uart_platform_driver);
 	amba_driver_unregister(&pl011_driver);
 	amba_driver_unregister(&pl011_driver);
 }
 }
 
 

+ 10 - 12
drivers/tty/serial/atmel_serial.c

@@ -165,6 +165,7 @@ struct atmel_uart_port {
 	struct tasklet_struct	tasklet;
 	struct tasklet_struct	tasklet;
 	unsigned int		irq_status;
 	unsigned int		irq_status;
 	unsigned int		irq_status_prev;
 	unsigned int		irq_status_prev;
+	unsigned int		status_change;
 
 
 	struct circ_buf		rx_ring;
 	struct circ_buf		rx_ring;
 
 
@@ -315,8 +316,7 @@ static int atmel_config_rs485(struct uart_port *port,
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 		dev_dbg(port->dev, "Setting UART to RS485\n");
 		dev_dbg(port->dev, "Setting UART to RS485\n");
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-		if ((rs485conf->delay_rts_after_send) > 0)
-			UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+		UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 		mode |= ATMEL_US_USMODE_RS485;
 	} else {
 	} else {
 		dev_dbg(port->dev, "Setting UART to RS232\n");
 		dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -354,8 +354,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 
 
 	/* override mode to RS485 if needed, otherwise keep the current mode */
 	/* override mode to RS485 if needed, otherwise keep the current mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		if ((port->rs485.delay_rts_after_send) > 0)
-			UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
 		mode &= ~ATMEL_US_USMODE;
 		mode &= ~ATMEL_US_USMODE;
 		mode |= ATMEL_US_USMODE_RS485;
 		mode |= ATMEL_US_USMODE_RS485;
 	}
 	}
@@ -1177,6 +1176,9 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
 	if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
 	if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
 				| ATMEL_US_CTSIC)) {
 				| ATMEL_US_CTSIC)) {
 		atmel_port->irq_status = status;
 		atmel_port->irq_status = status;
+		atmel_port->status_change = atmel_port->irq_status ^
+					    atmel_port->irq_status_prev;
+		atmel_port->irq_status_prev = status;
 		tasklet_schedule(&atmel_port->tasklet);
 		tasklet_schedule(&atmel_port->tasklet);
 	}
 	}
 }
 }
@@ -1523,17 +1525,14 @@ static void atmel_tasklet_func(unsigned long data)
 {
 {
 	struct uart_port *port = (struct uart_port *)data;
 	struct uart_port *port = (struct uart_port *)data;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-	unsigned int status;
-	unsigned int status_change;
+	unsigned int status = atmel_port->irq_status;
+	unsigned int status_change = atmel_port->status_change;
 
 
 	/* The interrupt handler does not take the lock */
 	/* The interrupt handler does not take the lock */
 	spin_lock(&port->lock);
 	spin_lock(&port->lock);
 
 
 	atmel_port->schedule_tx(port);
 	atmel_port->schedule_tx(port);
 
 
-	status = atmel_port->irq_status;
-	status_change = status ^ atmel_port->irq_status_prev;
-
 	if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
 	if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
 				| ATMEL_US_DCD | ATMEL_US_CTS)) {
 				| ATMEL_US_DCD | ATMEL_US_CTS)) {
 		/* TODO: All reads to CSR will clear these interrupts! */
 		/* TODO: All reads to CSR will clear these interrupts! */
@@ -1548,7 +1547,7 @@ static void atmel_tasklet_func(unsigned long data)
 
 
 		wake_up_interruptible(&port->state->port.delta_msr_wait);
 		wake_up_interruptible(&port->state->port.delta_msr_wait);
 
 
-		atmel_port->irq_status_prev = status;
+		atmel_port->status_change = 0;
 	}
 	}
 
 
 	atmel_port->schedule_rx(port);
 	atmel_port->schedule_rx(port);
@@ -2061,8 +2060,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
 
 	/* mode */
 	/* mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		if ((port->rs485.delay_rts_after_send) > 0)
-			UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 		mode |= ATMEL_US_USMODE_RS485;
 	} else if (termios->c_cflag & CRTSCTS) {
 	} else if (termios->c_cflag & CRTSCTS) {
 		/* RS232 with hardware handshake (RTS/CTS) */
 		/* RS232 with hardware handshake (RTS/CTS) */

+ 12 - 12
drivers/tty/serial/bfin_uart.c

@@ -74,8 +74,8 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
 
 
 static void bfin_serial_reset_irda(struct uart_port *port);
 static void bfin_serial_reset_irda(struct uart_port *port);
 
 
-#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
-	defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
+#if defined(SERIAL_BFIN_CTSRTS) || \
+	defined(SERIAL_BFIN_HARD_CTSRTS)
 static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
 static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
 {
 {
 	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
 	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
@@ -110,7 +110,7 @@ static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)
 	struct bfin_serial_port *uart = dev_id;
 	struct bfin_serial_port *uart = dev_id;
 	struct uart_port *uport = &uart->port;
 	struct uart_port *uport = &uart->port;
 	unsigned int status = bfin_serial_get_mctrl(uport);
 	unsigned int status = bfin_serial_get_mctrl(uport);
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+#ifdef SERIAL_BFIN_HARD_CTSRTS
 
 
 	UART_CLEAR_SCTS(uart);
 	UART_CLEAR_SCTS(uart);
 	if (uport->hw_stopped) {
 	if (uport->hw_stopped) {
@@ -700,7 +700,7 @@ static int bfin_serial_startup(struct uart_port *port)
 # endif
 # endif
 #endif
 #endif
 
 
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+#ifdef SERIAL_BFIN_CTSRTS
 	if (uart->cts_pin >= 0) {
 	if (uart->cts_pin >= 0) {
 		if (request_irq(gpio_to_irq(uart->cts_pin),
 		if (request_irq(gpio_to_irq(uart->cts_pin),
 			bfin_serial_mctrl_cts_int,
 			bfin_serial_mctrl_cts_int,
@@ -718,7 +718,7 @@ static int bfin_serial_startup(struct uart_port *port)
 			gpio_direction_output(uart->rts_pin, 0);
 			gpio_direction_output(uart->rts_pin, 0);
 	}
 	}
 #endif
 #endif
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+#ifdef SERIAL_BFIN_HARD_CTSRTS
 	if (uart->cts_pin >= 0) {
 	if (uart->cts_pin >= 0) {
 		if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int,
 		if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int,
 			0, "BFIN_UART_MODEM_STATUS", uart)) {
 			0, "BFIN_UART_MODEM_STATUS", uart)) {
@@ -766,13 +766,13 @@ static void bfin_serial_shutdown(struct uart_port *port)
 	free_irq(uart->tx_irq, uart);
 	free_irq(uart->tx_irq, uart);
 #endif
 #endif
 
 
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+#ifdef SERIAL_BFIN_CTSRTS
 	if (uart->cts_pin >= 0)
 	if (uart->cts_pin >= 0)
 		free_irq(gpio_to_irq(uart->cts_pin), uart);
 		free_irq(gpio_to_irq(uart->cts_pin), uart);
 	if (uart->rts_pin >= 0)
 	if (uart->rts_pin >= 0)
 		gpio_free(uart->rts_pin);
 		gpio_free(uart->rts_pin);
 #endif
 #endif
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+#ifdef SERIAL_BFIN_HARD_CTSRTS
 	if (uart->cts_pin >= 0)
 	if (uart->cts_pin >= 0)
 		free_irq(uart->status_irq, uart);
 		free_irq(uart->status_irq, uart);
 #endif
 #endif
@@ -788,7 +788,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned int ier, lcr = 0;
 	unsigned int ier, lcr = 0;
 	unsigned long timeout;
 	unsigned long timeout;
 
 
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+#ifdef SERIAL_BFIN_CTSRTS
 	if (old == NULL && uart->cts_pin != -1)
 	if (old == NULL && uart->cts_pin != -1)
 		termios->c_cflag |= CRTSCTS;
 		termios->c_cflag |= CRTSCTS;
 	else if (uart->cts_pin == -1)
 	else if (uart->cts_pin == -1)
@@ -1110,8 +1110,8 @@ bfin_serial_console_setup(struct console *co, char *options)
 	int baud = 57600;
 	int baud = 57600;
 	int bits = 8;
 	int bits = 8;
 	int parity = 'n';
 	int parity = 'n';
-# if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
-	defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
+# if defined(SERIAL_BFIN_CTSRTS) || \
+	defined(SERIAL_BFIN_HARD_CTSRTS)
 	int flow = 'r';
 	int flow = 'r';
 # else
 # else
 	int flow = 'n';
 	int flow = 'n';
@@ -1322,8 +1322,8 @@ static int bfin_serial_probe(struct platform_device *pdev)
 		init_timer(&(uart->rx_dma_timer));
 		init_timer(&(uart->rx_dma_timer));
 #endif
 #endif
 
 
-#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
-	defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
+#if defined(SERIAL_BFIN_CTSRTS) || \
+	defined(SERIAL_BFIN_HARD_CTSRTS)
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 		if (res == NULL)
 		if (res == NULL)
 			uart->cts_pin = -1;
 			uart->cts_pin = -1;

+ 14 - 92
drivers/tty/serial/crisv10.c

@@ -56,10 +56,6 @@ static char *serial_version = "$Revision: 1.25 $";
 #error "RX_TIMEOUT_TICKS == 0 not allowed, use 1"
 #error "RX_TIMEOUT_TICKS == 0 not allowed, use 1"
 #endif
 #endif
 
 
-#if defined(CONFIG_ETRAX_RS485_ON_PA) && defined(CONFIG_ETRAX_RS485_ON_PORT_G)
-#error "Disable either CONFIG_ETRAX_RS485_ON_PA or CONFIG_ETRAX_RS485_ON_PORT_G"
-#endif
-
 /*
 /*
  * All of the compatibilty code so we can compile serial.c against
  * All of the compatibilty code so we can compile serial.c against
  * older kernels is hidden in serial_compat.h
  * older kernels is hidden in serial_compat.h
@@ -455,30 +451,6 @@ static struct e100_serial rs_table[] = {
 static struct fast_timer fast_timers[NR_PORTS];
 static struct fast_timer fast_timers[NR_PORTS];
 #endif
 #endif
 
 
-#ifdef CONFIG_ETRAX_SERIAL_PROC_ENTRY
-#define PROCSTAT(x) x
-struct ser_statistics_type {
-	int overrun_cnt;
-	int early_errors_cnt;
-	int ser_ints_ok_cnt;
-	int errors_cnt;
-	unsigned long int processing_flip;
-	unsigned long processing_flip_still_room;
-	unsigned long int timeout_flush_cnt;
-	int rx_dma_ints;
-	int tx_dma_ints;
-	int rx_tot;
-	int tx_tot;
-};
-
-static struct ser_statistics_type ser_stat[NR_PORTS];
-
-#else
-
-#define PROCSTAT(x)
-
-#endif /* CONFIG_ETRAX_SERIAL_PROC_ENTRY */
-
 /* RS-485 */
 /* RS-485 */
 #if defined(CONFIG_ETRAX_RS485)
 #if defined(CONFIG_ETRAX_RS485)
 #ifdef CONFIG_ETRAX_FAST_TIMER
 #ifdef CONFIG_ETRAX_FAST_TIMER
@@ -487,9 +459,6 @@ static struct fast_timer fast_timers_rs485[NR_PORTS];
 #if defined(CONFIG_ETRAX_RS485_ON_PA)
 #if defined(CONFIG_ETRAX_RS485_ON_PA)
 static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT;
 static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT;
 #endif
 #endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
-static int rs485_port_g_bit = CONFIG_ETRAX_RS485_ON_PORT_G_BIT;
-#endif
 #endif
 #endif
 
 
 /* Info and macros needed for each ports extra control/status signals. */
 /* Info and macros needed for each ports extra control/status signals. */
@@ -739,10 +708,10 @@ static unsigned char dummy_ser[NR_PORTS] = {0xFF, 0xFF, 0xFF,0xFF};
     defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED) || \
     defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED) || \
     defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED) || \
     defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED) || \
     defined(CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED)
     defined(CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED)
-#define CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED
+#define ETRAX_SERX_DTR_RI_DSR_CD_MIXED
 #endif
 #endif
 
 
-#ifdef CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED
+#ifdef ETRAX_SERX_DTR_RI_DSR_CD_MIXED
 /* The pins can be mixed on PA and PB */
 /* The pins can be mixed on PA and PB */
 #define CONTROL_PINS_PORT_NOT_USED(line) \
 #define CONTROL_PINS_PORT_NOT_USED(line) \
   &dummy_ser[line], &dummy_ser[line], \
   &dummy_ser[line], &dummy_ser[line], \
@@ -835,7 +804,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] =
 #endif
 #endif
 	}
 	}
 };
 };
-#else  /* CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
+#else  /* ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
 
 
 /* All pins are on either PA or PB for each serial port */
 /* All pins are on either PA or PB for each serial port */
 #define CONTROL_PINS_PORT_NOT_USED(line) \
 #define CONTROL_PINS_PORT_NOT_USED(line) \
@@ -917,7 +886,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] =
 #endif
 #endif
 	}
 	}
 };
 };
-#endif /* !CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
+#endif /* !ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
 
 
 #define E100_RTS_MASK 0x20
 #define E100_RTS_MASK 0x20
 #define E100_CTS_MASK 0x40
 #define E100_CTS_MASK 0x40
@@ -1367,16 +1336,6 @@ e100_enable_rs485(struct tty_struct *tty, struct serial_rs485 *r)
 #if defined(CONFIG_ETRAX_RS485_ON_PA)
 #if defined(CONFIG_ETRAX_RS485_ON_PA)
 	*R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit);
 	*R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit);
 #endif
 #endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
-	REG_SHADOW_SET(R_PORT_G_DATA,  port_g_data_shadow,
-		       rs485_port_g_bit, 1);
-#endif
-#if defined(CONFIG_ETRAX_RS485_LTC1387)
-	REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
-		       CONFIG_ETRAX_RS485_LTC1387_DXEN_PORT_G_BIT, 1);
-	REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
-		       CONFIG_ETRAX_RS485_LTC1387_RXEN_PORT_G_BIT, 1);
-#endif
 
 
 	info->rs485 = *r;
 	info->rs485 = *r;
 
 
@@ -1676,7 +1635,8 @@ alloc_recv_buffer(unsigned int size)
 {
 {
 	struct etrax_recv_buffer *buffer;
 	struct etrax_recv_buffer *buffer;
 
 
-	if (!(buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC)))
+	buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC);
+	if (!buffer)
 		return NULL;
 		return NULL;
 
 
 	buffer->next = NULL;
 	buffer->next = NULL;
@@ -1712,7 +1672,8 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl
 {
 {
 	struct etrax_recv_buffer *buffer;
 	struct etrax_recv_buffer *buffer;
 	if (info->uses_dma_in) {
 	if (info->uses_dma_in) {
-		if (!(buffer = alloc_recv_buffer(4)))
+		buffer = alloc_recv_buffer(4);
+		if (!buffer)
 			return 0;
 			return 0;
 
 
 		buffer->length = 1;
 		buffer->length = 1;
@@ -1750,7 +1711,8 @@ static unsigned int handle_descr_data(struct e100_serial *info,
 
 
 	append_recv_buffer(info, buffer);
 	append_recv_buffer(info, buffer);
 
 
-	if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
+	buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE);
+	if (!buffer)
 		panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
 		panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
 
 
 	descr->buf = virt_to_phys(buffer->buffer);
 	descr->buf = virt_to_phys(buffer->buffer);
@@ -1841,7 +1803,6 @@ static void receive_chars_dma(struct e100_serial *info)
 		 */
 		 */
 		unsigned char data = info->ioport[REG_DATA];
 		unsigned char data = info->ioport[REG_DATA];
 
 
-		PROCSTAT(ser_stat[info->line].errors_cnt++);
 		DEBUG_LOG(info->line, "#dERR: s d 0x%04X\n",
 		DEBUG_LOG(info->line, "#dERR: s d 0x%04X\n",
 			  ((rstat & SER_ERROR_MASK) << 8) | data);
 			  ((rstat & SER_ERROR_MASK) << 8) | data);
 
 
@@ -1867,7 +1828,8 @@ static int start_recv_dma(struct e100_serial *info)
 
 
 	/* Set up the receiving descriptors */
 	/* Set up the receiving descriptors */
 	for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
 	for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
-		if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
+		buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE);
+		if (!buffer)
 			panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
 			panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
 
 
 		descr[i].ctrl = d_int;
 		descr[i].ctrl = d_int;
@@ -1943,7 +1905,6 @@ tr_interrupt(int irq, void *dev_id)
 			/* Read jiffies_usec first,
 			/* Read jiffies_usec first,
 			 * we want this time to be as late as possible
 			 * we want this time to be as late as possible
 			 */
 			 */
- 			PROCSTAT(ser_stat[info->line].tx_dma_ints++);
 			info->last_tx_active_usec = GET_JIFFIES_USEC();
 			info->last_tx_active_usec = GET_JIFFIES_USEC();
 			info->last_tx_active = jiffies;
 			info->last_tx_active = jiffies;
 			transmit_chars_dma(info);
 			transmit_chars_dma(info);
@@ -2022,7 +1983,6 @@ static int force_eop_if_needed(struct e100_serial *info)
 	 */
 	 */
 	if (!info->forced_eop) {
 	if (!info->forced_eop) {
 		info->forced_eop = 1;
 		info->forced_eop = 1;
-		PROCSTAT(ser_stat[info->line].timeout_flush_cnt++);
 		TIMERD(DEBUG_LOG(info->line, "timeout EOP %i\n", info->line));
 		TIMERD(DEBUG_LOG(info->line, "timeout EOP %i\n", info->line));
 		FORCE_EOP(info);
 		FORCE_EOP(info);
 	}
 	}
@@ -2374,7 +2334,6 @@ static void handle_ser_rx_interrupt(struct e100_serial *info)
 			DEBUG_LOG(info->line, "#iERR s d %04X\n",
 			DEBUG_LOG(info->line, "#iERR s d %04X\n",
 			          ((rstat & SER_ERROR_MASK) << 8) | data);
 			          ((rstat & SER_ERROR_MASK) << 8) | data);
 		}
 		}
-		PROCSTAT(ser_stat[info->line].early_errors_cnt++);
 	} else { /* It was a valid byte, now let the DMA do the rest */
 	} else { /* It was a valid byte, now let the DMA do the rest */
 		unsigned long curr_time_u = GET_JIFFIES_USEC();
 		unsigned long curr_time_u = GET_JIFFIES_USEC();
 		unsigned long curr_time = jiffies;
 		unsigned long curr_time = jiffies;
@@ -2407,7 +2366,6 @@ static void handle_ser_rx_interrupt(struct e100_serial *info)
 		DINTR2(DEBUG_LOG(info->line, "ser_rx OK %d\n", info->line));
 		DINTR2(DEBUG_LOG(info->line, "ser_rx OK %d\n", info->line));
 		info->break_detected_cnt = 0;
 		info->break_detected_cnt = 0;
 
 
-		PROCSTAT(ser_stat[info->line].ser_ints_ok_cnt++);
 	}
 	}
 	/* Restarting the DMA never hurts */
 	/* Restarting the DMA never hurts */
 	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
 	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
@@ -2867,19 +2825,6 @@ change_speed(struct e100_serial *info)
 			*R_SERIAL_PRESCALE = divisor;
 			*R_SERIAL_PRESCALE = divisor;
 			info->baud = SERIAL_PRESCALE_BASE/divisor;
 			info->baud = SERIAL_PRESCALE_BASE/divisor;
 		}
 		}
-#ifdef CONFIG_ETRAX_EXTERN_PB6CLK_ENABLED
-		else if ((info->baud_base==CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8 &&
-			  info->custom_divisor == 1) ||
-			 (info->baud_base==CONFIG_ETRAX_EXTERN_PB6CLK_FREQ &&
-			  info->custom_divisor == 8)) {
-				/* ext_clk selected */
-				alt_source =
-					IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, extern) |
-					IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, extern);
-				DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8));
-				info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8;
-			}
-#endif
 		else
 		else
 		{
 		{
 			/* Bad baudbase, we don't support using timer0
 			/* Bad baudbase, we don't support using timer0
@@ -3216,9 +3161,7 @@ rs_throttle(struct tty_struct * tty)
 {
 {
 	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 #ifdef SERIAL_DEBUG_THROTTLE
 #ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("throttle %s: %lu....\n", tty_name(tty, buf),
+	printk("throttle %s: %lu....\n", tty_name(tty),
 	       (unsigned long)tty->ldisc.chars_in_buffer(tty));
 	       (unsigned long)tty->ldisc.chars_in_buffer(tty));
 #endif
 #endif
 	DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty)));
 	DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty)));
@@ -3238,9 +3181,7 @@ rs_unthrottle(struct tty_struct * tty)
 {
 {
 	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 #ifdef SERIAL_DEBUG_THROTTLE
 #ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("unthrottle %s: %lu....\n", tty_name(tty, buf),
+	printk("unthrottle %s: %lu....\n", tty_name(tty),
 	       (unsigned long)tty->ldisc.chars_in_buffer(tty));
 	       (unsigned long)tty->ldisc.chars_in_buffer(tty));
 #endif
 #endif
 	DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty)));
 	DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty)));
@@ -3724,16 +3665,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
 		info->rs485.flags &= ~(SER_RS485_ENABLED);
 		info->rs485.flags &= ~(SER_RS485_ENABLED);
 #if defined(CONFIG_ETRAX_RS485_ON_PA)
 #if defined(CONFIG_ETRAX_RS485_ON_PA)
 		*R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit);
 		*R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit);
-#endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
-		REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
-			       rs485_port_g_bit, 0);
-#endif
-#if defined(CONFIG_ETRAX_RS485_LTC1387)
-		REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
-			       CONFIG_ETRAX_RS485_LTC1387_DXEN_PORT_G_BIT, 0);
-		REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
-			       CONFIG_ETRAX_RS485_LTC1387_RXEN_PORT_G_BIT, 0);
 #endif
 #endif
 	}
 	}
 #endif
 #endif
@@ -4263,15 +4194,6 @@ static int __init rs_init(void)
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 #endif
 #endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
-	if (cris_io_interface_allocate_pins(if_serial_0, 'g', rs485_pa_bit,
-			rs485_port_g_bit)) {
-		printk(KERN_ERR "ETRAX100LX serial: Could not allocate "
-			"RS485 pin\n");
-		put_tty_driver(driver);
-		return -EBUSY;
-	}
-#endif
 #endif
 #endif
 
 
 	/* Initialize the tty_driver structure */
 	/* Initialize the tty_driver structure */

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

@@ -72,6 +72,7 @@ static int __init parse_options(struct earlycon_device *device, char *options)
 
 
 	switch (port->iotype) {
 	switch (port->iotype) {
 	case UPIO_MEM32:
 	case UPIO_MEM32:
+	case UPIO_MEM32BE:
 		port->regshift = 2;	/* fall-through */
 		port->regshift = 2;	/* fall-through */
 	case UPIO_MEM:
 	case UPIO_MEM:
 		port->mapbase = addr;
 		port->mapbase = addr;
@@ -90,9 +91,11 @@ static int __init parse_options(struct earlycon_device *device, char *options)
 		strlcpy(device->options, options, length);
 		strlcpy(device->options, options, length);
 	}
 	}
 
 
-	if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32)
+	if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32 ||
+	    port->iotype == UPIO_MEM32BE)
 		pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
 		pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
-			(port->iotype == UPIO_MEM32) ? "32" : "",
+			(port->iotype == UPIO_MEM) ? "" :
+			(port->iotype == UPIO_MEM32) ? "32" : "32be",
 			(unsigned long long)port->mapbase,
 			(unsigned long long)port->mapbase,
 			device->options);
 			device->options);
 	else
 	else
@@ -133,7 +136,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match)
  *
  *
  *	Registers the earlycon console matching the earlycon specified
  *	Registers the earlycon console matching the earlycon specified
  *	in the param string @buf. Acceptable param strings are of the form
  *	in the param string @buf. Acceptable param strings are of the form
- *	   <name>,io|mmio|mmio32,<addr>,<options>
+ *	   <name>,io|mmio|mmio32|mmio32be,<addr>,<options>
  *	   <name>,0x<addr>,<options>
  *	   <name>,0x<addr>,<options>
  *	   <name>,<options>
  *	   <name>,<options>
  *	   <name>
  *	   <name>

+ 6 - 5
drivers/tty/serial/icom.c

@@ -1504,7 +1504,8 @@ static int icom_probe(struct pci_dev *dev,
 		return retval;
 		return retval;
 	}
 	}
 
 
-	if ( (retval = pci_request_regions(dev, "icom"))) {
+	retval = pci_request_regions(dev, "icom");
+	if (retval) {
 		 dev_err(&dev->dev, "pci_request_regions FAILED\n");
 		 dev_err(&dev->dev, "pci_request_regions FAILED\n");
 		 pci_disable_device(dev);
 		 pci_disable_device(dev);
 		 return retval;
 		 return retval;
@@ -1512,7 +1513,8 @@ static int icom_probe(struct pci_dev *dev,
 
 
 	pci_set_master(dev);
 	pci_set_master(dev);
 
 
-	if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
+	retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg);
+	if (retval) {
 		dev_err(&dev->dev, "PCI Config read FAILED\n");
 		dev_err(&dev->dev, "PCI Config read FAILED\n");
 		return retval;
 		return retval;
 	}
 	}
@@ -1556,9 +1558,8 @@ static int icom_probe(struct pci_dev *dev,
 	}
 	}
 
 
 	 /* save off irq and request irq line */
 	 /* save off irq and request irq line */
-	 if ( (retval = request_irq(dev->irq, icom_interrupt,
-				   IRQF_SHARED, ICOM_DRIVER_NAME,
-				   (void *) icom_adapter))) {
+	 retval = request_irq(dev->irq, icom_interrupt, IRQF_SHARED, ICOM_DRIVER_NAME, (void *)icom_adapter);
+	 if (retval) {
 		  goto probe_exit2;
 		  goto probe_exit2;
 	 }
 	 }
 
 

+ 9 - 10
drivers/tty/serial/ifx6x60.c

@@ -1175,7 +1175,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 	ret = request_irq(gpio_to_irq(ifx_dev->gpio.reset_out),
 	ret = request_irq(gpio_to_irq(ifx_dev->gpio.reset_out),
 			  ifx_spi_reset_interrupt,
 			  ifx_spi_reset_interrupt,
 			  IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME,
 			  IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME,
-		(void *)ifx_dev);
+			  ifx_dev);
 	if (ret) {
 	if (ret) {
 		dev_err(&spi->dev, "Unable to get irq %x\n",
 		dev_err(&spi->dev, "Unable to get irq %x\n",
 			gpio_to_irq(ifx_dev->gpio.reset_out));
 			gpio_to_irq(ifx_dev->gpio.reset_out));
@@ -1185,9 +1185,8 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 	ret = ifx_spi_reset(ifx_dev);
 	ret = ifx_spi_reset(ifx_dev);
 
 
 	ret = request_irq(gpio_to_irq(ifx_dev->gpio.srdy),
 	ret = request_irq(gpio_to_irq(ifx_dev->gpio.srdy),
-			  ifx_spi_srdy_interrupt,
-			  IRQF_TRIGGER_RISING, DRVNAME,
-			  (void *)ifx_dev);
+			  ifx_spi_srdy_interrupt, IRQF_TRIGGER_RISING, DRVNAME,
+			  ifx_dev);
 	if (ret) {
 	if (ret) {
 		dev_err(&spi->dev, "Unable to get irq %x",
 		dev_err(&spi->dev, "Unable to get irq %x",
 			gpio_to_irq(ifx_dev->gpio.srdy));
 			gpio_to_irq(ifx_dev->gpio.srdy));
@@ -1212,7 +1211,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 	return 0;
 	return 0;
 
 
 error_ret7:
 error_ret7:
-	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), (void *)ifx_dev);
+	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
 error_ret6:
 error_ret6:
 	gpio_free(ifx_dev->gpio.srdy);
 	gpio_free(ifx_dev->gpio.srdy);
 error_ret5:
 error_ret5:
@@ -1243,8 +1242,8 @@ static int ifx_spi_spi_remove(struct spi_device *spi)
 	/* stop activity */
 	/* stop activity */
 	tasklet_kill(&ifx_dev->io_work_tasklet);
 	tasklet_kill(&ifx_dev->io_work_tasklet);
 	/* free irq */
 	/* free irq */
-	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), (void *)ifx_dev);
-	free_irq(gpio_to_irq(ifx_dev->gpio.srdy), (void *)ifx_dev);
+	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev);
+	free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev);
 
 
 	gpio_free(ifx_dev->gpio.srdy);
 	gpio_free(ifx_dev->gpio.srdy);
 	gpio_free(ifx_dev->gpio.mrdy);
 	gpio_free(ifx_dev->gpio.mrdy);
@@ -1381,7 +1380,7 @@ static void __exit ifx_spi_exit(void)
 	/* unregister */
 	/* unregister */
 	tty_unregister_driver(tty_drv);
 	tty_unregister_driver(tty_drv);
 	put_tty_driver(tty_drv);
 	put_tty_driver(tty_drv);
-	spi_unregister_driver((void *)&ifx_spi_driver);
+	spi_unregister_driver(&ifx_spi_driver);
 	unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
 	unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
 }
 }
 
 
@@ -1420,7 +1419,7 @@ static int __init ifx_spi_init(void)
 		goto err_free_tty;
 		goto err_free_tty;
 	}
 	}
 
 
-	result = spi_register_driver((void *)&ifx_spi_driver);
+	result = spi_register_driver(&ifx_spi_driver);
 	if (result) {
 	if (result) {
 		pr_err("%s: spi_register_driver failed(%d)",
 		pr_err("%s: spi_register_driver failed(%d)",
 			DRVNAME, result);
 			DRVNAME, result);
@@ -1436,7 +1435,7 @@ static int __init ifx_spi_init(void)
 
 
 	return 0;
 	return 0;
 err_unreg_spi:
 err_unreg_spi:
-	spi_unregister_driver((void *)&ifx_spi_driver);
+	spi_unregister_driver(&ifx_spi_driver);
 err_unreg_tty:
 err_unreg_tty:
 	tty_unregister_driver(tty_drv);
 	tty_unregister_driver(tty_drv);
 err_free_tty:
 err_free_tty:

+ 8 - 10
drivers/tty/serial/imx.c

@@ -239,7 +239,7 @@ static struct imx_uart_data imx_uart_devdata[] = {
 	},
 	},
 };
 };
 
 
-static struct platform_device_id imx_uart_devtype[] = {
+static const struct platform_device_id imx_uart_devtype[] = {
 	{
 	{
 		.name = "imx1-uart",
 		.name = "imx1-uart",
 		.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
 		.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
@@ -853,7 +853,7 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
 #define TXTL 2 /* reset default */
 #define TXTL 2 /* reset default */
 #define RXTL 1 /* reset default */
 #define RXTL 1 /* reset default */
 
 
-static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
+static void imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 {
 {
 	unsigned int val;
 	unsigned int val;
 
 
@@ -861,7 +861,6 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
 	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
 	val |= TXTL << UFCR_TXTL_SHF | RXTL;
 	val |= TXTL << UFCR_TXTL_SHF | RXTL;
 	writel(val, sport->port.membase + UFCR);
 	writel(val, sport->port.membase + UFCR);
-	return 0;
 }
 }
 
 
 #define RX_BUF_SIZE	(PAGE_SIZE)
 #define RX_BUF_SIZE	(PAGE_SIZE)
@@ -1122,6 +1121,12 @@ 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);
 	/* Reset fifo's and state machines */
 	/* Reset fifo's and state machines */
 	i = 100;
 	i = 100;
 
 
@@ -1132,13 +1137,6 @@ static int imx_startup(struct uart_port *port)
 	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
 	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
 		udelay(1);
 		udelay(1);
 
 
-	/* 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);
-
 	/*
 	/*
 	 * Finally, clear and enable interrupts
 	 * Finally, clear and enable interrupts
 	 */
 	 */

+ 2 - 1
drivers/tty/serial/ioc3_serial.c

@@ -2137,7 +2137,8 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 
 
 	/* register port with the serial core */
 	/* register port with the serial core */
 
 
-	if ((ret = ioc3_serial_core_attach(is, idd)))
+	ret = ioc3_serial_core_attach(is, idd);
+	if (ret)
 		goto out4;
 		goto out4;
 
 
 	Num_of_ioc3_cards++;
 	Num_of_ioc3_cards++;

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

@@ -1011,7 +1011,8 @@ static irqreturn_t ioc4_intr(int irq, void *arg)
 		 */
 		 */
 		for (xx = 0; xx < num_intrs; xx++) {
 		for (xx = 0; xx < num_intrs; xx++) {
 			intr_info = &soft->is_intr_type[intr_type].is_intr_info[xx];
 			intr_info = &soft->is_intr_type[intr_type].is_intr_info[xx];
-			if ((this_mir = this_ir & intr_info->sd_bits)) {
+			this_mir = this_ir & intr_info->sd_bits;
+			if (this_mir) {
 				/* Disable owned interrupts, call handler */
 				/* Disable owned interrupts, call handler */
 				handled++;
 				handled++;
 				write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC,
 				write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC,
@@ -2865,10 +2866,12 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
 
 
 	/* register port with the serial core - 1 rs232, 1 rs422 */
 	/* register port with the serial core - 1 rs232, 1 rs422 */
 
 
-	if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS232)))
+	ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS232);
+	if (ret)
 		goto out4;
 		goto out4;
 
 
-	if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS422)))
+	ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS422);
+	if (ret)
 		goto out5;
 		goto out5;
 
 
 	Num_of_ioc4_cards++;
 	Num_of_ioc4_cards++;

+ 3 - 3
drivers/tty/serial/kgdb_nmi.c

@@ -173,18 +173,18 @@ static int kgdb_nmi_poll_one_knock(void)
 bool kgdb_nmi_poll_knock(void)
 bool kgdb_nmi_poll_knock(void)
 {
 {
 	if (kgdb_nmi_knock < 0)
 	if (kgdb_nmi_knock < 0)
-		return 1;
+		return true;
 
 
 	while (1) {
 	while (1) {
 		int ret;
 		int ret;
 
 
 		ret = kgdb_nmi_poll_one_knock();
 		ret = kgdb_nmi_poll_one_knock();
 		if (ret == NO_POLL_CHAR)
 		if (ret == NO_POLL_CHAR)
-			return 0;
+			return false;
 		else if (ret == 1)
 		else if (ret == 1)
 			break;
 			break;
 	}
 	}
-	return 1;
+	return true;
 }
 }
 
 
 /*
 /*

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

@@ -597,7 +597,7 @@ console_initcall(mcf_console_init);
 #define	MCF_CONSOLE	NULL
 #define	MCF_CONSOLE	NULL
 
 
 /****************************************************************************/
 /****************************************************************************/
-#endif /* CONFIG_MCF_CONSOLE */
+#endif /* CONFIG_SERIAL_MCF_CONSOLE */
 /****************************************************************************/
 /****************************************************************************/
 
 
 /*
 /*

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

@@ -370,7 +370,7 @@ static int meson_uart_verify_port(struct uart_port *port,
 static void meson_uart_release_port(struct uart_port *port)
 static void meson_uart_release_port(struct uart_port *port)
 {
 {
 	if (port->flags & UPF_IOREMAP) {
 	if (port->flags & UPF_IOREMAP) {
-		iounmap(port->membase);
+		devm_iounmap(port->dev, port->membase);
 		port->membase = NULL;
 		port->membase = NULL;
 	}
 	}
 }
 }

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

@@ -405,7 +405,7 @@ static struct psc_ops mpc5200b_psc_ops = {
 	.get_mr1 = mpc52xx_psc_get_mr1,
 	.get_mr1 = mpc52xx_psc_get_mr1,
 };
 };
 
 
-#endif /* CONFIG_MPC52xx */
+#endif /* CONFIG_PPC_MPC52xx */
 
 
 #ifdef CONFIG_PPC_MPC512x
 #ifdef CONFIG_PPC_MPC512x
 #define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1))
 #define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1))

+ 16 - 9
drivers/tty/serial/mpsc.c

@@ -913,7 +913,8 @@ static int mpsc_make_ready(struct mpsc_port_info *pi)
 
 
 	if (!pi->ready) {
 	if (!pi->ready) {
 		mpsc_init_hw(pi);
 		mpsc_init_hw(pi);
-		if ((rc = mpsc_alloc_ring_mem(pi)))
+		rc = mpsc_alloc_ring_mem(pi);
+		if (rc)
 			return rc;
 			return rc;
 		mpsc_init_rings(pi);
 		mpsc_init_rings(pi);
 		pi->ready = 1;
 		pi->ready = 1;
@@ -1895,7 +1896,8 @@ static int mpsc_shared_drv_probe(struct platform_device *dev)
 	int				 rc = -ENODEV;
 	int				 rc = -ENODEV;
 
 
 	if (dev->id == 0) {
 	if (dev->id == 0) {
-		if (!(rc = mpsc_shared_map_regs(dev))) {
+		rc = mpsc_shared_map_regs(dev);
+		if (!rc) {
 			pdata = (struct mpsc_shared_pdata *)
 			pdata = (struct mpsc_shared_pdata *)
 				dev_get_platdata(&dev->dev);
 				dev_get_platdata(&dev->dev);
 
 
@@ -2081,14 +2083,16 @@ static int mpsc_drv_probe(struct platform_device *dev)
 	if (dev->id < MPSC_NUM_CTLRS) {
 	if (dev->id < MPSC_NUM_CTLRS) {
 		pi = &mpsc_ports[dev->id];
 		pi = &mpsc_ports[dev->id];
 
 
-		if (!(rc = mpsc_drv_map_regs(pi, dev))) {
+		rc = mpsc_drv_map_regs(pi, dev);
+		if (!rc) {
 			mpsc_drv_get_platform_data(pi, dev, dev->id);
 			mpsc_drv_get_platform_data(pi, dev, dev->id);
 			pi->port.dev = &dev->dev;
 			pi->port.dev = &dev->dev;
 
 
-			if (!(rc = mpsc_make_ready(pi))) {
+			rc = mpsc_make_ready(pi);
+			if (!rc) {
 				spin_lock_init(&pi->tx_lock);
 				spin_lock_init(&pi->tx_lock);
-				if (!(rc = uart_add_one_port(&mpsc_reg,
-								&pi->port))) {
+				rc = uart_add_one_port(&mpsc_reg, &pi->port);
+				if (!rc) {
 					rc = 0;
 					rc = 0;
 				} else {
 				} else {
 					mpsc_release_port((struct uart_port *)
 					mpsc_release_port((struct uart_port *)
@@ -2136,9 +2140,12 @@ static int __init mpsc_drv_init(void)
 	memset(mpsc_ports, 0, sizeof(mpsc_ports));
 	memset(mpsc_ports, 0, sizeof(mpsc_ports));
 	memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs));
 	memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs));
 
 
-	if (!(rc = uart_register_driver(&mpsc_reg))) {
-		if (!(rc = platform_driver_register(&mpsc_shared_driver))) {
-			if ((rc = platform_driver_register(&mpsc_driver))) {
+	rc = uart_register_driver(&mpsc_reg);
+	if (!rc) {
+		rc = platform_driver_register(&mpsc_shared_driver);
+		if (!rc) {
+			rc = platform_driver_register(&mpsc_driver);
+			if (rc) {
 				platform_driver_unregister(&mpsc_shared_driver);
 				platform_driver_unregister(&mpsc_shared_driver);
 				uart_unregister_driver(&mpsc_reg);
 				uart_unregister_driver(&mpsc_reg);
 			}
 			}

+ 0 - 232
drivers/tty/serial/msm_smd_tty.c

@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-
-#include <mach/msm_smd.h>
-
-#define MAX_SMD_TTYS 32
-
-struct smd_tty_info {
-	struct tty_port port;
-	smd_channel_t *ch;
-};
-
-struct smd_tty_channel_desc {
-	int id;
-	const char *name;
-};
-
-static struct smd_tty_info smd_tty[MAX_SMD_TTYS];
-
-static const struct smd_tty_channel_desc smd_default_tty_channels[] = {
-	{ .id = 0, .name = "SMD_DS" },
-	{ .id = 27, .name = "SMD_GPSNMEA" },
-};
-
-static const struct smd_tty_channel_desc *smd_tty_channels =
-		smd_default_tty_channels;
-static int smd_tty_channels_len = ARRAY_SIZE(smd_default_tty_channels);
-
-static void smd_tty_notify(void *priv, unsigned event)
-{
-	unsigned char *ptr;
-	int avail;
-	struct smd_tty_info *info = priv;
-	struct tty_struct *tty;
-
-	if (event != SMD_EVENT_DATA)
-		return;
-
-	tty = tty_port_tty_get(&info->port);
-	if (!tty)
-		return;
-
-	for (;;) {
-		if (test_bit(TTY_THROTTLED, &tty->flags))
-			break;
-		avail = smd_read_avail(info->ch);
-		if (avail == 0)
-			break;
-
-		avail = tty_prepare_flip_string(&info->port, &ptr, avail);
-
-		if (smd_read(info->ch, ptr, avail) != avail) {
-			/* shouldn't be possible since we're in interrupt
-			** context here and nobody else could 'steal' our
-			** characters.
-			*/
-			pr_err("OOPS - smd_tty_buffer mismatch?!");
-		}
-
-		tty_flip_buffer_push(&info->port);
-	}
-
-	/* XXX only when writable and necessary */
-	tty_wakeup(tty);
-	tty_kref_put(tty);
-}
-
-static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
-{
-	struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
-			port);
-	int i, res = 0;
-	const char *name = NULL;
-
-	for (i = 0; i < smd_tty_channels_len; i++) {
-		if (smd_tty_channels[i].id == tty->index) {
-			name = smd_tty_channels[i].name;
-			break;
-		}
-	}
-	if (!name)
-		return -ENODEV;
-
-	if (info->ch)
-		smd_kick(info->ch);
-	else
-		res = smd_open(name, &info->ch, info, smd_tty_notify);
-
-	if (!res)
-		tty->driver_data = info;
-
-	return res;
-}
-
-static void smd_tty_port_shutdown(struct tty_port *tport)
-{
-	struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
-			port);
-
-	if (info->ch) {
-		smd_close(info->ch);
-		info->ch = 0;
-	}
-}
-
-static int smd_tty_open(struct tty_struct *tty, struct file *f)
-{
-	struct smd_tty_info *info = smd_tty + tty->index;
-
-	return tty_port_open(&info->port, tty, f);
-}
-
-static void smd_tty_close(struct tty_struct *tty, struct file *f)
-{
-	struct smd_tty_info *info = tty->driver_data;
-
-	tty_port_close(&info->port, tty, f);
-}
-
-static int smd_tty_write(struct tty_struct *tty,
-			 const unsigned char *buf, int len)
-{
-	struct smd_tty_info *info = tty->driver_data;
-	int avail;
-
-	/* if we're writing to a packet channel we will
-	** never be able to write more data than there
-	** is currently space for
-	*/
-	avail = smd_write_avail(info->ch);
-	if (len > avail)
-		len = avail;
-
-	return smd_write(info->ch, buf, len);
-}
-
-static int smd_tty_write_room(struct tty_struct *tty)
-{
-	struct smd_tty_info *info = tty->driver_data;
-	return smd_write_avail(info->ch);
-}
-
-static int smd_tty_chars_in_buffer(struct tty_struct *tty)
-{
-	struct smd_tty_info *info = tty->driver_data;
-	return smd_read_avail(info->ch);
-}
-
-static void smd_tty_unthrottle(struct tty_struct *tty)
-{
-	struct smd_tty_info *info = tty->driver_data;
-	smd_kick(info->ch);
-}
-
-static const struct tty_port_operations smd_tty_port_ops = {
-	.shutdown = smd_tty_port_shutdown,
-	.activate = smd_tty_port_activate,
-};
-
-static const struct tty_operations smd_tty_ops = {
-	.open = smd_tty_open,
-	.close = smd_tty_close,
-	.write = smd_tty_write,
-	.write_room = smd_tty_write_room,
-	.chars_in_buffer = smd_tty_chars_in_buffer,
-	.unthrottle = smd_tty_unthrottle,
-};
-
-static struct tty_driver *smd_tty_driver;
-
-static int __init smd_tty_init(void)
-{
-	int ret, i;
-
-	smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS);
-	if (smd_tty_driver == 0)
-		return -ENOMEM;
-
-	smd_tty_driver->driver_name = "smd_tty_driver";
-	smd_tty_driver->name = "smd";
-	smd_tty_driver->major = 0;
-	smd_tty_driver->minor_start = 0;
-	smd_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	smd_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	smd_tty_driver->init_termios = tty_std_termios;
-	smd_tty_driver->init_termios.c_iflag = 0;
-	smd_tty_driver->init_termios.c_oflag = 0;
-	smd_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
-	smd_tty_driver->init_termios.c_lflag = 0;
-	smd_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS |
-		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(smd_tty_driver, &smd_tty_ops);
-
-	ret = tty_register_driver(smd_tty_driver);
-	if (ret)
-		return ret;
-
-	for (i = 0; i < smd_tty_channels_len; i++) {
-		struct tty_port *port = &smd_tty[smd_tty_channels[i].id].port;
-		tty_port_init(port);
-		port->ops = &smd_tty_port_ops;
-		tty_port_register_device(port, smd_tty_driver,
-				smd_tty_channels[i].id, NULL);
-	}
-
-	return 0;
-}
-
-module_init(smd_tty_init);

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

@@ -169,7 +169,7 @@ struct mxs_auart_port {
 	bool			ms_irq_enabled;
 	bool			ms_irq_enabled;
 };
 };
 
 
-static struct platform_device_id mxs_auart_devtype[] = {
+static const struct platform_device_id mxs_auart_devtype[] = {
 	{ .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
 	{ .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
 	{ .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
 	{ .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
 	{ /* sentinel */ }
 	{ /* sentinel */ }

+ 5 - 3
drivers/tty/serial/of_serial.c

@@ -67,14 +67,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 	if (of_property_read_u32(np, "clock-frequency", &clk)) {
 	if (of_property_read_u32(np, "clock-frequency", &clk)) {
 
 
 		/* Get clk rate through clk driver if present */
 		/* Get clk rate through clk driver if present */
-		info->clk = clk_get(&ofdev->dev, NULL);
+		info->clk = devm_clk_get(&ofdev->dev, NULL);
 		if (IS_ERR(info->clk)) {
 		if (IS_ERR(info->clk)) {
 			dev_warn(&ofdev->dev,
 			dev_warn(&ofdev->dev,
 				"clk or clock-frequency not defined\n");
 				"clk or clock-frequency not defined\n");
 			return PTR_ERR(info->clk);
 			return PTR_ERR(info->clk);
 		}
 		}
 
 
-		clk_prepare_enable(info->clk);
+		ret = clk_prepare_enable(info->clk);
+		if (ret < 0)
+			return ret;
+
 		clk = clk_get_rate(info->clk);
 		clk = clk_get_rate(info->clk);
 	}
 	}
 	/* If current-speed was set, then try not to change it. */
 	/* If current-speed was set, then try not to change it. */
@@ -188,7 +191,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 	{
 	{
 		struct uart_8250_port port8250;
 		struct uart_8250_port port8250;
 		memset(&port8250, 0, sizeof(port8250));
 		memset(&port8250, 0, sizeof(port8250));
-		port.type = port_type;
 		port8250.port = port;
 		port8250.port = port;
 
 
 		if (port.fifosize)
 		if (port.fifosize)

+ 2 - 2
drivers/tty/serial/samsung.c

@@ -348,7 +348,7 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
 		s3c24xx_serial_start_tx_dma(ourport, count);
 		s3c24xx_serial_start_tx_dma(ourport, count);
 }
 }
 
 
-void s3c24xx_serial_start_tx(struct uart_port *port)
+static void s3c24xx_serial_start_tx(struct uart_port *port)
 {
 {
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
 	struct circ_buf *xmit = &port->state->xmit;
 	struct circ_buf *xmit = &port->state->xmit;
@@ -2337,7 +2337,7 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
 #define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL
 #define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL
 #endif
 #endif
 
 
-static struct platform_device_id s3c24xx_serial_driver_ids[] = {
+static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
 	{
 	{
 		.name		= "s3c2410-uart",
 		.name		= "s3c2410-uart",
 		.driver_data	= S3C2410_SERIAL_DRV_DATA,
 		.driver_data	= S3C2410_SERIAL_DRV_DATA,

+ 243 - 85
drivers/tty/serial/sc16is7xx.c

@@ -25,6 +25,7 @@
 #include <linux/serial.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
 
 
 #define SC16IS7XX_NAME			"sc16is7xx"
 #define SC16IS7XX_NAME			"sc16is7xx"
@@ -300,25 +301,38 @@ struct sc16is7xx_devtype {
 	int	nr_uart;
 	int	nr_uart;
 };
 };
 
 
+#define SC16IS7XX_RECONF_MD		(1 << 0)
+#define SC16IS7XX_RECONF_IER		(1 << 1)
+#define SC16IS7XX_RECONF_RS485		(1 << 2)
+
+struct sc16is7xx_one_config {
+	unsigned int			flags;
+	u8				ier_clear;
+};
+
 struct sc16is7xx_one {
 struct sc16is7xx_one {
 	struct uart_port		port;
 	struct uart_port		port;
-	struct work_struct		tx_work;
-	struct work_struct		md_work;
+	struct kthread_work		tx_work;
+	struct kthread_work		reg_work;
+	struct sc16is7xx_one_config	config;
 };
 };
 
 
 struct sc16is7xx_port {
 struct sc16is7xx_port {
 	struct uart_driver		uart;
 	struct uart_driver		uart;
 	struct sc16is7xx_devtype	*devtype;
 	struct sc16is7xx_devtype	*devtype;
 	struct regmap			*regmap;
 	struct regmap			*regmap;
-	struct mutex			mutex;
 	struct clk			*clk;
 	struct clk			*clk;
 #ifdef CONFIG_GPIOLIB
 #ifdef CONFIG_GPIOLIB
 	struct gpio_chip		gpio;
 	struct gpio_chip		gpio;
 #endif
 #endif
 	unsigned char			buf[SC16IS7XX_FIFO_SIZE];
 	unsigned char			buf[SC16IS7XX_FIFO_SIZE];
+	struct kthread_worker		kworker;
+	struct task_struct		*kworker_task;
+	struct kthread_work		irq_work;
 	struct sc16is7xx_one		p[0];
 	struct sc16is7xx_one		p[0];
 };
 };
 
 
+#define to_sc16is7xx_port(p,e)	((container_of((p), struct sc16is7xx_port, e)))
 #define to_sc16is7xx_one(p,e)	((container_of((p), struct sc16is7xx_one, e)))
 #define to_sc16is7xx_one(p,e)	((container_of((p), struct sc16is7xx_one, e)))
 
 
 static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
 static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
@@ -615,9 +629,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
 					       !!(msr & SC16IS7XX_MSR_CTS_BIT));
 					       !!(msr & SC16IS7XX_MSR_CTS_BIT));
 			break;
 			break;
 		case SC16IS7XX_IIR_THRI_SRC:
 		case SC16IS7XX_IIR_THRI_SRC:
-			mutex_lock(&s->mutex);
 			sc16is7xx_handle_tx(port);
 			sc16is7xx_handle_tx(port);
-			mutex_unlock(&s->mutex);
 			break;
 			break;
 		default:
 		default:
 			dev_err_ratelimited(port->dev,
 			dev_err_ratelimited(port->dev,
@@ -628,81 +640,115 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
 	} while (1);
 	} while (1);
 }
 }
 
 
-static irqreturn_t sc16is7xx_ist(int irq, void *dev_id)
+static void sc16is7xx_ist(struct kthread_work *ws)
 {
 {
-	struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id;
+	struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
 	int i;
 	int i;
 
 
 	for (i = 0; i < s->uart.nr; ++i)
 	for (i = 0; i < s->uart.nr; ++i)
 		sc16is7xx_port_irq(s, i);
 		sc16is7xx_port_irq(s, i);
+}
+
+static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
+{
+	struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id;
+
+	queue_kthread_work(&s->kworker, &s->irq_work);
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-static void sc16is7xx_wq_proc(struct work_struct *ws)
+static void sc16is7xx_tx_proc(struct kthread_work *ws)
 {
 {
-	struct sc16is7xx_one *one = to_sc16is7xx_one(ws, tx_work);
-	struct sc16is7xx_port *s = dev_get_drvdata(one->port.dev);
+	struct uart_port *port = &(to_sc16is7xx_one(ws, tx_work)->port);
+
+	if ((port->rs485.flags & SER_RS485_ENABLED) &&
+	    (port->rs485.delay_rts_before_send > 0))
+		msleep(port->rs485.delay_rts_before_send);
 
 
-	mutex_lock(&s->mutex);
-	sc16is7xx_handle_tx(&one->port);
-	mutex_unlock(&s->mutex);
+	sc16is7xx_handle_tx(port);
 }
 }
 
 
-static void sc16is7xx_stop_tx(struct uart_port* port)
+static void sc16is7xx_reconf_rs485(struct uart_port *port)
 {
 {
-	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-	struct circ_buf *xmit = &one->port.state->xmit;
-
-	/* handle rs485 */
-	if (port->rs485.flags & SER_RS485_ENABLED) {
-		/* do nothing if current tx not yet completed */
-		int lsr = sc16is7xx_port_read(port, SC16IS7XX_LSR_REG);
-		if (!(lsr & SC16IS7XX_LSR_TEMT_BIT))
-			return;
-
-		if (uart_circ_empty(xmit) &&
-		    (port->rs485.delay_rts_after_send > 0))
-			mdelay(port->rs485.delay_rts_after_send);
+	const u32 mask = SC16IS7XX_EFCR_AUTO_RS485_BIT |
+			 SC16IS7XX_EFCR_RTS_INVERT_BIT;
+	u32 efcr = 0;
+	struct serial_rs485 *rs485 = &port->rs485;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&port->lock, irqflags);
+	if (rs485->flags & SER_RS485_ENABLED) {
+		efcr |=	SC16IS7XX_EFCR_AUTO_RS485_BIT;
+
+		if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
+			efcr |= SC16IS7XX_EFCR_RTS_INVERT_BIT;
 	}
 	}
+	spin_unlock_irqrestore(&port->lock, irqflags);
 
 
-	sc16is7xx_port_update(port, SC16IS7XX_IER_REG,
-			      SC16IS7XX_IER_THRI_BIT,
-			      0);
+	sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, mask, efcr);
 }
 }
 
 
-static void sc16is7xx_stop_rx(struct uart_port* port)
+static void sc16is7xx_reg_proc(struct kthread_work *ws)
 {
 {
+	struct sc16is7xx_one *one = to_sc16is7xx_one(ws, reg_work);
+	struct sc16is7xx_one_config config;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&one->port.lock, irqflags);
+	config = one->config;
+	memset(&one->config, 0, sizeof(one->config));
+	spin_unlock_irqrestore(&one->port.lock, irqflags);
+
+	if (config.flags & SC16IS7XX_RECONF_MD)
+		sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
+				      SC16IS7XX_MCR_LOOP_BIT,
+				      (one->port.mctrl & TIOCM_LOOP) ?
+				      SC16IS7XX_MCR_LOOP_BIT : 0);
+
+	if (config.flags & SC16IS7XX_RECONF_IER)
+		sc16is7xx_port_update(&one->port, SC16IS7XX_IER_REG,
+				      config.ier_clear, 0);
+
+	if (config.flags & SC16IS7XX_RECONF_RS485)
+		sc16is7xx_reconf_rs485(&one->port);
+}
+
+static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit)
+{
+	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
 	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
 	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
 
 
-	one->port.read_status_mask &= ~SC16IS7XX_LSR_DR_BIT;
-	sc16is7xx_port_update(port, SC16IS7XX_IER_REG,
-			      SC16IS7XX_LSR_DR_BIT,
-			      0);
+	one->config.flags |= SC16IS7XX_RECONF_IER;
+	one->config.ier_clear |= bit;
+	queue_kthread_work(&s->kworker, &one->reg_work);
+}
+
+static void sc16is7xx_stop_tx(struct uart_port *port)
+{
+	sc16is7xx_ier_clear(port, SC16IS7XX_IER_THRI_BIT);
+}
+
+static void sc16is7xx_stop_rx(struct uart_port *port)
+{
+	sc16is7xx_ier_clear(port, SC16IS7XX_IER_RDI_BIT);
 }
 }
 
 
 static void sc16is7xx_start_tx(struct uart_port *port)
 static void sc16is7xx_start_tx(struct uart_port *port)
 {
 {
+	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
 	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
 	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
 
 
-	/* handle rs485 */
-	if ((port->rs485.flags & SER_RS485_ENABLED) &&
-	    (port->rs485.delay_rts_before_send > 0)) {
-		mdelay(port->rs485.delay_rts_before_send);
-	}
-
-	if (!work_pending(&one->tx_work))
-		schedule_work(&one->tx_work);
+	queue_kthread_work(&s->kworker, &one->tx_work);
 }
 }
 
 
 static unsigned int sc16is7xx_tx_empty(struct uart_port *port)
 static unsigned int sc16is7xx_tx_empty(struct uart_port *port)
 {
 {
-	unsigned int lvl, lsr;
+	unsigned int lsr;
 
 
-	lvl = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG);
 	lsr = sc16is7xx_port_read(port, SC16IS7XX_LSR_REG);
 	lsr = sc16is7xx_port_read(port, SC16IS7XX_LSR_REG);
 
 
-	return ((lsr & SC16IS7XX_LSR_THRE_BIT) && !lvl) ? TIOCSER_TEMT : 0;
+	return (lsr & SC16IS7XX_LSR_TEMT_BIT) ? TIOCSER_TEMT : 0;
 }
 }
 
 
 static unsigned int sc16is7xx_get_mctrl(struct uart_port *port)
 static unsigned int sc16is7xx_get_mctrl(struct uart_port *port)
@@ -713,21 +759,13 @@ static unsigned int sc16is7xx_get_mctrl(struct uart_port *port)
 	return TIOCM_DSR | TIOCM_CAR;
 	return TIOCM_DSR | TIOCM_CAR;
 }
 }
 
 
-static void sc16is7xx_md_proc(struct work_struct *ws)
-{
-	struct sc16is7xx_one *one = to_sc16is7xx_one(ws, md_work);
-
-	sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
-			      SC16IS7XX_MCR_LOOP_BIT,
-			      (one->port.mctrl & TIOCM_LOOP) ?
-				      SC16IS7XX_MCR_LOOP_BIT : 0);
-}
-
 static void sc16is7xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void sc16is7xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 {
+	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
 	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
 	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
 
 
-	schedule_work(&one->md_work);
+	one->config.flags |= SC16IS7XX_RECONF_MD;
+	queue_kthread_work(&s->kworker, &one->reg_work);
 }
 }
 
 
 static void sc16is7xx_break_ctl(struct uart_port *port, int break_state)
 static void sc16is7xx_break_ctl(struct uart_port *port, int break_state)
@@ -831,9 +869,8 @@ static void sc16is7xx_set_termios(struct uart_port *port,
 static int sc16is7xx_config_rs485(struct uart_port *port,
 static int sc16is7xx_config_rs485(struct uart_port *port,
 				  struct serial_rs485 *rs485)
 				  struct serial_rs485 *rs485)
 {
 {
-	const u32 mask = SC16IS7XX_EFCR_AUTO_RS485_BIT |
-			 SC16IS7XX_EFCR_RTS_INVERT_BIT;
-	u32 efcr = 0;
+	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+	struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
 
 
 	if (rs485->flags & SER_RS485_ENABLED) {
 	if (rs485->flags & SER_RS485_ENABLED) {
 		bool rts_during_rx, rts_during_tx;
 		bool rts_during_rx, rts_during_tx;
@@ -841,21 +878,23 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
 		rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
 		rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
 		rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
 		rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
 
 
-		efcr |= SC16IS7XX_EFCR_AUTO_RS485_BIT;
-
-		if (!rts_during_rx && rts_during_tx)
-			/* default */;
-		else if (rts_during_rx && !rts_during_tx)
-			efcr |= SC16IS7XX_EFCR_RTS_INVERT_BIT;
-		else
+		if (rts_during_rx == rts_during_tx)
 			dev_err(port->dev,
 			dev_err(port->dev,
 				"unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n",
 				"unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n",
 				rts_during_tx, rts_during_rx);
 				rts_during_tx, rts_during_rx);
-	}
 
 
-	sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, mask, efcr);
+		/*
+		 * RTS signal is handled by HW, it's timing can't be influenced.
+		 * However, it's sometimes useful to delay TX even without RTS
+		 * control therefore we try to handle .delay_rts_before_send.
+		 */
+		if (rs485->delay_rts_after_send)
+			return -EINVAL;
+	}
 
 
 	port->rs485 = *rs485;
 	port->rs485 = *rs485;
+	one->config.flags |= SC16IS7XX_RECONF_RS485;
+	queue_kthread_work(&s->kworker, &one->reg_work);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -916,6 +955,8 @@ static int sc16is7xx_startup(struct uart_port *port)
 
 
 static void sc16is7xx_shutdown(struct uart_port *port)
 static void sc16is7xx_shutdown(struct uart_port *port)
 {
 {
+	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+
 	/* Disable all interrupts */
 	/* Disable all interrupts */
 	sc16is7xx_port_write(port, SC16IS7XX_IER_REG, 0);
 	sc16is7xx_port_write(port, SC16IS7XX_IER_REG, 0);
 	/* Disable TX/RX */
 	/* Disable TX/RX */
@@ -926,6 +967,8 @@ static void sc16is7xx_shutdown(struct uart_port *port)
 			      SC16IS7XX_EFCR_TXDISABLE_BIT);
 			      SC16IS7XX_EFCR_TXDISABLE_BIT);
 
 
 	sc16is7xx_power(port, 0);
 	sc16is7xx_power(port, 0);
+
+	flush_kthread_worker(&s->kworker);
 }
 }
 
 
 static const char *sc16is7xx_type(struct uart_port *port)
 static const char *sc16is7xx_type(struct uart_port *port)
@@ -1043,6 +1086,7 @@ static int sc16is7xx_probe(struct device *dev,
 			   struct sc16is7xx_devtype *devtype,
 			   struct sc16is7xx_devtype *devtype,
 			   struct regmap *regmap, int irq, unsigned long flags)
 			   struct regmap *regmap, int irq, unsigned long flags)
 {
 {
+	struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
 	unsigned long freq, *pfreq = dev_get_platdata(dev);
 	unsigned long freq, *pfreq = dev_get_platdata(dev);
 	int i, ret;
 	int i, ret;
 	struct sc16is7xx_port *s;
 	struct sc16is7xx_port *s;
@@ -1084,6 +1128,16 @@ static int sc16is7xx_probe(struct device *dev,
 		goto out_clk;
 		goto out_clk;
 	}
 	}
 
 
+	init_kthread_worker(&s->kworker);
+	init_kthread_work(&s->irq_work, sc16is7xx_ist);
+	s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
+				      "sc16is7xx");
+	if (IS_ERR(s->kworker_task)) {
+		ret = PTR_ERR(s->kworker_task);
+		goto out_uart;
+	}
+	sched_setscheduler(s->kworker_task, SCHED_FIFO, &sched_param);
+
 #ifdef CONFIG_GPIOLIB
 #ifdef CONFIG_GPIOLIB
 	if (devtype->nr_gpio) {
 	if (devtype->nr_gpio) {
 		/* Setup GPIO cotroller */
 		/* Setup GPIO cotroller */
@@ -1099,12 +1153,10 @@ static int sc16is7xx_probe(struct device *dev,
 		s->gpio.can_sleep	 = 1;
 		s->gpio.can_sleep	 = 1;
 		ret = gpiochip_add(&s->gpio);
 		ret = gpiochip_add(&s->gpio);
 		if (ret)
 		if (ret)
-			goto out_uart;
+			goto out_thread;
 	}
 	}
 #endif
 #endif
 
 
-	mutex_init(&s->mutex);
-
 	for (i = 0; i < devtype->nr_uart; ++i) {
 	for (i = 0; i < devtype->nr_uart; ++i) {
 		/* Initialize port data */
 		/* Initialize port data */
 		s->p[i].port.line	= i;
 		s->p[i].port.line	= i;
@@ -1123,10 +1175,9 @@ static int sc16is7xx_probe(struct device *dev,
 		sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFCR_REG,
 		sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFCR_REG,
 				     SC16IS7XX_EFCR_RXDISABLE_BIT |
 				     SC16IS7XX_EFCR_RXDISABLE_BIT |
 				     SC16IS7XX_EFCR_TXDISABLE_BIT);
 				     SC16IS7XX_EFCR_TXDISABLE_BIT);
-		/* Initialize queue for start TX */
-		INIT_WORK(&s->p[i].tx_work, sc16is7xx_wq_proc);
-		/* Initialize queue for changing mode */
-		INIT_WORK(&s->p[i].md_work, sc16is7xx_md_proc);
+		/* Initialize kthread work structs */
+		init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
+		init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
 		/* Register port */
 		/* Register port */
 		uart_add_one_port(&s->uart, &s->p[i].port);
 		uart_add_one_port(&s->uart, &s->p[i].port);
 		/* Go to suspend mode */
 		/* Go to suspend mode */
@@ -1134,22 +1185,23 @@ static int sc16is7xx_probe(struct device *dev,
 	}
 	}
 
 
 	/* Setup interrupt */
 	/* Setup interrupt */
-	ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_ist,
-					IRQF_ONESHOT | flags, dev_name(dev), s);
+	ret = devm_request_irq(dev, irq, sc16is7xx_irq,
+			       IRQF_ONESHOT | flags, dev_name(dev), s);
 	if (!ret)
 	if (!ret)
 		return 0;
 		return 0;
 
 
 	for (i = 0; i < s->uart.nr; i++)
 	for (i = 0; i < s->uart.nr; i++)
 		uart_remove_one_port(&s->uart, &s->p[i].port);
 		uart_remove_one_port(&s->uart, &s->p[i].port);
 
 
-	mutex_destroy(&s->mutex);
-
 #ifdef CONFIG_GPIOLIB
 #ifdef CONFIG_GPIOLIB
 	if (devtype->nr_gpio)
 	if (devtype->nr_gpio)
 		gpiochip_remove(&s->gpio);
 		gpiochip_remove(&s->gpio);
 
 
-out_uart:
+out_thread:
 #endif
 #endif
+	kthread_stop(s->kworker_task);
+
+out_uart:
 	uart_unregister_driver(&s->uart);
 	uart_unregister_driver(&s->uart);
 
 
 out_clk:
 out_clk:
@@ -1170,13 +1222,13 @@ static int sc16is7xx_remove(struct device *dev)
 #endif
 #endif
 
 
 	for (i = 0; i < s->uart.nr; i++) {
 	for (i = 0; i < s->uart.nr; i++) {
-		cancel_work_sync(&s->p[i].tx_work);
-		cancel_work_sync(&s->p[i].md_work);
 		uart_remove_one_port(&s->uart, &s->p[i].port);
 		uart_remove_one_port(&s->uart, &s->p[i].port);
 		sc16is7xx_power(&s->p[i].port, 0);
 		sc16is7xx_power(&s->p[i].port, 0);
 	}
 	}
 
 
-	mutex_destroy(&s->mutex);
+	flush_kthread_worker(&s->kworker);
+	kthread_stop(s->kworker_task);
+
 	uart_unregister_driver(&s->uart);
 	uart_unregister_driver(&s->uart);
 	if (!IS_ERR(s->clk))
 	if (!IS_ERR(s->clk))
 		clk_disable_unprepare(s->clk);
 		clk_disable_unprepare(s->clk);
@@ -1204,6 +1256,75 @@ static struct regmap_config regcfg = {
 	.precious_reg = sc16is7xx_regmap_precious,
 	.precious_reg = sc16is7xx_regmap_precious,
 };
 };
 
 
+#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
+static int sc16is7xx_spi_probe(struct spi_device *spi)
+{
+	struct sc16is7xx_devtype *devtype;
+	unsigned long flags = 0;
+	struct regmap *regmap;
+	int ret;
+
+	/* Setup SPI bus */
+	spi->bits_per_word	= 8;
+	/* only supports mode 0 on SC16IS762 */
+	spi->mode		= spi->mode ? : SPI_MODE_0;
+	spi->max_speed_hz	= spi->max_speed_hz ? : 15000000;
+	ret = spi_setup(spi);
+	if (ret)
+		return ret;
+
+	if (spi->dev.of_node) {
+		const struct of_device_id *of_id =
+			of_match_device(sc16is7xx_dt_ids, &spi->dev);
+
+		devtype = (struct sc16is7xx_devtype *)of_id->data;
+	} else {
+		const struct spi_device_id *id_entry = spi_get_device_id(spi);
+
+		devtype = (struct sc16is7xx_devtype *)id_entry->driver_data;
+		flags = IRQF_TRIGGER_FALLING;
+	}
+
+	regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
+			      (devtype->nr_uart - 1);
+	regmap = devm_regmap_init_spi(spi, &regcfg);
+
+	return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq, flags);
+}
+
+static int sc16is7xx_spi_remove(struct spi_device *spi)
+{
+	return sc16is7xx_remove(&spi->dev);
+}
+
+static const struct spi_device_id sc16is7xx_spi_id_table[] = {
+	{ "sc16is74x",	(kernel_ulong_t)&sc16is74x_devtype, },
+	{ "sc16is740",	(kernel_ulong_t)&sc16is74x_devtype, },
+	{ "sc16is741",	(kernel_ulong_t)&sc16is74x_devtype, },
+	{ "sc16is750",	(kernel_ulong_t)&sc16is750_devtype, },
+	{ "sc16is752",	(kernel_ulong_t)&sc16is752_devtype, },
+	{ "sc16is760",	(kernel_ulong_t)&sc16is760_devtype, },
+	{ "sc16is762",	(kernel_ulong_t)&sc16is762_devtype, },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(spi, sc16is7xx_spi_id_table);
+
+static struct spi_driver sc16is7xx_spi_uart_driver = {
+	.driver = {
+		.name		= SC16IS7XX_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(sc16is7xx_dt_ids),
+	},
+	.probe		= sc16is7xx_spi_probe,
+	.remove		= sc16is7xx_spi_remove,
+	.id_table	= sc16is7xx_spi_id_table,
+};
+
+MODULE_ALIAS("spi:sc16is7xx");
+#endif
+
+#ifdef CONFIG_SERIAL_SC16IS7XX_I2C
 static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
 static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
 			       const struct i2c_device_id *id)
 			       const struct i2c_device_id *id)
 {
 {
@@ -1235,6 +1356,8 @@ static int sc16is7xx_i2c_remove(struct i2c_client *client)
 
 
 static const struct i2c_device_id sc16is7xx_i2c_id_table[] = {
 static const struct i2c_device_id sc16is7xx_i2c_id_table[] = {
 	{ "sc16is74x",	(kernel_ulong_t)&sc16is74x_devtype, },
 	{ "sc16is74x",	(kernel_ulong_t)&sc16is74x_devtype, },
+	{ "sc16is740",	(kernel_ulong_t)&sc16is74x_devtype, },
+	{ "sc16is741",	(kernel_ulong_t)&sc16is74x_devtype, },
 	{ "sc16is750",	(kernel_ulong_t)&sc16is750_devtype, },
 	{ "sc16is750",	(kernel_ulong_t)&sc16is750_devtype, },
 	{ "sc16is752",	(kernel_ulong_t)&sc16is752_devtype, },
 	{ "sc16is752",	(kernel_ulong_t)&sc16is752_devtype, },
 	{ "sc16is760",	(kernel_ulong_t)&sc16is760_devtype, },
 	{ "sc16is760",	(kernel_ulong_t)&sc16is760_devtype, },
@@ -1253,8 +1376,43 @@ static struct i2c_driver sc16is7xx_i2c_uart_driver = {
 	.remove		= sc16is7xx_i2c_remove,
 	.remove		= sc16is7xx_i2c_remove,
 	.id_table	= sc16is7xx_i2c_id_table,
 	.id_table	= sc16is7xx_i2c_id_table,
 };
 };
-module_i2c_driver(sc16is7xx_i2c_uart_driver);
+
 MODULE_ALIAS("i2c:sc16is7xx");
 MODULE_ALIAS("i2c:sc16is7xx");
+#endif
+
+static int __init sc16is7xx_init(void)
+{
+	int ret = 0;
+#ifdef CONFIG_SERIAL_SC16IS7XX_I2C
+	ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
+	if (ret < 0) {
+		pr_err("failed to init sc16is7xx i2c --> %d\n", ret);
+		return ret;
+	}
+#endif
+
+#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
+	ret = spi_register_driver(&sc16is7xx_spi_uart_driver);
+	if (ret < 0) {
+		pr_err("failed to init sc16is7xx spi --> %d\n", ret);
+		return ret;
+	}
+#endif
+	return ret;
+}
+module_init(sc16is7xx_init);
+
+static void __exit sc16is7xx_exit(void)
+{
+#ifdef CONFIG_SERIAL_SC16IS7XX_I2C
+	i2c_del_driver(&sc16is7xx_i2c_uart_driver);
+#endif
+
+#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
+	spi_unregister_driver(&sc16is7xx_spi_uart_driver);
+#endif
+}
+module_exit(sc16is7xx_exit);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jon Ringle <jringle@gridpoint.com>");
 MODULE_AUTHOR("Jon Ringle <jringle@gridpoint.com>");

+ 97 - 61
drivers/tty/serial/serial-tegra.c

@@ -131,8 +131,8 @@ struct tegra_uart_port {
 	struct dma_async_tx_descriptor		*rx_dma_desc;
 	struct dma_async_tx_descriptor		*rx_dma_desc;
 	dma_cookie_t				tx_cookie;
 	dma_cookie_t				tx_cookie;
 	dma_cookie_t				rx_cookie;
 	dma_cookie_t				rx_cookie;
-	int					tx_bytes_requested;
-	int					rx_bytes_requested;
+	unsigned int				tx_bytes_requested;
+	unsigned int				rx_bytes_requested;
 };
 };
 
 
 static void tegra_uart_start_next_tx(struct tegra_uart_port *tup);
 static void tegra_uart_start_next_tx(struct tegra_uart_port *tup);
@@ -234,6 +234,22 @@ static void tegra_uart_break_ctl(struct uart_port *u, int break_ctl)
 	tup->lcr_shadow = lcr;
 	tup->lcr_shadow = lcr;
 }
 }
 
 
+/**
+ * tegra_uart_wait_cycle_time: Wait for N UART clock periods
+ *
+ * @tup:	Tegra serial port data structure.
+ * @cycles:	Number of clock periods to wait.
+ *
+ * Tegra UARTs are clocked at 16X the baud/bit rate and hence the UART
+ * clock speed is 16X the current baud rate.
+ */
+static void tegra_uart_wait_cycle_time(struct tegra_uart_port *tup,
+				       unsigned int cycles)
+{
+	if (tup->current_baud)
+		udelay(DIV_ROUND_UP(cycles * 1000000, tup->current_baud * 16));
+}
+
 /* Wait for a symbol-time. */
 /* Wait for a symbol-time. */
 static void tegra_uart_wait_sym_time(struct tegra_uart_port *tup,
 static void tegra_uart_wait_sym_time(struct tegra_uart_port *tup,
 		unsigned int syms)
 		unsigned int syms)
@@ -263,8 +279,12 @@ static void tegra_uart_fifo_reset(struct tegra_uart_port *tup, u8 fcr_bits)
 	/* Dummy read to ensure the write is posted */
 	/* Dummy read to ensure the write is posted */
 	tegra_uart_read(tup, UART_SCR);
 	tegra_uart_read(tup, UART_SCR);
 
 
-	/* Wait for the flush to propagate. */
-	tegra_uart_wait_sym_time(tup, 1);
+	/*
+	 * For all tegra devices (up to t210), there is a hardware issue that
+	 * requires software to wait for 32 UART clock periods for the flush
+	 * to propagate, otherwise data could be lost.
+	 */
+	tegra_uart_wait_cycle_time(tup, 32);
 }
 }
 
 
 static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud)
 static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud)
@@ -388,9 +408,9 @@ static void tegra_uart_tx_dma_complete(void *args)
 	struct circ_buf *xmit = &tup->uport.state->xmit;
 	struct circ_buf *xmit = &tup->uport.state->xmit;
 	struct dma_tx_state state;
 	struct dma_tx_state state;
 	unsigned long flags;
 	unsigned long flags;
-	int count;
+	unsigned int count;
 
 
-	dmaengine_tx_status(tup->tx_dma_chan, tup->rx_cookie, &state);
+	dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
 	count = tup->tx_bytes_requested - state.residue;
 	count = tup->tx_bytes_requested - state.residue;
 	async_tx_ack(tup->tx_dma_desc);
 	async_tx_ack(tup->tx_dma_desc);
 	spin_lock_irqsave(&tup->uport.lock, flags);
 	spin_lock_irqsave(&tup->uport.lock, flags);
@@ -480,7 +500,7 @@ static void tegra_uart_stop_tx(struct uart_port *u)
 	struct tegra_uart_port *tup = to_tegra_uport(u);
 	struct tegra_uart_port *tup = to_tegra_uport(u);
 	struct circ_buf *xmit = &tup->uport.state->xmit;
 	struct circ_buf *xmit = &tup->uport.state->xmit;
 	struct dma_tx_state state;
 	struct dma_tx_state state;
-	int count;
+	unsigned int count;
 
 
 	if (tup->tx_in_progress != TEGRA_UART_TX_DMA)
 	if (tup->tx_in_progress != TEGRA_UART_TX_DMA)
 		return;
 		return;
@@ -530,10 +550,15 @@ static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
 }
 }
 
 
 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,
-		struct tty_port *tty, int count)
+				      struct tty_port *tty,
+				      unsigned int count)
 {
 {
 	int copied;
 	int copied;
 
 
+	/* If count is zero, then there is no data to be copied */
+	if (!count)
+		return;
+
 	tup->uport.icount.rx += count;
 	tup->uport.icount.rx += count;
 	if (!tty) {
 	if (!tty) {
 		dev_err(tup->uport.dev, "No tty port\n");
 		dev_err(tup->uport.dev, "No tty port\n");
@@ -555,21 +580,30 @@ 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;
-	int count = tup->rx_bytes_requested;
+	unsigned int count = tup->rx_bytes_requested;
 	struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
 	struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
 	struct tty_port *port = &u->state->port;
 	struct tty_port *port = &u->state->port;
 	unsigned long flags;
 	unsigned long flags;
+	struct dma_tx_state state;
+	enum dma_status status;
 
 
-	async_tx_ack(tup->rx_dma_desc);
 	spin_lock_irqsave(&u->lock, flags);
 	spin_lock_irqsave(&u->lock, flags);
 
 
+	status = dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
+
+	if (status == DMA_IN_PROGRESS) {
+		dev_dbg(tup->uport.dev, "RX DMA is in progress\n");
+		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 */
 	/* If we are here, DMA is stopped */
-	if (count)
-		tegra_uart_copy_rx_to_tty(tup, port, count);
+	tegra_uart_copy_rx_to_tty(tup, port, count);
 
 
 	tegra_uart_handle_rx_pio(tup, port);
 	tegra_uart_handle_rx_pio(tup, port);
 	if (tty) {
 	if (tty) {
@@ -584,6 +618,7 @@ static void tegra_uart_rx_dma_complete(void *args)
 	if (tup->rts_active)
 	if (tup->rts_active)
 		set_rts(tup, true);
 		set_rts(tup, true);
 
 
+done:
 	spin_unlock_irqrestore(&u->lock, flags);
 	spin_unlock_irqrestore(&u->lock, flags);
 }
 }
 
 
@@ -594,7 +629,7 @@ static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
 	struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
 	struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
 	struct tty_port *port = &tup->uport.state->port;
 	struct tty_port *port = &tup->uport.state->port;
 	struct uart_port *u = &tup->uport;
 	struct uart_port *u = &tup->uport;
-	int count;
+	unsigned int count;
 
 
 	/* Deactivate flow control to stop sender */
 	/* Deactivate flow control to stop sender */
 	if (tup->rts_active)
 	if (tup->rts_active)
@@ -606,8 +641,7 @@ static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
 	count = tup->rx_bytes_requested - state.residue;
 	count = tup->rx_bytes_requested - state.residue;
 
 
 	/* If we are here, DMA is stopped */
 	/* If we are here, DMA is stopped */
-	if (count)
-		tegra_uart_copy_rx_to_tty(tup, port, count);
+	tegra_uart_copy_rx_to_tty(tup, port, count);
 
 
 	tegra_uart_handle_rx_pio(tup, port);
 	tegra_uart_handle_rx_pio(tup, port);
 	if (tty) {
 	if (tty) {
@@ -865,6 +899,16 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
 	tup->fcr_shadow |= TEGRA_UART_TX_TRIG_16B;
 	tup->fcr_shadow |= TEGRA_UART_TX_TRIG_16B;
 	tegra_uart_write(tup, tup->fcr_shadow, UART_FCR);
 	tegra_uart_write(tup, tup->fcr_shadow, UART_FCR);
 
 
+	/* Dummy read to ensure the write is posted */
+	tegra_uart_read(tup, UART_SCR);
+
+	/*
+	 * For all tegra devices (up to t210), there is a hardware issue that
+	 * requires software to wait for 3 UART clock periods after enabling
+	 * the TX fifo, otherwise data could be lost.
+	 */
+	tegra_uart_wait_cycle_time(tup, 3);
+
 	/*
 	/*
 	 * Initialize the UART with default configuration
 	 * Initialize the UART with default configuration
 	 * (115200, N, 8, 1) so that the receive DMA buffer may be
 	 * (115200, N, 8, 1) so that the receive DMA buffer may be
@@ -905,6 +949,28 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
 	return 0;
 	return 0;
 }
 }
 
 
+static void tegra_uart_dma_channel_free(struct tegra_uart_port *tup,
+		bool dma_to_memory)
+{
+	if (dma_to_memory) {
+		dmaengine_terminate_all(tup->rx_dma_chan);
+		dma_release_channel(tup->rx_dma_chan);
+		dma_free_coherent(tup->uport.dev, TEGRA_UART_RX_DMA_BUFFER_SIZE,
+				tup->rx_dma_buf_virt, tup->rx_dma_buf_phys);
+		tup->rx_dma_chan = NULL;
+		tup->rx_dma_buf_phys = 0;
+		tup->rx_dma_buf_virt = NULL;
+	} else {
+		dmaengine_terminate_all(tup->tx_dma_chan);
+		dma_release_channel(tup->tx_dma_chan);
+		dma_unmap_single(tup->uport.dev, tup->tx_dma_buf_phys,
+			UART_XMIT_SIZE, DMA_TO_DEVICE);
+		tup->tx_dma_chan = NULL;
+		tup->tx_dma_buf_phys = 0;
+		tup->tx_dma_buf_virt = NULL;
+	}
+}
+
 static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
 static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
 			bool dma_to_memory)
 			bool dma_to_memory)
 {
 {
@@ -933,67 +999,39 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
 			dma_release_channel(dma_chan);
 			dma_release_channel(dma_chan);
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
+		dma_sconfig.src_addr = tup->uport.mapbase;
+		dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		dma_sconfig.src_maxburst = 4;
+		tup->rx_dma_chan = dma_chan;
+		tup->rx_dma_buf_virt = dma_buf;
+		tup->rx_dma_buf_phys = dma_phys;
 	} else {
 	} else {
 		dma_phys = dma_map_single(tup->uport.dev,
 		dma_phys = dma_map_single(tup->uport.dev,
 			tup->uport.state->xmit.buf, UART_XMIT_SIZE,
 			tup->uport.state->xmit.buf, UART_XMIT_SIZE,
 			DMA_TO_DEVICE);
 			DMA_TO_DEVICE);
+		if (dma_mapping_error(tup->uport.dev, dma_phys)) {
+			dev_err(tup->uport.dev, "dma_map_single tx failed\n");
+			dma_release_channel(dma_chan);
+			return -ENOMEM;
+		}
 		dma_buf = tup->uport.state->xmit.buf;
 		dma_buf = tup->uport.state->xmit.buf;
-	}
-
-	if (dma_to_memory) {
-		dma_sconfig.src_addr = tup->uport.mapbase;
-		dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-		dma_sconfig.src_maxburst = 4;
-	} else {
 		dma_sconfig.dst_addr = tup->uport.mapbase;
 		dma_sconfig.dst_addr = tup->uport.mapbase;
 		dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
 		dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
 		dma_sconfig.dst_maxburst = 16;
 		dma_sconfig.dst_maxburst = 16;
+		tup->tx_dma_chan = dma_chan;
+		tup->tx_dma_buf_virt = dma_buf;
+		tup->tx_dma_buf_phys = dma_phys;
 	}
 	}
 
 
 	ret = dmaengine_slave_config(dma_chan, &dma_sconfig);
 	ret = dmaengine_slave_config(dma_chan, &dma_sconfig);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(tup->uport.dev,
 		dev_err(tup->uport.dev,
 			"Dma slave config failed, err = %d\n", ret);
 			"Dma slave config failed, err = %d\n", ret);
-		goto scrub;
+		tegra_uart_dma_channel_free(tup, dma_to_memory);
+		return ret;
 	}
 	}
 
 
-	if (dma_to_memory) {
-		tup->rx_dma_chan = dma_chan;
-		tup->rx_dma_buf_virt = dma_buf;
-		tup->rx_dma_buf_phys = dma_phys;
-	} else {
-		tup->tx_dma_chan = dma_chan;
-		tup->tx_dma_buf_virt = dma_buf;
-		tup->tx_dma_buf_phys = dma_phys;
-	}
 	return 0;
 	return 0;
-
-scrub:
-	dma_release_channel(dma_chan);
-	return ret;
-}
-
-static void tegra_uart_dma_channel_free(struct tegra_uart_port *tup,
-		bool dma_to_memory)
-{
-	struct dma_chan *dma_chan;
-
-	if (dma_to_memory) {
-		dma_free_coherent(tup->uport.dev, TEGRA_UART_RX_DMA_BUFFER_SIZE,
-				tup->rx_dma_buf_virt, tup->rx_dma_buf_phys);
-		dma_chan = tup->rx_dma_chan;
-		tup->rx_dma_chan = NULL;
-		tup->rx_dma_buf_phys = 0;
-		tup->rx_dma_buf_virt = NULL;
-	} else {
-		dma_unmap_single(tup->uport.dev, tup->tx_dma_buf_phys,
-			UART_XMIT_SIZE, DMA_TO_DEVICE);
-		dma_chan = tup->tx_dma_chan;
-		tup->tx_dma_chan = NULL;
-		tup->tx_dma_buf_phys = 0;
-		tup->tx_dma_buf_virt = NULL;
-	}
-	dma_release_channel(dma_chan);
 }
 }
 
 
 static int tegra_uart_startup(struct uart_port *u)
 static int tegra_uart_startup(struct uart_port *u)
@@ -1060,8 +1098,6 @@ static void tegra_uart_shutdown(struct uart_port *u)
 	tegra_uart_dma_channel_free(tup, true);
 	tegra_uart_dma_channel_free(tup, true);
 	tegra_uart_dma_channel_free(tup, false);
 	tegra_uart_dma_channel_free(tup, false);
 	free_irq(u->irq, tup);
 	free_irq(u->irq, tup);
-
-	tegra_uart_flush_buffer(u);
 }
 }
 
 
 static void tegra_uart_enable_ms(struct uart_port *u)
 static void tegra_uart_enable_ms(struct uart_port *u)

+ 22 - 10
drivers/tty/serial/serial_core.c

@@ -335,18 +335,29 @@ unsigned int
 uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
 uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
 		   struct ktermios *old, unsigned int min, unsigned int max)
 		   struct ktermios *old, unsigned int min, unsigned int max)
 {
 {
-	unsigned int try, baud, altbaud = 38400;
+	unsigned int try;
+	unsigned int baud;
+	unsigned int altbaud;
 	int hung_up = 0;
 	int hung_up = 0;
 	upf_t flags = port->flags & UPF_SPD_MASK;
 	upf_t flags = port->flags & UPF_SPD_MASK;
 
 
-	if (flags == UPF_SPD_HI)
+	switch (flags) {
+	case UPF_SPD_HI:
 		altbaud = 57600;
 		altbaud = 57600;
-	else if (flags == UPF_SPD_VHI)
+		break;
+	case UPF_SPD_VHI:
 		altbaud = 115200;
 		altbaud = 115200;
-	else if (flags == UPF_SPD_SHI)
+		break;
+	case UPF_SPD_SHI:
 		altbaud = 230400;
 		altbaud = 230400;
-	else if (flags == UPF_SPD_WARP)
+		break;
+	case UPF_SPD_WARP:
 		altbaud = 460800;
 		altbaud = 460800;
+		break;
+	default:
+		altbaud = 38400;
+		break;
+	}
 
 
 	for (try = 0; try < 2; try++) {
 	for (try = 0; try < 2; try++) {
 		baud = tty_termios_baud_rate(termios);
 		baud = tty_termios_baud_rate(termios);
@@ -894,12 +905,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
 			 * need to rate-limit; it's CAP_SYS_ADMIN only.
 			 * need to rate-limit; it's CAP_SYS_ADMIN only.
 			 */
 			 */
 			if (uport->flags & UPF_SPD_MASK) {
 			if (uport->flags & UPF_SPD_MASK) {
-				char buf[64];
-
 				dev_notice(uport->dev,
 				dev_notice(uport->dev,
 				       "%s sets custom speed on %s. This is deprecated.\n",
 				       "%s sets custom speed on %s. This is deprecated.\n",
 				      current->comm,
 				      current->comm,
-				      tty_name(port->tty, buf));
+				      tty_name(port->tty));
 			}
 			}
 			uart_change_speed(tty, state, NULL);
 			uart_change_speed(tty, state, NULL);
 		}
 		}
@@ -1816,8 +1825,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,<addr>,<options>
- *	   console=<name>,io|mmio|mmio32,<addr>,<options>
+ *	   earlycon=<name>,io|mmio|mmio32|mmio32be,<addr>,<options>
+ *	   console=<name>,io|mmio|mmio32|mmio32be,<addr>,<options>
  *
  *
  *	The optional form
  *	The optional form
  *	   earlycon=<name>,0x<addr>,<options>
  *	   earlycon=<name>,0x<addr>,<options>
@@ -1835,6 +1844,9 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
 	} else if (strncmp(p, "mmio32,", 7) == 0) {
 	} else if (strncmp(p, "mmio32,", 7) == 0) {
 		*iotype = UPIO_MEM32;
 		*iotype = UPIO_MEM32;
 		p += 7;
 		p += 7;
+	} else if (strncmp(p, "mmio32be,", 9) == 0) {
+		*iotype = UPIO_MEM32BE;
+		p += 9;
 	} else if (strncmp(p, "io,", 3) == 0) {
 	} else if (strncmp(p, "io,", 3) == 0) {
 		*iotype = UPIO_PORT;
 		*iotype = UPIO_PORT;
 		p += 3;
 		p += 3;

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

@@ -328,7 +328,7 @@ static int ks8695uart_startup(struct uart_port *port)
 {
 {
 	int retval;
 	int retval;
 
 
-	set_irq_flags(KS8695_IRQ_UART_TX, IRQF_VALID | IRQF_NOAUTOEN);
+	irq_modify_status(KS8695_IRQ_UART_TX, IRQ_NOREQUEST, IRQ_NOAUTOEN);
 	tx_enable(port, 0);
 	tx_enable(port, 0);
 	rx_enable(port, 1);
 	rx_enable(port, 1);
 	ms_enable(port, 1);
 	ms_enable(port, 1);

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

@@ -49,8 +49,7 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
 	unsigned int count = 0;
 	unsigned int count = 0;
 
 
 	for (i = 0; i < UART_GPIO_MAX; i++)
 	for (i = 0; i < UART_GPIO_MAX; i++)
-		if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
-		    mctrl_gpios_desc[i].dir_out) {
+		if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
 			desc_array[count] = gpios->gpio[i];
 			desc_array[count] = gpios->gpio[i];
 			value_array[count] = !!(mctrl & mctrl_gpios_desc[i].mctrl);
 			value_array[count] = !!(mctrl & mctrl_gpios_desc[i].mctrl);
 			count++;
 			count++;
@@ -118,7 +117,7 @@ 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 (!IS_ERR_OR_NULL(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);
 }
 }

+ 51 - 45
drivers/tty/serial/sh-sci.c

@@ -81,7 +81,8 @@ struct sci_port {
 
 
 	/* Platform configuration */
 	/* Platform configuration */
 	struct plat_sci_port	*cfg;
 	struct plat_sci_port	*cfg;
-	int			overrun_bit;
+	unsigned int		overrun_reg;
+	unsigned int		overrun_mask;
 	unsigned int		error_mask;
 	unsigned int		error_mask;
 	unsigned int		sampling_rate;
 	unsigned int		sampling_rate;
 	resource_size_t		reg_size;
 	resource_size_t		reg_size;
@@ -168,6 +169,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= sci_reg_invalid,
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -188,6 +191,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= sci_reg_invalid,
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -207,6 +212,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= sci_reg_invalid,
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= { 0x30, 16 },
+		[SCPDR]		= { 0x34, 16 },
 	},
 	},
 
 
 	/*
 	/*
@@ -226,6 +233,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= sci_reg_invalid,
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= { 0x30, 16 },
+		[SCPDR]		= { 0x34, 16 },
 	},
 	},
 
 
 	/*
 	/*
@@ -246,6 +255,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= { 0x20, 16 },
 		[SCSPTR]	= { 0x20, 16 },
 		[SCLSR]		= { 0x24, 16 },
 		[SCLSR]		= { 0x24, 16 },
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -265,6 +276,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= sci_reg_invalid,
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -284,6 +297,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= { 0x20, 16 },
 		[SCSPTR]	= { 0x20, 16 },
 		[SCLSR]		= { 0x24, 16 },
 		[SCLSR]		= { 0x24, 16 },
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -303,6 +318,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= { 0x20, 16 },
 		[SCSPTR]	= { 0x20, 16 },
 		[SCLSR]		= { 0x24, 16 },
 		[SCLSR]		= { 0x24, 16 },
 		[HSSRR]		= { 0x40, 16 },
 		[HSSRR]		= { 0x40, 16 },
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -323,6 +340,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= sci_reg_invalid,
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= { 0x24, 16 },
 		[SCLSR]		= { 0x24, 16 },
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -343,6 +362,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= { 0x24, 16 },
 		[SCSPTR]	= { 0x24, 16 },
 		[SCLSR]		= { 0x28, 16 },
 		[SCLSR]		= { 0x28, 16 },
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 
 
 	/*
 	/*
@@ -363,6 +384,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCSPTR]	= sci_reg_invalid,
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
 		[HSSRR]		= sci_reg_invalid,
+		[SCPCR]		= sci_reg_invalid,
+		[SCPDR]		= sci_reg_invalid,
 	},
 	},
 };
 };
 
 
@@ -781,7 +804,7 @@ static int sci_handle_errors(struct uart_port *port)
 	struct sci_port *s = to_sci_port(port);
 	struct sci_port *s = to_sci_port(port);
 
 
 	/* Handle overruns */
 	/* Handle overruns */
-	if (status & (1 << s->overrun_bit)) {
+	if (status & s->overrun_mask) {
 		port->icount.overrun++;
 		port->icount.overrun++;
 
 
 		/* overrun error */
 		/* overrun error */
@@ -844,32 +867,17 @@ 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;
 	struct plat_sci_reg *reg;
-	int copied = 0, offset;
-	u16 status, bit;
-
-	switch (port->type) {
-	case PORT_SCIF:
-	case PORT_HSCIF:
-		offset = SCLSR;
-		break;
-	case PORT_SCIFA:
-	case PORT_SCIFB:
-		offset = SCxSR;
-		break;
-	default:
-		return 0;
-	}
+	int copied = 0;
+	u16 status;
 
 
-	reg = sci_getreg(port, offset);
+	reg = sci_getreg(port, s->overrun_reg);
 	if (!reg->size)
 	if (!reg->size)
 		return 0;
 		return 0;
 
 
-	status = serial_port_in(port, offset);
-	bit = 1 << s->overrun_bit;
-
-	if (status & bit) {
-		status &= ~bit;
-		serial_port_out(port, offset, status);
+	status = serial_port_in(port, s->overrun_reg);
+	if (status & s->overrun_mask) {
+		status &= ~s->overrun_mask;
+		serial_port_out(port, s->overrun_reg, status);
 
 
 		port->icount.overrun++;
 		port->icount.overrun++;
 
 
@@ -1021,15 +1029,11 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 
 
 	ssr_status = serial_port_in(port, SCxSR);
 	ssr_status = serial_port_in(port, SCxSR);
 	scr_status = serial_port_in(port, SCSCR);
 	scr_status = serial_port_in(port, SCSCR);
-	switch (port->type) {
-	case PORT_SCIF:
-	case PORT_HSCIF:
-		orer_status = serial_port_in(port, SCLSR);
-		break;
-	case PORT_SCIFA:
-	case PORT_SCIFB:
+	if (s->overrun_reg == SCxSR)
 		orer_status = ssr_status;
 		orer_status = ssr_status;
-		break;
+	else {
+		if (sci_getreg(port, s->overrun_reg)->size)
+			orer_status = serial_port_in(port, s->overrun_reg);
 	}
 	}
 
 
 	err_enabled = scr_status & port_rx_irq_mask(port);
 	err_enabled = scr_status & port_rx_irq_mask(port);
@@ -1059,7 +1063,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 		ret = sci_br_interrupt(irq, ptr);
 		ret = sci_br_interrupt(irq, ptr);
 
 
 	/* Overrun Interrupt */
 	/* Overrun Interrupt */
-	if (orer_status & (1 << s->overrun_bit))
+	if (orer_status & s->overrun_mask)
 		sci_handle_fifo_overrun(port);
 		sci_handle_fifo_overrun(port);
 
 
 	return ret;
 	return ret;
@@ -2226,32 +2230,38 @@ static int sci_init_single(struct platform_device *dev,
 	switch (p->type) {
 	switch (p->type) {
 	case PORT_SCIFB:
 	case PORT_SCIFB:
 		port->fifosize = 256;
 		port->fifosize = 256;
-		sci_port->overrun_bit = 9;
+		sci_port->overrun_reg = SCxSR;
+		sci_port->overrun_mask = SCIFA_ORER;
 		sampling_rate = 16;
 		sampling_rate = 16;
 		break;
 		break;
 	case PORT_HSCIF:
 	case PORT_HSCIF:
 		port->fifosize = 128;
 		port->fifosize = 128;
 		sampling_rate = 0;
 		sampling_rate = 0;
-		sci_port->overrun_bit = 0;
+		sci_port->overrun_reg = SCLSR;
+		sci_port->overrun_mask = SCLSR_ORER;
 		break;
 		break;
 	case PORT_SCIFA:
 	case PORT_SCIFA:
 		port->fifosize = 64;
 		port->fifosize = 64;
-		sci_port->overrun_bit = 9;
+		sci_port->overrun_reg = SCxSR;
+		sci_port->overrun_mask = SCIFA_ORER;
 		sampling_rate = 16;
 		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_bit = 9;
+			sci_port->overrun_reg = SCxSR;
+			sci_port->overrun_mask = SCIFA_ORER;
 			sampling_rate = 16;
 			sampling_rate = 16;
 		} else {
 		} else {
-			sci_port->overrun_bit = 0;
+			sci_port->overrun_reg = SCLSR;
+			sci_port->overrun_mask = SCLSR_ORER;
 			sampling_rate = 32;
 			sampling_rate = 32;
 		}
 		}
 		break;
 		break;
 	default:
 	default:
 		port->fifosize = 1;
 		port->fifosize = 1;
-		sci_port->overrun_bit = 5;
+		sci_port->overrun_reg = SCxSR;
+		sci_port->overrun_mask = SCI_ORER;
 		sampling_rate = 32;
 		sampling_rate = 32;
 		break;
 		break;
 	}
 	}
@@ -2296,16 +2306,12 @@ static int sci_init_single(struct platform_device *dev,
 	sci_port->error_mask = (p->type == PORT_SCI) ?
 	sci_port->error_mask = (p->type == PORT_SCI) ?
 			SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK;
 			SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK;
 
 
-	/*
-	 * Establish sensible defaults for the overrun detection, unless
-	 * the part has explicitly disabled support for it.
-	 */
-
 	/*
 	/*
 	 * Make the error mask inclusive of overrun detection, if
 	 * Make the error mask inclusive of overrun detection, if
 	 * supported.
 	 * supported.
 	 */
 	 */
-	sci_port->error_mask |= 1 << sci_port->overrun_bit;
+	if (sci_port->overrun_reg == SCxSR)
+		sci_port->error_mask |= 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;

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

@@ -1,7 +1,115 @@
+#include <linux/bitops.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 
 
+#define SCI_MAJOR		204
+#define SCI_MINOR_START		8
+
+
+/*
+ * SCI register subset common for all port types.
+ * Not all registers will exist on all parts.
+ */
+enum {
+	SCSMR,				/* Serial Mode Register */
+	SCBRR,				/* Bit Rate Register */
+	SCSCR,				/* Serial Control Register */
+	SCxSR,				/* Serial Status Register */
+	SCFCR,				/* FIFO Control Register */
+	SCFDR,				/* FIFO Data Count Register */
+	SCxTDR,				/* Transmit (FIFO) Data Register */
+	SCxRDR,				/* Receive (FIFO) Data Register */
+	SCLSR,				/* Line Status Register */
+	SCTFDR,				/* Transmit FIFO Data Count Register */
+	SCRFDR,				/* Receive FIFO Data Count Register */
+	SCSPTR,				/* Serial Port Register */
+	HSSRR,				/* Sampling Rate Register */
+	SCPCR,				/* Serial Port Control Register */
+	SCPDR,				/* Serial Port Data Register */
+
+	SCIx_NR_REGS,
+};
+
+
+/* SCSMR (Serial Mode Register) */
+#define SCSMR_CHR	BIT(6)	/* 7-bit Character Length */
+#define SCSMR_PE	BIT(5)	/* Parity Enable */
+#define SCSMR_ODD	BIT(4)	/* Odd Parity */
+#define SCSMR_STOP	BIT(3)	/* Stop Bit Length */
+#define SCSMR_CKS	0x0003	/* Clock Select */
+
+/* Serial Control Register, SCIFA/SCIFB only bits */
+#define SCSCR_TDRQE	BIT(15)	/* Tx Data Transfer Request Enable */
+#define SCSCR_RDRQE	BIT(14)	/* Rx Data Transfer Request Enable */
+
+/* SCxSR (Serial Status Register) on SCI */
+#define SCI_TDRE	BIT(7)	/* Transmit Data Register Empty */
+#define SCI_RDRF	BIT(6)	/* Receive Data Register Full */
+#define SCI_ORER	BIT(5)	/* Overrun Error */
+#define SCI_FER		BIT(4)	/* Framing Error */
+#define SCI_PER		BIT(3)	/* Parity Error */
+#define SCI_TEND	BIT(2)	/* Transmit End */
+#define SCI_RESERVED	0x03	/* All reserved bits */
+
+#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)
+
+/* SCxSR (Serial Status Register) on SCIF, SCIFA, SCIFB, HSCIF */
+#define SCIF_ER		BIT(7)	/* Receive Error */
+#define SCIF_TEND	BIT(6)	/* Transmission End */
+#define SCIF_TDFE	BIT(5)	/* Transmit FIFO Data Empty */
+#define SCIF_BRK	BIT(4)	/* Break Detect */
+#define SCIF_FER	BIT(3)	/* Framing Error */
+#define SCIF_PER	BIT(2)	/* Parity Error */
+#define SCIF_RDF	BIT(1)	/* Receive FIFO Data Full */
+#define SCIF_DR		BIT(0)	/* Receive Data Ready */
+/* SCIF only (optional) */
+#define SCIF_PERC	0xf000	/* Number of Parity Errors */
+#define SCIF_FERC	0x0f00	/* Number of Framing Errors */
+/*SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 only */
+#define SCIFA_ORER	BIT(9)	/* Overrun Error */
+
+#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)
+
+/* SCFCR (FIFO Control Register) */
+#define SCFCR_MCE	BIT(3)	/* Modem Control Enable */
+#define SCFCR_TFRST	BIT(2)	/* Transmit FIFO Data Register Reset */
+#define SCFCR_RFRST	BIT(1)	/* Receive FIFO Data Register Reset */
+#define SCFCR_LOOP	BIT(0)	/* Loopback Test */
+
+/* SCLSR (Line Status Register) on (H)SCIF */
+#define SCLSR_ORER	BIT(0)	/* Overrun Error */
+
+/* SCSPTR (Serial Port Register), optional */
+#define SCSPTR_RTSIO	BIT(7)	/* Serial Port RTS Pin Input/Output */
+#define SCSPTR_RTSDT	BIT(6)	/* Serial Port RTS Pin Data */
+#define SCSPTR_CTSIO	BIT(5)	/* Serial Port CTS Pin Input/Output */
+#define SCSPTR_CTSDT	BIT(4)	/* Serial Port CTS Pin Data */
+#define SCSPTR_SPB2IO	BIT(1)	/* Serial Port Break Input/Output */
+#define SCSPTR_SPB2DT	BIT(0)	/* Serial Port Break Data */
+
+/* HSSRR HSCIF */
+#define HSCIF_SRE	BIT(15)	/* Sampling Rate Register Enable */
+
+/* SCPCR (Serial Port Control Register), SCIFA/SCIFB only */
+#define SCPCR_RTSC	BIT(4)	/* Serial Port RTS Pin / Output Pin */
+#define SCPCR_CTSC	BIT(3)	/* Serial Port CTS Pin / Input Pin */
+
+/* SCPDR (Serial Port Data Register), SCIFA/SCIFB only */
+#define SCPDR_RTSD	BIT(4)	/* Serial Port RTS Output Pin Data */
+#define SCPDR_CTSD	BIT(3)	/* Serial Port CTS Input Pin Data */
+
+
 #define SCxSR_TEND(port)	(((port)->type == PORT_SCI) ? SCI_TEND   : SCIF_TEND)
 #define SCxSR_TEND(port)	(((port)->type == PORT_SCI) ? SCI_TEND   : SCIF_TEND)
 #define SCxSR_RDxF(port)	(((port)->type == PORT_SCI) ? SCI_RDRF   : SCIF_RDF)
 #define SCxSR_RDxF(port)	(((port)->type == PORT_SCI) ? SCI_RDRF   : SCIF_RDF)
 #define SCxSR_TDxE(port)	(((port)->type == PORT_SCI) ? SCI_TDRE   : SCIF_TDFE)
 #define SCxSR_TDxE(port)	(((port)->type == PORT_SCI) ? SCI_TDRE   : SCIF_TDFE)
@@ -15,24 +123,24 @@
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
     defined(CONFIG_ARCH_SH73A0) || \
     defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_SH7372) || \
     defined(CONFIG_ARCH_R8A7740)
     defined(CONFIG_ARCH_R8A7740)
 
 
-# define SCxSR_RDxF_CLEAR(port)	 (serial_port_in(port, SCxSR) & 0xfffc)
-# define SCxSR_ERROR_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfd73)
-# define SCxSR_TDxE_CLEAR(port)	 (serial_port_in(port, SCxSR) & 0xffdf)
-# define SCxSR_BREAK_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffe3)
+# 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
 #else
-# define SCxSR_RDxF_CLEAR(port)	 (((port)->type == PORT_SCI) ? 0xbc : 0x00fc)
-# define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073)
-# define SCxSR_TDxE_CLEAR(port)  (((port)->type == PORT_SCI) ? 0x78 : 0x00df)
-# define SCxSR_BREAK_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x00e3)
+# 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
 #endif
 
 
-/* SCFCR */
-#define SCFCR_RFRST 0x0002
-#define SCFCR_TFRST 0x0004
-#define SCFCR_MCE   0x0008
-
-#define SCI_MAJOR		204
-#define SCI_MINOR_START		8

+ 281 - 341
drivers/tty/serial/sirfsoc_uart.c

@@ -36,8 +36,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count);
 static struct uart_driver sirfsoc_uart_drv;
 static struct uart_driver sirfsoc_uart_drv;
 
 
 static void sirfsoc_uart_tx_dma_complete_callback(void *param);
 static void sirfsoc_uart_tx_dma_complete_callback(void *param);
-static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port);
-static void sirfsoc_uart_rx_dma_complete_callback(void *param);
 static const struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = {
 static const struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = {
 	{4000000, 2359296},
 	{4000000, 2359296},
 	{3500000, 1310721},
 	{3500000, 1310721},
@@ -59,50 +57,7 @@ static const struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = {
 	{9600, 1114979},
 	{9600, 1114979},
 };
 };
 
 
-static struct sirfsoc_uart_port sirfsoc_uart_ports[SIRFSOC_UART_NR] = {
-	[0] = {
-		.port = {
-			.iotype		= UPIO_MEM,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 0,
-		},
-	},
-	[1] = {
-		.port = {
-			.iotype		= UPIO_MEM,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 1,
-		},
-	},
-	[2] = {
-		.port = {
-			.iotype		= UPIO_MEM,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 2,
-		},
-	},
-	[3] = {
-		.port = {
-			.iotype		= UPIO_MEM,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 3,
-		},
-	},
-	[4] = {
-		.port = {
-			.iotype		= UPIO_MEM,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 4,
-		},
-	},
-	[5] = {
-		.port = {
-			.iotype		= UPIO_MEM,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 5,
-		},
-	},
-};
+static struct sirfsoc_uart_port *sirf_ports[SIRFSOC_UART_NR];
 
 
 static inline struct sirfsoc_uart_port *to_sirfport(struct uart_port *port)
 static inline struct sirfsoc_uart_port *to_sirfport(struct uart_port *port)
 {
 {
@@ -116,8 +71,7 @@ static inline unsigned int sirfsoc_uart_tx_empty(struct uart_port *port)
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
 	struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
 	reg = rd_regl(port, ureg->sirfsoc_tx_fifo_status);
 	reg = rd_regl(port, ureg->sirfsoc_tx_fifo_status);
-
-	return (reg & ufifo_st->ff_empty(port->line)) ? TIOCSER_TEMT : 0;
+	return (reg & ufifo_st->ff_empty(port)) ? TIOCSER_TEMT : 0;
 }
 }
 
 
 static unsigned int sirfsoc_uart_get_mctrl(struct uart_port *port)
 static unsigned int sirfsoc_uart_get_mctrl(struct uart_port *port)
@@ -152,6 +106,26 @@ static void sirfsoc_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	unsigned int val = assert ? SIRFUART_AFC_CTRL_RX_THD : 0x0;
 	unsigned int val = assert ? SIRFUART_AFC_CTRL_RX_THD : 0x0;
 	unsigned int current_val;
 	unsigned int current_val;
 
 
+	if (mctrl & TIOCM_LOOP) {
+		if (sirfport->uart_reg->uart_type == SIRF_REAL_UART)
+			wr_regl(port, ureg->sirfsoc_line_ctrl,
+				rd_regl(port, ureg->sirfsoc_line_ctrl) |
+				SIRFUART_LOOP_BACK);
+		else
+			wr_regl(port, ureg->sirfsoc_mode1,
+				rd_regl(port, ureg->sirfsoc_mode1) |
+				SIRFSOC_USP_LOOP_BACK_CTRL);
+	} else {
+		if (sirfport->uart_reg->uart_type == SIRF_REAL_UART)
+			wr_regl(port, ureg->sirfsoc_line_ctrl,
+				rd_regl(port, ureg->sirfsoc_line_ctrl) &
+				~SIRFUART_LOOP_BACK);
+		else
+			wr_regl(port, ureg->sirfsoc_mode1,
+				rd_regl(port, ureg->sirfsoc_mode1) &
+				~SIRFSOC_USP_LOOP_BACK_CTRL);
+	}
+
 	if (!sirfport->hw_flow_ctrl || !sirfport->ms_enabled)
 	if (!sirfport->hw_flow_ctrl || !sirfport->ms_enabled)
 		return;
 		return;
 	if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
 	if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
@@ -182,16 +156,19 @@ static void sirfsoc_uart_stop_tx(struct uart_port *port)
 				rd_regl(port, ureg->sirfsoc_int_en_reg) &
 				rd_regl(port, ureg->sirfsoc_int_en_reg) &
 				~uint_en->sirfsoc_txfifo_empty_en);
 				~uint_en->sirfsoc_txfifo_empty_en);
 			else
 			else
-				wr_regl(port, SIRFUART_INT_EN_CLR,
+				wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
 				uint_en->sirfsoc_txfifo_empty_en);
 				uint_en->sirfsoc_txfifo_empty_en);
 		}
 		}
 	} else {
 	} else {
+		if (sirfport->uart_reg->uart_type == SIRF_USP_UART)
+			wr_regl(port, ureg->sirfsoc_tx_rx_en, rd_regl(port,
+				ureg->sirfsoc_tx_rx_en) & ~SIRFUART_TX_EN);
 		if (!sirfport->is_atlas7)
 		if (!sirfport->is_atlas7)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 				rd_regl(port, ureg->sirfsoc_int_en_reg) &
 				rd_regl(port, ureg->sirfsoc_int_en_reg) &
 				~uint_en->sirfsoc_txfifo_empty_en);
 				~uint_en->sirfsoc_txfifo_empty_en);
 		else
 		else
-			wr_regl(port, SIRFUART_INT_EN_CLR,
+			wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
 				uint_en->sirfsoc_txfifo_empty_en);
 				uint_en->sirfsoc_txfifo_empty_en);
 	}
 	}
 }
 }
@@ -222,7 +199,7 @@ static void sirfsoc_uart_tx_with_dma(struct sirfsoc_uart_port *sirfport)
 				rd_regl(port, ureg->sirfsoc_int_en_reg)&
 				rd_regl(port, ureg->sirfsoc_int_en_reg)&
 				~(uint_en->sirfsoc_txfifo_empty_en));
 				~(uint_en->sirfsoc_txfifo_empty_en));
 	else
 	else
-		wr_regl(port, SIRFUART_INT_EN_CLR,
+		wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
 				uint_en->sirfsoc_txfifo_empty_en);
 				uint_en->sirfsoc_txfifo_empty_en);
 	/*
 	/*
 	 * DMA requires buffer address and buffer length are both aligned with
 	 * DMA requires buffer address and buffer length are both aligned with
@@ -290,8 +267,11 @@ static void sirfsoc_uart_start_tx(struct uart_port *port)
 	if (sirfport->tx_dma_chan)
 	if (sirfport->tx_dma_chan)
 		sirfsoc_uart_tx_with_dma(sirfport);
 		sirfsoc_uart_tx_with_dma(sirfport);
 	else {
 	else {
-		sirfsoc_uart_pio_tx_chars(sirfport,
-			SIRFSOC_UART_IO_TX_REASONABLE_CNT);
+		if (sirfport->uart_reg->uart_type == SIRF_USP_UART)
+			wr_regl(port, ureg->sirfsoc_tx_rx_en, rd_regl(port,
+				ureg->sirfsoc_tx_rx_en) | SIRFUART_TX_EN);
+		wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP);
+		sirfsoc_uart_pio_tx_chars(sirfport, port->fifosize);
 		wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
 		wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
 		if (!sirfport->is_atlas7)
 		if (!sirfport->is_atlas7)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
@@ -314,21 +294,25 @@ static void sirfsoc_uart_stop_rx(struct uart_port *port)
 		if (!sirfport->is_atlas7)
 		if (!sirfport->is_atlas7)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 				rd_regl(port, ureg->sirfsoc_int_en_reg) &
 				rd_regl(port, ureg->sirfsoc_int_en_reg) &
-				~(SIRFUART_RX_DMA_INT_EN(port, uint_en) |
+				~(SIRFUART_RX_DMA_INT_EN(uint_en,
+				sirfport->uart_reg->uart_type) |
 				uint_en->sirfsoc_rx_done_en));
 				uint_en->sirfsoc_rx_done_en));
 		else
 		else
-			wr_regl(port, SIRFUART_INT_EN_CLR,
-					SIRFUART_RX_DMA_INT_EN(port, uint_en)|
-					uint_en->sirfsoc_rx_done_en);
+			wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
+				SIRFUART_RX_DMA_INT_EN(uint_en,
+				sirfport->uart_reg->uart_type)|
+				uint_en->sirfsoc_rx_done_en);
 		dmaengine_terminate_all(sirfport->rx_dma_chan);
 		dmaengine_terminate_all(sirfport->rx_dma_chan);
 	} else {
 	} else {
 		if (!sirfport->is_atlas7)
 		if (!sirfport->is_atlas7)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 				rd_regl(port, ureg->sirfsoc_int_en_reg)&
 				rd_regl(port, ureg->sirfsoc_int_en_reg)&
-				~(SIRFUART_RX_IO_INT_EN(port, uint_en)));
+				~(SIRFUART_RX_IO_INT_EN(uint_en,
+				sirfport->uart_reg->uart_type)));
 		else
 		else
-			wr_regl(port, SIRFUART_INT_EN_CLR,
-					SIRFUART_RX_IO_INT_EN(port, uint_en));
+			wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
+				SIRFUART_RX_IO_INT_EN(uint_en,
+				sirfport->uart_reg->uart_type));
 	}
 	}
 }
 }
 
 
@@ -349,7 +333,7 @@ static void sirfsoc_uart_disable_ms(struct uart_port *port)
 					rd_regl(port, ureg->sirfsoc_int_en_reg)&
 					rd_regl(port, ureg->sirfsoc_int_en_reg)&
 					~uint_en->sirfsoc_cts_en);
 					~uint_en->sirfsoc_cts_en);
 		else
 		else
-			wr_regl(port, SIRFUART_INT_EN_CLR,
+			wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
 					uint_en->sirfsoc_cts_en);
 					uint_en->sirfsoc_cts_en);
 	} else
 	} else
 		disable_irq(gpio_to_irq(sirfport->cts_gpio));
 		disable_irq(gpio_to_irq(sirfport->cts_gpio));
@@ -379,7 +363,8 @@ static void sirfsoc_uart_enable_ms(struct uart_port *port)
 	if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
 	if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
 		wr_regl(port, ureg->sirfsoc_afc_ctrl,
 		wr_regl(port, ureg->sirfsoc_afc_ctrl,
 				rd_regl(port, ureg->sirfsoc_afc_ctrl) |
 				rd_regl(port, ureg->sirfsoc_afc_ctrl) |
-				SIRFUART_AFC_TX_EN | SIRFUART_AFC_RX_EN);
+				SIRFUART_AFC_TX_EN | SIRFUART_AFC_RX_EN |
+				SIRFUART_AFC_CTRL_RX_THD);
 		if (!sirfport->is_atlas7)
 		if (!sirfport->is_atlas7)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 					rd_regl(port, ureg->sirfsoc_int_en_reg)
 					rd_regl(port, ureg->sirfsoc_int_en_reg)
@@ -417,7 +402,7 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count)
 	if (!tty)
 	if (!tty)
 		return -ENODEV;
 		return -ENODEV;
 	while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
 	while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
-					ufifo_st->ff_empty(port->line))) {
+					ufifo_st->ff_empty(port))) {
 		ch = rd_regl(port, ureg->sirfsoc_rx_fifo_data) |
 		ch = rd_regl(port, ureg->sirfsoc_rx_fifo_data) |
 			SIRFUART_DUMMY_READ;
 			SIRFUART_DUMMY_READ;
 		if (unlikely(uart_handle_sysrq_char(port, ch)))
 		if (unlikely(uart_handle_sysrq_char(port, ch)))
@@ -444,7 +429,7 @@ sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count)
 	unsigned int num_tx = 0;
 	unsigned int num_tx = 0;
 	while (!uart_circ_empty(xmit) &&
 	while (!uart_circ_empty(xmit) &&
 		!(rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
 		!(rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
-					ufifo_st->ff_full(port->line)) &&
+					ufifo_st->ff_full(port)) &&
 		count--) {
 		count--) {
 		wr_regl(port, ureg->sirfsoc_tx_fifo_data,
 		wr_regl(port, ureg->sirfsoc_tx_fifo_data,
 				xmit->buf[xmit->tail]);
 				xmit->buf[xmit->tail]);
@@ -478,139 +463,6 @@ static void sirfsoc_uart_tx_dma_complete_callback(void *param)
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 }
 
 
-static void sirfsoc_uart_insert_rx_buf_to_tty(
-		struct sirfsoc_uart_port *sirfport, int count)
-{
-	struct uart_port *port = &sirfport->port;
-	struct tty_port *tport = &port->state->port;
-	int inserted;
-
-	inserted = tty_insert_flip_string(tport,
-		sirfport->rx_dma_items[sirfport->rx_completed].xmit.buf, count);
-	port->icount.rx += inserted;
-}
-
-static void sirfsoc_rx_submit_one_dma_desc(struct uart_port *port, int index)
-{
-	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
-
-	sirfport->rx_dma_items[index].xmit.tail =
-		sirfport->rx_dma_items[index].xmit.head = 0;
-	sirfport->rx_dma_items[index].desc =
-		dmaengine_prep_slave_single(sirfport->rx_dma_chan,
-		sirfport->rx_dma_items[index].dma_addr, SIRFSOC_RX_DMA_BUF_SIZE,
-		DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
-	if (!sirfport->rx_dma_items[index].desc) {
-		dev_err(port->dev, "DMA slave single fail\n");
-		return;
-	}
-	sirfport->rx_dma_items[index].desc->callback =
-		sirfsoc_uart_rx_dma_complete_callback;
-	sirfport->rx_dma_items[index].desc->callback_param = sirfport;
-	sirfport->rx_dma_items[index].cookie =
-		dmaengine_submit(sirfport->rx_dma_items[index].desc);
-	dma_async_issue_pending(sirfport->rx_dma_chan);
-}
-
-static void sirfsoc_rx_tmo_process_tl(unsigned long param)
-{
-	struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
-	struct uart_port *port = &sirfport->port;
-	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
-	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-	struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st;
-	unsigned int count;
-	unsigned long flags;
-	struct dma_tx_state tx_state;
-
-	spin_lock_irqsave(&port->lock, flags);
-	while (DMA_COMPLETE == dmaengine_tx_status(sirfport->rx_dma_chan,
-		sirfport->rx_dma_items[sirfport->rx_completed].cookie, &tx_state)) {
-		sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
-					SIRFSOC_RX_DMA_BUF_SIZE);
-		sirfport->rx_completed++;
-		sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
-	}
-	count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head,
-		sirfport->rx_dma_items[sirfport->rx_issued].xmit.tail,
-		SIRFSOC_RX_DMA_BUF_SIZE);
-	if (count > 0)
-		sirfsoc_uart_insert_rx_buf_to_tty(sirfport, count);
-	wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
-			rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
-			SIRFUART_IO_MODE);
-	sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count);
-	if (sirfport->rx_io_count == 4) {
-		sirfport->rx_io_count = 0;
-		wr_regl(port, ureg->sirfsoc_int_st_reg,
-				uint_st->sirfsoc_rx_done);
-		if (!sirfport->is_atlas7)
-			wr_regl(port, ureg->sirfsoc_int_en_reg,
-				rd_regl(port, ureg->sirfsoc_int_en_reg) &
-				~(uint_en->sirfsoc_rx_done_en));
-		else
-			wr_regl(port, SIRFUART_INT_EN_CLR,
-					uint_en->sirfsoc_rx_done_en);
-		sirfsoc_uart_start_next_rx_dma(port);
-	} else {
-		wr_regl(port, ureg->sirfsoc_int_st_reg,
-				uint_st->sirfsoc_rx_done);
-		if (!sirfport->is_atlas7)
-			wr_regl(port, ureg->sirfsoc_int_en_reg,
-				rd_regl(port, ureg->sirfsoc_int_en_reg) |
-				(uint_en->sirfsoc_rx_done_en));
-		else
-			wr_regl(port, ureg->sirfsoc_int_en_reg,
-					uint_en->sirfsoc_rx_done_en);
-	}
-	spin_unlock_irqrestore(&port->lock, flags);
-	tty_flip_buffer_push(&port->state->port);
-}
-
-static void sirfsoc_uart_handle_rx_tmo(struct sirfsoc_uart_port *sirfport)
-{
-	struct uart_port *port = &sirfport->port;
-	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
-	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-	struct dma_tx_state tx_state;
-	dmaengine_tx_status(sirfport->rx_dma_chan,
-		sirfport->rx_dma_items[sirfport->rx_issued].cookie, &tx_state);
-	dmaengine_terminate_all(sirfport->rx_dma_chan);
-	sirfport->rx_dma_items[sirfport->rx_issued].xmit.head =
-		SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
-	if (!sirfport->is_atlas7)
-		wr_regl(port, ureg->sirfsoc_int_en_reg,
-			rd_regl(port, ureg->sirfsoc_int_en_reg) &
-			~(uint_en->sirfsoc_rx_timeout_en));
-	else
-		wr_regl(port, SIRFUART_INT_EN_CLR,
-				uint_en->sirfsoc_rx_timeout_en);
-	tasklet_schedule(&sirfport->rx_tmo_process_tasklet);
-}
-
-static void sirfsoc_uart_handle_rx_done(struct sirfsoc_uart_port *sirfport)
-{
-	struct uart_port *port = &sirfport->port;
-	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
-	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-	struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st;
-
-	sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count);
-	if (sirfport->rx_io_count == 4) {
-		sirfport->rx_io_count = 0;
-		if (!sirfport->is_atlas7)
-			wr_regl(port, ureg->sirfsoc_int_en_reg,
-				rd_regl(port, ureg->sirfsoc_int_en_reg) &
-				~(uint_en->sirfsoc_rx_done_en));
-		else
-			wr_regl(port, SIRFUART_INT_EN_CLR,
-					uint_en->sirfsoc_rx_done_en);
-		wr_regl(port, ureg->sirfsoc_int_st_reg,
-				uint_st->sirfsoc_rx_timeout);
-		sirfsoc_uart_start_next_rx_dma(port);
-	}
-}
-
 static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
 static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
 {
 {
 	unsigned long intr_status;
 	unsigned long intr_status;
@@ -628,20 +480,25 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
 	intr_status = rd_regl(port, ureg->sirfsoc_int_st_reg);
 	intr_status = rd_regl(port, ureg->sirfsoc_int_st_reg);
 	wr_regl(port, ureg->sirfsoc_int_st_reg, intr_status);
 	wr_regl(port, ureg->sirfsoc_int_st_reg, intr_status);
 	intr_status &= rd_regl(port, ureg->sirfsoc_int_en_reg);
 	intr_status &= rd_regl(port, ureg->sirfsoc_int_en_reg);
-	if (unlikely(intr_status & (SIRFUART_ERR_INT_STAT(port, uint_st)))) {
+	if (unlikely(intr_status & (SIRFUART_ERR_INT_STAT(uint_st,
+				sirfport->uart_reg->uart_type)))) {
 		if (intr_status & uint_st->sirfsoc_rxd_brk) {
 		if (intr_status & uint_st->sirfsoc_rxd_brk) {
 			port->icount.brk++;
 			port->icount.brk++;
 			if (uart_handle_break(port))
 			if (uart_handle_break(port))
 				goto recv_char;
 				goto recv_char;
 		}
 		}
-		if (intr_status & uint_st->sirfsoc_rx_oflow)
+		if (intr_status & uint_st->sirfsoc_rx_oflow) {
 			port->icount.overrun++;
 			port->icount.overrun++;
+			flag = TTY_OVERRUN;
+		}
 		if (intr_status & uint_st->sirfsoc_frm_err) {
 		if (intr_status & uint_st->sirfsoc_frm_err) {
 			port->icount.frame++;
 			port->icount.frame++;
 			flag = TTY_FRAME;
 			flag = TTY_FRAME;
 		}
 		}
-		if (intr_status & uint_st->sirfsoc_parity_err)
+		if (intr_status & uint_st->sirfsoc_parity_err) {
+			port->icount.parity++;
 			flag = TTY_PARITY;
 			flag = TTY_PARITY;
+		}
 		wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
 		wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
 		wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
 		wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
 		wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
 		wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
@@ -662,15 +519,51 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
 		uart_handle_cts_change(port, cts_status);
 		uart_handle_cts_change(port, cts_status);
 		wake_up_interruptible(&state->port.delta_msr_wait);
 		wake_up_interruptible(&state->port.delta_msr_wait);
 	}
 	}
-	if (sirfport->rx_dma_chan) {
-		if (intr_status & uint_st->sirfsoc_rx_timeout)
-			sirfsoc_uart_handle_rx_tmo(sirfport);
-		if (intr_status & uint_st->sirfsoc_rx_done)
-			sirfsoc_uart_handle_rx_done(sirfport);
-	} else {
-		if (intr_status & SIRFUART_RX_IO_INT_ST(uint_st))
-			sirfsoc_uart_pio_rx_chars(port,
-					SIRFSOC_UART_IO_RX_MAX_CNT);
+	if (!sirfport->rx_dma_chan &&
+		(intr_status & SIRFUART_RX_IO_INT_ST(uint_st))) {
+		/*
+		 * chip will trigger continuous RX_TIMEOUT interrupt
+		 * in RXFIFO empty and not trigger if RXFIFO recevice
+		 * data in limit time, original method use RX_TIMEOUT
+		 * will trigger lots of useless interrupt in RXFIFO
+		 * empty.RXFIFO received one byte will trigger RX_DONE
+		 * interrupt.use RX_DONE to wait for data received
+		 * into RXFIFO, use RX_THD/RX_FULL for lots data receive
+		 * and use RX_TIMEOUT for the last left data.
+		 */
+		if (intr_status & uint_st->sirfsoc_rx_done) {
+			if (!sirfport->is_atlas7) {
+				wr_regl(port, ureg->sirfsoc_int_en_reg,
+					rd_regl(port, ureg->sirfsoc_int_en_reg)
+					& ~(uint_en->sirfsoc_rx_done_en));
+				wr_regl(port, ureg->sirfsoc_int_en_reg,
+				rd_regl(port, ureg->sirfsoc_int_en_reg)
+				| (uint_en->sirfsoc_rx_timeout_en));
+			} else {
+				wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
+					uint_en->sirfsoc_rx_done_en);
+				wr_regl(port, ureg->sirfsoc_int_en_reg,
+					uint_en->sirfsoc_rx_timeout_en);
+			}
+		} else {
+			if (intr_status & uint_st->sirfsoc_rx_timeout) {
+				if (!sirfport->is_atlas7) {
+					wr_regl(port, ureg->sirfsoc_int_en_reg,
+					rd_regl(port, ureg->sirfsoc_int_en_reg)
+					& ~(uint_en->sirfsoc_rx_timeout_en));
+					wr_regl(port, ureg->sirfsoc_int_en_reg,
+					rd_regl(port, ureg->sirfsoc_int_en_reg)
+					| (uint_en->sirfsoc_rx_done_en));
+				} else {
+					wr_regl(port,
+						ureg->sirfsoc_int_en_clr_reg,
+						uint_en->sirfsoc_rx_timeout_en);
+					wr_regl(port, ureg->sirfsoc_int_en_reg,
+						uint_en->sirfsoc_rx_done_en);
+				}
+			}
+			sirfsoc_uart_pio_rx_chars(port, port->fifosize);
+		}
 	}
 	}
 	spin_unlock(&port->lock);
 	spin_unlock(&port->lock);
 	tty_flip_buffer_push(&state->port);
 	tty_flip_buffer_push(&state->port);
@@ -684,10 +577,10 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
 				return IRQ_HANDLED;
 				return IRQ_HANDLED;
 			} else {
 			} else {
 				sirfsoc_uart_pio_tx_chars(sirfport,
 				sirfsoc_uart_pio_tx_chars(sirfport,
-					SIRFSOC_UART_IO_TX_REASONABLE_CNT);
+						port->fifosize);
 				if ((uart_circ_empty(xmit)) &&
 				if ((uart_circ_empty(xmit)) &&
 				(rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
 				(rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
-				ufifo_st->ff_empty(port->line)))
+				ufifo_st->ff_empty(port)))
 					sirfsoc_uart_stop_tx(port);
 					sirfsoc_uart_stop_tx(port);
 			}
 			}
 		}
 		}
@@ -697,41 +590,8 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-static void sirfsoc_uart_rx_dma_complete_tl(unsigned long param)
-{
-	struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
-	struct uart_port *port = &sirfport->port;
-	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
-	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-	unsigned long flags;
-	struct dma_tx_state tx_state;
-	spin_lock_irqsave(&port->lock, flags);
-	while (DMA_COMPLETE == dmaengine_tx_status(sirfport->rx_dma_chan,
-			sirfport->rx_dma_items[sirfport->rx_completed].cookie, &tx_state)) {
-		sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
-					SIRFSOC_RX_DMA_BUF_SIZE);
-		if (rd_regl(port, ureg->sirfsoc_int_en_reg) &
-				uint_en->sirfsoc_rx_timeout_en)
-			sirfsoc_rx_submit_one_dma_desc(port,
-					sirfport->rx_completed++);
-		else
-			sirfport->rx_completed++;
-		sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
-	}
-	spin_unlock_irqrestore(&port->lock, flags);
-	tty_flip_buffer_push(&port->state->port);
-}
-
 static void sirfsoc_uart_rx_dma_complete_callback(void *param)
 static void sirfsoc_uart_rx_dma_complete_callback(void *param)
 {
 {
-	struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sirfport->port.lock, flags);
-	sirfport->rx_issued++;
-	sirfport->rx_issued %= SIRFSOC_RX_LOOP_BUF_CNT;
-	tasklet_schedule(&sirfport->rx_dma_complete_tasklet);
-	spin_unlock_irqrestore(&sirfport->port.lock, flags);
 }
 }
 
 
 /* submit rx dma task into dmaengine */
 /* submit rx dma task into dmaengine */
@@ -740,21 +600,36 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
 	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
 	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
 	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-	int i;
 	sirfport->rx_io_count = 0;
 	sirfport->rx_io_count = 0;
 	wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
 	wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
 		rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
 		rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
 		~SIRFUART_IO_MODE);
 		~SIRFUART_IO_MODE);
-	for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
-		sirfsoc_rx_submit_one_dma_desc(port, i);
-	sirfport->rx_completed = sirfport->rx_issued = 0;
+	sirfport->rx_dma_items.xmit.tail =
+		sirfport->rx_dma_items.xmit.head = 0;
+	sirfport->rx_dma_items.desc =
+		dmaengine_prep_dma_cyclic(sirfport->rx_dma_chan,
+		sirfport->rx_dma_items.dma_addr, SIRFSOC_RX_DMA_BUF_SIZE,
+		SIRFSOC_RX_DMA_BUF_SIZE / 2,
+		DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+	if (IS_ERR_OR_NULL(sirfport->rx_dma_items.desc)) {
+		dev_err(port->dev, "DMA slave single fail\n");
+		return;
+	}
+	sirfport->rx_dma_items.desc->callback =
+		sirfsoc_uart_rx_dma_complete_callback;
+	sirfport->rx_dma_items.desc->callback_param = sirfport;
+	sirfport->rx_dma_items.cookie =
+		dmaengine_submit(sirfport->rx_dma_items.desc);
+	dma_async_issue_pending(sirfport->rx_dma_chan);
 	if (!sirfport->is_atlas7)
 	if (!sirfport->is_atlas7)
 		wr_regl(port, ureg->sirfsoc_int_en_reg,
 		wr_regl(port, ureg->sirfsoc_int_en_reg,
 				rd_regl(port, ureg->sirfsoc_int_en_reg) |
 				rd_regl(port, ureg->sirfsoc_int_en_reg) |
-				SIRFUART_RX_DMA_INT_EN(port, uint_en));
+				SIRFUART_RX_DMA_INT_EN(uint_en,
+				sirfport->uart_reg->uart_type));
 	else
 	else
 		wr_regl(port, ureg->sirfsoc_int_en_reg,
 		wr_regl(port, ureg->sirfsoc_int_en_reg,
-			SIRFUART_RX_DMA_INT_EN(port, uint_en));
+				SIRFUART_RX_DMA_INT_EN(uint_en,
+				sirfport->uart_reg->uart_type));
 }
 }
 
 
 static void sirfsoc_uart_start_rx(struct uart_port *port)
 static void sirfsoc_uart_start_rx(struct uart_port *port)
@@ -773,10 +648,12 @@ static void sirfsoc_uart_start_rx(struct uart_port *port)
 		if (!sirfport->is_atlas7)
 		if (!sirfport->is_atlas7)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 				rd_regl(port, ureg->sirfsoc_int_en_reg) |
 				rd_regl(port, ureg->sirfsoc_int_en_reg) |
-				SIRFUART_RX_IO_INT_EN(port, uint_en));
+				SIRFUART_RX_IO_INT_EN(uint_en,
+					sirfport->uart_reg->uart_type));
 		else
 		else
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
-				SIRFUART_RX_IO_INT_EN(port, uint_en));
+				SIRFUART_RX_IO_INT_EN(uint_en,
+					sirfport->uart_reg->uart_type));
 	}
 	}
 }
 }
 
 
@@ -789,7 +666,7 @@ sirfsoc_usp_calc_sample_div(unsigned long set_rate,
 	unsigned long ioclk_div = 0;
 	unsigned long ioclk_div = 0;
 	unsigned long temp_delta;
 	unsigned long temp_delta;
 
 
-	for (sample_div = SIRF_MIN_SAMPLE_DIV;
+	for (sample_div = SIRF_USP_MIN_SAMPLE_DIV;
 			sample_div <= SIRF_MAX_SAMPLE_DIV; sample_div++) {
 			sample_div <= SIRF_MAX_SAMPLE_DIV; sample_div++) {
 		temp_delta = ioclk_rate -
 		temp_delta = ioclk_rate -
 		(ioclk_rate + (set_rate * sample_div) / 2)
 		(ioclk_rate + (set_rate * sample_div) / 2)
@@ -910,10 +787,11 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
 					config_reg |= SIRFUART_STICK_BIT_MARK;
 					config_reg |= SIRFUART_STICK_BIT_MARK;
 				else
 				else
 					config_reg |= SIRFUART_STICK_BIT_SPACE;
 					config_reg |= SIRFUART_STICK_BIT_SPACE;
-			} else if (termios->c_cflag & PARODD) {
-				config_reg |= SIRFUART_STICK_BIT_ODD;
 			} else {
 			} else {
-				config_reg |= SIRFUART_STICK_BIT_EVEN;
+				if (termios->c_cflag & PARODD)
+					config_reg |= SIRFUART_STICK_BIT_ODD;
+				else
+					config_reg |= SIRFUART_STICK_BIT_EVEN;
 			}
 			}
 		}
 		}
 	} else {
 	} else {
@@ -976,7 +854,7 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
 	wr_regl(port, ureg->sirfsoc_tx_fifo_op,
 	wr_regl(port, ureg->sirfsoc_tx_fifo_op,
 			(txfifo_op_reg & ~SIRFUART_FIFO_START));
 			(txfifo_op_reg & ~SIRFUART_FIFO_START));
 	if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
 	if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
-		config_reg |= SIRFUART_RECV_TIMEOUT(port, rx_time_out);
+		config_reg |= SIRFUART_UART_RECV_TIMEOUT(rx_time_out);
 		wr_regl(port, ureg->sirfsoc_line_ctrl, config_reg);
 		wr_regl(port, ureg->sirfsoc_line_ctrl, config_reg);
 	} else {
 	} else {
 		/*tx frame ctrl*/
 		/*tx frame ctrl*/
@@ -999,7 +877,7 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
 		wr_regl(port, ureg->sirfsoc_rx_frame_ctrl, len_val);
 		wr_regl(port, ureg->sirfsoc_rx_frame_ctrl, len_val);
 		/*async param*/
 		/*async param*/
 		wr_regl(port, ureg->sirfsoc_async_param_reg,
 		wr_regl(port, ureg->sirfsoc_async_param_reg,
-			(SIRFUART_RECV_TIMEOUT(port, rx_time_out)) |
+			(SIRFUART_USP_RECV_TIMEOUT(rx_time_out)) |
 			(sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) <<
 			(sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) <<
 			SIRFSOC_USP_ASYNC_DIV2_OFFSET);
 			SIRFSOC_USP_ASYNC_DIV2_OFFSET);
 	}
 	}
@@ -1011,6 +889,7 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
 		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE);
 		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE);
 	else
 	else
 		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
 		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
+	sirfport->rx_period_time = 20000000;
 	/* Reset Rx/Tx FIFO Threshold level for proper baudrate */
 	/* Reset Rx/Tx FIFO Threshold level for proper baudrate */
 	if (set_baud < 1000000)
 	if (set_baud < 1000000)
 		threshold_div = 1;
 		threshold_div = 1;
@@ -1032,19 +911,10 @@ static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state,
 			      unsigned int oldstate)
 			      unsigned int oldstate)
 {
 {
 	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
 	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
-	if (!state) {
-		if (sirfport->is_bt_uart) {
-			clk_prepare_enable(sirfport->clk_noc);
-			clk_prepare_enable(sirfport->clk_general);
-		}
+	if (!state)
 		clk_prepare_enable(sirfport->clk);
 		clk_prepare_enable(sirfport->clk);
-	} else {
+	else
 		clk_disable_unprepare(sirfport->clk);
 		clk_disable_unprepare(sirfport->clk);
-		if (sirfport->is_bt_uart) {
-			clk_disable_unprepare(sirfport->clk_general);
-			clk_disable_unprepare(sirfport->clk_noc);
-		}
-	}
 }
 }
 
 
 static int sirfsoc_uart_startup(struct uart_port *port)
 static int sirfsoc_uart_startup(struct uart_port *port)
@@ -1053,7 +923,7 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	unsigned int index			= port->line;
 	unsigned int index			= port->line;
 	int ret;
 	int ret;
-	set_irq_flags(port->irq, IRQF_VALID | IRQF_NOAUTOEN);
+	irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
 	ret = request_irq(port->irq,
 	ret = request_irq(port->irq,
 				sirfsoc_uart_isr,
 				sirfsoc_uart_isr,
 				0,
 				0,
@@ -1064,7 +934,6 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 							index, port->irq);
 							index, port->irq);
 		goto irq_err;
 		goto irq_err;
 	}
 	}
-
 	/* initial hardware settings */
 	/* initial hardware settings */
 	wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl,
 	wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl,
 		rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl) |
 		rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl) |
@@ -1072,6 +941,9 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 	wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
 	wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
 		rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
 		rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
 		SIRFUART_IO_MODE);
 		SIRFUART_IO_MODE);
+	wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+		rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
+		~SIRFUART_RX_DMA_FLUSH);
 	wr_regl(port, ureg->sirfsoc_tx_dma_io_len, 0);
 	wr_regl(port, ureg->sirfsoc_tx_dma_io_len, 0);
 	wr_regl(port, ureg->sirfsoc_rx_dma_io_len, 0);
 	wr_regl(port, ureg->sirfsoc_rx_dma_io_len, 0);
 	wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_RX_EN | SIRFUART_TX_EN);
 	wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_RX_EN | SIRFUART_TX_EN);
@@ -1080,7 +952,6 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 			SIRFSOC_USP_ENDIAN_CTRL_LSBF |
 			SIRFSOC_USP_ENDIAN_CTRL_LSBF |
 			SIRFSOC_USP_EN);
 			SIRFSOC_USP_EN);
 	wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_RESET);
 	wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_RESET);
-	wr_regl(port, ureg->sirfsoc_tx_fifo_op, 0);
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
 	wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port));
 	wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port));
@@ -1100,8 +971,8 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 	sirfport->ms_enabled = false;
 	sirfport->ms_enabled = false;
 	if (sirfport->uart_reg->uart_type == SIRF_USP_UART &&
 	if (sirfport->uart_reg->uart_type == SIRF_USP_UART &&
 		sirfport->hw_flow_ctrl) {
 		sirfport->hw_flow_ctrl) {
-		set_irq_flags(gpio_to_irq(sirfport->cts_gpio),
-			IRQF_VALID | IRQF_NOAUTOEN);
+		irq_modify_status(gpio_to_irq(sirfport->cts_gpio),
+			IRQ_NOREQUEST, IRQ_NOAUTOEN);
 		ret = request_irq(gpio_to_irq(sirfport->cts_gpio),
 		ret = request_irq(gpio_to_irq(sirfport->cts_gpio),
 			sirfsoc_uart_usp_cts_handler, IRQF_TRIGGER_FALLING |
 			sirfsoc_uart_usp_cts_handler, IRQF_TRIGGER_FALLING |
 			IRQF_TRIGGER_RISING, "usp_cts_irq", sirfport);
 			IRQF_TRIGGER_RISING, "usp_cts_irq", sirfport);
@@ -1110,8 +981,16 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 			goto init_rx_err;
 			goto init_rx_err;
 		}
 		}
 	}
 	}
-
 	enable_irq(port->irq);
 	enable_irq(port->irq);
+	if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) {
+		sirfport->is_hrt_enabled = true;
+		sirfport->rx_period_time = 20000000;
+		sirfport->rx_dma_items.xmit.tail =
+			sirfport->rx_dma_items.xmit.head = 0;
+		hrtimer_start(&sirfport->hrt,
+			ns_to_ktime(sirfport->rx_period_time),
+			HRTIMER_MODE_REL);
+	}
 
 
 	return 0;
 	return 0;
 init_rx_err:
 init_rx_err:
@@ -1127,7 +1006,7 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
 	if (!sirfport->is_atlas7)
 	if (!sirfport->is_atlas7)
 		wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
 		wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
 	else
 	else
-		wr_regl(port, SIRFUART_INT_EN_CLR, ~0UL);
+		wr_regl(port, ureg->sirfsoc_int_en_clr_reg, ~0UL);
 
 
 	free_irq(port->irq, sirfport);
 	free_irq(port->irq, sirfport);
 	if (sirfport->ms_enabled)
 	if (sirfport->ms_enabled)
@@ -1139,6 +1018,13 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
 	}
 	}
 	if (sirfport->tx_dma_chan)
 	if (sirfport->tx_dma_chan)
 		sirfport->tx_dma_state = TX_DMA_IDLE;
 		sirfport->tx_dma_state = TX_DMA_IDLE;
+	if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) {
+		while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
+			SIRFUART_RX_FIFO_MASK) > 0)
+			;
+		sirfport->is_hrt_enabled = false;
+		hrtimer_cancel(&sirfport->hrt);
+	}
 }
 }
 
 
 static const char *sirfsoc_uart_type(struct uart_port *port)
 static const char *sirfsoc_uart_type(struct uart_port *port)
@@ -1196,27 +1082,29 @@ sirfsoc_uart_console_setup(struct console *co, char *options)
 	unsigned int bits = 8;
 	unsigned int bits = 8;
 	unsigned int parity = 'n';
 	unsigned int parity = 'n';
 	unsigned int flow = 'n';
 	unsigned int flow = 'n';
-	struct uart_port *port = &sirfsoc_uart_ports[co->index].port;
-	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
-	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
+	struct sirfsoc_uart_port *sirfport;
+	struct sirfsoc_register *ureg;
 	if (co->index < 0 || co->index >= SIRFSOC_UART_NR)
 	if (co->index < 0 || co->index >= SIRFSOC_UART_NR)
-		return -EINVAL;
-
-	if (!port->mapbase)
+		co->index = 1;
+	sirfport = sirf_ports[co->index];
+	if (!sirfport)
+		return -ENODEV;
+	ureg = &sirfport->uart_reg->uart_reg;
+	if (!sirfport->port.mapbase)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	/* enable usp in mode1 register */
 	/* enable usp in mode1 register */
 	if (sirfport->uart_reg->uart_type == SIRF_USP_UART)
 	if (sirfport->uart_reg->uart_type == SIRF_USP_UART)
-		wr_regl(port, ureg->sirfsoc_mode1, SIRFSOC_USP_EN |
+		wr_regl(&sirfport->port, ureg->sirfsoc_mode1, SIRFSOC_USP_EN |
 				SIRFSOC_USP_ENDIAN_CTRL_LSBF);
 				SIRFSOC_USP_ENDIAN_CTRL_LSBF);
 	if (options)
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
-	port->cons = co;
+	sirfport->port.cons = co;
 
 
 	/* default console tx/rx transfer using io mode */
 	/* default console tx/rx transfer using io mode */
 	sirfport->rx_dma_chan = NULL;
 	sirfport->rx_dma_chan = NULL;
 	sirfport->tx_dma_chan = NULL;
 	sirfport->tx_dma_chan = NULL;
-	return uart_set_options(port, co, baud, parity, bits, flow);
+	return uart_set_options(&sirfport->port, co, baud, parity, bits, flow);
 }
 }
 
 
 static void sirfsoc_uart_console_putchar(struct uart_port *port, int ch)
 static void sirfsoc_uart_console_putchar(struct uart_port *port, int ch)
@@ -1224,8 +1112,8 @@ static void sirfsoc_uart_console_putchar(struct uart_port *port, int ch)
 	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
 	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
 	struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
-	while (rd_regl(port,
-		ureg->sirfsoc_tx_fifo_status) & ufifo_st->ff_full(port->line))
+	while (rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
+		ufifo_st->ff_full(port))
 		cpu_relax();
 		cpu_relax();
 	wr_regl(port, ureg->sirfsoc_tx_fifo_data, ch);
 	wr_regl(port, ureg->sirfsoc_tx_fifo_data, ch);
 }
 }
@@ -1233,8 +1121,10 @@ static void sirfsoc_uart_console_putchar(struct uart_port *port, int ch)
 static void sirfsoc_uart_console_write(struct console *co, const char *s,
 static void sirfsoc_uart_console_write(struct console *co, const char *s,
 							unsigned int count)
 							unsigned int count)
 {
 {
-	struct uart_port *port = &sirfsoc_uart_ports[co->index].port;
-	uart_console_write(port, s, count, sirfsoc_uart_console_putchar);
+	struct sirfsoc_uart_port *sirfport = sirf_ports[co->index];
+
+	uart_console_write(&sirfport->port, s, count,
+			sirfsoc_uart_console_putchar);
 }
 }
 
 
 static struct console sirfsoc_uart_console = {
 static struct console sirfsoc_uart_console = {
@@ -1269,10 +1159,75 @@ static struct uart_driver sirfsoc_uart_drv = {
 #endif
 #endif
 };
 };
 
 
-static const struct of_device_id sirfsoc_uart_ids[] = {
+static enum hrtimer_restart
+	sirfsoc_uart_rx_dma_hrtimer_callback(struct hrtimer *hrt)
+{
+	struct sirfsoc_uart_port *sirfport;
+	struct uart_port *port;
+	int count, inserted;
+	struct dma_tx_state tx_state;
+	struct tty_struct *tty;
+	struct sirfsoc_register *ureg;
+	struct circ_buf *xmit;
+
+	sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt);
+	port = &sirfport->port;
+	inserted = 0;
+	tty = port->state->port.tty;
+	ureg = &sirfport->uart_reg->uart_reg;
+	xmit = &sirfport->rx_dma_items.xmit;
+	dmaengine_tx_status(sirfport->rx_dma_chan,
+		sirfport->rx_dma_items.cookie, &tx_state);
+	xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
+	count = CIRC_CNT_TO_END(xmit->head, xmit->tail,
+			SIRFSOC_RX_DMA_BUF_SIZE);
+	while (count > 0) {
+		inserted = tty_insert_flip_string(tty->port,
+			(const unsigned char *)&xmit->buf[xmit->tail], count);
+		if (!inserted)
+			goto next_hrt;
+		port->icount.rx += inserted;
+		xmit->tail = (xmit->tail + inserted) &
+				(SIRFSOC_RX_DMA_BUF_SIZE - 1);
+		count = CIRC_CNT_TO_END(xmit->head, xmit->tail,
+				SIRFSOC_RX_DMA_BUF_SIZE);
+		tty_flip_buffer_push(tty->port);
+	}
+	/*
+	 * if RX DMA buffer data have all push into tty buffer, and there is
+	 * only little data(less than a dma transfer unit) left in rxfifo,
+	 * fetch it out in pio mode and switch back to dma immediately
+	 */
+	if (!inserted && !count &&
+		((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
+		SIRFUART_RX_FIFO_MASK) > 0)) {
+		/* switch to pio mode */
+		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+			rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
+			SIRFUART_IO_MODE);
+		while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
+			SIRFUART_RX_FIFO_MASK) > 0) {
+			if (sirfsoc_uart_pio_rx_chars(port, 16) > 0)
+				tty_flip_buffer_push(tty->port);
+		}
+		wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
+		wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
+		wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
+		/* switch back to dma mode */
+		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+			rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
+			~SIRFUART_IO_MODE);
+	}
+next_hrt:
+	hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time));
+	return HRTIMER_RESTART;
+}
+
+static struct of_device_id sirfsoc_uart_ids[] = {
 	{ .compatible = "sirf,prima2-uart", .data = &sirfsoc_uart,},
 	{ .compatible = "sirf,prima2-uart", .data = &sirfsoc_uart,},
 	{ .compatible = "sirf,atlas7-uart", .data = &sirfsoc_uart},
 	{ .compatible = "sirf,atlas7-uart", .data = &sirfsoc_uart},
 	{ .compatible = "sirf,prima2-usp-uart", .data = &sirfsoc_usp},
 	{ .compatible = "sirf,prima2-usp-uart", .data = &sirfsoc_usp},
+	{ .compatible = "sirf,atlas7-usp-uart", .data = &sirfsoc_usp},
 	{}
 	{}
 };
 };
 MODULE_DEVICE_TABLE(of, sirfsoc_uart_ids);
 MODULE_DEVICE_TABLE(of, sirfsoc_uart_ids);
@@ -1283,7 +1238,6 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 	struct uart_port *port;
 	struct uart_port *port;
 	struct resource *res;
 	struct resource *res;
 	int ret;
 	int ret;
-	int i, j;
 	struct dma_slave_config slv_cfg = {
 	struct dma_slave_config slv_cfg = {
 		.src_maxburst = 2,
 		.src_maxburst = 2,
 	};
 	};
@@ -1293,16 +1247,15 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 	const struct of_device_id *match;
 	const struct of_device_id *match;
 
 
 	match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node);
 	match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node);
-	if (of_property_read_u32(pdev->dev.of_node, "cell-index", &pdev->id)) {
-		dev_err(&pdev->dev,
-			"Unable to find cell-index in uart node.\n");
-		ret = -EFAULT;
+	sirfport = devm_kzalloc(&pdev->dev, sizeof(*sirfport), GFP_KERNEL);
+	if (!sirfport) {
+		ret = -ENOMEM;
 		goto err;
 		goto err;
 	}
 	}
-	if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart"))
-		pdev->id += ((struct sirfsoc_uart_register *)
-				match->data)->uart_param.register_uart_nr;
-	sirfport = &sirfsoc_uart_ports[pdev->id];
+	sirfport->port.line = of_alias_get_id(pdev->dev.of_node, "serial");
+	sirf_ports[sirfport->port.line] = sirfport;
+	sirfport->port.iotype = UPIO_MEM;
+	sirfport->port.flags = UPF_BOOT_AUTOCONF;
 	port = &sirfport->port;
 	port = &sirfport->port;
 	port->dev = &pdev->dev;
 	port->dev = &pdev->dev;
 	port->private_data = sirfport;
 	port->private_data = sirfport;
@@ -1310,9 +1263,12 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 
 
 	sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node,
 	sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node,
 		"sirf,uart-has-rtscts");
 		"sirf,uart-has-rtscts");
-	if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart"))
+	if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart") ||
+		of_device_is_compatible(pdev->dev.of_node, "sirf,atlas7-uart"))
 		sirfport->uart_reg->uart_type = SIRF_REAL_UART;
 		sirfport->uart_reg->uart_type = SIRF_REAL_UART;
-	if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart")) {
+	if (of_device_is_compatible(pdev->dev.of_node,
+		"sirf,prima2-usp-uart") || of_device_is_compatible(
+		pdev->dev.of_node, "sirf,atlas7-usp-uart")) {
 		sirfport->uart_reg->uart_type =	SIRF_USP_UART;
 		sirfport->uart_reg->uart_type =	SIRF_USP_UART;
 		if (!sirfport->hw_flow_ctrl)
 		if (!sirfport->hw_flow_ctrl)
 			goto usp_no_flow_control;
 			goto usp_no_flow_control;
@@ -1350,7 +1306,8 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 		gpio_direction_output(sirfport->rts_gpio, 1);
 		gpio_direction_output(sirfport->rts_gpio, 1);
 	}
 	}
 usp_no_flow_control:
 usp_no_flow_control:
-	if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas7-uart"))
+	if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas7-uart") ||
+	    of_device_is_compatible(pdev->dev.of_node, "sirf,atlas7-usp-uart"))
 		sirfport->is_atlas7 = true;
 		sirfport->is_atlas7 = true;
 
 
 	if (of_property_read_u32(pdev->dev.of_node,
 	if (of_property_read_u32(pdev->dev.of_node,
@@ -1368,12 +1325,9 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 		ret = -EFAULT;
 		ret = -EFAULT;
 		goto err;
 		goto err;
 	}
 	}
-	tasklet_init(&sirfport->rx_dma_complete_tasklet,
-			sirfsoc_uart_rx_dma_complete_tl, (unsigned long)sirfport);
-	tasklet_init(&sirfport->rx_tmo_process_tasklet,
-			sirfsoc_rx_tmo_process_tl, (unsigned long)sirfport);
 	port->mapbase = res->start;
 	port->mapbase = res->start;
-	port->membase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	port->membase = devm_ioremap(&pdev->dev,
+			res->start, resource_size(res));
 	if (!port->membase) {
 	if (!port->membase) {
 		dev_err(&pdev->dev, "Cannot remap resource.\n");
 		dev_err(&pdev->dev, "Cannot remap resource.\n");
 		ret = -ENOMEM;
 		ret = -ENOMEM;
@@ -1393,20 +1347,6 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 		goto err;
 		goto err;
 	}
 	}
 	port->uartclk = clk_get_rate(sirfport->clk);
 	port->uartclk = clk_get_rate(sirfport->clk);
-	if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas7-bt-uart")) {
-		sirfport->clk_general = devm_clk_get(&pdev->dev, "general");
-		if (IS_ERR(sirfport->clk_general)) {
-			ret = PTR_ERR(sirfport->clk_general);
-			goto err;
-		}
-		sirfport->clk_noc = devm_clk_get(&pdev->dev, "noc");
-		if (IS_ERR(sirfport->clk_noc)) {
-			ret = PTR_ERR(sirfport->clk_noc);
-			goto err;
-		}
-		sirfport->is_bt_uart = true;
-	} else
-		sirfport->is_bt_uart = false;
 
 
 	port->ops = &sirfsoc_uart_ops;
 	port->ops = &sirfsoc_uart_ops;
 	spin_lock_init(&port->lock);
 	spin_lock_init(&port->lock);
@@ -1419,30 +1359,32 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx");
 	sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx");
-	for (i = 0; sirfport->rx_dma_chan && i < SIRFSOC_RX_LOOP_BUF_CNT; i++) {
-		sirfport->rx_dma_items[i].xmit.buf =
-			dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
-			&sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL);
-		if (!sirfport->rx_dma_items[i].xmit.buf) {
-			dev_err(port->dev, "Uart alloc bufa failed\n");
-			ret = -ENOMEM;
-			goto alloc_coherent_err;
-		}
-		sirfport->rx_dma_items[i].xmit.head =
-			sirfport->rx_dma_items[i].xmit.tail = 0;
+	sirfport->rx_dma_items.xmit.buf =
+		dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
+		&sirfport->rx_dma_items.dma_addr, GFP_KERNEL);
+	if (!sirfport->rx_dma_items.xmit.buf) {
+		dev_err(port->dev, "Uart alloc bufa failed\n");
+		ret = -ENOMEM;
+		goto alloc_coherent_err;
 	}
 	}
+	sirfport->rx_dma_items.xmit.head =
+		sirfport->rx_dma_items.xmit.tail = 0;
 	if (sirfport->rx_dma_chan)
 	if (sirfport->rx_dma_chan)
 		dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
 		dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
 	sirfport->tx_dma_chan = dma_request_slave_channel(port->dev, "tx");
 	sirfport->tx_dma_chan = dma_request_slave_channel(port->dev, "tx");
 	if (sirfport->tx_dma_chan)
 	if (sirfport->tx_dma_chan)
 		dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
 		dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
+	if (sirfport->rx_dma_chan) {
+		hrtimer_init(&sirfport->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		sirfport->hrt.function = sirfsoc_uart_rx_dma_hrtimer_callback;
+		sirfport->is_hrt_enabled = false;
+	}
 
 
 	return 0;
 	return 0;
 alloc_coherent_err:
 alloc_coherent_err:
-	for (j = 0; j < i; j++)
-		dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
-				sirfport->rx_dma_items[j].xmit.buf,
-				sirfport->rx_dma_items[j].dma_addr);
+	dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
+			sirfport->rx_dma_items.xmit.buf,
+			sirfport->rx_dma_items.dma_addr);
 	dma_release_channel(sirfport->rx_dma_chan);
 	dma_release_channel(sirfport->rx_dma_chan);
 err:
 err:
 	return ret;
 	return ret;
@@ -1454,13 +1396,11 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
 	struct uart_port *port = &sirfport->port;
 	struct uart_port *port = &sirfport->port;
 	uart_remove_one_port(&sirfsoc_uart_drv, port);
 	uart_remove_one_port(&sirfsoc_uart_drv, port);
 	if (sirfport->rx_dma_chan) {
 	if (sirfport->rx_dma_chan) {
-		int i;
 		dmaengine_terminate_all(sirfport->rx_dma_chan);
 		dmaengine_terminate_all(sirfport->rx_dma_chan);
 		dma_release_channel(sirfport->rx_dma_chan);
 		dma_release_channel(sirfport->rx_dma_chan);
-		for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
-			dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
-					sirfport->rx_dma_items[i].xmit.buf,
-					sirfport->rx_dma_items[i].dma_addr);
+		dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
+				sirfport->rx_dma_items.xmit.buf,
+				sirfport->rx_dma_items.dma_addr);
 	}
 	}
 	if (sirfport->tx_dma_chan) {
 	if (sirfport->tx_dma_chan) {
 		dmaengine_terminate_all(sirfport->tx_dma_chan);
 		dmaengine_terminate_all(sirfport->tx_dma_chan);

+ 54 - 66
drivers/tty/serial/sirfsoc_uart.h

@@ -6,11 +6,11 @@
  * Licensed under GPLv2 or later.
  * Licensed under GPLv2 or later.
  */
  */
 #include <linux/bitops.h>
 #include <linux/bitops.h>
+#include <linux/log2.h>
+#include <linux/hrtimer.h>
 struct sirfsoc_uart_param {
 struct sirfsoc_uart_param {
 	const char *uart_name;
 	const char *uart_name;
 	const char *port_name;
 	const char *port_name;
-	u32 uart_nr;
-	u32 register_uart_nr;
 };
 };
 
 
 struct sirfsoc_register {
 struct sirfsoc_register {
@@ -21,6 +21,7 @@ struct sirfsoc_register {
 	u32 sirfsoc_tx_rx_en;
 	u32 sirfsoc_tx_rx_en;
 	u32 sirfsoc_int_en_reg;
 	u32 sirfsoc_int_en_reg;
 	u32 sirfsoc_int_st_reg;
 	u32 sirfsoc_int_st_reg;
+	u32 sirfsoc_int_en_clr_reg;
 	u32 sirfsoc_tx_dma_io_ctrl;
 	u32 sirfsoc_tx_dma_io_ctrl;
 	u32 sirfsoc_tx_dma_io_len;
 	u32 sirfsoc_tx_dma_io_len;
 	u32 sirfsoc_tx_fifo_ctrl;
 	u32 sirfsoc_tx_fifo_ctrl;
@@ -45,8 +46,8 @@ struct sirfsoc_register {
 	u32 sirfsoc_async_param_reg;
 	u32 sirfsoc_async_param_reg;
 };
 };
 
 
-typedef u32 (*fifo_full_mask)(int line);
-typedef u32 (*fifo_empty_mask)(int line);
+typedef u32 (*fifo_full_mask)(struct uart_port *port);
+typedef u32 (*fifo_empty_mask)(struct uart_port *port);
 
 
 struct sirfsoc_fifo_status {
 struct sirfsoc_fifo_status {
 	fifo_full_mask ff_full;
 	fifo_full_mask ff_full;
@@ -105,21 +106,20 @@ struct sirfsoc_uart_register {
 	enum sirfsoc_uart_type uart_type;
 	enum sirfsoc_uart_type uart_type;
 };
 };
 
 
-u32 usp_ff_full(int line)
+u32 uart_usp_ff_full_mask(struct uart_port *port)
 {
 {
-	return 0x80;
-}
-u32 usp_ff_empty(int line)
-{
-	return 0x100;
-}
-u32 uart_ff_full(int line)
-{
-	return (line == 1) ? (0x20) : (0x80);
+	u32 full_bit;
+
+	full_bit = ilog2(port->fifosize);
+	return (1 << full_bit);
 }
 }
-u32 uart_ff_empty(int line)
+
+u32 uart_usp_ff_empty_mask(struct uart_port *port)
 {
 {
-	return (line == 1) ? (0x40) : (0x100);
+	u32 empty_bit;
+
+	empty_bit = ilog2(port->fifosize) + 1;
+	return (1 << empty_bit);
 }
 }
 struct sirfsoc_uart_register sirfsoc_usp = {
 struct sirfsoc_uart_register sirfsoc_usp = {
 	.uart_reg = {
 	.uart_reg = {
@@ -145,6 +145,7 @@ struct sirfsoc_uart_register sirfsoc_usp = {
 		.sirfsoc_rx_fifo_op	= 0x0130,
 		.sirfsoc_rx_fifo_op	= 0x0130,
 		.sirfsoc_rx_fifo_status	= 0x0134,
 		.sirfsoc_rx_fifo_status	= 0x0134,
 		.sirfsoc_rx_fifo_data	= 0x0138,
 		.sirfsoc_rx_fifo_data	= 0x0138,
+		.sirfsoc_int_en_clr_reg = 0x140,
 	},
 	},
 	.uart_int_en = {
 	.uart_int_en = {
 		.sirfsoc_rx_done_en	= BIT(0),
 		.sirfsoc_rx_done_en	= BIT(0),
@@ -177,14 +178,12 @@ struct sirfsoc_uart_register sirfsoc_usp = {
 		.sirfsoc_rxd_brk	= BIT(15),
 		.sirfsoc_rxd_brk	= BIT(15),
 	},
 	},
 	.fifo_status = {
 	.fifo_status = {
-		.ff_full		= usp_ff_full,
-		.ff_empty		= usp_ff_empty,
+		.ff_full		= uart_usp_ff_full_mask,
+		.ff_empty		= uart_usp_ff_empty_mask,
 	},
 	},
 	.uart_param = {
 	.uart_param = {
 		.uart_name = "ttySiRF",
 		.uart_name = "ttySiRF",
 		.port_name = "sirfsoc-uart",
 		.port_name = "sirfsoc-uart",
-		.uart_nr = 2,
-		.register_uart_nr = 3,
 	},
 	},
 };
 };
 
 
@@ -195,6 +194,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 		.sirfsoc_divisor	= 0x0050,
 		.sirfsoc_divisor	= 0x0050,
 		.sirfsoc_int_en_reg	= 0x0054,
 		.sirfsoc_int_en_reg	= 0x0054,
 		.sirfsoc_int_st_reg	= 0x0058,
 		.sirfsoc_int_st_reg	= 0x0058,
+		.sirfsoc_int_en_clr_reg	= 0x0060,
 		.sirfsoc_tx_dma_io_ctrl	= 0x0100,
 		.sirfsoc_tx_dma_io_ctrl	= 0x0100,
 		.sirfsoc_tx_dma_io_len	= 0x0104,
 		.sirfsoc_tx_dma_io_len	= 0x0104,
 		.sirfsoc_tx_fifo_ctrl	= 0x0108,
 		.sirfsoc_tx_fifo_ctrl	= 0x0108,
@@ -249,14 +249,12 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 		.sirfsoc_rts		= BIT(15),
 		.sirfsoc_rts		= BIT(15),
 	},
 	},
 	.fifo_status = {
 	.fifo_status = {
-		.ff_full		= uart_ff_full,
-		.ff_empty		= uart_ff_empty,
+		.ff_full		= uart_usp_ff_full_mask,
+		.ff_empty		= uart_usp_ff_empty_mask,
 	},
 	},
 	.uart_param = {
 	.uart_param = {
 		.uart_name = "ttySiRF",
 		.uart_name = "ttySiRF",
 		.port_name = "sirfsoc_uart",
 		.port_name = "sirfsoc_uart",
-		.uart_nr = 3,
-		.register_uart_nr = 0,
 	},
 	},
 };
 };
 /* uart io ctrl */
 /* uart io ctrl */
@@ -296,10 +294,10 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 
 
 #define SIRFUART_IO_MODE			BIT(0)
 #define SIRFUART_IO_MODE			BIT(0)
 #define SIRFUART_DMA_MODE			0x0
 #define SIRFUART_DMA_MODE			0x0
+#define SIRFUART_RX_DMA_FLUSH			0x4
 
 
-/* Macro Specific*/
-#define SIRFUART_INT_EN_CLR                    0x0060
 /* Baud Rate Calculation */
 /* Baud Rate Calculation */
+#define SIRF_USP_MIN_SAMPLE_DIV			0x1
 #define SIRF_MIN_SAMPLE_DIV			0xf
 #define SIRF_MIN_SAMPLE_DIV			0xf
 #define SIRF_MAX_SAMPLE_DIV			0x3f
 #define SIRF_MAX_SAMPLE_DIV			0x3f
 #define SIRF_IOCLK_DIV_MAX			0xffff
 #define SIRF_IOCLK_DIV_MAX			0xffff
@@ -326,55 +324,54 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 #define SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET	24
 #define SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET	24
 #define SIRFSOC_USP_ASYNC_DIV2_MASK		0x3f
 #define SIRFSOC_USP_ASYNC_DIV2_MASK		0x3f
 #define SIRFSOC_USP_ASYNC_DIV2_OFFSET		16
 #define SIRFSOC_USP_ASYNC_DIV2_OFFSET		16
-
+#define SIRFSOC_USP_LOOP_BACK_CTRL		BIT(2)
 /* USP-UART Common */
 /* USP-UART Common */
 #define SIRFSOC_UART_RX_TIMEOUT(br, to)	(((br) * (((to) + 999) / 1000)) / 1000)
 #define SIRFSOC_UART_RX_TIMEOUT(br, to)	(((br) * (((to) + 999) / 1000)) / 1000)
 #define SIRFUART_RECV_TIMEOUT_VALUE(x)	\
 #define SIRFUART_RECV_TIMEOUT_VALUE(x)	\
 				(((x) > 0xFFFF) ? 0xFFFF : ((x) & 0xFFFF))
 				(((x) > 0xFFFF) ? 0xFFFF : ((x) & 0xFFFF))
-#define SIRFUART_RECV_TIMEOUT(port, x)	\
-		(((port)->line > 2) ? (x & 0xFFFF) : ((x) & 0xFFFF) << 16)
+#define SIRFUART_USP_RECV_TIMEOUT(x)	(x & 0xFFFF)
+#define SIRFUART_UART_RECV_TIMEOUT(x)	((x & 0xFFFF) << 16)
 
 
-#define SIRFUART_FIFO_THD(port)		((port->line) == 1 ? 16 : 64)
-#define SIRFUART_ERR_INT_STAT(port, unit_st)			\
+#define SIRFUART_FIFO_THD(port)		(port->fifosize >> 1)
+#define SIRFUART_ERR_INT_STAT(unit_st, uart_type)			\
 				(uint_st->sirfsoc_rx_oflow |		\
 				(uint_st->sirfsoc_rx_oflow |		\
 				uint_st->sirfsoc_frm_err |		\
 				uint_st->sirfsoc_frm_err |		\
 				uint_st->sirfsoc_rxd_brk |		\
 				uint_st->sirfsoc_rxd_brk |		\
-		((port->line > 2) ? 0 : uint_st->sirfsoc_parity_err))
-#define SIRFUART_RX_IO_INT_EN(port, uint_en)				\
-				(uint_en->sirfsoc_rx_timeout_en |\
+				((uart_type != SIRF_REAL_UART) ? \
+				 0 : uint_st->sirfsoc_parity_err))
+#define SIRFUART_RX_IO_INT_EN(uint_en, uart_type)			\
+				(uint_en->sirfsoc_rx_done_en |\
 				 uint_en->sirfsoc_rxfifo_thd_en |\
 				 uint_en->sirfsoc_rxfifo_thd_en |\
 				 uint_en->sirfsoc_rxfifo_full_en |\
 				 uint_en->sirfsoc_rxfifo_full_en |\
 				 uint_en->sirfsoc_frm_err_en |\
 				 uint_en->sirfsoc_frm_err_en |\
 				 uint_en->sirfsoc_rx_oflow_en |\
 				 uint_en->sirfsoc_rx_oflow_en |\
 				 uint_en->sirfsoc_rxd_brk_en |\
 				 uint_en->sirfsoc_rxd_brk_en |\
-		((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en))
+				((uart_type != SIRF_REAL_UART) ? \
+				 0 : uint_en->sirfsoc_parity_err_en))
 #define SIRFUART_RX_IO_INT_ST(uint_st)				\
 #define SIRFUART_RX_IO_INT_ST(uint_st)				\
-				(uint_st->sirfsoc_rx_timeout |\
-				 uint_st->sirfsoc_rxfifo_thd |\
-				 uint_st->sirfsoc_rxfifo_full)
+				(uint_st->sirfsoc_rxfifo_thd |\
+				 uint_st->sirfsoc_rxfifo_full|\
+				 uint_st->sirfsoc_rx_done |\
+				 uint_st->sirfsoc_rx_timeout)
 #define SIRFUART_CTS_INT_ST(uint_st)	(uint_st->sirfsoc_cts)
 #define SIRFUART_CTS_INT_ST(uint_st)	(uint_st->sirfsoc_cts)
-#define SIRFUART_RX_DMA_INT_EN(port, uint_en)				\
-				(uint_en->sirfsoc_rx_timeout_en |\
-				 uint_en->sirfsoc_frm_err_en |\
+#define SIRFUART_RX_DMA_INT_EN(uint_en, uart_type)		\
+				(uint_en->sirfsoc_frm_err_en |\
 				 uint_en->sirfsoc_rx_oflow_en |\
 				 uint_en->sirfsoc_rx_oflow_en |\
 				 uint_en->sirfsoc_rxd_brk_en |\
 				 uint_en->sirfsoc_rxd_brk_en |\
-		((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en))
+				((uart_type != SIRF_REAL_UART) ? \
+				 0 : uint_en->sirfsoc_parity_err_en))
 /* Generic Definitions */
 /* Generic Definitions */
 #define SIRFSOC_UART_NAME			"ttySiRF"
 #define SIRFSOC_UART_NAME			"ttySiRF"
 #define SIRFSOC_UART_MAJOR			0
 #define SIRFSOC_UART_MAJOR			0
 #define SIRFSOC_UART_MINOR			0
 #define SIRFSOC_UART_MINOR			0
 #define SIRFUART_PORT_NAME			"sirfsoc-uart"
 #define SIRFUART_PORT_NAME			"sirfsoc-uart"
 #define SIRFUART_MAP_SIZE			0x200
 #define SIRFUART_MAP_SIZE			0x200
-#define SIRFSOC_UART_NR				6
+#define SIRFSOC_UART_NR				11
 #define SIRFSOC_PORT_TYPE			0xa5
 #define SIRFSOC_PORT_TYPE			0xa5
 
 
 /* Uart Common Use Macro*/
 /* Uart Common Use Macro*/
-#define SIRFSOC_RX_DMA_BUF_SIZE	256
+#define SIRFSOC_RX_DMA_BUF_SIZE		(1024 * 32)
 #define BYTES_TO_ALIGN(dma_addr)	((unsigned long)(dma_addr) & 0x3)
 #define BYTES_TO_ALIGN(dma_addr)	((unsigned long)(dma_addr) & 0x3)
-#define LOOP_DMA_BUFA_FILL	1
-#define LOOP_DMA_BUFB_FILL	2
-#define TX_TRAN_PIO		1
-#define TX_TRAN_DMA		2
 /* Uart Fifo Level Chk */
 /* Uart Fifo Level Chk */
 #define SIRFUART_TX_FIFO_SC_OFFSET	0
 #define SIRFUART_TX_FIFO_SC_OFFSET	0
 #define SIRFUART_TX_FIFO_LC_OFFSET	10
 #define SIRFUART_TX_FIFO_LC_OFFSET	10
@@ -389,8 +386,8 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 #define SIRFUART_RX_FIFO_CHK_SC SIRFUART_TX_FIFO_CHK_SC
 #define SIRFUART_RX_FIFO_CHK_SC SIRFUART_TX_FIFO_CHK_SC
 #define	SIRFUART_RX_FIFO_CHK_LC SIRFUART_TX_FIFO_CHK_LC
 #define	SIRFUART_RX_FIFO_CHK_LC SIRFUART_TX_FIFO_CHK_LC
 #define SIRFUART_RX_FIFO_CHK_HC SIRFUART_TX_FIFO_CHK_HC
 #define SIRFUART_RX_FIFO_CHK_HC SIRFUART_TX_FIFO_CHK_HC
+#define SIRFUART_RX_FIFO_MASK 0x7f
 /* Indicate how many buffers used */
 /* Indicate how many buffers used */
-#define SIRFSOC_RX_LOOP_BUF_CNT		2
 
 
 /* For Fast Baud Rate Calculation */
 /* For Fast Baud Rate Calculation */
 struct sirfsoc_baudrate_to_regv {
 struct sirfsoc_baudrate_to_regv {
@@ -404,7 +401,7 @@ enum sirfsoc_tx_state {
 	TX_DMA_PAUSE,
 	TX_DMA_PAUSE,
 };
 };
 
 
-struct sirfsoc_loop_buffer {
+struct sirfsoc_rx_buffer {
 	struct circ_buf			xmit;
 	struct circ_buf			xmit;
 	dma_cookie_t			cookie;
 	dma_cookie_t			cookie;
 	struct dma_async_tx_descriptor	*desc;
 	struct dma_async_tx_descriptor	*desc;
@@ -417,10 +414,6 @@ struct sirfsoc_uart_port {
 
 
 	struct uart_port		port;
 	struct uart_port		port;
 	struct clk			*clk;
 	struct clk			*clk;
-	/* UART6 for BT usage in A7DA platform need multi-clock source */
-	bool				is_bt_uart;
-	struct clk			*clk_general;
-	struct clk			*clk_noc;
 	/* for SiRFatlas7, there are SET/CLR for UART_INT_EN */
 	/* for SiRFatlas7, there are SET/CLR for UART_INT_EN */
 	bool				is_atlas7;
 	bool				is_atlas7;
 	struct sirfsoc_uart_register	*uart_reg;
 	struct sirfsoc_uart_register	*uart_reg;
@@ -428,17 +421,16 @@ struct sirfsoc_uart_port {
 	struct dma_chan			*tx_dma_chan;
 	struct dma_chan			*tx_dma_chan;
 	dma_addr_t			tx_dma_addr;
 	dma_addr_t			tx_dma_addr;
 	struct dma_async_tx_descriptor	*tx_dma_desc;
 	struct dma_async_tx_descriptor	*tx_dma_desc;
-	struct tasklet_struct		rx_dma_complete_tasklet;
-	struct tasklet_struct		rx_tmo_process_tasklet;
 	unsigned int			rx_io_count;
 	unsigned int			rx_io_count;
 	unsigned long			transfer_size;
 	unsigned long			transfer_size;
 	enum sirfsoc_tx_state		tx_dma_state;
 	enum sirfsoc_tx_state		tx_dma_state;
 	unsigned int			cts_gpio;
 	unsigned int			cts_gpio;
 	unsigned int			rts_gpio;
 	unsigned int			rts_gpio;
 
 
-	struct sirfsoc_loop_buffer	rx_dma_items[SIRFSOC_RX_LOOP_BUF_CNT];
-	int				rx_completed;
-	int				rx_issued;
+	struct sirfsoc_rx_buffer	rx_dma_items;
+	struct hrtimer			hrt;
+	bool				is_hrt_enabled;
+	unsigned long			rx_period_time;
 };
 };
 
 
 /* Register Access Control */
 /* Register Access Control */
@@ -447,10 +439,6 @@ struct sirfsoc_uart_port {
 #define wr_regl(port, reg, val)		__raw_writel(val, portaddr(port, reg))
 #define wr_regl(port, reg, val)		__raw_writel(val, portaddr(port, reg))
 
 
 /* UART Port Mask */
 /* UART Port Mask */
-#define SIRFUART_FIFOLEVEL_MASK(port)	((port->line == 1) ? (0x1f) : (0x7f))
-#define SIRFUART_FIFOFULL_MASK(port)	((port->line == 1) ? (0x20) : (0x80))
-#define SIRFUART_FIFOEMPTY_MASK(port)	((port->line == 1) ? (0x40) : (0x100))
-
-/* I/O Mode */
-#define SIRFSOC_UART_IO_RX_MAX_CNT		256
-#define SIRFSOC_UART_IO_TX_REASONABLE_CNT	256
+#define SIRFUART_FIFOLEVEL_MASK(port)	((port->fifosize - 1) & 0xFFF)
+#define SIRFUART_FIFOFULL_MASK(port)	(port->fifosize & 0xFFF)
+#define SIRFUART_FIFOEMPTY_MASK(port)	((port->fifosize & 0xFFF) << 1)

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

@@ -716,7 +716,7 @@ static int sprd_probe(struct platform_device *pdev)
 	up->flags = UPF_BOOT_AUTOCONF;
 	up->flags = UPF_BOOT_AUTOCONF;
 
 
 	clk = devm_clk_get(&pdev->dev, NULL);
 	clk = devm_clk_get(&pdev->dev, NULL);
-	if (!IS_ERR(clk))
+	if (!IS_ERR_OR_NULL(clk))
 		up->uartclk = clk_get_rate(clk);
 		up->uartclk = clk_get_rate(clk);
 
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

+ 739 - 0
drivers/tty/serial/stm32-usart.c

@@ -0,0 +1,739 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ *
+ * Inspired by st-asc.c from STMicroelectronics (c)
+ */
+
+#if defined(CONFIG_SERIAL_STM32_USART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/serial_core.h>
+#include <linux/clk.h>
+
+#define DRIVER_NAME "stm32-usart"
+
+/* Register offsets */
+#define USART_SR		0x00
+#define USART_DR		0x04
+#define USART_BRR		0x08
+#define USART_CR1		0x0c
+#define USART_CR2		0x10
+#define USART_CR3		0x14
+#define USART_GTPR		0x18
+
+/* USART_SR */
+#define USART_SR_PE		BIT(0)
+#define USART_SR_FE		BIT(1)
+#define USART_SR_NF		BIT(2)
+#define USART_SR_ORE		BIT(3)
+#define USART_SR_IDLE		BIT(4)
+#define USART_SR_RXNE		BIT(5)
+#define USART_SR_TC		BIT(6)
+#define USART_SR_TXE		BIT(7)
+#define USART_SR_LBD		BIT(8)
+#define USART_SR_CTS		BIT(9)
+#define USART_SR_ERR_MASK	(USART_SR_LBD | USART_SR_ORE | \
+				 USART_SR_FE | USART_SR_PE)
+/* Dummy bits */
+#define USART_SR_DUMMY_RX	BIT(16)
+
+/* USART_DR */
+#define USART_DR_MASK		GENMASK(8, 0)
+
+/* USART_BRR */
+#define USART_BRR_DIV_F_MASK	GENMASK(3, 0)
+#define USART_BRR_DIV_M_MASK	GENMASK(15, 4)
+#define USART_BRR_DIV_M_SHIFT	4
+
+/* USART_CR1 */
+#define USART_CR1_SBK		BIT(0)
+#define USART_CR1_RWU		BIT(1)
+#define USART_CR1_RE		BIT(2)
+#define USART_CR1_TE		BIT(3)
+#define USART_CR1_IDLEIE	BIT(4)
+#define USART_CR1_RXNEIE	BIT(5)
+#define USART_CR1_TCIE		BIT(6)
+#define USART_CR1_TXEIE		BIT(7)
+#define USART_CR1_PEIE		BIT(8)
+#define USART_CR1_PS		BIT(9)
+#define USART_CR1_PCE		BIT(10)
+#define USART_CR1_WAKE		BIT(11)
+#define USART_CR1_M		BIT(12)
+#define USART_CR1_UE		BIT(13)
+#define USART_CR1_OVER8		BIT(15)
+#define USART_CR1_IE_MASK	GENMASK(8, 4)
+
+/* USART_CR2 */
+#define USART_CR2_ADD_MASK	GENMASK(3, 0)
+#define USART_CR2_LBDL		BIT(5)
+#define USART_CR2_LBDIE		BIT(6)
+#define USART_CR2_LBCL		BIT(8)
+#define USART_CR2_CPHA		BIT(9)
+#define USART_CR2_CPOL		BIT(10)
+#define USART_CR2_CLKEN		BIT(11)
+#define USART_CR2_STOP_2B	BIT(13)
+#define USART_CR2_STOP_MASK	GENMASK(13, 12)
+#define USART_CR2_LINEN		BIT(14)
+
+/* USART_CR3 */
+#define USART_CR3_EIE		BIT(0)
+#define USART_CR3_IREN		BIT(1)
+#define USART_CR3_IRLP		BIT(2)
+#define USART_CR3_HDSEL		BIT(3)
+#define USART_CR3_NACK		BIT(4)
+#define USART_CR3_SCEN		BIT(5)
+#define USART_CR3_DMAR		BIT(6)
+#define USART_CR3_DMAT		BIT(7)
+#define USART_CR3_RTSE		BIT(8)
+#define USART_CR3_CTSE		BIT(9)
+#define USART_CR3_CTSIE		BIT(10)
+#define USART_CR3_ONEBIT	BIT(11)
+
+/* USART_GTPR */
+#define USART_GTPR_PSC_MASK	GENMASK(7, 0)
+#define USART_GTPR_GT_MASK	GENMASK(15, 8)
+
+#define DRIVER_NAME "stm32-usart"
+#define STM32_SERIAL_NAME "ttyS"
+#define STM32_MAX_PORTS 6
+
+struct stm32_port {
+	struct uart_port port;
+	struct clk *clk;
+	bool hw_flow_control;
+};
+
+static struct stm32_port stm32_ports[STM32_MAX_PORTS];
+static struct uart_driver stm32_usart_driver;
+
+static void stm32_stop_tx(struct uart_port *port);
+
+static inline struct stm32_port *to_stm32_port(struct uart_port *port)
+{
+	return container_of(port, struct stm32_port, port);
+}
+
+static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits)
+{
+	u32 val;
+
+	val = readl_relaxed(port->membase + reg);
+	val |= bits;
+	writel_relaxed(val, port->membase + reg);
+}
+
+static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits)
+{
+	u32 val;
+
+	val = readl_relaxed(port->membase + reg);
+	val &= ~bits;
+	writel_relaxed(val, port->membase + reg);
+}
+
+static void stm32_receive_chars(struct uart_port *port)
+{
+	struct tty_port *tport = &port->state->port;
+	unsigned long c;
+	u32 sr;
+	char flag;
+
+	if (port->irq_wake)
+		pm_wakeup_event(tport->tty->dev, 0);
+
+	while ((sr = readl_relaxed(port->membase + USART_SR)) & USART_SR_RXNE) {
+		sr |= USART_SR_DUMMY_RX;
+		c = readl_relaxed(port->membase + USART_DR);
+		flag = TTY_NORMAL;
+		port->icount.rx++;
+
+		if (sr & USART_SR_ERR_MASK) {
+			if (sr & USART_SR_LBD) {
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					continue;
+			} else if (sr & USART_SR_ORE) {
+				port->icount.overrun++;
+			} else if (sr & USART_SR_PE) {
+				port->icount.parity++;
+			} else if (sr & USART_SR_FE) {
+				port->icount.frame++;
+			}
+
+			sr &= port->read_status_mask;
+
+			if (sr & USART_SR_LBD)
+				flag = TTY_BREAK;
+			else if (sr & USART_SR_PE)
+				flag = TTY_PARITY;
+			else if (sr & USART_SR_FE)
+				flag = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char(port, c))
+			continue;
+		uart_insert_char(port, sr, USART_SR_ORE, c, flag);
+	}
+
+	spin_unlock(&port->lock);
+	tty_flip_buffer_push(tport);
+	spin_lock(&port->lock);
+}
+
+static void stm32_transmit_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+
+	if (port->x_char) {
+		writel_relaxed(port->x_char, port->membase + USART_DR);
+		port->x_char = 0;
+		port->icount.tx++;
+		return;
+	}
+
+	if (uart_tx_stopped(port)) {
+		stm32_stop_tx(port);
+		return;
+	}
+
+	if (uart_circ_empty(xmit)) {
+		stm32_stop_tx(port);
+		return;
+	}
+
+	writel_relaxed(xmit->buf[xmit->tail], port->membase + USART_DR);
+	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+	port->icount.tx++;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		stm32_stop_tx(port);
+}
+
+static irqreturn_t stm32_interrupt(int irq, void *ptr)
+{
+	struct uart_port *port = ptr;
+	u32 sr;
+
+	spin_lock(&port->lock);
+
+	sr = readl_relaxed(port->membase + USART_SR);
+
+	if (sr & USART_SR_RXNE)
+		stm32_receive_chars(port);
+
+	if (sr & USART_SR_TXE)
+		stm32_transmit_chars(port);
+
+	spin_unlock(&port->lock);
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int stm32_tx_empty(struct uart_port *port)
+{
+	return readl_relaxed(port->membase + USART_SR) & USART_SR_TXE;
+}
+
+static void stm32_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
+		stm32_set_bits(port, USART_CR3, USART_CR3_RTSE);
+	else
+		stm32_clr_bits(port, USART_CR3, USART_CR3_RTSE);
+}
+
+static unsigned int stm32_get_mctrl(struct uart_port *port)
+{
+	/* This routine is used to get signals of: DCD, DSR, RI, and CTS */
+	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* Transmit stop */
+static void stm32_stop_tx(struct uart_port *port)
+{
+	stm32_clr_bits(port, USART_CR1, USART_CR1_TXEIE);
+}
+
+/* There are probably characters waiting to be transmitted. */
+static void stm32_start_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+
+	if (uart_circ_empty(xmit))
+		return;
+
+	stm32_set_bits(port, USART_CR1, USART_CR1_TXEIE | USART_CR1_TE);
+}
+
+/* Throttle the remote when input buffer is about to overflow. */
+static void stm32_throttle(struct uart_port *port)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	stm32_clr_bits(port, USART_CR1, USART_CR1_RXNEIE);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Unthrottle the remote, the input buffer can now accept data. */
+static void stm32_unthrottle(struct uart_port *port)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	stm32_set_bits(port, USART_CR1, USART_CR1_RXNEIE);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Receive stop */
+static void stm32_stop_rx(struct uart_port *port)
+{
+	stm32_clr_bits(port, USART_CR1, USART_CR1_RXNEIE);
+}
+
+/* Handle breaks - ignored by us */
+static void stm32_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+static int stm32_startup(struct uart_port *port)
+{
+	const char *name = to_platform_device(port->dev)->name;
+	u32 val;
+	int ret;
+
+	ret = request_irq(port->irq, stm32_interrupt, IRQF_NO_SUSPEND,
+			  name, port);
+	if (ret)
+		return ret;
+
+	val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+	stm32_set_bits(port, USART_CR1, val);
+
+	return 0;
+}
+
+static void stm32_shutdown(struct uart_port *port)
+{
+	u32 val;
+
+	val = USART_CR1_TXEIE | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+	stm32_set_bits(port, USART_CR1, val);
+
+	free_irq(port->irq, port);
+}
+
+static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
+			    struct ktermios *old)
+{
+	struct stm32_port *stm32_port = to_stm32_port(port);
+	unsigned int baud;
+	u32 usartdiv, mantissa, fraction, oversampling;
+	tcflag_t cflag = termios->c_cflag;
+	u32 cr1, cr2, cr3;
+	unsigned long flags;
+
+	if (!stm32_port->hw_flow_control)
+		cflag &= ~CRTSCTS;
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 8);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Stop serial port and reset value */
+	writel_relaxed(0, port->membase + USART_CR1);
+
+	cr1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE | USART_CR1_RXNEIE;
+	cr2 = 0;
+	cr3 = 0;
+
+	if (cflag & CSTOPB)
+		cr2 |= USART_CR2_STOP_2B;
+
+	if (cflag & PARENB) {
+		cr1 |= USART_CR1_PCE;
+		if ((cflag & CSIZE) == CS8)
+			cr1 |= USART_CR1_M;
+	}
+
+	if (cflag & PARODD)
+		cr1 |= USART_CR1_PS;
+
+	port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS);
+	if (cflag & CRTSCTS) {
+		port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
+		cr3 |= USART_CR3_CTSE;
+	}
+
+	usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
+
+	/*
+	 * The USART supports 16 or 8 times oversampling.
+	 * By default we prefer 16 times oversampling, so that the receiver
+	 * has a better tolerance to clock deviations.
+	 * 8 times oversampling is only used to achieve higher speeds.
+	 */
+	if (usartdiv < 16) {
+		oversampling = 8;
+		stm32_set_bits(port, USART_CR1, USART_CR1_OVER8);
+	} else {
+		oversampling = 16;
+		stm32_clr_bits(port, USART_CR1, USART_CR1_OVER8);
+	}
+
+	mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT;
+	fraction = usartdiv % oversampling;
+	writel_relaxed(mantissa | fraction, port->membase + USART_BRR);
+
+	uart_update_timeout(port, cflag, baud);
+
+	port->read_status_mask = USART_SR_ORE;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= USART_SR_PE | USART_SR_FE;
+	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+		port->read_status_mask |= USART_SR_LBD;
+
+	/* Characters to ignore */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask = USART_SR_PE | USART_SR_FE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= USART_SR_LBD;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= USART_SR_ORE;
+	}
+
+	/* Ignore all characters if CREAD is not set */
+	if ((termios->c_cflag & CREAD) == 0)
+		port->ignore_status_mask |= USART_SR_DUMMY_RX;
+
+	writel_relaxed(cr3, port->membase + USART_CR3);
+	writel_relaxed(cr2, port->membase + USART_CR2);
+	writel_relaxed(cr1, port->membase + USART_CR1);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *stm32_type(struct uart_port *port)
+{
+	return (port->type == PORT_STM32) ? DRIVER_NAME : NULL;
+}
+
+static void stm32_release_port(struct uart_port *port)
+{
+}
+
+static int stm32_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void stm32_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_STM32;
+}
+
+static int
+stm32_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	/* No user changeable parameters */
+	return -EINVAL;
+}
+
+static void stm32_pm(struct uart_port *port, unsigned int state,
+		unsigned int oldstate)
+{
+	struct stm32_port *stm32port = container_of(port,
+			struct stm32_port, port);
+	unsigned long flags = 0;
+
+	switch (state) {
+	case UART_PM_STATE_ON:
+		clk_prepare_enable(stm32port->clk);
+		break;
+	case UART_PM_STATE_OFF:
+		spin_lock_irqsave(&port->lock, flags);
+		stm32_clr_bits(port, USART_CR1, USART_CR1_UE);
+		spin_unlock_irqrestore(&port->lock, flags);
+		clk_disable_unprepare(stm32port->clk);
+		break;
+	}
+}
+
+static const struct uart_ops stm32_uart_ops = {
+	.tx_empty	= stm32_tx_empty,
+	.set_mctrl	= stm32_set_mctrl,
+	.get_mctrl	= stm32_get_mctrl,
+	.stop_tx	= stm32_stop_tx,
+	.start_tx	= stm32_start_tx,
+	.throttle	= stm32_throttle,
+	.unthrottle	= stm32_unthrottle,
+	.stop_rx	= stm32_stop_rx,
+	.break_ctl	= stm32_break_ctl,
+	.startup	= stm32_startup,
+	.shutdown	= stm32_shutdown,
+	.set_termios	= stm32_set_termios,
+	.pm		= stm32_pm,
+	.type		= stm32_type,
+	.release_port	= stm32_release_port,
+	.request_port	= stm32_request_port,
+	.config_port	= stm32_config_port,
+	.verify_port	= stm32_verify_port,
+};
+
+static int stm32_init_port(struct stm32_port *stm32port,
+			  struct platform_device *pdev)
+{
+	struct uart_port *port = &stm32port->port;
+	struct resource *res;
+	int ret;
+
+	port->iotype	= UPIO_MEM;
+	port->flags	= UPF_BOOT_AUTOCONF;
+	port->ops	= &stm32_uart_ops;
+	port->dev	= &pdev->dev;
+	port->irq	= platform_get_irq(pdev, 0);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	port->membase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(port->membase))
+		return PTR_ERR(port->membase);
+	port->mapbase = res->start;
+
+	spin_lock_init(&port->lock);
+
+	stm32port->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(stm32port->clk))
+		return PTR_ERR(stm32port->clk);
+
+	/* Ensure that clk rate is correct by enabling the clk */
+	ret = clk_prepare_enable(stm32port->clk);
+	if (ret)
+		return ret;
+
+	stm32port->port.uartclk = clk_get_rate(stm32port->clk);
+	if (!stm32port->port.uartclk)
+		ret = -EINVAL;
+
+	clk_disable_unprepare(stm32port->clk);
+
+	return ret;
+}
+
+static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int id;
+
+	if (!np)
+		return NULL;
+
+	id = of_alias_get_id(np, "serial");
+	if (id < 0)
+		id = 0;
+
+	if (WARN_ON(id >= STM32_MAX_PORTS))
+		return NULL;
+
+	stm32_ports[id].hw_flow_control = of_property_read_bool(np,
+							"auto-flow-control");
+	stm32_ports[id].port.line = id;
+	return &stm32_ports[id];
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id stm32_match[] = {
+	{ .compatible = "st,stm32-usart", },
+	{ .compatible = "st,stm32-uart", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, stm32_match);
+#endif
+
+static int stm32_serial_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct stm32_port *stm32port;
+
+	stm32port = stm32_of_get_stm32_port(pdev);
+	if (!stm32port)
+		return -ENODEV;
+
+	ret = stm32_init_port(stm32port, pdev);
+	if (ret)
+		return ret;
+
+	ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, &stm32port->port);
+
+	return 0;
+}
+
+static int stm32_serial_remove(struct platform_device *pdev)
+{
+	struct uart_port *port = platform_get_drvdata(pdev);
+
+	return uart_remove_one_port(&stm32_usart_driver, port);
+}
+
+
+#ifdef CONFIG_SERIAL_STM32_CONSOLE
+static void stm32_console_putchar(struct uart_port *port, int ch)
+{
+	while (!(readl_relaxed(port->membase + USART_SR) & USART_SR_TXE))
+		cpu_relax();
+
+	writel_relaxed(ch, port->membase + USART_DR);
+}
+
+static void stm32_console_write(struct console *co, const char *s, unsigned cnt)
+{
+	struct uart_port *port = &stm32_ports[co->index].port;
+	unsigned long flags;
+	u32 old_cr1, new_cr1;
+	int locked = 1;
+
+	local_irq_save(flags);
+	if (port->sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock(&port->lock);
+	else
+		spin_lock(&port->lock);
+
+	/* Save and disable interrupts */
+	old_cr1 = readl_relaxed(port->membase + USART_CR1);
+	new_cr1 = old_cr1 & ~USART_CR1_IE_MASK;
+	writel_relaxed(new_cr1, port->membase + USART_CR1);
+
+	uart_console_write(port, s, cnt, stm32_console_putchar);
+
+	/* Restore interrupt state */
+	writel_relaxed(old_cr1, port->membase + USART_CR1);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
+}
+
+static int stm32_console_setup(struct console *co, char *options)
+{
+	struct stm32_port *stm32port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index >= STM32_MAX_PORTS)
+		return -ENODEV;
+
+	stm32port = &stm32_ports[co->index];
+
+	/*
+	 * This driver does not support early console initialization
+	 * (use ARM early printk support instead), so we only expect
+	 * this to be called during the uart port registration when the
+	 * driver gets probed and the port should be mapped at that point.
+	 */
+	if (stm32port->port.mapbase == 0 || stm32port->port.membase == NULL)
+		return -ENXIO;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&stm32port->port, co, baud, parity, bits, flow);
+}
+
+static struct console stm32_console = {
+	.name		= STM32_SERIAL_NAME,
+	.device		= uart_console_device,
+	.write		= stm32_console_write,
+	.setup		= stm32_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &stm32_usart_driver,
+};
+
+#define STM32_SERIAL_CONSOLE (&stm32_console)
+
+#else
+#define STM32_SERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_STM32_CONSOLE */
+
+static struct uart_driver stm32_usart_driver = {
+	.driver_name	= DRIVER_NAME,
+	.dev_name	= STM32_SERIAL_NAME,
+	.major		= 0,
+	.minor		= 0,
+	.nr		= STM32_MAX_PORTS,
+	.cons		= STM32_SERIAL_CONSOLE,
+};
+
+static struct platform_driver stm32_serial_driver = {
+	.probe		= stm32_serial_probe,
+	.remove		= stm32_serial_remove,
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.of_match_table = of_match_ptr(stm32_match),
+	},
+};
+
+static int __init usart_init(void)
+{
+	static char banner[] __initdata = "STM32 USART driver initialized";
+	int ret;
+
+	pr_info("%s\n", banner);
+
+	ret = uart_register_driver(&stm32_usart_driver);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&stm32_serial_driver);
+	if (ret)
+		uart_unregister_driver(&stm32_usart_driver);
+
+	return ret;
+}
+
+static void __exit usart_exit(void)
+{
+	platform_driver_unregister(&stm32_serial_driver);
+	uart_unregister_driver(&stm32_usart_driver);
+}
+
+module_init(usart_init);
+module_exit(usart_exit);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_DESCRIPTION("STMicroelectronics STM32 serial port driver");
+MODULE_LICENSE("GPL v2");

+ 2 - 1
drivers/tty/serial/xilinx_uartps.c

@@ -1075,7 +1075,8 @@ static void cdns_uart_console_putchar(struct uart_port *port, int ch)
 	writel(ch, port->membase + CDNS_UART_FIFO_OFFSET);
 	writel(ch, port->membase + CDNS_UART_FIFO_OFFSET);
 }
 }
 
 
-static void cdns_early_write(struct console *con, const char *s, unsigned n)
+static void __init cdns_early_write(struct console *con, const char *s,
+				    unsigned n)
 {
 {
 	struct earlycon_device *dev = con->data;
 	struct earlycon_device *dev = con->data;
 
 

+ 10 - 5
drivers/tty/synclink.c

@@ -4410,7 +4410,8 @@ static void synclink_cleanup(void)
 	printk("Unloading %s: %s\n", driver_name, driver_version);
 	printk("Unloading %s: %s\n", driver_name, driver_version);
 
 
 	if (serial_driver) {
 	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
+		rc = tty_unregister_driver(serial_driver);
+		if (rc)
 			printk("%s(%d) failed to unregister tty driver err=%d\n",
 			printk("%s(%d) failed to unregister tty driver err=%d\n",
 			       __FILE__,__LINE__,rc);
 			       __FILE__,__LINE__,rc);
 		put_tty_driver(serial_driver);
 		put_tty_driver(serial_driver);
@@ -7751,7 +7752,8 @@ static int hdlcdev_open(struct net_device *dev)
 		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
 		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
 
 
 	/* generic HDLC layer open processing */
 	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
+	rc = hdlc_open(dev);
+	if (rc)
 		return rc;
 		return rc;
 
 
 	/* arbitrate between network and tty opens */
 	/* arbitrate between network and tty opens */
@@ -8018,7 +8020,8 @@ static int hdlcdev_init(struct mgsl_struct *info)
 
 
 	/* allocate and initialize network and HDLC layer objects */
 	/* allocate and initialize network and HDLC layer objects */
 
 
-	if (!(dev = alloc_hdlcdev(info))) {
+	dev = alloc_hdlcdev(info);
+	if (!dev) {
 		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
 		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
@@ -8039,7 +8042,8 @@ static int hdlcdev_init(struct mgsl_struct *info)
 	hdlc->xmit   = hdlcdev_xmit;
 	hdlc->xmit   = hdlcdev_xmit;
 
 
 	/* register objects with HDLC layer */
 	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
+	rc = register_hdlc_device(dev);
+	if (rc) {
 		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
 		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
 		free_netdev(dev);
 		free_netdev(dev);
 		return rc;
 		return rc;
@@ -8075,7 +8079,8 @@ static int synclink_init_one (struct pci_dev *dev,
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
-	if (!(info = mgsl_allocate_device())) {
+	info = mgsl_allocate_device();
+	if (!info) {
 		printk("can't allocate device instance data.\n");
 		printk("can't allocate device instance data.\n");
 		return -EIO;
 		return -EIO;
 	}
 	}

+ 10 - 5
drivers/tty/synclink_gt.c

@@ -1539,7 +1539,8 @@ static int hdlcdev_open(struct net_device *dev)
 	DBGINFO(("%s hdlcdev_open\n", dev->name));
 	DBGINFO(("%s hdlcdev_open\n", dev->name));
 
 
 	/* generic HDLC layer open processing */
 	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
+	rc = hdlc_open(dev);
+	if (rc)
 		return rc;
 		return rc;
 
 
 	/* arbitrate between network and tty opens */
 	/* arbitrate between network and tty opens */
@@ -1803,7 +1804,8 @@ static int hdlcdev_init(struct slgt_info *info)
 
 
 	/* allocate and initialize network and HDLC layer objects */
 	/* allocate and initialize network and HDLC layer objects */
 
 
-	if (!(dev = alloc_hdlcdev(info))) {
+	dev = alloc_hdlcdev(info);
+	if (!dev) {
 		printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);
 		printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
@@ -1824,7 +1826,8 @@ static int hdlcdev_init(struct slgt_info *info)
 	hdlc->xmit   = hdlcdev_xmit;
 	hdlc->xmit   = hdlcdev_xmit;
 
 
 	/* register objects with HDLC layer */
 	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
+	rc = register_hdlc_device(dev);
+	if (rc) {
 		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
 		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
 		free_netdev(dev);
 		free_netdev(dev);
 		return rc;
 		return rc;
@@ -1879,7 +1882,8 @@ static void rx_async(struct slgt_info *info)
 
 
 			stat = 0;
 			stat = 0;
 
 
-			if ((status = *(p+1) & (BIT1 + BIT0))) {
+			status = *(p + 1) & (BIT1 + BIT0);
+			if (status) {
 				if (status & BIT1)
 				if (status & BIT1)
 					icount->parity++;
 					icount->parity++;
 				else if (status & BIT0)
 				else if (status & BIT0)
@@ -3755,7 +3759,8 @@ static void slgt_cleanup(void)
 	if (serial_driver) {
 	if (serial_driver) {
 		for (info=slgt_device_list ; info != NULL ; info=info->next_device)
 		for (info=slgt_device_list ; info != NULL ; info=info->next_device)
 			tty_unregister_device(serial_driver, info->line);
 			tty_unregister_device(serial_driver, info->line);
-		if ((rc = tty_unregister_driver(serial_driver)))
+		rc = tty_unregister_driver(serial_driver);
+		if (rc)
 			DBGERR(("tty_unregister_driver error=%d\n", rc));
 			DBGERR(("tty_unregister_driver error=%d\n", rc));
 		put_tty_driver(serial_driver);
 		put_tty_driver(serial_driver);
 	}
 	}

+ 8 - 4
drivers/tty/synclinkmp.c

@@ -1655,7 +1655,8 @@ static int hdlcdev_open(struct net_device *dev)
 		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
 		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
 
 
 	/* generic HDLC layer open processing */
 	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
+	rc = hdlc_open(dev);
+	if (rc)
 		return rc;
 		return rc;
 
 
 	/* arbitrate between network and tty opens */
 	/* arbitrate between network and tty opens */
@@ -1922,7 +1923,8 @@ static int hdlcdev_init(SLMP_INFO *info)
 
 
 	/* allocate and initialize network and HDLC layer objects */
 	/* allocate and initialize network and HDLC layer objects */
 
 
-	if (!(dev = alloc_hdlcdev(info))) {
+	dev = alloc_hdlcdev(info);
+	if (!dev) {
 		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
 		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
@@ -1943,7 +1945,8 @@ static int hdlcdev_init(SLMP_INFO *info)
 	hdlc->xmit   = hdlcdev_xmit;
 	hdlc->xmit   = hdlcdev_xmit;
 
 
 	/* register objects with HDLC layer */
 	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
+	rc = register_hdlc_device(dev);
+	if (rc) {
 		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
 		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
 		free_netdev(dev);
 		free_netdev(dev);
 		return rc;
 		return rc;
@@ -3920,7 +3923,8 @@ static void synclinkmp_cleanup(void)
 	printk("Unloading %s %s\n", driver_name, driver_version);
 	printk("Unloading %s %s\n", driver_name, driver_version);
 
 
 	if (serial_driver) {
 	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
+		rc = tty_unregister_driver(serial_driver);
+		if (rc)
 			printk("%s(%d) failed to unregister tty driver err=%d\n",
 			printk("%s(%d) failed to unregister tty driver err=%d\n",
 			       __FILE__,__LINE__,rc);
 			       __FILE__,__LINE__,rc);
 		put_tty_driver(serial_driver);
 		put_tty_driver(serial_driver);

+ 2 - 1
drivers/tty/tty_buffer.c

@@ -286,7 +286,8 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
 	change = (b->flags & TTYB_NORMAL) && (~flags & TTYB_NORMAL);
 	change = (b->flags & TTYB_NORMAL) && (~flags & TTYB_NORMAL);
 	if (change || left < size) {
 	if (change || left < size) {
 		/* This is the slow path - looking for new buffers to use */
 		/* This is the slow path - looking for new buffers to use */
-		if ((n = tty_buffer_alloc(port, size)) != NULL) {
+		n = tty_buffer_alloc(port, size);
+		if (n != NULL) {
 			n->flags = flags;
 			n->flags = flags;
 			buf->tail = n;
 			buf->tail = n;
 			b->commit = b->used;
 			b->commit = b->used;

+ 13 - 21
drivers/tty/tty_io.c

@@ -235,7 +235,6 @@ static void tty_del_file(struct file *file)
 /**
 /**
  *	tty_name	-	return tty naming
  *	tty_name	-	return tty naming
  *	@tty: tty structure
  *	@tty: tty structure
- *	@buf: buffer for output
  *
  *
  *	Convert a tty structure into a name. The name reflects the kernel
  *	Convert a tty structure into a name. The name reflects the kernel
  *	naming policy and if udev is in use may not reflect user space
  *	naming policy and if udev is in use may not reflect user space
@@ -243,13 +242,11 @@ static void tty_del_file(struct file *file)
  *	Locking: none
  *	Locking: none
  */
  */
 
 
-char *tty_name(struct tty_struct *tty, char *buf)
+const char *tty_name(const struct tty_struct *tty)
 {
 {
 	if (!tty) /* Hmm.  NULL pointer.  That's fun. */
 	if (!tty) /* Hmm.  NULL pointer.  That's fun. */
-		strcpy(buf, "NULL tty");
-	else
-		strcpy(buf, tty->name);
-	return buf;
+		return "NULL tty";
+	return tty->name;
 }
 }
 
 
 EXPORT_SYMBOL(tty_name);
 EXPORT_SYMBOL(tty_name);
@@ -770,8 +767,7 @@ static void do_tty_hangup(struct work_struct *work)
 void tty_hangup(struct tty_struct *tty)
 void tty_hangup(struct tty_struct *tty)
 {
 {
 #ifdef TTY_DEBUG_HANGUP
 #ifdef TTY_DEBUG_HANGUP
-	char	buf[64];
-	printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
+	printk(KERN_DEBUG "%s hangup...\n", tty_name(tty));
 #endif
 #endif
 	schedule_work(&tty->hangup_work);
 	schedule_work(&tty->hangup_work);
 }
 }
@@ -790,9 +786,7 @@ EXPORT_SYMBOL(tty_hangup);
 void tty_vhangup(struct tty_struct *tty)
 void tty_vhangup(struct tty_struct *tty)
 {
 {
 #ifdef TTY_DEBUG_HANGUP
 #ifdef TTY_DEBUG_HANGUP
-	char	buf[64];
-
-	printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
+	printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty));
 #endif
 #endif
 	__tty_hangup(tty, 0);
 	__tty_hangup(tty, 0);
 }
 }
@@ -831,9 +825,7 @@ void tty_vhangup_self(void)
 static void tty_vhangup_session(struct tty_struct *tty)
 static void tty_vhangup_session(struct tty_struct *tty)
 {
 {
 #ifdef TTY_DEBUG_HANGUP
 #ifdef TTY_DEBUG_HANGUP
-	char	buf[64];
-
-	printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty, buf));
+	printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty));
 #endif
 #endif
 	__tty_hangup(tty, 1);
 	__tty_hangup(tty, 1);
 }
 }
@@ -1769,7 +1761,6 @@ int tty_release(struct inode *inode, struct file *filp)
 	struct tty_struct *o_tty = NULL;
 	struct tty_struct *o_tty = NULL;
 	int	do_sleep, final;
 	int	do_sleep, final;
 	int	idx;
 	int	idx;
-	char	buf[64];
 	long	timeout = 0;
 	long	timeout = 0;
 	int	once = 1;
 	int	once = 1;
 
 
@@ -1793,7 +1784,7 @@ int tty_release(struct inode *inode, struct file *filp)
 
 
 #ifdef TTY_DEBUG_HANGUP
 #ifdef TTY_DEBUG_HANGUP
 	printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__,
 	printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__,
-			tty_name(tty, buf), tty->count);
+			tty_name(tty), tty->count);
 #endif
 #endif
 
 
 	if (tty->ops->close)
 	if (tty->ops->close)
@@ -1844,7 +1835,7 @@ int tty_release(struct inode *inode, struct file *filp)
 		if (once) {
 		if (once) {
 			once = 0;
 			once = 0;
 			printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
 			printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
-			       __func__, tty_name(tty, buf));
+			       __func__, tty_name(tty));
 		}
 		}
 		schedule_timeout_killable(timeout);
 		schedule_timeout_killable(timeout);
 		if (timeout < 120 * HZ)
 		if (timeout < 120 * HZ)
@@ -1856,13 +1847,13 @@ int tty_release(struct inode *inode, struct file *filp)
 	if (o_tty) {
 	if (o_tty) {
 		if (--o_tty->count < 0) {
 		if (--o_tty->count < 0) {
 			printk(KERN_WARNING "%s: bad pty slave count (%d) for %s\n",
 			printk(KERN_WARNING "%s: bad pty slave count (%d) for %s\n",
-				__func__, o_tty->count, tty_name(o_tty, buf));
+				__func__, o_tty->count, tty_name(o_tty));
 			o_tty->count = 0;
 			o_tty->count = 0;
 		}
 		}
 	}
 	}
 	if (--tty->count < 0) {
 	if (--tty->count < 0) {
 		printk(KERN_WARNING "%s: bad tty->count (%d) for %s\n",
 		printk(KERN_WARNING "%s: bad tty->count (%d) for %s\n",
-				__func__, tty->count, tty_name(tty, buf));
+				__func__, tty->count, tty_name(tty));
 		tty->count = 0;
 		tty->count = 0;
 	}
 	}
 
 
@@ -1905,7 +1896,7 @@ int tty_release(struct inode *inode, struct file *filp)
 		return 0;
 		return 0;
 
 
 #ifdef TTY_DEBUG_HANGUP
 #ifdef TTY_DEBUG_HANGUP
-	printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty, buf));
+	printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty));
 #endif
 #endif
 	/*
 	/*
 	 * Ask the line discipline code to release its structures
 	 * Ask the line discipline code to release its structures
@@ -1916,7 +1907,8 @@ int tty_release(struct inode *inode, struct file *filp)
 	tty_flush_works(tty);
 	tty_flush_works(tty);
 
 
 #ifdef TTY_DEBUG_HANGUP
 #ifdef TTY_DEBUG_HANGUP
-	printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__, tty_name(tty, buf));
+	printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__,
+	       tty_name(tty));
 #endif
 #endif
 	/*
 	/*
 	 * The release_tty function takes care of the details of clearing
 	 * The release_tty function takes care of the details of clearing

+ 1 - 3
drivers/tty/tty_ioctl.c

@@ -211,9 +211,7 @@ int tty_unthrottle_safe(struct tty_struct *tty)
 void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 {
 {
 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
-	char buf[64];
-
-	printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
+	printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty));
 #endif
 #endif
 	if (!timeout)
 	if (!timeout)
 		timeout = MAX_SCHEDULE_TIMEOUT;
 		timeout = MAX_SCHEDULE_TIMEOUT;

+ 3 - 5
drivers/tty/tty_ldisc.c

@@ -22,9 +22,8 @@
 #undef LDISC_DEBUG_HANGUP
 #undef LDISC_DEBUG_HANGUP
 
 
 #ifdef LDISC_DEBUG_HANGUP
 #ifdef LDISC_DEBUG_HANGUP
-#define tty_ldisc_debug(tty, f, args...) ({				       \
-	char __b[64];							       \
-	printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty, __b), ##args); \
+#define tty_ldisc_debug(tty, f, args...) ({				  \
+	printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty), ##args); \
 })
 })
 #else
 #else
 #define tty_ldisc_debug(tty, f, args...)
 #define tty_ldisc_debug(tty, f, args...)
@@ -483,7 +482,6 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
 
 
 static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 {
 {
-	char buf[64];
 	struct tty_ldisc *new_ldisc;
 	struct tty_ldisc *new_ldisc;
 	int r;
 	int r;
 
 
@@ -504,7 +502,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 		if (r < 0)
 		if (r < 0)
 			panic("Couldn't open N_TTY ldisc for "
 			panic("Couldn't open N_TTY ldisc for "
 			      "%s --- error %d.",
 			      "%s --- error %d.",
-			      tty_name(tty, buf), r);
+			      tty_name(tty), r);
 	}
 	}
 }
 }
 
 

+ 2 - 1
drivers/tty/tty_ldsem.c

@@ -299,7 +299,8 @@ down_write_failed(struct ld_semaphore *sem, long count, long timeout)
 		timeout = schedule_timeout(timeout);
 		timeout = schedule_timeout(timeout);
 		raw_spin_lock_irq(&sem->wait_lock);
 		raw_spin_lock_irq(&sem->wait_lock);
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if ((locked = writer_trylock(sem)))
+		locked = writer_trylock(sem);
+		if (locked)
 			break;
 			break;
 	}
 	}
 
 

+ 37 - 23
drivers/tty/vt/consolemap.c

@@ -261,19 +261,22 @@ u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
 	int m;
 	int m;
 	if (glyph < 0 || glyph >= MAX_GLYPH)
 	if (glyph < 0 || glyph >= MAX_GLYPH)
 		return 0;
 		return 0;
-	else if (!(p = *conp->vc_uni_pagedir_loc))
-		return glyph;
-	else if (use_unicode) {
-		if (!p->inverse_trans_unicode)
+	else {
+		p = *conp->vc_uni_pagedir_loc;
+		if (!p)
 			return glyph;
 			return glyph;
-		else
-			return p->inverse_trans_unicode[glyph];
-	} else {
-		m = inv_translate[conp->vc_num];
-		if (!p->inverse_translations[m])
-			return glyph;
-		else
-			return p->inverse_translations[m][glyph];
+		else if (use_unicode) {
+			if (!p->inverse_trans_unicode)
+				return glyph;
+			else
+				return p->inverse_trans_unicode[glyph];
+			} else {
+			m = inv_translate[conp->vc_num];
+			if (!p->inverse_translations[m])
+				return glyph;
+			else
+				return p->inverse_translations[m][glyph];
+			}
 	}
 	}
 }
 }
 EXPORT_SYMBOL_GPL(inverse_translate);
 EXPORT_SYMBOL_GPL(inverse_translate);
@@ -397,7 +400,8 @@ static void con_release_unimap(struct uni_pagedir *p)
 
 
 	if (p == dflt) dflt = NULL;  
 	if (p == dflt) dflt = NULL;  
 	for (i = 0; i < 32; i++) {
 	for (i = 0; i < 32; i++) {
-		if ((p1 = p->uni_pgdir[i]) != NULL) {
+		p1 = p->uni_pgdir[i];
+		if (p1 != NULL) {
 			for (j = 0; j < 32; j++)
 			for (j = 0; j < 32; j++)
 				kfree(p1[j]);
 				kfree(p1[j]);
 			kfree(p1);
 			kfree(p1);
@@ -473,14 +477,16 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
 	int i, n;
 	int i, n;
 	u16 **p1, *p2;
 	u16 **p1, *p2;
 
 
-	if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
+	p1 = p->uni_pgdir[n = unicode >> 11];
+	if (!p1) {
 		p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
 		p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
 		if (!p1) return -ENOMEM;
 		if (!p1) return -ENOMEM;
 		for (i = 0; i < 32; i++)
 		for (i = 0; i < 32; i++)
 			p1[i] = NULL;
 			p1[i] = NULL;
 	}
 	}
 
 
-	if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
+	p2 = p1[n = (unicode >> 6) & 0x1f];
+	if (!p2) {
 		p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
 		p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
 		if (!p2) return -ENOMEM;
 		if (!p2) return -ENOMEM;
 		memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
 		memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
@@ -569,10 +575,12 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
 		 * entries from "p" (old) to "q" (new).
 		 * entries from "p" (old) to "q" (new).
 		 */
 		 */
 		l = 0;		/* unicode value */
 		l = 0;		/* unicode value */
-		for (i = 0; i < 32; i++)
-		if ((p1 = p->uni_pgdir[i]))
-			for (j = 0; j < 32; j++)
-			if ((p2 = p1[j])) {
+		for (i = 0; i < 32; i++) {
+		p1 = p->uni_pgdir[i];
+		if (p1)
+			for (j = 0; j < 32; j++) {
+			p2 = p1[j];
+			if (p2) {
 				for (k = 0; k < 64; k++, l++)
 				for (k = 0; k < 64; k++, l++)
 				if (p2[k] != 0xffff) {
 				if (p2[k] != 0xffff) {
 					/*
 					/*
@@ -593,9 +601,11 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
 				/* Account for row of 64 empty entries */
 				/* Account for row of 64 empty entries */
 				l += 64;
 				l += 64;
 			}
 			}
+		}
 		else
 		else
 			/* Account for empty table */
 			/* Account for empty table */
 			l += 32 * 64;
 			l += 32 * 64;
+		}
 
 
 		/*
 		/*
 		 * Finished copying font table, set vc_uni_pagedir to new table
 		 * Finished copying font table, set vc_uni_pagedir to new table
@@ -735,10 +745,12 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
 	ect = 0;
 	ect = 0;
 	if (*vc->vc_uni_pagedir_loc) {
 	if (*vc->vc_uni_pagedir_loc) {
 		p = *vc->vc_uni_pagedir_loc;
 		p = *vc->vc_uni_pagedir_loc;
-		for (i = 0; i < 32; i++)
-		if ((p1 = p->uni_pgdir[i]))
-			for (j = 0; j < 32; j++)
-			if ((p2 = *(p1++)))
+		for (i = 0; i < 32; i++) {
+		p1 = p->uni_pgdir[i];
+		if (p1)
+			for (j = 0; j < 32; j++) {
+			p2 = *(p1++);
+			if (p2)
 				for (k = 0; k < 64; k++) {
 				for (k = 0; k < 64; k++) {
 					if (*p2 < MAX_GLYPH && ect++ < ct) {
 					if (*p2 < MAX_GLYPH && ect++ < ct) {
 						__put_user((u_short)((i<<11)+(j<<6)+k),
 						__put_user((u_short)((i<<11)+(j<<6)+k),
@@ -749,6 +761,8 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
 					}
 					}
 					p2++;
 					p2++;
 				}
 				}
+			}
+		}
 	}
 	}
 	__put_user(ect, uct);
 	__put_user(ect, uct);
 	console_unlock();
 	console_unlock();

+ 62 - 30
drivers/tty/vt/vt.c

@@ -108,6 +108,7 @@
 #define CON_DRIVER_FLAG_MODULE 1
 #define CON_DRIVER_FLAG_MODULE 1
 #define CON_DRIVER_FLAG_INIT   2
 #define CON_DRIVER_FLAG_INIT   2
 #define CON_DRIVER_FLAG_ATTR   4
 #define CON_DRIVER_FLAG_ATTR   4
+#define CON_DRIVER_FLAG_ZOMBIE 8
 
 
 struct con_driver {
 struct con_driver {
 	const struct consw *con;
 	const struct consw *con;
@@ -135,6 +136,7 @@ const struct consw *conswitchp;
  */
  */
 #define DEFAULT_BELL_PITCH	750
 #define DEFAULT_BELL_PITCH	750
 #define DEFAULT_BELL_DURATION	(HZ/8)
 #define DEFAULT_BELL_DURATION	(HZ/8)
+#define DEFAULT_CURSOR_BLINK_MS	200
 
 
 struct vc vc_cons [MAX_NR_CONSOLES];
 struct vc vc_cons [MAX_NR_CONSOLES];
 
 
@@ -153,6 +155,7 @@ static int set_vesa_blanking(char __user *p);
 static void set_cursor(struct vc_data *vc);
 static void set_cursor(struct vc_data *vc);
 static void hide_cursor(struct vc_data *vc);
 static void hide_cursor(struct vc_data *vc);
 static void console_callback(struct work_struct *ignored);
 static void console_callback(struct work_struct *ignored);
+static void con_driver_unregister_callback(struct work_struct *ignored);
 static void blank_screen_t(unsigned long dummy);
 static void blank_screen_t(unsigned long dummy);
 static void set_palette(struct vc_data *vc);
 static void set_palette(struct vc_data *vc);
 
 
@@ -182,6 +185,7 @@ static int blankinterval = 10*60;
 core_param(consoleblank, blankinterval, int, 0444);
 core_param(consoleblank, blankinterval, int, 0444);
 
 
 static DECLARE_WORK(console_work, console_callback);
 static DECLARE_WORK(console_work, console_callback);
+static DECLARE_WORK(con_driver_unregister_work, con_driver_unregister_callback);
 
 
 /*
 /*
  * fg_console is the current virtual console,
  * fg_console is the current virtual console,
@@ -1590,6 +1594,13 @@ static void setterm_command(struct vc_data *vc)
 		case 15: /* activate the previous console */
 		case 15: /* activate the previous console */
 			set_console(last_console);
 			set_console(last_console);
 			break;
 			break;
+		case 16: /* set cursor blink duration in msec */
+			if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 &&
+					vc->vc_par[1] <= USHRT_MAX)
+				vc->vc_cur_blink_ms = vc->vc_par[1];
+			else
+				vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
+			break;
 	}
 	}
 }
 }
 
 
@@ -1717,6 +1728,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
 
 
 	vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
 	vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
 	vc->vc_bell_duration = DEFAULT_BELL_DURATION;
 	vc->vc_bell_duration = DEFAULT_BELL_DURATION;
+	vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
 
 
 	gotoxy(vc, 0, 0);
 	gotoxy(vc, 0, 0);
 	save_cur(vc);
 	save_cur(vc);
@@ -3192,22 +3204,6 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last,
 
 
 
 
 #ifdef CONFIG_VT_HW_CONSOLE_BINDING
 #ifdef CONFIG_VT_HW_CONSOLE_BINDING
-static int con_is_graphics(const struct consw *csw, int first, int last)
-{
-	int i, retval = 0;
-
-	for (i = first; i <= last; i++) {
-		struct vc_data *vc = vc_cons[i].d;
-
-		if (vc && vc->vc_mode == KD_GRAPHICS) {
-			retval = 1;
-			break;
-		}
-	}
-
-	return retval;
-}
-
 /* unlocked version of unbind_con_driver() */
 /* unlocked version of unbind_con_driver() */
 int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
 int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
 {
 {
@@ -3293,8 +3289,7 @@ static int vt_bind(struct con_driver *con)
 	const struct consw *defcsw = NULL, *csw = NULL;
 	const struct consw *defcsw = NULL, *csw = NULL;
 	int i, more = 1, first = -1, last = -1, deflt = 0;
 	int i, more = 1, first = -1, last = -1, deflt = 0;
 
 
- 	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
-	    con_is_graphics(con->con, con->first, con->last))
+ 	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE))
 		goto err;
 		goto err;
 
 
 	csw = con->con;
 	csw = con->con;
@@ -3345,8 +3340,7 @@ static int vt_unbind(struct con_driver *con)
 	int i, more = 1, first = -1, last = -1, deflt = 0;
 	int i, more = 1, first = -1, last = -1, deflt = 0;
 	int ret;
 	int ret;
 
 
- 	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
-	    con_is_graphics(con->con, con->first, con->last))
+ 	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE))
 		goto err;
 		goto err;
 
 
 	csw = con->con;
 	csw = con->con;
@@ -3596,7 +3590,8 @@ static int do_register_con_driver(const struct consw *csw, int first, int last)
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
 		con_driver = &registered_con_driver[i];
 		con_driver = &registered_con_driver[i];
 
 
-		if (con_driver->con == NULL) {
+		if (con_driver->con == NULL &&
+		    !(con_driver->flag & CON_DRIVER_FLAG_ZOMBIE)) {
 			con_driver->con = csw;
 			con_driver->con = csw;
 			con_driver->desc = desc;
 			con_driver->desc = desc;
 			con_driver->node = i;
 			con_driver->node = i;
@@ -3658,16 +3653,20 @@ int do_unregister_con_driver(const struct consw *csw)
 		struct con_driver *con_driver = &registered_con_driver[i];
 		struct con_driver *con_driver = &registered_con_driver[i];
 
 
 		if (con_driver->con == csw) {
 		if (con_driver->con == csw) {
-			vtconsole_deinit_device(con_driver);
-			device_destroy(vtconsole_class,
-				       MKDEV(0, con_driver->node));
+			/*
+			 * Defer the removal of the sysfs entries since that
+			 * will acquire the kernfs s_active lock and we can't
+			 * acquire this lock while holding the console lock:
+			 * the unbind sysfs entry imposes already the opposite
+			 * order. Reset con already here to prevent any later
+			 * lookup to succeed and mark this slot as zombie, so
+			 * it won't get reused until we complete the removal
+			 * in the deferred work.
+			 */
 			con_driver->con = NULL;
 			con_driver->con = NULL;
-			con_driver->desc = NULL;
-			con_driver->dev = NULL;
-			con_driver->node = 0;
-			con_driver->flag = 0;
-			con_driver->first = 0;
-			con_driver->last = 0;
+			con_driver->flag = CON_DRIVER_FLAG_ZOMBIE;
+			schedule_work(&con_driver_unregister_work);
+
 			return 0;
 			return 0;
 		}
 		}
 	}
 	}
@@ -3676,6 +3675,39 @@ int do_unregister_con_driver(const struct consw *csw)
 }
 }
 EXPORT_SYMBOL_GPL(do_unregister_con_driver);
 EXPORT_SYMBOL_GPL(do_unregister_con_driver);
 
 
+static void con_driver_unregister_callback(struct work_struct *ignored)
+{
+	int i;
+
+	console_lock();
+
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		struct con_driver *con_driver = &registered_con_driver[i];
+
+		if (!(con_driver->flag & CON_DRIVER_FLAG_ZOMBIE))
+			continue;
+
+		console_unlock();
+
+		vtconsole_deinit_device(con_driver);
+		device_destroy(vtconsole_class, MKDEV(0, con_driver->node));
+
+		console_lock();
+
+		if (WARN_ON_ONCE(con_driver->con))
+			con_driver->con = NULL;
+		con_driver->desc = NULL;
+		con_driver->dev = NULL;
+		con_driver->node = 0;
+		WARN_ON_ONCE(con_driver->flag != CON_DRIVER_FLAG_ZOMBIE);
+		con_driver->flag = 0;
+		con_driver->first = 0;
+		con_driver->last = 0;
+	}
+
+	console_unlock();
+}
+
 /*
 /*
  *	If we support more console drivers, this function is used
  *	If we support more console drivers, this function is used
  *	when a driver wants to take over some existing consoles
  *	when a driver wants to take over some existing consoles

+ 3 - 2
drivers/video/console/fbcon.c

@@ -402,7 +402,7 @@ static void cursor_timer_handler(unsigned long dev_addr)
 	struct fbcon_ops *ops = info->fbcon_par;
 	struct fbcon_ops *ops = info->fbcon_par;
 
 
 	queue_work(system_power_efficient_wq, &info->queue);
 	queue_work(system_power_efficient_wq, &info->queue);
-	mod_timer(&ops->cursor_timer, jiffies + HZ/5);
+	mod_timer(&ops->cursor_timer, jiffies + ops->cur_blink_jiffies);
 }
 }
 
 
 static void fbcon_add_cursor_timer(struct fb_info *info)
 static void fbcon_add_cursor_timer(struct fb_info *info)
@@ -417,7 +417,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info)
 
 
 		init_timer(&ops->cursor_timer);
 		init_timer(&ops->cursor_timer);
 		ops->cursor_timer.function = cursor_timer_handler;
 		ops->cursor_timer.function = cursor_timer_handler;
-		ops->cursor_timer.expires = jiffies + HZ / 5;
+		ops->cursor_timer.expires = jiffies + ops->cur_blink_jiffies;
 		ops->cursor_timer.data = (unsigned long ) info;
 		ops->cursor_timer.data = (unsigned long ) info;
 		add_timer(&ops->cursor_timer);
 		add_timer(&ops->cursor_timer);
 		ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
 		ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
@@ -1309,6 +1309,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 	if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
 	if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
 		return;
 		return;
 
 
+	ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
 	if (vc->vc_cursor_type & 0x10)
 	if (vc->vc_cursor_type & 0x10)
 		fbcon_del_cursor_timer(info);
 		fbcon_del_cursor_timer(info);
 	else
 	else

+ 1 - 0
drivers/video/console/fbcon.h

@@ -70,6 +70,7 @@ struct fbcon_ops {
 	struct fb_cursor cursor_state;
 	struct fb_cursor cursor_state;
 	struct display *p;
 	struct display *p;
         int    currcon;	                /* Current VC. */
         int    currcon;	                /* Current VC. */
+	int    cur_blink_jiffies;
 	int    cursor_flash;
 	int    cursor_flash;
 	int    cursor_reset;
 	int    cursor_reset;
 	int    blank_state;
 	int    blank_state;

+ 1 - 0
include/linux/console_struct.h

@@ -104,6 +104,7 @@ struct vc_data {
 	unsigned int    vc_resize_user;         /* resize request from user */
 	unsigned int    vc_resize_user;         /* resize request from user */
 	unsigned int	vc_bell_pitch;		/* Console bell pitch */
 	unsigned int	vc_bell_pitch;		/* Console bell pitch */
 	unsigned int	vc_bell_duration;	/* Console bell duration */
 	unsigned int	vc_bell_duration;	/* Console bell duration */
+	unsigned short	vc_cur_blink_ms;	/* Cursor blink duration */
 	struct vc_data **vc_display_fg;		/* [!] Ptr to var holding fg console for this display */
 	struct vc_data **vc_display_fg;		/* [!] Ptr to var holding fg console for this display */
 	struct uni_pagedir *vc_uni_pagedir;
 	struct uni_pagedir *vc_uni_pagedir;
 	struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
 	struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */

+ 3 - 0
include/linux/serial_8250.h

@@ -12,6 +12,7 @@
 #define _LINUX_SERIAL_8250_H
 #define _LINUX_SERIAL_8250_H
 
 
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
+#include <linux/serial_reg.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 
 
 /*
 /*
@@ -137,6 +138,8 @@ extern int early_serial_setup(struct uart_port *port);
 
 
 extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
 extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
 extern void serial8250_early_out(struct uart_port *port, int offset, int value);
 extern void serial8250_early_out(struct uart_port *port, int offset, int value);
+extern int early_serial8250_setup(struct earlycon_device *device,
+					 const char *options);
 extern void serial8250_do_set_termios(struct uart_port *port,
 extern void serial8250_do_set_termios(struct uart_port *port,
 		struct ktermios *termios, struct ktermios *old);
 		struct ktermios *termios, struct ktermios *old);
 extern int serial8250_do_startup(struct uart_port *port);
 extern int serial8250_do_startup(struct uart_port *port);

+ 1 - 1
include/linux/serial_core.h

@@ -35,7 +35,7 @@
 #define uart_console(port) \
 #define uart_console(port) \
 	((port)->cons && (port)->cons->index == (port)->line)
 	((port)->cons && (port)->cons->index == (port)->line)
 #else
 #else
-#define uart_console(port)      (0)
+#define uart_console(port)      ({ (void)port; 0; })
 #endif
 #endif
 
 
 struct uart_port;
 struct uart_port;

+ 11 - 75
include/linux/serial_sci.h

@@ -1,6 +1,7 @@
 #ifndef __LINUX_SERIAL_SCI_H
 #ifndef __LINUX_SERIAL_SCI_H
 #define __LINUX_SERIAL_SCI_H
 #define __LINUX_SERIAL_SCI_H
 
 
+#include <linux/bitops.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_dma.h>
 
 
@@ -10,59 +11,16 @@
 
 
 #define SCIx_NOT_SUPPORTED	(-1)
 #define SCIx_NOT_SUPPORTED	(-1)
 
 
-/* SCSMR (Serial Mode Register) */
-#define SCSMR_CHR	(1 << 6)	/* 7-bit Character Length */
-#define SCSMR_PE	(1 << 5)	/* Parity Enable */
-#define SCSMR_ODD	(1 << 4)	/* Odd Parity */
-#define SCSMR_STOP	(1 << 3)	/* Stop Bit Length */
-#define SCSMR_CKS	0x0003		/* Clock Select */
-
 /* Serial Control Register (@ = not supported by all parts) */
 /* Serial Control Register (@ = not supported by all parts) */
-#define SCSCR_TIE	(1 << 7)	/* Transmit Interrupt Enable */
-#define SCSCR_RIE	(1 << 6)	/* Receive Interrupt Enable */
-#define SCSCR_TE	(1 << 5)	/* Transmit Enable */
-#define SCSCR_RE	(1 << 4)	/* Receive Enable */
-#define SCSCR_REIE	(1 << 3)	/* Receive Error Interrupt Enable @ */
-#define SCSCR_TOIE	(1 << 2)	/* Timeout Interrupt Enable @ */
-#define SCSCR_CKE1	(1 << 1)	/* Clock Enable 1 */
-#define SCSCR_CKE0	(1 << 0)	/* Clock Enable 0 */
-/* SCIFA/SCIFB only */
-#define SCSCR_TDRQE	(1 << 15)	/* Tx Data Transfer Request Enable */
-#define SCSCR_RDRQE	(1 << 14)	/* Rx Data Transfer Request Enable */
-
-/* SCxSR (Serial Status Register) on SCI */
-#define SCI_TDRE  0x80			/* Transmit Data Register Empty */
-#define SCI_RDRF  0x40			/* Receive Data Register Full */
-#define SCI_ORER  0x20			/* Overrun Error */
-#define SCI_FER   0x10			/* Framing Error */
-#define SCI_PER   0x08			/* Parity Error */
-#define SCI_TEND  0x04			/* Transmit End */
-
-#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
-
-/* SCxSR (Serial Status Register) on SCIF, HSCIF */
-#define SCIF_ER    0x0080		/* Receive Error */
-#define SCIF_TEND  0x0040		/* Transmission End */
-#define SCIF_TDFE  0x0020		/* Transmit FIFO Data Empty */
-#define SCIF_BRK   0x0010		/* Break Detect */
-#define SCIF_FER   0x0008		/* Framing Error */
-#define SCIF_PER   0x0004		/* Parity Error */
-#define SCIF_RDF   0x0002		/* Receive FIFO Data Full */
-#define SCIF_DR    0x0001		/* Receive Data Ready */
-
-#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
-
-/* SCFCR (FIFO Control Register) */
-#define SCFCR_LOOP	(1 << 0)	/* Loopback Test */
-
-/* SCSPTR (Serial Port Register), optional */
-#define SCSPTR_RTSIO	(1 << 7)	/* Serial Port RTS Pin Input/Output */
-#define SCSPTR_CTSIO	(1 << 5)	/* Serial Port CTS Pin Input/Output */
-#define SCSPTR_SPB2IO	(1 << 1)	/* Serial Port Break Input/Output */
-#define SCSPTR_SPB2DT	(1 << 0)	/* Serial Port Break Data */
-
-/* HSSRR HSCIF */
-#define HSCIF_SRE	0x8000		/* Sampling Rate Register Enable */
+#define SCSCR_TIE	BIT(7)	/* Transmit Interrupt Enable */
+#define SCSCR_RIE	BIT(6)	/* Receive Interrupt Enable */
+#define SCSCR_TE	BIT(5)	/* Transmit Enable */
+#define SCSCR_RE	BIT(4)	/* Receive Enable */
+#define SCSCR_REIE	BIT(3)	/* Receive Error Interrupt Enable @ */
+#define SCSCR_TOIE	BIT(2)	/* Timeout Interrupt Enable @ */
+#define SCSCR_CKE1	BIT(1)	/* Clock Enable 1 */
+#define SCSCR_CKE0	BIT(0)	/* Clock Enable 0 */
+
 
 
 enum {
 enum {
 	SCIx_PROBE_REGTYPE,
 	SCIx_PROBE_REGTYPE,
@@ -82,28 +40,6 @@ enum {
 	SCIx_NR_REGTYPES,
 	SCIx_NR_REGTYPES,
 };
 };
 
 
-/*
- * SCI register subset common for all port types.
- * Not all registers will exist on all parts.
- */
-enum {
-	SCSMR,				/* Serial Mode Register */
-	SCBRR,				/* Bit Rate Register */
-	SCSCR,				/* Serial Control Register */
-	SCxSR,				/* Serial Status Register */
-	SCFCR,				/* FIFO Control Register */
-	SCFDR,				/* FIFO Data Count Register */
-	SCxTDR,				/* Transmit (FIFO) Data Register */
-	SCxRDR,				/* Receive (FIFO) Data Register */
-	SCLSR,				/* Line Status Register */
-	SCTFDR,				/* Transmit FIFO Data Count Register */
-	SCRFDR,				/* Receive FIFO Data Count Register */
-	SCSPTR,				/* Serial Port Register */
-	HSSRR,				/* Sampling Rate Register */
-
-	SCIx_NR_REGS,
-};
-
 struct device;
 struct device;
 
 
 struct plat_sci_port_ops {
 struct plat_sci_port_ops {
@@ -113,7 +49,7 @@ struct plat_sci_port_ops {
 /*
 /*
  * Port-specific capabilities
  * Port-specific capabilities
  */
  */
-#define SCIx_HAVE_RTSCTS	(1 << 0)
+#define SCIx_HAVE_RTSCTS	BIT(0)
 
 
 /*
 /*
  * Platform device specific platform_data struct
  * Platform device specific platform_data struct

+ 1 - 1
include/linux/tty.h

@@ -422,7 +422,7 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty)
 
 
 extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
 extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
 			      const char *routine);
 			      const char *routine);
-extern char *tty_name(struct tty_struct *tty, char *buf);
+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);
 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);

+ 1 - 0
include/uapi/linux/Kbuild

@@ -138,6 +138,7 @@ header-y += genetlink.h
 header-y += gen_stats.h
 header-y += gen_stats.h
 header-y += gfs2_ondisk.h
 header-y += gfs2_ondisk.h
 header-y += gigaset_dev.h
 header-y += gigaset_dev.h
+header-y += gsmmux.h
 header-y += hdlcdrv.h
 header-y += hdlcdrv.h
 header-y += hdlc.h
 header-y += hdlc.h
 header-y += hdreg.h
 header-y += hdreg.h

+ 3 - 0
include/linux/gsmmux.h → include/uapi/linux/gsmmux.h

@@ -1,6 +1,9 @@
 #ifndef _LINUX_GSMMUX_H
 #ifndef _LINUX_GSMMUX_H
 #define _LINUX_GSMMUX_H
 #define _LINUX_GSMMUX_H
 
 
+#include <linux/if.h>
+#include <linux/ioctl.h>
+
 struct gsm_config
 struct gsm_config
 {
 {
 	unsigned int adaption;
 	unsigned int adaption;

+ 3 - 0
include/uapi/linux/serial_core.h

@@ -258,4 +258,7 @@
 /* Cris v10 / v32 SoC */
 /* Cris v10 / v32 SoC */
 #define PORT_CRIS	112
 #define PORT_CRIS	112
 
 
+/* STM32 USART */
+#define PORT_STM32	113
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
 #endif /* _UAPILINUX_SERIAL_CORE_H */

+ 1 - 1
include/uapi/linux/tty_flags.h

@@ -15,7 +15,7 @@
 #define ASYNCB_FOURPORT		 1 /* Set OU1, OUT2 per AST Fourport settings */
 #define ASYNCB_FOURPORT		 1 /* Set OU1, OUT2 per AST Fourport settings */
 #define ASYNCB_SAK		 2 /* Secure Attention Key (Orange book) */
 #define ASYNCB_SAK		 2 /* Secure Attention Key (Orange book) */
 #define ASYNCB_SPLIT_TERMIOS	 3 /* [x] Separate termios for dialin/callout */
 #define ASYNCB_SPLIT_TERMIOS	 3 /* [x] Separate termios for dialin/callout */
-#define ASYNCB_SPD_HI		 4 /* Use 56000 instead of 38400 bps */
+#define ASYNCB_SPD_HI		 4 /* Use 57600 instead of 38400 bps */
 #define ASYNCB_SPD_VHI		 5 /* Use 115200 instead of 38400 bps */
 #define ASYNCB_SPD_VHI		 5 /* Use 115200 instead of 38400 bps */
 #define ASYNCB_SKIP_TEST	 6 /* Skip UART test during autoconfiguration */
 #define ASYNCB_SKIP_TEST	 6 /* Skip UART test during autoconfiguration */
 #define ASYNCB_AUTO_IRQ		 7 /* Do automatic IRQ during
 #define ASYNCB_AUTO_IRQ		 7 /* Do automatic IRQ during