Browse Source

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

Pull tty/serial driver updates from Greg KH:
 "Here is the big tty/serial driver patchset for 4.11-rc1.

  Not much here, but a lot of little fixes and individual serial driver
  updates all over the subsystem. Majority are for the sh-sci driver and
  platform (the arch-specific changes have acks from the maintainer).

  The start of the "serial bus" code is here as well, but nothing is
  converted to use it yet. That work is still ongoing, hopefully will
  start to show up across different subsystems for 4.12 (bluetooth is
  one major place that will be used.)

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

* tag 'tty-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (109 commits)
  tty: pl011: Work around QDF2400 E44 stuck BUSY bit
  atmel_serial: Use the fractional divider when possible
  tty: Remove extra include in HVC console tty framework
  serial: exar: Enable MSI support
  serial: exar: Move register defines from uapi header to consumer site
  serial: pci: Remove unused pci_boards entries
  serial: exar: Move Commtech adapters to 8250_exar as well
  serial: exar: Fix feature control register constants
  serial: exar: Fix initialization of EXAR registers for ports > 0
  serial: exar: Fix mapping of port I/O resources
  serial: sh-sci: fix hardware RX trigger level setting
  tty/serial: atmel: ensure state is restored after suspending
  serial: 8250_dw: Avoid "too much work" from bogus rx timeout interrupt
  serdev: ttyport: check whether tty_init_dev() fails
  serial: 8250_pci: make pciserial_detach_ports() static
  ARM: dts: STiH410-b2260: Enable HW flow-control
  ARM: dts: STiH407-family: Use new Pinctrl groups
  ARM: dts: STiH407-pinctrl: Add Pinctrl group for HW flow-control
  ARM: dts: STiH410-b2260: Identify the UART RTS line
  dt-bindings: serial: Update 'uart-has-rtscts' description
  ...
Linus Torvalds 8 years ago
parent
commit
37c85961c3
100 changed files with 2513 additions and 1503 deletions
  1. 6 0
      Documentation/admin-guide/kernel-parameters.txt
  2. 1 0
      Documentation/devicetree/bindings/serial/8250.txt
  3. 2 1
      Documentation/devicetree/bindings/serial/serial.txt
  4. 36 0
      Documentation/devicetree/bindings/serial/slave-device.txt
  5. 8 0
      MAINTAINERS
  6. 1 2
      arch/arm/boot/dts/stih407-family.dtsi
  7. 10 2
      arch/arm/boot/dts/stih407-pinctrl.dtsi
  8. 5 0
      arch/arm/boot/dts/stih410-b2260.dts
  9. 3 6
      arch/sh/kernel/cpu/sh2/setup-sh7619.c
  10. 1 2
      arch/sh/kernel/cpu/sh2a/setup-mxg.c
  11. 8 16
      arch/sh/kernel/cpu/sh2a/setup-sh7201.c
  12. 4 12
      arch/sh/kernel/cpu/sh2a/setup-sh7203.c
  13. 4 8
      arch/sh/kernel/cpu/sh2a/setup-sh7206.c
  14. 8 24
      arch/sh/kernel/cpu/sh2a/setup-sh7264.c
  15. 8 24
      arch/sh/kernel/cpu/sh2a/setup-sh7269.c
  16. 1 5
      arch/sh/kernel/cpu/sh3/setup-sh7705.c
  17. 0 10
      arch/sh/kernel/cpu/sh3/setup-sh770x.c
  18. 2 6
      arch/sh/kernel/cpu/sh3/setup-sh7710.c
  19. 0 4
      arch/sh/kernel/cpu/sh3/setup-sh7720.c
  20. 1 2
      arch/sh/kernel/cpu/sh4/setup-sh4-202.c
  21. 2 7
      arch/sh/kernel/cpu/sh4/setup-sh7750.c
  22. 11 10
      arch/sh/kernel/cpu/sh4/setup-sh7760.c
  23. 4 8
      arch/sh/kernel/cpu/sh4a/setup-sh7343.c
  24. 1 3
      arch/sh/kernel/cpu/sh4a/setup-sh7366.c
  25. 3 6
      arch/sh/kernel/cpu/sh4a/setup-sh7722.c
  26. 3 18
      arch/sh/kernel/cpu/sh4a/setup-sh7723.c
  27. 3 18
      arch/sh/kernel/cpu/sh4a/setup-sh7724.c
  28. 6 12
      arch/sh/kernel/cpu/sh4a/setup-sh7734.c
  29. 3 6
      arch/sh/kernel/cpu/sh4a/setup-sh7757.c
  30. 3 6
      arch/sh/kernel/cpu/sh4a/setup-sh7763.c
  31. 10 20
      arch/sh/kernel/cpu/sh4a/setup-sh7770.c
  32. 2 4
      arch/sh/kernel/cpu/sh4a/setup-sh7780.c
  33. 6 12
      arch/sh/kernel/cpu/sh4a/setup-sh7785.c
  34. 6 12
      arch/sh/kernel/cpu/sh4a/setup-sh7786.c
  35. 3 6
      arch/sh/kernel/cpu/sh4a/setup-shx3.c
  36. 2 2
      arch/sh/kernel/cpu/sh5/setup-sh5.c
  37. 23 0
      drivers/acpi/spcr.c
  38. 1 0
      drivers/char/Kconfig
  39. 15 2
      drivers/dma/hsu/pci.c
  40. 1 0
      drivers/tty/Makefile
  41. 1 1
      drivers/tty/goldfish.c
  42. 0 1
      drivers/tty/hvc/hvc_console.c
  43. 16 0
      drivers/tty/serdev/Kconfig
  44. 5 0
      drivers/tty/serdev/Makefile
  45. 421 0
      drivers/tty/serdev/core.c
  46. 226 0
      drivers/tty/serdev/serdev-ttyport.c
  47. 25 3
      drivers/tty/serial/8250/8250_dw.c
  48. 487 0
      drivers/tty/serial/8250/8250_exar.c
  49. 4 0
      drivers/tty/serial/8250/8250_gsc.c
  50. 1 1
      drivers/tty/serial/8250/8250_hp300.c
  51. 2 2
      drivers/tty/serial/8250/8250_lpss.c
  52. 42 3
      drivers/tty/serial/8250/8250_mid.c
  53. 1 0
      drivers/tty/serial/8250/8250_moxa.c
  54. 25 69
      drivers/tty/serial/8250/8250_of.c
  55. 17 16
      drivers/tty/serial/8250/8250_omap.c
  56. 22 493
      drivers/tty/serial/8250/8250_pci.c
  57. 28 4
      drivers/tty/serial/8250/8250_port.c
  58. 8 3
      drivers/tty/serial/8250/Kconfig
  59. 1 0
      drivers/tty/serial/8250/Makefile
  60. 1 0
      drivers/tty/serial/Kconfig
  61. 1 1
      drivers/tty/serial/amba-pl010.c
  62. 61 9
      drivers/tty/serial/amba-pl011.c
  63. 1 1
      drivers/tty/serial/ar933x_uart.c
  64. 48 3
      drivers/tty/serial/atmel_serial.c
  65. 1 1
      drivers/tty/serial/bfin_sport_uart.c
  66. 10 8
      drivers/tty/serial/cpm_uart/cpm_uart_core.c
  67. 1 1
      drivers/tty/serial/dz.c
  68. 1 1
      drivers/tty/serial/efm32-uart.c
  69. 17 18
      drivers/tty/serial/fsl_lpuart.c
  70. 1 1
      drivers/tty/serial/icom.c
  71. 18 14
      drivers/tty/serial/imx.c
  72. 1 1
      drivers/tty/serial/ioc3_serial.c
  73. 1 1
      drivers/tty/serial/ioc4_serial.c
  74. 1 1
      drivers/tty/serial/ip22zilog.c
  75. 33 9
      drivers/tty/serial/lantiq.c
  76. 1 1
      drivers/tty/serial/lpc32xx_hs.c
  77. 1 1
      drivers/tty/serial/max310x.c
  78. 1 1
      drivers/tty/serial/meson_uart.c
  79. 1 1
      drivers/tty/serial/mpsc.c
  80. 1 0
      drivers/tty/serial/msm_serial.c
  81. 3 0
      drivers/tty/serial/mxs-auart.c
  82. 56 1
      drivers/tty/serial/omap-serial.c
  83. 3 3
      drivers/tty/serial/pic32_uart.c
  84. 1 1
      drivers/tty/serial/pmac_zilog.c
  85. 1 1
      drivers/tty/serial/pnx8xxx_uart.c
  86. 1 1
      drivers/tty/serial/pxa.c
  87. 9 11
      drivers/tty/serial/samsung.c
  88. 0 4
      drivers/tty/serial/samsung.h
  89. 1 1
      drivers/tty/serial/serial-tegra.c
  90. 1 1
      drivers/tty/serial/serial_txx9.c
  91. 578 514
      drivers/tty/serial/sh-sci.c
  92. 9 3
      drivers/tty/serial/sh-sci.h
  93. 1 1
      drivers/tty/serial/sirfsoc_uart.c
  94. 1 1
      drivers/tty/serial/sn_console.c
  95. 1 1
      drivers/tty/serial/sprd_serial.c
  96. 92 9
      drivers/tty/serial/st-asc.c
  97. 1 1
      drivers/tty/serial/sunhv.c
  98. 1 1
      drivers/tty/serial/sunzilog.c
  99. 1 1
      drivers/tty/serial/vr41xx_siu.c
  100. 1 1
      drivers/tty/serial/vt8500_serial.c

+ 6 - 0
Documentation/admin-guide/kernel-parameters.txt

@@ -957,6 +957,12 @@
 			serial port must already be setup and configured.
 			serial port must already be setup and configured.
 			Options are not yet supported.
 			Options are not yet supported.
 
 
+		lantiq,<addr>
+			Start an early, polled-mode console on a lantiq serial
+			(lqasc) port at the specified address. The serial port
+			must already be setup and configured. Options are not
+			yet supported.
+
 		lpuart,<addr>
 		lpuart,<addr>
 		lpuart32,<addr>
 		lpuart32,<addr>
 			Use early console provided by Freescale LP UART driver
 			Use early console provided by Freescale LP UART driver

+ 1 - 0
Documentation/devicetree/bindings/serial/8250.txt

@@ -19,6 +19,7 @@ Required properties:
 	- "altr,16550-FIFO128"
 	- "altr,16550-FIFO128"
 	- "fsl,16550-FIFO64"
 	- "fsl,16550-FIFO64"
 	- "fsl,ns16550"
 	- "fsl,ns16550"
+	- "ti,da830-uart"
 	- "serial" if the port type is unknown.
 	- "serial" if the port type is unknown.
 - 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.

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

@@ -23,7 +23,8 @@ Optional properties:
     they are available for use (wired and enabled by pinmux configuration).
     they are available for use (wired and enabled by pinmux configuration).
     This depends on both the UART hardware and the board wiring.
     This depends on both the UART hardware and the board wiring.
     Note that this property is mutually-exclusive with "cts-gpios" and
     Note that this property is mutually-exclusive with "cts-gpios" and
-    "rts-gpios" above.
+    "rts-gpios" above, unless support is provided to switch between modes
+    dynamically.
 
 
 
 
 Examples:
 Examples:

+ 36 - 0
Documentation/devicetree/bindings/serial/slave-device.txt

@@ -0,0 +1,36 @@
+Serial Slave Device DT binding
+
+This documents the binding structure and common properties for serial
+attached devices. Common examples include Bluetooth, WiFi, NFC and GPS
+devices.
+
+Serial attached devices shall be a child node of the host UART device the
+slave device is attached to. It is expected that the attached device is
+the only child node of the UART device. The slave device node name shall
+reflect the generic type of device for the node.
+
+Required Properties:
+
+- compatible 	: A string reflecting the vendor and specific device the node
+		  represents.
+
+Optional Properties:
+
+- max-speed	: The maximum baud rate the device operates at. This should
+		  only be present if the maximum is less than the slave device
+		  can support. For example, a particular board has some signal
+		  quality issue or the host processor can't support higher
+		  baud rates.
+
+Example:
+
+serial@1234 {
+	compatible = "ns16550a";
+	interrupts = <1>;
+
+	bluetooth {
+		compatible = "brcm,bcm43341-bt";
+		interrupt-parent = <&gpio>;
+		interrupts = <10>;
+	};
+};

+ 8 - 0
MAINTAINERS

@@ -10927,6 +10927,14 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/serial/
 F:	Documentation/devicetree/bindings/serial/
 F:	drivers/tty/serial/
 F:	drivers/tty/serial/
 
 
+SERIAL DEVICE BUS
+M:	Rob Herring <robh@kernel.org>
+L:	linux-serial@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/serial/slave-device.txt
+F:	drivers/tty/serdev/
+F:	include/linux/serdev.h
+
 SERIAL IR RECEIVER
 SERIAL IR RECEIVER
 M:	Sean Young <sean@mess.org>
 M:	Sean Young <sean@mess.org>
 L:	linux-media@vger.kernel.org
 L:	linux-media@vger.kernel.org

+ 1 - 2
arch/arm/boot/dts/stih407-family.dtsi

@@ -222,9 +222,8 @@
 			compatible = "st,asc";
 			compatible = "st,asc";
 			reg = <0x9830000 0x2c>;
 			reg = <0x9830000 0x2c>;
 			interrupts = <GIC_SPI 122 IRQ_TYPE_NONE>;
 			interrupts = <GIC_SPI 122 IRQ_TYPE_NONE>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_serial0>;
 			clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
 			clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+			/* Pinctrl moved out to a per-board configuration */
 
 
 			status = "disabled";
 			status = "disabled";
 		};
 		};

+ 10 - 2
arch/arm/boot/dts/stih407-pinctrl.dtsi

@@ -465,8 +465,16 @@
 			serial0 {
 			serial0 {
 				pinctrl_serial0: serial0-0 {
 				pinctrl_serial0: serial0-0 {
 					st,pins {
 					st,pins {
-						tx = <&pio17 0 ALT1 OUT>;
-						rx = <&pio17 1 ALT1 IN>;
+						tx =  <&pio17 0 ALT1 OUT>;
+						rx =  <&pio17 1 ALT1 IN>;
+					};
+				};
+				pinctrl_serial0_hw_flowctrl: serial0-0_hw_flowctrl {
+					st,pins {
+						tx =  <&pio17 0 ALT1 OUT>;
+						rx =  <&pio17 1 ALT1 IN>;
+						cts = <&pio17 2 ALT1 IN>;
+						rts = <&pio17 3 ALT1 OUT>;
 					};
 					};
 				};
 				};
 			};
 			};

+ 5 - 0
arch/arm/boot/dts/stih410-b2260.dts

@@ -62,6 +62,11 @@
 		/* Low speed expansion connector */
 		/* Low speed expansion connector */
 		uart0: serial@9830000 {
 		uart0: serial@9830000 {
 			label = "LS-UART0";
 			label = "LS-UART0";
+			pinctrl-names = "default", "no-hw-flowctrl";
+			pinctrl-0 = <&pinctrl_serial0_hw_flowctrl>;
+			pinctrl-1 = <&pinctrl_serial0>;
+			rts-gpios = <&pio17 3 GPIO_ACTIVE_LOW>;
+			uart-has-rtscts;
 			status = "okay";
 			status = "okay";
 		};
 		};
 
 

+ 3 - 6
arch/sh/kernel/cpu/sh2/setup-sh7619.c

@@ -61,8 +61,7 @@ static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, NULL,
 			 NULL, prio_registers, NULL);
 			 NULL, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -82,8 +81,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -103,8 +101,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 1 - 2
arch/sh/kernel/cpu/sh2a/setup-mxg.c

@@ -129,8 +129,7 @@ static struct platform_device mtu2_device = {
 };
 };
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 8 - 16
arch/sh/kernel/cpu/sh2a/setup-sh7201.c

@@ -178,8 +178,7 @@ static DECLARE_INTC_DESC(intc_desc, "sh7201", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 			 mask_registers, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -199,8 +198,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -220,8 +218,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -241,8 +238,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -262,8 +258,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -283,8 +278,7 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -304,8 +298,7 @@ static struct platform_device scif5_device = {
 };
 };
 
 
 static struct plat_sci_port scif6_platform_data = {
 static struct plat_sci_port scif6_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -325,8 +318,7 @@ static struct platform_device scif6_device = {
 };
 };
 
 
 static struct plat_sci_port scif7_platform_data = {
 static struct plat_sci_port scif7_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 4 - 12
arch/sh/kernel/cpu/sh2a/setup-sh7203.c

@@ -174,9 +174,7 @@ static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 			 mask_registers, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -197,9 +195,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -220,9 +216,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -243,9 +237,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };

+ 4 - 8
arch/sh/kernel/cpu/sh2a/setup-sh7206.c

@@ -134,8 +134,7 @@ static DECLARE_INTC_DESC(intc_desc, "sh7206", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 			 mask_registers, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -155,8 +154,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -176,8 +174,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -197,8 +194,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 8 - 24
arch/sh/kernel/cpu/sh2a/setup-sh7264.c

@@ -226,9 +226,7 @@ static DECLARE_INTC_DESC(intc_desc, "sh7264", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 			 mask_registers, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -252,9 +250,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -278,9 +274,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -304,9 +298,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -330,9 +322,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -356,9 +346,7 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -382,9 +370,7 @@ static struct platform_device scif5_device = {
 };
 };
 
 
 static struct plat_sci_port scif6_platform_data = {
 static struct plat_sci_port scif6_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -408,9 +394,7 @@ static struct platform_device scif6_device = {
 };
 };
 
 
 static struct plat_sci_port scif7_platform_data = {
 static struct plat_sci_port scif7_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };

+ 8 - 24
arch/sh/kernel/cpu/sh2a/setup-sh7269.c

@@ -248,9 +248,7 @@ static DECLARE_INTC_DESC(intc_desc, "sh7269", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 			 mask_registers, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -274,9 +272,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -300,9 +296,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -326,9 +320,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -352,9 +344,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -378,9 +368,7 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -404,9 +392,7 @@ static struct platform_device scif5_device = {
 };
 };
 
 
 static struct plat_sci_port scif6_platform_data = {
 static struct plat_sci_port scif6_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -430,9 +416,7 @@ static struct platform_device scif6_device = {
 };
 };
 
 
 static struct plat_sci_port scif7_platform_data = {
 static struct plat_sci_port scif7_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
-			  SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 };

+ 1 - 5
arch/sh/kernel/cpu/sh3/setup-sh7705.c

@@ -70,9 +70,7 @@ static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, NULL,
 			 NULL, prio_registers, NULL);
 			 NULL, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TIE | SCSCR_RIE  | SCSCR_TE |
-			  SCSCR_RE  | SCSCR_CKE1 | SCSCR_CKE0,
+	.scscr		= SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.ops		= &sh770x_sci_port_ops,
 	.ops		= &sh770x_sci_port_ops,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,
@@ -94,8 +92,6 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TIE | SCSCR_RIE | SCSCR_TE | SCSCR_RE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.ops		= &sh770x_sci_port_ops,
 	.ops		= &sh770x_sci_port_ops,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,

+ 0 - 10
arch/sh/kernel/cpu/sh3/setup-sh770x.c

@@ -109,12 +109,8 @@ static struct platform_device rtc_device = {
 };
 };
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.port_reg	= 0xa4000136,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TE | SCSCR_RE,
 	.type		= PORT_SCI,
 	.type		= PORT_SCI,
 	.ops		= &sh770x_sci_port_ops,
 	.ops		= &sh770x_sci_port_ops,
-	.regshift	= 1,
 };
 };
 
 
 static struct resource scif0_resources[] = {
 static struct resource scif0_resources[] = {
@@ -135,8 +131,6 @@ static struct platform_device scif0_device = {
     defined(CONFIG_CPU_SUBTYPE_SH7707) || \
     defined(CONFIG_CPU_SUBTYPE_SH7707) || \
     defined(CONFIG_CPU_SUBTYPE_SH7709)
     defined(CONFIG_CPU_SUBTYPE_SH7709)
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TE | SCSCR_RE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.ops		= &sh770x_sci_port_ops,
 	.ops		= &sh770x_sci_port_ops,
 	.regtype	= SCIx_SH3_SCIF_REGTYPE,
 	.regtype	= SCIx_SH3_SCIF_REGTYPE,
@@ -160,12 +154,8 @@ static struct platform_device scif1_device = {
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
     defined(CONFIG_CPU_SUBTYPE_SH7709)
     defined(CONFIG_CPU_SUBTYPE_SH7709)
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TE | SCSCR_RE,
 	.type		= PORT_IRDA,
 	.type		= PORT_IRDA,
 	.ops		= &sh770x_sci_port_ops,
 	.ops		= &sh770x_sci_port_ops,
-	.regshift	= 1,
 };
 };
 
 
 static struct resource scif2_resources[] = {
 static struct resource scif2_resources[] = {

+ 2 - 6
arch/sh/kernel/cpu/sh3/setup-sh7710.c

@@ -98,9 +98,7 @@ static struct platform_device rtc_device = {
 };
 };
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TE | SCSCR_RE | SCSCR_REIE |
-			  SCSCR_CKE1 | SCSCR_CKE0,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -120,9 +118,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TE | SCSCR_RE | SCSCR_REIE |
-			  SCSCR_CKE1 | SCSCR_CKE0,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 0 - 4
arch/sh/kernel/cpu/sh3/setup-sh7720.c

@@ -52,8 +52,6 @@ static struct platform_device rtc_device = {
 };
 };
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.ops		= &sh7720_sci_port_ops,
 	.ops		= &sh7720_sci_port_ops,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,
@@ -75,8 +73,6 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.ops		= &sh7720_sci_port_ops,
 	.ops		= &sh7720_sci_port_ops,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,
 	.regtype	= SCIx_SH7705_SCIF_REGTYPE,

+ 1 - 2
arch/sh/kernel/cpu/sh4/setup-sh4-202.c

@@ -17,8 +17,7 @@
 #include <linux/io.h>
 #include <linux/io.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 2 - 7
arch/sh/kernel/cpu/sh4/setup-sh7750.c

@@ -38,15 +38,11 @@ static struct platform_device rtc_device = {
 };
 };
 
 
 static struct plat_sci_port sci_platform_data = {
 static struct plat_sci_port sci_platform_data = {
-	.port_reg	= 0xffe0001C,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TE | SCSCR_RE,
 	.type		= PORT_SCI,
 	.type		= PORT_SCI,
-	.regshift	= 2,
 };
 };
 
 
 static struct resource sci_resources[] = {
 static struct resource sci_resources[] = {
-	DEFINE_RES_MEM(0xffe00000, 0x100),
+	DEFINE_RES_MEM(0xffe00000, 0x20),
 	DEFINE_RES_IRQ(evt2irq(0x4e0)),
 	DEFINE_RES_IRQ(evt2irq(0x4e0)),
 };
 };
 
 
@@ -61,8 +57,7 @@ static struct platform_device sci_device = {
 };
 };
 
 
 static struct plat_sci_port scif_platform_data = {
 static struct plat_sci_port scif_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_TE | SCSCR_RE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 11 - 10
arch/sh/kernel/cpu/sh4/setup-sh7760.c

@@ -128,8 +128,7 @@ static DECLARE_INTC_DESC(intc_desc_irq, "sh7760-irq", vectors_irq, groups,
 			 mask_registers, prio_registers, NULL);
 			 mask_registers, prio_registers, NULL);
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -153,9 +152,8 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
 
 
@@ -178,8 +176,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -203,14 +200,18 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	/*
+	 * This is actually a SIM card module serial port, based on an SCI with
+	 * additional registers. The sh-sci driver doesn't support the SIM port
+	 * type, declare it as a SCI. Don't declare the additional registers in
+	 * the memory resource or the driver will compute an incorrect regshift
+	 * value.
+	 */
 	.type		= PORT_SCI,
 	.type		= PORT_SCI,
-	.regshift	= 2,
 };
 };
 
 
 static struct resource scif3_resources[] = {
 static struct resource scif3_resources[] = {
-	DEFINE_RES_MEM(0xfe480000, 0x100),
+	DEFINE_RES_MEM(0xfe480000, 0x10),
 	DEFINE_RES_IRQ(evt2irq(0xc00)),
 	DEFINE_RES_IRQ(evt2irq(0xc00)),
 	DEFINE_RES_IRQ(evt2irq(0xc20)),
 	DEFINE_RES_IRQ(evt2irq(0xc20)),
 	DEFINE_RES_IRQ(evt2irq(0xc40)),
 	DEFINE_RES_IRQ(evt2irq(0xc40)),

+ 4 - 8
arch/sh/kernel/cpu/sh4a/setup-sh7343.c

@@ -18,8 +18,7 @@
 
 
 /* Serial */
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scscr		= SCSCR_CKE1,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 };
 };
 
 
@@ -39,8 +38,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scscr		= SCSCR_CKE1,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 };
 };
 
 
@@ -60,8 +58,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scscr		= SCSCR_CKE1,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 };
 };
 
 
@@ -81,8 +78,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scscr		= SCSCR_CKE1,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 };
 };
 
 

+ 1 - 3
arch/sh/kernel/cpu/sh4a/setup-sh7366.c

@@ -20,9 +20,7 @@
 #include <asm/clock.h>
 #include <asm/clock.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.port_reg	= 0xa405013e,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 3 - 6
arch/sh/kernel/cpu/sh4a/setup-sh7722.c

@@ -179,8 +179,7 @@ struct platform_device dma_device = {
 
 
 /* Serial */
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.ops		= &sh7722_sci_port_ops,
 	.ops		= &sh7722_sci_port_ops,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
@@ -202,8 +201,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.ops		= &sh7722_sci_port_ops,
 	.ops		= &sh7722_sci_port_ops,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
@@ -225,8 +223,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.ops		= &sh7722_sci_port_ops,
 	.ops		= &sh7722_sci_port_ops,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,

+ 3 - 18
arch/sh/kernel/cpu/sh4a/setup-sh7723.c

@@ -23,9 +23,7 @@
 
 
 /* Serial */
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.port_reg	= 0xa4050160,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 };
@@ -46,9 +44,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 };
@@ -69,9 +65,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 };
@@ -92,9 +86,6 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
 	.sampling_rate	= 8,
 	.sampling_rate	= 8,
 	.type           = PORT_SCIFA,
 	.type           = PORT_SCIFA,
 };
 };
@@ -115,9 +106,6 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
 	.sampling_rate	= 8,
 	.sampling_rate	= 8,
 	.type           = PORT_SCIFA,
 	.type           = PORT_SCIFA,
 };
 };
@@ -138,9 +126,6 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
 	.sampling_rate	= 8,
 	.sampling_rate	= 8,
 	.type           = PORT_SCIFA,
 	.type           = PORT_SCIFA,
 };
 };

+ 3 - 18
arch/sh/kernel/cpu/sh4a/setup-sh7724.c

@@ -290,9 +290,7 @@ static struct platform_device dma1_device = {
 
 
 /* Serial */
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 };
@@ -313,9 +311,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 };
@@ -336,9 +332,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 };
@@ -359,9 +353,6 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
 	.sampling_rate	= 8,
 	.sampling_rate	= 8,
 	.type           = PORT_SCIFA,
 	.type           = PORT_SCIFA,
 };
 };
@@ -382,9 +373,6 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
 	.sampling_rate	= 8,
 	.sampling_rate	= 8,
 	.type           = PORT_SCIFA,
 	.type           = PORT_SCIFA,
 };
 };
@@ -405,9 +393,6 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.port_reg	= SCIx_NOT_SUPPORTED,
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
 	.sampling_rate	= 8,
 	.sampling_rate	= 8,
 	.type           = PORT_SCIFA,
 	.type           = PORT_SCIFA,
 };
 };

+ 6 - 12
arch/sh/kernel/cpu/sh4a/setup-sh7734.c

@@ -25,8 +25,7 @@
 
 
 /* SCIF */
 /* SCIF */
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr          = SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 };
 };
@@ -47,8 +46,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr          = SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 };
 };
@@ -69,8 +67,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr          = SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 };
 };
@@ -91,8 +88,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr          = SCSCR_REIE | SCSCR_TOIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 };
 };
@@ -113,8 +109,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr          = SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 	.regtype        = SCIx_SH4_SCIF_BRG_REGTYPE,
 };
 };
@@ -135,8 +130,7 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.flags          = UPF_BOOT_AUTOCONF,
-	.scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr          = SCSCR_REIE,
 	.type           = PORT_SCIF,
 	.type           = PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_BRG_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_BRG_REGTYPE,
 };
 };

+ 3 - 6
arch/sh/kernel/cpu/sh4a/setup-sh7757.c

@@ -24,8 +24,7 @@
 #include <cpu/sh7757.h>
 #include <cpu/sh7757.h>
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -45,8 +44,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -66,8 +64,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 3 - 6
arch/sh/kernel/cpu/sh4a/setup-sh7763.c

@@ -19,8 +19,7 @@
 #include <linux/usb/ohci_pdriver.h>
 #include <linux/usb/ohci_pdriver.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -41,8 +40,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -63,8 +61,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };

+ 10 - 20
arch/sh/kernel/cpu/sh4a/setup-sh7770.c

@@ -16,8 +16,7 @@
 #include <linux/io.h>
 #include <linux/io.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -37,8 +36,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -58,8 +56,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -79,8 +76,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -100,8 +96,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -121,8 +116,7 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -142,8 +136,7 @@ static struct platform_device scif5_device = {
 };
 };
 
 
 static struct plat_sci_port scif6_platform_data = {
 static struct plat_sci_port scif6_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -163,8 +156,7 @@ static struct platform_device scif6_device = {
 };
 };
 
 
 static struct plat_sci_port scif7_platform_data = {
 static struct plat_sci_port scif7_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -184,8 +176,7 @@ static struct platform_device scif7_device = {
 };
 };
 
 
 static struct plat_sci_port scif8_platform_data = {
 static struct plat_sci_port scif8_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -205,8 +196,7 @@ static struct platform_device scif8_device = {
 };
 };
 
 
 static struct plat_sci_port scif9_platform_data = {
 static struct plat_sci_port scif9_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 2 - 4
arch/sh/kernel/cpu/sh4a/setup-sh7780.c

@@ -18,8 +18,7 @@
 #include <cpu/dma-register.h>
 #include <cpu/dma-register.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -40,8 +39,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };

+ 6 - 12
arch/sh/kernel/cpu/sh4a/setup-sh7785.c

@@ -20,8 +20,7 @@
 #include <cpu/dma-register.h>
 #include <cpu/dma-register.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -42,8 +41,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -64,8 +62,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -86,8 +83,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -108,8 +104,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -130,8 +125,7 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };

+ 6 - 12
arch/sh/kernel/cpu/sh4a/setup-sh7786.c

@@ -28,8 +28,7 @@
 #include <asm/mmzone.h>
 #include <asm/mmzone.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -56,8 +55,7 @@ static struct platform_device scif0_device = {
  * The rest of these all have multiplexed IRQs
  * The rest of these all have multiplexed IRQs
  */
  */
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -87,8 +85,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -109,8 +106,7 @@ static struct platform_device scif2_device = {
 };
 };
 
 
 static struct plat_sci_port scif3_platform_data = {
 static struct plat_sci_port scif3_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -131,8 +127,7 @@ static struct platform_device scif3_device = {
 };
 };
 
 
 static struct plat_sci_port scif4_platform_data = {
 static struct plat_sci_port scif4_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };
@@ -153,8 +148,7 @@ static struct platform_device scif4_device = {
 };
 };
 
 
 static struct plat_sci_port scif5_platform_data = {
 static struct plat_sci_port scif5_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 	.regtype	= SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 };

+ 3 - 6
arch/sh/kernel/cpu/sh4a/setup-shx3.c

@@ -28,8 +28,7 @@
  * all rather than adding infrastructure to hack around it.
  * all rather than adding infrastructure to hack around it.
  */
  */
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -52,8 +51,7 @@ static struct platform_device scif0_device = {
 };
 };
 
 
 static struct plat_sci_port scif1_platform_data = {
 static struct plat_sci_port scif1_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 
@@ -76,8 +74,7 @@ static struct platform_device scif1_device = {
 };
 };
 
 
 static struct plat_sci_port scif2_platform_data = {
 static struct plat_sci_port scif2_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 2 - 2
arch/sh/kernel/cpu/sh5/setup-sh5.c

@@ -17,8 +17,8 @@
 #include <asm/addrspace.h>
 #include <asm/addrspace.h>
 
 
 static struct plat_sci_port scif0_platform_data = {
 static struct plat_sci_port scif0_platform_data = {
-	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.flags		= UPF_IOREMAP,
+	.scscr		= SCSCR_REIE,
 	.type		= PORT_SCIF,
 	.type		= PORT_SCIF,
 };
 };
 
 

+ 23 - 0
drivers/acpi/spcr.c

@@ -16,6 +16,26 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 
 
+/*
+ * Some Qualcomm Datacenter Technologies SoCs have a defective UART BUSY bit.
+ * Detect them by examining the OEM fields in the SPCR header, similiar to PCI
+ * quirk detection in pci_mcfg.c.
+ */
+static bool qdf2400_erratum_44_present(struct acpi_table_header *h)
+{
+	if (memcmp(h->oem_id, "QCOM  ", ACPI_OEM_ID_SIZE))
+		return false;
+
+	if (!memcmp(h->oem_table_id, "QDF2432 ", ACPI_OEM_TABLE_ID_SIZE))
+		return true;
+
+	if (!memcmp(h->oem_table_id, "QDF2400 ", ACPI_OEM_TABLE_ID_SIZE) &&
+			h->oem_revision == 0)
+		return true;
+
+	return false;
+}
+
 /**
 /**
  * parse_spcr() - parse ACPI SPCR table and add preferred console
  * parse_spcr() - parse ACPI SPCR table and add preferred console
  *
  *
@@ -93,6 +113,9 @@ int __init parse_spcr(bool earlycon)
 		goto done;
 		goto done;
 	}
 	}
 
 
+	if (qdf2400_erratum_44_present(&table->header))
+		uart = "qdf2400_e44";
+
 	snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
 	snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
 		 table->serial_port.address, baud_rate);
 		 table->serial_port.address, baud_rate);
 
 

+ 1 - 0
drivers/char/Kconfig

@@ -46,6 +46,7 @@ config SGI_MBCS
          say Y or M here, otherwise say N.
          say Y or M here, otherwise say N.
 
 
 source "drivers/tty/serial/Kconfig"
 source "drivers/tty/serial/Kconfig"
+source "drivers/tty/serdev/Kconfig"
 
 
 config TTY_PRINTK
 config TTY_PRINTK
 	tristate "TTY driver to output user messages via printk"
 	tristate "TTY driver to output user messages via printk"

+ 15 - 2
drivers/dma/hsu/pci.c

@@ -23,15 +23,28 @@
 
 
 #define HSU_PCI_CHAN_OFFSET	0x100
 #define HSU_PCI_CHAN_OFFSET	0x100
 
 
+#define PCI_DEVICE_ID_INTEL_MFLD_HSU_DMA	0x081e
+#define PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA	0x1192
+
 static irqreturn_t hsu_pci_irq(int irq, void *dev)
 static irqreturn_t hsu_pci_irq(int irq, void *dev)
 {
 {
 	struct hsu_dma_chip *chip = dev;
 	struct hsu_dma_chip *chip = dev;
+	struct pci_dev *pdev = to_pci_dev(chip->dev);
 	u32 dmaisr;
 	u32 dmaisr;
 	u32 status;
 	u32 status;
 	unsigned short i;
 	unsigned short i;
 	int ret = 0;
 	int ret = 0;
 	int err;
 	int err;
 
 
+	/*
+	 * On Intel Tangier B0 and Anniedale the interrupt line, disregarding
+	 * to have different numbers, is shared between HSU DMA and UART IPs.
+	 * Thus on such SoCs we are expecting that IRQ handler is called in
+	 * UART driver only.
+	 */
+	if (pdev->device == PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA)
+		return IRQ_HANDLED;
+
 	dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
 	dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
 	for (i = 0; i < chip->hsu->nr_channels; i++) {
 	for (i = 0; i < chip->hsu->nr_channels; i++) {
 		if (dmaisr & 0x1) {
 		if (dmaisr & 0x1) {
@@ -113,8 +126,8 @@ static void hsu_pci_remove(struct pci_dev *pdev)
 }
 }
 
 
 static const struct pci_device_id hsu_pci_id_table[] = {
 static const struct pci_device_id hsu_pci_id_table[] = {
-	{ PCI_VDEVICE(INTEL, 0x081e), 0 },
-	{ PCI_VDEVICE(INTEL, 0x1192), 0 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MFLD_HSU_DMA), 0 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA), 0 },
 	{ }
 	{ }
 };
 };
 MODULE_DEVICE_TABLE(pci, hsu_pci_id_table);
 MODULE_DEVICE_TABLE(pci, hsu_pci_id_table);

+ 1 - 0
drivers/tty/Makefile

@@ -13,6 +13,7 @@ obj-$(CONFIG_R3964)		+= n_r3964.o
 obj-y				+= vt/
 obj-y				+= vt/
 obj-$(CONFIG_HVC_DRIVER)	+= hvc/
 obj-$(CONFIG_HVC_DRIVER)	+= hvc/
 obj-y				+= serial/
 obj-y				+= serial/
+obj-$(CONFIG_SERIAL_DEV_BUS)	+= serdev/
 
 
 # tty drivers
 # tty drivers
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o

+ 1 - 1
drivers/tty/goldfish.c

@@ -300,7 +300,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 
 
 err_tty_register_device_failed:
 err_tty_register_device_failed:
-	free_irq(irq, pdev);
+	free_irq(irq, qtty);
 err_request_irq_failed:
 err_request_irq_failed:
 	goldfish_tty_current_line_count--;
 	goldfish_tty_current_line_count--;
 	if (goldfish_tty_current_line_count == 0)
 	if (goldfish_tty_current_line_count == 0)

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

@@ -29,7 +29,6 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/list.h>
-#include <linux/init.h>
 #include <linux/major.h>
 #include <linux/major.h>
 #include <linux/atomic.h>
 #include <linux/atomic.h>
 #include <linux/sysrq.h>
 #include <linux/sysrq.h>

+ 16 - 0
drivers/tty/serdev/Kconfig

@@ -0,0 +1,16 @@
+#
+# Serial bus device driver configuration
+#
+menuconfig SERIAL_DEV_BUS
+	tristate "Serial device bus"
+	help
+	  Core support for devices connected via a serial port.
+
+if SERIAL_DEV_BUS
+
+config SERIAL_DEV_CTRL_TTYPORT
+	bool "Serial device TTY port controller"
+	depends on TTY
+	depends on SERIAL_DEV_BUS != m
+
+endif

+ 5 - 0
drivers/tty/serdev/Makefile

@@ -0,0 +1,5 @@
+serdev-objs := core.o
+
+obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o
+
+obj-$(CONFIG_SERIAL_DEV_CTRL_TTYPORT) += serdev-ttyport.o

+ 421 - 0
drivers/tty/serdev/core.c

@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org>
+ *
+ * Based on drivers/spmi/spmi.c:
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/errno.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/serdev.h>
+#include <linux/slab.h>
+
+static bool is_registered;
+static DEFINE_IDA(ctrl_ida);
+
+static void serdev_device_release(struct device *dev)
+{
+	struct serdev_device *serdev = to_serdev_device(dev);
+	kfree(serdev);
+}
+
+static const struct device_type serdev_device_type = {
+	.release	= serdev_device_release,
+};
+
+static void serdev_ctrl_release(struct device *dev)
+{
+	struct serdev_controller *ctrl = to_serdev_controller(dev);
+	ida_simple_remove(&ctrl_ida, ctrl->nr);
+	kfree(ctrl);
+}
+
+static const struct device_type serdev_ctrl_type = {
+	.release	= serdev_ctrl_release,
+};
+
+static int serdev_device_match(struct device *dev, struct device_driver *drv)
+{
+	/* TODO: ACPI and platform matching */
+	return of_driver_match_device(dev, drv);
+}
+
+static int serdev_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	/* TODO: ACPI and platform modalias */
+	return of_device_uevent_modalias(dev, env);
+}
+
+/**
+ * serdev_device_add() - add a device previously constructed via serdev_device_alloc()
+ * @serdev:	serdev_device to be added
+ */
+int serdev_device_add(struct serdev_device *serdev)
+{
+	struct device *parent = serdev->dev.parent;
+	int err;
+
+	dev_set_name(&serdev->dev, "%s-%d", dev_name(parent), serdev->nr);
+
+	err = device_add(&serdev->dev);
+	if (err < 0) {
+		dev_err(&serdev->dev, "Can't add %s, status %d\n",
+			dev_name(&serdev->dev), err);
+		goto err_device_add;
+	}
+
+	dev_dbg(&serdev->dev, "device %s registered\n", dev_name(&serdev->dev));
+
+err_device_add:
+	return err;
+}
+EXPORT_SYMBOL_GPL(serdev_device_add);
+
+/**
+ * serdev_device_remove(): remove an serdev device
+ * @serdev:	serdev_device to be removed
+ */
+void serdev_device_remove(struct serdev_device *serdev)
+{
+	device_unregister(&serdev->dev);
+}
+EXPORT_SYMBOL_GPL(serdev_device_remove);
+
+int serdev_device_open(struct serdev_device *serdev)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->open)
+		return -EINVAL;
+
+	return ctrl->ops->open(ctrl);
+}
+EXPORT_SYMBOL_GPL(serdev_device_open);
+
+void serdev_device_close(struct serdev_device *serdev)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->close)
+		return;
+
+	ctrl->ops->close(ctrl);
+}
+EXPORT_SYMBOL_GPL(serdev_device_close);
+
+int serdev_device_write_buf(struct serdev_device *serdev,
+			    const unsigned char *buf, size_t count)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->write_buf)
+		return -EINVAL;
+
+	return ctrl->ops->write_buf(ctrl, buf, count);
+}
+EXPORT_SYMBOL_GPL(serdev_device_write_buf);
+
+void serdev_device_write_flush(struct serdev_device *serdev)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->write_flush)
+		return;
+
+	ctrl->ops->write_flush(ctrl);
+}
+EXPORT_SYMBOL_GPL(serdev_device_write_flush);
+
+int serdev_device_write_room(struct serdev_device *serdev)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->write_room)
+		return 0;
+
+	return serdev->ctrl->ops->write_room(ctrl);
+}
+EXPORT_SYMBOL_GPL(serdev_device_write_room);
+
+unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, unsigned int speed)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->set_baudrate)
+		return 0;
+
+	return ctrl->ops->set_baudrate(ctrl, speed);
+
+}
+EXPORT_SYMBOL_GPL(serdev_device_set_baudrate);
+
+void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->set_flow_control)
+		return;
+
+	ctrl->ops->set_flow_control(ctrl, enable);
+}
+EXPORT_SYMBOL_GPL(serdev_device_set_flow_control);
+
+static int serdev_drv_probe(struct device *dev)
+{
+	const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
+
+	return sdrv->probe(to_serdev_device(dev));
+}
+
+static int serdev_drv_remove(struct device *dev)
+{
+	const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
+
+	sdrv->remove(to_serdev_device(dev));
+	return 0;
+}
+
+static ssize_t modalias_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
+	buf[len] = '\n';
+	buf[len+1] = 0;
+	return len+1;
+}
+
+static struct device_attribute serdev_device_attrs[] = {
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
+
+static struct bus_type serdev_bus_type = {
+	.name		= "serial",
+	.match		= serdev_device_match,
+	.probe		= serdev_drv_probe,
+	.remove		= serdev_drv_remove,
+	.uevent		= serdev_uevent,
+	.dev_attrs	= serdev_device_attrs,
+};
+
+/**
+ * serdev_controller_alloc() - Allocate a new serdev device
+ * @ctrl:	associated controller
+ *
+ * Caller is responsible for either calling serdev_device_add() to add the
+ * newly allocated controller, or calling serdev_device_put() to discard it.
+ */
+struct serdev_device *serdev_device_alloc(struct serdev_controller *ctrl)
+{
+	struct serdev_device *serdev;
+
+	serdev = kzalloc(sizeof(*serdev), GFP_KERNEL);
+	if (!serdev)
+		return NULL;
+
+	serdev->ctrl = ctrl;
+	ctrl->serdev = serdev;
+	device_initialize(&serdev->dev);
+	serdev->dev.parent = &ctrl->dev;
+	serdev->dev.bus = &serdev_bus_type;
+	serdev->dev.type = &serdev_device_type;
+	return serdev;
+}
+EXPORT_SYMBOL_GPL(serdev_device_alloc);
+
+/**
+ * serdev_controller_alloc() - Allocate a new serdev controller
+ * @parent:	parent device
+ * @size:	size of private data
+ *
+ * Caller is responsible for either calling serdev_controller_add() to add the
+ * newly allocated controller, or calling serdev_controller_put() to discard it.
+ * The allocated private data region may be accessed via
+ * serdev_controller_get_drvdata()
+ */
+struct serdev_controller *serdev_controller_alloc(struct device *parent,
+					      size_t size)
+{
+	struct serdev_controller *ctrl;
+	int id;
+
+	if (WARN_ON(!parent))
+		return NULL;
+
+	ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL);
+	if (!ctrl)
+		return NULL;
+
+	device_initialize(&ctrl->dev);
+	ctrl->dev.type = &serdev_ctrl_type;
+	ctrl->dev.bus = &serdev_bus_type;
+	ctrl->dev.parent = parent;
+	ctrl->dev.of_node = parent->of_node;
+	serdev_controller_set_drvdata(ctrl, &ctrl[1]);
+
+	id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		dev_err(parent,
+			"unable to allocate serdev controller identifier.\n");
+		serdev_controller_put(ctrl);
+		return NULL;
+	}
+
+	ctrl->nr = id;
+	dev_set_name(&ctrl->dev, "serial%d", id);
+
+	dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id);
+	return ctrl;
+}
+EXPORT_SYMBOL_GPL(serdev_controller_alloc);
+
+static int of_serdev_register_devices(struct serdev_controller *ctrl)
+{
+	struct device_node *node;
+	struct serdev_device *serdev = NULL;
+	int err;
+	bool found = false;
+
+	for_each_available_child_of_node(ctrl->dev.of_node, node) {
+		if (!of_get_property(node, "compatible", NULL))
+			continue;
+
+		dev_dbg(&ctrl->dev, "adding child %s\n", node->full_name);
+
+		serdev = serdev_device_alloc(ctrl);
+		if (!serdev)
+			continue;
+
+		serdev->dev.of_node = node;
+
+		err = serdev_device_add(serdev);
+		if (err) {
+			dev_err(&serdev->dev,
+				"failure adding device. status %d\n", err);
+			serdev_device_put(serdev);
+		} else
+			found = true;
+	}
+	if (!found)
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * serdev_controller_add() - Add an serdev controller
+ * @ctrl:	controller to be registered.
+ *
+ * Register a controller previously allocated via serdev_controller_alloc() with
+ * the serdev core.
+ */
+int serdev_controller_add(struct serdev_controller *ctrl)
+{
+	int ret;
+
+	/* Can't register until after driver model init */
+	if (WARN_ON(!is_registered))
+		return -EAGAIN;
+
+	ret = device_add(&ctrl->dev);
+	if (ret)
+		return ret;
+
+	ret = of_serdev_register_devices(ctrl);
+	if (ret)
+		goto out_dev_del;
+
+	dev_dbg(&ctrl->dev, "serdev%d registered: dev:%p\n",
+		ctrl->nr, &ctrl->dev);
+	return 0;
+
+out_dev_del:
+	device_del(&ctrl->dev);
+	return ret;
+};
+EXPORT_SYMBOL_GPL(serdev_controller_add);
+
+/* Remove a device associated with a controller */
+static int serdev_remove_device(struct device *dev, void *data)
+{
+	struct serdev_device *serdev = to_serdev_device(dev);
+	if (dev->type == &serdev_device_type)
+		serdev_device_remove(serdev);
+	return 0;
+}
+
+/**
+ * serdev_controller_remove(): remove an serdev controller
+ * @ctrl:	controller to remove
+ *
+ * Remove a serdev controller.  Caller is responsible for calling
+ * serdev_controller_put() to discard the allocated controller.
+ */
+void serdev_controller_remove(struct serdev_controller *ctrl)
+{
+	int dummy;
+
+	if (!ctrl)
+		return;
+
+	dummy = device_for_each_child(&ctrl->dev, NULL,
+				      serdev_remove_device);
+	device_del(&ctrl->dev);
+}
+EXPORT_SYMBOL_GPL(serdev_controller_remove);
+
+/**
+ * serdev_driver_register() - Register client driver with serdev core
+ * @sdrv:	client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the serdev framework.
+ * It is typically called from the driver's module-init function.
+ */
+int __serdev_device_driver_register(struct serdev_device_driver *sdrv, struct module *owner)
+{
+	sdrv->driver.bus = &serdev_bus_type;
+	sdrv->driver.owner = owner;
+
+	/* force drivers to async probe so I/O is possible in probe */
+        sdrv->driver.probe_type = PROBE_PREFER_ASYNCHRONOUS;
+
+	return driver_register(&sdrv->driver);
+}
+EXPORT_SYMBOL_GPL(__serdev_device_driver_register);
+
+static void __exit serdev_exit(void)
+{
+	bus_unregister(&serdev_bus_type);
+}
+module_exit(serdev_exit);
+
+static int __init serdev_init(void)
+{
+	int ret;
+
+	ret = bus_register(&serdev_bus_type);
+	if (ret)
+		return ret;
+
+	is_registered = true;
+	return 0;
+}
+/* Must be before serial drivers register */
+postcore_initcall(serdev_init);
+
+MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Serial attached device bus");

+ 226 - 0
drivers/tty/serdev/serdev-ttyport.c

@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/serdev.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+
+#define SERPORT_ACTIVE		1
+
+struct serport {
+	struct tty_port *port;
+	struct tty_struct *tty;
+	struct tty_driver *tty_drv;
+	int tty_idx;
+	unsigned long flags;
+};
+
+/*
+ * Callback functions from the tty port.
+ */
+
+static int ttyport_receive_buf(struct tty_port *port, const unsigned char *cp,
+				const unsigned char *fp, size_t count)
+{
+	struct serdev_controller *ctrl = port->client_data;
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+
+	if (!test_bit(SERPORT_ACTIVE, &serport->flags))
+		return 0;
+
+	return serdev_controller_receive_buf(ctrl, cp, count);
+}
+
+static void ttyport_write_wakeup(struct tty_port *port)
+{
+	struct serdev_controller *ctrl = port->client_data;
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+
+	if (!test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &port->tty->flags))
+		return;
+
+	if (test_bit(SERPORT_ACTIVE, &serport->flags))
+		serdev_controller_write_wakeup(ctrl);
+}
+
+static const struct tty_port_client_operations client_ops = {
+	.receive_buf = ttyport_receive_buf,
+	.write_wakeup = ttyport_write_wakeup,
+};
+
+/*
+ * Callback functions from the serdev core.
+ */
+
+static int ttyport_write_buf(struct serdev_controller *ctrl, const unsigned char *data, size_t len)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+
+	if (!test_bit(SERPORT_ACTIVE, &serport->flags))
+		return 0;
+
+	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	return tty->ops->write(serport->tty, data, len);
+}
+
+static void ttyport_write_flush(struct serdev_controller *ctrl)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+
+	tty_driver_flush_buffer(tty);
+}
+
+static int ttyport_write_room(struct serdev_controller *ctrl)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+
+	return tty_write_room(tty);
+}
+
+static int ttyport_open(struct serdev_controller *ctrl)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty;
+	struct ktermios ktermios;
+
+	tty = tty_init_dev(serport->tty_drv, serport->tty_idx);
+	if (IS_ERR(tty))
+		return PTR_ERR(tty);
+	serport->tty = tty;
+
+	serport->port->client_ops = &client_ops;
+	serport->port->client_data = ctrl;
+
+	if (tty->ops->open)
+		tty->ops->open(serport->tty, NULL);
+	else
+		tty_port_open(serport->port, tty, NULL);
+
+	/* Bring the UART into a known 8 bits no parity hw fc state */
+	ktermios = tty->termios;
+	ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
+			      INLCR | IGNCR | ICRNL | IXON);
+	ktermios.c_oflag &= ~OPOST;
+	ktermios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+	ktermios.c_cflag &= ~(CSIZE | PARENB);
+	ktermios.c_cflag |= CS8;
+	ktermios.c_cflag |= CRTSCTS;
+	tty_set_termios(tty, &ktermios);
+
+	set_bit(SERPORT_ACTIVE, &serport->flags);
+
+	tty_unlock(serport->tty);
+	return 0;
+}
+
+static void ttyport_close(struct serdev_controller *ctrl)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+
+	clear_bit(SERPORT_ACTIVE, &serport->flags);
+
+	if (tty->ops->close)
+		tty->ops->close(tty, NULL);
+
+	tty_release_struct(tty, serport->tty_idx);
+}
+
+static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigned int speed)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+	struct ktermios ktermios = tty->termios;
+
+	ktermios.c_cflag &= ~CBAUD;
+	tty_termios_encode_baud_rate(&ktermios, speed, speed);
+
+	/* tty_set_termios() return not checked as it is always 0 */
+	tty_set_termios(tty, &ktermios);
+	return speed;
+}
+
+static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+	struct ktermios ktermios = tty->termios;
+
+	if (enable)
+		ktermios.c_cflag |= CRTSCTS;
+	else
+		ktermios.c_cflag &= ~CRTSCTS;
+
+	tty_set_termios(tty, &ktermios);
+}
+
+static const struct serdev_controller_ops ctrl_ops = {
+	.write_buf = ttyport_write_buf,
+	.write_flush = ttyport_write_flush,
+	.write_room = ttyport_write_room,
+	.open = ttyport_open,
+	.close = ttyport_close,
+	.set_flow_control = ttyport_set_flow_control,
+	.set_baudrate = ttyport_set_baudrate,
+};
+
+struct device *serdev_tty_port_register(struct tty_port *port,
+					struct device *parent,
+					struct tty_driver *drv, int idx)
+{
+	struct serdev_controller *ctrl;
+	struct serport *serport;
+	int ret;
+
+	if (!port || !drv || !parent)
+		return ERR_PTR(-ENODEV);
+
+	ctrl = serdev_controller_alloc(parent, sizeof(struct serport));
+	if (!ctrl)
+		return ERR_PTR(-ENOMEM);
+	serport = serdev_controller_get_drvdata(ctrl);
+
+	serport->port = port;
+	serport->tty_idx = idx;
+	serport->tty_drv = drv;
+
+	ctrl->ops = &ctrl_ops;
+
+	ret = serdev_controller_add(ctrl);
+	if (ret)
+		goto err_controller_put;
+
+	dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx);
+	return &ctrl->dev;
+
+err_controller_put:
+	serdev_controller_put(ctrl);
+	return ERR_PTR(ret);
+}
+
+void serdev_tty_port_unregister(struct tty_port *port)
+{
+	struct serdev_controller *ctrl = port->client_data;
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+
+	if (!serport)
+		return;
+
+	serdev_controller_remove(ctrl);
+	port->client_ops = NULL;
+	port->client_data = NULL;
+	serdev_controller_put(ctrl);
+}

+ 25 - 3
drivers/tty/serial/8250/8250_dw.c

@@ -201,8 +201,31 @@ static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset)
 
 
 static int dw8250_handle_irq(struct uart_port *p)
 static int dw8250_handle_irq(struct uart_port *p)
 {
 {
+	struct uart_8250_port *up = up_to_u8250p(p);
 	struct dw8250_data *d = p->private_data;
 	struct dw8250_data *d = p->private_data;
 	unsigned int iir = p->serial_in(p, UART_IIR);
 	unsigned int iir = p->serial_in(p, UART_IIR);
+	unsigned int status;
+	unsigned long flags;
+
+	/*
+	 * There are ways to get Designware-based UARTs into a state where
+	 * they are asserting UART_IIR_RX_TIMEOUT but there is no actual
+	 * data available.  If we see such a case then we'll do a bogus
+	 * read.  If we don't do this then the "RX TIMEOUT" interrupt will
+	 * fire forever.
+	 *
+	 * This problem has only been observed so far when not in DMA mode
+	 * so we limit the workaround only to non-DMA mode.
+	 */
+	if (!up->dma && ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)) {
+		spin_lock_irqsave(&p->lock, flags);
+		status = p->serial_in(p, UART_LSR);
+
+		if (!(status & (UART_LSR_DR | UART_LSR_BI)))
+			(void) p->serial_in(p, UART_RX);
+
+		spin_unlock_irqrestore(&p->lock, flags);
+	}
 
 
 	if (serial8250_handle_irq(p, iir))
 	if (serial8250_handle_irq(p, iir))
 		return 1;
 		return 1;
@@ -248,11 +271,11 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
 	if (!ret)
 	if (!ret)
 		p->uartclk = rate;
 		p->uartclk = rate;
 
 
+out:
 	p->status &= ~UPSTAT_AUTOCTS;
 	p->status &= ~UPSTAT_AUTOCTS;
 	if (termios->c_cflag & CRTSCTS)
 	if (termios->c_cflag & CRTSCTS)
 		p->status |= UPSTAT_AUTOCTS;
 		p->status |= UPSTAT_AUTOCTS;
 
 
-out:
 	serial8250_do_set_termios(p, termios, old);
 	serial8250_do_set_termios(p, termios, old);
 }
 }
 
 
@@ -326,13 +349,11 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
 			p->serial_in = dw8250_serial_in32;
 			p->serial_in = dw8250_serial_in32;
 			data->uart_16550_compatible = true;
 			data->uart_16550_compatible = true;
 		}
 		}
-		p->set_termios = dw8250_set_termios;
 	}
 	}
 
 
 	/* Platforms with iDMA */
 	/* Platforms with iDMA */
 	if (platform_get_resource_byname(to_platform_device(p->dev),
 	if (platform_get_resource_byname(to_platform_device(p->dev),
 					 IORESOURCE_MEM, "lpss_priv")) {
 					 IORESOURCE_MEM, "lpss_priv")) {
-		p->set_termios = dw8250_set_termios;
 		data->dma.rx_param = p->dev->parent;
 		data->dma.rx_param = p->dev->parent;
 		data->dma.tx_param = p->dev->parent;
 		data->dma.tx_param = p->dev->parent;
 		data->dma.fn = dw8250_idma_filter;
 		data->dma.fn = dw8250_idma_filter;
@@ -414,6 +435,7 @@ static int dw8250_probe(struct platform_device *pdev)
 	p->serial_in	= dw8250_serial_in;
 	p->serial_in	= dw8250_serial_in;
 	p->serial_out	= dw8250_serial_out;
 	p->serial_out	= dw8250_serial_out;
 	p->set_ldisc	= dw8250_set_ldisc;
 	p->set_ldisc	= dw8250_set_ldisc;
+	p->set_termios	= dw8250_set_termios;
 
 
 	p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
 	p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
 	if (!p->membase)
 	if (!p->membase)

+ 487 - 0
drivers/tty/serial/8250/8250_exar.c

@@ -0,0 +1,487 @@
+/*
+ *  Probe module for 8250/16550-type Exar chips PCI serial ports.
+ *
+ *  Based on drivers/tty/serial/8250/8250_pci.c,
+ *
+ *  Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/8250_pci.h>
+
+#include <asm/byteorder.h>
+
+#include "8250.h"
+
+#define PCI_DEVICE_ID_COMMTECH_4224PCI335	0x0002
+#define PCI_DEVICE_ID_COMMTECH_4222PCI335	0x0004
+#define PCI_DEVICE_ID_COMMTECH_2324PCI335	0x000a
+#define PCI_DEVICE_ID_COMMTECH_2328PCI335	0x000b
+#define PCI_DEVICE_ID_COMMTECH_4224PCIE		0x0020
+#define PCI_DEVICE_ID_COMMTECH_4228PCIE		0x0021
+#define PCI_DEVICE_ID_COMMTECH_4222PCIE		0x0022
+#define PCI_DEVICE_ID_EXAR_XR17V4358		0x4358
+#define PCI_DEVICE_ID_EXAR_XR17V8358		0x8358
+
+#define UART_EXAR_8XMODE	0x88	/* 8X sampling rate select */
+
+#define UART_EXAR_FCTR		0x08	/* Feature Control Register */
+#define UART_FCTR_EXAR_IRDA	0x10	/* IrDa data encode select */
+#define UART_FCTR_EXAR_485	0x20	/* Auto 485 half duplex dir ctl */
+#define UART_FCTR_EXAR_TRGA	0x00	/* FIFO trigger table A */
+#define UART_FCTR_EXAR_TRGB	0x60	/* FIFO trigger table B */
+#define UART_FCTR_EXAR_TRGC	0x80	/* FIFO trigger table C */
+#define UART_FCTR_EXAR_TRGD	0xc0	/* FIFO trigger table D programmable */
+
+#define UART_EXAR_TXTRG		0x0a	/* Tx FIFO trigger level write-only */
+#define UART_EXAR_RXTRG		0x0b	/* Rx FIFO trigger level write-only */
+
+#define UART_EXAR_MPIOINT_7_0	0x8f	/* MPIOINT[7:0] */
+#define UART_EXAR_MPIOLVL_7_0	0x90	/* MPIOLVL[7:0] */
+#define UART_EXAR_MPIO3T_7_0	0x91	/* MPIO3T[7:0] */
+#define UART_EXAR_MPIOINV_7_0	0x92	/* MPIOINV[7:0] */
+#define UART_EXAR_MPIOSEL_7_0	0x93	/* MPIOSEL[7:0] */
+#define UART_EXAR_MPIOOD_7_0	0x94	/* MPIOOD[7:0] */
+#define UART_EXAR_MPIOINT_15_8	0x95	/* MPIOINT[15:8] */
+#define UART_EXAR_MPIOLVL_15_8	0x96	/* MPIOLVL[15:8] */
+#define UART_EXAR_MPIO3T_15_8	0x97	/* MPIO3T[15:8] */
+#define UART_EXAR_MPIOINV_15_8	0x98	/* MPIOINV[15:8] */
+#define UART_EXAR_MPIOSEL_15_8	0x99	/* MPIOSEL[15:8] */
+#define UART_EXAR_MPIOOD_15_8	0x9a	/* MPIOOD[15:8] */
+
+struct exar8250;
+
+/**
+ * struct exar8250_board - board information
+ * @num_ports: number of serial ports
+ * @reg_shift: describes UART register mapping in PCI memory
+ */
+struct exar8250_board {
+	unsigned int num_ports;
+	unsigned int reg_shift;
+	bool has_slave;
+	int	(*setup)(struct exar8250 *, struct pci_dev *,
+			 struct uart_8250_port *, int);
+	void	(*exit)(struct pci_dev *pcidev);
+};
+
+struct exar8250 {
+	unsigned int		nr;
+	struct exar8250_board	*board;
+	int			line[0];
+};
+
+static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
+			 int idx, unsigned int offset,
+			 struct uart_8250_port *port)
+{
+	const struct exar8250_board *board = priv->board;
+	unsigned int bar = 0;
+
+	if (!pcim_iomap_table(pcidev)[bar] && !pcim_iomap(pcidev, bar, 0))
+		return -ENOMEM;
+
+	port->port.iotype = UPIO_MEM;
+	port->port.mapbase = pci_resource_start(pcidev, bar) + offset;
+	port->port.membase = pcim_iomap_table(pcidev)[bar] + offset;
+	port->port.regshift = board->reg_shift;
+
+	return 0;
+}
+
+static int
+pci_fastcom335_setup(struct exar8250 *priv, struct pci_dev *pcidev,
+		     struct uart_8250_port *port, int idx)
+{
+	unsigned int offset = idx * 0x200;
+	unsigned int baud = 1843200;
+	u8 __iomem *p;
+	int err;
+
+	port->port.flags |= UPF_EXAR_EFR;
+	port->port.uartclk = baud * 16;
+
+	err = default_setup(priv, pcidev, idx, offset, port);
+	if (err)
+		return err;
+
+	p = port->port.membase;
+
+	writeb(0x00, p + UART_EXAR_8XMODE);
+	writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
+	writeb(32, p + UART_EXAR_TXTRG);
+	writeb(32, p + UART_EXAR_RXTRG);
+
+	/*
+	 * Setup Multipurpose Input/Output pins.
+	 */
+	if (idx == 0) {
+		switch (pcidev->device) {
+		case PCI_DEVICE_ID_COMMTECH_4222PCI335:
+		case PCI_DEVICE_ID_COMMTECH_4224PCI335:
+			writeb(0x78, p + UART_EXAR_MPIOLVL_7_0);
+			writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
+			writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
+			break;
+		case PCI_DEVICE_ID_COMMTECH_2324PCI335:
+		case PCI_DEVICE_ID_COMMTECH_2328PCI335:
+			writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
+			writeb(0xc0, p + UART_EXAR_MPIOINV_7_0);
+			writeb(0xc0, p + UART_EXAR_MPIOSEL_7_0);
+			break;
+		}
+		writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
+		writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
+		writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
+	}
+
+	return 0;
+}
+
+static int
+pci_connect_tech_setup(struct exar8250 *priv, struct pci_dev *pcidev,
+		       struct uart_8250_port *port, int idx)
+{
+	unsigned int offset = idx * 0x200;
+	unsigned int baud = 1843200;
+
+	port->port.uartclk = baud * 16;
+	return default_setup(priv, pcidev, idx, offset, port);
+}
+
+static int
+pci_xr17c154_setup(struct exar8250 *priv, struct pci_dev *pcidev,
+		   struct uart_8250_port *port, int idx)
+{
+	unsigned int offset = idx * 0x200;
+	unsigned int baud = 921600;
+
+	port->port.uartclk = baud * 16;
+	return default_setup(priv, pcidev, idx, offset, port);
+}
+
+static void setup_gpio(u8 __iomem *p)
+{
+	writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
+	writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
+	writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
+	writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
+	writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
+	writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
+	writeb(0x00, p + UART_EXAR_MPIOINT_15_8);
+	writeb(0x00, p + UART_EXAR_MPIOLVL_15_8);
+	writeb(0x00, p + UART_EXAR_MPIO3T_15_8);
+	writeb(0x00, p + UART_EXAR_MPIOINV_15_8);
+	writeb(0x00, p + UART_EXAR_MPIOSEL_15_8);
+	writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
+}
+
+static void *
+xr17v35x_register_gpio(struct pci_dev *pcidev)
+{
+	struct platform_device *pdev;
+
+	pdev = platform_device_alloc("gpio_exar", PLATFORM_DEVID_AUTO);
+	if (!pdev)
+		return NULL;
+
+	platform_set_drvdata(pdev, pcidev);
+	if (platform_device_add(pdev) < 0) {
+		platform_device_put(pdev);
+		return NULL;
+	}
+
+	return pdev;
+}
+
+static int
+pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
+		   struct uart_8250_port *port, int idx)
+{
+	const struct exar8250_board *board = priv->board;
+	unsigned int offset = idx * 0x400;
+	unsigned int baud = 7812500;
+	u8 __iomem *p;
+	int ret;
+
+	port->port.uartclk = baud * 16;
+	/*
+	 * Setup the uart clock for the devices on expansion slot to
+	 * half the clock speed of the main chip (which is 125MHz)
+	 */
+	if (board->has_slave && idx >= 8)
+		port->port.uartclk /= 2;
+
+	ret = default_setup(priv, pcidev, idx, offset, port);
+	if (ret)
+		return ret;
+
+	p = port->port.membase;
+
+	writeb(0x00, p + UART_EXAR_8XMODE);
+	writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
+	writeb(128, p + UART_EXAR_TXTRG);
+	writeb(128, p + UART_EXAR_RXTRG);
+
+	if (idx == 0) {
+		/* Setup Multipurpose Input/Output pins. */
+		setup_gpio(p);
+
+		port->port.private_data = xr17v35x_register_gpio(pcidev);
+	}
+
+	return 0;
+}
+
+static void pci_xr17v35x_exit(struct pci_dev *pcidev)
+{
+	struct exar8250 *priv = pci_get_drvdata(pcidev);
+	struct uart_8250_port *port = serial8250_get_port(priv->line[0]);
+	struct platform_device *pdev = port->port.private_data;
+
+	platform_device_unregister(pdev);
+	port->port.private_data = NULL;
+}
+
+static int
+exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
+{
+	unsigned int nr_ports, i, bar = 0, maxnr;
+	struct exar8250_board *board;
+	struct uart_8250_port uart;
+	struct exar8250 *priv;
+	int rc;
+
+	board = (struct exar8250_board *)ent->driver_data;
+	if (!board)
+		return -EINVAL;
+
+	rc = pcim_enable_device(pcidev);
+	if (rc)
+		return rc;
+
+	maxnr = pci_resource_len(pcidev, bar) >> (board->reg_shift + 3);
+
+	nr_ports = board->num_ports ? board->num_ports : pcidev->device & 0x0f;
+
+	priv = devm_kzalloc(&pcidev->dev, sizeof(*priv) +
+			    sizeof(unsigned int) * nr_ports,
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->board = board;
+
+	pci_set_master(pcidev);
+
+	rc = pci_alloc_irq_vectors(pcidev, 1, 1, PCI_IRQ_ALL_TYPES);
+	if (rc < 0)
+		return rc;
+
+	memset(&uart, 0, sizeof(uart));
+	uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ
+			  | UPF_EXAR_EFR;
+	uart.port.irq = pci_irq_vector(pcidev, 0);
+	uart.port.dev = &pcidev->dev;
+
+	for (i = 0; i < nr_ports && i < maxnr; i++) {
+		rc = board->setup(priv, pcidev, &uart, i);
+		if (rc) {
+			dev_err(&pcidev->dev, "Failed to setup port %u\n", i);
+			break;
+		}
+
+		dev_dbg(&pcidev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
+			uart.port.iobase, uart.port.irq, uart.port.iotype);
+
+		priv->line[i] = serial8250_register_8250_port(&uart);
+		if (priv->line[i] < 0) {
+			dev_err(&pcidev->dev,
+				"Couldn't register serial port %lx, irq %d, type %d, error %d\n",
+				uart.port.iobase, uart.port.irq,
+				uart.port.iotype, priv->line[i]);
+			break;
+		}
+	}
+	priv->nr = i;
+	pci_set_drvdata(pcidev, priv);
+	return 0;
+}
+
+static void exar_pci_remove(struct pci_dev *pcidev)
+{
+	struct exar8250 *priv = pci_get_drvdata(pcidev);
+	unsigned int i;
+
+	for (i = 0; i < priv->nr; i++)
+		serial8250_unregister_port(priv->line[i]);
+
+	if (priv->board->exit)
+		priv->board->exit(pcidev);
+}
+
+static int __maybe_unused exar_suspend(struct device *dev)
+{
+	struct pci_dev *pcidev = to_pci_dev(dev);
+	struct exar8250 *priv = pci_get_drvdata(pcidev);
+	unsigned int i;
+
+	for (i = 0; i < priv->nr; i++)
+		if (priv->line[i] >= 0)
+			serial8250_suspend_port(priv->line[i]);
+
+	/* Ensure that every init quirk is properly torn down */
+	if (priv->board->exit)
+		priv->board->exit(pcidev);
+
+	return 0;
+}
+
+static int __maybe_unused exar_resume(struct device *dev)
+{
+	struct pci_dev *pcidev = to_pci_dev(dev);
+	struct exar8250 *priv = pci_get_drvdata(pcidev);
+	unsigned int i;
+
+	for (i = 0; i < priv->nr; i++)
+		if (priv->line[i] >= 0)
+			serial8250_resume_port(priv->line[i]);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
+
+static const struct exar8250_board pbn_fastcom335_2 = {
+	.num_ports	= 2,
+	.setup		= pci_fastcom335_setup,
+};
+
+static const struct exar8250_board pbn_fastcom335_4 = {
+	.num_ports	= 4,
+	.setup		= pci_fastcom335_setup,
+};
+
+static const struct exar8250_board pbn_fastcom335_8 = {
+	.num_ports	= 8,
+	.setup		= pci_fastcom335_setup,
+};
+
+static const struct exar8250_board pbn_connect = {
+	.setup		= pci_connect_tech_setup,
+};
+
+static const struct exar8250_board pbn_exar_ibm_saturn = {
+	.num_ports	= 1,
+	.setup		= pci_xr17c154_setup,
+};
+
+static const struct exar8250_board pbn_exar_XR17C15x = {
+	.setup		= pci_xr17c154_setup,
+};
+
+static const struct exar8250_board pbn_exar_XR17V35x = {
+	.setup		= pci_xr17v35x_setup,
+	.exit		= pci_xr17v35x_exit,
+};
+
+static const struct exar8250_board pbn_exar_XR17V4358 = {
+	.num_ports	= 12,
+	.has_slave	= true,
+	.setup		= pci_xr17v35x_setup,
+	.exit		= pci_xr17v35x_exit,
+};
+
+static const struct exar8250_board pbn_exar_XR17V8358 = {
+	.num_ports	= 16,
+	.has_slave	= true,
+	.setup		= pci_xr17v35x_setup,
+	.exit		= pci_xr17v35x_exit,
+};
+
+#define CONNECT_DEVICE(devid, sdevid, bd) {				\
+	PCI_DEVICE_SUB(							\
+		PCI_VENDOR_ID_EXAR,					\
+		PCI_DEVICE_ID_EXAR_##devid,				\
+		PCI_SUBVENDOR_ID_CONNECT_TECH,				\
+		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_##sdevid), 0, 0,	\
+		(kernel_ulong_t)&bd					\
+	}
+
+#define EXAR_DEVICE(vend, devid, bd) {					\
+	PCI_VDEVICE(vend, PCI_DEVICE_ID_##devid), (kernel_ulong_t)&bd	\
+	}
+
+#define IBM_DEVICE(devid, sdevid, bd) {			\
+	PCI_DEVICE_SUB(					\
+		PCI_VENDOR_ID_EXAR,			\
+		PCI_DEVICE_ID_EXAR_##devid,		\
+		PCI_VENDOR_ID_IBM,			\
+		PCI_SUBDEVICE_ID_IBM_##sdevid), 0, 0,	\
+		(kernel_ulong_t)&bd			\
+	}
+
+static struct pci_device_id exar_pci_tbl[] = {
+	CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect),
+	CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect),
+	CONNECT_DEVICE(XR17C158, UART_8_232, pbn_connect),
+	CONNECT_DEVICE(XR17C152, UART_1_1, pbn_connect),
+	CONNECT_DEVICE(XR17C154, UART_2_2, pbn_connect),
+	CONNECT_DEVICE(XR17C158, UART_4_4, pbn_connect),
+	CONNECT_DEVICE(XR17C152, UART_2, pbn_connect),
+	CONNECT_DEVICE(XR17C154, UART_4, pbn_connect),
+	CONNECT_DEVICE(XR17C158, UART_8, pbn_connect),
+	CONNECT_DEVICE(XR17C152, UART_2_485, pbn_connect),
+	CONNECT_DEVICE(XR17C154, UART_4_485, pbn_connect),
+	CONNECT_DEVICE(XR17C158, UART_8_485, pbn_connect),
+
+	IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn),
+
+	/* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */
+	EXAR_DEVICE(EXAR, EXAR_XR17C152, pbn_exar_XR17C15x),
+	EXAR_DEVICE(EXAR, EXAR_XR17C154, pbn_exar_XR17C15x),
+	EXAR_DEVICE(EXAR, EXAR_XR17C158, pbn_exar_XR17C15x),
+
+	/* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs */
+	EXAR_DEVICE(EXAR, EXAR_XR17V352, pbn_exar_XR17V35x),
+	EXAR_DEVICE(EXAR, EXAR_XR17V354, pbn_exar_XR17V35x),
+	EXAR_DEVICE(EXAR, EXAR_XR17V358, pbn_exar_XR17V35x),
+	EXAR_DEVICE(EXAR, EXAR_XR17V4358, pbn_exar_XR17V4358),
+	EXAR_DEVICE(EXAR, EXAR_XR17V8358, pbn_exar_XR17V8358),
+	EXAR_DEVICE(COMMTECH, COMMTECH_4222PCIE, pbn_exar_XR17V35x),
+	EXAR_DEVICE(COMMTECH, COMMTECH_4224PCIE, pbn_exar_XR17V35x),
+	EXAR_DEVICE(COMMTECH, COMMTECH_4228PCIE, pbn_exar_XR17V35x),
+
+	EXAR_DEVICE(COMMTECH, COMMTECH_4222PCI335, pbn_fastcom335_2),
+	EXAR_DEVICE(COMMTECH, COMMTECH_4224PCI335, pbn_fastcom335_4),
+	EXAR_DEVICE(COMMTECH, COMMTECH_2324PCI335, pbn_fastcom335_4),
+	EXAR_DEVICE(COMMTECH, COMMTECH_2328PCI335, pbn_fastcom335_8),
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, exar_pci_tbl);
+
+static struct pci_driver exar_pci_driver = {
+	.name		= "exar_serial",
+	.probe		= exar_pci_probe,
+	.remove		= exar_pci_remove,
+	.driver         = {
+		.pm     = &exar_pci_pm,
+	},
+	.id_table	= exar_pci_tbl,
+};
+module_pci_driver(exar_pci_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Exar Serial Dricer");
+MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");

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

@@ -60,6 +60,10 @@ static int __init serial_init_chip(struct parisc_device *dev)
 					7272727 : 1843200;
 					7272727 : 1843200;
 	uart.port.mapbase	= address;
 	uart.port.mapbase	= address;
 	uart.port.membase	= ioremap_nocache(address, 16);
 	uart.port.membase	= ioremap_nocache(address, 16);
+	if (!uart.port.membase) {
+		dev_warn(&dev->dev, "Failed to map memory\n");
+		return -ENOMEM;
+	}
 	uart.port.irq	= dev->irq;
 	uart.port.irq	= dev->irq;
 	uart.port.flags	= UPF_BOOT_AUTOCONF;
 	uart.port.flags	= UPF_BOOT_AUTOCONF;
 	uart.port.dev	= &dev->dev;
 	uart.port.dev	= &dev->dev;

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

@@ -19,7 +19,7 @@
 
 
 #include "8250.h"
 #include "8250.h"
 
 
-#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
+#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI) && !defined(CONFIG_COMPILE_TEST)
 #warning CONFIG_SERIAL_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
 #warning CONFIG_SERIAL_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
 #endif
 #endif
 
 

+ 2 - 2
drivers/tty/serial/8250/8250_lpss.c

@@ -332,10 +332,10 @@ static void lpss8250_remove(struct pci_dev *pdev)
 {
 {
 	struct lpss8250 *lpss = pci_get_drvdata(pdev);
 	struct lpss8250 *lpss = pci_get_drvdata(pdev);
 
 
+	serial8250_unregister_port(lpss->line);
+
 	if (lpss->board->exit)
 	if (lpss->board->exit)
 		lpss->board->exit(lpss);
 		lpss->board->exit(lpss);
-
-	serial8250_unregister_port(lpss->line);
 }
 }
 
 
 static const struct lpss8250_board byt_board = {
 static const struct lpss8250_board byt_board = {

+ 42 - 3
drivers/tty/serial/8250/8250_mid.c

@@ -75,6 +75,37 @@ static int pnw_setup(struct mid8250 *mid, struct uart_port *p)
 	return 0;
 	return 0;
 }
 }
 
 
+static int tng_handle_irq(struct uart_port *p)
+{
+	struct mid8250 *mid = p->private_data;
+	struct uart_8250_port *up = up_to_u8250p(p);
+	struct hsu_dma_chip *chip;
+	u32 status;
+	int ret = 0;
+	int err;
+
+	chip = pci_get_drvdata(mid->dma_dev);
+
+	/* Rx DMA */
+	err = hsu_dma_get_status(chip, mid->dma_index * 2 + 1, &status);
+	if (err > 0) {
+		serial8250_rx_dma_flush(up);
+		ret |= 1;
+	} else if (err == 0)
+		ret |= hsu_dma_do_irq(chip, mid->dma_index * 2 + 1, status);
+
+	/* Tx DMA */
+	err = hsu_dma_get_status(chip, mid->dma_index * 2, &status);
+	if (err > 0)
+		ret |= 1;
+	else if (err == 0)
+		ret |= hsu_dma_do_irq(chip, mid->dma_index * 2, status);
+
+	/* UART */
+	ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+	return IRQ_RETVAL(ret);
+}
+
 static int tng_setup(struct mid8250 *mid, struct uart_port *p)
 static int tng_setup(struct mid8250 *mid, struct uart_port *p)
 {
 {
 	struct pci_dev *pdev = to_pci_dev(p->dev);
 	struct pci_dev *pdev = to_pci_dev(p->dev);
@@ -90,6 +121,8 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
 
 
 	mid->dma_index = index;
 	mid->dma_index = index;
 	mid->dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
 	mid->dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
+
+	p->handle_irq = tng_handle_irq;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -131,8 +164,16 @@ static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
 	unsigned int bar = FL_GET_BASE(mid->board->flags);
 	unsigned int bar = FL_GET_BASE(mid->board->flags);
 	int ret;
 	int ret;
 
 
+	pci_set_master(pdev);
+
+	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+	if (ret < 0)
+		return ret;
+
+	p->irq = pci_irq_vector(pdev, 0);
+
 	chip->dev = &pdev->dev;
 	chip->dev = &pdev->dev;
-	chip->irq = pdev->irq;
+	chip->irq = pci_irq_vector(pdev, 0);
 	chip->regs = p->membase;
 	chip->regs = p->membase;
 	chip->length = pci_resource_len(pdev, bar);
 	chip->length = pci_resource_len(pdev, bar);
 	chip->offset = DNV_DMA_CHAN_OFFSET;
 	chip->offset = DNV_DMA_CHAN_OFFSET;
@@ -250,8 +291,6 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	pci_set_master(pdev);
-
 	mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL);
 	mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL);
 	if (!mid)
 	if (!mid)
 		return -ENOMEM;
 		return -ENOMEM;

+ 1 - 0
drivers/tty/serial/8250/8250_moxa.c

@@ -68,6 +68,7 @@ static int moxa8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 			   sizeof(unsigned int) * nr_ports, GFP_KERNEL);
 			   sizeof(unsigned int) * nr_ports, GFP_KERNEL);
 	if (!brd)
 	if (!brd)
 		return -ENOMEM;
 		return -ENOMEM;
+	brd->num_ports = nr_ports;
 
 
 	memset(&uart, 0, sizeof(struct uart_8250_port));
 	memset(&uart, 0, sizeof(struct uart_8250_port));
 
 

+ 25 - 69
drivers/tty/serial/8250/8250_of.c

@@ -172,7 +172,8 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 {
 {
 	const struct of_device_id *match;
 	const struct of_device_id *match;
 	struct of_serial_info *info;
 	struct of_serial_info *info;
-	struct uart_port port;
+	struct uart_8250_port port8250;
+	u32 tx_threshold;
 	int port_type;
 	int port_type;
 	int ret;
 	int ret;
 
 
@@ -188,41 +189,24 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	port_type = (unsigned long)match->data;
 	port_type = (unsigned long)match->data;
-	ret = of_platform_serial_setup(ofdev, port_type, &port, info);
+	memset(&port8250, 0, sizeof(port8250));
+	ret = of_platform_serial_setup(ofdev, port_type, &port8250.port, info);
 	if (ret)
 	if (ret)
 		goto out;
 		goto out;
 
 
-	switch (port_type) {
-	case PORT_8250 ... PORT_MAX_8250:
-	{
-		u32 tx_threshold;
-		struct uart_8250_port port8250;
-		memset(&port8250, 0, sizeof(port8250));
-		port8250.port = port;
+	if (port8250.port.fifosize)
+		port8250.capabilities = UART_CAP_FIFO;
 
 
-		if (port.fifosize)
-			port8250.capabilities = UART_CAP_FIFO;
+	/* Check for TX FIFO threshold & set tx_loadsz */
+	if ((of_property_read_u32(ofdev->dev.of_node, "tx-threshold",
+				  &tx_threshold) == 0) &&
+	    (tx_threshold < port8250.port.fifosize))
+		port8250.tx_loadsz = port8250.port.fifosize - tx_threshold;
 
 
-		/* Check for TX FIFO threshold & set tx_loadsz */
-		if ((of_property_read_u32(ofdev->dev.of_node, "tx-threshold",
-					  &tx_threshold) == 0) &&
-		    (tx_threshold < port.fifosize))
-			port8250.tx_loadsz = port.fifosize - tx_threshold;
+	if (of_property_read_bool(ofdev->dev.of_node, "auto-flow-control"))
+		port8250.capabilities |= UART_CAP_AFE;
 
 
-		if (of_property_read_bool(ofdev->dev.of_node,
-					  "auto-flow-control"))
-			port8250.capabilities |= UART_CAP_AFE;
-
-		ret = serial8250_register_8250_port(&port8250);
-		break;
-	}
-	default:
-		/* need to add code for these */
-	case PORT_UNKNOWN:
-		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
-		ret = -ENODEV;
-		break;
-	}
+	ret = serial8250_register_8250_port(&port8250);
 	if (ret < 0)
 	if (ret < 0)
 		goto out;
 		goto out;
 
 
@@ -232,7 +216,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 	return 0;
 	return 0;
 out:
 out:
 	kfree(info);
 	kfree(info);
-	irq_dispose_mapping(port.irq);
+	irq_dispose_mapping(port8250.port.irq);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -242,14 +226,8 @@ out:
 static int of_platform_serial_remove(struct platform_device *ofdev)
 static int of_platform_serial_remove(struct platform_device *ofdev)
 {
 {
 	struct of_serial_info *info = platform_get_drvdata(ofdev);
 	struct of_serial_info *info = platform_get_drvdata(ofdev);
-	switch (info->type) {
-	case PORT_8250 ... PORT_MAX_8250:
-		serial8250_unregister_port(info->line);
-		break;
-	default:
-		/* need to add code for these */
-		break;
-	}
+
+	serial8250_unregister_port(info->line);
 
 
 	if (info->clk)
 	if (info->clk)
 		clk_disable_unprepare(info->clk);
 		clk_disable_unprepare(info->clk);
@@ -258,18 +236,23 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
 }
 }
 
 
 #ifdef CONFIG_PM_SLEEP
 #ifdef CONFIG_PM_SLEEP
-static void of_serial_suspend_8250(struct of_serial_info *info)
+static int of_serial_suspend(struct device *dev)
 {
 {
+	struct of_serial_info *info = dev_get_drvdata(dev);
 	struct uart_8250_port *port8250 = serial8250_get_port(info->line);
 	struct uart_8250_port *port8250 = serial8250_get_port(info->line);
 	struct uart_port *port = &port8250->port;
 	struct uart_port *port = &port8250->port;
 
 
 	serial8250_suspend_port(info->line);
 	serial8250_suspend_port(info->line);
+
 	if (info->clk && (!uart_console(port) || console_suspend_enabled))
 	if (info->clk && (!uart_console(port) || console_suspend_enabled))
 		clk_disable_unprepare(info->clk);
 		clk_disable_unprepare(info->clk);
+
+	return 0;
 }
 }
 
 
-static void of_serial_resume_8250(struct of_serial_info *info)
+static int of_serial_resume(struct device *dev)
 {
 {
+	struct of_serial_info *info = dev_get_drvdata(dev);
 	struct uart_8250_port *port8250 = serial8250_get_port(info->line);
 	struct uart_8250_port *port8250 = serial8250_get_port(info->line);
 	struct uart_port *port = &port8250->port;
 	struct uart_port *port = &port8250->port;
 
 
@@ -277,34 +260,6 @@ static void of_serial_resume_8250(struct of_serial_info *info)
 		clk_prepare_enable(info->clk);
 		clk_prepare_enable(info->clk);
 
 
 	serial8250_resume_port(info->line);
 	serial8250_resume_port(info->line);
-}
-
-static int of_serial_suspend(struct device *dev)
-{
-	struct of_serial_info *info = dev_get_drvdata(dev);
-
-	switch (info->type) {
-	case PORT_8250 ... PORT_MAX_8250:
-		of_serial_suspend_8250(info);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int of_serial_resume(struct device *dev)
-{
-	struct of_serial_info *info = dev_get_drvdata(dev);
-
-	switch (info->type) {
-	case PORT_8250 ... PORT_MAX_8250:
-		of_serial_resume_8250(info);
-		break;
-	default:
-		break;
-	}
 
 
 	return 0;
 	return 0;
 }
 }
@@ -332,6 +287,7 @@ static const struct of_device_id of_platform_serial_table[] = {
 		.data = (void *)PORT_ALTR_16550_F128, },
 		.data = (void *)PORT_ALTR_16550_F128, },
 	{ .compatible = "mrvl,mmp-uart",
 	{ .compatible = "mrvl,mmp-uart",
 		.data = (void *)PORT_XSCALE, },
 		.data = (void *)PORT_XSCALE, },
+	{ .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
 	{ /* end of list */ },
 	{ /* end of list */ },
 };
 };
 MODULE_DEVICE_TABLE(of, of_platform_serial_table);
 MODULE_DEVICE_TABLE(of, of_platform_serial_table);

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

@@ -790,6 +790,7 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
 {
 {
 	struct omap8250_priv	*priv = p->port.private_data;
 	struct omap8250_priv	*priv = p->port.private_data;
 	struct uart_8250_dma	*dma = p->dma;
 	struct uart_8250_dma	*dma = p->dma;
+	struct dma_tx_state     state;
 	unsigned long		flags;
 	unsigned long		flags;
 	int ret;
 	int ret;
 
 
@@ -800,10 +801,12 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
 		return;
 		return;
 	}
 	}
 
 
-	ret = dmaengine_pause(dma->rxchan);
-	if (WARN_ON_ONCE(ret))
-		priv->rx_dma_broken = true;
-
+	ret = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+	if (ret == DMA_IN_PROGRESS) {
+		ret = dmaengine_pause(dma->rxchan);
+		if (WARN_ON_ONCE(ret))
+			priv->rx_dma_broken = true;
+	}
 	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
 	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
 
 
 	__dma_rx_do_complete(p);
 	__dma_rx_do_complete(p);
@@ -1075,15 +1078,15 @@ static int omap8250_no_handle_irq(struct uart_port *port)
 }
 }
 
 
 static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
 static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
-static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE;
+static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE;
 
 
 static const struct of_device_id omap8250_dt_ids[] = {
 static const struct of_device_id omap8250_dt_ids[] = {
 	{ .compatible = "ti,omap2-uart" },
 	{ .compatible = "ti,omap2-uart" },
 	{ .compatible = "ti,omap3-uart" },
 	{ .compatible = "ti,omap3-uart" },
 	{ .compatible = "ti,omap4-uart" },
 	{ .compatible = "ti,omap4-uart" },
 	{ .compatible = "ti,am3352-uart", .data = &am3352_habit, },
 	{ .compatible = "ti,am3352-uart", .data = &am3352_habit, },
-	{ .compatible = "ti,am4372-uart", .data = &am4372_habit, },
-	{ .compatible = "ti,dra742-uart", .data = &am4372_habit, },
+	{ .compatible = "ti,am4372-uart", .data = &am3352_habit, },
+	{ .compatible = "ti,dra742-uart", .data = &dra742_habit, },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
 MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
@@ -1218,14 +1221,6 @@ static int omap8250_probe(struct platform_device *pdev)
 			priv->omap8250_dma.rx_size = RX_TRIGGER;
 			priv->omap8250_dma.rx_size = RX_TRIGGER;
 			priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
 			priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
 			priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
 			priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
-
-			if (of_machine_is_compatible("ti,am33xx"))
-				priv->habit |= OMAP_DMA_TX_KICK;
-			/*
-			 * pause is currently not supported atleast on omap-sdma
-			 * and edma on most earlier kernels.
-			 */
-			priv->rx_dma_broken = true;
 		}
 		}
 	}
 	}
 #endif
 #endif
@@ -1240,7 +1235,8 @@ static int omap8250_probe(struct platform_device *pdev)
 	pm_runtime_put_autosuspend(&pdev->dev);
 	pm_runtime_put_autosuspend(&pdev->dev);
 	return 0;
 	return 0;
 err:
 err:
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return ret;
 	return ret;
 }
 }
@@ -1249,6 +1245,7 @@ static int omap8250_remove(struct platform_device *pdev)
 {
 {
 	struct omap8250_priv *priv = platform_get_drvdata(pdev);
 	struct omap8250_priv *priv = platform_get_drvdata(pdev);
 
 
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	serial8250_unregister_port(priv->line);
 	serial8250_unregister_port(priv->line);
@@ -1348,6 +1345,10 @@ static int omap8250_runtime_suspend(struct device *dev)
 	struct omap8250_priv *priv = dev_get_drvdata(dev);
 	struct omap8250_priv *priv = dev_get_drvdata(dev);
 	struct uart_8250_port *up;
 	struct uart_8250_port *up;
 
 
+	/* In case runtime-pm tries this before we are setup */
+	if (!priv)
+		return 0;
+
 	up = serial8250_get_port(priv->line);
 	up = serial8250_get_port(priv->line);
 	/*
 	/*
 	 * When using 'no_console_suspend', the console UART must not be
 	 * When using 'no_console_suspend', the console UART must not be

+ 22 - 493
drivers/tty/serial/8250/8250_pci.c

@@ -1477,11 +1477,16 @@ static int pci_fintek_init(struct pci_dev *dev)
 {
 {
 	unsigned long iobase;
 	unsigned long iobase;
 	u32 max_port, i;
 	u32 max_port, i;
-	u32 bar_data[3];
+	resource_size_t bar_data[3];
 	u8 config_base;
 	u8 config_base;
 	struct serial_private *priv = pci_get_drvdata(dev);
 	struct serial_private *priv = pci_get_drvdata(dev);
 	struct uart_8250_port *port;
 	struct uart_8250_port *port;
 
 
+	if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) ||
+			!(pci_resource_flags(dev, 4) & IORESOURCE_IO) ||
+			!(pci_resource_flags(dev, 3) & IORESOURCE_IO))
+		return -ENODEV;
+
 	switch (dev->device) {
 	switch (dev->device) {
 	case 0x1104: /* 4 ports */
 	case 0x1104: /* 4 ports */
 	case 0x1108: /* 8 ports */
 	case 0x1108: /* 8 ports */
@@ -1495,9 +1500,9 @@ static int pci_fintek_init(struct pci_dev *dev)
 	}
 	}
 
 
 	/* Get the io address dispatch from the BIOS */
 	/* Get the io address dispatch from the BIOS */
-	pci_read_config_dword(dev, 0x24, &bar_data[0]);
-	pci_read_config_dword(dev, 0x20, &bar_data[1]);
-	pci_read_config_dword(dev, 0x1c, &bar_data[2]);
+	bar_data[0] = pci_resource_start(dev, 5);
+	bar_data[1] = pci_resource_start(dev, 4);
+	bar_data[2] = pci_resource_start(dev, 3);
 
 
 	for (i = 0; i < max_port; ++i) {
 	for (i = 0; i < max_port; ++i) {
 		/* UART0 configuration offset start from 0x40 */
 		/* UART0 configuration offset start from 0x40 */
@@ -1605,135 +1610,6 @@ 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
-
-#define UART_EXAR_MPIOINT_7_0	0x8f	/* MPIOINT[7:0] */
-#define UART_EXAR_MPIOLVL_7_0	0x90	/* MPIOLVL[7:0] */
-#define UART_EXAR_MPIO3T_7_0	0x91	/* MPIO3T[7:0] */
-#define UART_EXAR_MPIOINV_7_0	0x92	/* MPIOINV[7:0] */
-#define UART_EXAR_MPIOSEL_7_0	0x93	/* MPIOSEL[7:0] */
-#define UART_EXAR_MPIOOD_7_0	0x94	/* MPIOOD[7:0] */
-#define UART_EXAR_MPIOINT_15_8	0x95	/* MPIOINT[15:8] */
-#define UART_EXAR_MPIOLVL_15_8	0x96	/* MPIOLVL[15:8] */
-#define UART_EXAR_MPIO3T_15_8	0x97	/* MPIO3T[15:8] */
-#define UART_EXAR_MPIOINV_15_8	0x98	/* MPIOINV[15:8] */
-#define UART_EXAR_MPIOSEL_15_8	0x99	/* MPIOSEL[15:8] */
-#define UART_EXAR_MPIOOD_15_8	0x9a	/* MPIOOD[15:8] */
-
-static int
-pci_xr17c154_setup(struct serial_private *priv,
-		  const struct pciserial_board *board,
-		  struct uart_8250_port *port, int idx)
-{
-	port->port.flags |= UPF_EXAR_EFR;
-	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
-pci_xr17v35x_setup(struct serial_private *priv,
-		  const struct pciserial_board *board,
-		  struct uart_8250_port *port, int idx)
-{
-	u8 __iomem *p;
-
-	p = pci_ioremap_bar(priv->dev, 0);
-	if (p == NULL)
-		return -ENOMEM;
-
-	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.
-	 */
-	if (idx == 0) {
-		writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
-		writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
-		writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
-		writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
-		writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
-		writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
-		writeb(0x00, p + UART_EXAR_MPIOINT_15_8);
-		writeb(0x00, p + UART_EXAR_MPIOLVL_15_8);
-		writeb(0x00, p + UART_EXAR_MPIO3T_15_8);
-		writeb(0x00, p + UART_EXAR_MPIOINV_15_8);
-		writeb(0x00, p + UART_EXAR_MPIOSEL_15_8);
-		writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
-	}
-	writeb(0x00, p + UART_EXAR_8XMODE);
-	writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
-	writeb(128, p + UART_EXAR_TXTRG);
-	writeb(128, p + UART_EXAR_RXTRG);
-	iounmap(p);
-
-	return pci_default_setup(priv, board, port, idx);
-}
-
-#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004
-#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002
-#define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a
-#define PCI_DEVICE_ID_COMMTECH_2328PCI335 0x000b
-
-static int
-pci_fastcom335_setup(struct serial_private *priv,
-		  const struct pciserial_board *board,
-		  struct uart_8250_port *port, int idx)
-{
-	u8 __iomem *p;
-
-	p = pci_ioremap_bar(priv->dev, 0);
-	if (p == NULL)
-		return -ENOMEM;
-
-	port->port.flags |= UPF_EXAR_EFR;
-
-	/*
-	 * Setup Multipurpose Input/Output pins.
-	 */
-	if (idx == 0) {
-		switch (priv->dev->device) {
-		case PCI_DEVICE_ID_COMMTECH_4222PCI335:
-		case PCI_DEVICE_ID_COMMTECH_4224PCI335:
-			writeb(0x78, p + UART_EXAR_MPIOLVL_7_0);
-			writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
-			writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
-			break;
-		case PCI_DEVICE_ID_COMMTECH_2324PCI335:
-		case PCI_DEVICE_ID_COMMTECH_2328PCI335:
-			writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
-			writeb(0xc0, p + UART_EXAR_MPIOINV_7_0);
-			writeb(0xc0, p + UART_EXAR_MPIOSEL_7_0);
-			break;
-		}
-		writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
-		writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
-		writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
-	}
-	writeb(0x00, p + UART_EXAR_8XMODE);
-	writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
-	writeb(32, p + UART_EXAR_TXTRG);
-	writeb(32, p + UART_EXAR_RXTRG);
-	iounmap(p);
-
-	return pci_default_setup(priv, board, port, idx);
-}
-
 static int
 static int
 pci_wch_ch353_setup(struct serial_private *priv,
 pci_wch_ch353_setup(struct serial_private *priv,
 		    const struct pciserial_board *board,
 		    const struct pciserial_board *board,
@@ -1809,9 +1685,6 @@ pci_wch_ch38x_setup(struct serial_private *priv,
 #define PCI_VENDOR_ID_AGESTAR		0x5372
 #define PCI_VENDOR_ID_AGESTAR		0x5372
 #define PCI_DEVICE_ID_AGESTAR_9375	0x6872
 #define PCI_DEVICE_ID_AGESTAR_9375	0x6872
 #define PCI_VENDOR_ID_ASIX		0x9710
 #define PCI_VENDOR_ID_ASIX		0x9710
-#define PCI_DEVICE_ID_COMMTECH_4224PCIE	0x0020
-#define PCI_DEVICE_ID_COMMTECH_4228PCIE	0x0021
-#define PCI_DEVICE_ID_COMMTECH_4222PCIE	0x0022
 #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
 #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
 #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
 #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
 
 
@@ -2272,65 +2145,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.init		= pci_timedia_init,
 		.init		= pci_timedia_init,
 		.setup		= pci_timedia_setup,
 		.setup		= pci_timedia_setup,
 	},
 	},
-	/*
-	 * Exar cards
-	 */
-	{
-		.vendor = PCI_VENDOR_ID_EXAR,
-		.device = PCI_DEVICE_ID_EXAR_XR17C152,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17c154_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EXAR,
-		.device = PCI_DEVICE_ID_EXAR_XR17C154,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17c154_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EXAR,
-		.device = PCI_DEVICE_ID_EXAR_XR17C158,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17c154_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EXAR,
-		.device = PCI_DEVICE_ID_EXAR_XR17V352,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17v35x_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EXAR,
-		.device = PCI_DEVICE_ID_EXAR_XR17V354,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17v35x_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EXAR,
-		.device = PCI_DEVICE_ID_EXAR_XR17V358,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.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,
-		.device = PCI_DEVICE_ID_EXAR_XR17V8358,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17v35x_setup,
-	},
 	/*
 	/*
 	 * Xircom cards
 	 * Xircom cards
 	 */
 	 */
@@ -2555,59 +2369,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.setup		= pci_asix_setup,
 		.setup		= pci_asix_setup,
 	},
 	},
-	/*
-	 * Commtech, Inc. Fastcom adapters
-	 *
-	 */
-	{
-		.vendor = PCI_VENDOR_ID_COMMTECH,
-		.device = PCI_DEVICE_ID_COMMTECH_4222PCI335,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_fastcom335_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_COMMTECH,
-		.device = PCI_DEVICE_ID_COMMTECH_4224PCI335,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_fastcom335_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_COMMTECH,
-		.device = PCI_DEVICE_ID_COMMTECH_2324PCI335,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_fastcom335_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_COMMTECH,
-		.device = PCI_DEVICE_ID_COMMTECH_2328PCI335,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_fastcom335_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_COMMTECH,
-		.device = PCI_DEVICE_ID_COMMTECH_4222PCIE,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17v35x_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_COMMTECH,
-		.device = PCI_DEVICE_ID_COMMTECH_4224PCIE,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17v35x_setup,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_COMMTECH,
-		.device = PCI_DEVICE_ID_COMMTECH_4228PCIE,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_xr17v35x_setup,
-	},
 	/*
 	/*
 	 * Broadcom TruManage (NetXtreme)
 	 * Broadcom TruManage (NetXtreme)
 	 */
 	 */
@@ -2719,17 +2480,11 @@ enum pci_board_num_t {
 
 
 	pbn_b0_4_1152000,
 	pbn_b0_4_1152000,
 
 
-	pbn_b0_2_1152000_200,
-	pbn_b0_4_1152000_200,
-	pbn_b0_8_1152000_200,
+	pbn_b0_4_1250000,
 
 
 	pbn_b0_2_1843200,
 	pbn_b0_2_1843200,
 	pbn_b0_4_1843200,
 	pbn_b0_4_1843200,
 
 
-	pbn_b0_2_1843200_200,
-	pbn_b0_4_1843200_200,
-	pbn_b0_8_1843200_200,
-
 	pbn_b0_1_4000000,
 	pbn_b0_1_4000000,
 
 
 	pbn_b0_bt_1_115200,
 	pbn_b0_bt_1_115200,
@@ -2820,15 +2575,6 @@ enum pci_board_num_t {
 	pbn_computone_6,
 	pbn_computone_6,
 	pbn_computone_8,
 	pbn_computone_8,
 	pbn_sbsxrsio,
 	pbn_sbsxrsio,
-	pbn_exar_XR17C152,
-	pbn_exar_XR17C154,
-	pbn_exar_XR17C158,
-	pbn_exar_XR17V352,
-	pbn_exar_XR17V354,
-	pbn_exar_XR17V358,
-	pbn_exar_XR17V4358,
-	pbn_exar_XR17V8358,
-	pbn_exar_ibm_saturn,
 	pbn_pasemi_1682M,
 	pbn_pasemi_1682M,
 	pbn_ni8430_2,
 	pbn_ni8430_2,
 	pbn_ni8430_4,
 	pbn_ni8430_4,
@@ -2933,25 +2679,11 @@ static struct pciserial_board pci_boards[] = {
 		.uart_offset	= 8,
 		.uart_offset	= 8,
 	},
 	},
 
 
-	[pbn_b0_2_1152000_200] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 2,
-		.base_baud	= 1152000,
-		.uart_offset	= 0x200,
-	},
-
-	[pbn_b0_4_1152000_200] = {
+	[pbn_b0_4_1250000] = {
 		.flags		= FL_BASE0,
 		.flags		= FL_BASE0,
 		.num_ports	= 4,
 		.num_ports	= 4,
-		.base_baud	= 1152000,
-		.uart_offset	= 0x200,
-	},
-
-	[pbn_b0_8_1152000_200] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 8,
-		.base_baud	= 1152000,
-		.uart_offset	= 0x200,
+		.base_baud	= 1250000,
+		.uart_offset	= 8,
 	},
 	},
 
 
 	[pbn_b0_2_1843200] = {
 	[pbn_b0_2_1843200] = {
@@ -2967,24 +2699,6 @@ static struct pciserial_board pci_boards[] = {
 		.uart_offset	= 8,
 		.uart_offset	= 8,
 	},
 	},
 
 
-	[pbn_b0_2_1843200_200] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 2,
-		.base_baud	= 1843200,
-		.uart_offset	= 0x200,
-	},
-	[pbn_b0_4_1843200_200] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 4,
-		.base_baud	= 1843200,
-		.uart_offset	= 0x200,
-	},
-	[pbn_b0_8_1843200_200] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 8,
-		.base_baud	= 1843200,
-		.uart_offset	= 0x200,
-	},
 	[pbn_b0_1_4000000] = {
 	[pbn_b0_1_4000000] = {
 		.flags		= FL_BASE0,
 		.flags		= FL_BASE0,
 		.num_ports	= 1,
 		.num_ports	= 1,
@@ -3468,76 +3182,6 @@ static struct pciserial_board pci_boards[] = {
 		.uart_offset	= 256,
 		.uart_offset	= 256,
 		.reg_shift	= 4,
 		.reg_shift	= 4,
 	},
 	},
-	/*
-	 * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
-	 *  Only basic 16550A support.
-	 *  XR17C15[24] are not tested, but they should work.
-	 */
-	[pbn_exar_XR17C152] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 2,
-		.base_baud	= 921600,
-		.uart_offset	= 0x200,
-	},
-	[pbn_exar_XR17C154] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 4,
-		.base_baud	= 921600,
-		.uart_offset	= 0x200,
-	},
-	[pbn_exar_XR17C158] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 8,
-		.base_baud	= 921600,
-		.uart_offset	= 0x200,
-	},
-	[pbn_exar_XR17V352] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 2,
-		.base_baud	= 7812500,
-		.uart_offset	= 0x400,
-		.reg_shift	= 0,
-		.first_offset	= 0,
-	},
-	[pbn_exar_XR17V354] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 4,
-		.base_baud	= 7812500,
-		.uart_offset	= 0x400,
-		.reg_shift	= 0,
-		.first_offset	= 0,
-	},
-	[pbn_exar_XR17V358] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 8,
-		.base_baud	= 7812500,
-		.uart_offset	= 0x400,
-		.reg_shift	= 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] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 16,
-		.base_baud	= 7812500,
-		.uart_offset	= 0x400,
-		.reg_shift	= 0,
-		.first_offset	= 0,
-	},
-	[pbn_exar_ibm_saturn] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 1,
-		.base_baud	= 921600,
-		.uart_offset	= 0x200,
-	},
-
 	/*
 	/*
 	 * PA Semi PWRficient PA6T-1682M on-chip UART
 	 * PA Semi PWRficient PA6T-1682M on-chip UART
 	 */
 	 */
@@ -3734,6 +3378,10 @@ static const struct pci_device_id blacklist[] = {
 	{ PCI_VDEVICE(INTEL, 0x228c), },
 	{ PCI_VDEVICE(INTEL, 0x228c), },
 	{ PCI_VDEVICE(INTEL, 0x9ce3), },
 	{ PCI_VDEVICE(INTEL, 0x9ce3), },
 	{ PCI_VDEVICE(INTEL, 0x9ce4), },
 	{ PCI_VDEVICE(INTEL, 0x9ce4), },
+
+	/* Exar devices */
+	{ PCI_VDEVICE(EXAR, PCI_ANY_ID), },
+	{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), },
 };
 };
 
 
 /*
 /*
@@ -3908,7 +3556,7 @@ err_out:
 }
 }
 EXPORT_SYMBOL_GPL(pciserial_init_ports);
 EXPORT_SYMBOL_GPL(pciserial_init_ports);
 
 
-void pciserial_detach_ports(struct serial_private *priv)
+static void pciserial_detach_ports(struct serial_private *priv)
 {
 {
 	struct pci_serial_quirk *quirk;
 	struct pci_serial_quirk *quirk;
 	int i;
 	int i;
@@ -4159,58 +3807,6 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_VENDOR_ID_AFAVLAB,
 		PCI_VENDOR_ID_AFAVLAB,
 		PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
 		PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
 		pbn_b0_4_1152000 },
 		pbn_b0_4_1152000 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
-		pbn_b0_2_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
-		pbn_b0_4_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
-		pbn_b0_8_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
-		pbn_b0_2_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
-		pbn_b0_4_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
-		pbn_b0_8_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
-		pbn_b0_2_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
-		pbn_b0_4_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
-		pbn_b0_8_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
-		pbn_b0_2_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
-		pbn_b0_4_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-		PCI_SUBVENDOR_ID_CONNECT_TECH,
-		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
-		pbn_b0_8_1843200_200 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-		PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
-		0, 0, pbn_exar_ibm_saturn },
-
 	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
 	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b2_bt_1_115200 },
 		pbn_b2_bt_1_115200 },
@@ -4938,45 +4534,6 @@ static struct pci_device_id serial_pci_tbl[] = {
 	{	PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
 	{	PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b3_8_115200 },
 		pbn_b3_8_115200 },
-
-	/*
-	 * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
-	 */
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17C152 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17C154 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17C158 },
-	/*
-	 * Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs
-	 */
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17V352 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17V354 },
-	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		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_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17V8358 },
 	/*
 	/*
 	 * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
 	 * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
 	 */
 	 */
@@ -5552,43 +5109,15 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_ANY_ID, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
 		0, 0, pbn_wch384_4 },
 		0, 0, pbn_wch384_4 },
 
 
-	/*
-	 * Commtech, Inc. Fastcom adapters
-	 */
-	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCI335,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_b0_2_1152000_200 },
-	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCI335,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_b0_4_1152000_200 },
-	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2324PCI335,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_b0_4_1152000_200 },
-	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2328PCI335,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_b0_8_1152000_200 },
-	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCIE,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17V352 },
-	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCIE,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17V354 },
-	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4228PCIE,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0,
-		0, pbn_exar_XR17V358 },
-
 	/* Fintek PCI serial cards */
 	/* Fintek PCI serial cards */
 	{ PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
 	{ PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
 	{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
 	{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
 	{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
 	{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
 
 
+	/* MKS Tenta SCOM-080x serial cards */
+	{ PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 },
+	{ PCI_DEVICE(0x1601, 0xa801), .driver_data = pbn_b0_4_1250000 },
+
 	/*
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL

+ 28 - 4
drivers/tty/serial/8250/8250_port.c

@@ -44,6 +44,12 @@
 
 
 #include "8250.h"
 #include "8250.h"
 
 
+/*
+ * These are definitions for the Exar XR17V35X and XR17(C|D)15X
+ */
+#define UART_EXAR_SLEEP		0x8b	/* Sleep mode */
+#define UART_EXAR_DVID		0x8d	/* Device identification */
+
 /*
 /*
  * Debugging.
  * Debugging.
  */
  */
@@ -273,6 +279,15 @@ static const struct serial8250_config uart_config[] = {
 		.rxtrig_bytes	= {1, 4, 8, 14},
 		.rxtrig_bytes	= {1, 4, 8, 14},
 		.flags		= UART_CAP_FIFO,
 		.flags		= UART_CAP_FIFO,
 	},
 	},
+	[PORT_DA830] = {
+		.name		= "TI DA8xx/66AK2x",
+		.fifo_size	= 16,
+		.tx_loadsz	= 16,
+		.fcr		= UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
+				  UART_FCR_R_TRIG_10,
+		.rxtrig_bytes	= {1, 4, 8, 14},
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
+	},
 };
 };
 
 
 /* Uart divisor latch read */
 /* Uart divisor latch read */
@@ -1753,8 +1768,6 @@ void serial8250_tx_chars(struct uart_8250_port *up)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(port);
 		uart_write_wakeup(port);
 
 
-	pr_debug("%s: THRE\n", __func__);
-
 	/*
 	/*
 	 * With RPM enabled, we have to wait until the FIFO is empty before the
 	 * With RPM enabled, we have to wait until the FIFO is empty before the
 	 * HW can go idle. So we get here once again with empty FIFO and disable
 	 * HW can go idle. So we get here once again with empty FIFO and disable
@@ -1819,8 +1832,6 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
 
 
 	status = serial_port_in(port, UART_LSR);
 	status = serial_port_in(port, UART_LSR);
 
 
-	pr_debug("%s: status = %x\n", __func__, status);
-
 	if (status & (UART_LSR_DR | UART_LSR_BI)) {
 	if (status & (UART_LSR_DR | UART_LSR_BI)) {
 		if (!up->dma || handle_rx_dma(up, iir))
 		if (!up->dma || handle_rx_dma(up, iir))
 			status = serial8250_rx_chars(up, status);
 			status = serial8250_rx_chars(up, status);
@@ -2118,6 +2129,19 @@ int serial8250_do_startup(struct uart_port *port)
 		serial_port_out(port, UART_LCR, 0);
 		serial_port_out(port, UART_LCR, 0);
 	}
 	}
 
 
+	if (port->type == PORT_DA830) {
+		/* Reset the port */
+		serial_port_out(port, UART_IER, 0);
+		serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
+		mdelay(10);
+
+		/* Enable Tx, Rx and free run mode */
+		serial_port_out(port, UART_DA830_PWREMU_MGMT,
+				UART_DA830_PWREMU_MGMT_UTRST |
+				UART_DA830_PWREMU_MGMT_URRST |
+				UART_DA830_PWREMU_MGMT_FREE);
+	}
+
 #ifdef CONFIG_SERIAL_8250_RSA
 #ifdef CONFIG_SERIAL_8250_RSA
 	/*
 	/*
 	 * If this is an RSA port, see if we can kick it up to the
 	 * If this is an RSA port, see if we can kick it up to the

+ 8 - 3
drivers/tty/serial/8250/Kconfig

@@ -117,7 +117,7 @@ config SERIAL_8250_DMA
 	  compatible UART controllers that support DMA signaling.
 	  compatible UART controllers that support DMA signaling.
 
 
 config SERIAL_8250_PCI
 config SERIAL_8250_PCI
-	tristate "8250/16550 PCI device support" if EXPERT
+	tristate "8250/16550 PCI device support"
 	depends on SERIAL_8250 && PCI
 	depends on SERIAL_8250 && PCI
 	default SERIAL_8250
 	default SERIAL_8250
 	help
 	help
@@ -127,6 +127,11 @@ config SERIAL_8250_PCI
 	  Note that serial ports on NetMos 9835 Multi-I/O cards are handled
 	  Note that serial ports on NetMos 9835 Multi-I/O cards are handled
 	  by the parport_serial driver, enabled with CONFIG_PARPORT_SERIAL.
 	  by the parport_serial driver, enabled with CONFIG_PARPORT_SERIAL.
 
 
+config SERIAL_8250_EXAR
+        tristate "8250/16550 PCI device support"
+        depends on SERIAL_8250_PCI
+	default SERIAL_8250
+
 config SERIAL_8250_HP300
 config SERIAL_8250_HP300
 	tristate
 	tristate
 	depends on SERIAL_8250 && HP300
 	depends on SERIAL_8250 && HP300
@@ -402,7 +407,7 @@ config SERIAL_8250_INGENIC
 	  its UARTs, say Y to this option. If unsure, say N.
 	  its UARTs, say Y to this option. If unsure, say N.
 
 
 config SERIAL_8250_LPSS
 config SERIAL_8250_LPSS
-	tristate "Support for serial ports on Intel LPSS platforms" if EXPERT
+	tristate "Support for serial ports on Intel LPSS platforms"
 	default SERIAL_8250
 	default SERIAL_8250
 	depends on SERIAL_8250 && PCI
 	depends on SERIAL_8250 && PCI
 	depends on X86 || COMPILE_TEST
 	depends on X86 || COMPILE_TEST
@@ -417,7 +422,7 @@ config SERIAL_8250_LPSS
 	    - Intel Quark X1000 SoC
 	    - Intel Quark X1000 SoC
 
 
 config SERIAL_8250_MID
 config SERIAL_8250_MID
-	tristate "Support for serial ports on Intel MID platforms" if EXPERT
+	tristate "Support for serial ports on Intel MID platforms"
 	default SERIAL_8250
 	default SERIAL_8250
 	depends on SERIAL_8250 && PCI
 	depends on SERIAL_8250 && PCI
 	depends on X86 || COMPILE_TEST
 	depends on X86 || COMPILE_TEST

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

@@ -10,6 +10,7 @@ obj-$(CONFIG_SERIAL_8250)		+= 8250.o 8250_base.o
 8250_base-$(CONFIG_SERIAL_8250_FINTEK)	+= 8250_fintek.o
 8250_base-$(CONFIG_SERIAL_8250_FINTEK)	+= 8250_fintek.o
 obj-$(CONFIG_SERIAL_8250_GSC)		+= 8250_gsc.o
 obj-$(CONFIG_SERIAL_8250_GSC)		+= 8250_gsc.o
 obj-$(CONFIG_SERIAL_8250_PCI)		+= 8250_pci.o
 obj-$(CONFIG_SERIAL_8250_PCI)		+= 8250_pci.o
+obj-$(CONFIG_SERIAL_8250_EXAR)		+= 8250_exar.o
 obj-$(CONFIG_SERIAL_8250_HP300)		+= 8250_hp300.o
 obj-$(CONFIG_SERIAL_8250_HP300)		+= 8250_hp300.o
 obj-$(CONFIG_SERIAL_8250_CS)		+= serial_cs.o
 obj-$(CONFIG_SERIAL_8250_CS)		+= serial_cs.o
 obj-$(CONFIG_SERIAL_8250_ACORN)		+= 8250_acorn.o
 obj-$(CONFIG_SERIAL_8250_ACORN)		+= 8250_acorn.o

+ 1 - 0
drivers/tty/serial/Kconfig

@@ -1161,6 +1161,7 @@ config SERIAL_LANTIQ
 	depends on LANTIQ
 	depends on LANTIQ
 	select SERIAL_CORE
 	select SERIAL_CORE
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
 	help
 	help
 	  Support for console and UART on Lantiq SoCs.
 	  Support for console and UART on Lantiq SoCs.
 
 

+ 1 - 1
drivers/tty/serial/amba-pl010.c

@@ -554,7 +554,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
 	return ret;
 	return ret;
 }
 }
 
 
-static struct uart_ops amba_pl010_pops = {
+static const struct uart_ops amba_pl010_pops = {
 	.tx_empty	= pl010_tx_empty,
 	.tx_empty	= pl010_tx_empty,
 	.set_mctrl	= pl010_set_mctrl,
 	.set_mctrl	= pl010_set_mctrl,
 	.get_mctrl	= pl010_get_mctrl,
 	.get_mctrl	= pl010_get_mctrl,

+ 61 - 9
drivers/tty/serial/amba-pl011.c

@@ -97,6 +97,7 @@ struct vendor_data {
 	unsigned int		fr_dsr;
 	unsigned int		fr_dsr;
 	unsigned int		fr_cts;
 	unsigned int		fr_cts;
 	unsigned int		fr_ri;
 	unsigned int		fr_ri;
+	unsigned int		inv_fr;
 	bool			access_32b;
 	bool			access_32b;
 	bool			oversampling;
 	bool			oversampling;
 	bool			dma_threshold;
 	bool			dma_threshold;
@@ -141,6 +142,30 @@ static struct vendor_data vendor_sbsa = {
 	.fixed_options		= true,
 	.fixed_options		= true,
 };
 };
 
 
+/*
+ * Erratum 44 for QDF2432v1 and QDF2400v1 SoCs describes the BUSY bit as
+ * occasionally getting stuck as 1. To avoid the potential for a hang, check
+ * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART
+ * implementations, so only do so if an affected platform is detected in
+ * parse_spcr().
+ */
+static bool qdf2400_e44_present = false;
+
+static struct vendor_data vendor_qdt_qdf2400_e44 = {
+	.reg_offset		= pl011_std_offsets,
+	.fr_busy		= UART011_FR_TXFE,
+	.fr_dsr			= UART01x_FR_DSR,
+	.fr_cts			= UART01x_FR_CTS,
+	.fr_ri			= UART011_FR_RI,
+	.inv_fr			= UART011_FR_TXFE,
+	.access_32b		= true,
+	.oversampling		= false,
+	.dma_threshold		= false,
+	.cts_event_workaround	= false,
+	.always_enabled		= true,
+	.fixed_options		= true,
+};
+
 static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
 static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
 	[REG_DR] = UART01x_DR,
 	[REG_DR] = UART01x_DR,
 	[REG_ST_DMAWM] = ST_UART011_DMAWM,
 	[REG_ST_DMAWM] = ST_UART011_DMAWM,
@@ -1518,7 +1543,10 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
 {
 {
 	struct uart_amba_port *uap =
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 	    container_of(port, struct uart_amba_port, port);
-	unsigned int status = pl011_read(uap, REG_FR);
+
+	/* Allow feature register bits to be inverted to work around errata */
+	unsigned int status = pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr;
+
 	return status & (uap->vendor->fr_busy | UART01x_FR_TXFF) ?
 	return status & (uap->vendor->fr_busy | UART01x_FR_TXFF) ?
 							0 : TIOCSER_TEMT;
 							0 : TIOCSER_TEMT;
 }
 }
@@ -2114,7 +2142,7 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
 	return ret;
 	return ret;
 }
 }
 
 
-static struct uart_ops amba_pl011_pops = {
+static const struct uart_ops amba_pl011_pops = {
 	.tx_empty	= pl011_tx_empty,
 	.tx_empty	= pl011_tx_empty,
 	.set_mctrl	= pl011_set_mctrl,
 	.set_mctrl	= pl011_set_mctrl,
 	.get_mctrl	= pl011_get_mctrl,
 	.get_mctrl	= pl011_get_mctrl,
@@ -2215,10 +2243,12 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
 
 
 	/*
 	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the TCR
+	 *	Finally, wait for transmitter to become empty and restore the
+	 *	TCR. Allow feature register bits to be inverted to work around
+	 *	errata.
 	 */
 	 */
-	while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy)
+	while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr)
+						& uap->vendor->fr_busy)
 		cpu_relax();
 		cpu_relax();
 	if (!uap->vendor->always_enabled)
 	if (!uap->vendor->always_enabled)
 		pl011_write(old_cr, uap, REG_CR);
 		pl011_write(old_cr, uap, REG_CR);
@@ -2340,8 +2370,12 @@ static int __init pl011_console_match(struct console *co, char *name, int idx,
 	resource_size_t addr;
 	resource_size_t addr;
 	int i;
 	int i;
 
 
-	if (strcmp(name, "pl011") != 0)
+	if (strcmp(name, "qdf2400_e44") == 0) {
+		pr_info_once("UART: Working around QDF2400 SoC erratum 44");
+		qdf2400_e44_present = true;
+	} else if (strcmp(name, "pl011") != 0 || strcmp(name, "ttyAMA") != 0) {
 		return -ENODEV;
 		return -ENODEV;
+	}
 
 
 	if (uart_parse_earlycon(options, &iotype, &addr, &options))
 	if (uart_parse_earlycon(options, &iotype, &addr, &options))
 		return -ENODEV;
 		return -ENODEV;
@@ -2376,13 +2410,29 @@ static struct console amba_console = {
 	.device		= uart_console_device,
 	.device		= uart_console_device,
 	.setup		= pl011_console_setup,
 	.setup		= pl011_console_setup,
 	.match		= pl011_console_match,
 	.match		= pl011_console_match,
-	.flags		= CON_PRINTBUFFER,
+	.flags		= CON_PRINTBUFFER | CON_ANYTIME,
 	.index		= -1,
 	.index		= -1,
 	.data		= &amba_reg,
 	.data		= &amba_reg,
 };
 };
 
 
 #define AMBA_CONSOLE	(&amba_console)
 #define AMBA_CONSOLE	(&amba_console)
 
 
+static void qdf2400_e44_putc(struct uart_port *port, int c)
+{
+	while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
+		cpu_relax();
+	writel(c, port->membase + UART01x_DR);
+	while (!(readl(port->membase + UART01x_FR) & UART011_FR_TXFE))
+		cpu_relax();
+}
+
+static void qdf2400_e44_early_write(struct console *con, const char *s, unsigned n)
+{
+	struct earlycon_device *dev = con->data;
+
+	uart_console_write(&dev->port, s, n, qdf2400_e44_putc);
+}
+
 static void pl011_putc(struct uart_port *port, int c)
 static void pl011_putc(struct uart_port *port, int c)
 {
 {
 	while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
 	while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
@@ -2408,7 +2458,8 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
 	if (!device->port.membase)
 	if (!device->port.membase)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	device->con->write = pl011_early_write;
+	device->con->write = qdf2400_e44_present ?
+				qdf2400_e44_early_write : pl011_early_write;
 	return 0;
 	return 0;
 }
 }
 OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
 OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
@@ -2645,7 +2696,8 @@ static int sbsa_uart_probe(struct platform_device *pdev)
 	uap->port.irq	= ret;
 	uap->port.irq	= ret;
 
 
 	uap->reg_offset	= vendor_sbsa.reg_offset;
 	uap->reg_offset	= vendor_sbsa.reg_offset;
-	uap->vendor	= &vendor_sbsa;
+	uap->vendor	= qdf2400_e44_present ?
+					&vendor_qdt_qdf2400_e44 : &vendor_sbsa;
 	uap->fifosize	= 32;
 	uap->fifosize	= 32;
 	uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM;
 	uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM;
 	uap->port.ops	= &sbsa_uart_pops;
 	uap->port.ops	= &sbsa_uart_pops;

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

@@ -493,7 +493,7 @@ static int ar933x_uart_verify_port(struct uart_port *port,
 	return 0;
 	return 0;
 }
 }
 
 
-static struct uart_ops ar933x_uart_ops = {
+static const struct uart_ops ar933x_uart_ops = {
 	.tx_empty	= ar933x_uart_tx_empty,
 	.tx_empty	= ar933x_uart_tx_empty,
 	.set_mctrl	= ar933x_uart_set_mctrl,
 	.set_mctrl	= ar933x_uart_set_mctrl,
 	.get_mctrl	= ar933x_uart_get_mctrl,
 	.get_mctrl	= ar933x_uart_get_mctrl,

+ 48 - 3
drivers/tty/serial/atmel_serial.c

@@ -175,6 +175,17 @@ struct atmel_uart_port {
 	unsigned int		pending_status;
 	unsigned int		pending_status;
 	spinlock_t		lock_suspended;
 	spinlock_t		lock_suspended;
 
 
+	struct {
+		u32		cr;
+		u32		mr;
+		u32		imr;
+		u32		brgr;
+		u32		rtor;
+		u32		ttgr;
+		u32		fmr;
+		u32		fimr;
+	} cache;
+
 	int (*prepare_rx)(struct uart_port *port);
 	int (*prepare_rx)(struct uart_port *port);
 	int (*prepare_tx)(struct uart_port *port);
 	int (*prepare_tx)(struct uart_port *port);
 	void (*schedule_rx)(struct uart_port *port);
 	void (*schedule_rx)(struct uart_port *port);
@@ -1758,7 +1769,9 @@ static void atmel_get_ip_name(struct uart_port *port)
 
 
 	/*
 	/*
 	 * Only USART devices from at91sam9260 SOC implement fractional
 	 * Only USART devices from at91sam9260 SOC implement fractional
-	 * baudrate.
+	 * baudrate. It is available for all asynchronous modes, with the
+	 * following restriction: the sampling clock's duty cycle is not
+	 * constant.
 	 */
 	 */
 	atmel_port->has_frac_baudrate = false;
 	atmel_port->has_frac_baudrate = false;
 	atmel_port->has_hw_timer = false;
 	atmel_port->has_hw_timer = false;
@@ -2202,8 +2215,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * then
 	 * then
 	 * 8 CD + FP = selected clock / (2 * baudrate)
 	 * 8 CD + FP = selected clock / (2 * baudrate)
 	 */
 	 */
-	if (atmel_port->has_frac_baudrate &&
-	    (mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_NORMAL) {
+	if (atmel_port->has_frac_baudrate) {
 		div = DIV_ROUND_CLOSEST(port->uartclk, baud * 2);
 		div = DIV_ROUND_CLOSEST(port->uartclk, baud * 2);
 		cd = div >> 3;
 		cd = div >> 3;
 		fp = div & ATMEL_US_FP_MASK;
 		fp = div & ATMEL_US_FP_MASK;
@@ -2659,6 +2671,20 @@ static int atmel_serial_suspend(struct platform_device *pdev,
 			cpu_relax();
 			cpu_relax();
 	}
 	}
 
 
+	if (atmel_is_console_port(port) && !console_suspend_enabled) {
+		/* Cache register values as we won't get a full shutdown/startup
+		 * cycle
+		 */
+		atmel_port->cache.mr = atmel_uart_readl(port, ATMEL_US_MR);
+		atmel_port->cache.imr = atmel_uart_readl(port, ATMEL_US_IMR);
+		atmel_port->cache.brgr = atmel_uart_readl(port, ATMEL_US_BRGR);
+		atmel_port->cache.rtor = atmel_uart_readl(port,
+							  atmel_port->rtor);
+		atmel_port->cache.ttgr = atmel_uart_readl(port, ATMEL_US_TTGR);
+		atmel_port->cache.fmr = atmel_uart_readl(port, ATMEL_US_FMR);
+		atmel_port->cache.fimr = atmel_uart_readl(port, ATMEL_US_FIMR);
+	}
+
 	/* we can not wake up if we're running on slow clock */
 	/* we can not wake up if we're running on slow clock */
 	atmel_port->may_wakeup = device_may_wakeup(&pdev->dev);
 	atmel_port->may_wakeup = device_may_wakeup(&pdev->dev);
 	if (atmel_serial_clk_will_stop()) {
 	if (atmel_serial_clk_will_stop()) {
@@ -2681,6 +2707,25 @@ static int atmel_serial_resume(struct platform_device *pdev)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned long flags;
 	unsigned long flags;
 
 
+	if (atmel_is_console_port(port) && !console_suspend_enabled) {
+		atmel_uart_writel(port, ATMEL_US_MR, atmel_port->cache.mr);
+		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->cache.imr);
+		atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->cache.brgr);
+		atmel_uart_writel(port, atmel_port->rtor,
+				  atmel_port->cache.rtor);
+		atmel_uart_writel(port, ATMEL_US_TTGR, atmel_port->cache.ttgr);
+
+		if (atmel_port->fifo_size) {
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_FIFOEN |
+					  ATMEL_US_RXFCLR | ATMEL_US_TXFLCLR);
+			atmel_uart_writel(port, ATMEL_US_FMR,
+					  atmel_port->cache.fmr);
+			atmel_uart_writel(port, ATMEL_US_FIER,
+					  atmel_port->cache.fimr);
+		}
+		atmel_start_rx(port);
+	}
+
 	spin_lock_irqsave(&atmel_port->lock_suspended, flags);
 	spin_lock_irqsave(&atmel_port->lock_suspended, flags);
 	if (atmel_port->pending) {
 	if (atmel_port->pending) {
 		atmel_handle_receive(port, atmel_port->pending);
 		atmel_handle_receive(port, atmel_port->pending);

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

@@ -740,7 +740,7 @@ static int sport_uart_resume(struct device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
+static const struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
 	.suspend	= sport_uart_suspend,
 	.suspend	= sport_uart_suspend,
 	.resume		= sport_uart_resume,
 	.resume		= sport_uart_resume,
 };
 };

+ 10 - 8
drivers/tty/serial/cpm_uart/cpm_uart_core.c

@@ -1302,7 +1302,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
 	struct uart_cpm_port *pinfo;
 	struct uart_cpm_port *pinfo;
 	struct uart_port *port;
 	struct uart_port *port;
 
 
-	struct device_node *np = NULL;
+	struct device_node *np;
 	int i = 0;
 	int i = 0;
 
 
 	if (co->index >= UART_NR) {
 	if (co->index >= UART_NR) {
@@ -1311,17 +1311,19 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	do {
-		np = of_find_node_by_type(np, "serial");
-		if (!np)
-			return -ENODEV;
-
+	for_each_node_by_type(np, "serial") {
 		if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") &&
 		if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") &&
 		    !of_device_is_compatible(np, "fsl,cpm1-scc-uart") &&
 		    !of_device_is_compatible(np, "fsl,cpm1-scc-uart") &&
 		    !of_device_is_compatible(np, "fsl,cpm2-smc-uart") &&
 		    !of_device_is_compatible(np, "fsl,cpm2-smc-uart") &&
 		    !of_device_is_compatible(np, "fsl,cpm2-scc-uart"))
 		    !of_device_is_compatible(np, "fsl,cpm2-scc-uart"))
-			i--;
-	} while (i++ != co->index);
+			continue;
+
+		if (i++ == co->index)
+			break;
+	}
+
+	if (!np)
+		return -ENODEV;
 
 
 	pinfo = &cpm_uart_ports[co->index];
 	pinfo = &cpm_uart_ports[co->index];
 
 

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

@@ -739,7 +739,7 @@ static int dz_verify_port(struct uart_port *uport, struct serial_struct *ser)
 	return ret;
 	return ret;
 }
 }
 
 
-static struct uart_ops dz_ops = {
+static const struct uart_ops dz_ops = {
 	.tx_empty	= dz_tx_empty,
 	.tx_empty	= dz_tx_empty,
 	.get_mctrl	= dz_get_mctrl,
 	.get_mctrl	= dz_get_mctrl,
 	.set_mctrl	= dz_set_mctrl,
 	.set_mctrl	= dz_set_mctrl,

+ 1 - 1
drivers/tty/serial/efm32-uart.c

@@ -487,7 +487,7 @@ static int efm32_uart_verify_port(struct uart_port *port,
 	return ret;
 	return ret;
 }
 }
 
 
-static struct uart_ops efm32_uart_pops = {
+static const struct uart_ops efm32_uart_pops = {
 	.tx_empty = efm32_uart_tx_empty,
 	.tx_empty = efm32_uart_tx_empty,
 	.set_mctrl = efm32_uart_set_mctrl,
 	.set_mctrl = efm32_uart_set_mctrl,
 	.get_mctrl = efm32_uart_get_mctrl,
 	.get_mctrl = efm32_uart_get_mctrl,

+ 17 - 18
drivers/tty/serial/fsl_lpuart.c

@@ -1407,6 +1407,18 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	/* ask the core to calculate the divisor */
 	/* ask the core to calculate the divisor */
 	baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
 	baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
 
 
+	/*
+	 * Need to update the Ring buffer length according to the selected
+	 * baud rate and restart Rx DMA path.
+	 *
+	 * Since timer function acqures sport->port.lock, need to stop before
+	 * acquring same lock because otherwise del_timer_sync() can deadlock.
+	 */
+	if (old && sport->lpuart_dma_rx_use) {
+		del_timer_sync(&sport->lpuart_timer);
+		lpuart_dma_rx_free(&sport->port);
+	}
+
 	spin_lock_irqsave(&sport->port.lock, flags);
 	spin_lock_irqsave(&sport->port.lock, flags);
 
 
 	sport->port.read_status_mask = 0;
 	sport->port.read_status_mask = 0;
@@ -1456,22 +1468,11 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	/* restore control register */
 	/* restore control register */
 	writeb(old_cr2, sport->port.membase + UARTCR2);
 	writeb(old_cr2, sport->port.membase + UARTCR2);
 
 
-	/*
-	 * If new baud rate is set, we will also need to update the Ring buffer
-	 * length according to the selected baud rate and restart Rx DMA path.
-	 */
-	if (old) {
-		if (sport->lpuart_dma_rx_use) {
-			del_timer_sync(&sport->lpuart_timer);
-			lpuart_dma_rx_free(&sport->port);
-		}
-
-		if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
-			sport->lpuart_dma_rx_use = true;
+	if (old && sport->lpuart_dma_rx_use) {
+		if (!lpuart_start_rx_dma(sport))
 			rx_dma_timer_init(sport);
 			rx_dma_timer_init(sport);
-		} else {
+		else
 			sport->lpuart_dma_rx_use = false;
 			sport->lpuart_dma_rx_use = false;
-		}
 	}
 	}
 
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -2131,12 +2132,10 @@ static int lpuart_resume(struct device *dev)
 
 
 	if (sport->lpuart_dma_rx_use) {
 	if (sport->lpuart_dma_rx_use) {
 		if (sport->port.irq_wake) {
 		if (sport->port.irq_wake) {
-			if (!lpuart_start_rx_dma(sport)) {
-				sport->lpuart_dma_rx_use = true;
+			if (!lpuart_start_rx_dma(sport))
 				rx_dma_timer_init(sport);
 				rx_dma_timer_init(sport);
-			} else {
+			else
 				sport->lpuart_dma_rx_use = false;
 				sport->lpuart_dma_rx_use = false;
-			}
 		}
 		}
 	}
 	}
 
 

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

@@ -1286,7 +1286,7 @@ static void icom_config_port(struct uart_port *port, int flags)
 	port->type = PORT_ICOM;
 	port->type = PORT_ICOM;
 }
 }
 
 
-static struct uart_ops icom_ops = {
+static const struct uart_ops icom_ops = {
 	.tx_empty = icom_tx_empty,
 	.tx_empty = icom_tx_empty,
 	.set_mctrl = icom_set_mctrl,
 	.set_mctrl = icom_set_mctrl,
 	.get_mctrl = icom_get_mctrl,
 	.get_mctrl = icom_get_mctrl,

+ 18 - 14
drivers/tty/serial/imx.c

@@ -205,6 +205,7 @@ struct imx_port {
 	struct timer_list	timer;
 	struct timer_list	timer;
 	unsigned int		old_status;
 	unsigned int		old_status;
 	unsigned int		have_rtscts:1;
 	unsigned int		have_rtscts:1;
+	unsigned int		have_rtsgpio:1;
 	unsigned int		dte_mode:1;
 	unsigned int		dte_mode:1;
 	unsigned int		irda_inv_rx:1;
 	unsigned int		irda_inv_rx:1;
 	unsigned int		irda_inv_tx:1;
 	unsigned int		irda_inv_tx:1;
@@ -335,15 +336,15 @@ static void imx_port_ucrs_restore(struct uart_port *port,
 
 
 static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
 static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
 {
 {
-	*ucr2 &= ~UCR2_CTSC;
-	*ucr2 |= UCR2_CTS;
+	*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
 
 
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS);
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS);
 }
 }
 
 
 static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
 static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
 {
 {
-	*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
+	*ucr2 &= ~UCR2_CTSC;
+	*ucr2 |= UCR2_CTS;
 
 
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS);
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS);
 }
 }
@@ -376,9 +377,9 @@ static void imx_stop_tx(struct uart_port *port)
 	    readl(port->membase + USR2) & USR2_TXDC) {
 	    readl(port->membase + USR2) & USR2_TXDC) {
 		temp = readl(port->membase + UCR2);
 		temp = readl(port->membase + UCR2);
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-			imx_port_rts_inactive(sport, &temp);
-		else
 			imx_port_rts_active(sport, &temp);
 			imx_port_rts_active(sport, &temp);
+		else
+			imx_port_rts_inactive(sport, &temp);
 		temp |= UCR2_RXEN;
 		temp |= UCR2_RXEN;
 		writel(temp, port->membase + UCR2);
 		writel(temp, port->membase + UCR2);
 
 
@@ -584,9 +585,9 @@ static void imx_start_tx(struct uart_port *port)
 	if (port->rs485.flags & SER_RS485_ENABLED) {
 	if (port->rs485.flags & SER_RS485_ENABLED) {
 		temp = readl(port->membase + UCR2);
 		temp = readl(port->membase + UCR2);
 		if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
 		if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
-			imx_port_rts_inactive(sport, &temp);
-		else
 			imx_port_rts_active(sport, &temp);
 			imx_port_rts_active(sport, &temp);
+		else
+			imx_port_rts_inactive(sport, &temp);
 		if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
 		if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
 			temp &= ~UCR2_RXEN;
 			temp &= ~UCR2_RXEN;
 		writel(temp, port->membase + UCR2);
 		writel(temp, port->membase + UCR2);
@@ -1476,9 +1477,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 				 */
 				 */
 				if (port->rs485.flags &
 				if (port->rs485.flags &
 				    SER_RS485_RTS_AFTER_SEND)
 				    SER_RS485_RTS_AFTER_SEND)
-					imx_port_rts_inactive(sport, &ucr2);
-				else
 					imx_port_rts_active(sport, &ucr2);
 					imx_port_rts_active(sport, &ucr2);
+				else
+					imx_port_rts_inactive(sport, &ucr2);
 			} else {
 			} else {
 				imx_port_rts_auto(sport, &ucr2);
 				imx_port_rts_auto(sport, &ucr2);
 			}
 			}
@@ -1488,9 +1489,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	} else if (port->rs485.flags & SER_RS485_ENABLED) {
 	} else if (port->rs485.flags & SER_RS485_ENABLED) {
 		/* disable transmitter */
 		/* disable transmitter */
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-			imx_port_rts_inactive(sport, &ucr2);
-		else
 			imx_port_rts_active(sport, &ucr2);
 			imx_port_rts_active(sport, &ucr2);
+		else
+			imx_port_rts_inactive(sport, &ucr2);
 	}
 	}
 
 
 
 
@@ -1725,16 +1726,16 @@ static int imx_rs485_config(struct uart_port *port,
 	rs485conf->delay_rts_after_send = 0;
 	rs485conf->delay_rts_after_send = 0;
 
 
 	/* RTS is required to control the transmitter */
 	/* RTS is required to control the transmitter */
-	if (!sport->have_rtscts)
+	if (!sport->have_rtscts && !sport->have_rtsgpio)
 		rs485conf->flags &= ~SER_RS485_ENABLED;
 		rs485conf->flags &= ~SER_RS485_ENABLED;
 
 
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 		/* disable transmitter */
 		/* disable transmitter */
 		temp = readl(sport->port.membase + UCR2);
 		temp = readl(sport->port.membase + UCR2);
 		if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
 		if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
-			imx_port_rts_inactive(sport, &temp);
-		else
 			imx_port_rts_active(sport, &temp);
 			imx_port_rts_active(sport, &temp);
+		else
+			imx_port_rts_inactive(sport, &temp);
 		writel(temp, sport->port.membase + UCR2);
 		writel(temp, sport->port.membase + UCR2);
 	}
 	}
 
 
@@ -2048,6 +2049,9 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 	if (of_get_property(np, "fsl,dte-mode", NULL))
 	if (of_get_property(np, "fsl,dte-mode", NULL))
 		sport->dte_mode = 1;
 		sport->dte_mode = 1;
 
 
+	if (of_get_property(np, "rts-gpios", NULL))
+		sport->have_rtsgpio = 1;
+
 	return 0;
 	return 0;
 }
 }
 #else
 #else

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

@@ -1873,7 +1873,7 @@ static int ic3_request_port(struct uart_port *port)
 }
 }
 
 
 /* Associate the uart functions above - given to serial core */
 /* Associate the uart functions above - given to serial core */
-static struct uart_ops ioc3_ops = {
+static const struct uart_ops ioc3_ops = {
 	.tx_empty = ic3_tx_empty,
 	.tx_empty = ic3_tx_empty,
 	.set_mctrl = ic3_set_mctrl,
 	.set_mctrl = ic3_set_mctrl,
 	.get_mctrl = ic3_get_mctrl,
 	.get_mctrl = ic3_get_mctrl,

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

@@ -2596,7 +2596,7 @@ static int ic4_request_port(struct uart_port *port)
 
 
 /* Associate the uart functions above - given to serial core */
 /* Associate the uart functions above - given to serial core */
 
 
-static struct uart_ops ioc4_ops = {
+static const struct uart_ops ioc4_ops = {
 	.tx_empty	= ic4_tx_empty,
 	.tx_empty	= ic4_tx_empty,
 	.set_mctrl	= ic4_set_mctrl,
 	.set_mctrl	= ic4_set_mctrl,
 	.get_mctrl	= ic4_get_mctrl,
 	.get_mctrl	= ic4_get_mctrl,

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

@@ -930,7 +930,7 @@ static int ip22zilog_verify_port(struct uart_port *port, struct serial_struct *s
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
-static struct uart_ops ip22zilog_pops = {
+static const struct uart_ops ip22zilog_pops = {
 	.tx_empty	=	ip22zilog_tx_empty,
 	.tx_empty	=	ip22zilog_tx_empty,
 	.set_mctrl	=	ip22zilog_set_mctrl,
 	.set_mctrl	=	ip22zilog_set_mctrl,
 	.get_mctrl	=	ip22zilog_get_mctrl,
 	.get_mctrl	=	ip22zilog_get_mctrl,

+ 33 - 9
drivers/tty/serial/lantiq.c

@@ -16,7 +16,7 @@
  *
  *
  * Copyright (C) 2004 Infineon IFAP DC COM CPE
  * Copyright (C) 2004 Infineon IFAP DC COM CPE
  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2007 John Crispin <john@phrozen.org>
  * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
  * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
  */
  */
 
 
@@ -557,7 +557,7 @@ lqasc_verify_port(struct uart_port *port,
 	return ret;
 	return ret;
 }
 }
 
 
-static struct uart_ops lqasc_pops = {
+static const struct uart_ops lqasc_pops = {
 	.tx_empty =	lqasc_tx_empty,
 	.tx_empty =	lqasc_tx_empty,
 	.set_mctrl =	lqasc_set_mctrl,
 	.set_mctrl =	lqasc_set_mctrl,
 	.get_mctrl =	lqasc_get_mctrl,
 	.get_mctrl =	lqasc_get_mctrl,
@@ -590,13 +590,20 @@ lqasc_console_putchar(struct uart_port *port, int ch)
 	ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
 	ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
 }
 }
 
 
+static void lqasc_serial_port_write(struct uart_port *port, const char *s,
+				    u_int count)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ltq_asc_lock, flags);
+	uart_console_write(port, s, count, lqasc_console_putchar);
+	spin_unlock_irqrestore(&ltq_asc_lock, flags);
+}
 
 
 static void
 static void
 lqasc_console_write(struct console *co, const char *s, u_int count)
 lqasc_console_write(struct console *co, const char *s, u_int count)
 {
 {
 	struct ltq_uart_port *ltq_port;
 	struct ltq_uart_port *ltq_port;
-	struct uart_port *port;
-	unsigned long flags;
 
 
 	if (co->index >= MAXPORTS)
 	if (co->index >= MAXPORTS)
 		return;
 		return;
@@ -605,11 +612,7 @@ lqasc_console_write(struct console *co, const char *s, u_int count)
 	if (!ltq_port)
 	if (!ltq_port)
 		return;
 		return;
 
 
-	port = &ltq_port->port;
-
-	spin_lock_irqsave(&ltq_asc_lock, flags);
-	uart_console_write(port, s, count, lqasc_console_putchar);
-	spin_unlock_irqrestore(&ltq_asc_lock, flags);
+	lqasc_serial_port_write(&ltq_port->port, s, count);
 }
 }
 
 
 static int __init
 static int __init
@@ -659,6 +662,27 @@ lqasc_console_init(void)
 }
 }
 console_initcall(lqasc_console_init);
 console_initcall(lqasc_console_init);
 
 
+static void lqasc_serial_early_console_write(struct console *co,
+					     const char *s,
+					     u_int count)
+{
+	struct earlycon_device *dev = co->data;
+
+	lqasc_serial_port_write(&dev->port, s, count);
+}
+
+static int __init
+lqasc_serial_early_console_setup(struct earlycon_device *device,
+				 const char *opt)
+{
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->con->write = lqasc_serial_early_console_write;
+	return 0;
+}
+OF_EARLYCON_DECLARE(lantiq, DRVNAME, lqasc_serial_early_console_setup);
+
 static struct uart_driver lqasc_reg = {
 static struct uart_driver lqasc_reg = {
 	.owner =	THIS_MODULE,
 	.owner =	THIS_MODULE,
 	.driver_name =	DRVNAME,
 	.driver_name =	DRVNAME,

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

@@ -645,7 +645,7 @@ static int serial_lpc32xx_verify_port(struct uart_port *port,
 	return ret;
 	return ret;
 }
 }
 
 
-static struct uart_ops serial_lpc32xx_pops = {
+static const struct uart_ops serial_lpc32xx_pops = {
 	.tx_empty	= serial_lpc32xx_tx_empty,
 	.tx_empty	= serial_lpc32xx_tx_empty,
 	.set_mctrl	= serial_lpc32xx_set_mctrl,
 	.set_mctrl	= serial_lpc32xx_set_mctrl,
 	.get_mctrl	= serial_lpc32xx_get_mctrl,
 	.get_mctrl	= serial_lpc32xx_get_mctrl,

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

@@ -236,7 +236,7 @@
 
 
 /* Misc definitions */
 /* Misc definitions */
 #define MAX310X_FIFO_SIZE		(128)
 #define MAX310X_FIFO_SIZE		(128)
-#define MAX310x_REV_MASK		(0xfc)
+#define MAX310x_REV_MASK		(0xf8)
 
 
 /* MAX3107 specific */
 /* MAX3107 specific */
 #define MAX3107_REV_ID			(0xa0)
 #define MAX3107_REV_ID			(0xa0)

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

@@ -364,7 +364,7 @@ static void meson_uart_set_termios(struct uart_port *port,
 
 
 	writel(val, port->membase + AML_UART_CONTROL);
 	writel(val, port->membase + AML_UART_CONTROL);
 
 
-	baud = uart_get_baud_rate(port, termios, old, 9600, 115200);
+	baud = uart_get_baud_rate(port, termios, old, 9600, 4000000);
 	meson_uart_change_speed(port, baud);
 	meson_uart_change_speed(port, baud);
 
 
 	port->read_status_mask = AML_UART_TX_FIFO_WERR;
 	port->read_status_mask = AML_UART_TX_FIFO_WERR;

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

@@ -1670,7 +1670,7 @@ static void mpsc_put_poll_char(struct uart_port *port,
 }
 }
 #endif
 #endif
 
 
-static struct uart_ops mpsc_pops = {
+static const struct uart_ops mpsc_pops = {
 	.tx_empty	= mpsc_tx_empty,
 	.tx_empty	= mpsc_tx_empty,
 	.set_mctrl	= mpsc_set_mctrl,
 	.set_mctrl	= mpsc_set_mctrl,
 	.get_mctrl	= mpsc_get_mctrl,
 	.get_mctrl	= mpsc_get_mctrl,

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

@@ -1809,6 +1809,7 @@ static const struct of_device_id msm_match_table[] = {
 	{ .compatible = "qcom,msm-uartdm" },
 	{ .compatible = "qcom,msm-uartdm" },
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(of, msm_match_table);
 
 
 static struct platform_driver msm_platform_driver = {
 static struct platform_driver msm_platform_driver = {
 	.remove = msm_serial_remove,
 	.remove = msm_serial_remove,

+ 3 - 0
drivers/tty/serial/mxs-auart.c

@@ -95,6 +95,7 @@
 #define AUART_LINECTRL_BAUD_DIVFRAC_SHIFT	8
 #define AUART_LINECTRL_BAUD_DIVFRAC_SHIFT	8
 #define AUART_LINECTRL_BAUD_DIVFRAC_MASK	0x00003f00
 #define AUART_LINECTRL_BAUD_DIVFRAC_MASK	0x00003f00
 #define AUART_LINECTRL_BAUD_DIVFRAC(v)		(((v) & 0x3f) << 8)
 #define AUART_LINECTRL_BAUD_DIVFRAC(v)		(((v) & 0x3f) << 8)
+#define AUART_LINECTRL_SPS			(1 << 7)
 #define AUART_LINECTRL_WLEN_MASK		0x00000060
 #define AUART_LINECTRL_WLEN_MASK		0x00000060
 #define AUART_LINECTRL_WLEN(v)			(((v) & 0x3) << 5)
 #define AUART_LINECTRL_WLEN(v)			(((v) & 0x3) << 5)
 #define AUART_LINECTRL_FEN			(1 << 4)
 #define AUART_LINECTRL_FEN			(1 << 4)
@@ -1014,6 +1015,8 @@ static void mxs_auart_settermios(struct uart_port *u,
 		ctrl |= AUART_LINECTRL_PEN;
 		ctrl |= AUART_LINECTRL_PEN;
 		if ((cflag & PARODD) == 0)
 		if ((cflag & PARODD) == 0)
 			ctrl |= AUART_LINECTRL_EPS;
 			ctrl |= AUART_LINECTRL_EPS;
+		if (cflag & CMSPAR)
+			ctrl |= AUART_LINECTRL_SPS;
 	}
 	}
 
 
 	u->read_status_mask = AUART_STAT_OERR;
 	u->read_status_mask = AUART_STAT_OERR;

+ 56 - 1
drivers/tty/serial/omap-serial.c

@@ -1234,6 +1234,61 @@ out:
 
 
 #ifdef CONFIG_SERIAL_OMAP_CONSOLE
 #ifdef CONFIG_SERIAL_OMAP_CONSOLE
 
 
+#ifdef CONFIG_SERIAL_EARLYCON
+static unsigned int __init omap_serial_early_in(struct uart_port *port,
+						int offset)
+{
+	offset <<= port->regshift;
+	return readw(port->membase + offset);
+}
+
+static void __init omap_serial_early_out(struct uart_port *port, int offset,
+					 int value)
+{
+	offset <<= port->regshift;
+	writew(value, port->membase + offset);
+}
+
+static void __init omap_serial_early_putc(struct uart_port *port, int c)
+{
+	unsigned int status;
+
+	for (;;) {
+		status = omap_serial_early_in(port, UART_LSR);
+		if ((status & BOTH_EMPTY) == BOTH_EMPTY)
+			break;
+		cpu_relax();
+	}
+	omap_serial_early_out(port, UART_TX, c);
+}
+
+static void __init early_omap_serial_write(struct console *console,
+					   const char *s, unsigned int count)
+{
+	struct earlycon_device *device = console->data;
+	struct uart_port *port = &device->port;
+
+	uart_console_write(port, s, count, omap_serial_early_putc);
+}
+
+static int __init early_omap_serial_setup(struct earlycon_device *device,
+					  const char *options)
+{
+	struct uart_port *port = &device->port;
+
+	if (!(device->port.membase || device->port.iobase))
+		return -ENODEV;
+
+	port->regshift = 2;
+	device->con->write = early_omap_serial_write;
+	return 0;
+}
+
+OF_EARLYCON_DECLARE(omapserial, "ti,omap2-uart", early_omap_serial_setup);
+OF_EARLYCON_DECLARE(omapserial, "ti,omap3-uart", early_omap_serial_setup);
+OF_EARLYCON_DECLARE(omapserial, "ti,omap4-uart", early_omap_serial_setup);
+#endif /* CONFIG_SERIAL_EARLYCON */
+
 static struct uart_omap_port *serial_omap_console_ports[OMAP_MAX_HSUART_PORTS];
 static struct uart_omap_port *serial_omap_console_ports[OMAP_MAX_HSUART_PORTS];
 
 
 static struct uart_driver serial_omap_reg;
 static struct uart_driver serial_omap_reg;
@@ -1395,7 +1450,7 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct uart_ops serial_omap_pops = {
+static const struct uart_ops serial_omap_pops = {
 	.tx_empty	= serial_omap_tx_empty,
 	.tx_empty	= serial_omap_tx_empty,
 	.set_mctrl	= serial_omap_set_mctrl,
 	.set_mctrl	= serial_omap_set_mctrl,
 	.get_mctrl	= serial_omap_get_mctrl,
 	.get_mctrl	= serial_omap_get_mctrl,

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

@@ -495,13 +495,13 @@ static int pic32_uart_startup(struct uart_port *port)
 
 
 out_t:
 out_t:
 	kfree(sport->irq_tx_name);
 	kfree(sport->irq_tx_name);
-	free_irq(sport->irq_tx, sport);
+	free_irq(sport->irq_tx, port);
 out_r:
 out_r:
 	kfree(sport->irq_rx_name);
 	kfree(sport->irq_rx_name);
-	free_irq(sport->irq_rx, sport);
+	free_irq(sport->irq_rx, port);
 out_f:
 out_f:
 	kfree(sport->irq_fault_name);
 	kfree(sport->irq_fault_name);
-	free_irq(sport->irq_fault, sport);
+	free_irq(sport->irq_fault, port);
 out_done:
 out_done:
 	return ret;
 	return ret;
 }
 }

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

@@ -1379,7 +1379,7 @@ static void pmz_poll_put_char(struct uart_port *port, unsigned char c)
 
 
 #endif /* CONFIG_CONSOLE_POLL */
 #endif /* CONFIG_CONSOLE_POLL */
 
 
-static struct uart_ops pmz_pops = {
+static const struct uart_ops pmz_pops = {
 	.tx_empty	=	pmz_tx_empty,
 	.tx_empty	=	pmz_tx_empty,
 	.set_mctrl	=	pmz_set_mctrl,
 	.set_mctrl	=	pmz_set_mctrl,
 	.get_mctrl	=	pmz_get_mctrl,
 	.get_mctrl	=	pmz_get_mctrl,

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

@@ -631,7 +631,7 @@ pnx8xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
 	return ret;
 	return ret;
 }
 }
 
 
-static struct uart_ops pnx8xxx_pops = {
+static const struct uart_ops pnx8xxx_pops = {
 	.tx_empty	= pnx8xxx_tx_empty,
 	.tx_empty	= pnx8xxx_tx_empty,
 	.set_mctrl	= pnx8xxx_set_mctrl,
 	.set_mctrl	= pnx8xxx_set_mctrl,
 	.get_mctrl	= pnx8xxx_get_mctrl,
 	.get_mctrl	= pnx8xxx_get_mctrl,

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

@@ -762,7 +762,7 @@ static struct console serial_pxa_console = {
 #define PXA_CONSOLE	NULL
 #define PXA_CONSOLE	NULL
 #endif
 #endif
 
 
-static struct uart_ops serial_pxa_pops = {
+static const struct uart_ops serial_pxa_pops = {
 	.tx_empty	= serial_pxa_tx_empty,
 	.tx_empty	= serial_pxa_tx_empty,
 	.set_mctrl	= serial_pxa_set_mctrl,
 	.set_mctrl	= serial_pxa_set_mctrl,
 	.get_mctrl	= serial_pxa_get_mctrl,
 	.get_mctrl	= serial_pxa_get_mctrl,

+ 9 - 11
drivers/tty/serial/samsung.c

@@ -859,7 +859,6 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
 static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
 static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
 {
 {
 	struct s3c24xx_uart_dma	*dma = p->dma;
 	struct s3c24xx_uart_dma	*dma = p->dma;
-	dma_cap_mask_t mask;
 	unsigned long flags;
 	unsigned long flags;
 
 
 	/* Default slave configuration parameters */
 	/* Default slave configuration parameters */
@@ -876,21 +875,17 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
 	else
 	else
 		dma->tx_conf.dst_maxburst = 1;
 		dma->tx_conf.dst_maxburst = 1;
 
 
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
+	dma->rx_chan = dma_request_chan(p->port.dev, "rx");
 
 
-	dma->rx_chan = dma_request_slave_channel_compat(mask, dma->fn,
-					dma->rx_param, p->port.dev, "rx");
-	if (!dma->rx_chan)
-		return -ENODEV;
+	if (IS_ERR(dma->rx_chan))
+		return PTR_ERR(dma->rx_chan);
 
 
 	dmaengine_slave_config(dma->rx_chan, &dma->rx_conf);
 	dmaengine_slave_config(dma->rx_chan, &dma->rx_conf);
 
 
-	dma->tx_chan = dma_request_slave_channel_compat(mask, dma->fn,
-					dma->tx_param, p->port.dev, "tx");
-	if (!dma->tx_chan) {
+	dma->tx_chan = dma_request_chan(p->port.dev, "tx");
+	if (IS_ERR(dma->tx_chan)) {
 		dma_release_channel(dma->rx_chan);
 		dma_release_channel(dma->rx_chan);
-		return -ENODEV;
+		return PTR_ERR(dma->tx_chan);
 	}
 	}
 
 
 	dmaengine_slave_config(dma->tx_chan, &dma->tx_conf);
 	dmaengine_slave_config(dma->tx_chan, &dma->tx_conf);
@@ -1921,6 +1916,7 @@ static int s3c24xx_serial_resume(struct device *dev)
 static int s3c24xx_serial_resume_noirq(struct device *dev)
 static int s3c24xx_serial_resume_noirq(struct device *dev)
 {
 {
 	struct uart_port *port = s3c24xx_dev_to_port(dev);
 	struct uart_port *port = s3c24xx_dev_to_port(dev);
+	struct s3c24xx_uart_port *ourport = to_ourport(port);
 
 
 	if (port) {
 	if (port) {
 		/* restore IRQ mask */
 		/* restore IRQ mask */
@@ -1930,7 +1926,9 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
 				uintm &= ~S3C64XX_UINTM_TXD_MSK;
 				uintm &= ~S3C64XX_UINTM_TXD_MSK;
 			if (rx_enabled(port))
 			if (rx_enabled(port))
 				uintm &= ~S3C64XX_UINTM_RXD_MSK;
 				uintm &= ~S3C64XX_UINTM_RXD_MSK;
+			clk_prepare_enable(ourport->clk);
 			wr_regl(port, S3C64XX_UINTM, uintm);
 			wr_regl(port, S3C64XX_UINTM, uintm);
+			clk_disable_unprepare(ourport->clk);
 		}
 		}
 	}
 	}
 
 

+ 0 - 4
drivers/tty/serial/samsung.h

@@ -44,10 +44,6 @@ struct s3c24xx_serial_drv_data {
 };
 };
 
 
 struct s3c24xx_uart_dma {
 struct s3c24xx_uart_dma {
-	dma_filter_fn			fn;
-	void				*rx_param;
-	void				*tx_param;
-
 	unsigned int			rx_chan_id;
 	unsigned int			rx_chan_id;
 	unsigned int			tx_chan_id;
 	unsigned int			tx_chan_id;
 
 

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

@@ -1191,7 +1191,7 @@ static const char *tegra_uart_type(struct uart_port *u)
 	return TEGRA_UART_TYPE;
 	return TEGRA_UART_TYPE;
 }
 }
 
 
-static struct uart_ops tegra_uart_ops = {
+static const struct uart_ops tegra_uart_ops = {
 	.tx_empty	= tegra_uart_tx_empty,
 	.tx_empty	= tegra_uart_tx_empty,
 	.set_mctrl	= tegra_uart_set_mctrl,
 	.set_mctrl	= tegra_uart_set_mctrl,
 	.get_mctrl	= tegra_uart_get_mctrl,
 	.get_mctrl	= tegra_uart_get_mctrl,

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

@@ -845,7 +845,7 @@ serial_txx9_type(struct uart_port *port)
 	return "txx9";
 	return "txx9";
 }
 }
 
 
-static struct uart_ops serial_txx9_pops = {
+static const struct uart_ops serial_txx9_pops = {
 	.tx_empty	= serial_txx9_tx_empty,
 	.tx_empty	= serial_txx9_tx_empty,
 	.set_mctrl	= serial_txx9_set_mctrl,
 	.set_mctrl	= serial_txx9_set_mctrl,
 	.get_mctrl	= serial_txx9_get_mctrl,
 	.get_mctrl	= serial_txx9_get_mctrl,

+ 578 - 514
drivers/tty/serial/sh-sci.c

@@ -101,23 +101,30 @@ enum SCI_CLKS {
 	for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--)	\
 	for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--)	\
 		if ((_port)->sampling_rate_mask & SCI_SR((_sr)))
 		if ((_port)->sampling_rate_mask & SCI_SR((_sr)))
 
 
+struct plat_sci_reg {
+	u8 offset, size;
+};
+
+struct sci_port_params {
+	const struct plat_sci_reg regs[SCIx_NR_REGS];
+	unsigned int fifosize;
+	unsigned int overrun_reg;
+	unsigned int overrun_mask;
+	unsigned int sampling_rate_mask;
+	unsigned int error_mask;
+	unsigned int error_clear;
+};
+
 struct sci_port {
 struct sci_port {
 	struct uart_port	port;
 	struct uart_port	port;
 
 
 	/* Platform configuration */
 	/* Platform configuration */
-	struct plat_sci_port	*cfg;
-	unsigned int		overrun_reg;
-	unsigned int		overrun_mask;
-	unsigned int		error_mask;
-	unsigned int		error_clear;
+	const struct sci_port_params *params;
+	const struct plat_sci_port *cfg;
 	unsigned int		sampling_rate_mask;
 	unsigned int		sampling_rate_mask;
 	resource_size_t		reg_size;
 	resource_size_t		reg_size;
 	struct mctrl_gpios	*gpios;
 	struct mctrl_gpios	*gpios;
 
 
-	/* Break timer */
-	struct timer_list	break_timer;
-	int			break_flag;
-
 	/* Clocks */
 	/* Clocks */
 	struct clk		*clks[SCI_NUM_CLKS];
 	struct clk		*clks[SCI_NUM_CLKS];
 	unsigned long		clk_rates[SCI_NUM_CLKS];
 	unsigned long		clk_rates[SCI_NUM_CLKS];
@@ -141,7 +148,12 @@ struct sci_port {
 	struct timer_list		rx_timer;
 	struct timer_list		rx_timer;
 	unsigned int			rx_timeout;
 	unsigned int			rx_timeout;
 #endif
 #endif
+	unsigned int			rx_frame;
+	int				rx_trigger;
+	struct timer_list		rx_fifo_timer;
+	int				rx_fifo_timeout;
 
 
+	bool has_rtscts;
 	bool autorts;
 	bool autorts;
 };
 };
 
 
@@ -156,110 +168,97 @@ to_sci_port(struct uart_port *uart)
 	return container_of(uart, struct sci_port, port);
 	return container_of(uart, struct sci_port, port);
 }
 }
 
 
-struct plat_sci_reg {
-	u8 offset, size;
-};
-
-/* Helper for invalidating specific entries of an inherited map. */
-#define sci_reg_invalid	{ .offset = 0, .size = 0 }
-
-static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
-	[SCIx_PROBE_REGTYPE] = {
-		[0 ... SCIx_NR_REGS - 1] = sci_reg_invalid,
-	},
-
+static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
 	/*
 	/*
 	 * Common SCI definitions, dependent on the port's regshift
 	 * Common SCI definitions, dependent on the port's regshift
 	 * value.
 	 * value.
 	 */
 	 */
 	[SCIx_SCI_REGTYPE] = {
 	[SCIx_SCI_REGTYPE] = {
-		[SCSMR]		= { 0x00,  8 },
-		[SCBRR]		= { 0x01,  8 },
-		[SCSCR]		= { 0x02,  8 },
-		[SCxTDR]	= { 0x03,  8 },
-		[SCxSR]		= { 0x04,  8 },
-		[SCxRDR]	= { 0x05,  8 },
-		[SCFCR]		= sci_reg_invalid,
-		[SCFDR]		= sci_reg_invalid,
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= sci_reg_invalid,
-		[SCLSR]		= sci_reg_invalid,
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00,  8 },
+			[SCBRR]		= { 0x01,  8 },
+			[SCSCR]		= { 0x02,  8 },
+			[SCxTDR]	= { 0x03,  8 },
+			[SCxSR]		= { 0x04,  8 },
+			[SCxRDR]	= { 0x05,  8 },
+		},
+		.fifosize = 1,
+		.overrun_reg = SCxSR,
+		.overrun_mask = SCI_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER,
+		.error_clear = SCI_ERROR_CLEAR & ~SCI_ORER,
 	},
 	},
 
 
 	/*
 	/*
-	 * Common definitions for legacy IrDA ports, dependent on
-	 * regshift value.
+	 * Common definitions for legacy IrDA ports.
 	 */
 	 */
 	[SCIx_IRDA_REGTYPE] = {
 	[SCIx_IRDA_REGTYPE] = {
-		[SCSMR]		= { 0x00,  8 },
-		[SCBRR]		= { 0x01,  8 },
-		[SCSCR]		= { 0x02,  8 },
-		[SCxTDR]	= { 0x03,  8 },
-		[SCxSR]		= { 0x04,  8 },
-		[SCxRDR]	= { 0x05,  8 },
-		[SCFCR]		= { 0x06,  8 },
-		[SCFDR]		= { 0x07, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= sci_reg_invalid,
-		[SCLSR]		= sci_reg_invalid,
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00,  8 },
+			[SCBRR]		= { 0x02,  8 },
+			[SCSCR]		= { 0x04,  8 },
+			[SCxTDR]	= { 0x06,  8 },
+			[SCxSR]		= { 0x08, 16 },
+			[SCxRDR]	= { 0x0a,  8 },
+			[SCFCR]		= { 0x0c,  8 },
+			[SCFDR]		= { 0x0e, 16 },
+		},
+		.fifosize = 1,
+		.overrun_reg = SCxSR,
+		.overrun_mask = SCI_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER,
+		.error_clear = SCI_ERROR_CLEAR & ~SCI_ORER,
 	},
 	},
 
 
 	/*
 	/*
 	 * Common SCIFA definitions.
 	 * Common SCIFA definitions.
 	 */
 	 */
 	[SCIx_SCIFA_REGTYPE] = {
 	[SCIx_SCIFA_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x20,  8 },
-		[SCxSR]		= { 0x14, 16 },
-		[SCxRDR]	= { 0x24,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= sci_reg_invalid,
-		[SCLSR]		= sci_reg_invalid,
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= { 0x30, 16 },
-		[SCPDR]		= { 0x34, 16 },
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x20,  8 },
+			[SCxSR]		= { 0x14, 16 },
+			[SCxRDR]	= { 0x24,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+			[SCPCR]		= { 0x30, 16 },
+			[SCPDR]		= { 0x34, 16 },
+		},
+		.fifosize = 64,
+		.overrun_reg = SCxSR,
+		.overrun_mask = SCIFA_ORER,
+		.sampling_rate_mask = SCI_SR_SCIFAB,
+		.error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,
+		.error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,
 	},
 	},
 
 
 	/*
 	/*
 	 * Common SCIFB definitions.
 	 * Common SCIFB definitions.
 	 */
 	 */
 	[SCIx_SCIFB_REGTYPE] = {
 	[SCIx_SCIFB_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x40,  8 },
-		[SCxSR]		= { 0x14, 16 },
-		[SCxRDR]	= { 0x60,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= sci_reg_invalid,
-		[SCTFDR]	= { 0x38, 16 },
-		[SCRFDR]	= { 0x3c, 16 },
-		[SCSPTR]	= sci_reg_invalid,
-		[SCLSR]		= sci_reg_invalid,
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= { 0x30, 16 },
-		[SCPDR]		= { 0x34, 16 },
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x40,  8 },
+			[SCxSR]		= { 0x14, 16 },
+			[SCxRDR]	= { 0x60,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCTFDR]	= { 0x38, 16 },
+			[SCRFDR]	= { 0x3c, 16 },
+			[SCPCR]		= { 0x30, 16 },
+			[SCPDR]		= { 0x34, 16 },
+		},
+		.fifosize = 256,
+		.overrun_reg = SCxSR,
+		.overrun_mask = SCIFA_ORER,
+		.sampling_rate_mask = SCI_SR_SCIFAB,
+		.error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,
+		.error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,
 	},
 	},
 
 
 	/*
 	/*
@@ -267,69 +266,70 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 	 * count registers.
 	 * count registers.
 	 */
 	 */
 	[SCIx_SH2_SCIF_FIFODATA_REGTYPE] = {
 	[SCIx_SH2_SCIF_FIFODATA_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x0c,  8 },
-		[SCxSR]		= { 0x10, 16 },
-		[SCxRDR]	= { 0x14,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= { 0x20, 16 },
-		[SCLSR]		= { 0x24, 16 },
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x0c,  8 },
+			[SCxSR]		= { 0x10, 16 },
+			[SCxRDR]	= { 0x14,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+			[SCSPTR]	= { 0x20, 16 },
+			[SCLSR]		= { 0x24, 16 },
+		},
+		.fifosize = 16,
+		.overrun_reg = SCLSR,
+		.overrun_mask = SCLSR_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK,
+		.error_clear = SCIF_ERROR_CLEAR,
 	},
 	},
 
 
 	/*
 	/*
 	 * Common SH-3 SCIF definitions.
 	 * Common SH-3 SCIF definitions.
 	 */
 	 */
 	[SCIx_SH3_SCIF_REGTYPE] = {
 	[SCIx_SH3_SCIF_REGTYPE] = {
-		[SCSMR]		= { 0x00,  8 },
-		[SCBRR]		= { 0x02,  8 },
-		[SCSCR]		= { 0x04,  8 },
-		[SCxTDR]	= { 0x06,  8 },
-		[SCxSR]		= { 0x08, 16 },
-		[SCxRDR]	= { 0x0a,  8 },
-		[SCFCR]		= { 0x0c,  8 },
-		[SCFDR]		= { 0x0e, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= sci_reg_invalid,
-		[SCLSR]		= sci_reg_invalid,
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00,  8 },
+			[SCBRR]		= { 0x02,  8 },
+			[SCSCR]		= { 0x04,  8 },
+			[SCxTDR]	= { 0x06,  8 },
+			[SCxSR]		= { 0x08, 16 },
+			[SCxRDR]	= { 0x0a,  8 },
+			[SCFCR]		= { 0x0c,  8 },
+			[SCFDR]		= { 0x0e, 16 },
+		},
+		.fifosize = 16,
+		.overrun_reg = SCLSR,
+		.overrun_mask = SCLSR_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK,
+		.error_clear = SCIF_ERROR_CLEAR,
 	},
 	},
 
 
 	/*
 	/*
 	 * Common SH-4(A) SCIF(B) definitions.
 	 * Common SH-4(A) SCIF(B) definitions.
 	 */
 	 */
 	[SCIx_SH4_SCIF_REGTYPE] = {
 	[SCIx_SH4_SCIF_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x0c,  8 },
-		[SCxSR]		= { 0x10, 16 },
-		[SCxRDR]	= { 0x14,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= { 0x20, 16 },
-		[SCLSR]		= { 0x24, 16 },
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x0c,  8 },
+			[SCxSR]		= { 0x10, 16 },
+			[SCxRDR]	= { 0x14,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+			[SCSPTR]	= { 0x20, 16 },
+			[SCLSR]		= { 0x24, 16 },
+		},
+		.fifosize = 16,
+		.overrun_reg = SCLSR,
+		.overrun_mask = SCLSR_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK,
+		.error_clear = SCIF_ERROR_CLEAR,
 	},
 	},
 
 
 	/*
 	/*
@@ -337,46 +337,55 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 	 * External Clock (BRG).
 	 * External Clock (BRG).
 	 */
 	 */
 	[SCIx_SH4_SCIF_BRG_REGTYPE] = {
 	[SCIx_SH4_SCIF_BRG_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x0c,  8 },
-		[SCxSR]		= { 0x10, 16 },
-		[SCxRDR]	= { 0x14,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= { 0x20, 16 },
-		[SCLSR]		= { 0x24, 16 },
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= { 0x30, 16 },
-		[SCCKS]		= { 0x34, 16 },
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x0c,  8 },
+			[SCxSR]		= { 0x10, 16 },
+			[SCxRDR]	= { 0x14,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+			[SCSPTR]	= { 0x20, 16 },
+			[SCLSR]		= { 0x24, 16 },
+			[SCDL]		= { 0x30, 16 },
+			[SCCKS]		= { 0x34, 16 },
+		},
+		.fifosize = 16,
+		.overrun_reg = SCLSR,
+		.overrun_mask = SCLSR_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK,
+		.error_clear = SCIF_ERROR_CLEAR,
 	},
 	},
 
 
 	/*
 	/*
 	 * Common HSCIF definitions.
 	 * Common HSCIF definitions.
 	 */
 	 */
 	[SCIx_HSCIF_REGTYPE] = {
 	[SCIx_HSCIF_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x0c,  8 },
-		[SCxSR]		= { 0x10, 16 },
-		[SCxRDR]	= { 0x14,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= { 0x20, 16 },
-		[SCLSR]		= { 0x24, 16 },
-		[HSSRR]		= { 0x40, 16 },
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= { 0x30, 16 },
-		[SCCKS]		= { 0x34, 16 },
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x0c,  8 },
+			[SCxSR]		= { 0x10, 16 },
+			[SCxRDR]	= { 0x14,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+			[SCSPTR]	= { 0x20, 16 },
+			[SCLSR]		= { 0x24, 16 },
+			[HSSRR]		= { 0x40, 16 },
+			[SCDL]		= { 0x30, 16 },
+			[SCCKS]		= { 0x34, 16 },
+			[HSRTRGR]	= { 0x54, 16 },
+			[HSTTRGR]	= { 0x58, 16 },
+		},
+		.fifosize = 128,
+		.overrun_reg = SCLSR,
+		.overrun_mask = SCLSR_ORER,
+		.sampling_rate_mask = SCI_SR_RANGE(8, 32),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK,
+		.error_clear = SCIF_ERROR_CLEAR,
 	},
 	},
 
 
 	/*
 	/*
@@ -384,23 +393,23 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 	 * register.
 	 * register.
 	 */
 	 */
 	[SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE] = {
 	[SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x0c,  8 },
-		[SCxSR]		= { 0x10, 16 },
-		[SCxRDR]	= { 0x14,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= sci_reg_invalid,
-		[SCLSR]		= { 0x24, 16 },
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x0c,  8 },
+			[SCxSR]		= { 0x10, 16 },
+			[SCxRDR]	= { 0x14,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+			[SCLSR]		= { 0x24, 16 },
+		},
+		.fifosize = 16,
+		.overrun_reg = SCLSR,
+		.overrun_mask = SCLSR_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK,
+		.error_clear = SCIF_ERROR_CLEAR,
 	},
 	},
 
 
 	/*
 	/*
@@ -408,23 +417,26 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 	 * count registers.
 	 * count registers.
 	 */
 	 */
 	[SCIx_SH4_SCIF_FIFODATA_REGTYPE] = {
 	[SCIx_SH4_SCIF_FIFODATA_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x0c,  8 },
-		[SCxSR]		= { 0x10, 16 },
-		[SCxRDR]	= { 0x14,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= { 0x1c, 16 },	/* aliased to SCFDR */
-		[SCRFDR]	= { 0x20, 16 },
-		[SCSPTR]	= { 0x24, 16 },
-		[SCLSR]		= { 0x28, 16 },
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x0c,  8 },
+			[SCxSR]		= { 0x10, 16 },
+			[SCxRDR]	= { 0x14,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+			[SCTFDR]	= { 0x1c, 16 },	/* aliased to SCFDR */
+			[SCRFDR]	= { 0x20, 16 },
+			[SCSPTR]	= { 0x24, 16 },
+			[SCLSR]		= { 0x28, 16 },
+		},
+		.fifosize = 16,
+		.overrun_reg = SCLSR,
+		.overrun_mask = SCLSR_ORER,
+		.sampling_rate_mask = SCI_SR(32),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK,
+		.error_clear = SCIF_ERROR_CLEAR,
 	},
 	},
 
 
 	/*
 	/*
@@ -432,27 +444,26 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 	 * registers.
 	 * registers.
 	 */
 	 */
 	[SCIx_SH7705_SCIF_REGTYPE] = {
 	[SCIx_SH7705_SCIF_REGTYPE] = {
-		[SCSMR]		= { 0x00, 16 },
-		[SCBRR]		= { 0x04,  8 },
-		[SCSCR]		= { 0x08, 16 },
-		[SCxTDR]	= { 0x20,  8 },
-		[SCxSR]		= { 0x14, 16 },
-		[SCxRDR]	= { 0x24,  8 },
-		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
-		[SCSPTR]	= sci_reg_invalid,
-		[SCLSR]		= sci_reg_invalid,
-		[HSSRR]		= sci_reg_invalid,
-		[SCPCR]		= sci_reg_invalid,
-		[SCPDR]		= sci_reg_invalid,
-		[SCDL]		= sci_reg_invalid,
-		[SCCKS]		= sci_reg_invalid,
+		.regs = {
+			[SCSMR]		= { 0x00, 16 },
+			[SCBRR]		= { 0x04,  8 },
+			[SCSCR]		= { 0x08, 16 },
+			[SCxTDR]	= { 0x20,  8 },
+			[SCxSR]		= { 0x14, 16 },
+			[SCxRDR]	= { 0x24,  8 },
+			[SCFCR]		= { 0x18, 16 },
+			[SCFDR]		= { 0x1c, 16 },
+		},
+		.fifosize = 64,
+		.overrun_reg = SCxSR,
+		.overrun_mask = SCIFA_ORER,
+		.sampling_rate_mask = SCI_SR(16),
+		.error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,
+		.error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,
 	},
 	},
 };
 };
 
 
-#define sci_getreg(up, offset)		(sci_regmap[to_sci_port(up)->cfg->regtype] + offset)
+#define sci_getreg(up, offset)		(&to_sci_port(up)->params->regs[offset])
 
 
 /*
 /*
  * The "offset" here is rather misleading, in that it refers to an enum
  * The "offset" here is rather misleading, in that it refers to an enum
@@ -486,41 +497,6 @@ static void sci_serial_out(struct uart_port *p, int offset, int value)
 		WARN(1, "Invalid register access\n");
 		WARN(1, "Invalid register access\n");
 }
 }
 
 
-static int sci_probe_regmap(struct plat_sci_port *cfg)
-{
-	switch (cfg->type) {
-	case PORT_SCI:
-		cfg->regtype = SCIx_SCI_REGTYPE;
-		break;
-	case PORT_IRDA:
-		cfg->regtype = SCIx_IRDA_REGTYPE;
-		break;
-	case PORT_SCIFA:
-		cfg->regtype = SCIx_SCIFA_REGTYPE;
-		break;
-	case PORT_SCIFB:
-		cfg->regtype = SCIx_SCIFB_REGTYPE;
-		break;
-	case PORT_SCIF:
-		/*
-		 * The SH-4 is a bit of a misnomer here, although that's
-		 * where this particular port layout originated. This
-		 * configuration (or some slight variation thereof)
-		 * remains the dominant model for all SCIFs.
-		 */
-		cfg->regtype = SCIx_SH4_SCIF_REGTYPE;
-		break;
-	case PORT_HSCIF:
-		cfg->regtype = SCIx_HSCIF_REGTYPE;
-		break;
-	default:
-		pr_err("Can't probe register map for given port\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static void sci_port_enable(struct sci_port *sci_port)
 static void sci_port_enable(struct sci_port *sci_port)
 {
 {
 	unsigned int i;
 	unsigned int i;
@@ -544,14 +520,6 @@ static void sci_port_disable(struct sci_port *sci_port)
 	if (!sci_port->port.dev)
 	if (!sci_port->port.dev)
 		return;
 		return;
 
 
-	/* Cancel the break timer to ensure that the timer handler will not try
-	 * to access the hardware with clocks and power disabled. Reset the
-	 * break flag to make the break debouncing state machine ready for the
-	 * next break.
-	 */
-	del_timer_sync(&sci_port->break_timer);
-	sci_port->break_flag = 0;
-
 	for (i = SCI_NUM_CLKS; i-- > 0; )
 	for (i = SCI_NUM_CLKS; i-- > 0; )
 		clk_disable_unprepare(sci_port->clks[i]);
 		clk_disable_unprepare(sci_port->clks[i]);
 
 
@@ -646,7 +614,7 @@ static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
 	if (port->type == PORT_SCI) {
 	if (port->type == PORT_SCI) {
 		/* Just store the mask */
 		/* Just store the mask */
 		serial_port_out(port, SCxSR, mask);
 		serial_port_out(port, SCxSR, mask);
-	} else if (to_sci_port(port)->overrun_mask == SCIFA_ORER) {
+	} else if (to_sci_port(port)->params->overrun_mask == SCIFA_ORER) {
 		/* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */
 		/* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */
 		/* Only clear the status bits we want to clear */
 		/* Only clear the status bits we want to clear */
 		serial_port_out(port, SCxSR,
 		serial_port_out(port, SCxSR,
@@ -719,7 +687,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 
 
 		/* Enable RXD and TXD pin functions */
 		/* Enable RXD and TXD pin functions */
 		ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
 		ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
-		if (to_sci_port(port)->cfg->capabilities & SCIx_HAVE_RTSCTS) {
+		if (to_sci_port(port)->has_rtscts) {
 			/* RTS# is output, driven 1 */
 			/* RTS# is output, driven 1 */
 			ctrl |= SCPCR_RTSC;
 			ctrl |= SCPCR_RTSC;
 			serial_port_out(port, SCPDR,
 			serial_port_out(port, SCPDR,
@@ -741,11 +709,13 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 
 
 static int sci_txfill(struct uart_port *port)
 static int sci_txfill(struct uart_port *port)
 {
 {
+	struct sci_port *s = to_sci_port(port);
+	unsigned int fifo_mask = (s->params->fifosize << 1) - 1;
 	const struct plat_sci_reg *reg;
 	const struct plat_sci_reg *reg;
 
 
 	reg = sci_getreg(port, SCTFDR);
 	reg = sci_getreg(port, SCTFDR);
 	if (reg->size)
 	if (reg->size)
-		return serial_port_in(port, SCTFDR) & ((port->fifosize << 1) - 1);
+		return serial_port_in(port, SCTFDR) & fifo_mask;
 
 
 	reg = sci_getreg(port, SCFDR);
 	reg = sci_getreg(port, SCFDR);
 	if (reg->size)
 	if (reg->size)
@@ -761,33 +731,21 @@ static int sci_txroom(struct uart_port *port)
 
 
 static int sci_rxfill(struct uart_port *port)
 static int sci_rxfill(struct uart_port *port)
 {
 {
+	struct sci_port *s = to_sci_port(port);
+	unsigned int fifo_mask = (s->params->fifosize << 1) - 1;
 	const struct plat_sci_reg *reg;
 	const struct plat_sci_reg *reg;
 
 
 	reg = sci_getreg(port, SCRFDR);
 	reg = sci_getreg(port, SCRFDR);
 	if (reg->size)
 	if (reg->size)
-		return serial_port_in(port, SCRFDR) & ((port->fifosize << 1) - 1);
+		return serial_port_in(port, SCRFDR) & fifo_mask;
 
 
 	reg = sci_getreg(port, SCFDR);
 	reg = sci_getreg(port, SCFDR);
 	if (reg->size)
 	if (reg->size)
-		return serial_port_in(port, SCFDR) & ((port->fifosize << 1) - 1);
+		return serial_port_in(port, SCFDR) & fifo_mask;
 
 
 	return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
 	return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
 }
 }
 
 
-/*
- * SCI helper for checking the state of the muxed port/RXD pins.
- */
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	struct sci_port *s = to_sci_port(port);
-
-	if (s->cfg->port_reg <= 0)
-		return 1;
-
-	/* Cast for ARM damage */
-	return !!__raw_readb((void __iomem *)(uintptr_t)s->cfg->port_reg);
-}
-
 /* ********************************************************************** *
 /* ********************************************************************** *
  *                   the interrupt related routines                       *
  *                   the interrupt related routines                       *
  * ********************************************************************** */
  * ********************************************************************** */
@@ -855,7 +813,6 @@ static void sci_transmit_chars(struct uart_port *port)
 
 
 static void sci_receive_chars(struct uart_port *port)
 static void sci_receive_chars(struct uart_port *port)
 {
 {
-	struct sci_port *sci_port = to_sci_port(port);
 	struct tty_port *tport = &port->state->port;
 	struct tty_port *tport = &port->state->port;
 	int i, count, copied = 0;
 	int i, count, copied = 0;
 	unsigned short status;
 	unsigned short status;
@@ -875,8 +832,7 @@ static void sci_receive_chars(struct uart_port *port)
 
 
 		if (port->type == PORT_SCI) {
 		if (port->type == PORT_SCI) {
 			char c = serial_port_in(port, SCxRDR);
 			char c = serial_port_in(port, SCxRDR);
-			if (uart_handle_sysrq_char(port, c) ||
-			    sci_port->break_flag)
+			if (uart_handle_sysrq_char(port, c))
 				count = 0;
 				count = 0;
 			else
 			else
 				tty_insert_flip_char(tport, c, TTY_NORMAL);
 				tty_insert_flip_char(tport, c, TTY_NORMAL);
@@ -885,25 +841,6 @@ static void sci_receive_chars(struct uart_port *port)
 				char c = serial_port_in(port, SCxRDR);
 				char c = serial_port_in(port, SCxRDR);
 
 
 				status = serial_port_in(port, SCxSR);
 				status = serial_port_in(port, SCxSR);
-#if defined(CONFIG_CPU_SH3)
-				/* Skip "chars" during break */
-				if (sci_port->break_flag) {
-					if ((c == 0) &&
-					    (status & SCxSR_FER(port))) {
-						count--; i--;
-						continue;
-					}
-
-					/* Nonzero => end-of-break */
-					dev_dbg(port->dev, "debounce<%02x>\n", c);
-					sci_port->break_flag = 0;
-
-					if (STEPFN(c)) {
-						count--; i--;
-						continue;
-					}
-				}
-#endif /* CONFIG_CPU_SH3 */
 				if (uart_handle_sysrq_char(port, c)) {
 				if (uart_handle_sysrq_char(port, c)) {
 					count--; i--;
 					count--; i--;
 					continue;
 					continue;
@@ -941,37 +878,6 @@ static void sci_receive_chars(struct uart_port *port)
 	}
 	}
 }
 }
 
 
-#define SCI_BREAK_JIFFIES (HZ/20)
-
-/*
- * The sci generates interrupts during the break,
- * 1 per millisecond or so during the break period, for 9600 baud.
- * So dont bother disabling interrupts.
- * But dont want more than 1 break event.
- * Use a kernel timer to periodically poll the rx line until
- * the break is finished.
- */
-static inline void sci_schedule_break_timer(struct sci_port *port)
-{
-	mod_timer(&port->break_timer, jiffies + SCI_BREAK_JIFFIES);
-}
-
-/* Ensure that two consecutive samples find the break over. */
-static void sci_break_timer(unsigned long data)
-{
-	struct sci_port *port = (struct sci_port *)data;
-
-	if (sci_rxd_in(&port->port) == 0) {
-		port->break_flag = 1;
-		sci_schedule_break_timer(port);
-	} else if (port->break_flag == 1) {
-		/* break is over. */
-		port->break_flag = 2;
-		sci_schedule_break_timer(port);
-	} else
-		port->break_flag = 0;
-}
-
 static int sci_handle_errors(struct uart_port *port)
 static int sci_handle_errors(struct uart_port *port)
 {
 {
 	int copied = 0;
 	int copied = 0;
@@ -980,7 +886,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 & s->overrun_mask) {
+	if (status & s->params->overrun_mask) {
 		port->icount.overrun++;
 		port->icount.overrun++;
 
 
 		/* overrun error */
 		/* overrun error */
@@ -991,35 +897,13 @@ static int sci_handle_errors(struct uart_port *port)
 	}
 	}
 
 
 	if (status & SCxSR_FER(port)) {
 	if (status & SCxSR_FER(port)) {
-		if (sci_rxd_in(port) == 0) {
-			/* Notify of BREAK */
-			struct sci_port *sci_port = to_sci_port(port);
-
-			if (!sci_port->break_flag) {
-				port->icount.brk++;
-
-				sci_port->break_flag = 1;
-				sci_schedule_break_timer(sci_port);
+		/* frame error */
+		port->icount.frame++;
 
 
-				/* Do sysrq handling. */
-				if (uart_handle_break(port))
-					return 0;
-
-				dev_dbg(port->dev, "BREAK detected\n");
-
-				if (tty_insert_flip_char(tport, 0, TTY_BREAK))
-					copied++;
-			}
-
-		} else {
-			/* frame error */
-			port->icount.frame++;
-
-			if (tty_insert_flip_char(tport, 0, TTY_FRAME))
-				copied++;
+		if (tty_insert_flip_char(tport, 0, TTY_FRAME))
+			copied++;
 
 
-			dev_notice(port->dev, "frame error\n");
-		}
+		dev_notice(port->dev, "frame error\n");
 	}
 	}
 
 
 	if (status & SCxSR_PER(port)) {
 	if (status & SCxSR_PER(port)) {
@@ -1046,14 +930,14 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
 	int copied = 0;
 	int copied = 0;
 	u16 status;
 	u16 status;
 
 
-	reg = sci_getreg(port, s->overrun_reg);
+	reg = sci_getreg(port, s->params->overrun_reg);
 	if (!reg->size)
 	if (!reg->size)
 		return 0;
 		return 0;
 
 
-	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);
+	status = serial_port_in(port, s->params->overrun_reg);
+	if (status & s->params->overrun_mask) {
+		status &= ~s->params->overrun_mask;
+		serial_port_out(port, s->params->overrun_reg, status);
 
 
 		port->icount.overrun++;
 		port->icount.overrun++;
 
 
@@ -1072,17 +956,11 @@ static int sci_handle_breaks(struct uart_port *port)
 	int copied = 0;
 	int copied = 0;
 	unsigned short status = serial_port_in(port, SCxSR);
 	unsigned short status = serial_port_in(port, SCxSR);
 	struct tty_port *tport = &port->state->port;
 	struct tty_port *tport = &port->state->port;
-	struct sci_port *s = to_sci_port(port);
 
 
 	if (uart_handle_break(port))
 	if (uart_handle_break(port))
 		return 0;
 		return 0;
 
 
-	if (!s->break_flag && status & SCxSR_BRK(port)) {
-#if defined(CONFIG_CPU_SH3)
-		/* Debounce break */
-		s->break_flag = 1;
-#endif
-
+	if (status & SCxSR_BRK(port)) {
 		port->icount.brk++;
 		port->icount.brk++;
 
 
 		/* Notify of BREAK */
 		/* Notify of BREAK */
@@ -1100,6 +978,146 @@ static int sci_handle_breaks(struct uart_port *port)
 	return copied;
 	return copied;
 }
 }
 
 
+static int scif_set_rtrg(struct uart_port *port, int rx_trig)
+{
+	unsigned int bits;
+
+	if (rx_trig < 1)
+		rx_trig = 1;
+	if (rx_trig >= port->fifosize)
+		rx_trig = port->fifosize;
+
+	/* HSCIF can be set to an arbitrary level. */
+	if (sci_getreg(port, HSRTRGR)->size) {
+		serial_port_out(port, HSRTRGR, rx_trig);
+		return rx_trig;
+	}
+
+	switch (port->type) {
+	case PORT_SCIF:
+		if (rx_trig < 4) {
+			bits = 0;
+			rx_trig = 1;
+		} else if (rx_trig < 8) {
+			bits = SCFCR_RTRG0;
+			rx_trig = 4;
+		} else if (rx_trig < 14) {
+			bits = SCFCR_RTRG1;
+			rx_trig = 8;
+		} else {
+			bits = SCFCR_RTRG0 | SCFCR_RTRG1;
+			rx_trig = 14;
+		}
+		break;
+	case PORT_SCIFA:
+	case PORT_SCIFB:
+		if (rx_trig < 16) {
+			bits = 0;
+			rx_trig = 1;
+		} else if (rx_trig < 32) {
+			bits = SCFCR_RTRG0;
+			rx_trig = 16;
+		} else if (rx_trig < 48) {
+			bits = SCFCR_RTRG1;
+			rx_trig = 32;
+		} else {
+			bits = SCFCR_RTRG0 | SCFCR_RTRG1;
+			rx_trig = 48;
+		}
+		break;
+	default:
+		WARN(1, "unknown FIFO configuration");
+		return 1;
+	}
+
+	serial_port_out(port, SCFCR,
+		(serial_port_in(port, SCFCR) &
+		~(SCFCR_RTRG1 | SCFCR_RTRG0)) | bits);
+
+	return rx_trig;
+}
+
+static int scif_rtrg_enabled(struct uart_port *port)
+{
+	if (sci_getreg(port, HSRTRGR)->size)
+		return serial_port_in(port, HSRTRGR) != 0;
+	else
+		return (serial_port_in(port, SCFCR) &
+			(SCFCR_RTRG0 | SCFCR_RTRG1)) != 0;
+}
+
+static void rx_fifo_timer_fn(unsigned long arg)
+{
+	struct sci_port *s = (struct sci_port *)arg;
+	struct uart_port *port = &s->port;
+
+	dev_dbg(port->dev, "Rx timed out\n");
+	scif_set_rtrg(port, 1);
+}
+
+static ssize_t rx_trigger_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct uart_port *port = dev_get_drvdata(dev);
+	struct sci_port *sci = to_sci_port(port);
+
+	return sprintf(buf, "%d\n", sci->rx_trigger);
+}
+
+static ssize_t rx_trigger_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct uart_port *port = dev_get_drvdata(dev);
+	struct sci_port *sci = to_sci_port(port);
+	long r;
+
+	if (kstrtol(buf, 0, &r) == -EINVAL)
+		return -EINVAL;
+
+	sci->rx_trigger = scif_set_rtrg(port, r);
+	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+		scif_set_rtrg(port, 1);
+
+	return count;
+}
+
+static DEVICE_ATTR(rx_fifo_trigger, 0644, rx_trigger_show, rx_trigger_store);
+
+static ssize_t rx_fifo_timeout_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct uart_port *port = dev_get_drvdata(dev);
+	struct sci_port *sci = to_sci_port(port);
+
+	return sprintf(buf, "%d\n", sci->rx_fifo_timeout);
+}
+
+static ssize_t rx_fifo_timeout_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct uart_port *port = dev_get_drvdata(dev);
+	struct sci_port *sci = to_sci_port(port);
+	long r;
+
+	if (kstrtol(buf, 0, &r) == -EINVAL)
+		return -EINVAL;
+	sci->rx_fifo_timeout = r;
+	scif_set_rtrg(port, 1);
+	if (r > 0)
+		setup_timer(&sci->rx_fifo_timer, rx_fifo_timer_fn,
+			    (unsigned long)sci);
+	return count;
+}
+
+static DEVICE_ATTR(rx_fifo_timeout, 0644, rx_fifo_timeout_show, rx_fifo_timeout_store);
+
+
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 static void sci_dma_tx_complete(void *arg)
 static void sci_dma_tx_complete(void *arg)
 {
 {
@@ -1410,20 +1428,14 @@ static void rx_timer_fn(unsigned long arg)
 }
 }
 
 
 static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
 static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
-					     enum dma_transfer_direction dir,
-					     unsigned int id)
+					     enum dma_transfer_direction dir)
 {
 {
-	dma_cap_mask_t mask;
 	struct dma_chan *chan;
 	struct dma_chan *chan;
 	struct dma_slave_config cfg;
 	struct dma_slave_config cfg;
 	int ret;
 	int ret;
 
 
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
-					(void *)(unsigned long)id, port->dev,
-					dir == DMA_MEM_TO_DEV ? "tx" : "rx");
+	chan = dma_request_slave_channel(port->dev,
+					 dir == DMA_MEM_TO_DEV ? "tx" : "rx");
 	if (!chan) {
 	if (!chan) {
 		dev_warn(port->dev,
 		dev_warn(port->dev,
 			 "dma_request_slave_channel_compat failed\n");
 			 "dma_request_slave_channel_compat failed\n");
@@ -1459,12 +1471,11 @@ static void sci_request_dma(struct uart_port *port)
 
 
 	dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
 	dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
 
 
-	if (!port->dev->of_node &&
-	    (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0))
+	if (!port->dev->of_node)
 		return;
 		return;
 
 
 	s->cookie_tx = -EINVAL;
 	s->cookie_tx = -EINVAL;
-	chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV, s->cfg->dma_slave_tx);
+	chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV);
 	dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
 	dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
 	if (chan) {
 	if (chan) {
 		s->chan_tx = chan;
 		s->chan_tx = chan;
@@ -1486,7 +1497,7 @@ static void sci_request_dma(struct uart_port *port)
 		INIT_WORK(&s->work_tx, work_fn_tx);
 		INIT_WORK(&s->work_tx, work_fn_tx);
 	}
 	}
 
 
-	chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM, s->cfg->dma_slave_rx);
+	chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM);
 	dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
 	dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
 	if (chan) {
 	if (chan) {
 		unsigned int i;
 		unsigned int i;
@@ -1546,10 +1557,10 @@ static inline void sci_free_dma(struct uart_port *port)
 
 
 static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
 static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
 {
 {
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
 	struct uart_port *port = ptr;
 	struct uart_port *port = ptr;
 	struct sci_port *s = to_sci_port(port);
 	struct sci_port *s = to_sci_port(port);
 
 
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
 	if (s->chan_rx) {
 	if (s->chan_rx) {
 		u16 scr = serial_port_in(port, SCSCR);
 		u16 scr = serial_port_in(port, SCSCR);
 		u16 ssr = serial_port_in(port, SCxSR);
 		u16 ssr = serial_port_in(port, SCxSR);
@@ -1574,6 +1585,14 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
 	}
 	}
 #endif
 #endif
 
 
+	if (s->rx_trigger > 1 && s->rx_fifo_timeout > 0) {
+		if (!scif_rtrg_enabled(port))
+			scif_set_rtrg(port, s->rx_trigger);
+
+		mod_timer(&s->rx_fifo_timer, jiffies + DIV_ROUND_UP(
+			  s->rx_frame * s->rx_fifo_timeout, 1000));
+	}
+
 	/* I think sci_receive_chars has to be called irrespective
 	/* I think sci_receive_chars has to be called irrespective
 	 * of whether the I_IXOFF is set, otherwise, how is the interrupt
 	 * of whether the I_IXOFF is set, otherwise, how is the interrupt
 	 * to be disabled?
 	 * to be disabled?
@@ -1642,12 +1661,10 @@ 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);
-	if (s->overrun_reg == SCxSR)
+	if (s->params->overrun_reg == SCxSR)
 		orer_status = ssr_status;
 		orer_status = ssr_status;
-	else {
-		if (sci_getreg(port, s->overrun_reg)->size)
-			orer_status = serial_port_in(port, s->overrun_reg);
-	}
+	else if (sci_getreg(port, s->params->overrun_reg)->size)
+		orer_status = serial_port_in(port, s->params->overrun_reg);
 
 
 	err_enabled = scr_status & port_rx_irq_mask(port);
 	err_enabled = scr_status & port_rx_irq_mask(port);
 
 
@@ -1673,7 +1690,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 & s->overrun_mask) {
+	if (orer_status & s->params->overrun_mask) {
 		sci_handle_fifo_overrun(port);
 		sci_handle_fifo_overrun(port);
 		ret = IRQ_HANDLED;
 		ret = IRQ_HANDLED;
 	}
 	}
@@ -1743,8 +1760,10 @@ static int sci_request_irq(struct sci_port *port)
 		desc = sci_irq_desc + i;
 		desc = sci_irq_desc + i;
 		port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
 		port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
 					    dev_name(up->dev), desc->desc);
 					    dev_name(up->dev), desc->desc);
-		if (!port->irqstr[j])
+		if (!port->irqstr[j]) {
+			ret = -ENOMEM;
 			goto out_nomem;
 			goto out_nomem;
+		}
 
 
 		ret = request_irq(irq, desc->handler, up->irqflags,
 		ret = request_irq(irq, desc->handler, up->irqflags,
 				  port->irqstr[j], port);
 				  port->irqstr[j], port);
@@ -1874,7 +1893,7 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
 
 	mctrl_gpio_set(s->gpios, mctrl);
 	mctrl_gpio_set(s->gpios, mctrl);
 
 
-	if (!(s->cfg->capabilities & SCIx_HAVE_RTSCTS))
+	if (!s->has_rtscts)
 		return;
 		return;
 
 
 	if (!(mctrl & TIOCM_RTS)) {
 	if (!(mctrl & TIOCM_RTS)) {
@@ -2136,6 +2155,7 @@ static void sci_reset(struct uart_port *port)
 {
 {
 	const struct plat_sci_reg *reg;
 	const struct plat_sci_reg *reg;
 	unsigned int status;
 	unsigned int status;
+	struct sci_port *s = to_sci_port(port);
 
 
 	do {
 	do {
 		status = serial_port_in(port, SCxSR);
 		status = serial_port_in(port, SCxSR);
@@ -2155,12 +2175,26 @@ static void sci_reset(struct uart_port *port)
 		status &= ~(SCLSR_TO | SCLSR_ORER);
 		status &= ~(SCLSR_TO | SCLSR_ORER);
 		serial_port_out(port, SCLSR, status);
 		serial_port_out(port, SCLSR, status);
 	}
 	}
+
+	if (s->rx_trigger > 1) {
+		if (s->rx_fifo_timeout) {
+			scif_set_rtrg(port, 1);
+			setup_timer(&s->rx_fifo_timer, rx_fifo_timer_fn,
+				    (unsigned long)s);
+		} else {
+			if (port->type == PORT_SCIFA ||
+			    port->type == PORT_SCIFB)
+				scif_set_rtrg(port, 1);
+			else
+				scif_set_rtrg(port, s->rx_trigger);
+		}
+	}
 }
 }
 
 
 static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 			    struct ktermios *old)
 {
 {
-	unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i;
+	unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i, bits;
 	unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0;
 	unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0;
 	unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0;
 	unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0;
 	struct sci_port *s = to_sci_port(port);
 	struct sci_port *s = to_sci_port(port);
@@ -2341,7 +2375,8 @@ done:
 		serial_port_out(port, SCFCR, ctrl);
 		serial_port_out(port, SCFCR, ctrl);
 	}
 	}
 
 
-	scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0);
+	scr_val |= SCSCR_RE | SCSCR_TE |
+		   (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
 	dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val);
 	dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val);
 	serial_port_out(port, SCSCR, scr_val);
 	serial_port_out(port, SCSCR, scr_val);
 	if ((srr + 1 == 5) &&
 	if ((srr + 1 == 5) &&
@@ -2355,7 +2390,6 @@ done:
 		udelay(DIV_ROUND_UP(10 * 1000000, baud));
 		udelay(DIV_ROUND_UP(10 * 1000000, baud));
 	}
 	}
 
 
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
 	/*
 	/*
 	 * Calculate delay for 2 DMA buffers (4 FIFO).
 	 * Calculate delay for 2 DMA buffers (4 FIFO).
 	 * See serial_core.c::uart_update_timeout().
 	 * See serial_core.c::uart_update_timeout().
@@ -2366,36 +2400,34 @@ done:
 	 * value obtained by this formula is too small. Therefore, if the value
 	 * value obtained by this formula is too small. Therefore, if the value
 	 * is smaller than 20ms, use 20ms as the timeout value for DMA.
 	 * is smaller than 20ms, use 20ms as the timeout value for DMA.
 	 */
 	 */
-	if (s->chan_rx) {
-		unsigned int bits;
+	/* byte size and parity */
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		bits = 7;
+		break;
+	case CS6:
+		bits = 8;
+		break;
+	case CS7:
+		bits = 9;
+		break;
+	default:
+		bits = 10;
+		break;
+	}
 
 
-		/* byte size and parity */
-		switch (termios->c_cflag & CSIZE) {
-		case CS5:
-			bits = 7;
-			break;
-		case CS6:
-			bits = 8;
-			break;
-		case CS7:
-			bits = 9;
-			break;
-		default:
-			bits = 10;
-			break;
-		}
+	if (termios->c_cflag & CSTOPB)
+		bits++;
+	if (termios->c_cflag & PARENB)
+		bits++;
 
 
-		if (termios->c_cflag & CSTOPB)
-			bits++;
-		if (termios->c_cflag & PARENB)
-			bits++;
-		s->rx_timeout = DIV_ROUND_UP((s->buf_len_rx * 2 * bits * HZ) /
-					     (baud / 10), 10);
-		dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
-			s->rx_timeout * 1000 / HZ, port->timeout);
-		if (s->rx_timeout < msecs_to_jiffies(20))
-			s->rx_timeout = msecs_to_jiffies(20);
-	}
+	s->rx_frame = (100 * bits * HZ) / (baud / 10);
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	s->rx_timeout = DIV_ROUND_UP(s->buf_len_rx * 2 * s->rx_frame, 1000);
+	dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
+		s->rx_timeout * 1000 / HZ, port->timeout);
+	if (s->rx_timeout < msecs_to_jiffies(20))
+		s->rx_timeout = msecs_to_jiffies(20);
 #endif
 #endif
 
 
 	if ((termios->c_cflag & CREAD) != 0)
 	if ((termios->c_cflag & CREAD) != 0)
@@ -2452,7 +2484,7 @@ static int sci_remap_port(struct uart_port *port)
 	if (port->membase)
 	if (port->membase)
 		return 0;
 		return 0;
 
 
-	if (port->flags & UPF_IOREMAP) {
+	if (port->dev->of_node || (port->flags & UPF_IOREMAP)) {
 		port->membase = ioremap_nocache(port->mapbase, sport->reg_size);
 		port->membase = ioremap_nocache(port->mapbase, sport->reg_size);
 		if (unlikely(!port->membase)) {
 		if (unlikely(!port->membase)) {
 			dev_err(port->dev, "can't remap port#%d\n", port->line);
 			dev_err(port->dev, "can't remap port#%d\n", port->line);
@@ -2474,7 +2506,7 @@ static void sci_release_port(struct uart_port *port)
 {
 {
 	struct sci_port *sport = to_sci_port(port);
 	struct sci_port *sport = to_sci_port(port);
 
 
-	if (port->flags & UPF_IOREMAP) {
+	if (port->dev->of_node || (port->flags & UPF_IOREMAP)) {
 		iounmap(port->membase);
 		iounmap(port->membase);
 		port->membase = NULL;
 		port->membase = NULL;
 	}
 	}
@@ -2604,9 +2636,50 @@ found:
 	return 0;
 	return 0;
 }
 }
 
 
+static const struct sci_port_params *
+sci_probe_regmap(const struct plat_sci_port *cfg)
+{
+	unsigned int regtype;
+
+	if (cfg->regtype != SCIx_PROBE_REGTYPE)
+		return &sci_port_params[cfg->regtype];
+
+	switch (cfg->type) {
+	case PORT_SCI:
+		regtype = SCIx_SCI_REGTYPE;
+		break;
+	case PORT_IRDA:
+		regtype = SCIx_IRDA_REGTYPE;
+		break;
+	case PORT_SCIFA:
+		regtype = SCIx_SCIFA_REGTYPE;
+		break;
+	case PORT_SCIFB:
+		regtype = SCIx_SCIFB_REGTYPE;
+		break;
+	case PORT_SCIF:
+		/*
+		 * The SH-4 is a bit of a misnomer here, although that's
+		 * where this particular port layout originated. This
+		 * configuration (or some slight variation thereof)
+		 * remains the dominant model for all SCIFs.
+		 */
+		regtype = SCIx_SH4_SCIF_REGTYPE;
+		break;
+	case PORT_HSCIF:
+		regtype = SCIx_HSCIF_REGTYPE;
+		break;
+	default:
+		pr_err("Can't probe register map for given port\n");
+		return NULL;
+	}
+
+	return &sci_port_params[regtype];
+}
+
 static int sci_init_single(struct platform_device *dev,
 static int sci_init_single(struct platform_device *dev,
 			   struct sci_port *sci_port, unsigned int index,
 			   struct sci_port *sci_port, unsigned int index,
-			   struct plat_sci_port *p, bool early)
+			   const struct plat_sci_port *p, bool early)
 {
 {
 	struct uart_port *port = &sci_port->port;
 	struct uart_port *port = &sci_port->port;
 	const struct resource *res;
 	const struct resource *res;
@@ -2643,57 +2716,41 @@ static int sci_init_single(struct platform_device *dev,
 		sci_port->irqs[3] = sci_port->irqs[0];
 		sci_port->irqs[3] = sci_port->irqs[0];
 	}
 	}
 
 
-	if (p->regtype == SCIx_PROBE_REGTYPE) {
-		ret = sci_probe_regmap(p);
-		if (unlikely(ret))
-			return ret;
-	}
+	sci_port->params = sci_probe_regmap(p);
+	if (unlikely(sci_port->params == NULL))
+		return -EINVAL;
 
 
 	switch (p->type) {
 	switch (p->type) {
 	case PORT_SCIFB:
 	case PORT_SCIFB:
-		port->fifosize = 256;
-		sci_port->overrun_reg = SCxSR;
-		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
+		sci_port->rx_trigger = 48;
 		break;
 		break;
 	case PORT_HSCIF:
 	case PORT_HSCIF:
-		port->fifosize = 128;
-		sci_port->overrun_reg = SCLSR;
-		sci_port->overrun_mask = SCLSR_ORER;
-		sci_port->sampling_rate_mask = SCI_SR_RANGE(8, 32);
+		sci_port->rx_trigger = 64;
 		break;
 		break;
 	case PORT_SCIFA:
 	case PORT_SCIFA:
-		port->fifosize = 64;
-		sci_port->overrun_reg = SCxSR;
-		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
+		sci_port->rx_trigger = 32;
 		break;
 		break;
 	case PORT_SCIF:
 	case PORT_SCIF:
-		port->fifosize = 16;
-		if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
-			sci_port->overrun_reg = SCxSR;
-			sci_port->overrun_mask = SCIFA_ORER;
-			sci_port->sampling_rate_mask = SCI_SR(16);
-		} else {
-			sci_port->overrun_reg = SCLSR;
-			sci_port->overrun_mask = SCLSR_ORER;
-			sci_port->sampling_rate_mask = SCI_SR(32);
-		}
+		if (p->regtype == SCIx_SH7705_SCIF_REGTYPE)
+			/* RX triggering not implemented for this IP */
+			sci_port->rx_trigger = 1;
+		else
+			sci_port->rx_trigger = 8;
 		break;
 		break;
 	default:
 	default:
-		port->fifosize = 1;
-		sci_port->overrun_reg = SCxSR;
-		sci_port->overrun_mask = SCI_ORER;
-		sci_port->sampling_rate_mask = SCI_SR(32);
+		sci_port->rx_trigger = 1;
 		break;
 		break;
 	}
 	}
 
 
+	sci_port->rx_fifo_timeout = 0;
+
 	/* SCIFA on sh7723 and sh7724 need a custom sampling rate that doesn't
 	/* SCIFA on sh7723 and sh7724 need a custom sampling rate that doesn't
 	 * match the SoC datasheet, this should be investigated. Let platform
 	 * match the SoC datasheet, this should be investigated. Let platform
 	 * data override the sampling rate for now.
 	 * data override the sampling rate for now.
 	 */
 	 */
-	if (p->sampling_rate)
-		sci_port->sampling_rate_mask = SCI_SR(p->sampling_rate);
+	sci_port->sampling_rate_mask = p->sampling_rate
+				     ? SCI_SR(p->sampling_rate)
+				     : sci_port->params->sampling_rate_mask;
 
 
 	if (!early) {
 	if (!early) {
 		ret = sci_init_clocks(sci_port, &dev->dev);
 		ret = sci_init_clocks(sci_port, &dev->dev);
@@ -2705,34 +2762,17 @@ static int sci_init_single(struct platform_device *dev,
 		pm_runtime_enable(&dev->dev);
 		pm_runtime_enable(&dev->dev);
 	}
 	}
 
 
-	sci_port->break_timer.data = (unsigned long)sci_port;
-	sci_port->break_timer.function = sci_break_timer;
-	init_timer(&sci_port->break_timer);
-
-	/*
-	 * Establish some sensible defaults for the error detection.
-	 */
-	if (p->type == PORT_SCI) {
-		sci_port->error_mask = SCI_DEFAULT_ERROR_MASK;
-		sci_port->error_clear = SCI_ERROR_CLEAR;
-	} else {
-		sci_port->error_mask = SCIF_DEFAULT_ERROR_MASK;
-		sci_port->error_clear = SCIF_ERROR_CLEAR;
-	}
+	port->type		= p->type;
+	port->flags		= UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
+	port->fifosize		= sci_port->params->fifosize;
 
 
-	/*
-	 * Make the error mask inclusive of overrun detection, if
-	 * supported.
-	 */
-	if (sci_port->overrun_reg == SCxSR) {
-		sci_port->error_mask |= sci_port->overrun_mask;
-		sci_port->error_clear &= ~sci_port->overrun_mask;
+	if (port->type == PORT_SCI) {
+		if (sci_port->reg_size >= 0x20)
+			port->regshift = 2;
+		else
+			port->regshift = 1;
 	}
 	}
 
 
-	port->type		= p->type;
-	port->flags		= UPF_FIXED_PORT | p->flags;
-	port->regshift		= p->regshift;
-
 	/*
 	/*
 	 * The UART port needs an IRQ value, so we peg this to the RX IRQ
 	 * The UART port needs an IRQ value, so we peg this to the RX IRQ
 	 * for the multi-IRQ ports, which is where we are primarily
 	 * for the multi-IRQ ports, which is where we are primarily
@@ -2746,10 +2786,6 @@ static int sci_init_single(struct platform_device *dev,
 	port->serial_in		= sci_serial_in;
 	port->serial_in		= sci_serial_in;
 	port->serial_out	= sci_serial_out;
 	port->serial_out	= sci_serial_out;
 
 
-	if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0)
-		dev_dbg(port->dev, "DMA tx %d, rx %d\n",
-			p->dma_slave_tx, p->dma_slave_rx);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2791,7 +2827,8 @@ static void serial_console_write(struct console *co, const char *s,
 
 
 	/* first save SCSCR then disable interrupts, keep clock source */
 	/* first save SCSCR then disable interrupts, keep clock source */
 	ctrl = serial_port_in(port, SCSCR);
 	ctrl = serial_port_in(port, SCSCR);
-	ctrl_temp = (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) |
+	ctrl_temp = SCSCR_RE | SCSCR_TE |
+		    (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) |
 		    (ctrl & (SCSCR_CKE1 | SCSCR_CKE0));
 		    (ctrl & (SCSCR_CKE1 | SCSCR_CKE0));
 	serial_port_out(port, SCSCR, ctrl_temp);
 	serial_port_out(port, SCSCR, ctrl_temp);
 
 
@@ -2866,7 +2903,7 @@ static char early_serial_buf[32];
 
 
 static int sci_probe_earlyprintk(struct platform_device *pdev)
 static int sci_probe_earlyprintk(struct platform_device *pdev)
 {
 {
-	struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev);
+	const struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev);
 
 
 	if (early_serial_console.data)
 	if (early_serial_console.data)
 		return -EEXIST;
 		return -EEXIST;
@@ -2916,6 +2953,15 @@ static int sci_remove(struct platform_device *dev)
 
 
 	sci_cleanup_single(port);
 	sci_cleanup_single(port);
 
 
+	if (port->port.fifosize > 1) {
+		sysfs_remove_file(&dev->dev.kobj,
+				  &dev_attr_rx_fifo_trigger.attr);
+	}
+	if (port->port.type == PORT_SCIFA || port->port.type == PORT_SCIFB) {
+		sysfs_remove_file(&dev->dev.kobj,
+				  &dev_attr_rx_fifo_timeout.attr);
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2963,12 +3009,13 @@ static const struct of_device_id of_sci_match[] = {
 };
 };
 MODULE_DEVICE_TABLE(of, of_sci_match);
 MODULE_DEVICE_TABLE(of, of_sci_match);
 
 
-static struct plat_sci_port *
-sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
+static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+					  unsigned int *dev_id)
 {
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *match;
 	const struct of_device_id *match;
 	struct plat_sci_port *p;
 	struct plat_sci_port *p;
+	struct sci_port *sp;
 	int id;
 	int id;
 
 
 	if (!IS_ENABLED(CONFIG_OF) || !np)
 	if (!IS_ENABLED(CONFIG_OF) || !np)
@@ -2989,15 +3036,14 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
 		return NULL;
 		return NULL;
 	}
 	}
 
 
+	sp = &sci_ports[id];
 	*dev_id = id;
 	*dev_id = id;
 
 
-	p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
 	p->type = SCI_OF_TYPE(match->data);
 	p->type = SCI_OF_TYPE(match->data);
 	p->regtype = SCI_OF_REGTYPE(match->data);
 	p->regtype = SCI_OF_REGTYPE(match->data);
-	p->scscr = SCSCR_RE | SCSCR_TE;
 
 
 	if (of_find_property(np, "uart-has-rtscts", NULL))
 	if (of_find_property(np, "uart-has-rtscts", NULL))
-		p->capabilities |= SCIx_HAVE_RTSCTS;
+		sp->has_rtscts = true;
 
 
 	return p;
 	return p;
 }
 }
@@ -3025,7 +3071,7 @@ static int sci_probe_single(struct platform_device *dev,
 	if (IS_ERR(sciport->gpios) && PTR_ERR(sciport->gpios) != -ENOSYS)
 	if (IS_ERR(sciport->gpios) && PTR_ERR(sciport->gpios) != -ENOSYS)
 		return PTR_ERR(sciport->gpios);
 		return PTR_ERR(sciport->gpios);
 
 
-	if (p->capabilities & SCIx_HAVE_RTSCTS) {
+	if (sciport->has_rtscts) {
 		if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
 		if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
 							UART_GPIO_CTS)) ||
 							UART_GPIO_CTS)) ||
 		    !IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
 		    !IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
@@ -3081,6 +3127,24 @@ static int sci_probe(struct platform_device *dev)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
+	if (sp->port.fifosize > 1) {
+		ret = sysfs_create_file(&dev->dev.kobj,
+				&dev_attr_rx_fifo_trigger.attr);
+		if (ret)
+			return ret;
+	}
+	if (sp->port.type == PORT_SCIFA || sp->port.type ==  PORT_SCIFB) {
+		ret = sysfs_create_file(&dev->dev.kobj,
+				&dev_attr_rx_fifo_timeout.attr);
+		if (ret) {
+			if (sp->port.fifosize > 1) {
+				sysfs_remove_file(&dev->dev.kobj,
+					&dev_attr_rx_fifo_trigger.attr);
+			}
+			return ret;
+		}
+	}
+
 #ifdef CONFIG_SH_STANDARD_BIOS
 #ifdef CONFIG_SH_STANDARD_BIOS
 	sh_bios_gdb_detach();
 	sh_bios_gdb_detach();
 #endif
 #endif
@@ -3159,12 +3223,12 @@ static int __init early_console_setup(struct earlycon_device *device,
 	device->port.serial_out	= sci_serial_out;
 	device->port.serial_out	= sci_serial_out;
 	device->port.type = type;
 	device->port.type = type;
 	memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port));
 	memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port));
+	port_cfg.type = type;
 	sci_ports[0].cfg = &port_cfg;
 	sci_ports[0].cfg = &port_cfg;
-	sci_ports[0].cfg->type = type;
-	sci_probe_regmap(sci_ports[0].cfg);
-	port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR) |
-			 SCSCR_RE | SCSCR_TE;
-	sci_serial_out(&sci_ports[0].port, SCSCR, port_cfg.scscr);
+	sci_ports[0].params = sci_probe_regmap(&port_cfg);
+	port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR);
+	sci_serial_out(&sci_ports[0].port, SCSCR,
+		       SCSCR_RE | SCSCR_TE | port_cfg.scscr);
 
 
 	device->con->write = serial_console_write;
 	device->con->write = serial_console_write;
 	return 0;
 	return 0;

+ 9 - 3
drivers/tty/serial/sh-sci.h

@@ -29,6 +29,8 @@ enum {
 	SCPDR,				/* Serial Port Data Register */
 	SCPDR,				/* Serial Port Data Register */
 	SCDL,				/* BRG Frequency Division Register */
 	SCDL,				/* BRG Frequency Division Register */
 	SCCKS,				/* BRG Clock Select Register */
 	SCCKS,				/* BRG Clock Select Register */
+	HSRTRGR,			/* Rx FIFO Data Count Trigger Register */
+	HSTTRGR,			/* Tx FIFO Data Count Trigger Register */
 
 
 	SCIx_NR_REGS,
 	SCIx_NR_REGS,
 };
 };
@@ -99,6 +101,10 @@ enum {
 #define SCIF_BREAK_CLEAR	(u32)(~(SCIF_PER | SCIF_FER | SCIF_BRK))
 #define SCIF_BREAK_CLEAR	(u32)(~(SCIF_PER | SCIF_FER | SCIF_BRK))
 
 
 /* SCFCR (FIFO Control Register) */
 /* SCFCR (FIFO Control Register) */
+#define SCFCR_RTRG1	BIT(7)	/* Receive FIFO Data Count Trigger */
+#define SCFCR_RTRG0	BIT(6)
+#define SCFCR_TTRG1	BIT(5)	/* Transmit FIFO Data Count Trigger */
+#define SCFCR_TTRG0	BIT(4)
 #define SCFCR_MCE	BIT(3)	/* Modem Control Enable */
 #define SCFCR_MCE	BIT(3)	/* Modem Control Enable */
 #define SCFCR_TFRST	BIT(2)	/* Transmit FIFO Data Register Reset */
 #define SCFCR_TFRST	BIT(2)	/* Transmit FIFO Data Register Reset */
 #define SCFCR_RFRST	BIT(1)	/* Receive FIFO Data Register Reset */
 #define SCFCR_RFRST	BIT(1)	/* Receive FIFO Data Register Reset */
@@ -145,18 +151,18 @@ enum {
 #define SCCKS_XIN	BIT(14)	/* SC_CLK uses bus clock (1) or SCIF_CLK (0) */
 #define SCCKS_XIN	BIT(14)	/* SC_CLK uses bus clock (1) or SCIF_CLK (0) */
 
 
 #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_DR | 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)
 #define SCxSR_FER(port)		(((port)->type == PORT_SCI) ? SCI_FER    : SCIF_FER)
 #define SCxSR_FER(port)		(((port)->type == PORT_SCI) ? SCI_FER    : SCIF_FER)
 #define SCxSR_PER(port)		(((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
 #define SCxSR_PER(port)		(((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
 #define SCxSR_BRK(port)		(((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)
 #define SCxSR_BRK(port)		(((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)
 
 
-#define SCxSR_ERRORS(port)	(to_sci_port(port)->error_mask)
+#define SCxSR_ERRORS(port)	(to_sci_port(port)->params->error_mask)
 
 
 #define SCxSR_RDxF_CLEAR(port) \
 #define SCxSR_RDxF_CLEAR(port) \
 	(((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR)
 	(((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR)
 #define SCxSR_ERROR_CLEAR(port) \
 #define SCxSR_ERROR_CLEAR(port) \
-	(to_sci_port(port)->error_clear)
+	(to_sci_port(port)->params->error_clear)
 #define SCxSR_TDxE_CLEAR(port) \
 #define SCxSR_TDxE_CLEAR(port) \
 	(((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR)
 	(((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR)
 #define SCxSR_BREAK_CLEAR(port) \
 #define SCxSR_BREAK_CLEAR(port) \

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

@@ -1061,7 +1061,7 @@ static void sirfsoc_uart_config_port(struct uart_port *port, int flags)
 	}
 	}
 }
 }
 
 
-static struct uart_ops sirfsoc_uart_ops = {
+static const struct uart_ops sirfsoc_uart_ops = {
 	.tx_empty	= sirfsoc_uart_tx_empty,
 	.tx_empty	= sirfsoc_uart_tx_empty,
 	.get_mctrl	= sirfsoc_uart_get_mctrl,
 	.get_mctrl	= sirfsoc_uart_get_mctrl,
 	.set_mctrl	= sirfsoc_uart_set_mctrl,
 	.set_mctrl	= sirfsoc_uart_set_mctrl,

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

@@ -380,7 +380,7 @@ static void snp_config_port(struct uart_port *port, int flags)
 
 
 /* Associate the uart functions above - given to serial core */
 /* Associate the uart functions above - given to serial core */
 
 
-static struct uart_ops sn_console_ops = {
+static const struct uart_ops sn_console_ops = {
 	.tx_empty = snp_tx_empty,
 	.tx_empty = snp_tx_empty,
 	.set_mctrl = snp_set_mctrl,
 	.set_mctrl = snp_set_mctrl,
 	.get_mctrl = snp_get_mctrl,
 	.get_mctrl = snp_get_mctrl,

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

@@ -498,7 +498,7 @@ static int sprd_verify_port(struct uart_port *port,
 	return 0;
 	return 0;
 }
 }
 
 
-static struct uart_ops serial_sprd_ops = {
+static const struct uart_ops serial_sprd_ops = {
 	.tx_empty = sprd_tx_empty,
 	.tx_empty = sprd_tx_empty,
 	.get_mctrl = sprd_get_mctrl,
 	.get_mctrl = sprd_get_mctrl,
 	.set_mctrl = sprd_set_mctrl,
 	.set_mctrl = sprd_set_mctrl,

+ 92 - 9
drivers/tty/serial/st-asc.c

@@ -18,6 +18,7 @@
 #include <linux/serial.h>
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/sysrq.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
@@ -30,15 +31,23 @@
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
+#include <linux/gpio/consumer.h>
 
 
 #define DRIVER_NAME "st-asc"
 #define DRIVER_NAME "st-asc"
 #define ASC_SERIAL_NAME "ttyAS"
 #define ASC_SERIAL_NAME "ttyAS"
 #define ASC_FIFO_SIZE 16
 #define ASC_FIFO_SIZE 16
 #define ASC_MAX_PORTS 8
 #define ASC_MAX_PORTS 8
 
 
+/* Pinctrl states */
+#define DEFAULT		0
+#define NO_HW_FLOWCTRL	1
+
 struct asc_port {
 struct asc_port {
 	struct uart_port port;
 	struct uart_port port;
+	struct gpio_desc *rts;
 	struct clk *clk;
 	struct clk *clk;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *states[2];
 	unsigned int hw_flow_control:1;
 	unsigned int hw_flow_control:1;
 	unsigned int force_m1:1;
 	unsigned int force_m1:1;
 };
 };
@@ -287,9 +296,19 @@ static void asc_transmit_chars(struct uart_port *port)
 static void asc_receive_chars(struct uart_port *port)
 static void asc_receive_chars(struct uart_port *port)
 {
 {
 	struct tty_port *tport = &port->state->port;
 	struct tty_port *tport = &port->state->port;
-	unsigned long status;
+	unsigned long status, mode;
 	unsigned long c = 0;
 	unsigned long c = 0;
 	char flag;
 	char flag;
+	bool ignore_pe = false;
+
+	/*
+	 * Datasheet states: If the MODE field selects an 8-bit frame then
+	 * this [parity error] bit is undefined. Software should ignore this
+	 * bit when reading 8-bit frames.
+	 */
+	mode = asc_in(port, ASC_CTL) & ASC_CTL_MODE_MSK;
+	if (mode == ASC_CTL_MODE_8BIT || mode == ASC_CTL_MODE_8BIT_PAR)
+		ignore_pe = true;
 
 
 	if (port->irq_wake)
 	if (port->irq_wake)
 		pm_wakeup_event(tport->tty->dev, 0);
 		pm_wakeup_event(tport->tty->dev, 0);
@@ -299,8 +318,8 @@ static void asc_receive_chars(struct uart_port *port)
 		flag = TTY_NORMAL;
 		flag = TTY_NORMAL;
 		port->icount.rx++;
 		port->icount.rx++;
 
 
-		if ((c & (ASC_RXBUF_FE | ASC_RXBUF_PE)) ||
-			status & ASC_STA_OE) {
+		if (status & ASC_STA_OE || c & ASC_RXBUF_FE ||
+		    (c & ASC_RXBUF_PE && !ignore_pe)) {
 
 
 			if (c & ASC_RXBUF_FE) {
 			if (c & ASC_RXBUF_FE) {
 				if (c == (ASC_RXBUF_FE | ASC_RXBUF_DUMMY_RX)) {
 				if (c == (ASC_RXBUF_FE | ASC_RXBUF_DUMMY_RX)) {
@@ -381,12 +400,27 @@ static unsigned int asc_tx_empty(struct uart_port *port)
 
 
 static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 {
+	struct asc_port *ascport = to_asc_port(port);
+
 	/*
 	/*
-	 * This routine is used for seting signals of: DTR, DCD, CTS/RTS
-	 * We use ASC's hardware for CTS/RTS, so don't need any for that.
-	 * Some boards have DTR and DCD implemented using PIO pins,
-	 * code to do this should be hooked in here.
+	 * This routine is used for seting signals of: DTR, DCD, CTS and RTS.
+	 * We use ASC's hardware for CTS/RTS when hardware flow-control is
+	 * enabled, however if the RTS line is required for another purpose,
+	 * commonly controlled using HUP from userspace, then we need to toggle
+	 * it manually, using GPIO.
+	 *
+	 * Some boards also have DTR and DCD implemented using PIO pins, code to
+	 * do this should be hooked in here.
 	 */
 	 */
+
+	if (!ascport->rts)
+		return;
+
+	/* If HW flow-control is enabled, we can't fiddle with the RTS line */
+	if (asc_in(port, ASC_CTL) & ASC_CTL_CTSENABLE)
+		return;
+
+	gpiod_set_value(ascport->rts, mctrl & TIOCM_RTS);
 }
 }
 
 
 static unsigned int asc_get_mctrl(struct uart_port *port)
 static unsigned int asc_get_mctrl(struct uart_port *port)
@@ -479,6 +513,8 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 			    struct ktermios *old)
 {
 {
 	struct asc_port *ascport = to_asc_port(port);
 	struct asc_port *ascport = to_asc_port(port);
+	struct device_node *np = port->dev->of_node;
+	struct gpio_desc *gpiod;
 	unsigned int baud;
 	unsigned int baud;
 	u32 ctrl_val;
 	u32 ctrl_val;
 	tcflag_t cflag;
 	tcflag_t cflag;
@@ -522,9 +558,32 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
 		ctrl_val |= ASC_CTL_PARITYODD;
 		ctrl_val |= ASC_CTL_PARITYODD;
 
 
 	/* hardware flow control */
 	/* hardware flow control */
-	if ((cflag & CRTSCTS))
+	if ((cflag & CRTSCTS)) {
 		ctrl_val |= ASC_CTL_CTSENABLE;
 		ctrl_val |= ASC_CTL_CTSENABLE;
 
 
+		/* If flow-control selected, stop handling RTS manually */
+		if (ascport->rts) {
+			devm_gpiod_put(port->dev, ascport->rts);
+			ascport->rts = NULL;
+
+			pinctrl_select_state(ascport->pinctrl,
+					     ascport->states[DEFAULT]);
+		}
+	} else {
+		/* If flow-control disabled, it's safe to handle RTS manually */
+		if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) {
+			pinctrl_select_state(ascport->pinctrl,
+					     ascport->states[NO_HW_FLOWCTRL]);
+
+			gpiod =	devm_get_gpiod_from_child(port->dev, "rts",
+							  &np->fwnode);
+			if (!IS_ERR(gpiod)) {
+				gpiod_direction_output(gpiod, 0);
+				ascport->rts = gpiod;
+			}
+		}
+	}
+
 	if ((baud < 19200) && !ascport->force_m1) {
 	if ((baud < 19200) && !ascport->force_m1) {
 		asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud)));
 		asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud)));
 	} else {
 	} else {
@@ -667,6 +726,7 @@ static int asc_init_port(struct asc_port *ascport,
 {
 {
 	struct uart_port *port = &ascport->port;
 	struct uart_port *port = &ascport->port;
 	struct resource *res;
 	struct resource *res;
+	int ret;
 
 
 	port->iotype	= UPIO_MEM;
 	port->iotype	= UPIO_MEM;
 	port->flags	= UPF_BOOT_AUTOCONF;
 	port->flags	= UPF_BOOT_AUTOCONF;
@@ -693,6 +753,27 @@ static int asc_init_port(struct asc_port *ascport,
 	WARN_ON(ascport->port.uartclk == 0);
 	WARN_ON(ascport->port.uartclk == 0);
 	clk_disable_unprepare(ascport->clk);
 	clk_disable_unprepare(ascport->clk);
 
 
+	ascport->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(ascport->pinctrl)) {
+		ret = PTR_ERR(ascport->pinctrl);
+		dev_err(&pdev->dev, "Failed to get Pinctrl: %d\n", ret);
+	}
+
+	ascport->states[DEFAULT] =
+		pinctrl_lookup_state(ascport->pinctrl, "default");
+	if (IS_ERR(ascport->states[DEFAULT])) {
+		ret = PTR_ERR(ascport->states[DEFAULT]);
+		dev_err(&pdev->dev,
+			"Failed to look up Pinctrl state 'default': %d\n", ret);
+		return ret;
+	}
+
+	/* "no-hw-flowctrl" state is optional */
+	ascport->states[NO_HW_FLOWCTRL] =
+		pinctrl_lookup_state(ascport->pinctrl, "no-hw-flowctrl");
+	if (IS_ERR(ascport->states[NO_HW_FLOWCTRL]))
+		ascport->states[NO_HW_FLOWCTRL] = NULL;
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -713,9 +794,11 @@ static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
 		return NULL;
 		return NULL;
 
 
 	asc_ports[id].hw_flow_control = of_property_read_bool(np,
 	asc_ports[id].hw_flow_control = of_property_read_bool(np,
-							"st,hw-flow-control");
+							"uart-has-rtscts");
 	asc_ports[id].force_m1 =  of_property_read_bool(np, "st,force_m1");
 	asc_ports[id].force_m1 =  of_property_read_bool(np, "st,force_m1");
 	asc_ports[id].port.line = id;
 	asc_ports[id].port.line = id;
+	asc_ports[id].rts = NULL;
+
 	return &asc_ports[id];
 	return &asc_ports[id];
 }
 }
 
 

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

@@ -370,7 +370,7 @@ static int sunhv_verify_port(struct uart_port *port, struct serial_struct *ser)
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
-static struct uart_ops sunhv_pops = {
+static const struct uart_ops sunhv_pops = {
 	.tx_empty	= sunhv_tx_empty,
 	.tx_empty	= sunhv_tx_empty,
 	.set_mctrl	= sunhv_set_mctrl,
 	.set_mctrl	= sunhv_set_mctrl,
 	.get_mctrl	= sunhv_get_mctrl,
 	.get_mctrl	= sunhv_get_mctrl,

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

@@ -1046,7 +1046,7 @@ static void sunzilog_put_poll_char(struct uart_port *port,
 }
 }
 #endif /* CONFIG_CONSOLE_POLL */
 #endif /* CONFIG_CONSOLE_POLL */
 
 
-static struct uart_ops sunzilog_pops = {
+static const struct uart_ops sunzilog_pops = {
 	.tx_empty	=	sunzilog_tx_empty,
 	.tx_empty	=	sunzilog_tx_empty,
 	.set_mctrl	=	sunzilog_set_mctrl,
 	.set_mctrl	=	sunzilog_set_mctrl,
 	.get_mctrl	=	sunzilog_get_mctrl,
 	.get_mctrl	=	sunzilog_get_mctrl,

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

@@ -681,7 +681,7 @@ static int siu_verify_port(struct uart_port *port, struct serial_struct *serial)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct uart_ops siu_uart_ops = {
+static const struct uart_ops siu_uart_ops = {
 	.tx_empty	= siu_tx_empty,
 	.tx_empty	= siu_tx_empty,
 	.set_mctrl	= siu_set_mctrl,
 	.set_mctrl	= siu_set_mctrl,
 	.get_mctrl	= siu_get_mctrl,
 	.get_mctrl	= siu_get_mctrl,

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

@@ -592,7 +592,7 @@ static void vt8500_put_poll_char(struct uart_port *port, unsigned char c)
 }
 }
 #endif
 #endif
 
 
-static struct uart_ops vt8500_uart_pops = {
+static const struct uart_ops vt8500_uart_pops = {
 	.tx_empty	= vt8500_tx_empty,
 	.tx_empty	= vt8500_tx_empty,
 	.set_mctrl	= vt8500_set_mctrl,
 	.set_mctrl	= vt8500_set_mctrl,
 	.get_mctrl	= vt8500_get_mctrl,
 	.get_mctrl	= vt8500_get_mctrl,

Some files were not shown because too many files changed in this diff