Browse Source

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

Pull tty / serial driver update from Greg KH:
 "Here's the big tty / serial driver update for 3.17-rc1.

  Nothing major, just a number of fixes and new features for different
  serial drivers, and some more tty core fixes and documentation of the
  tty locks.

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

* tag 'tty-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (82 commits)
  tty/n_gsm.c: fix a memory leak in gsmld_open
  pch_uart: don't hardcode PCI slot to get DMA device
  tty: n_gsm, use setup_timer
  Revert "ARC: [arcfpga] stdout-path now suffices for earlycon/console"
  serial: sc16is7xx: Correct initialization of s->clk
  serial: 8250_dw: Add support for deferred probing
  serial: 8250_dw: Add optional reset control support
  serial: st-asc: Fix overflow in baudrate calculation
  serial: st-asc: Don't call BUG in asc_console_setup()
  tty: serial: msm: Make of_device_id array const
  tty/n_gsm.c: get gsm->num after gsm_activate_mux
  serial/core: Fix too big allocation for attribute member
  drivers/tty/serial: use correct type for dma_map/unmap
  serial: altera_jtaguart: Fix putchar function passed to uart_console_write()
  serial/uart/8250: Add tunable RX interrupt trigger I/F of FIFO buffers
  Serial: allow port drivers to have a default attribute group
  tty: kgdb_nmi: Automatically manage tty enable
  serial: altera_jtaguart: Adpot uart_console_write()
  serial: samsung: improve code clarity by defining a variable
  serial: samsung: correct the case and default order in switch
  ...
Linus Torvalds 11 years ago
parent
commit
79eb238c76
93 changed files with 1583 additions and 1048 deletions
  1. 16 0
      Documentation/ABI/testing/sysfs-tty
  2. 2 2
      Documentation/devicetree/bindings/serial/efm32-uart.txt
  3. 5 1
      Documentation/devicetree/bindings/serial/fsl-lpuart.txt
  4. 50 6
      Documentation/devicetree/bindings/serial/samsung_uart.txt
  5. 32 0
      Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
  6. 1 1
      arch/arc/boot/dts/angel4.dts
  7. 0 7
      arch/arc/plat-arcfpga/Kconfig
  8. 2 95
      arch/arc/plat-arcfpga/platform.c
  9. 2 0
      arch/arm/boot/dts/exynos3250.dtsi
  10. 8 4
      arch/arm/boot/dts/exynos4.dtsi
  11. 11 4
      arch/arm/boot/dts/exynos5.dtsi
  12. 4 0
      arch/arm/boot/dts/exynos5260.dtsi
  13. 6 0
      arch/arm/boot/dts/exynos5410.dtsi
  14. 4 2
      arch/arm/boot/dts/exynos5440.dtsi
  15. 5 1
      arch/arm/boot/dts/s3c2416.dtsi
  16. 6 3
      arch/arm/boot/dts/s3c24xx.dtsi
  17. 4 0
      arch/arm/boot/dts/s3c64xx.dtsi
  18. 1 3
      drivers/char/pcmcia/synclink_cs.c
  19. 1 1
      drivers/tty/cyclades.c
  20. 0 5
      drivers/tty/ipwireless/tty.c
  21. 11 6
      drivers/tty/n_gsm.c
  22. 10 11
      drivers/tty/pty.c
  23. 0 5
      drivers/tty/serial/21285.c
  24. 2 0
      drivers/tty/serial/8250/8250.h
  25. 177 53
      drivers/tty/serial/8250/8250_core.c
  26. 103 87
      drivers/tty/serial/8250/8250_dw.c
  27. 1 2
      drivers/tty/serial/8250/8250_fsl.c
  28. 2 4
      drivers/tty/serial/8250/8250_pci.c
  29. 2 2
      drivers/tty/serial/Kconfig
  30. 5 14
      drivers/tty/serial/altera_jtaguart.c
  31. 2 11
      drivers/tty/serial/altera_uart.c
  32. 16 32
      drivers/tty/serial/amba-pl010.c
  33. 10 20
      drivers/tty/serial/amba-pl011.c
  34. 0 6
      drivers/tty/serial/apbuart.c
  35. 0 5
      drivers/tty/serial/ar933x_uart.c
  36. 121 216
      drivers/tty/serial/arc_uart.c
  37. 4 4
      drivers/tty/serial/atmel_serial.c
  38. 8 9
      drivers/tty/serial/bfin_sport_uart.c
  39. 8 14
      drivers/tty/serial/bfin_uart.c
  40. 0 1
      drivers/tty/serial/clps711x.c
  41. 0 9
      drivers/tty/serial/cpm_uart/cpm_uart_core.c
  42. 5 10
      drivers/tty/serial/crisv10.c
  43. 0 6
      drivers/tty/serial/dz.c
  44. 7 7
      drivers/tty/serial/efm32-uart.c
  45. 658 31
      drivers/tty/serial/fsl_lpuart.c
  46. 0 6
      drivers/tty/serial/icom.c
  47. 0 1
      drivers/tty/serial/ioc3_serial.c
  48. 0 1
      drivers/tty/serial/ioc4_serial.c
  49. 0 6
      drivers/tty/serial/jsm/jsm_tty.c
  50. 15 21
      drivers/tty/serial/kgdb_nmi.c
  51. 1 7
      drivers/tty/serial/lantiq.c
  52. 0 7
      drivers/tty/serial/lpc32xx_hs.c
  53. 0 1
      drivers/tty/serial/max310x.c
  54. 2 9
      drivers/tty/serial/mcf.c
  55. 3 3
      drivers/tty/serial/men_z135_uart.c
  56. 0 5
      drivers/tty/serial/mpsc.c
  57. 0 5
      drivers/tty/serial/mrst_max3110.c
  58. 20 12
      drivers/tty/serial/msm_serial.c
  59. 2 2
      drivers/tty/serial/msm_serial.h
  60. 0 11
      drivers/tty/serial/mux.c
  61. 0 6
      drivers/tty/serial/mxs-auart.c
  62. 0 6
      drivers/tty/serial/nwpserial.c
  63. 5 4
      drivers/tty/serial/pch_uart.c
  64. 1 1
      drivers/tty/serial/pxa.c
  65. 24 20
      drivers/tty/serial/samsung.c
  66. 4 6
      drivers/tty/serial/sc16is7xx.c
  67. 0 6
      drivers/tty/serial/sccnxp.c
  68. 4 0
      drivers/tty/serial/serial-tegra.c
  69. 35 24
      drivers/tty/serial/serial_core.c
  70. 0 7
      drivers/tty/serial/serial_txx9.c
  71. 64 30
      drivers/tty/serial/sh-sci.c
  72. 2 1
      drivers/tty/serial/sirfsoc_uart.c
  73. 1 1
      drivers/tty/serial/sirfsoc_uart.h
  74. 0 10
      drivers/tty/serial/sn_console.c
  75. 7 13
      drivers/tty/serial/st-asc.c
  76. 0 6
      drivers/tty/serial/sunhv.c
  77. 0 7
      drivers/tty/serial/sunsab.c
  78. 0 10
      drivers/tty/serial/tilegx.c
  79. 0 6
      drivers/tty/serial/timbuart.c
  80. 0 6
      drivers/tty/serial/uartlite.c
  81. 0 11
      drivers/tty/serial/ucc_uart.c
  82. 0 6
      drivers/tty/serial/xilinx_uartps.c
  83. 3 7
      drivers/tty/synclink.c
  84. 3 7
      drivers/tty/synclink_gt.c
  85. 3 8
      drivers/tty/synclinkmp.c
  86. 14 25
      drivers/tty/tty_io.c
  87. 36 7
      drivers/tty/tty_port.c
  88. 7 0
      include/linux/serial_8250.h
  89. 2 0
      include/linux/serial_core.h
  90. 1 3
      include/linux/tty.h
  91. 5 3
      include/linux/tty_driver.h
  92. 5 0
      include/uapi/linux/serial_reg.h
  93. 2 4
      net/irda/ircomm/ircomm_tty.c

+ 16 - 0
Documentation/ABI/testing/sysfs-tty

@@ -138,3 +138,19 @@ Description:
 
 
 		 These sysfs values expose the TIOCGSERIAL interface via
 		 These sysfs values expose the TIOCGSERIAL interface via
 		 sysfs rather than via ioctls.
 		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/rx_trig_bytes
+Date:		May 2014
+Contact:	Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
+Description:
+		 Shows current RX interrupt trigger bytes or sets the
+		 user specified value to change it for the FIFO buffer.
+		 Users can show or set this value regardless of opening the
+		 serial device file or not.
+
+		 The RX trigger can be set one of four kinds of values for UART
+		 serials. When users input a meaning less value to this I/F,
+		 the RX trigger is changed to the nearest lower value for the
+		 device specification. For example, when user sets 7bytes on
+		 16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
+		 automatically changed to 4 bytes.

+ 2 - 2
Documentation/devicetree/bindings/serial/efm32-uart.txt

@@ -6,7 +6,7 @@ Required properties:
 - interrupts : Should contain uart interrupt
 - interrupts : Should contain uart interrupt
 
 
 Optional properties:
 Optional properties:
-- efm32,location : Decides the location of the USART I/O pins.
+- energymicro,location : Decides the location of the USART I/O pins.
   Allowed range : [0 .. 5]
   Allowed range : [0 .. 5]
   Default: 0
   Default: 0
 
 
@@ -16,5 +16,5 @@ uart@0x4000c400 {
 	compatible = "energymicro,efm32-uart";
 	compatible = "energymicro,efm32-uart";
 	reg = <0x4000c400 0x400>;
 	reg = <0x4000c400 0x400>;
 	interrupts = <15>;
 	interrupts = <15>;
-	efm32,location = <0>;
+	energymicro,location = <0>;
 };
 };

+ 5 - 1
Documentation/devicetree/bindings/serial/fsl-lpuart.txt

@@ -1,7 +1,11 @@
 * Freescale low power universal asynchronous receiver/transmitter (lpuart)
 * Freescale low power universal asynchronous receiver/transmitter (lpuart)
 
 
 Required properties:
 Required properties:
-- compatible : Should be "fsl,<soc>-lpuart"
+- compatible :
+  - "fsl,vf610-lpuart" for lpuart compatible with the one integrated
+    on Vybrid vf610 SoC with 8-bit register organization
+  - "fsl,ls1021a-lpuart" for lpuart compatible with the one integrated
+    on LS1021A SoC with 32-bit big-endian register organization
 - reg : Address and length of the register set for the device
 - reg : Address and length of the register set for the device
 - interrupts : Should contain uart interrupt
 - interrupts : Should contain uart interrupt
 - clocks : phandle + clock specifier pairs, one for each entry in clock-names
 - clocks : phandle + clock specifier pairs, one for each entry in clock-names

+ 50 - 6
Documentation/devicetree/bindings/serial/samsung_uart.txt

@@ -1,14 +1,58 @@
 * Samsung's UART Controller
 * Samsung's UART Controller
 
 
-The Samsung's UART controller is used for interfacing SoC with serial communicaion
-devices.
+The Samsung's UART controller is used for interfacing SoC with serial
+communicaion devices.
 
 
 Required properties:
 Required properties:
-- compatible: should be
-  - "samsung,exynos4210-uart", for UART's compatible with Exynos4210 uart ports.
+- compatible: should be one of following:
+  - "samsung,exynos4210-uart" -  Exynos4210 SoC,
+  - "samsung,s3c2410-uart" - compatible with ports present on S3C2410 SoC,
+  - "samsung,s3c2412-uart" - compatible with ports present on S3C2412 SoC,
+  - "samsung,s3c2440-uart" - compatible with ports present on S3C2440 SoC,
+  - "samsung,s3c6400-uart" - compatible with ports present on S3C6400 SoC,
+  - "samsung,s5pv210-uart" - compatible with ports present on S5PV210 SoC.
 
 
 - reg: base physical address of the controller and length of memory mapped
 - reg: base physical address of the controller and length of memory mapped
   region.
   region.
 
 
-- interrupts: interrupt number to the cpu. The interrupt specifier format depends
-  on the interrupt controller parent.
+- interrupts: a single interrupt signal to SoC interrupt controller,
+  according to interrupt bindings documentation [1].
+
+- clock-names: input names of clocks used by the controller:
+  - "uart" - controller bus clock,
+  - "clk_uart_baudN" - Nth baud base clock input (N = 0, 1, ...),
+    according to SoC User's Manual (only N = 0 is allowedfor SoCs without
+    internal baud clock mux).
+- clocks: phandles and specifiers for all clocks specified in "clock-names"
+  property, in the same order, according to clock bindings documentation [2].
+
+[1] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Optional properties:
+- samsung,uart-fifosize: The fifo size supported by the UART channel
+
+Note: Each Samsung UART should have an alias correctly numbered in the
+"aliases" node, according to serialN format, where N is the port number
+(non-negative decimal integer) as specified by User's Manual of respective
+SoC.
+
+Example:
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+Example:
+	uart1: serial@7f005400 {
+		compatible = "samsung,s3c6400-uart";
+		reg = <0x7f005400 0x100>;
+		interrupt-parent = <&vic1>;
+		interrupts = <6>;
+		clock-names = "uart", "clk_uart_baud2",
+				"clk_uart_baud3";
+		clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
+				<&clocks SCLK_UART>;
+		samsung,uart-fifosize = <16>;
+	};

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

@@ -4,9 +4,18 @@ Required properties:
 - compatible : "snps,dw-apb-uart"
 - compatible : "snps,dw-apb-uart"
 - reg : offset and length of the register set for the device.
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
 - interrupts : should contain uart interrupt.
+
+Clock handling:
+The clock rate of the input clock needs to be supplied by one of
 - clock-frequency : the input clock frequency for the UART.
 - clock-frequency : the input clock frequency for the UART.
+- clocks : phandle to the input clock
+
+The supplying peripheral clock can also be handled, needing a second property
+- clock-names: tuple listing input clock names.
+	Required elements: "baudclk", "apb_pclk"
 
 
 Optional properties:
 Optional properties:
+- resets : phandle to the parent reset controller.
 - reg-shift : quantity to shift the register offsets by.  If this property is
 - reg-shift : quantity to shift the register offsets by.  If this property is
   not present then the register offsets are not shifted.
   not present then the register offsets are not shifted.
 - reg-io-width : the size (in bytes) of the IO accesses that should be
 - reg-io-width : the size (in bytes) of the IO accesses that should be
@@ -23,3 +32,26 @@ Example:
 		reg-shift = <2>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
 		reg-io-width = <4>;
 	};
 	};
+
+Example with one clock:
+
+	uart@80230000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x80230000 0x100>;
+		clocks = <&baudclk>;
+		interrupts = <10>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+Example with two clocks:
+
+	uart@80230000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x80230000 0x100>;
+		clocks = <&baudclk>, <&apb_pclk>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <10>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};

+ 1 - 1
arch/arc/boot/dts/angel4.dts

@@ -17,7 +17,7 @@
 	interrupt-parent = <&intc>;
 	interrupt-parent = <&intc>;
 
 
 	chosen {
 	chosen {
-		bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0";
+		bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
 	};
 	};
 
 
 	aliases {
 	aliases {

+ 0 - 7
arch/arc/plat-arcfpga/Kconfig

@@ -41,11 +41,4 @@ config ISS_SMP_EXTN
 	  -XTL (To enable CPU start/stop/set-PC for another CPU)
 	  -XTL (To enable CPU start/stop/set-PC for another CPU)
 	  It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
 	  It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
 
 
-config ARC_SERIAL_BAUD
-	int "UART Baud rate"
-	default "115200"
-	depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
-	help
-	  Baud rate for the ARC UART
-
 endif
 endif

+ 2 - 95
arch/arc/plat-arcfpga/platform.c

@@ -22,115 +22,22 @@
 #include <plat/smp.h>
 #include <plat/smp.h>
 #include <plat/irq.h>
 #include <plat/irq.h>
 
 
-/*----------------------- Platform Devices -----------------------------*/
-
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
-static unsigned long arc_uart_info[] = {
-	0,	/* uart->is_emulated (runtime @running_on_hw) */
-	0,	/* uart->port.uartclk */
-	0,	/* uart->baud */
-	0
-};
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
-/*
- * static platform data - but only for early serial
- * TBD: derive this from a special DT node
- */
-static struct resource arc_uart0_res[] = {
-	{
-		.start = UART0_BASE,
-		.end   = UART0_BASE + 0xFF,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = UART0_IRQ,
-		.end   = UART0_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device arc_uart0_dev = {
-	.name = "arc-uart",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(arc_uart0_res),
-	.resource = arc_uart0_res,
-	.dev = {
-		.platform_data = &arc_uart_info,
-	},
-};
-
-static struct platform_device *fpga_early_devs[] __initdata = {
-	&arc_uart0_dev,
-};
-#endif	/* CONFIG_SERIAL_ARC_CONSOLE */
-
-static void arc_fpga_serial_init(void)
-{
-	/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
-	arc_uart_info[0] = !running_on_hw;
-
-	arc_uart_info[1] = arc_get_core_freq();
-
-	arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
-	early_platform_add_devices(fpga_early_devs,
-				   ARRAY_SIZE(fpga_early_devs));
-
-	/*
-	 * ARC console driver registers (build time) as an early platform driver
-	 * of class "earlyprintk". However it needs explicit cmdline toggle
-	 * "earlyprintk=ttyARC0" to be successfuly runtime registered.
-	 * Otherwise the early probe below fails to find the driver
-	 */
-	early_platform_driver_probe("earlyprintk", 1, 0);
-
-	/*
-	 * This is to make sure that arc uart would be preferred console
-	 * despite one/more of following:
-	 *   -command line lacked "console=ttyARC0" or
-	 *   -CONFIG_VT_CONSOLE was enabled (for no reason whatsoever)
-	 * Note that this needs to be done after above early console is reg,
-	 * otherwise the early console never gets a chance to run.
-	 */
-	add_preferred_console("ttyARC", 0, "115200");
-#endif	/* CONFIG_SERIAL_ARC_CONSOLE */
-}
-#else	/* !IS_ENABLED(CONFIG_SERIAL_ARC) */
-static void arc_fpga_serial_init(void)
-{
-}
-#endif
-
 static void __init plat_fpga_early_init(void)
 static void __init plat_fpga_early_init(void)
 {
 {
 	pr_info("[plat-arcfpga]: registering early dev resources\n");
 	pr_info("[plat-arcfpga]: registering early dev resources\n");
 
 
-	arc_fpga_serial_init();
-
 #ifdef CONFIG_ISS_SMP_EXTN
 #ifdef CONFIG_ISS_SMP_EXTN
 	iss_model_init_early_smp();
 	iss_model_init_early_smp();
 #endif
 #endif
 }
 }
 
 
-static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
-	OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
-#endif
-	{}
-};
-
 static void __init plat_fpga_populate_dev(void)
 static void __init plat_fpga_populate_dev(void)
 {
 {
-	pr_info("[plat-arcfpga]: registering device resources\n");
-
 	/*
 	/*
 	 * Traverses flattened DeviceTree - registering platform devices
 	 * Traverses flattened DeviceTree - registering platform devices
-	 * complete with their resources
+	 * (if any) complete with their resources
 	 */
 	 */
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     plat_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 }
 
 
 /*----------------------- Machine Descriptions ------------------------------
 /*----------------------- Machine Descriptions ------------------------------

+ 2 - 0
arch/arm/boot/dts/exynos3250.dtsi

@@ -39,6 +39,8 @@
 		i2c5 = &i2c_5;
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
 		i2c6 = &i2c_6;
 		i2c7 = &i2c_7;
 		i2c7 = &i2c_7;
+		serial0 = &serial_0;
+		serial1 = &serial_1;
 	};
 	};
 
 
 	cpus {
 	cpus {

+ 8 - 4
arch/arm/boot/dts/exynos4.dtsi

@@ -44,6 +44,10 @@
 		fimc1 = &fimc_1;
 		fimc1 = &fimc_1;
 		fimc2 = &fimc_2;
 		fimc2 = &fimc_2;
 		fimc3 = &fimc_3;
 		fimc3 = &fimc_3;
+		serial0 = &serial_0;
+		serial1 = &serial_1;
+		serial2 = &serial_2;
+		serial3 = &serial_3;
 	};
 	};
 
 
 	clock_audss: clock-controller@03810000 {
 	clock_audss: clock-controller@03810000 {
@@ -363,7 +367,7 @@
 		status = "disabled";
 		status = "disabled";
 	};
 	};
 
 
-	serial@13800000 {
+	serial_0: serial@13800000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13800000 0x100>;
 		reg = <0x13800000 0x100>;
 		interrupts = <0 52 0>;
 		interrupts = <0 52 0>;
@@ -372,7 +376,7 @@
 		status = "disabled";
 		status = "disabled";
 	};
 	};
 
 
-	serial@13810000 {
+	serial_1: serial@13810000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13810000 0x100>;
 		reg = <0x13810000 0x100>;
 		interrupts = <0 53 0>;
 		interrupts = <0 53 0>;
@@ -381,7 +385,7 @@
 		status = "disabled";
 		status = "disabled";
 	};
 	};
 
 
-	serial@13820000 {
+	serial_2: serial@13820000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13820000 0x100>;
 		reg = <0x13820000 0x100>;
 		interrupts = <0 54 0>;
 		interrupts = <0 54 0>;
@@ -390,7 +394,7 @@
 		status = "disabled";
 		status = "disabled";
 	};
 	};
 
 
-	serial@13830000 {
+	serial_3: serial@13830000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13830000 0x100>;
 		reg = <0x13830000 0x100>;
 		interrupts = <0 55 0>;
 		interrupts = <0 55 0>;

+ 11 - 4
arch/arm/boot/dts/exynos5.dtsi

@@ -18,6 +18,13 @@
 / {
 / {
 	interrupt-parent = <&gic>;
 	interrupt-parent = <&gic>;
 
 
+	aliases {
+		serial0 = &serial_0;
+		serial1 = &serial_1;
+		serial2 = &serial_2;
+		serial3 = &serial_3;
+	};
+
 	chipid@10000000 {
 	chipid@10000000 {
 		compatible = "samsung,exynos4210-chipid";
 		compatible = "samsung,exynos4210-chipid";
 		reg = <0x10000000 0x100>;
 		reg = <0x10000000 0x100>;
@@ -50,25 +57,25 @@
 		interrupts = <1 9 0xf04>;
 		interrupts = <1 9 0xf04>;
 	};
 	};
 
 
-	serial@12C00000 {
+	serial_0: serial@12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
 		reg = <0x12C00000 0x100>;
 		interrupts = <0 51 0>;
 		interrupts = <0 51 0>;
 	};
 	};
 
 
-	serial@12C10000 {
+	serial_1: serial@12C10000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C10000 0x100>;
 		reg = <0x12C10000 0x100>;
 		interrupts = <0 52 0>;
 		interrupts = <0 52 0>;
 	};
 	};
 
 
-	serial@12C20000 {
+	serial_2: serial@12C20000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C20000 0x100>;
 		reg = <0x12C20000 0x100>;
 		interrupts = <0 53 0>;
 		interrupts = <0 53 0>;
 	};
 	};
 
 
-	serial@12C30000 {
+	serial_3: serial@12C30000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C30000 0x100>;
 		reg = <0x12C30000 0x100>;
 		interrupts = <0 54 0>;
 		interrupts = <0 54 0>;

+ 4 - 0
arch/arm/boot/dts/exynos5260.dtsi

@@ -21,6 +21,10 @@
 		pinctrl0 = &pinctrl_0;
 		pinctrl0 = &pinctrl_0;
 		pinctrl1 = &pinctrl_1;
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
 		pinctrl2 = &pinctrl_2;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
 	};
 	};
 
 
 	cpus {
 	cpus {

+ 6 - 0
arch/arm/boot/dts/exynos5410.dtsi

@@ -20,6 +20,12 @@
 	compatible = "samsung,exynos5410", "samsung,exynos5";
 	compatible = "samsung,exynos5410", "samsung,exynos5";
 	interrupt-parent = <&gic>;
 	interrupt-parent = <&gic>;
 
 
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
 	cpus {
 	cpus {
 		#address-cells = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		#size-cells = <0>;

+ 4 - 2
arch/arm/boot/dts/exynos5440.dtsi

@@ -18,6 +18,8 @@
 	interrupt-parent = <&gic>;
 	interrupt-parent = <&gic>;
 
 
 	aliases {
 	aliases {
+		serial0 = &serial_0;
+		serial1 = &serial_1;
 		spi0 = &spi_0;
 		spi0 = &spi_0;
 		tmuctrl0 = &tmuctrl_0;
 		tmuctrl0 = &tmuctrl_0;
 		tmuctrl1 = &tmuctrl_1;
 		tmuctrl1 = &tmuctrl_1;
@@ -102,7 +104,7 @@
 		>;
 		>;
 	};
 	};
 
 
-	serial@B0000 {
+	serial_0: serial@B0000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xB0000 0x1000>;
 		reg = <0xB0000 0x1000>;
 		interrupts = <0 2 0>;
 		interrupts = <0 2 0>;
@@ -110,7 +112,7 @@
 		clock-names = "uart", "clk_uart_baud0";
 		clock-names = "uart", "clk_uart_baud0";
 	};
 	};
 
 
-	serial@C0000 {
+	serial_1: serial@C0000 {
 		compatible = "samsung,exynos4210-uart";
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xC0000 0x1000>;
 		reg = <0xC0000 0x1000>;
 		interrupts = <0 3 0>;
 		interrupts = <0 3 0>;

+ 5 - 1
arch/arm/boot/dts/s3c2416.dtsi

@@ -16,6 +16,10 @@
 	model = "Samsung S3C2416 SoC";
 	model = "Samsung S3C2416 SoC";
 	compatible = "samsung,s3c2416";
 	compatible = "samsung,s3c2416";
 
 
+	aliases {
+		serial3 = &uart3;
+	};
+
 	cpus {
 	cpus {
 		#address-cells = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		#size-cells = <0>;
@@ -68,7 +72,7 @@
 				<&clocks SCLK_UART>;
 				<&clocks SCLK_UART>;
 	};
 	};
 
 
-	serial@5000C000 {
+	uart3: serial@5000C000 {
 		compatible = "samsung,s3c2440-uart";
 		compatible = "samsung,s3c2440-uart";
 		reg = <0x5000C000 0x4000>;
 		reg = <0x5000C000 0x4000>;
 		interrupts = <1 18 24 4>, <1 18 25 4>;
 		interrupts = <1 18 24 4>, <1 18 25 4>;

+ 6 - 3
arch/arm/boot/dts/s3c24xx.dtsi

@@ -16,6 +16,9 @@
 
 
 	aliases {
 	aliases {
 		pinctrl0 = &pinctrl_0;
 		pinctrl0 = &pinctrl_0;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
 	};
 	};
 
 
 	intc:interrupt-controller@4a000000 {
 	intc:interrupt-controller@4a000000 {
@@ -46,21 +49,21 @@
 		#pwm-cells = <4>;
 		#pwm-cells = <4>;
 	};
 	};
 
 
-	serial@50000000 {
+	uart0: serial@50000000 {
 		compatible = "samsung,s3c2410-uart";
 		compatible = "samsung,s3c2410-uart";
 		reg = <0x50000000 0x4000>;
 		reg = <0x50000000 0x4000>;
 		interrupts = <1 28 0 4>, <1 28 1 4>;
 		interrupts = <1 28 0 4>, <1 28 1 4>;
 		status = "disabled";
 		status = "disabled";
 	};
 	};
 
 
-	serial@50004000 {
+	uart1: serial@50004000 {
 		compatible = "samsung,s3c2410-uart";
 		compatible = "samsung,s3c2410-uart";
 		reg = <0x50004000 0x4000>;
 		reg = <0x50004000 0x4000>;
 		interrupts = <1 23 3 4>, <1 23 4 4>;
 		interrupts = <1 23 3 4>, <1 23 4 4>;
 		status = "disabled";
 		status = "disabled";
 	};
 	};
 
 
-	serial@50008000 {
+	uart2: serial@50008000 {
 		compatible = "samsung,s3c2410-uart";
 		compatible = "samsung,s3c2410-uart";
 		reg = <0x50008000 0x4000>;
 		reg = <0x50008000 0x4000>;
 		interrupts = <1 15 6 4>, <1 15 7 4>;
 		interrupts = <1 15 6 4>, <1 15 7 4>;

+ 4 - 0
arch/arm/boot/dts/s3c64xx.dtsi

@@ -23,6 +23,10 @@
 	aliases {
 	aliases {
 		i2c0 = &i2c0;
 		i2c0 = &i2c0;
 		pinctrl0 = &pinctrl0;
 		pinctrl0 = &pinctrl0;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
 	};
 	};
 
 
 	cpus {
 	cpus {

+ 1 - 3
drivers/char/pcmcia/synclink_cs.c

@@ -2347,8 +2347,6 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
 		printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
 		printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
 			 __FILE__, __LINE__, info->device_name, port->count);
 			 __FILE__, __LINE__, info->device_name, port->count);
 
 
-	WARN_ON(!port->count);
-
 	if (tty_port_close_start(port, tty, filp) == 0)
 	if (tty_port_close_start(port, tty, filp) == 0)
 		goto cleanup;
 		goto cleanup;
 
 
@@ -2510,7 +2508,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
 			 __FILE__, __LINE__, tty->driver->name, port->count);
 			 __FILE__, __LINE__, tty->driver->name, port->count);
 
 
 	/* If port is closing, signal caller to try again */
 	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
+	if (port->flags & ASYNC_CLOSING){
 		wait_event_interruptible_tty(tty, port->close_wait,
 		wait_event_interruptible_tty(tty, port->close_wait,
 					     !(port->flags & ASYNC_CLOSING));
 					     !(port->flags & ASYNC_CLOSING));
 		retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
 		retval = ((port->flags & ASYNC_HUP_NOTIFY) ?

+ 1 - 1
drivers/tty/cyclades.c

@@ -1579,7 +1579,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
 	/*
 	/*
 	 * If the port is the middle of closing, bail out now
 	 * If the port is the middle of closing, bail out now
 	 */
 	 */
-	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
+	if (info->port.flags & ASYNC_CLOSING) {
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 				!(info->port.flags & ASYNC_CLOSING));
 				!(info->port.flags & ASYNC_CLOSING));
 		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
 		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;

+ 0 - 5
drivers/tty/ipwireless/tty.c

@@ -93,11 +93,6 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	mutex_lock(&tty->ipw_tty_mutex);
 	mutex_lock(&tty->ipw_tty_mutex);
-
-	if (tty->closing) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return -ENODEV;
-	}
 	if (tty->port.count == 0)
 	if (tty->port.count == 0)
 		tty->tx_bytes_queued = 0;
 		tty->tx_bytes_queued = 0;
 
 

+ 11 - 6
drivers/tty/n_gsm.c

@@ -2088,9 +2088,7 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
 	struct gsm_dlci *dlci;
 	struct gsm_dlci *dlci;
 	int i = 0;
 	int i = 0;
 
 
-	init_timer(&gsm->t2_timer);
-	gsm->t2_timer.function = gsm_control_retransmit;
-	gsm->t2_timer.data = (unsigned long)gsm;
+	setup_timer(&gsm->t2_timer, gsm_control_retransmit, (unsigned long)gsm);
 	init_waitqueue_head(&gsm->event);
 	init_waitqueue_head(&gsm->event);
 	spin_lock_init(&gsm->control_lock);
 	spin_lock_init(&gsm->control_lock);
 	spin_lock_init(&gsm->tx_lock);
 	spin_lock_init(&gsm->tx_lock);
@@ -2230,8 +2228,7 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
 
 
 static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 {
 {
-	int ret, i;
-	int base = gsm->num << 6; /* Base for this MUX */
+	int ret, i, base;
 
 
 	gsm->tty = tty_kref_get(tty);
 	gsm->tty = tty_kref_get(tty);
 	gsm->output = gsmld_output;
 	gsm->output = gsmld_output;
@@ -2241,6 +2238,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 	else {
 	else {
 		/* Don't register device 0 - this is the control channel and not
 		/* Don't register device 0 - this is the control channel and not
 		   a usable tty interface */
 		   a usable tty interface */
+		base = gsm->num << 6; /* Base for this MUX */
 		for (i = 1; i < NUM_DLCI; i++)
 		for (i = 1; i < NUM_DLCI; i++)
 			tty_register_device(gsm_tty_driver, base + i, NULL);
 			tty_register_device(gsm_tty_driver, base + i, NULL);
 	}
 	}
@@ -2368,6 +2366,7 @@ static void gsmld_close(struct tty_struct *tty)
 static int gsmld_open(struct tty_struct *tty)
 static int gsmld_open(struct tty_struct *tty)
 {
 {
 	struct gsm_mux *gsm;
 	struct gsm_mux *gsm;
+	int ret;
 
 
 	if (tty->ops->write == NULL)
 	if (tty->ops->write == NULL)
 		return -EINVAL;
 		return -EINVAL;
@@ -2382,7 +2381,13 @@ static int gsmld_open(struct tty_struct *tty)
 
 
 	/* Attach the initial passive connection */
 	/* Attach the initial passive connection */
 	gsm->encoding = 1;
 	gsm->encoding = 1;
-	return gsmld_attach_gsm(tty, gsm);
+
+	ret = gsmld_attach_gsm(tty, gsm);
+	if (ret != 0) {
+		gsm_cleanup_mux(gsm);
+		mux_put(gsm);
+	}
+	return ret;
 }
 }
 
 
 /**
 /**

+ 10 - 11
drivers/tty/pty.c

@@ -316,7 +316,7 @@ done:
  *	pty_common_install		-	set up the pty pair
  *	pty_common_install		-	set up the pty pair
  *	@driver: the pty driver
  *	@driver: the pty driver
  *	@tty: the tty being instantiated
  *	@tty: the tty being instantiated
- *	@bool: legacy, true if this is BSD style
+ *	@legacy: true if this is BSD style
  *
  *
  *	Perform the initial set up for the tty/pty pair. Called from the
  *	Perform the initial set up for the tty/pty pair. Called from the
  *	tty layer when the port is first opened.
  *	tty layer when the port is first opened.
@@ -331,18 +331,17 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
 	int idx = tty->index;
 	int idx = tty->index;
 	int retval = -ENOMEM;
 	int retval = -ENOMEM;
 
 
-	o_tty = alloc_tty_struct();
-	if (!o_tty)
-		goto err;
 	ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
 	ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
 	ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
 	ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
 	if (!ports[0] || !ports[1])
 	if (!ports[0] || !ports[1])
-		goto err_free_tty;
+		goto err;
 	if (!try_module_get(driver->other->owner)) {
 	if (!try_module_get(driver->other->owner)) {
 		/* This cannot in fact currently happen */
 		/* This cannot in fact currently happen */
-		goto err_free_tty;
+		goto err;
 	}
 	}
-	initialize_tty_struct(o_tty, driver->other, idx);
+	o_tty = alloc_tty_struct(driver->other, idx);
+	if (!o_tty)
+		goto err_put_module;
 
 
 	if (legacy) {
 	if (legacy) {
 		/* We always use new tty termios data so we can do this
 		/* We always use new tty termios data so we can do this
@@ -387,12 +386,12 @@ err_free_termios:
 		tty_free_termios(tty);
 		tty_free_termios(tty);
 err_deinit_tty:
 err_deinit_tty:
 	deinitialize_tty_struct(o_tty);
 	deinitialize_tty_struct(o_tty);
-	module_put(o_tty->driver->owner);
-err_free_tty:
-	kfree(ports[0]);
-	kfree(ports[1]);
 	free_tty_struct(o_tty);
 	free_tty_struct(o_tty);
+err_put_module:
+	module_put(driver->other->owner);
 err:
 err:
+	kfree(ports[0]);
+	kfree(ports[1]);
 	return retval;
 	return retval;
 }
 }
 
 

+ 0 - 5
drivers/tty/serial/21285.c

@@ -78,10 +78,6 @@ static void serial21285_stop_rx(struct uart_port *port)
 	}
 	}
 }
 }
 
 
-static void serial21285_enable_ms(struct uart_port *port)
-{
-}
-
 static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
 static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
 {
 {
 	struct uart_port *port = dev_id;
 	struct uart_port *port = dev_id;
@@ -345,7 +341,6 @@ static struct uart_ops serial21285_ops = {
 	.stop_tx	= serial21285_stop_tx,
 	.stop_tx	= serial21285_stop_tx,
 	.start_tx	= serial21285_start_tx,
 	.start_tx	= serial21285_start_tx,
 	.stop_rx	= serial21285_stop_rx,
 	.stop_rx	= serial21285_stop_rx,
-	.enable_ms	= serial21285_enable_ms,
 	.break_ctl	= serial21285_break_ctl,
 	.break_ctl	= serial21285_break_ctl,
 	.startup	= serial21285_startup,
 	.startup	= serial21285_startup,
 	.shutdown	= serial21285_shutdown,
 	.shutdown	= serial21285_shutdown,

+ 2 - 0
drivers/tty/serial/8250/8250.h

@@ -12,6 +12,7 @@
  */
  */
 
 
 #include <linux/serial_8250.h>
 #include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
 #include <linux/dmaengine.h>
 #include <linux/dmaengine.h>
 
 
 struct uart_8250_dma {
 struct uart_8250_dma {
@@ -60,6 +61,7 @@ struct serial8250_config {
 	unsigned short	fifo_size;
 	unsigned short	fifo_size;
 	unsigned short	tx_loadsz;
 	unsigned short	tx_loadsz;
 	unsigned char	fcr;
 	unsigned char	fcr;
+	unsigned char	rxtrig_bytes[UART_FCR_R_TRIG_MAX_STATE];
 	unsigned int	flags;
 	unsigned int	flags;
 };
 };
 
 

+ 177 - 53
drivers/tty/serial/8250/8250_core.c

@@ -31,7 +31,6 @@
 #include <linux/tty.h>
 #include <linux/tty.h>
 #include <linux/ratelimit.h>
 #include <linux/ratelimit.h>
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_8250.h>
@@ -161,6 +160,7 @@ static const struct serial8250_config uart_config[] = {
 		.fifo_size	= 16,
 		.fifo_size	= 16,
 		.tx_loadsz	= 16,
 		.tx_loadsz	= 16,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.rxtrig_bytes	= {1, 4, 8, 14},
 		.flags		= UART_CAP_FIFO,
 		.flags		= UART_CAP_FIFO,
 	},
 	},
 	[PORT_CIRRUS] = {
 	[PORT_CIRRUS] = {
@@ -180,6 +180,7 @@ static const struct serial8250_config uart_config[] = {
 		.tx_loadsz	= 16,
 		.tx_loadsz	= 16,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
 				  UART_FCR_T_TRIG_00,
 				  UART_FCR_T_TRIG_00,
+		.rxtrig_bytes	= {8, 16, 24, 28},
 		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
 		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
 	},
 	},
 	[PORT_16750] = {
 	[PORT_16750] = {
@@ -188,6 +189,7 @@ static const struct serial8250_config uart_config[] = {
 		.tx_loadsz	= 64,
 		.tx_loadsz	= 64,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
 				  UART_FCR7_64BYTE,
 				  UART_FCR7_64BYTE,
+		.rxtrig_bytes	= {1, 16, 32, 56},
 		.flags		= UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
 		.flags		= UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
 	},
 	},
 	[PORT_STARTECH] = {
 	[PORT_STARTECH] = {
@@ -209,6 +211,7 @@ static const struct serial8250_config uart_config[] = {
 		.tx_loadsz	= 32,
 		.tx_loadsz	= 32,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
 				  UART_FCR_T_TRIG_10,
 				  UART_FCR_T_TRIG_10,
+		.rxtrig_bytes	= {8, 16, 56, 60},
 		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
 		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
 	},
 	},
 	[PORT_16850] = {
 	[PORT_16850] = {
@@ -266,6 +269,7 @@ static const struct serial8250_config uart_config[] = {
 		.tx_loadsz	= 8,
 		.tx_loadsz	= 8,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
 				  UART_FCR_T_TRIG_01,
 				  UART_FCR_T_TRIG_01,
+		.rxtrig_bytes	= {1, 4, 8, 14},
 		.flags		= UART_CAP_FIFO | UART_CAP_RTOIE,
 		.flags		= UART_CAP_FIFO | UART_CAP_RTOIE,
 	},
 	},
 	[PORT_XR17D15X] = {
 	[PORT_XR17D15X] = {
@@ -439,8 +443,7 @@ static int exar_handle_irq(struct uart_port *port);
 
 
 static void set_io_from_upio(struct uart_port *p)
 static void set_io_from_upio(struct uart_port *p)
 {
 {
-	struct uart_8250_port *up =
-		container_of(p, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(p);
 
 
 	up->dl_read = default_serial_dl_read;
 	up->dl_read = default_serial_dl_read;
 	up->dl_write = default_serial_dl_write;
 	up->dl_write = default_serial_dl_write;
@@ -531,11 +534,8 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
 
 
 void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
 void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
 {
 {
-	unsigned char fcr;
-
 	serial8250_clear_fifos(p);
 	serial8250_clear_fifos(p);
-	fcr = uart_config[p->port.type].fcr;
-	serial_out(p, UART_FCR, fcr);
+	serial_out(p, UART_FCR, p->fcr);
 }
 }
 EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
 EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
 
 
@@ -1277,8 +1277,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
 
 
 static void serial8250_stop_tx(struct uart_port *port)
 static void serial8250_stop_tx(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	__stop_tx(up);
 	__stop_tx(up);
 
 
@@ -1293,8 +1292,7 @@ static void serial8250_stop_tx(struct uart_port *port)
 
 
 static void serial8250_start_tx(struct uart_port *port)
 static void serial8250_start_tx(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	if (up->dma && !serial8250_tx_dma(up)) {
 	if (up->dma && !serial8250_tx_dma(up)) {
 		return;
 		return;
@@ -1322,8 +1320,7 @@ static void serial8250_start_tx(struct uart_port *port)
 
 
 static void serial8250_stop_rx(struct uart_port *port)
 static void serial8250_stop_rx(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	up->ier &= ~UART_IER_RLSI;
 	up->ier &= ~UART_IER_RLSI;
 	up->port.read_status_mask &= ~UART_LSR_DR;
 	up->port.read_status_mask &= ~UART_LSR_DR;
@@ -1332,8 +1329,7 @@ static void serial8250_stop_rx(struct uart_port *port)
 
 
 static void serial8250_enable_ms(struct uart_port *port)
 static void serial8250_enable_ms(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	/* no MSR capabilities */
 	/* no MSR capabilities */
 	if (up->bugs & UART_BUG_NOMSR)
 	if (up->bugs & UART_BUG_NOMSR)
@@ -1499,8 +1495,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
 {
 {
 	unsigned char status;
 	unsigned char status;
 	unsigned long flags;
 	unsigned long flags;
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	int dma_err = 0;
 	int dma_err = 0;
 
 
 	if (iir & UART_IIR_NO_INT)
 	if (iir & UART_IIR_NO_INT)
@@ -1785,8 +1780,7 @@ static void serial8250_backup_timeout(unsigned long data)
 
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
 static unsigned int serial8250_tx_empty(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	unsigned long flags;
 	unsigned long flags;
 	unsigned int lsr;
 	unsigned int lsr;
 
 
@@ -1800,8 +1794,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
 
 
 static unsigned int serial8250_get_mctrl(struct uart_port *port)
 static unsigned int serial8250_get_mctrl(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	unsigned int status;
 	unsigned int status;
 	unsigned int ret;
 	unsigned int ret;
 
 
@@ -1821,8 +1814,7 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
 
 
 static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	unsigned char mcr = 0;
 	unsigned char mcr = 0;
 
 
 	if (mctrl & TIOCM_RTS)
 	if (mctrl & TIOCM_RTS)
@@ -1843,8 +1835,7 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
 
 static void serial8250_break_ctl(struct uart_port *port, int break_state)
 static void serial8250_break_ctl(struct uart_port *port, int break_state)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	unsigned long flags;
 	unsigned long flags;
 
 
 	spin_lock_irqsave(&port->lock, flags);
 	spin_lock_irqsave(&port->lock, flags);
@@ -1911,8 +1902,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
 			 unsigned char c)
 			 unsigned char c)
 {
 {
 	unsigned int ier;
 	unsigned int ier;
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	/*
 	/*
 	 *	First save the IER then disable the interrupts
 	 *	First save the IER then disable the interrupts
@@ -1941,8 +1931,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
 
 
 static int serial8250_startup(struct uart_port *port)
 static int serial8250_startup(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	unsigned long flags;
 	unsigned long flags;
 	unsigned char lsr, iir;
 	unsigned char lsr, iir;
 	int retval;
 	int retval;
@@ -2194,8 +2183,7 @@ dont_test_tx_en:
 
 
 static void serial8250_shutdown(struct uart_port *port)
 static void serial8250_shutdown(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	unsigned long flags;
 	unsigned long flags;
 
 
 	/*
 	/*
@@ -2268,12 +2256,10 @@ void
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 		          struct ktermios *old)
 		          struct ktermios *old)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
-	unsigned char cval, fcr = 0;
+	struct uart_8250_port *up = up_to_u8250p(port);
+	unsigned char cval;
 	unsigned long flags;
 	unsigned long flags;
 	unsigned int baud, quot;
 	unsigned int baud, quot;
-	int fifo_bug = 0;
 
 
 	switch (termios->c_cflag & CSIZE) {
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
 	case CS5:
@@ -2296,7 +2282,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 	if (termios->c_cflag & PARENB) {
 	if (termios->c_cflag & PARENB) {
 		cval |= UART_LCR_PARITY;
 		cval |= UART_LCR_PARITY;
 		if (up->bugs & UART_BUG_PARITY)
 		if (up->bugs & UART_BUG_PARITY)
-			fifo_bug = 1;
+			up->fifo_bug = true;
 	}
 	}
 	if (!(termios->c_cflag & PARODD))
 	if (!(termios->c_cflag & PARODD))
 		cval |= UART_LCR_EPAR;
 		cval |= UART_LCR_EPAR;
@@ -2320,10 +2306,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 		quot++;
 		quot++;
 
 
 	if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
 	if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
-		fcr = uart_config[port->type].fcr;
-		if ((baud < 2400 && !up->dma) || fifo_bug) {
-			fcr &= ~UART_FCR_TRIGGER_MASK;
-			fcr |= UART_FCR_TRIGGER_1;
+		/* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
+		if ((baud < 2400 && !up->dma) || up->fifo_bug) {
+			up->fcr &= ~UART_FCR_TRIGGER_MASK;
+			up->fcr |= UART_FCR_TRIGGER_1;
 		}
 		}
 	}
 	}
 
 
@@ -2456,15 +2442,15 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * is written without DLAB set, this mode will be disabled.
 	 * is written without DLAB set, this mode will be disabled.
 	 */
 	 */
 	if (port->type == PORT_16750)
 	if (port->type == PORT_16750)
-		serial_port_out(port, UART_FCR, fcr);
+		serial_port_out(port, UART_FCR, up->fcr);
 
 
 	serial_port_out(port, UART_LCR, cval);		/* reset DLAB */
 	serial_port_out(port, UART_LCR, cval);		/* reset DLAB */
 	up->lcr = cval;					/* Save LCR */
 	up->lcr = cval;					/* Save LCR */
 	if (port->type != PORT_16750) {
 	if (port->type != PORT_16750) {
 		/* emulated UARTs (Lucent Venus 167x) need two steps */
 		/* emulated UARTs (Lucent Venus 167x) need two steps */
-		if (fcr & UART_FCR_ENABLE_FIFO)
+		if (up->fcr & UART_FCR_ENABLE_FIFO)
 			serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
 			serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
-		serial_port_out(port, UART_FCR, fcr);		/* set fcr */
+		serial_port_out(port, UART_FCR, up->fcr);	/* set fcr */
 	}
 	}
 	serial8250_set_mctrl(port, port->mctrl);
 	serial8250_set_mctrl(port, port->mctrl);
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
@@ -2498,8 +2484,7 @@ serial8250_set_ldisc(struct uart_port *port, int new)
 void serial8250_do_pm(struct uart_port *port, unsigned int state,
 void serial8250_do_pm(struct uart_port *port, unsigned int state,
 		      unsigned int oldstate)
 		      unsigned int oldstate)
 {
 {
-	struct uart_8250_port *p =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *p = up_to_u8250p(port);
 
 
 	serial8250_set_sleep(p, state != 0);
 	serial8250_set_sleep(p, state != 0);
 }
 }
@@ -2630,8 +2615,7 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
 
 
 static void serial8250_release_port(struct uart_port *port)
 static void serial8250_release_port(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	serial8250_release_std_resource(up);
 	serial8250_release_std_resource(up);
 	if (port->type == PORT_RSA)
 	if (port->type == PORT_RSA)
@@ -2640,8 +2624,7 @@ static void serial8250_release_port(struct uart_port *port)
 
 
 static int serial8250_request_port(struct uart_port *port)
 static int serial8250_request_port(struct uart_port *port)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 	int ret;
 	int ret;
 
 
 	if (port->type == PORT_8250_CIR)
 	if (port->type == PORT_8250_CIR)
@@ -2657,10 +2640,149 @@ static int serial8250_request_port(struct uart_port *port)
 	return ret;
 	return ret;
 }
 }
 
 
-static void serial8250_config_port(struct uart_port *port, int flags)
+static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
+{
+	const struct serial8250_config *conf_type = &uart_config[up->port.type];
+	unsigned char bytes;
+
+	bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
+
+	return bytes ? bytes : -EOPNOTSUPP;
+}
+
+static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
+{
+	const struct serial8250_config *conf_type = &uart_config[up->port.type];
+	int i;
+
+	if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
+		return -EOPNOTSUPP;
+
+	for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
+		if (bytes < conf_type->rxtrig_bytes[i])
+			/* Use the nearest lower value */
+			return (--i) << UART_FCR_R_TRIG_SHIFT;
+	}
+
+	return UART_FCR_R_TRIG_11;
+}
+
+static int do_get_rxtrig(struct tty_port *port)
+{
+	struct uart_state *state = container_of(port, struct uart_state, port);
+	struct uart_port *uport = state->uart_port;
+	struct uart_8250_port *up =
+		container_of(uport, struct uart_8250_port, port);
+
+	if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
+		return -EINVAL;
+
+	return fcr_get_rxtrig_bytes(up);
+}
+
+static int do_serial8250_get_rxtrig(struct tty_port *port)
+{
+	int rxtrig_bytes;
+
+	mutex_lock(&port->mutex);
+	rxtrig_bytes = do_get_rxtrig(port);
+	mutex_unlock(&port->mutex);
+
+	return rxtrig_bytes;
+}
+
+static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
+	struct device_attribute *attr, char *buf)
 {
 {
+	struct tty_port *port = dev_get_drvdata(dev);
+	int rxtrig_bytes;
+
+	rxtrig_bytes = do_serial8250_get_rxtrig(port);
+	if (rxtrig_bytes < 0)
+		return rxtrig_bytes;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
+}
+
+static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
+{
+	struct uart_state *state = container_of(port, struct uart_state, port);
+	struct uart_port *uport = state->uart_port;
 	struct uart_8250_port *up =
 	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+		container_of(uport, struct uart_8250_port, port);
+	int rxtrig;
+
+	if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
+	    up->fifo_bug)
+		return -EINVAL;
+
+	rxtrig = bytes_to_fcr_rxtrig(up, bytes);
+	if (rxtrig < 0)
+		return rxtrig;
+
+	serial8250_clear_fifos(up);
+	up->fcr &= ~UART_FCR_TRIGGER_MASK;
+	up->fcr |= (unsigned char)rxtrig;
+	serial_out(up, UART_FCR, up->fcr);
+	return 0;
+}
+
+static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
+{
+	int ret;
+
+	mutex_lock(&port->mutex);
+	ret = do_set_rxtrig(port, bytes);
+	mutex_unlock(&port->mutex);
+
+	return ret;
+}
+
+static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct tty_port *port = dev_get_drvdata(dev);
+	unsigned char bytes;
+	int ret;
+
+	if (!count)
+		return -EINVAL;
+
+	ret = kstrtou8(buf, 10, &bytes);
+	if (ret < 0)
+		return ret;
+
+	ret = do_serial8250_set_rxtrig(port, bytes);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
+		   serial8250_get_attr_rx_trig_bytes,
+		   serial8250_set_attr_rx_trig_bytes);
+
+static struct attribute *serial8250_dev_attrs[] = {
+	&dev_attr_rx_trig_bytes.attr,
+	NULL,
+	};
+
+static struct attribute_group serial8250_dev_attr_group = {
+	.attrs = serial8250_dev_attrs,
+	};
+
+static void register_dev_spec_attr_grp(struct uart_8250_port *up)
+{
+	const struct serial8250_config *conf_type = &uart_config[up->port.type];
+
+	if (conf_type->rxtrig_bytes[0])
+		up->port.attr_group = &serial8250_dev_attr_group;
+}
+
+static void serial8250_config_port(struct uart_port *port, int flags)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
 	int probeflags = PROBE_ANY;
 	int probeflags = PROBE_ANY;
 	int ret;
 	int ret;
 
 
@@ -2705,6 +2827,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)
 	if ((port->type == PORT_XR17V35X) ||
 	if ((port->type == PORT_XR17V35X) ||
 	   (port->type == PORT_XR17D15X))
 	   (port->type == PORT_XR17D15X))
 		port->handle_irq = exar_handle_irq;
 		port->handle_irq = exar_handle_irq;
+
+	register_dev_spec_attr_grp(up);
+	up->fcr = uart_config[up->port.type].fcr;
 }
 }
 
 
 static int
 static int
@@ -2859,8 +2984,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 
 
 static void serial8250_console_putchar(struct uart_port *port, int ch)
 static void serial8250_console_putchar(struct uart_port *port, int ch)
 {
 {
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	wait_for_xmitr(up, UART_LSR_THRE);
 	wait_for_xmitr(up, UART_LSR_THRE);
 	serial_port_out(port, UART_TX, ch);
 	serial_port_out(port, UART_TX, ch);

+ 103 - 87
drivers/tty/serial/8250/8250_dw.c

@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
+#include <linux/reset.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 
 
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
@@ -59,73 +60,17 @@ struct dw8250_data {
 	int			last_mcr;
 	int			last_mcr;
 	int			line;
 	int			line;
 	struct clk		*clk;
 	struct clk		*clk;
+	struct clk		*pclk;
+	struct reset_control	*rst;
 	struct uart_8250_dma	dma;
 	struct uart_8250_dma	dma;
 };
 };
 
 
-struct dw8250_acpi_desc {
-	void (*set_termios)(struct uart_port *p, struct ktermios *termios,
-			    struct ktermios *old);
-};
-
 #define BYT_PRV_CLK			0x800
 #define BYT_PRV_CLK			0x800
 #define BYT_PRV_CLK_EN			(1 << 0)
 #define BYT_PRV_CLK_EN			(1 << 0)
 #define BYT_PRV_CLK_M_VAL_SHIFT		1
 #define BYT_PRV_CLK_M_VAL_SHIFT		1
 #define BYT_PRV_CLK_N_VAL_SHIFT		16
 #define BYT_PRV_CLK_N_VAL_SHIFT		16
 #define BYT_PRV_CLK_UPDATE		(1 << 31)
 #define BYT_PRV_CLK_UPDATE		(1 << 31)
 
 
-static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
-			    struct ktermios *old)
-{
-	unsigned int baud = tty_termios_baud_rate(termios);
-	unsigned int m, n;
-	u32 reg;
-
-	/*
-	* For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
-	* dividers must be adjusted.
-	*
-	* uartclk = (m / n) * 100 MHz, where m <= n
-	*/
-	switch (baud) {
-	case 500000:
-	case 1000000:
-	case 2000000:
-	case 4000000:
-		m = 64;
-		n = 100;
-		p->uartclk = 64000000;
-		break;
-	case 3500000:
-		m = 56;
-		n = 100;
-		p->uartclk = 56000000;
-		break;
-	case 1500000:
-	case 3000000:
-		m = 48;
-		n = 100;
-		p->uartclk = 48000000;
-		break;
-	case 2500000:
-		m = 40;
-		n = 100;
-		p->uartclk = 40000000;
-		break;
-	default:
-		m = 2304;
-		n = 3125;
-		p->uartclk = 73728000;
-	}
-
-	/* Reset the clock */
-	reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
-	writel(reg, p->membase + BYT_PRV_CLK);
-	reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
-	writel(reg, p->membase + BYT_PRV_CLK);
-
-	serial8250_do_set_termios(p, termios, old);
-}
-
 static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
 static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
 {
 {
 	struct dw8250_data *d = p->private_data;
 	struct dw8250_data *d = p->private_data;
@@ -141,8 +86,9 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
 
 
 static void dw8250_force_idle(struct uart_port *p)
 static void dw8250_force_idle(struct uart_port *p)
 {
 {
-	serial8250_clear_and_reinit_fifos(container_of
-					  (p, struct uart_8250_port, port));
+	struct uart_8250_port *up = up_to_u8250p(p);
+
+	serial8250_clear_and_reinit_fifos(up);
 	(void)p->serial_in(p, UART_RX);
 	(void)p->serial_in(p, UART_RX);
 }
 }
 
 
@@ -242,6 +188,32 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 		pm_runtime_put_sync_suspend(port->dev);
 		pm_runtime_put_sync_suspend(port->dev);
 }
 }
 
 
+static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
+			       struct ktermios *old)
+{
+	unsigned int baud = tty_termios_baud_rate(termios);
+	struct dw8250_data *d = p->private_data;
+	unsigned int rate;
+	int ret;
+
+	if (IS_ERR(d->clk) || !old)
+		goto out;
+
+	/* Not requesting clock rates below 1.8432Mhz */
+	if (baud < 115200)
+		baud = 115200;
+
+	clk_disable_unprepare(d->clk);
+	rate = clk_round_rate(d->clk, baud * 16);
+	ret = clk_set_rate(d->clk, rate);
+	clk_prepare_enable(d->clk);
+
+	if (!ret)
+		p->uartclk = rate;
+out:
+	serial8250_do_set_termios(p, termios, old);
+}
+
 static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
 static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
 {
 {
 	struct dw8250_data *data = param;
 	struct dw8250_data *data = param;
@@ -286,6 +258,7 @@ static int dw8250_probe_of(struct uart_port *p,
 			   struct dw8250_data *data)
 			   struct dw8250_data *data)
 {
 {
 	struct device_node	*np = p->dev->of_node;
 	struct device_node	*np = p->dev->of_node;
+	struct uart_8250_port *up = up_to_u8250p(p);
 	u32			val;
 	u32			val;
 	bool has_ucv = true;
 	bool has_ucv = true;
 
 
@@ -299,7 +272,7 @@ static int dw8250_probe_of(struct uart_port *p,
 		p->membase += 7;
 		p->membase += 7;
 #endif
 #endif
 		p->serial_out = dw8250_serial_out_rb;
 		p->serial_out = dw8250_serial_out_rb;
-		p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+		p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
 		p->type = PORT_OCTEON;
 		p->type = PORT_OCTEON;
 		data->usr_reg = 0x27;
 		data->usr_reg = 0x27;
 		has_ucv = false;
 		has_ucv = false;
@@ -318,7 +291,7 @@ static int dw8250_probe_of(struct uart_port *p,
 		}
 		}
 	}
 	}
 	if (has_ucv)
 	if (has_ucv)
-		dw8250_setup_port(container_of(p, struct uart_8250_port, port));
+		dw8250_setup_port(up);
 
 
 	if (!of_property_read_u32(np, "reg-shift", &val))
 	if (!of_property_read_u32(np, "reg-shift", &val))
 		p->regshift = val;
 		p->regshift = val;
@@ -340,16 +313,10 @@ static int dw8250_probe_of(struct uart_port *p,
 static int dw8250_probe_acpi(struct uart_8250_port *up,
 static int dw8250_probe_acpi(struct uart_8250_port *up,
 			     struct dw8250_data *data)
 			     struct dw8250_data *data)
 {
 {
-	const struct acpi_device_id *id;
 	struct uart_port *p = &up->port;
 	struct uart_port *p = &up->port;
-	struct dw8250_acpi_desc *acpi_desc;
 
 
 	dw8250_setup_port(up);
 	dw8250_setup_port(up);
 
 
-	id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
-	if (!id)
-		return -ENODEV;
-
 	p->iotype = UPIO_MEM32;
 	p->iotype = UPIO_MEM32;
 	p->serial_in = dw8250_serial_in32;
 	p->serial_in = dw8250_serial_in32;
 	p->serial_out = dw8250_serial_out32;
 	p->serial_out = dw8250_serial_out32;
@@ -360,12 +327,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
 	up->dma->rxconf.src_maxburst = p->fifosize / 4;
 	up->dma->rxconf.src_maxburst = p->fifosize / 4;
 	up->dma->txconf.dst_maxburst = p->fifosize / 4;
 	up->dma->txconf.dst_maxburst = p->fifosize / 4;
 
 
-	acpi_desc = (struct dw8250_acpi_desc *)id->driver_data;
-	if (!acpi_desc)
-		return 0;
-
-	if (acpi_desc->set_termios)
-		p->set_termios = acpi_desc->set_termios;
+	up->port.set_termios = dw8250_set_termios;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -402,11 +364,40 @@ static int dw8250_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	data->usr_reg = DW_UART_USR;
 	data->usr_reg = DW_UART_USR;
-	data->clk = devm_clk_get(&pdev->dev, NULL);
+	data->clk = devm_clk_get(&pdev->dev, "baudclk");
+	if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER)
+		data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
 	if (!IS_ERR(data->clk)) {
 	if (!IS_ERR(data->clk)) {
-		clk_prepare_enable(data->clk);
-		uart.port.uartclk = clk_get_rate(data->clk);
+		err = clk_prepare_enable(data->clk);
+		if (err)
+			dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
+				 err);
+		else
+			uart.port.uartclk = clk_get_rate(data->clk);
+	}
+
+	data->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
+	if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) {
+		err = -EPROBE_DEFER;
+		goto err_clk;
 	}
 	}
+	if (!IS_ERR(data->pclk)) {
+		err = clk_prepare_enable(data->pclk);
+		if (err) {
+			dev_err(&pdev->dev, "could not enable apb_pclk\n");
+			goto err_clk;
+		}
+	}
+
+	data->rst = devm_reset_control_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) {
+		err = -EPROBE_DEFER;
+		goto err_pclk;
+	}
+	if (!IS_ERR(data->rst))
+		reset_control_deassert(data->rst);
 
 
 	data->dma.rx_chan_id = -1;
 	data->dma.rx_chan_id = -1;
 	data->dma.tx_chan_id = -1;
 	data->dma.tx_chan_id = -1;
@@ -422,18 +413,21 @@ static int dw8250_probe(struct platform_device *pdev)
 	if (pdev->dev.of_node) {
 	if (pdev->dev.of_node) {
 		err = dw8250_probe_of(&uart.port, data);
 		err = dw8250_probe_of(&uart.port, data);
 		if (err)
 		if (err)
-			return err;
+			goto err_reset;
 	} else if (ACPI_HANDLE(&pdev->dev)) {
 	} else if (ACPI_HANDLE(&pdev->dev)) {
 		err = dw8250_probe_acpi(&uart, data);
 		err = dw8250_probe_acpi(&uart, data);
 		if (err)
 		if (err)
-			return err;
+			goto err_reset;
 	} else {
 	} else {
-		return -ENODEV;
+		err = -ENODEV;
+		goto err_reset;
 	}
 	}
 
 
 	data->line = serial8250_register_8250_port(&uart);
 	data->line = serial8250_register_8250_port(&uart);
-	if (data->line < 0)
-		return data->line;
+	if (data->line < 0) {
+		err = data->line;
+		goto err_reset;
+	}
 
 
 	platform_set_drvdata(pdev, data);
 	platform_set_drvdata(pdev, data);
 
 
@@ -441,6 +435,20 @@ static int dw8250_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
 
 	return 0;
 	return 0;
+
+err_reset:
+	if (!IS_ERR(data->rst))
+		reset_control_assert(data->rst);
+
+err_pclk:
+	if (!IS_ERR(data->pclk))
+		clk_disable_unprepare(data->pclk);
+
+err_clk:
+	if (!IS_ERR(data->clk))
+		clk_disable_unprepare(data->clk);
+
+	return err;
 }
 }
 
 
 static int dw8250_remove(struct platform_device *pdev)
 static int dw8250_remove(struct platform_device *pdev)
@@ -451,6 +459,12 @@ static int dw8250_remove(struct platform_device *pdev)
 
 
 	serial8250_unregister_port(data->line);
 	serial8250_unregister_port(data->line);
 
 
+	if (!IS_ERR(data->rst))
+		reset_control_assert(data->rst);
+
+	if (!IS_ERR(data->pclk))
+		clk_disable_unprepare(data->pclk);
+
 	if (!IS_ERR(data->clk))
 	if (!IS_ERR(data->clk))
 		clk_disable_unprepare(data->clk);
 		clk_disable_unprepare(data->clk);
 
 
@@ -488,6 +502,9 @@ static int dw8250_runtime_suspend(struct device *dev)
 	if (!IS_ERR(data->clk))
 	if (!IS_ERR(data->clk))
 		clk_disable_unprepare(data->clk);
 		clk_disable_unprepare(data->clk);
 
 
+	if (!IS_ERR(data->pclk))
+		clk_disable_unprepare(data->pclk);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -495,6 +512,9 @@ static int dw8250_runtime_resume(struct device *dev)
 {
 {
 	struct dw8250_data *data = dev_get_drvdata(dev);
 	struct dw8250_data *data = dev_get_drvdata(dev);
 
 
+	if (!IS_ERR(data->pclk))
+		clk_prepare_enable(data->pclk);
+
 	if (!IS_ERR(data->clk))
 	if (!IS_ERR(data->clk))
 		clk_prepare_enable(data->clk);
 		clk_prepare_enable(data->clk);
 
 
@@ -514,16 +534,12 @@ static const struct of_device_id dw8250_of_match[] = {
 };
 };
 MODULE_DEVICE_TABLE(of, dw8250_of_match);
 MODULE_DEVICE_TABLE(of, dw8250_of_match);
 
 
-static struct dw8250_acpi_desc byt_8250_desc = {
-	.set_termios = byt_set_termios,
-};
-
 static const struct acpi_device_id dw8250_acpi_match[] = {
 static const struct acpi_device_id dw8250_acpi_match[] = {
 	{ "INT33C4", 0 },
 	{ "INT33C4", 0 },
 	{ "INT33C5", 0 },
 	{ "INT33C5", 0 },
 	{ "INT3434", 0 },
 	{ "INT3434", 0 },
 	{ "INT3435", 0 },
 	{ "INT3435", 0 },
-	{ "80860F0A", (kernel_ulong_t)&byt_8250_desc},
+	{ "80860F0A", 0 },
 	{ },
 	{ },
 };
 };
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);

+ 1 - 2
drivers/tty/serial/8250/8250_fsl.c

@@ -28,8 +28,7 @@ int fsl8250_handle_irq(struct uart_port *port)
 	unsigned char lsr, orig_lsr;
 	unsigned char lsr, orig_lsr;
 	unsigned long flags;
 	unsigned long flags;
 	unsigned int iir;
 	unsigned int iir;
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(port);
 
 
 	spin_lock_irqsave(&up->port.lock, flags);
 	spin_lock_irqsave(&up->port.lock, flags);
 
 

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

@@ -1581,8 +1581,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
 
 
 static void kt_handle_break(struct uart_port *p)
 static void kt_handle_break(struct uart_port *p)
 {
 {
-	struct uart_8250_port *up =
-		container_of(p, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(p);
 	/*
 	/*
 	 * On receipt of a BI, serial device in Intel ME (Intel
 	 * On receipt of a BI, serial device in Intel ME (Intel
 	 * management engine) needs to have its fifos cleared for sane
 	 * management engine) needs to have its fifos cleared for sane
@@ -1593,8 +1592,7 @@ static void kt_handle_break(struct uart_port *p)
 
 
 static unsigned int kt_serial_in(struct uart_port *p, int offset)
 static unsigned int kt_serial_in(struct uart_port *p, int offset)
 {
 {
-	struct uart_8250_port *up =
-		container_of(p, struct uart_8250_port, port);
+	struct uart_8250_port *up = up_to_u8250p(p);
 	unsigned int val;
 	unsigned int val;
 
 
 	/*
 	/*

+ 2 - 2
drivers/tty/serial/Kconfig

@@ -238,7 +238,6 @@ config SERIAL_SAMSUNG_UARTS_4
 config SERIAL_SAMSUNG_UARTS
 config SERIAL_SAMSUNG_UARTS
 	int
 	int
 	depends on PLAT_SAMSUNG
 	depends on PLAT_SAMSUNG
-	default 6 if CPU_S5P6450
 	default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
 	default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
 	default 3
 	default 3
 	help
 	help
@@ -774,7 +773,7 @@ config SERIAL_HS_LPC32XX
 
 
 config SERIAL_HS_LPC32XX_CONSOLE
 config SERIAL_HS_LPC32XX_CONSOLE
 	bool "Enable LPC32XX high speed UART serial console"
 	bool "Enable LPC32XX high speed UART serial console"
-	depends on SERIAL_HS_LPC32XX
+	depends on SERIAL_HS_LPC32XX=y
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE_CONSOLE
 	help
 	help
 	  If you would like to be able to use one of the high speed serial
 	  If you would like to be able to use one of the high speed serial
@@ -1473,6 +1472,7 @@ config SERIAL_ARC_CONSOLE
 	bool "Console on ARC UART"
 	bool "Console on ARC UART"
 	depends on SERIAL_ARC=y
 	depends on SERIAL_ARC=y
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
 	help
 	help
 	  Enable system Console on ARC UART
 	  Enable system Console on ARC UART
 
 

+ 5 - 14
drivers/tty/serial/altera_jtaguart.c

@@ -109,10 +109,6 @@ static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
 {
 {
 }
 }
 
 
-static void altera_jtaguart_enable_ms(struct uart_port *port)
-{
-}
-
 static void altera_jtaguart_set_termios(struct uart_port *port,
 static void altera_jtaguart_set_termios(struct uart_port *port,
 					struct ktermios *termios,
 					struct ktermios *termios,
 					struct ktermios *old)
 					struct ktermios *old)
@@ -291,7 +287,6 @@ static struct uart_ops altera_jtaguart_ops = {
 	.start_tx	= altera_jtaguart_start_tx,
 	.start_tx	= altera_jtaguart_start_tx,
 	.stop_tx	= altera_jtaguart_stop_tx,
 	.stop_tx	= altera_jtaguart_stop_tx,
 	.stop_rx	= altera_jtaguart_stop_rx,
 	.stop_rx	= altera_jtaguart_stop_rx,
-	.enable_ms	= altera_jtaguart_enable_ms,
 	.break_ctl	= altera_jtaguart_break_ctl,
 	.break_ctl	= altera_jtaguart_break_ctl,
 	.startup	= altera_jtaguart_startup,
 	.startup	= altera_jtaguart_startup,
 	.shutdown	= altera_jtaguart_shutdown,
 	.shutdown	= altera_jtaguart_shutdown,
@@ -309,9 +304,8 @@ static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
 
 
 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
-static void altera_jtaguart_console_putc(struct console *co, const char c)
+static void altera_jtaguart_console_putc(struct uart_port *port, int c)
 {
 {
-	struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
 	unsigned long status;
 	unsigned long status;
 	unsigned long flags;
 	unsigned long flags;
 
 
@@ -330,9 +324,8 @@ static void altera_jtaguart_console_putc(struct console *co, const char c)
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 }
 #else
 #else
-static void altera_jtaguart_console_putc(struct console *co, const char c)
+static void altera_jtaguart_console_putc(struct uart_port *port, int c)
 {
 {
-	struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
 	unsigned long flags;
 	unsigned long flags;
 
 
 	spin_lock_irqsave(&port->lock, flags);
 	spin_lock_irqsave(&port->lock, flags);
@@ -350,11 +343,9 @@ static void altera_jtaguart_console_putc(struct console *co, const char c)
 static void altera_jtaguart_console_write(struct console *co, const char *s,
 static void altera_jtaguart_console_write(struct console *co, const char *s,
 					  unsigned int count)
 					  unsigned int count)
 {
 {
-	for (; count; count--, s++) {
-		altera_jtaguart_console_putc(co, *s);
-		if (*s == '\n')
-			altera_jtaguart_console_putc(co, '\r');
-	}
+	struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
+
+	uart_console_write(port, s, count, altera_jtaguart_console_putc);
 }
 }
 
 
 static int __init altera_jtaguart_console_setup(struct console *co,
 static int __init altera_jtaguart_console_setup(struct console *co,

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

@@ -163,10 +163,6 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 }
 
 
-static void altera_uart_enable_ms(struct uart_port *port)
-{
-}
-
 static void altera_uart_set_termios(struct uart_port *port,
 static void altera_uart_set_termios(struct uart_port *port,
 				    struct ktermios *termios,
 				    struct ktermios *termios,
 				    struct ktermios *old)
 				    struct ktermios *old)
@@ -415,7 +411,6 @@ static struct uart_ops altera_uart_ops = {
 	.start_tx	= altera_uart_start_tx,
 	.start_tx	= altera_uart_start_tx,
 	.stop_tx	= altera_uart_stop_tx,
 	.stop_tx	= altera_uart_stop_tx,
 	.stop_rx	= altera_uart_stop_rx,
 	.stop_rx	= altera_uart_stop_rx,
-	.enable_ms	= altera_uart_enable_ms,
 	.break_ctl	= altera_uart_break_ctl,
 	.break_ctl	= altera_uart_break_ctl,
 	.startup	= altera_uart_startup,
 	.startup	= altera_uart_startup,
 	.shutdown	= altera_uart_shutdown,
 	.shutdown	= altera_uart_shutdown,
@@ -435,7 +430,7 @@ static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
 
 
 #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
 #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
 
 
-static void altera_uart_console_putc(struct uart_port *port, const char c)
+static void altera_uart_console_putc(struct uart_port *port, int c)
 {
 {
 	while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 	while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 		 ALTERA_UART_STATUS_TRDY_MSK))
 		 ALTERA_UART_STATUS_TRDY_MSK))
@@ -449,11 +444,7 @@ static void altera_uart_console_write(struct console *co, const char *s,
 {
 {
 	struct uart_port *port = &(altera_uart_ports + co->index)->port;
 	struct uart_port *port = &(altera_uart_ports + co->index)->port;
 
 
-	for (; count; count--, s++) {
-		altera_uart_console_putc(port, *s);
-		if (*s == '\n')
-			altera_uart_console_putc(port, '\r');
-	}
+	uart_console_write(port, s, count, altera_uart_console_putc);
 }
 }
 
 
 static int __init altera_uart_console_setup(struct console *co, char *options)
 static int __init altera_uart_console_setup(struct console *co, char *options)

+ 16 - 32
drivers/tty/serial/amba-pl010.c

@@ -46,8 +46,7 @@
 #include <linux/amba/serial.h>
 #include <linux/amba/serial.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 #define UART_NR		8
 #define UART_NR		8
 
 
@@ -688,28 +687,22 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
 		if (amba_ports[i] == NULL)
 		if (amba_ports[i] == NULL)
 			break;
 			break;
 
 
-	if (i == ARRAY_SIZE(amba_ports)) {
-		ret = -EBUSY;
-		goto out;
-	}
+	if (i == ARRAY_SIZE(amba_ports))
+		return -EBUSY;
 
 
-	uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
-	if (!uap) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
+			   GFP_KERNEL);
+	if (!uap)
+		return -ENOMEM;
 
 
-	base = ioremap(dev->res.start, resource_size(&dev->res));
-	if (!base) {
-		ret = -ENOMEM;
-		goto free;
-	}
+	base = devm_ioremap(&dev->dev, dev->res.start,
+			    resource_size(&dev->res));
+	if (!base)
+		return -ENOMEM;
 
 
-	uap->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(uap->clk)) {
-		ret = PTR_ERR(uap->clk);
-		goto unmap;
-	}
+	uap->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(uap->clk))
+		return PTR_ERR(uap->clk);
 
 
 	uap->port.dev = &dev->dev;
 	uap->port.dev = &dev->dev;
 	uap->port.mapbase = dev->res.start;
 	uap->port.mapbase = dev->res.start;
@@ -727,15 +720,9 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
 
 
 	amba_set_drvdata(dev, uap);
 	amba_set_drvdata(dev, uap);
 	ret = uart_add_one_port(&amba_reg, &uap->port);
 	ret = uart_add_one_port(&amba_reg, &uap->port);
-	if (ret) {
+	if (ret)
 		amba_ports[i] = NULL;
 		amba_ports[i] = NULL;
-		clk_put(uap->clk);
- unmap:
-		iounmap(base);
- free:
-		kfree(uap);
-	}
- out:
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -750,9 +737,6 @@ static int pl010_remove(struct amba_device *dev)
 		if (amba_ports[i] == uap)
 		if (amba_ports[i] == uap)
 			amba_ports[i] = NULL;
 			amba_ports[i] = NULL;
 
 
-	iounmap(uap->port.membase);
-	clk_put(uap->clk);
-	kfree(uap);
 	return 0;
 	return 0;
 }
 }
 
 

+ 10 - 20
drivers/tty/serial/amba-pl011.c

@@ -1484,7 +1484,7 @@ static int pl011_hwinit(struct uart_port *port)
 	 */
 	 */
 	retval = clk_prepare_enable(uap->clk);
 	retval = clk_prepare_enable(uap->clk);
 	if (retval)
 	if (retval)
-		goto out;
+		return retval;
 
 
 	uap->port.uartclk = clk_get_rate(uap->clk);
 	uap->port.uartclk = clk_get_rate(uap->clk);
 
 
@@ -1507,8 +1507,6 @@ static int pl011_hwinit(struct uart_port *port)
 			plat->init();
 			plat->init();
 	}
 	}
 	return 0;
 	return 0;
- out:
-	return retval;
 }
 }
 
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
@@ -2131,32 +2129,24 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		if (amba_ports[i] == NULL)
 		if (amba_ports[i] == NULL)
 			break;
 			break;
 
 
-	if (i == ARRAY_SIZE(amba_ports)) {
-		ret = -EBUSY;
-		goto out;
-	}
+	if (i == ARRAY_SIZE(amba_ports))
+		return -EBUSY;
 
 
 	uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
 	uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
 			   GFP_KERNEL);
 			   GFP_KERNEL);
-	if (uap == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (uap == NULL)
+		return -ENOMEM;
 
 
 	i = pl011_probe_dt_alias(i, &dev->dev);
 	i = pl011_probe_dt_alias(i, &dev->dev);
 
 
 	base = devm_ioremap(&dev->dev, dev->res.start,
 	base = devm_ioremap(&dev->dev, dev->res.start,
 			    resource_size(&dev->res));
 			    resource_size(&dev->res));
-	if (!base) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!base)
+		return -ENOMEM;
 
 
 	uap->clk = devm_clk_get(&dev->dev, NULL);
 	uap->clk = devm_clk_get(&dev->dev, NULL);
-	if (IS_ERR(uap->clk)) {
-		ret = PTR_ERR(uap->clk);
-		goto out;
-	}
+	if (IS_ERR(uap->clk))
+		return PTR_ERR(uap->clk);
 
 
 	uap->vendor = vendor;
 	uap->vendor = vendor;
 	uap->lcrh_rx = vendor->lcrh_rx;
 	uap->lcrh_rx = vendor->lcrh_rx;
@@ -2198,7 +2188,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		uart_unregister_driver(&amba_reg);
 		uart_unregister_driver(&amba_reg);
 		pl011_dma_remove(uap);
 		pl011_dma_remove(uap);
 	}
 	}
- out:
+
 	return ret;
 	return ret;
 }
 }
 
 

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

@@ -71,11 +71,6 @@ static void apbuart_stop_rx(struct uart_port *port)
 	UART_PUT_CTRL(port, cr);
 	UART_PUT_CTRL(port, cr);
 }
 }
 
 
-static void apbuart_enable_ms(struct uart_port *port)
-{
-	/* No modem status change interrupts for APBUART */
-}
-
 static void apbuart_rx_chars(struct uart_port *port)
 static void apbuart_rx_chars(struct uart_port *port)
 {
 {
 	unsigned int status, ch, rsr, flag;
 	unsigned int status, ch, rsr, flag;
@@ -337,7 +332,6 @@ static struct uart_ops grlib_apbuart_ops = {
 	.stop_tx = apbuart_stop_tx,
 	.stop_tx = apbuart_stop_tx,
 	.start_tx = apbuart_start_tx,
 	.start_tx = apbuart_start_tx,
 	.stop_rx = apbuart_stop_rx,
 	.stop_rx = apbuart_stop_rx,
-	.enable_ms = apbuart_enable_ms,
 	.break_ctl = apbuart_break_ctl,
 	.break_ctl = apbuart_break_ctl,
 	.startup = apbuart_startup,
 	.startup = apbuart_startup,
 	.shutdown = apbuart_shutdown,
 	.shutdown = apbuart_shutdown,

+ 0 - 5
drivers/tty/serial/ar933x_uart.c

@@ -176,10 +176,6 @@ static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
 	spin_unlock_irqrestore(&up->port.lock, flags);
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 }
 
 
-static void ar933x_uart_enable_ms(struct uart_port *port)
-{
-}
-
 /*
 /*
  * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
  * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
  */
  */
@@ -495,7 +491,6 @@ static struct uart_ops ar933x_uart_ops = {
 	.stop_tx	= ar933x_uart_stop_tx,
 	.stop_tx	= ar933x_uart_stop_tx,
 	.start_tx	= ar933x_uart_start_tx,
 	.start_tx	= ar933x_uart_start_tx,
 	.stop_rx	= ar933x_uart_stop_rx,
 	.stop_rx	= ar933x_uart_stop_rx,
-	.enable_ms	= ar933x_uart_enable_ms,
 	.break_ctl	= ar933x_uart_break_ctl,
 	.break_ctl	= ar933x_uart_break_ctl,
 	.startup	= ar933x_uart_startup,
 	.startup	= ar933x_uart_startup,
 	.shutdown	= ar933x_uart_shutdown,
 	.shutdown	= ar933x_uart_shutdown,

+ 121 - 216
drivers/tty/serial/arc_uart.c

@@ -37,8 +37,8 @@
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/io.h>
 #include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 
 /*************************************
 /*************************************
  * ARC UART Hardware Specs
  * ARC UART Hardware Specs
@@ -72,7 +72,7 @@
 #define RXOERR  0x02	/* OverFlow Err: Char recv but RXFULL still set */
 #define RXOERR  0x02	/* OverFlow Err: Char recv but RXFULL still set */
 
 
 /* Uart bit fiddling helpers: lowest level */
 /* Uart bit fiddling helpers: lowest level */
-#define RBASE(uart, reg)      (uart->port.membase + reg)
+#define RBASE(port, reg)      (port->membase + reg)
 #define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
 #define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
 #define UART_REG_GET(u, r)    readb(RBASE(u, r))
 #define UART_REG_GET(u, r)    readb(RBASE(u, r))
 
 
@@ -102,7 +102,6 @@
 struct arc_uart_port {
 struct arc_uart_port {
 	struct uart_port port;
 	struct uart_port port;
 	unsigned long baud;
 	unsigned long baud;
-	int is_emulated;	/* H/w vs. Instruction Set Simulator */
 };
 };
 
 
 #define to_arc_port(uport)  container_of(uport, struct arc_uart_port, port)
 #define to_arc_port(uport)  container_of(uport, struct arc_uart_port, port)
@@ -129,19 +128,15 @@ static struct uart_driver arc_uart_driver = {
 
 
 static void arc_serial_stop_rx(struct uart_port *port)
 static void arc_serial_stop_rx(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-
-	UART_RX_IRQ_DISABLE(uart);
+	UART_RX_IRQ_DISABLE(port);
 }
 }
 
 
 static void arc_serial_stop_tx(struct uart_port *port)
 static void arc_serial_stop_tx(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-
-	while (!(UART_GET_STATUS(uart) & TXEMPTY))
+	while (!(UART_GET_STATUS(port) & TXEMPTY))
 		cpu_relax();
 		cpu_relax();
 
 
-	UART_TX_IRQ_DISABLE(uart);
+	UART_TX_IRQ_DISABLE(port);
 }
 }
 
 
 /*
 /*
@@ -149,10 +144,9 @@ static void arc_serial_stop_tx(struct uart_port *port)
  */
  */
 static unsigned int arc_serial_tx_empty(struct uart_port *port)
 static unsigned int arc_serial_tx_empty(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
 	unsigned int stat;
 	unsigned int stat;
 
 
-	stat = UART_GET_STATUS(uart);
+	stat = UART_GET_STATUS(port);
 	if (stat & TXEMPTY)
 	if (stat & TXEMPTY)
 		return TIOCSER_TEMT;
 		return TIOCSER_TEMT;
 
 
@@ -166,24 +160,24 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
  *     = by uart_start( ) before calling us
  *     = by uart_start( ) before calling us
  *     = tx_ist checks that too before calling
  *     = tx_ist checks that too before calling
  */
  */
-static void arc_serial_tx_chars(struct arc_uart_port *uart)
+static void arc_serial_tx_chars(struct uart_port *port)
 {
 {
-	struct circ_buf *xmit = &uart->port.state->xmit;
+	struct circ_buf *xmit = &port->state->xmit;
 	int sent = 0;
 	int sent = 0;
 	unsigned char ch;
 	unsigned char ch;
 
 
-	if (unlikely(uart->port.x_char)) {
-		UART_SET_DATA(uart, uart->port.x_char);
-		uart->port.icount.tx++;
-		uart->port.x_char = 0;
+	if (unlikely(port->x_char)) {
+		UART_SET_DATA(port, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
 		sent = 1;
 		sent = 1;
 	} else if (!uart_circ_empty(xmit)) {
 	} else if (!uart_circ_empty(xmit)) {
 		ch = xmit->buf[xmit->tail];
 		ch = xmit->buf[xmit->tail];
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		uart->port.icount.tx++;
-		while (!(UART_GET_STATUS(uart) & TXEMPTY))
+		port->icount.tx++;
+		while (!(UART_GET_STATUS(port) & TXEMPTY))
 			cpu_relax();
 			cpu_relax();
-		UART_SET_DATA(uart, ch);
+		UART_SET_DATA(port, ch);
 		sent = 1;
 		sent = 1;
 	}
 	}
 
 
@@ -192,10 +186,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
 	 * By Hard ISR to schedule processing in software interrupt part
 	 * By Hard ISR to schedule processing in software interrupt part
 	 */
 	 */
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&uart->port);
+		uart_write_wakeup(port);
 
 
 	if (sent)
 	if (sent)
-		UART_TX_IRQ_ENABLE(uart);
+		UART_TX_IRQ_ENABLE(port);
 }
 }
 
 
 /*
 /*
@@ -204,12 +198,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
  */
  */
 static void arc_serial_start_tx(struct uart_port *port)
 static void arc_serial_start_tx(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-
-	arc_serial_tx_chars(uart);
+	arc_serial_tx_chars(port);
 }
 }
 
 
-static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
+static void arc_serial_rx_chars(struct uart_port *port, unsigned int status)
 {
 {
 	unsigned int ch, flg = 0;
 	unsigned int ch, flg = 0;
 
 
@@ -229,15 +221,15 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
 		 */
 		 */
 		if (unlikely(status & (RXOERR | RXFERR))) {
 		if (unlikely(status & (RXOERR | RXFERR))) {
 			if (status & RXOERR) {
 			if (status & RXOERR) {
-				uart->port.icount.overrun++;
+				port->icount.overrun++;
 				flg = TTY_OVERRUN;
 				flg = TTY_OVERRUN;
-				UART_CLR_STATUS(uart, RXOERR);
+				UART_CLR_STATUS(port, RXOERR);
 			}
 			}
 
 
 			if (status & RXFERR) {
 			if (status & RXFERR) {
-				uart->port.icount.frame++;
+				port->icount.frame++;
 				flg = TTY_FRAME;
 				flg = TTY_FRAME;
-				UART_CLR_STATUS(uart, RXFERR);
+				UART_CLR_STATUS(port, RXFERR);
 			}
 			}
 		} else
 		} else
 			flg = TTY_NORMAL;
 			flg = TTY_NORMAL;
@@ -245,16 +237,16 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
 		if (status & RXEMPTY)
 		if (status & RXEMPTY)
 			continue;
 			continue;
 
 
-		ch = UART_GET_DATA(uart);
-		uart->port.icount.rx++;
+		ch = UART_GET_DATA(port);
+		port->icount.rx++;
 
 
-		if (!(uart_handle_sysrq_char(&uart->port, ch)))
-			uart_insert_char(&uart->port, status, RXOERR, ch, flg);
+		if (!(uart_handle_sysrq_char(port, ch)))
+			uart_insert_char(port, status, RXOERR, ch, flg);
 
 
-		spin_unlock(&uart->port.lock);
-		tty_flip_buffer_push(&uart->port.state->port);
-		spin_lock(&uart->port.lock);
-	} while (!((status = UART_GET_STATUS(uart)) & RXEMPTY));
+		spin_unlock(&port->lock);
+		tty_flip_buffer_push(&port->state->port);
+		spin_lock(&port->lock);
+	} while (!((status = UART_GET_STATUS(port)) & RXEMPTY));
 }
 }
 
 
 /*
 /*
@@ -287,10 +279,10 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
 
 
 static irqreturn_t arc_serial_isr(int irq, void *dev_id)
 static irqreturn_t arc_serial_isr(int irq, void *dev_id)
 {
 {
-	struct arc_uart_port *uart = dev_id;
+	struct uart_port *port = dev_id;
 	unsigned int status;
 	unsigned int status;
 
 
-	status = UART_GET_STATUS(uart);
+	status = UART_GET_STATUS(port);
 
 
 	/*
 	/*
 	 * Single IRQ for both Rx (data available) Tx (room available) Interrupt
 	 * Single IRQ for both Rx (data available) Tx (room available) Interrupt
@@ -300,9 +292,9 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
 	if (status & RXIENB) {
 	if (status & RXIENB) {
 
 
 		/* already in ISR, no need of xx_irqsave */
 		/* already in ISR, no need of xx_irqsave */
-		spin_lock(&uart->port.lock);
-		arc_serial_rx_chars(uart, status);
-		spin_unlock(&uart->port.lock);
+		spin_lock(&port->lock);
+		arc_serial_rx_chars(port, status);
+		spin_unlock(&port->lock);
 	}
 	}
 
 
 	if ((status & TXIENB) && (status & TXEMPTY)) {
 	if ((status & TXIENB) && (status & TXEMPTY)) {
@@ -310,14 +302,14 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
 		/* Unconditionally disable further Tx-Interrupts.
 		/* Unconditionally disable further Tx-Interrupts.
 		 * will be enabled by tx_chars() if needed.
 		 * will be enabled by tx_chars() if needed.
 		 */
 		 */
-		UART_TX_IRQ_DISABLE(uart);
+		UART_TX_IRQ_DISABLE(port);
 
 
-		spin_lock(&uart->port.lock);
+		spin_lock(&port->lock);
 
 
-		if (!uart_tx_stopped(&uart->port))
-			arc_serial_tx_chars(uart);
+		if (!uart_tx_stopped(port))
+			arc_serial_tx_chars(port);
 
 
-		spin_unlock(&uart->port.lock);
+		spin_unlock(&port->lock);
 	}
 	}
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
@@ -340,13 +332,6 @@ static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	/* MCR not present */
 	/* MCR not present */
 }
 }
 
 
-/* Enable Modem Status Interrupts */
-
-static void arc_serial_enable_ms(struct uart_port *port)
-{
-	/* MSR not present */
-}
-
 static void arc_serial_break_ctl(struct uart_port *port, int break_state)
 static void arc_serial_break_ctl(struct uart_port *port, int break_state)
 {
 {
 	/* ARC UART doesn't support sending Break signal */
 	/* ARC UART doesn't support sending Break signal */
@@ -354,18 +339,15 @@ static void arc_serial_break_ctl(struct uart_port *port, int break_state)
 
 
 static int arc_serial_startup(struct uart_port *port)
 static int arc_serial_startup(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-
 	/* Before we hook up the ISR, Disable all UART Interrupts */
 	/* Before we hook up the ISR, Disable all UART Interrupts */
-	UART_ALL_IRQ_DISABLE(uart);
+	UART_ALL_IRQ_DISABLE(port);
 
 
-	if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
-			uart)) {
-		dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
+	if (request_irq(port->irq, arc_serial_isr, 0, "arc uart rx-tx", port)) {
+		dev_warn(port->dev, "Unable to attach ARC UART intr\n");
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 
 
-	UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
+	UART_RX_IRQ_ENABLE(port); /* Only Rx IRQ enabled to begin with */
 
 
 	return 0;
 	return 0;
 }
 }
@@ -373,8 +355,7 @@ static int arc_serial_startup(struct uart_port *port)
 /* This is not really needed */
 /* This is not really needed */
 static void arc_serial_shutdown(struct uart_port *port)
 static void arc_serial_shutdown(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-	free_irq(uart->port.irq, uart);
+	free_irq(port->irq, port);
 }
 }
 
 
 static void
 static void
@@ -398,25 +379,14 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
 	uartl = hw_val & 0xFF;
 	uartl = hw_val & 0xFF;
 	uarth = (hw_val >> 8) & 0xFF;
 	uarth = (hw_val >> 8) & 0xFF;
 
 
-	/*
-	 * UART ISS(Instruction Set simulator) emulation has a subtle bug:
-	 * A existing value of Baudh = 0 is used as a indication to startup
-	 * it's internal state machine.
-	 * Thus if baudh is set to 0, 2 times, it chokes.
-	 * This happens with BAUD=115200 and the formaula above
-	 * Until that is fixed, when running on ISS, we will set baudh to !0
-	 */
-	if (uart->is_emulated)
-		uarth = 1;
-
 	spin_lock_irqsave(&port->lock, flags);
 	spin_lock_irqsave(&port->lock, flags);
 
 
-	UART_ALL_IRQ_DISABLE(uart);
+	UART_ALL_IRQ_DISABLE(port);
 
 
-	UART_SET_BAUDL(uart, uartl);
-	UART_SET_BAUDH(uart, uarth);
+	UART_SET_BAUDL(port, uartl);
+	UART_SET_BAUDH(port, uarth);
 
 
-	UART_RX_IRQ_ENABLE(uart);
+	UART_RX_IRQ_ENABLE(port);
 
 
 	/*
 	/*
 	 * UART doesn't support Parity/Hardware Flow Control;
 	 * UART doesn't support Parity/Hardware Flow Control;
@@ -439,9 +409,7 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
 
 
 static const char *arc_serial_type(struct uart_port *port)
 static const char *arc_serial_type(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-
-	return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
+	return port->type == PORT_ARC ? DRIVER_NAME : NULL;
 }
 }
 
 
 static void arc_serial_release_port(struct uart_port *port)
 static void arc_serial_release_port(struct uart_port *port)
@@ -470,35 +438,28 @@ arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
  */
  */
 static void arc_serial_config_port(struct uart_port *port, int flags)
 static void arc_serial_config_port(struct uart_port *port, int flags)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-
 	if (flags & UART_CONFIG_TYPE)
 	if (flags & UART_CONFIG_TYPE)
-		uart->port.type = PORT_ARC;
+		port->type = PORT_ARC;
 }
 }
 
 
-#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)
+#ifdef CONFIG_CONSOLE_POLL
 
 
 static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
 static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
-
-	while (!(UART_GET_STATUS(uart) & TXEMPTY))
+	while (!(UART_GET_STATUS(port) & TXEMPTY))
 		cpu_relax();
 		cpu_relax();
 
 
-	UART_SET_DATA(uart, chr);
+	UART_SET_DATA(port, chr);
 }
 }
-#endif
 
 
-#ifdef CONFIG_CONSOLE_POLL
 static int arc_serial_poll_getchar(struct uart_port *port)
 static int arc_serial_poll_getchar(struct uart_port *port)
 {
 {
-	struct arc_uart_port *uart = to_arc_port(port);
 	unsigned char chr;
 	unsigned char chr;
 
 
-	while (!(UART_GET_STATUS(uart) & RXEMPTY))
+	while (!(UART_GET_STATUS(port) & RXEMPTY))
 		cpu_relax();
 		cpu_relax();
 
 
-	chr = UART_GET_DATA(uart);
+	chr = UART_GET_DATA(port);
 	return chr;
 	return chr;
 }
 }
 #endif
 #endif
@@ -510,7 +471,6 @@ static struct uart_ops arc_serial_pops = {
 	.stop_tx	= arc_serial_stop_tx,
 	.stop_tx	= arc_serial_stop_tx,
 	.start_tx	= arc_serial_start_tx,
 	.start_tx	= arc_serial_start_tx,
 	.stop_rx	= arc_serial_stop_rx,
 	.stop_rx	= arc_serial_stop_rx,
-	.enable_ms	= arc_serial_enable_ms,
 	.break_ctl	= arc_serial_break_ctl,
 	.break_ctl	= arc_serial_break_ctl,
 	.startup	= arc_serial_startup,
 	.startup	= arc_serial_startup,
 	.shutdown	= arc_serial_shutdown,
 	.shutdown	= arc_serial_shutdown,
@@ -526,71 +486,6 @@ static struct uart_ops arc_serial_pops = {
 #endif
 #endif
 };
 };
 
 
-static int
-arc_uart_init_one(struct platform_device *pdev, int dev_id)
-{
-	struct resource *res, *res2;
-	unsigned long *plat_data;
-	struct arc_uart_port *uart = &arc_uart_ports[dev_id];
-
-	plat_data = dev_get_platdata(&pdev->dev);
-	if (!plat_data)
-		return -ENODEV;
-
-	uart->is_emulated = !!plat_data[0];	/* workaround ISS bug */
-
-	if (is_early_platform_device(pdev)) {
-		uart->port.uartclk = plat_data[1];
-		uart->baud = plat_data[2];
-	} else {
-		struct device_node *np = pdev->dev.of_node;
-		u32 val;
-
-		if (of_property_read_u32(np, "clock-frequency", &val)) {
-			dev_err(&pdev->dev, "clock-frequency property NOTset\n");
-			return -EINVAL;
-		}
-		uart->port.uartclk = val;
-
-		if (of_property_read_u32(np, "current-speed", &val)) {
-			dev_err(&pdev->dev, "current-speed property NOT set\n");
-			return -EINVAL;
-		}
-		uart->baud = val;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
-	res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res2)
-		return -ENODEV;
-
-	uart->port.mapbase = res->start;
-	uart->port.membase = ioremap_nocache(res->start, resource_size(res));
-	if (!uart->port.membase)
-		/* No point of dev_err since UART itself is hosed here */
-		return -ENXIO;
-
-	uart->port.irq = res2->start;
-	uart->port.dev = &pdev->dev;
-	uart->port.iotype = UPIO_MEM;
-	uart->port.flags = UPF_BOOT_AUTOCONF;
-	uart->port.line = dev_id;
-	uart->port.ops = &arc_serial_pops;
-
-	uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
-
-	/*
-	 * uart_insert_char( ) uses it in decideding whether to ignore a
-	 * char or not. Explicitly setting it here, removes the subtelty
-	 */
-	uart->port.ignore_status_mask = 0;
-
-	return 0;
-}
-
 #ifdef CONFIG_SERIAL_ARC_CONSOLE
 #ifdef CONFIG_SERIAL_ARC_CONSOLE
 
 
 static int arc_serial_console_setup(struct console *co, char *options)
 static int arc_serial_console_setup(struct console *co, char *options)
@@ -624,7 +519,10 @@ static int arc_serial_console_setup(struct console *co, char *options)
 
 
 static void arc_serial_console_putchar(struct uart_port *port, int ch)
 static void arc_serial_console_putchar(struct uart_port *port, int ch)
 {
 {
-	arc_serial_poll_putchar(port, (unsigned char)ch);
+	while (!(UART_GET_STATUS(port) & TXEMPTY))
+		cpu_relax();
+
+	UART_SET_DATA(port, (unsigned char)ch);
 }
 }
 
 
 /*
 /*
@@ -651,48 +549,45 @@ static struct console arc_console = {
 	.data	= &arc_uart_driver
 	.data	= &arc_uart_driver
 };
 };
 
 
-static __init void early_serial_write(struct console *con, const char *s,
-					unsigned int n)
+static __init void arc_early_serial_write(struct console *con, const char *s,
+					  unsigned int n)
 {
 {
-	struct uart_port *port = &arc_uart_ports[con->index].port;
-	unsigned int i;
+	struct earlycon_device *dev = con->data;
 
 
-	for (i = 0; i < n; i++, s++) {
-		if (*s == '\n')
-			arc_serial_poll_putchar(port, '\r');
-		arc_serial_poll_putchar(port, *s);
-	}
+	uart_console_write(&dev->port, s, n, arc_serial_console_putchar);
 }
 }
 
 
-static struct console arc_early_serial_console __initdata = {
-	.name = "early_ARCuart",
-	.write = early_serial_write,
-	.flags = CON_PRINTBUFFER | CON_BOOT,
-	.index = -1
-};
-
-static int __init arc_serial_probe_earlyprintk(struct platform_device *pdev)
+static int __init arc_early_console_setup(struct earlycon_device *dev,
+					  const char *opt)
 {
 {
-	int dev_id = pdev->id < 0 ? 0 : pdev->id;
-	int rc;
+	struct uart_port *port = &dev->port;
+	unsigned int l, h, hw_val;
 
 
-	arc_early_serial_console.index = dev_id;
+	if (!dev->port.membase)
+		return -ENODEV;
 
 
-	rc = arc_uart_init_one(pdev, dev_id);
-	if (rc)
-		panic("early console init failed\n");
+	hw_val = port->uartclk / (dev->baud * 4) - 1;
+	l = hw_val & 0xFF;
+	h = (hw_val >> 8) & 0xFF;
 
 
-	arc_serial_console_setup(&arc_early_serial_console, NULL);
+	UART_SET_BAUDL(port, l);
+	UART_SET_BAUDH(port, h);
 
 
-	register_console(&arc_early_serial_console);
+	dev->con->write = arc_early_serial_write;
 	return 0;
 	return 0;
 }
 }
+EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
+OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup);
+
 #endif	/* CONFIG_SERIAL_ARC_CONSOLE */
 #endif	/* CONFIG_SERIAL_ARC_CONSOLE */
 
 
 static int arc_serial_probe(struct platform_device *pdev)
 static int arc_serial_probe(struct platform_device *pdev)
 {
 {
-	int rc, dev_id;
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *np = pdev->dev.of_node;
+	struct arc_uart_port *uart;
+	struct uart_port *port;
+	int dev_id;
+	u32 val;
 
 
 	/* no device tree device */
 	/* no device tree device */
 	if (!np)
 	if (!np)
@@ -702,12 +597,43 @@ static int arc_serial_probe(struct platform_device *pdev)
 	if (dev_id < 0)
 	if (dev_id < 0)
 		dev_id = 0;
 		dev_id = 0;
 
 
-	rc = arc_uart_init_one(pdev, dev_id);
-	if (rc)
-		return rc;
+	uart = &arc_uart_ports[dev_id];
+	port = &uart->port;
+
+	if (of_property_read_u32(np, "clock-frequency", &val)) {
+		dev_err(&pdev->dev, "clock-frequency property NOTset\n");
+		return -EINVAL;
+	}
+	port->uartclk = val;
+
+	if (of_property_read_u32(np, "current-speed", &val)) {
+		dev_err(&pdev->dev, "current-speed property NOT set\n");
+		return -EINVAL;
+	}
+	uart->baud = val;
+
+	port->membase = of_iomap(np, 0);
+	if (!port->membase)
+		/* No point of dev_err since UART itself is hosed here */
+		return -ENXIO;
+
+	port->irq = irq_of_parse_and_map(np, 0);
 
 
-	rc = uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
-	return rc;
+	port->dev = &pdev->dev;
+	port->iotype = UPIO_MEM;
+	port->flags = UPF_BOOT_AUTOCONF;
+	port->line = dev_id;
+	port->ops = &arc_serial_pops;
+
+	port->fifosize = ARC_UART_TX_FIFO_SIZE;
+
+	/*
+	 * uart_insert_char( ) uses it in decideding whether to ignore a
+	 * char or not. Explicitly setting it here, removes the subtelty
+	 */
+	port->ignore_status_mask = 0;
+
+	return uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
 }
 }
 
 
 static int arc_serial_remove(struct platform_device *pdev)
 static int arc_serial_remove(struct platform_device *pdev)
@@ -732,27 +658,6 @@ static struct platform_driver arc_platform_driver = {
 	 },
 	 },
 };
 };
 
 
-#ifdef CONFIG_SERIAL_ARC_CONSOLE
-
-static struct platform_driver early_arc_platform_driver __initdata = {
-	.probe = arc_serial_probe_earlyprintk,
-	.remove = arc_serial_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
-	 },
-};
-/*
- * Register an early platform driver of "earlyprintk" class.
- * ARCH platform code installs the driver and probes the early devices
- * The installation could rely on user specifying earlyprintk=xyx in cmd line
- * or it could be done independently, for all "earlyprintk" class drivers.
- * [see arch/arc/plat-arcfpga/platform.c]
- */
-early_platform_init("earlyprintk", &early_arc_platform_driver);
-
-#endif  /* CONFIG_SERIAL_ARC_CONSOLE */
-
 static int __init arc_serial_init(void)
 static int __init arc_serial_init(void)
 {
 {
 	int ret;
 	int ret;

+ 4 - 4
drivers/tty/serial/atmel_serial.c

@@ -706,7 +706,7 @@ static void atmel_release_tx_dma(struct uart_port *port)
 		dmaengine_terminate_all(chan);
 		dmaengine_terminate_all(chan);
 		dma_release_channel(chan);
 		dma_release_channel(chan);
 		dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1,
 		dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1,
-				DMA_MEM_TO_DEV);
+				DMA_TO_DEVICE);
 	}
 	}
 
 
 	atmel_port->desc_tx = NULL;
 	atmel_port->desc_tx = NULL;
@@ -804,7 +804,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
 	nent = dma_map_sg(port->dev,
 	nent = dma_map_sg(port->dev,
 				&atmel_port->sg_tx,
 				&atmel_port->sg_tx,
 				1,
 				1,
-				DMA_MEM_TO_DEV);
+				DMA_TO_DEVICE);
 
 
 	if (!nent) {
 	if (!nent) {
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		dev_dbg(port->dev, "need to release resource of dma\n");
@@ -883,7 +883,7 @@ static void atmel_release_rx_dma(struct uart_port *port)
 		dmaengine_terminate_all(chan);
 		dmaengine_terminate_all(chan);
 		dma_release_channel(chan);
 		dma_release_channel(chan);
 		dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1,
 		dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1,
-				DMA_DEV_TO_MEM);
+				DMA_FROM_DEVICE);
 	}
 	}
 
 
 	atmel_port->desc_rx = NULL;
 	atmel_port->desc_rx = NULL;
@@ -968,7 +968,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
 			nent = dma_map_sg(port->dev,
 			nent = dma_map_sg(port->dev,
 					&atmel_port->sg_rx,
 					&atmel_port->sg_rx,
 					1,
 					1,
-					DMA_DEV_TO_MEM);
+					DMA_FROM_DEVICE);
 
 
 	if (!nent) {
 	if (!nent) {
 		dev_dbg(port->dev, "need to release resource of dma\n");
 		dev_dbg(port->dev, "need to release resource of dma\n");

+ 8 - 9
drivers/tty/serial/bfin_sport_uart.c

@@ -426,11 +426,6 @@ static void sport_stop_rx(struct uart_port *port)
 	SSYNC();
 	SSYNC();
 }
 }
 
 
-static void sport_enable_ms(struct uart_port *port)
-{
-	pr_debug("%s enter\n", __func__);
-}
-
 static void sport_break_ctl(struct uart_port *port, int break_state)
 static void sport_break_ctl(struct uart_port *port, int break_state)
 {
 {
 	pr_debug("%s enter\n", __func__);
 	pr_debug("%s enter\n", __func__);
@@ -500,6 +495,13 @@ static void sport_set_termios(struct uart_port *port,
 
 
 	pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
 	pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
 
 
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
+	if (old == NULL && up->cts_pin != -1)
+		termios->c_cflag |= CRTSCTS;
+	else if (up->cts_pin == -1)
+		termios->c_cflag &= ~CRTSCTS;
+#endif
+
 	switch (termios->c_cflag & CSIZE) {
 	switch (termios->c_cflag & CSIZE) {
 	case CS8:
 	case CS8:
 		up->csize = 8;
 		up->csize = 8;
@@ -587,7 +589,6 @@ struct uart_ops sport_uart_ops = {
 	.stop_tx	= sport_stop_tx,
 	.stop_tx	= sport_stop_tx,
 	.start_tx	= sport_start_tx,
 	.start_tx	= sport_start_tx,
 	.stop_rx	= sport_stop_rx,
 	.stop_rx	= sport_stop_rx,
-	.enable_ms	= sport_enable_ms,
 	.break_ctl	= sport_break_ctl,
 	.break_ctl	= sport_break_ctl,
 	.startup	= sport_startup,
 	.startup	= sport_startup,
 	.shutdown	= sport_shutdown,
 	.shutdown	= sport_shutdown,
@@ -813,10 +814,8 @@ static int sport_uart_probe(struct platform_device *pdev)
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 		if (res == NULL)
 		if (res == NULL)
 			sport->cts_pin = -1;
 			sport->cts_pin = -1;
-		else {
+		else
 			sport->cts_pin = res->start;
 			sport->cts_pin = res->start;
-			sport->port.flags |= ASYNC_CTS_FLOW;
-		}
 
 
 		res = platform_get_resource(pdev, IORESOURCE_IO, 1);
 		res = platform_get_resource(pdev, IORESOURCE_IO, 1);
 		if (res == NULL)
 		if (res == NULL)

+ 8 - 14
drivers/tty/serial/bfin_uart.c

@@ -200,14 +200,6 @@ static void bfin_serial_stop_rx(struct uart_port *port)
 	UART_CLEAR_IER(uart, ERBFI);
 	UART_CLEAR_IER(uart, ERBFI);
 }
 }
 
 
-/*
- * Set the modem control timer to fire immediately.
- */
-static void bfin_serial_enable_ms(struct uart_port *port)
-{
-}
-
-
 #if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
 #if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
 # define UART_GET_ANOMALY_THRESHOLD(uart)    ((uart)->anomaly_threshold)
 # define UART_GET_ANOMALY_THRESHOLD(uart)    ((uart)->anomaly_threshold)
 # define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
 # define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
@@ -793,6 +785,13 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned int ier, lcr = 0;
 	unsigned int ier, lcr = 0;
 	unsigned long timeout;
 	unsigned long timeout;
 
 
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+	if (old == NULL && uart->cts_pin != -1)
+		termios->c_cflag |= CRTSCTS;
+	else if (uart->cts_pin == -1)
+		termios->c_cflag &= ~CRTSCTS;
+#endif
+
 	switch (termios->c_cflag & CSIZE) {
 	switch (termios->c_cflag & CSIZE) {
 	case CS8:
 	case CS8:
 		lcr = WLS(8);
 		lcr = WLS(8);
@@ -1014,7 +1013,6 @@ static struct uart_ops bfin_serial_pops = {
 	.stop_tx	= bfin_serial_stop_tx,
 	.stop_tx	= bfin_serial_stop_tx,
 	.start_tx	= bfin_serial_start_tx,
 	.start_tx	= bfin_serial_start_tx,
 	.stop_rx	= bfin_serial_stop_rx,
 	.stop_rx	= bfin_serial_stop_rx,
-	.enable_ms	= bfin_serial_enable_ms,
 	.break_ctl	= bfin_serial_break_ctl,
 	.break_ctl	= bfin_serial_break_ctl,
 	.startup	= bfin_serial_startup,
 	.startup	= bfin_serial_startup,
 	.shutdown	= bfin_serial_shutdown,
 	.shutdown	= bfin_serial_shutdown,
@@ -1325,12 +1323,8 @@ static int bfin_serial_probe(struct platform_device *pdev)
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 		if (res == NULL)
 		if (res == NULL)
 			uart->cts_pin = -1;
 			uart->cts_pin = -1;
-		else {
+		else
 			uart->cts_pin = res->start;
 			uart->cts_pin = res->start;
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-			uart->port.flags |= ASYNC_CTS_FLOW;
-#endif
-		}
 
 
 		res = platform_get_resource(pdev, IORESOURCE_IO, 1);
 		res = platform_get_resource(pdev, IORESOURCE_IO, 1);
 		if (res == NULL)
 		if (res == NULL)

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

@@ -352,7 +352,6 @@ static const struct uart_ops uart_clps711x_ops = {
 	.stop_tx	= uart_clps711x_stop_tx,
 	.stop_tx	= uart_clps711x_stop_tx,
 	.start_tx	= uart_clps711x_start_tx,
 	.start_tx	= uart_clps711x_start_tx,
 	.stop_rx	= uart_clps711x_nop_void,
 	.stop_rx	= uart_clps711x_nop_void,
-	.enable_ms	= uart_clps711x_nop_void,
 	.break_ctl	= uart_clps711x_break_ctl,
 	.break_ctl	= uart_clps711x_break_ctl,
 	.set_ldisc	= uart_clps711x_set_ldisc,
 	.set_ldisc	= uart_clps711x_set_ldisc,
 	.startup	= uart_clps711x_startup,
 	.startup	= uart_clps711x_startup,

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

@@ -201,14 +201,6 @@ static void cpm_uart_stop_rx(struct uart_port *port)
 		clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
 		clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
 }
 }
 
 
-/*
- * Enable Modem status interrupts
- */
-static void cpm_uart_enable_ms(struct uart_port *port)
-{
-	pr_debug("CPM uart[%d]:enable ms\n", port->line);
-}
-
 /*
 /*
  * Generate a break.
  * Generate a break.
  */
  */
@@ -1122,7 +1114,6 @@ static struct uart_ops cpm_uart_pops = {
 	.stop_tx	= cpm_uart_stop_tx,
 	.stop_tx	= cpm_uart_stop_tx,
 	.start_tx	= cpm_uart_start_tx,
 	.start_tx	= cpm_uart_start_tx,
 	.stop_rx	= cpm_uart_stop_rx,
 	.stop_rx	= cpm_uart_stop_rx,
-	.enable_ms	= cpm_uart_enable_ms,
 	.break_ctl	= cpm_uart_break_ctl,
 	.break_ctl	= cpm_uart_break_ctl,
 	.startup	= cpm_uart_startup,
 	.startup	= cpm_uart_startup,
 	.shutdown	= cpm_uart_shutdown,
 	.shutdown	= cpm_uart_shutdown,

+ 5 - 10
drivers/tty/serial/crisv10.c

@@ -3831,14 +3831,13 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	DECLARE_WAITQUEUE(wait, current);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long	flags;
 	unsigned long	flags;
 	int		retval;
 	int		retval;
-	int		do_clocal = 0, extra_count = 0;
+	int		do_clocal = 0;
 
 
 	/*
 	/*
 	 * If the device is in the middle of being closed, then block
 	 * If the device is in the middle of being closed, then block
 	 * until it's done, and then try again.
 	 * until it's done, and then try again.
 	 */
 	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->port.flags & ASYNC_CLOSING)) {
+	if (info->port.flags & ASYNC_CLOSING) {
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 			!(info->port.flags & ASYNC_CLOSING));
 			!(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
 #ifdef SERIAL_DO_RESTART
@@ -3879,10 +3878,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	       info->line, info->port.count);
 	       info->line, info->port.count);
 #endif
 #endif
 	local_irq_save(flags);
 	local_irq_save(flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count++;
-		info->port.count--;
-	}
+	info->port.count--;
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 	info->port.blocked_open++;
 	info->port.blocked_open++;
 	while (1) {
 	while (1) {
@@ -3921,7 +3917,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	}
 	}
 	set_current_state(TASK_RUNNING);
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&info->port.open_wait, &wait);
 	remove_wait_queue(&info->port.open_wait, &wait);
-	if (extra_count)
+	if (!tty_hung_up_p(filp))
 		info->port.count++;
 		info->port.count++;
 	info->port.blocked_open--;
 	info->port.blocked_open--;
 #ifdef SERIAL_DEBUG_OPEN
 #ifdef SERIAL_DEBUG_OPEN
@@ -3976,8 +3972,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
 	/*
 	/*
 	 * If the port is in the middle of closing, bail out now
 	 * If the port is in the middle of closing, bail out now
 	 */
 	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->port.flags & ASYNC_CLOSING)) {
+	if (info->port.flags & ASYNC_CLOSING) {
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 			!(info->port.flags & ASYNC_CLOSING));
 			!(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
 #ifdef SERIAL_DO_RESTART

+ 0 - 6
drivers/tty/serial/dz.c

@@ -151,11 +151,6 @@ static void dz_stop_rx(struct uart_port *uport)
 	dz_out(dport, DZ_LPR, dport->cflag);
 	dz_out(dport, DZ_LPR, dport->cflag);
 }
 }
 
 
-static void dz_enable_ms(struct uart_port *uport)
-{
-	/* nothing to do */
-}
-
 /*
 /*
  * ------------------------------------------------------------
  * ------------------------------------------------------------
  *
  *
@@ -751,7 +746,6 @@ static struct uart_ops dz_ops = {
 	.stop_tx	= dz_stop_tx,
 	.stop_tx	= dz_stop_tx,
 	.start_tx	= dz_start_tx,
 	.start_tx	= dz_start_tx,
 	.stop_rx	= dz_stop_rx,
 	.stop_rx	= dz_stop_rx,
-	.enable_ms	= dz_enable_ms,
 	.break_ctl	= dz_break_ctl,
 	.break_ctl	= dz_break_ctl,
 	.startup	= dz_startup,
 	.startup	= dz_startup,
 	.shutdown	= dz_shutdown,
 	.shutdown	= dz_shutdown,

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

@@ -185,11 +185,6 @@ static void efm32_uart_stop_rx(struct uart_port *port)
 	efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD);
 	efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD);
 }
 }
 
 
-static void efm32_uart_enable_ms(struct uart_port *port)
-{
-	/* no handshake lines, no modem status interrupts */
-}
-
 static void efm32_uart_break_ctl(struct uart_port *port, int ctl)
 static void efm32_uart_break_ctl(struct uart_port *port, int ctl)
 {
 {
 	/* not possible without fiddling with gpios */
 	/* not possible without fiddling with gpios */
@@ -499,7 +494,6 @@ static struct uart_ops efm32_uart_pops = {
 	.stop_tx = efm32_uart_stop_tx,
 	.stop_tx = efm32_uart_stop_tx,
 	.start_tx = efm32_uart_start_tx,
 	.start_tx = efm32_uart_start_tx,
 	.stop_rx = efm32_uart_stop_rx,
 	.stop_rx = efm32_uart_stop_rx,
-	.enable_ms = efm32_uart_enable_ms,
 	.break_ctl = efm32_uart_break_ctl,
 	.break_ctl = efm32_uart_break_ctl,
 	.startup = efm32_uart_startup,
 	.startup = efm32_uart_startup,
 	.shutdown = efm32_uart_shutdown,
 	.shutdown = efm32_uart_shutdown,
@@ -671,10 +665,16 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
 	if (!np)
 	if (!np)
 		return 1;
 		return 1;
 
 
-	ret = of_property_read_u32(np, "efm32,location", &location);
+	ret = of_property_read_u32(np, "energymicro,location", &location);
+
+	if (ret)
+		/* fall back to wrongly namespaced property */
+		ret = of_property_read_u32(np, "efm32,location", &location);
+
 	if (ret)
 	if (ret)
 		/* fall back to old and (wrongly) generic property "location" */
 		/* fall back to old and (wrongly) generic property "location" */
 		ret = of_property_read_u32(np, "location", &location);
 		ret = of_property_read_u32(np, "location", &location);
+
 	if (!ret) {
 	if (!ret) {
 		if (location > 5) {
 		if (location > 5) {
 			dev_err(&pdev->dev, "invalid location\n");
 			dev_err(&pdev->dev, "invalid location\n");

+ 658 - 31
drivers/tty/serial/fsl_lpuart.c

@@ -1,7 +1,7 @@
 /*
 /*
  *  Freescale lpuart serial port driver
  *  Freescale lpuart serial port driver
  *
  *
- *  Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *  Copyright 2012-2014 Freescale Semiconductor, Inc.
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -117,8 +117,113 @@
 #define UARTSFIFO_TXOF		0x02
 #define UARTSFIFO_TXOF		0x02
 #define UARTSFIFO_RXUF		0x01
 #define UARTSFIFO_RXUF		0x01
 
 
-#define DMA_MAXBURST		16
-#define DMA_MAXBURST_MASK	(DMA_MAXBURST - 1)
+/* 32-bit register defination */
+#define UARTBAUD		0x00
+#define UARTSTAT		0x04
+#define UARTCTRL		0x08
+#define UARTDATA		0x0C
+#define UARTMATCH		0x10
+#define UARTMODIR		0x14
+#define UARTFIFO		0x18
+#define UARTWATER		0x1c
+
+#define UARTBAUD_MAEN1		0x80000000
+#define UARTBAUD_MAEN2		0x40000000
+#define UARTBAUD_M10		0x20000000
+#define UARTBAUD_TDMAE		0x00800000
+#define UARTBAUD_RDMAE		0x00200000
+#define UARTBAUD_MATCFG		0x00400000
+#define UARTBAUD_BOTHEDGE	0x00020000
+#define UARTBAUD_RESYNCDIS	0x00010000
+#define UARTBAUD_LBKDIE		0x00008000
+#define UARTBAUD_RXEDGIE	0x00004000
+#define UARTBAUD_SBNS		0x00002000
+#define UARTBAUD_SBR		0x00000000
+#define UARTBAUD_SBR_MASK	0x1fff
+
+#define UARTSTAT_LBKDIF		0x80000000
+#define UARTSTAT_RXEDGIF	0x40000000
+#define UARTSTAT_MSBF		0x20000000
+#define UARTSTAT_RXINV		0x10000000
+#define UARTSTAT_RWUID		0x08000000
+#define UARTSTAT_BRK13		0x04000000
+#define UARTSTAT_LBKDE		0x02000000
+#define UARTSTAT_RAF		0x01000000
+#define UARTSTAT_TDRE		0x00800000
+#define UARTSTAT_TC		0x00400000
+#define UARTSTAT_RDRF		0x00200000
+#define UARTSTAT_IDLE		0x00100000
+#define UARTSTAT_OR		0x00080000
+#define UARTSTAT_NF		0x00040000
+#define UARTSTAT_FE		0x00020000
+#define UARTSTAT_PE		0x00010000
+#define UARTSTAT_MA1F		0x00008000
+#define UARTSTAT_M21F		0x00004000
+
+#define UARTCTRL_R8T9		0x80000000
+#define UARTCTRL_R9T8		0x40000000
+#define UARTCTRL_TXDIR		0x20000000
+#define UARTCTRL_TXINV		0x10000000
+#define UARTCTRL_ORIE		0x08000000
+#define UARTCTRL_NEIE		0x04000000
+#define UARTCTRL_FEIE		0x02000000
+#define UARTCTRL_PEIE		0x01000000
+#define UARTCTRL_TIE		0x00800000
+#define UARTCTRL_TCIE		0x00400000
+#define UARTCTRL_RIE		0x00200000
+#define UARTCTRL_ILIE		0x00100000
+#define UARTCTRL_TE		0x00080000
+#define UARTCTRL_RE		0x00040000
+#define UARTCTRL_RWU		0x00020000
+#define UARTCTRL_SBK		0x00010000
+#define UARTCTRL_MA1IE		0x00008000
+#define UARTCTRL_MA2IE		0x00004000
+#define UARTCTRL_IDLECFG	0x00000100
+#define UARTCTRL_LOOPS		0x00000080
+#define UARTCTRL_DOZEEN		0x00000040
+#define UARTCTRL_RSRC		0x00000020
+#define UARTCTRL_M		0x00000010
+#define UARTCTRL_WAKE		0x00000008
+#define UARTCTRL_ILT		0x00000004
+#define UARTCTRL_PE		0x00000002
+#define UARTCTRL_PT		0x00000001
+
+#define UARTDATA_NOISY		0x00008000
+#define UARTDATA_PARITYE	0x00004000
+#define UARTDATA_FRETSC		0x00002000
+#define UARTDATA_RXEMPT		0x00001000
+#define UARTDATA_IDLINE		0x00000800
+#define UARTDATA_MASK		0x3ff
+
+#define UARTMODIR_IREN		0x00020000
+#define UARTMODIR_TXCTSSRC	0x00000020
+#define UARTMODIR_TXCTSC	0x00000010
+#define UARTMODIR_RXRTSE	0x00000008
+#define UARTMODIR_TXRTSPOL	0x00000004
+#define UARTMODIR_TXRTSE	0x00000002
+#define UARTMODIR_TXCTSE	0x00000001
+
+#define UARTFIFO_TXEMPT		0x00800000
+#define UARTFIFO_RXEMPT		0x00400000
+#define UARTFIFO_TXOF		0x00020000
+#define UARTFIFO_RXUF		0x00010000
+#define UARTFIFO_TXFLUSH	0x00008000
+#define UARTFIFO_RXFLUSH	0x00004000
+#define UARTFIFO_TXOFE		0x00000200
+#define UARTFIFO_RXUFE		0x00000100
+#define UARTFIFO_TXFE		0x00000080
+#define UARTFIFO_FIFOSIZE_MASK	0x7
+#define UARTFIFO_TXSIZE_OFF	4
+#define UARTFIFO_RXFE		0x00000008
+#define UARTFIFO_RXSIZE_OFF	0
+
+#define UARTWATER_COUNT_MASK	0xff
+#define UARTWATER_TXCNT_OFF	8
+#define UARTWATER_RXCNT_OFF	24
+#define UARTWATER_WATER_MASK	0xff
+#define UARTWATER_TXWATER_OFF	0
+#define UARTWATER_RXWATER_OFF	16
+
 #define FSL_UART_RX_DMA_BUFFER_SIZE	64
 #define FSL_UART_RX_DMA_BUFFER_SIZE	64
 
 
 #define DRIVER_NAME	"fsl-lpuart"
 #define DRIVER_NAME	"fsl-lpuart"
@@ -130,6 +235,7 @@ struct lpuart_port {
 	struct clk		*clk;
 	struct clk		*clk;
 	unsigned int		txfifo_size;
 	unsigned int		txfifo_size;
 	unsigned int		rxfifo_size;
 	unsigned int		rxfifo_size;
+	bool			lpuart32;
 
 
 	bool			lpuart_dma_use;
 	bool			lpuart_dma_use;
 	struct dma_chan		*dma_tx_chan;
 	struct dma_chan		*dma_tx_chan;
@@ -154,6 +260,9 @@ static struct of_device_id lpuart_dt_ids[] = {
 	{
 	{
 		.compatible = "fsl,vf610-lpuart",
 		.compatible = "fsl,vf610-lpuart",
 	},
 	},
+	{
+		.compatible = "fsl,ls1021a-lpuart",
+	},
 	{ /* sentinel */ }
 	{ /* sentinel */ }
 };
 };
 MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
 MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
@@ -162,6 +271,16 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
 static void lpuart_dma_tx_complete(void *arg);
 static void lpuart_dma_tx_complete(void *arg);
 static void lpuart_dma_rx_complete(void *arg);
 static void lpuart_dma_rx_complete(void *arg);
 
 
+static u32 lpuart32_read(void __iomem *addr)
+{
+	return ioread32be(addr);
+}
+
+static void lpuart32_write(u32 val, void __iomem *addr)
+{
+	iowrite32be(val, addr);
+}
+
 static void lpuart_stop_tx(struct uart_port *port)
 static void lpuart_stop_tx(struct uart_port *port)
 {
 {
 	unsigned char temp;
 	unsigned char temp;
@@ -171,6 +290,15 @@ static void lpuart_stop_tx(struct uart_port *port)
 	writeb(temp, port->membase + UARTCR2);
 	writeb(temp, port->membase + UARTCR2);
 }
 }
 
 
+static void lpuart32_stop_tx(struct uart_port *port)
+{
+	unsigned long temp;
+
+	temp = lpuart32_read(port->membase + UARTCTRL);
+	temp &= ~(UARTCTRL_TIE | UARTCTRL_TCIE);
+	lpuart32_write(temp, port->membase + UARTCTRL);
+}
+
 static void lpuart_stop_rx(struct uart_port *port)
 static void lpuart_stop_rx(struct uart_port *port)
 {
 {
 	unsigned char temp;
 	unsigned char temp;
@@ -179,8 +307,12 @@ static void lpuart_stop_rx(struct uart_port *port)
 	writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2);
 	writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2);
 }
 }
 
 
-static void lpuart_enable_ms(struct uart_port *port)
+static void lpuart32_stop_rx(struct uart_port *port)
 {
 {
+	unsigned long temp;
+
+	temp = lpuart32_read(port->membase + UARTCTRL);
+	lpuart32_write(temp & ~UARTCTRL_RE, port->membase + UARTCTRL);
 }
 }
 
 
 static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
 static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
@@ -240,7 +372,7 @@ static int lpuart_dma_tx(struct lpuart_port *sport, unsigned long count)
 
 
 	dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
 	dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
-	sport->dma_tx_bytes = count & ~(DMA_MAXBURST_MASK);
+	sport->dma_tx_bytes = count & ~(sport->txfifo_size - 1);
 	tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
 	tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
 	sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
 	sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
 					tx_bus_addr, sport->dma_tx_bytes,
 					tx_bus_addr, sport->dma_tx_bytes,
@@ -269,7 +401,7 @@ static void lpuart_prepare_tx(struct lpuart_port *sport)
 	if (!count)
 	if (!count)
 		return;
 		return;
 
 
-	if (count < DMA_MAXBURST)
+	if (count < sport->txfifo_size)
 		writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
 		writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
 				sport->port.membase + UARTCR5);
 				sport->port.membase + UARTCR5);
 	else {
 	else {
@@ -405,6 +537,30 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
 		lpuart_stop_tx(&sport->port);
 		lpuart_stop_tx(&sport->port);
 }
 }
 
 
+static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
+{
+	struct circ_buf *xmit = &sport->port.state->xmit;
+	unsigned long txcnt;
+
+	txcnt = lpuart32_read(sport->port.membase + UARTWATER);
+	txcnt = txcnt >> UARTWATER_TXCNT_OFF;
+	txcnt &= UARTWATER_COUNT_MASK;
+	while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) {
+		lpuart32_write(xmit->buf[xmit->tail], sport->port.membase + UARTDATA);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		sport->port.icount.tx++;
+		txcnt = lpuart32_read(sport->port.membase + UARTWATER);
+		txcnt = txcnt >> UARTWATER_TXCNT_OFF;
+		txcnt &= UARTWATER_COUNT_MASK;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&sport->port);
+
+	if (uart_circ_empty(xmit))
+		lpuart32_stop_tx(&sport->port);
+}
+
 static void lpuart_start_tx(struct uart_port *port)
 static void lpuart_start_tx(struct uart_port *port)
 {
 {
 	struct lpuart_port *sport = container_of(port,
 	struct lpuart_port *sport = container_of(port,
@@ -424,6 +580,18 @@ static void lpuart_start_tx(struct uart_port *port)
 	}
 	}
 }
 }
 
 
+static void lpuart32_start_tx(struct uart_port *port)
+{
+	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+	unsigned long temp;
+
+	temp = lpuart32_read(port->membase + UARTCTRL);
+	lpuart32_write(temp | UARTCTRL_TIE, port->membase + UARTCTRL);
+
+	if (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE)
+		lpuart32_transmit_buffer(sport);
+}
+
 static irqreturn_t lpuart_txint(int irq, void *dev_id)
 static irqreturn_t lpuart_txint(int irq, void *dev_id)
 {
 {
 	struct lpuart_port *sport = dev_id;
 	struct lpuart_port *sport = dev_id;
@@ -432,16 +600,25 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
 
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 	spin_lock_irqsave(&sport->port.lock, flags);
 	if (sport->port.x_char) {
 	if (sport->port.x_char) {
-		writeb(sport->port.x_char, sport->port.membase + UARTDR);
+		if (sport->lpuart32)
+			lpuart32_write(sport->port.x_char, sport->port.membase + UARTDATA);
+		else
+			writeb(sport->port.x_char, sport->port.membase + UARTDR);
 		goto out;
 		goto out;
 	}
 	}
 
 
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-		lpuart_stop_tx(&sport->port);
+		if (sport->lpuart32)
+			lpuart32_stop_tx(&sport->port);
+		else
+			lpuart_stop_tx(&sport->port);
 		goto out;
 		goto out;
 	}
 	}
 
 
-	lpuart_transmit_buffer(sport);
+	if (sport->lpuart32)
+		lpuart32_transmit_buffer(sport);
+	else
+		lpuart_transmit_buffer(sport);
 
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&sport->port);
 		uart_write_wakeup(&sport->port);
@@ -514,6 +691,70 @@ out:
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
+{
+	struct lpuart_port *sport = dev_id;
+	unsigned int flg, ignored = 0;
+	struct tty_port *port = &sport->port.state->port;
+	unsigned long flags;
+	unsigned long rx, sr;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	while (!(lpuart32_read(sport->port.membase + UARTFIFO) & UARTFIFO_RXEMPT)) {
+		flg = TTY_NORMAL;
+		sport->port.icount.rx++;
+		/*
+		 * to clear the FE, OR, NF, FE, PE flags,
+		 * read STAT then read DATA reg
+		 */
+		sr = lpuart32_read(sport->port.membase + UARTSTAT);
+		rx = lpuart32_read(sport->port.membase + UARTDATA);
+		rx &= 0x3ff;
+
+		if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
+			continue;
+
+		if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) {
+			if (sr & UARTSTAT_PE)
+				sport->port.icount.parity++;
+			else if (sr & UARTSTAT_FE)
+				sport->port.icount.frame++;
+
+			if (sr & UARTSTAT_OR)
+				sport->port.icount.overrun++;
+
+			if (sr & sport->port.ignore_status_mask) {
+				if (++ignored > 100)
+					goto out;
+				continue;
+			}
+
+			sr &= sport->port.read_status_mask;
+
+			if (sr & UARTSTAT_PE)
+				flg = TTY_PARITY;
+			else if (sr & UARTSTAT_FE)
+				flg = TTY_FRAME;
+
+			if (sr & UARTSTAT_OR)
+				flg = TTY_OVERRUN;
+
+#ifdef SUPPORT_SYSRQ
+			sport->port.sysrq = 0;
+#endif
+		}
+
+		tty_insert_flip_char(port, rx, flg);
+	}
+
+out:
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+
+	tty_flip_buffer_push(port);
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t lpuart_int(int irq, void *dev_id)
 static irqreturn_t lpuart_int(int irq, void *dev_id)
 {
 {
 	struct lpuart_port *sport = dev_id;
 	struct lpuart_port *sport = dev_id;
@@ -538,6 +779,26 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+static irqreturn_t lpuart32_int(int irq, void *dev_id)
+{
+	struct lpuart_port *sport = dev_id;
+	unsigned long sts, rxcount;
+
+	sts = lpuart32_read(sport->port.membase + UARTSTAT);
+	rxcount = lpuart32_read(sport->port.membase + UARTWATER);
+	rxcount = rxcount >> UARTWATER_RXCNT_OFF;
+
+	if (sts & UARTSTAT_RDRF || rxcount > 0)
+		lpuart32_rxint(irq, dev_id);
+
+	if ((sts & UARTSTAT_TDRE) &&
+		!(lpuart32_read(sport->port.membase + UARTBAUD) & UARTBAUD_TDMAE))
+		lpuart_txint(irq, dev_id);
+
+	lpuart32_write(sts, sport->port.membase + UARTSTAT);
+	return IRQ_HANDLED;
+}
+
 /* return TIOCSER_TEMT when transmitter is not busy */
 /* return TIOCSER_TEMT when transmitter is not busy */
 static unsigned int lpuart_tx_empty(struct uart_port *port)
 static unsigned int lpuart_tx_empty(struct uart_port *port)
 {
 {
@@ -545,6 +806,12 @@ static unsigned int lpuart_tx_empty(struct uart_port *port)
 		TIOCSER_TEMT : 0;
 		TIOCSER_TEMT : 0;
 }
 }
 
 
+static unsigned int lpuart32_tx_empty(struct uart_port *port)
+{
+	return (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TC) ?
+		TIOCSER_TEMT : 0;
+}
+
 static unsigned int lpuart_get_mctrl(struct uart_port *port)
 static unsigned int lpuart_get_mctrl(struct uart_port *port)
 {
 {
 	unsigned int temp = 0;
 	unsigned int temp = 0;
@@ -560,6 +827,21 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port)
 	return temp;
 	return temp;
 }
 }
 
 
+static unsigned int lpuart32_get_mctrl(struct uart_port *port)
+{
+	unsigned int temp = 0;
+	unsigned long reg;
+
+	reg = lpuart32_read(port->membase + UARTMODIR);
+	if (reg & UARTMODIR_TXCTSE)
+		temp |= TIOCM_CTS;
+
+	if (reg & UARTMODIR_RXRTSE)
+		temp |= TIOCM_RTS;
+
+	return temp;
+}
+
 static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 {
 	unsigned char temp;
 	unsigned char temp;
@@ -576,6 +858,22 @@ static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	writeb(temp, port->membase + UARTMODEM);
 	writeb(temp, port->membase + UARTMODEM);
 }
 }
 
 
+static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	unsigned long temp;
+
+	temp = lpuart32_read(port->membase + UARTMODIR) &
+			~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
+
+	if (mctrl & TIOCM_RTS)
+		temp |= UARTMODIR_RXRTSE;
+
+	if (mctrl & TIOCM_CTS)
+		temp |= UARTMODIR_TXCTSE;
+
+	lpuart32_write(temp, port->membase + UARTMODIR);
+}
+
 static void lpuart_break_ctl(struct uart_port *port, int break_state)
 static void lpuart_break_ctl(struct uart_port *port, int break_state)
 {
 {
 	unsigned char temp;
 	unsigned char temp;
@@ -588,6 +886,18 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
 	writeb(temp, port->membase + UARTCR2);
 	writeb(temp, port->membase + UARTCR2);
 }
 }
 
 
+static void lpuart32_break_ctl(struct uart_port *port, int break_state)
+{
+	unsigned long temp;
+
+	temp = lpuart32_read(port->membase + UARTCTRL) & ~UARTCTRL_SBK;
+
+	if (break_state != 0)
+		temp |= UARTCTRL_SBK;
+
+	lpuart32_write(temp, port->membase + UARTCTRL);
+}
+
 static void lpuart_setup_watermark(struct lpuart_port *sport)
 static void lpuart_setup_watermark(struct lpuart_port *sport)
 {
 {
 	unsigned char val, cr2;
 	unsigned char val, cr2;
@@ -599,15 +909,7 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
 			UARTCR2_RIE | UARTCR2_RE);
 			UARTCR2_RIE | UARTCR2_RE);
 	writeb(cr2, sport->port.membase + UARTCR2);
 	writeb(cr2, sport->port.membase + UARTCR2);
 
 
-	/* determine FIFO size and enable FIFO mode */
 	val = readb(sport->port.membase + UARTPFIFO);
 	val = readb(sport->port.membase + UARTPFIFO);
-
-	sport->txfifo_size = 0x1 << (((val >> UARTPFIFO_TXSIZE_OFF) &
-		UARTPFIFO_FIFOSIZE_MASK) + 1);
-
-	sport->rxfifo_size = 0x1 << (((val >> UARTPFIFO_RXSIZE_OFF) &
-		UARTPFIFO_FIFOSIZE_MASK) + 1);
-
 	writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
 	writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
 			sport->port.membase + UARTPFIFO);
 			sport->port.membase + UARTPFIFO);
 
 
@@ -622,6 +924,31 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
 	writeb(cr2_saved, sport->port.membase + UARTCR2);
 	writeb(cr2_saved, sport->port.membase + UARTCR2);
 }
 }
 
 
+static void lpuart32_setup_watermark(struct lpuart_port *sport)
+{
+	unsigned long val, ctrl;
+	unsigned long ctrl_saved;
+
+	ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
+	ctrl_saved = ctrl;
+	ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_TE |
+			UARTCTRL_RIE | UARTCTRL_RE);
+	lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
+
+	/* enable FIFO mode */
+	val = lpuart32_read(sport->port.membase + UARTFIFO);
+	val |= UARTFIFO_TXFE | UARTFIFO_RXFE;
+	val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
+	lpuart32_write(val, sport->port.membase + UARTFIFO);
+
+	/* set the watermark */
+	val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
+	lpuart32_write(val, sport->port.membase + UARTWATER);
+
+	/* Restore cr2 */
+	lpuart32_write(ctrl_saved, sport->port.membase + UARTCTRL);
+}
+
 static int lpuart_dma_tx_request(struct uart_port *port)
 static int lpuart_dma_tx_request(struct uart_port *port)
 {
 {
 	struct lpuart_port *sport = container_of(port,
 	struct lpuart_port *sport = container_of(port,
@@ -652,7 +979,7 @@ static int lpuart_dma_tx_request(struct uart_port *port)
 	dma_buf = sport->port.state->xmit.buf;
 	dma_buf = sport->port.state->xmit.buf;
 	dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
 	dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
 	dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
 	dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-	dma_tx_sconfig.dst_maxburst = DMA_MAXBURST;
+	dma_tx_sconfig.dst_maxburst = sport->txfifo_size;
 	dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
 	dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
 	ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
 	ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
 
 
@@ -724,13 +1051,6 @@ static int lpuart_dma_rx_request(struct uart_port *port)
 	sport->dma_rx_buf_bus = dma_bus;
 	sport->dma_rx_buf_bus = dma_bus;
 	sport->dma_rx_in_progress = 0;
 	sport->dma_rx_in_progress = 0;
 
 
-	sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
-				FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
-				sport->rxfifo_size / 2;
-
-	if (sport->dma_rx_timeout < msecs_to_jiffies(20))
-		sport->dma_rx_timeout = msecs_to_jiffies(20);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -772,7 +1092,16 @@ static int lpuart_startup(struct uart_port *port)
 	unsigned long flags;
 	unsigned long flags;
 	unsigned char temp;
 	unsigned char temp;
 
 
-	/*whether use dma support by dma request results*/
+	/* determine FIFO size and enable FIFO mode */
+	temp = readb(sport->port.membase + UARTPFIFO);
+
+	sport->txfifo_size = 0x1 << (((temp >> UARTPFIFO_TXSIZE_OFF) &
+		UARTPFIFO_FIFOSIZE_MASK) + 1);
+
+	sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) &
+		UARTPFIFO_FIFOSIZE_MASK) + 1);
+
+	/* Whether use dma support by dma request results */
 	if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
 	if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
 		sport->lpuart_dma_use = false;
 		sport->lpuart_dma_use = false;
 	} else {
 	} else {
@@ -798,6 +1127,40 @@ static int lpuart_startup(struct uart_port *port)
 	return 0;
 	return 0;
 }
 }
 
 
+static int lpuart32_startup(struct uart_port *port)
+{
+	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+	int ret;
+	unsigned long flags;
+	unsigned long temp;
+
+	/* determine FIFO size */
+	temp = lpuart32_read(sport->port.membase + UARTFIFO);
+
+	sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) &
+		UARTFIFO_FIFOSIZE_MASK) - 1);
+
+	sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) &
+		UARTFIFO_FIFOSIZE_MASK) - 1);
+
+	ret = devm_request_irq(port->dev, port->irq, lpuart32_int, 0,
+				DRIVER_NAME, sport);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	lpuart32_setup_watermark(sport);
+
+	temp = lpuart32_read(sport->port.membase + UARTCTRL);
+	temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | UARTCTRL_TE);
+	temp |= UARTCTRL_ILIE;
+	lpuart32_write(temp, sport->port.membase + UARTCTRL);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+	return 0;
+}
+
 static void lpuart_shutdown(struct uart_port *port)
 static void lpuart_shutdown(struct uart_port *port)
 {
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@@ -822,6 +1185,25 @@ static void lpuart_shutdown(struct uart_port *port)
 	}
 	}
 }
 }
 
 
+static void lpuart32_shutdown(struct uart_port *port)
+{
+	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+	unsigned long temp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* disable Rx/Tx and interrupts */
+	temp = lpuart32_read(port->membase + UARTCTRL);
+	temp &= ~(UARTCTRL_TE | UARTCTRL_RE |
+			UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
+	lpuart32_write(temp, port->membase + UARTCTRL);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	devm_free_irq(port->dev, port->irq, sport);
+}
+
 static void
 static void
 lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 		   struct ktermios *old)
 		   struct ktermios *old)
@@ -922,6 +1304,17 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	/* update the per-port timeout */
 	/* update the per-port timeout */
 	uart_update_timeout(port, termios->c_cflag, baud);
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 
+	if (sport->lpuart_dma_use) {
+		/* Calculate delay for 1.5 DMA buffers */
+		sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
+					FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
+					sport->rxfifo_size / 2;
+		dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
+			sport->dma_rx_timeout * 1000 / HZ, sport->port.timeout);
+		if (sport->dma_rx_timeout < msecs_to_jiffies(20))
+			sport->dma_rx_timeout = msecs_to_jiffies(20);
+	}
+
 	/* wait transmit engin complete */
 	/* wait transmit engin complete */
 	while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
 	while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
 		barrier();
 		barrier();
@@ -948,6 +1341,125 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 }
 
 
+static void
+lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
+		   struct ktermios *old)
+{
+	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+	unsigned long flags;
+	unsigned long ctrl, old_ctrl, bd, modem;
+	unsigned int  baud;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+	unsigned int sbr;
+
+	ctrl = old_ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
+	bd = lpuart32_read(sport->port.membase + UARTBAUD);
+	modem = lpuart32_read(sport->port.membase + UARTMODIR);
+	/*
+	 * only support CS8 and CS7, and for CS7 must enable PE.
+	 * supported mode:
+	 *  - (7,e/o,1)
+	 *  - (8,n,1)
+	 *  - (8,m/s,1)
+	 *  - (8,e/o,1)
+	 */
+	while ((termios->c_cflag & CSIZE) != CS8 &&
+		(termios->c_cflag & CSIZE) != CS7) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	if ((termios->c_cflag & CSIZE) == CS8 ||
+		(termios->c_cflag & CSIZE) == CS7)
+		ctrl = old_ctrl & ~UARTCTRL_M;
+
+	if (termios->c_cflag & CMSPAR) {
+		if ((termios->c_cflag & CSIZE) != CS8) {
+			termios->c_cflag &= ~CSIZE;
+			termios->c_cflag |= CS8;
+		}
+		ctrl |= UARTCTRL_M;
+	}
+
+	if (termios->c_cflag & CRTSCTS) {
+		modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
+	} else {
+		termios->c_cflag &= ~CRTSCTS;
+		modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		termios->c_cflag &= ~CSTOPB;
+
+	/* parity must be enabled when CS7 to match 8-bits format */
+	if ((termios->c_cflag & CSIZE) == CS7)
+		termios->c_cflag |= PARENB;
+
+	if ((termios->c_cflag & PARENB)) {
+		if (termios->c_cflag & CMSPAR) {
+			ctrl &= ~UARTCTRL_PE;
+			ctrl |= UARTCTRL_M;
+		} else {
+			ctrl |= UARTCR1_PE;
+			if ((termios->c_cflag & CSIZE) == CS8)
+				ctrl |= UARTCTRL_M;
+			if (termios->c_cflag & PARODD)
+				ctrl |= UARTCTRL_PT;
+			else
+				ctrl &= ~UARTCTRL_PT;
+		}
+	}
+
+	/* ask the core to calculate the divisor */
+	baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	sport->port.read_status_mask = 0;
+	if (termios->c_iflag & INPCK)
+		sport->port.read_status_mask |=	(UARTSTAT_FE | UARTSTAT_PE);
+	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+		sport->port.read_status_mask |= UARTSTAT_FE;
+
+	/* characters to ignore */
+	sport->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		sport->port.ignore_status_mask |= UARTSTAT_PE;
+	if (termios->c_iflag & IGNBRK) {
+		sport->port.ignore_status_mask |= UARTSTAT_FE;
+		/*
+		 * if we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			sport->port.ignore_status_mask |= UARTSTAT_OR;
+	}
+
+	/* update the per-port timeout */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	/* wait transmit engin complete */
+	while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
+		barrier();
+
+	/* disable transmit and receive */
+	lpuart32_write(old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
+			sport->port.membase + UARTCTRL);
+
+	sbr = sport->port.uartclk / (16 * baud);
+	bd &= ~UARTBAUD_SBR_MASK;
+	bd |= sbr & UARTBAUD_SBR_MASK;
+	bd |= UARTBAUD_BOTHEDGE;
+	bd &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
+	lpuart32_write(bd, sport->port.membase + UARTBAUD);
+	lpuart32_write(modem, sport->port.membase + UARTMODIR);
+	lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
+	/* restore control register */
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
 static const char *lpuart_type(struct uart_port *port)
 static const char *lpuart_type(struct uart_port *port)
 {
 {
 	return "FSL_LPUART";
 	return "FSL_LPUART";
@@ -996,7 +1508,6 @@ static struct uart_ops lpuart_pops = {
 	.stop_tx	= lpuart_stop_tx,
 	.stop_tx	= lpuart_stop_tx,
 	.start_tx	= lpuart_start_tx,
 	.start_tx	= lpuart_start_tx,
 	.stop_rx	= lpuart_stop_rx,
 	.stop_rx	= lpuart_stop_rx,
-	.enable_ms	= lpuart_enable_ms,
 	.break_ctl	= lpuart_break_ctl,
 	.break_ctl	= lpuart_break_ctl,
 	.startup	= lpuart_startup,
 	.startup	= lpuart_startup,
 	.shutdown	= lpuart_shutdown,
 	.shutdown	= lpuart_shutdown,
@@ -1008,6 +1519,24 @@ static struct uart_ops lpuart_pops = {
 	.verify_port	= lpuart_verify_port,
 	.verify_port	= lpuart_verify_port,
 };
 };
 
 
+static struct uart_ops lpuart32_pops = {
+	.tx_empty	= lpuart32_tx_empty,
+	.set_mctrl	= lpuart32_set_mctrl,
+	.get_mctrl	= lpuart32_get_mctrl,
+	.stop_tx	= lpuart32_stop_tx,
+	.start_tx	= lpuart32_start_tx,
+	.stop_rx	= lpuart32_stop_rx,
+	.break_ctl	= lpuart32_break_ctl,
+	.startup	= lpuart32_startup,
+	.shutdown	= lpuart32_shutdown,
+	.set_termios	= lpuart32_set_termios,
+	.type		= lpuart_type,
+	.request_port	= lpuart_request_port,
+	.release_port	= lpuart_release_port,
+	.config_port	= lpuart_config_port,
+	.verify_port	= lpuart_verify_port,
+};
+
 static struct lpuart_port *lpuart_ports[UART_NR];
 static struct lpuart_port *lpuart_ports[UART_NR];
 
 
 #ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
 #ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
@@ -1019,6 +1548,14 @@ static void lpuart_console_putchar(struct uart_port *port, int ch)
 	writeb(ch, port->membase + UARTDR);
 	writeb(ch, port->membase + UARTDR);
 }
 }
 
 
+static void lpuart32_console_putchar(struct uart_port *port, int ch)
+{
+	while (!(lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE))
+		barrier();
+
+	lpuart32_write(ch, port->membase + UARTDATA);
+}
+
 static void
 static void
 lpuart_console_write(struct console *co, const char *s, unsigned int count)
 lpuart_console_write(struct console *co, const char *s, unsigned int count)
 {
 {
@@ -1040,6 +1577,27 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
 	writeb(old_cr2, sport->port.membase + UARTCR2);
 	writeb(old_cr2, sport->port.membase + UARTCR2);
 }
 }
 
 
+static void
+lpuart32_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct lpuart_port *sport = lpuart_ports[co->index];
+	unsigned long  old_cr, cr;
+
+	/* first save CR2 and then disable interrupts */
+	cr = old_cr = lpuart32_read(sport->port.membase + UARTCTRL);
+	cr |= (UARTCTRL_TE |  UARTCTRL_RE);
+	cr &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
+	lpuart32_write(cr, sport->port.membase + UARTCTRL);
+
+	uart_console_write(&sport->port, s, count, lpuart32_console_putchar);
+
+	/* wait for transmitter finish complete and restore CR2 */
+	while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
+		barrier();
+
+	lpuart32_write(old_cr, sport->port.membase + UARTCTRL);
+}
+
 /*
 /*
  * if the port was already initialised (eg, by a boot loader),
  * if the port was already initialised (eg, by a boot loader),
  * try to determine the current setup.
  * try to determine the current setup.
@@ -1093,6 +1651,49 @@ lpuart_console_get_options(struct lpuart_port *sport, int *baud,
 				"from %d to %d\n", baud_raw, *baud);
 				"from %d to %d\n", baud_raw, *baud);
 }
 }
 
 
+static void __init
+lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
+			   int *parity, int *bits)
+{
+	unsigned long cr, bd;
+	unsigned int sbr, uartclk, baud_raw;
+
+	cr = lpuart32_read(sport->port.membase + UARTCTRL);
+	cr &= UARTCTRL_TE | UARTCTRL_RE;
+	if (!cr)
+		return;
+
+	/* ok, the port was enabled */
+
+	cr = lpuart32_read(sport->port.membase + UARTCTRL);
+
+	*parity = 'n';
+	if (cr & UARTCTRL_PE) {
+		if (cr & UARTCTRL_PT)
+			*parity = 'o';
+		else
+			*parity = 'e';
+	}
+
+	if (cr & UARTCTRL_M)
+		*bits = 9;
+	else
+		*bits = 8;
+
+	bd = lpuart32_read(sport->port.membase + UARTBAUD);
+	bd &= UARTBAUD_SBR_MASK;
+	sbr = bd;
+	uartclk = clk_get_rate(sport->clk);
+	/*
+	 * baud = mod_clk/(16*(sbr[13]+(brfa)/32)
+	 */
+	baud_raw = uartclk / (16 * sbr);
+
+	if (*baud != baud_raw)
+		printk(KERN_INFO "Serial: Console lpuart rounded baud rate"
+				"from %d to %d\n", baud_raw, *baud);
+}
+
 static int __init lpuart_console_setup(struct console *co, char *options)
 static int __init lpuart_console_setup(struct console *co, char *options)
 {
 {
 	struct lpuart_port *sport;
 	struct lpuart_port *sport;
@@ -1116,9 +1717,15 @@ static int __init lpuart_console_setup(struct console *co, char *options)
 	if (options)
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	else
 	else
-		lpuart_console_get_options(sport, &baud, &parity, &bits);
+		if (sport->lpuart32)
+			lpuart32_console_get_options(sport, &baud, &parity, &bits);
+		else
+			lpuart_console_get_options(sport, &baud, &parity, &bits);
 
 
-	lpuart_setup_watermark(sport);
+	if (sport->lpuart32)
+		lpuart32_setup_watermark(sport);
+	else
+		lpuart_setup_watermark(sport);
 
 
 	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 }
 }
@@ -1134,9 +1741,21 @@ static struct console lpuart_console = {
 	.data		= &lpuart_reg,
 	.data		= &lpuart_reg,
 };
 };
 
 
+static struct console lpuart32_console = {
+	.name		= DEV_NAME,
+	.write		= lpuart32_console_write,
+	.device		= uart_console_device,
+	.setup		= lpuart_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &lpuart_reg,
+};
+
 #define LPUART_CONSOLE	(&lpuart_console)
 #define LPUART_CONSOLE	(&lpuart_console)
+#define LPUART32_CONSOLE	(&lpuart32_console)
 #else
 #else
 #define LPUART_CONSOLE	NULL
 #define LPUART_CONSOLE	NULL
+#define LPUART32_CONSOLE	NULL
 #endif
 #endif
 
 
 static struct uart_driver lpuart_reg = {
 static struct uart_driver lpuart_reg = {
@@ -1166,7 +1785,7 @@ static int lpuart_probe(struct platform_device *pdev)
 		return ret;
 		return ret;
 	}
 	}
 	sport->port.line = ret;
 	sport->port.line = ret;
-
+	sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 	if (!res)
 		return -ENODEV;
 		return -ENODEV;
@@ -1180,7 +1799,10 @@ static int lpuart_probe(struct platform_device *pdev)
 	sport->port.type = PORT_LPUART;
 	sport->port.type = PORT_LPUART;
 	sport->port.iotype = UPIO_MEM;
 	sport->port.iotype = UPIO_MEM;
 	sport->port.irq = platform_get_irq(pdev, 0);
 	sport->port.irq = platform_get_irq(pdev, 0);
-	sport->port.ops = &lpuart_pops;
+	if (sport->lpuart32)
+		sport->port.ops = &lpuart32_pops;
+	else
+		sport->port.ops = &lpuart_pops;
 	sport->port.flags = UPF_BOOT_AUTOCONF;
 	sport->port.flags = UPF_BOOT_AUTOCONF;
 
 
 	sport->clk = devm_clk_get(&pdev->dev, "ipg");
 	sport->clk = devm_clk_get(&pdev->dev, "ipg");
@@ -1202,6 +1824,11 @@ static int lpuart_probe(struct platform_device *pdev)
 
 
 	platform_set_drvdata(pdev, &sport->port);
 	platform_set_drvdata(pdev, &sport->port);
 
 
+	if (sport->lpuart32)
+		lpuart_reg.cons = LPUART32_CONSOLE;
+	else
+		lpuart_reg.cons = LPUART_CONSOLE;
+
 	ret = uart_add_one_port(&lpuart_reg, &sport->port);
 	ret = uart_add_one_port(&lpuart_reg, &sport->port);
 	if (ret) {
 	if (ret) {
 		clk_disable_unprepare(sport->clk);
 		clk_disable_unprepare(sport->clk);

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

@@ -1052,11 +1052,6 @@ static void icom_stop_rx(struct uart_port *port)
 	writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
 	writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
 }
 }
 
 
-static void icom_enable_ms(struct uart_port *port)
-{
-	/* no-op */
-}
-
 static void icom_break(struct uart_port *port, int break_state)
 static void icom_break(struct uart_port *port, int break_state)
 {
 {
 	unsigned char cmdReg;
 	unsigned char cmdReg;
@@ -1300,7 +1295,6 @@ static struct uart_ops icom_ops = {
 	.start_tx = icom_start_tx,
 	.start_tx = icom_start_tx,
 	.send_xchar = icom_send_xchar,
 	.send_xchar = icom_send_xchar,
 	.stop_rx = icom_stop_rx,
 	.stop_rx = icom_stop_rx,
-	.enable_ms = icom_enable_ms,
 	.break_ctl = icom_break,
 	.break_ctl = icom_break,
 	.startup = icom_open,
 	.startup = icom_open,
 	.shutdown = icom_close,
 	.shutdown = icom_close,

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

@@ -1880,7 +1880,6 @@ static struct uart_ops ioc3_ops = {
 	.stop_tx = ic3_stop_tx,
 	.stop_tx = ic3_stop_tx,
 	.start_tx = ic3_start_tx,
 	.start_tx = ic3_start_tx,
 	.stop_rx = ic3_stop_rx,
 	.stop_rx = ic3_stop_rx,
-	.enable_ms = null_void_function,
 	.break_ctl = ic3_break_ctl,
 	.break_ctl = ic3_break_ctl,
 	.startup = ic3_startup,
 	.startup = ic3_startup,
 	.shutdown = ic3_shutdown,
 	.shutdown = ic3_shutdown,

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

@@ -2597,7 +2597,6 @@ static struct uart_ops ioc4_ops = {
 	.stop_tx	= ic4_stop_tx,
 	.stop_tx	= ic4_stop_tx,
 	.start_tx	= ic4_start_tx,
 	.start_tx	= ic4_start_tx,
 	.stop_rx	= null_void_function,
 	.stop_rx	= null_void_function,
-	.enable_ms	= null_void_function,
 	.break_ctl	= ic4_break_ctl,
 	.break_ctl	= ic4_break_ctl,
 	.startup	= ic4_startup,
 	.startup	= ic4_startup,
 	.shutdown	= ic4_shutdown,
 	.shutdown	= ic4_shutdown,

+ 0 - 6
drivers/tty/serial/jsm/jsm_tty.c

@@ -177,11 +177,6 @@ static void jsm_tty_stop_rx(struct uart_port *port)
 	channel->ch_bd->bd_ops->disable_receiver(channel);
 	channel->ch_bd->bd_ops->disable_receiver(channel);
 }
 }
 
 
-static void jsm_tty_enable_ms(struct uart_port *port)
-{
-	/* Nothing needed */
-}
-
 static void jsm_tty_break(struct uart_port *port, int break_state)
 static void jsm_tty_break(struct uart_port *port, int break_state)
 {
 {
 	unsigned long lock_flags;
 	unsigned long lock_flags;
@@ -354,7 +349,6 @@ static struct uart_ops jsm_ops = {
 	.start_tx	= jsm_tty_start_tx,
 	.start_tx	= jsm_tty_start_tx,
 	.send_xchar	= jsm_tty_send_xchar,
 	.send_xchar	= jsm_tty_send_xchar,
 	.stop_rx	= jsm_tty_stop_rx,
 	.stop_rx	= jsm_tty_stop_rx,
-	.enable_ms	= jsm_tty_enable_ms,
 	.break_ctl	= jsm_tty_break,
 	.break_ctl	= jsm_tty_break,
 	.startup	= jsm_tty_open,
 	.startup	= jsm_tty_open,
 	.shutdown	= jsm_tty_close,
 	.shutdown	= jsm_tty_close,

+ 15 - 21
drivers/tty/serial/kgdb_nmi.c

@@ -42,7 +42,7 @@ static char *kgdb_nmi_magic = "$3#33";
 module_param_named(magic, kgdb_nmi_magic, charp, 0600);
 module_param_named(magic, kgdb_nmi_magic, charp, 0600);
 MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
 MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
 
 
-static bool kgdb_nmi_tty_enabled;
+static atomic_t kgdb_nmi_num_readers = ATOMIC_INIT(0);
 
 
 static int kgdb_nmi_console_setup(struct console *co, char *options)
 static int kgdb_nmi_console_setup(struct console *co, char *options)
 {
 {
@@ -136,7 +136,7 @@ static int kgdb_nmi_poll_one_knock(void)
 		n = 0;
 		n = 0;
 	}
 	}
 
 
-	if (kgdb_nmi_tty_enabled) {
+	if (atomic_read(&kgdb_nmi_num_readers)) {
 		kgdb_tty_recv(c);
 		kgdb_tty_recv(c);
 		return 0;
 		return 0;
 	}
 	}
@@ -197,7 +197,8 @@ static void kgdb_nmi_tty_receiver(unsigned long data)
 	priv->timer.expires = jiffies + (HZ/100);
 	priv->timer.expires = jiffies + (HZ/100);
 	add_timer(&priv->timer);
 	add_timer(&priv->timer);
 
 
-	if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo)))
+	if (likely(!atomic_read(&kgdb_nmi_num_readers) ||
+		   !kfifo_len(&priv->fifo)))
 		return;
 		return;
 
 
 	while (kfifo_out(&priv->fifo, &ch, 1))
 	while (kfifo_out(&priv->fifo, &ch, 1))
@@ -270,13 +271,23 @@ static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
 static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
 static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
 {
 {
 	struct kgdb_nmi_tty_priv *priv = tty->driver_data;
 	struct kgdb_nmi_tty_priv *priv = tty->driver_data;
+	unsigned int mode = file->f_flags & O_ACCMODE;
+	int ret;
+
+	ret = tty_port_open(&priv->port, tty, file);
+	if (!ret && (mode == O_RDONLY || mode == O_RDWR))
+		atomic_inc(&kgdb_nmi_num_readers);
 
 
-	return tty_port_open(&priv->port, tty, file);
+	return ret;
 }
 }
 
 
 static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
 static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
 {
 {
 	struct kgdb_nmi_tty_priv *priv = tty->driver_data;
 	struct kgdb_nmi_tty_priv *priv = tty->driver_data;
+	unsigned int mode = file->f_flags & O_ACCMODE;
+
+	if (mode == O_RDONLY || mode == O_RDWR)
+		atomic_dec(&kgdb_nmi_num_readers);
 
 
 	tty_port_close(&priv->port, tty, file);
 	tty_port_close(&priv->port, tty, file);
 }
 }
@@ -313,12 +324,6 @@ static const struct tty_operations kgdb_nmi_tty_ops = {
 	.write		= kgdb_nmi_tty_write,
 	.write		= kgdb_nmi_tty_write,
 };
 };
 
 
-static int kgdb_nmi_enable_console(int argc, const char *argv[])
-{
-	kgdb_nmi_tty_enabled = !(argc == 1 && !strcmp(argv[1], "off"));
-	return 0;
-}
-
 int kgdb_register_nmi_console(void)
 int kgdb_register_nmi_console(void)
 {
 {
 	int ret;
 	int ret;
@@ -348,19 +353,10 @@ int kgdb_register_nmi_console(void)
 		goto err_drv_reg;
 		goto err_drv_reg;
 	}
 	}
 
 
-	ret = kdb_register("nmi_console", kgdb_nmi_enable_console, "[off]",
-			   "switch to Linux NMI console", 0);
-	if (ret) {
-		pr_err("%s: can't register kdb command: %d\n", __func__, ret);
-		goto err_kdb_reg;
-	}
-
 	register_console(&kgdb_nmi_console);
 	register_console(&kgdb_nmi_console);
 	arch_kgdb_ops.enable_nmi(1);
 	arch_kgdb_ops.enable_nmi(1);
 
 
 	return 0;
 	return 0;
-err_kdb_reg:
-	tty_unregister_driver(kgdb_nmi_tty_driver);
 err_drv_reg:
 err_drv_reg:
 	put_tty_driver(kgdb_nmi_tty_driver);
 	put_tty_driver(kgdb_nmi_tty_driver);
 	return ret;
 	return ret;
@@ -375,8 +371,6 @@ int kgdb_unregister_nmi_console(void)
 		return 0;
 		return 0;
 	arch_kgdb_ops.enable_nmi(0);
 	arch_kgdb_ops.enable_nmi(0);
 
 
-	kdb_unregister("nmi_console");
-
 	ret = unregister_console(&kgdb_nmi_console);
 	ret = unregister_console(&kgdb_nmi_console);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;

+ 1 - 7
drivers/tty/serial/lantiq.c

@@ -154,11 +154,6 @@ lqasc_stop_rx(struct uart_port *port)
 	ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
 	ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
 }
 }
 
 
-static void
-lqasc_enable_ms(struct uart_port *port)
-{
-}
-
 static int
 static int
 lqasc_rx_chars(struct uart_port *port)
 lqasc_rx_chars(struct uart_port *port)
 {
 {
@@ -568,7 +563,6 @@ static struct uart_ops lqasc_pops = {
 	.stop_tx =	lqasc_stop_tx,
 	.stop_tx =	lqasc_stop_tx,
 	.start_tx =	lqasc_start_tx,
 	.start_tx =	lqasc_start_tx,
 	.stop_rx =	lqasc_stop_rx,
 	.stop_rx =	lqasc_stop_rx,
-	.enable_ms =	lqasc_enable_ms,
 	.break_ctl =	lqasc_break_ctl,
 	.break_ctl =	lqasc_break_ctl,
 	.startup =	lqasc_startup,
 	.startup =	lqasc_startup,
 	.shutdown =	lqasc_shutdown,
 	.shutdown =	lqasc_shutdown,
@@ -709,7 +703,7 @@ lqasc_probe(struct platform_device *pdev)
 	port = &ltq_port->port;
 	port = &ltq_port->port;
 
 
 	port->iotype	= SERIAL_IO_MEM;
 	port->iotype	= SERIAL_IO_MEM;
-	port->flags	= ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
+	port->flags	= UPF_BOOT_AUTOCONF | UPF_IOREMAP;
 	port->ops	= &lqasc_pops;
 	port->ops	= &lqasc_pops;
 	port->fifosize	= 16;
 	port->fifosize	= 16;
 	port->type	= PORT_LTQ_ASC,
 	port->type	= PORT_LTQ_ASC,

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

@@ -427,12 +427,6 @@ static void serial_lpc32xx_stop_rx(struct uart_port *port)
 		LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
 		LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
 }
 }
 
 
-/* port->lock held by caller.  */
-static void serial_lpc32xx_enable_ms(struct uart_port *port)
-{
-	/* Modem status is not supported */
-}
-
 /* port->lock is not held.  */
 /* port->lock is not held.  */
 static void serial_lpc32xx_break_ctl(struct uart_port *port,
 static void serial_lpc32xx_break_ctl(struct uart_port *port,
 				     int break_state)
 				     int break_state)
@@ -658,7 +652,6 @@ static struct uart_ops serial_lpc32xx_pops = {
 	.stop_tx	= serial_lpc32xx_stop_tx,
 	.stop_tx	= serial_lpc32xx_stop_tx,
 	.start_tx	= serial_lpc32xx_start_tx,
 	.start_tx	= serial_lpc32xx_start_tx,
 	.stop_rx	= serial_lpc32xx_stop_rx,
 	.stop_rx	= serial_lpc32xx_stop_rx,
-	.enable_ms	= serial_lpc32xx_enable_ms,
 	.break_ctl	= serial_lpc32xx_break_ctl,
 	.break_ctl	= serial_lpc32xx_break_ctl,
 	.startup	= serial_lpc32xx_startup,
 	.startup	= serial_lpc32xx_startup,
 	.shutdown	= serial_lpc32xx_shutdown,
 	.shutdown	= serial_lpc32xx_shutdown,

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

@@ -1008,7 +1008,6 @@ static const struct uart_ops max310x_ops = {
 	.stop_tx	= max310x_null_void,
 	.stop_tx	= max310x_null_void,
 	.start_tx	= max310x_start_tx,
 	.start_tx	= max310x_start_tx,
 	.stop_rx	= max310x_null_void,
 	.stop_rx	= max310x_null_void,
-	.enable_ms	= max310x_null_void,
 	.break_ctl	= max310x_break_ctl,
 	.break_ctl	= max310x_break_ctl,
 	.startup	= max310x_startup,
 	.startup	= max310x_startup,
 	.shutdown	= max310x_shutdown,
 	.shutdown	= max310x_shutdown,

+ 2 - 9
drivers/tty/serial/mcf.c

@@ -150,12 +150,6 @@ static void mcf_break_ctl(struct uart_port *port, int break_state)
 
 
 /****************************************************************************/
 /****************************************************************************/
 
 
-static void mcf_enable_ms(struct uart_port *port)
-{
-}
-
-/****************************************************************************/
-
 static int mcf_startup(struct uart_port *port)
 static int mcf_startup(struct uart_port *port)
 {
 {
 	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
@@ -507,7 +501,6 @@ static const struct uart_ops mcf_uart_ops = {
 	.start_tx	= mcf_start_tx,
 	.start_tx	= mcf_start_tx,
 	.stop_tx	= mcf_stop_tx,
 	.stop_tx	= mcf_stop_tx,
 	.stop_rx	= mcf_stop_rx,
 	.stop_rx	= mcf_stop_rx,
-	.enable_ms	= mcf_enable_ms,
 	.break_ctl	= mcf_break_ctl,
 	.break_ctl	= mcf_break_ctl,
 	.startup	= mcf_startup,
 	.startup	= mcf_startup,
 	.shutdown	= mcf_shutdown,
 	.shutdown	= mcf_shutdown,
@@ -544,7 +537,7 @@ int __init early_mcf_setup(struct mcf_platform_uart *platp)
 		port->iotype = SERIAL_IO_MEM;
 		port->iotype = SERIAL_IO_MEM;
 		port->irq = platp[i].irq;
 		port->irq = platp[i].irq;
 		port->uartclk = MCF_BUSCLK;
 		port->uartclk = MCF_BUSCLK;
-		port->flags = ASYNC_BOOT_AUTOCONF;
+		port->flags = UPF_BOOT_AUTOCONF;
 		port->ops = &mcf_uart_ops;
 		port->ops = &mcf_uart_ops;
 	}
 	}
 
 
@@ -669,7 +662,7 @@ static int mcf_probe(struct platform_device *pdev)
 		port->irq = platp[i].irq;
 		port->irq = platp[i].irq;
 		port->uartclk = MCF_BUSCLK;
 		port->uartclk = MCF_BUSCLK;
 		port->ops = &mcf_uart_ops;
 		port->ops = &mcf_uart_ops;
-		port->flags = ASYNC_BOOT_AUTOCONF;
+		port->flags = UPF_BOOT_AUTOCONF;
 
 
 		uart_add_one_port(&mcf_driver, port);
 		uart_add_one_port(&mcf_driver, port);
 	}
 	}

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

@@ -308,9 +308,6 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
 	if (port->x_char)
 	if (port->x_char)
 		goto out;
 		goto out;
 
 
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(port);
-
 	/* calculate bytes to copy */
 	/* calculate bytes to copy */
 	qlen = uart_circ_chars_pending(xmit);
 	qlen = uart_circ_chars_pending(xmit);
 	if (qlen <= 0)
 	if (qlen <= 0)
@@ -357,6 +354,9 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
 
 
 	port->icount.tx += n;
 	port->icount.tx += n;
 
 
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
 irq_en:
 irq_en:
 	if (!uart_circ_empty(xmit))
 	if (!uart_circ_empty(xmit))
 		men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
 		men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);

+ 0 - 5
drivers/tty/serial/mpsc.c

@@ -1336,10 +1336,6 @@ static void mpsc_stop_rx(struct uart_port *port)
 	mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
 	mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
 }
 }
 
 
-static void mpsc_enable_ms(struct uart_port *port)
-{
-}
-
 static void mpsc_break_ctl(struct uart_port *port, int ctl)
 static void mpsc_break_ctl(struct uart_port *port, int ctl)
 {
 {
 	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
 	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
@@ -1674,7 +1670,6 @@ static struct uart_ops mpsc_pops = {
 	.stop_tx	= mpsc_stop_tx,
 	.stop_tx	= mpsc_stop_tx,
 	.start_tx	= mpsc_start_tx,
 	.start_tx	= mpsc_start_tx,
 	.stop_rx	= mpsc_stop_rx,
 	.stop_rx	= mpsc_stop_rx,
-	.enable_ms	= mpsc_enable_ms,
 	.break_ctl	= mpsc_break_ctl,
 	.break_ctl	= mpsc_break_ctl,
 	.startup	= mpsc_startup,
 	.startup	= mpsc_startup,
 	.shutdown	= mpsc_shutdown,
 	.shutdown	= mpsc_shutdown,

+ 0 - 5
drivers/tty/serial/mrst_max3110.c

@@ -698,10 +698,6 @@ static void serial_m3110_pm(struct uart_port *port, unsigned int state,
 {
 {
 }
 }
 
 
-static void serial_m3110_enable_ms(struct uart_port *port)
-{
-}
-
 static struct uart_ops serial_m3110_ops = {
 static struct uart_ops serial_m3110_ops = {
 	.tx_empty	= serial_m3110_tx_empty,
 	.tx_empty	= serial_m3110_tx_empty,
 	.set_mctrl	= serial_m3110_set_mctrl,
 	.set_mctrl	= serial_m3110_set_mctrl,
@@ -709,7 +705,6 @@ static struct uart_ops serial_m3110_ops = {
 	.stop_tx	= serial_m3110_stop_tx,
 	.stop_tx	= serial_m3110_stop_tx,
 	.start_tx	= serial_m3110_start_tx,
 	.start_tx	= serial_m3110_start_tx,
 	.stop_rx	= serial_m3110_stop_rx,
 	.stop_rx	= serial_m3110_stop_rx,
-	.enable_ms	= serial_m3110_enable_ms,
 	.break_ctl	= serial_m3110_break_ctl,
 	.break_ctl	= serial_m3110_break_ctl,
 	.startup	= serial_m3110_startup,
 	.startup	= serial_m3110_startup,
 	.shutdown	= serial_m3110_shutdown,
 	.shutdown	= serial_m3110_shutdown,

+ 20 - 12
drivers/tty/serial/msm_serial.c

@@ -125,14 +125,14 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
 	port->icount.rx += count;
 	port->icount.rx += count;
 
 
 	while (count > 0) {
 	while (count > 0) {
-		unsigned int c;
+		unsigned char buf[4];
 
 
 		sr = msm_read(port, UART_SR);
 		sr = msm_read(port, UART_SR);
 		if ((sr & UART_SR_RX_READY) == 0) {
 		if ((sr & UART_SR_RX_READY) == 0) {
 			msm_port->old_snap_state -= count;
 			msm_port->old_snap_state -= count;
 			break;
 			break;
 		}
 		}
-		c = msm_read(port, UARTDM_RF);
+		ioread32_rep(port->membase + UARTDM_RF, buf, 1);
 		if (sr & UART_SR_RX_BREAK) {
 		if (sr & UART_SR_RX_BREAK) {
 			port->icount.brk++;
 			port->icount.brk++;
 			if (uart_handle_break(port))
 			if (uart_handle_break(port))
@@ -141,8 +141,7 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
 			port->icount.frame++;
 			port->icount.frame++;
 
 
 		/* TODO: handle sysrq */
 		/* TODO: handle sysrq */
-		tty_insert_flip_string(tport, (char *)&c,
-				       (count > 4) ? 4 : count);
+		tty_insert_flip_string(tport, buf, min(count, 4));
 		count -= 4;
 		count -= 4;
 	}
 	}
 
 
@@ -219,6 +218,12 @@ static void handle_tx(struct uart_port *port)
 	struct msm_port *msm_port = UART_TO_MSM(port);
 	struct msm_port *msm_port = UART_TO_MSM(port);
 	unsigned int tx_count, num_chars;
 	unsigned int tx_count, num_chars;
 	unsigned int tf_pointer = 0;
 	unsigned int tf_pointer = 0;
+	void __iomem *tf;
+
+	if (msm_port->is_uartdm)
+		tf = port->membase + UARTDM_TF;
+	else
+		tf = port->membase + UART_TF;
 
 
 	tx_count = uart_circ_chars_pending(xmit);
 	tx_count = uart_circ_chars_pending(xmit);
 	tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
 	tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
@@ -228,8 +233,7 @@ static void handle_tx(struct uart_port *port)
 		if (msm_port->is_uartdm)
 		if (msm_port->is_uartdm)
 			reset_dm_count(port, tx_count + 1);
 			reset_dm_count(port, tx_count + 1);
 
 
-		msm_write(port, port->x_char,
-			  msm_port->is_uartdm ? UARTDM_TF : UART_TF);
+		iowrite8_rep(tf, &port->x_char, 1);
 		port->icount.tx++;
 		port->icount.tx++;
 		port->x_char = 0;
 		port->x_char = 0;
 	} else if (tx_count && msm_port->is_uartdm) {
 	} else if (tx_count && msm_port->is_uartdm) {
@@ -239,7 +243,6 @@ static void handle_tx(struct uart_port *port)
 	while (tf_pointer < tx_count) {
 	while (tf_pointer < tx_count) {
 		int i;
 		int i;
 		char buf[4] = { 0 };
 		char buf[4] = { 0 };
-		unsigned int *bf = (unsigned int *)&buf;
 
 
 		if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 		if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 			break;
 			break;
@@ -255,7 +258,7 @@ static void handle_tx(struct uart_port *port)
 			port->icount.tx++;
 			port->icount.tx++;
 		}
 		}
 
 
-		msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
+		iowrite32_rep(tf, buf, 1);
 		xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1);
 		xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1);
 		tf_pointer += num_chars;
 		tf_pointer += num_chars;
 	}
 	}
@@ -861,12 +864,18 @@ static void msm_console_write(struct console *co, const char *s,
 	struct msm_port *msm_port;
 	struct msm_port *msm_port;
 	int num_newlines = 0;
 	int num_newlines = 0;
 	bool replaced = false;
 	bool replaced = false;
+	void __iomem *tf;
 
 
 	BUG_ON(co->index < 0 || co->index >= UART_NR);
 	BUG_ON(co->index < 0 || co->index >= UART_NR);
 
 
 	port = get_port_from_line(co->index);
 	port = get_port_from_line(co->index);
 	msm_port = UART_TO_MSM(port);
 	msm_port = UART_TO_MSM(port);
 
 
+	if (msm_port->is_uartdm)
+		tf = port->membase + UARTDM_TF;
+	else
+		tf = port->membase + UART_TF;
+
 	/* Account for newlines that will get a carriage return added */
 	/* Account for newlines that will get a carriage return added */
 	for (i = 0; i < count; i++)
 	for (i = 0; i < count; i++)
 		if (s[i] == '\n')
 		if (s[i] == '\n')
@@ -882,7 +891,6 @@ static void msm_console_write(struct console *co, const char *s,
 		int j;
 		int j;
 		unsigned int num_chars;
 		unsigned int num_chars;
 		char buf[4] = { 0 };
 		char buf[4] = { 0 };
-		unsigned int *bf = (unsigned int *)&buf;
 
 
 		if (msm_port->is_uartdm)
 		if (msm_port->is_uartdm)
 			num_chars = min(count - i, (unsigned int)sizeof(buf));
 			num_chars = min(count - i, (unsigned int)sizeof(buf));
@@ -907,7 +915,7 @@ static void msm_console_write(struct console *co, const char *s,
 		while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 		while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 			cpu_relax();
 			cpu_relax();
 
 
-		msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
+		iowrite32_rep(tf, buf, 1);
 		i += num_chars;
 		i += num_chars;
 	}
 	}
 	spin_unlock(&port->lock);
 	spin_unlock(&port->lock);
@@ -917,7 +925,7 @@ static int __init msm_console_setup(struct console *co, char *options)
 {
 {
 	struct uart_port *port;
 	struct uart_port *port;
 	struct msm_port *msm_port;
 	struct msm_port *msm_port;
-	int baud, flow, bits, parity;
+	int baud = 0, flow, bits, parity;
 
 
 	if (unlikely(co->index >= UART_NR || co->index < 0))
 	if (unlikely(co->index >= UART_NR || co->index < 0))
 		return -ENXIO;
 		return -ENXIO;
@@ -1057,7 +1065,7 @@ static int msm_serial_remove(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct of_device_id msm_match_table[] = {
+static const struct of_device_id msm_match_table[] = {
 	{ .compatible = "qcom,msm-uart" },
 	{ .compatible = "qcom,msm-uart" },
 	{ .compatible = "qcom,msm-uartdm" },
 	{ .compatible = "qcom,msm-uartdm" },
 	{}
 	{}

+ 2 - 2
drivers/tty/serial/msm_serial.h

@@ -126,13 +126,13 @@
 static inline
 static inline
 void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
 void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
 {
 {
-	__raw_writel(val, port->membase + off);
+	writel_relaxed(val, port->membase + off);
 }
 }
 
 
 static inline
 static inline
 unsigned int msm_read(struct uart_port *port, unsigned int off)
 unsigned int msm_read(struct uart_port *port, unsigned int off)
 {
 {
-	return __raw_readl(port->membase + off);
+	return readl_relaxed(port->membase + off);
 }
 }
 
 
 /*
 /*

+ 0 - 11
drivers/tty/serial/mux.c

@@ -168,16 +168,6 @@ static void mux_stop_rx(struct uart_port *port)
 {
 {
 }
 }
 
 
-/**
- * mux_enable_ms - Enable modum status interrupts.
- * @port: Ptr to the uart_port.
- *
- * The Serial Mux does not support this function.
- */
-static void mux_enable_ms(struct uart_port *port)
-{
-}
-
 /**
 /**
  * mux_break_ctl - Control the transmitssion of a break signal.
  * mux_break_ctl - Control the transmitssion of a break signal.
  * @port: Ptr to the uart_port.
  * @port: Ptr to the uart_port.
@@ -449,7 +439,6 @@ static struct uart_ops mux_pops = {
 	.stop_tx =		mux_stop_tx,
 	.stop_tx =		mux_stop_tx,
 	.start_tx =		mux_start_tx,
 	.start_tx =		mux_start_tx,
 	.stop_rx =		mux_stop_rx,
 	.stop_rx =		mux_stop_rx,
-	.enable_ms =		mux_enable_ms,
 	.break_ctl =		mux_break_ctl,
 	.break_ctl =		mux_break_ctl,
 	.startup =		mux_startup,
 	.startup =		mux_startup,
 	.shutdown =		mux_shutdown,
 	.shutdown =		mux_shutdown,

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

@@ -815,17 +815,11 @@ static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
 			     u->membase + AUART_LINECTRL_CLR);
 			     u->membase + AUART_LINECTRL_CLR);
 }
 }
 
 
-static void mxs_auart_enable_ms(struct uart_port *port)
-{
-	/* just empty */
-}
-
 static struct uart_ops mxs_auart_ops = {
 static struct uart_ops mxs_auart_ops = {
 	.tx_empty       = mxs_auart_tx_empty,
 	.tx_empty       = mxs_auart_tx_empty,
 	.start_tx       = mxs_auart_start_tx,
 	.start_tx       = mxs_auart_start_tx,
 	.stop_tx	= mxs_auart_stop_tx,
 	.stop_tx	= mxs_auart_stop_tx,
 	.stop_rx	= mxs_auart_stop_rx,
 	.stop_rx	= mxs_auart_stop_rx,
-	.enable_ms      = mxs_auart_enable_ms,
 	.break_ctl      = mxs_auart_break_ctl,
 	.break_ctl      = mxs_auart_break_ctl,
 	.set_mctrl	= mxs_auart_set_mctrl,
 	.set_mctrl	= mxs_auart_set_mctrl,
 	.get_mctrl      = mxs_auart_get_mctrl,
 	.get_mctrl      = mxs_auart_get_mctrl,

+ 0 - 6
drivers/tty/serial/nwpserial.c

@@ -240,11 +240,6 @@ static void nwpserial_break_ctl(struct uart_port *port, int ctl)
 	/* N/A */
 	/* N/A */
 }
 }
 
 
-static void nwpserial_enable_ms(struct uart_port *port)
-{
-	/* N/A */
-}
-
 static void nwpserial_stop_rx(struct uart_port *port)
 static void nwpserial_stop_rx(struct uart_port *port)
 {
 {
 	struct nwpserial_port *up;
 	struct nwpserial_port *up;
@@ -315,7 +310,6 @@ static struct uart_ops nwpserial_pops = {
 	.stop_tx      = nwpserial_stop_tx,
 	.stop_tx      = nwpserial_stop_tx,
 	.start_tx     = nwpserial_start_tx,
 	.start_tx     = nwpserial_start_tx,
 	.stop_rx      = nwpserial_stop_rx,
 	.stop_rx      = nwpserial_stop_rx,
-	.enable_ms    = nwpserial_enable_ms,
 	.break_ctl    = nwpserial_break_ctl,
 	.break_ctl    = nwpserial_break_ctl,
 	.startup      = nwpserial_startup,
 	.startup      = nwpserial_startup,
 	.shutdown     = nwpserial_shutdown,
 	.shutdown     = nwpserial_shutdown,

+ 5 - 4
drivers/tty/serial/pch_uart.c

@@ -736,9 +736,10 @@ static void pch_request_dma(struct uart_port *port)
 	dma_cap_zero(mask);
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 	dma_cap_set(DMA_SLAVE, mask);
 
 
-	dma_dev = pci_get_bus_and_slot(priv->pdev->bus->number,
-				       PCI_DEVFN(0xa, 0)); /* Get DMA's dev
-								information */
+	/* Get DMA's dev information */
+	dma_dev = pci_get_slot(priv->pdev->bus,
+			PCI_DEVFN(PCI_SLOT(priv->pdev->devfn), 0));
+
 	/* Set Tx DMA */
 	/* Set Tx DMA */
 	param = &priv->param_tx;
 	param = &priv->param_tx;
 	param->dma_dev = &dma_dev->dev;
 	param->dma_dev = &dma_dev->dev;
@@ -1047,7 +1048,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
 					priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
 					priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc) {
 	if (!desc) {
-		dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
+		dev_err(priv->port.dev, "%s:dmaengine_prep_slave_sg Failed\n",
 			__func__);
 			__func__);
 		return 0;
 		return 0;
 	}
 	}

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

@@ -778,7 +778,7 @@ static struct uart_ops serial_pxa_pops = {
 	.request_port	= serial_pxa_request_port,
 	.request_port	= serial_pxa_request_port,
 	.config_port	= serial_pxa_config_port,
 	.config_port	= serial_pxa_config_port,
 	.verify_port	= serial_pxa_verify_port,
 	.verify_port	= serial_pxa_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
+#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_PXA_CONSOLE)
 	.poll_get_char = serial_pxa_get_poll_char,
 	.poll_get_char = serial_pxa_get_poll_char,
 	.poll_put_char = serial_pxa_put_poll_char,
 	.poll_put_char = serial_pxa_put_poll_char,
 #endif
 #endif

+ 24 - 20
drivers/tty/serial/samsung.c

@@ -203,10 +203,6 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
 	}
 	}
 }
 }
 
 
-static void s3c24xx_serial_enable_ms(struct uart_port *port)
-{
-}
-
 static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
 static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
 {
 {
 	return to_ourport(port)->info;
 	return to_ourport(port)->info;
@@ -952,7 +948,6 @@ static struct uart_ops s3c24xx_serial_ops = {
 	.stop_tx	= s3c24xx_serial_stop_tx,
 	.stop_tx	= s3c24xx_serial_stop_tx,
 	.start_tx	= s3c24xx_serial_start_tx,
 	.start_tx	= s3c24xx_serial_start_tx,
 	.stop_rx	= s3c24xx_serial_stop_rx,
 	.stop_rx	= s3c24xx_serial_stop_rx,
-	.enable_ms	= s3c24xx_serial_enable_ms,
 	.break_ctl	= s3c24xx_serial_break_ctl,
 	.break_ctl	= s3c24xx_serial_break_ctl,
 	.startup	= s3c24xx_serial_startup,
 	.startup	= s3c24xx_serial_startup,
 	.shutdown	= s3c24xx_serial_shutdown,
 	.shutdown	= s3c24xx_serial_shutdown,
@@ -1226,8 +1221,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 		wr_regl(port, S3C64XX_UINTSP, 0xf);
 		wr_regl(port, S3C64XX_UINTSP, 0xf);
 	}
 	}
 
 
-	dbg("port: map=%08x, mem=%p, irq=%d (%d,%d), clock=%u\n",
-	    port->mapbase, port->membase, port->irq,
+	dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
+	    &port->mapbase, port->membase, port->irq,
 	    ourport->rx_irq, ourport->tx_irq, port->uartclk);
 	    ourport->rx_irq, ourport->tx_irq, port->uartclk);
 
 
 	/* reset the fifos (and setup the uart) */
 	/* reset the fifos (and setup the uart) */
@@ -1274,12 +1269,20 @@ static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(
 
 
 static int s3c24xx_serial_probe(struct platform_device *pdev)
 static int s3c24xx_serial_probe(struct platform_device *pdev)
 {
 {
+	struct device_node *np = pdev->dev.of_node;
 	struct s3c24xx_uart_port *ourport;
 	struct s3c24xx_uart_port *ourport;
+	int index = probe_index;
 	int ret;
 	int ret;
 
 
-	dbg("s3c24xx_serial_probe(%p) %d\n", pdev, probe_index);
+	if (np) {
+		ret = of_alias_get_id(np, "serial");
+		if (ret >= 0)
+			index = ret;
+	}
+
+	dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index);
 
 
-	ourport = &s3c24xx_serial_ports[probe_index];
+	ourport = &s3c24xx_serial_ports[index];
 
 
 	ourport->drv_data = s3c24xx_get_driver_data(pdev);
 	ourport->drv_data = s3c24xx_get_driver_data(pdev);
 	if (!ourport->drv_data) {
 	if (!ourport->drv_data) {
@@ -1293,9 +1296,15 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 			dev_get_platdata(&pdev->dev) :
 			dev_get_platdata(&pdev->dev) :
 			ourport->drv_data->def_cfg;
 			ourport->drv_data->def_cfg;
 
 
-	ourport->port.fifosize = (ourport->info->fifosize) ?
-		ourport->info->fifosize :
-		ourport->drv_data->fifosize[probe_index];
+	if (np)
+		of_property_read_u32(np,
+			"samsung,uart-fifosize", &ourport->port.fifosize);
+
+	if (!ourport->port.fifosize) {
+		ourport->port.fifosize = (ourport->info->fifosize) ?
+			ourport->info->fifosize :
+			ourport->drv_data->fifosize[index];
+	}
 
 
 	probe_index++;
 	probe_index++;
 
 
@@ -1303,7 +1312,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 
 
 	ret = s3c24xx_serial_init_port(ourport, pdev);
 	ret = s3c24xx_serial_init_port(ourport, pdev);
 	if (ret < 0)
 	if (ret < 0)
-		goto probe_err;
+		return ret;
 
 
 	if (!s3c24xx_uart_drv.state) {
 	if (!s3c24xx_uart_drv.state) {
 		ret = uart_register_driver(&s3c24xx_uart_drv);
 		ret = uart_register_driver(&s3c24xx_uart_drv);
@@ -1335,9 +1344,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
 		dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
 
 
 	return 0;
 	return 0;
-
- probe_err:
-	return ret;
 }
 }
 
 
 static int s3c24xx_serial_remove(struct platform_device *dev)
 static int s3c24xx_serial_remove(struct platform_device *dev)
@@ -1537,8 +1543,8 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
 		case S3C2410_LCON_CS7:
 		case S3C2410_LCON_CS7:
 			*bits = 7;
 			*bits = 7;
 			break;
 			break;
-		default:
 		case S3C2410_LCON_CS8:
 		case S3C2410_LCON_CS8:
+		default:
 			*bits = 8;
 			*bits = 8;
 			break;
 			break;
 		}
 		}
@@ -1712,9 +1718,7 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
 #define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
 #define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
 #endif
 #endif
 
 
-#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) || \
-	defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) || \
-	defined(CONFIG_CPU_S5PC100)
+#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
 static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
 static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
 	.info = &(struct s3c24xx_uart_info) {
 	.info = &(struct s3c24xx_uart_info) {
 		.name		= "Samsung S3C6400 UART",
 		.name		= "Samsung S3C6400 UART",

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

@@ -991,7 +991,6 @@ static const struct uart_ops sc16is7xx_ops = {
 	.stop_tx	= sc16is7xx_stop_tx,
 	.stop_tx	= sc16is7xx_stop_tx,
 	.start_tx	= sc16is7xx_start_tx,
 	.start_tx	= sc16is7xx_start_tx,
 	.stop_rx	= sc16is7xx_stop_rx,
 	.stop_rx	= sc16is7xx_stop_rx,
-	.enable_ms	= sc16is7xx_null_void,
 	.break_ctl	= sc16is7xx_break_ctl,
 	.break_ctl	= sc16is7xx_break_ctl,
 	.startup	= sc16is7xx_startup,
 	.startup	= sc16is7xx_startup,
 	.shutdown	= sc16is7xx_shutdown,
 	.shutdown	= sc16is7xx_shutdown,
@@ -1061,7 +1060,6 @@ static int sc16is7xx_probe(struct device *dev,
 			   struct regmap *regmap, int irq, unsigned long flags)
 			   struct regmap *regmap, int irq, unsigned long flags)
 {
 {
 	unsigned long freq, *pfreq = dev_get_platdata(dev);
 	unsigned long freq, *pfreq = dev_get_platdata(dev);
-	struct clk *clk;
 	int i, ret;
 	int i, ret;
 	struct sc16is7xx_port *s;
 	struct sc16is7xx_port *s;
 
 
@@ -1077,14 +1075,14 @@ static int sc16is7xx_probe(struct device *dev,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	clk = devm_clk_get(dev, NULL);
-	if (IS_ERR(clk)) {
+	s->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(s->clk)) {
 		if (pfreq)
 		if (pfreq)
 			freq = *pfreq;
 			freq = *pfreq;
 		else
 		else
-			return PTR_ERR(clk);
+			return PTR_ERR(s->clk);
 	} else {
 	} else {
-		freq = clk_get_rate(clk);
+		freq = clk_get_rate(s->clk);
 	}
 	}
 
 
 	s->regmap = regmap;
 	s->regmap = regmap;

+ 0 - 6
drivers/tty/serial/sccnxp.c

@@ -533,11 +533,6 @@ static unsigned int sccnxp_tx_empty(struct uart_port *port)
 	return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
 	return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
 }
 }
 
 
-static void sccnxp_enable_ms(struct uart_port *port)
-{
-	/* Do nothing */
-}
-
 static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 {
 	struct sccnxp_port *s = dev_get_drvdata(port->dev);
 	struct sccnxp_port *s = dev_get_drvdata(port->dev);
@@ -790,7 +785,6 @@ static const struct uart_ops sccnxp_ops = {
 	.stop_tx	= sccnxp_stop_tx,
 	.stop_tx	= sccnxp_stop_tx,
 	.start_tx	= sccnxp_start_tx,
 	.start_tx	= sccnxp_start_tx,
 	.stop_rx	= sccnxp_stop_rx,
 	.stop_rx	= sccnxp_stop_rx,
-	.enable_ms	= sccnxp_enable_ms,
 	.break_ctl	= sccnxp_break_ctl,
 	.break_ctl	= sccnxp_break_ctl,
 	.startup	= sccnxp_startup,
 	.startup	= sccnxp_startup,
 	.shutdown	= sccnxp_shutdown,
 	.shutdown	= sccnxp_shutdown,

+ 4 - 0
drivers/tty/serial/serial-tegra.c

@@ -482,6 +482,9 @@ static void tegra_uart_stop_tx(struct uart_port *u)
 	struct dma_tx_state state;
 	struct dma_tx_state state;
 	int count;
 	int count;
 
 
+	if (tup->tx_in_progress != TEGRA_UART_TX_DMA)
+		return;
+
 	dmaengine_terminate_all(tup->tx_dma_chan);
 	dmaengine_terminate_all(tup->tx_dma_chan);
 	dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
 	dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
 	count = tup->tx_bytes_requested - state.residue;
 	count = tup->tx_bytes_requested - state.residue;
@@ -599,6 +602,7 @@ static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
 
 
 	dmaengine_terminate_all(tup->rx_dma_chan);
 	dmaengine_terminate_all(tup->rx_dma_chan);
 	dmaengine_tx_status(tup->rx_dma_chan,  tup->rx_cookie, &state);
 	dmaengine_tx_status(tup->rx_dma_chan,  tup->rx_cookie, &state);
+	async_tx_ack(tup->rx_dma_desc);
 	count = tup->rx_bytes_requested - state.residue;
 	count = tup->rx_bytes_requested - state.residue;
 
 
 	/* If we are here, DMA is stopped */
 	/* If we are here, DMA is stopped */

+ 35 - 24
drivers/tty/serial/serial_core.c

@@ -243,6 +243,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
 		/*
 		/*
 		 * Turn off DTR and RTS early.
 		 * Turn off DTR and RTS early.
 		 */
 		 */
+		if (uart_console(uport) && tty)
+			uport->cons->cflag = tty->termios.c_cflag;
+
 		if (!tty || (tty->termios.c_cflag & HUPCL))
 		if (!tty || (tty->termios.c_cflag & HUPCL))
 			uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
 			uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
 
 
@@ -447,6 +450,7 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
 		return;
 		return;
 
 
 	termios = &tty->termios;
 	termios = &tty->termios;
+	uport->ops->set_termios(uport, termios, old_termios);
 
 
 	/*
 	/*
 	 * Set flags based on termios cflag
 	 * Set flags based on termios cflag
@@ -460,8 +464,6 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
 		clear_bit(ASYNCB_CHECK_CD, &port->flags);
 		clear_bit(ASYNCB_CHECK_CD, &port->flags);
 	else
 	else
 		set_bit(ASYNCB_CHECK_CD, &port->flags);
 		set_bit(ASYNCB_CHECK_CD, &port->flags);
-
-	uport->ops->set_termios(uport, termios, old_termios);
 }
 }
 
 
 static inline int __uart_put_char(struct uart_port *port,
 static inline int __uart_put_char(struct uart_port *port,
@@ -1050,6 +1052,15 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
 	return ret;
 	return ret;
 }
 }
 
 
+static void uart_enable_ms(struct uart_port *uport)
+{
+	/*
+	 * Force modem status interrupts on
+	 */
+	if (uport->ops->enable_ms)
+		uport->ops->enable_ms(uport);
+}
+
 /*
 /*
  * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
  * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
  * - mask passed in arg for lines of interest
  * - mask passed in arg for lines of interest
@@ -1073,11 +1084,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
 	 */
 	 */
 	spin_lock_irq(&uport->lock);
 	spin_lock_irq(&uport->lock);
 	memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
 	memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
-
-	/*
-	 * Force modem status interrupts on
-	 */
-	uport->ops->enable_ms(uport);
+	uart_enable_ms(uport);
 	spin_unlock_irq(&uport->lock);
 	spin_unlock_irq(&uport->lock);
 
 
 	add_wait_queue(&port->delta_msr_wait, &wait);
 	add_wait_queue(&port->delta_msr_wait, &wait);
@@ -1274,6 +1281,8 @@ static void uart_set_termios(struct tty_struct *tty,
 	}
 	}
 
 
 	uart_change_speed(tty, state, old_termios);
 	uart_change_speed(tty, state, old_termios);
+	/* reload cflag from termios; port driver may have overriden flags */
+	cflag = tty->termios.c_cflag;
 
 
 	/* Handle transition to B0 status */
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
 	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
@@ -1360,8 +1369,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 	tty_ldisc_flush(tty);
 	tty_ldisc_flush(tty);
 
 
 	tty_port_tty_set(port, NULL);
 	tty_port_tty_set(port, NULL);
-	spin_lock_irqsave(&port->lock, flags);
 	tty->closing = 0;
 	tty->closing = 0;
+	spin_lock_irqsave(&port->lock, flags);
 
 
 	if (port->blocked_open) {
 	if (port->blocked_open) {
 		spin_unlock_irqrestore(&port->lock, flags);
 		spin_unlock_irqrestore(&port->lock, flags);
@@ -1508,7 +1517,7 @@ static int uart_carrier_raised(struct tty_port *port)
 	struct uart_port *uport = state->uart_port;
 	struct uart_port *uport = state->uart_port;
 	int mctrl;
 	int mctrl;
 	spin_lock_irq(&uport->lock);
 	spin_lock_irq(&uport->lock);
-	uport->ops->enable_ms(uport);
+	uart_enable_ms(uport);
 	mctrl = uport->ops->get_mctrl(uport);
 	mctrl = uport->ops->get_mctrl(uport);
 	spin_unlock_irq(&uport->lock);
 	spin_unlock_irq(&uport->lock);
 	if (mctrl & TIOCM_CAR)
 	if (mctrl & TIOCM_CAR)
@@ -1575,14 +1584,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
 		(state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
 		(state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
 	tty_port_tty_set(port, tty);
 	tty_port_tty_set(port, tty);
 
 
-	/*
-	 * If the port is in the middle of closing, bail out now.
-	 */
-	if (tty_hung_up_p(filp)) {
-		retval = -EAGAIN;
-		goto err_dec_count;
-	}
-
 	/*
 	/*
 	 * Start up the serial port.
 	 * Start up the serial port.
 	 */
 	 */
@@ -2563,12 +2564,6 @@ static const struct attribute_group tty_dev_attr_group = {
 	.attrs = tty_dev_attrs,
 	.attrs = tty_dev_attrs,
 	};
 	};
 
 
-static const struct attribute_group *tty_dev_attr_groups[] = {
-	&tty_dev_attr_group,
-	NULL
-	};
-
-
 /**
 /**
  *	uart_add_one_port - attach a driver-defined port structure
  *	uart_add_one_port - attach a driver-defined port structure
  *	@drv: pointer to the uart low level driver structure for this port
  *	@drv: pointer to the uart low level driver structure for this port
@@ -2585,6 +2580,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 	struct tty_port *port;
 	struct tty_port *port;
 	int ret = 0;
 	int ret = 0;
 	struct device *tty_dev;
 	struct device *tty_dev;
+	int num_groups;
 
 
 	BUG_ON(in_interrupt());
 	BUG_ON(in_interrupt());
 
 
@@ -2618,12 +2614,26 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 
 
 	uart_configure_port(drv, state, uport);
 	uart_configure_port(drv, state, uport);
 
 
+	num_groups = 2;
+	if (uport->attr_group)
+		num_groups++;
+
+	uport->tty_groups = kcalloc(num_groups, sizeof(*uport->tty_groups),
+				    GFP_KERNEL);
+	if (!uport->tty_groups) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	uport->tty_groups[0] = &tty_dev_attr_group;
+	if (uport->attr_group)
+		uport->tty_groups[1] = uport->attr_group;
+
 	/*
 	/*
 	 * Register the port whether it's detected or not.  This allows
 	 * Register the port whether it's detected or not.  This allows
 	 * setserial to be used to alter this port's parameters.
 	 * setserial to be used to alter this port's parameters.
 	 */
 	 */
 	tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
 	tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
-			uport->line, uport->dev, port, tty_dev_attr_groups);
+			uport->line, uport->dev, port, uport->tty_groups);
 	if (likely(!IS_ERR(tty_dev))) {
 	if (likely(!IS_ERR(tty_dev))) {
 		device_set_wakeup_capable(tty_dev, 1);
 		device_set_wakeup_capable(tty_dev, 1);
 	} else {
 	} else {
@@ -2702,6 +2712,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
 	 */
 	 */
 	if (uport->type != PORT_UNKNOWN)
 	if (uport->type != PORT_UNKNOWN)
 		uport->ops->release_port(uport);
 		uport->ops->release_port(uport);
+	kfree(uport->tty_groups);
 
 
 	/*
 	/*
 	 * Indicate that there isn't a port here anymore.
 	 * Indicate that there isn't a port here anymore.

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

@@ -142,7 +142,6 @@ struct uart_txx9_port {
 #define TXX9_SIFCR_RDIL_12	0x00000180
 #define TXX9_SIFCR_RDIL_12	0x00000180
 #define TXX9_SIFCR_RDIL_MAX	0x00000180
 #define TXX9_SIFCR_RDIL_MAX	0x00000180
 #define TXX9_SIFCR_TDIL_MASK	0x00000018
 #define TXX9_SIFCR_TDIL_MASK	0x00000018
-#define TXX9_SIFCR_TDIL_MASK	0x00000018
 #define TXX9_SIFCR_TDIL_1	0x00000000
 #define TXX9_SIFCR_TDIL_1	0x00000000
 #define TXX9_SIFCR_TDIL_4	0x00000001
 #define TXX9_SIFCR_TDIL_4	0x00000001
 #define TXX9_SIFCR_TDIL_8	0x00000010
 #define TXX9_SIFCR_TDIL_8	0x00000010
@@ -244,11 +243,6 @@ static void serial_txx9_stop_rx(struct uart_port *port)
 	up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
 	up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
 }
 }
 
 
-static void serial_txx9_enable_ms(struct uart_port *port)
-{
-	/* TXX9-SIO can not control DTR... */
-}
-
 static void serial_txx9_initialize(struct uart_port *port)
 static void serial_txx9_initialize(struct uart_port *port)
 {
 {
 	struct uart_txx9_port *up = to_uart_txx9_port(port);
 	struct uart_txx9_port *up = to_uart_txx9_port(port);
@@ -858,7 +852,6 @@ static struct uart_ops serial_txx9_pops = {
 	.stop_tx	= serial_txx9_stop_tx,
 	.stop_tx	= serial_txx9_stop_tx,
 	.start_tx	= serial_txx9_start_tx,
 	.start_tx	= serial_txx9_start_tx,
 	.stop_rx	= serial_txx9_stop_rx,
 	.stop_rx	= serial_txx9_stop_rx,
-	.enable_ms	= serial_txx9_enable_ms,
 	.break_ctl	= serial_txx9_break_ctl,
 	.break_ctl	= serial_txx9_break_ctl,
 	.startup	= serial_txx9_startup,
 	.startup	= serial_txx9_startup,
 	.shutdown	= serial_txx9_shutdown,
 	.shutdown	= serial_txx9_shutdown,

+ 64 - 30
drivers/tty/serial/sh-sci.c

@@ -1560,13 +1560,6 @@ static void sci_stop_rx(struct uart_port *port)
 	serial_port_out(port, SCSCR, ctrl);
 	serial_port_out(port, SCSCR, ctrl);
 }
 }
 
 
-static void sci_enable_ms(struct uart_port *port)
-{
-	/*
-	 * Not supported by hardware, always a nop.
-	 */
-}
-
 static void sci_break_ctl(struct uart_port *port, int break_state)
 static void sci_break_ctl(struct uart_port *port, int break_state)
 {
 {
 	struct sci_port *s = to_sci_port(port);
 	struct sci_port *s = to_sci_port(port);
@@ -1783,30 +1776,71 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 	return ((freq + 16 * bps) / (32 * bps) - 1);
 	return ((freq + 16 * bps) / (32 * bps) - 1);
 }
 }
 
 
+/* calculate frame length from SMR */
+static int sci_baud_calc_frame_len(unsigned int smr_val)
+{
+	int len = 10;
+
+	if (smr_val & SCSMR_CHR)
+		len--;
+	if (smr_val & SCSMR_PE)
+		len++;
+	if (smr_val & SCSMR_STOP)
+		len++;
+
+	return len;
+}
+
+
 /* calculate sample rate, BRR, and clock select for HSCIF */
 /* calculate sample rate, BRR, and clock select for HSCIF */
 static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
 static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
 				int *brr, unsigned int *srr,
 				int *brr, unsigned int *srr,
-				unsigned int *cks)
+				unsigned int *cks, int frame_len)
 {
 {
-	int sr, c, br, err;
+	int sr, c, br, err, recv_margin;
 	int min_err = 1000; /* 100% */
 	int min_err = 1000; /* 100% */
+	int recv_max_margin = 0;
 
 
 	/* Find the combination of sample rate and clock select with the
 	/* Find the combination of sample rate and clock select with the
 	   smallest deviation from the desired baud rate. */
 	   smallest deviation from the desired baud rate. */
 	for (sr = 8; sr <= 32; sr++) {
 	for (sr = 8; sr <= 32; sr++) {
 		for (c = 0; c <= 3; c++) {
 		for (c = 0; c <= 3; c++) {
 			/* integerized formulas from HSCIF documentation */
 			/* integerized formulas from HSCIF documentation */
-			br = freq / (sr * (1 << (2 * c + 1)) * bps) - 1;
-			if (br < 0 || br > 255)
+			br = DIV_ROUND_CLOSEST(freq, (sr *
+					      (1 << (2 * c + 1)) * bps)) - 1;
+			br = clamp(br, 0, 255);
+			err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr *
+					       (1 << (2 * c + 1)) / 1000)) -
+					       1000;
+			if (err < 0)
 				continue;
 				continue;
-			err = freq / ((br + 1) * bps * sr *
-			      (1 << (2 * c + 1)) / 1000) - 1000;
+
+			/* Calc recv margin
+			 * M: Receive margin (%)
+			 * N: Ratio of bit rate to clock (N = sampling rate)
+			 * D: Clock duty (D = 0 to 1.0)
+			 * L: Frame length (L = 9 to 12)
+			 * F: Absolute value of clock frequency deviation
+			 *
+			 *  M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) -
+			 *      (|D - 0.5| / N * (1 + F))|
+			 *  NOTE: Usually, treat D for 0.5, F is 0 by this
+			 *        calculation.
+			 */
+			recv_margin = abs((500 -
+					DIV_ROUND_CLOSEST(1000, sr << 1)) / 10);
 			if (min_err > err) {
 			if (min_err > err) {
 				min_err = err;
 				min_err = err;
-				*brr = br;
-				*srr = sr - 1;
-				*cks = c;
-			}
+				recv_max_margin = recv_margin;
+			} else if ((min_err == err) &&
+				   (recv_margin > recv_max_margin))
+				recv_max_margin = recv_margin;
+			else
+				continue;
+
+			*brr = br;
+			*srr = sr - 1;
+			*cks = c;
 		}
 		}
 	}
 	}
 
 
@@ -1840,10 +1874,19 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 {
 {
 	struct sci_port *s = to_sci_port(port);
 	struct sci_port *s = to_sci_port(port);
 	struct plat_sci_reg *reg;
 	struct plat_sci_reg *reg;
-	unsigned int baud, smr_val, max_baud, cks = 0;
+	unsigned int baud, smr_val = 0, max_baud, cks = 0;
 	int t = -1;
 	int t = -1;
 	unsigned int srr = 15;
 	unsigned int srr = 15;
 
 
+	if ((termios->c_cflag & CSIZE) == CS7)
+		smr_val |= SCSMR_CHR;
+	if (termios->c_cflag & PARENB)
+		smr_val |= SCSMR_PE;
+	if (termios->c_cflag & PARODD)
+		smr_val |= SCSMR_PE | SCSMR_ODD;
+	if (termios->c_cflag & CSTOPB)
+		smr_val |= SCSMR_STOP;
+
 	/*
 	/*
 	 * earlyprintk comes here early on with port->uartclk set to zero.
 	 * earlyprintk comes here early on with port->uartclk set to zero.
 	 * the clock framework is not up and running at this point so here
 	 * the clock framework is not up and running at this point so here
@@ -1857,8 +1900,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 	baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
 	baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
 	if (likely(baud && port->uartclk)) {
 	if (likely(baud && port->uartclk)) {
 		if (s->cfg->type == PORT_HSCIF) {
 		if (s->cfg->type == PORT_HSCIF) {
+			int frame_len = sci_baud_calc_frame_len(smr_val);
 			sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
 			sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
-					    &cks);
+					    &cks, frame_len);
 		} else {
 		} else {
 			t = sci_scbrr_calc(s, baud, port->uartclk);
 			t = sci_scbrr_calc(s, baud, port->uartclk);
 			for (cks = 0; t >= 256 && cks <= 3; cks++)
 			for (cks = 0; t >= 256 && cks <= 3; cks++)
@@ -1870,16 +1914,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 
 	sci_reset(port);
 	sci_reset(port);
 
 
-	smr_val = serial_port_in(port, SCSMR) & 3;
-
-	if ((termios->c_cflag & CSIZE) == CS7)
-		smr_val |= SCSMR_CHR;
-	if (termios->c_cflag & PARENB)
-		smr_val |= SCSMR_PE;
-	if (termios->c_cflag & PARODD)
-		smr_val |= SCSMR_PE | SCSMR_ODD;
-	if (termios->c_cflag & CSTOPB)
-		smr_val |= SCSMR_STOP;
+	smr_val |= serial_port_in(port, SCSMR) & 3;
 
 
 	uart_update_timeout(port, termios->c_cflag, baud);
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 
@@ -2080,7 +2115,6 @@ static struct uart_ops sci_uart_ops = {
 	.start_tx	= sci_start_tx,
 	.start_tx	= sci_start_tx,
 	.stop_tx	= sci_stop_tx,
 	.stop_tx	= sci_stop_tx,
 	.stop_rx	= sci_stop_rx,
 	.stop_rx	= sci_stop_rx,
-	.enable_ms	= sci_enable_ms,
 	.break_ctl	= sci_break_ctl,
 	.break_ctl	= sci_break_ctl,
 	.startup	= sci_startup,
 	.startup	= sci_startup,
 	.shutdown	= sci_shutdown,
 	.shutdown	= sci_shutdown,

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

@@ -290,7 +290,8 @@ static void sirfsoc_uart_start_tx(struct uart_port *port)
 	if (sirfport->tx_dma_chan)
 	if (sirfport->tx_dma_chan)
 		sirfsoc_uart_tx_with_dma(sirfport);
 		sirfsoc_uart_tx_with_dma(sirfport);
 	else {
 	else {
-		sirfsoc_uart_pio_tx_chars(sirfport, 1);
+		sirfsoc_uart_pio_tx_chars(sirfport,
+			SIRFSOC_UART_IO_TX_REASONABLE_CNT);
 		wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
 		wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
 		if (!sirfport->is_marco)
 		if (!sirfport->is_marco)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 			wr_regl(port, ureg->sirfsoc_int_en_reg,

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

@@ -449,4 +449,4 @@ struct sirfsoc_uart_port {
 
 
 /* I/O Mode */
 /* I/O Mode */
 #define SIRFSOC_UART_IO_RX_MAX_CNT		256
 #define SIRFSOC_UART_IO_RX_MAX_CNT		256
-#define SIRFSOC_UART_IO_TX_REASONABLE_CNT	6
+#define SIRFSOC_UART_IO_TX_REASONABLE_CNT	256

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

@@ -274,15 +274,6 @@ static void snp_release_port(struct uart_port *port)
 {
 {
 }
 }
 
 
-/**
- * snp_enable_ms - Force modem status interrupts on - no-op for us
- * @port: Port to operate on - we ignore - no-op function
- *
- */
-static void snp_enable_ms(struct uart_port *port)
-{
-}
-
 /**
 /**
  * snp_shutdown - shut down the port - free irq and disable - no-op for us
  * snp_shutdown - shut down the port - free irq and disable - no-op for us
  * @port: Port to shut down - we ignore
  * @port: Port to shut down - we ignore
@@ -396,7 +387,6 @@ static struct uart_ops sn_console_ops = {
 	.stop_tx = snp_stop_tx,
 	.stop_tx = snp_stop_tx,
 	.start_tx = snp_start_tx,
 	.start_tx = snp_start_tx,
 	.stop_rx = snp_stop_rx,
 	.stop_rx = snp_stop_rx,
-	.enable_ms = snp_enable_ms,
 	.break_ctl = snp_break_ctl,
 	.break_ctl = snp_break_ctl,
 	.startup = snp_startup,
 	.startup = snp_startup,
 	.shutdown = snp_shutdown,
 	.shutdown = snp_shutdown,

+ 7 - 13
drivers/tty/serial/st-asc.c

@@ -411,12 +411,6 @@ static void asc_stop_rx(struct uart_port *port)
 	asc_disable_rx_interrupts(port);
 	asc_disable_rx_interrupts(port);
 }
 }
 
 
-/* Force modem status interrupts on */
-static void asc_enable_ms(struct uart_port *port)
-{
-	/* Nothing here yet .. */
-}
-
 /* Handle breaks - ignored by us */
 /* Handle breaks - ignored by us */
 static void asc_break_ctl(struct uart_port *port, int break_state)
 static void asc_break_ctl(struct uart_port *port, int break_state)
 {
 {
@@ -533,12 +527,12 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
 		 * ASCBaudRate =   ------------------------
 		 * ASCBaudRate =   ------------------------
 		 *                          inputclock
 		 *                          inputclock
 		 *
 		 *
-		 * However to keep the maths inside 32bits we divide top and
-		 * bottom by 64. The +1 is to avoid a divide by zero if the
-		 * input clock rate is something unexpected.
+		 * To keep maths inside 64bits, we divide inputclock by 16.
 		 */
 		 */
-		u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1);
-		asc_out(port, ASC_BAUDRATE, counter);
+		u64 dividend = (u64)baud * (1 << 16);
+
+		do_div(dividend, port->uartclk / 16);
+		asc_out(port, ASC_BAUDRATE, dividend);
 		ctrl_val |= ASC_CTL_BAUDMODE;
 		ctrl_val |= ASC_CTL_BAUDMODE;
 	}
 	}
 
 
@@ -644,7 +638,6 @@ static struct uart_ops asc_uart_ops = {
 	.start_tx	= asc_start_tx,
 	.start_tx	= asc_start_tx,
 	.stop_tx	= asc_stop_tx,
 	.stop_tx	= asc_stop_tx,
 	.stop_rx	= asc_stop_rx,
 	.stop_rx	= asc_stop_rx,
-	.enable_ms	= asc_enable_ms,
 	.break_ctl	= asc_break_ctl,
 	.break_ctl	= asc_break_ctl,
 	.startup	= asc_startup,
 	.startup	= asc_startup,
 	.shutdown	= asc_shutdown,
 	.shutdown	= asc_shutdown,
@@ -849,7 +842,8 @@ static int asc_console_setup(struct console *co, char *options)
 	 * this to be called during the uart port registration when the
 	 * this to be called during the uart port registration when the
 	 * driver gets probed and the port should be mapped at that point.
 	 * driver gets probed and the port should be mapped at that point.
 	 */
 	 */
-	BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
+	if (ascport->port.mapbase == 0 || ascport->port.membase == NULL)
+		return -ENXIO;
 
 
 	if (options)
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 		uart_parse_options(options, &baud, &parity, &bits, &flow);

+ 0 - 6
drivers/tty/serial/sunhv.c

@@ -285,11 +285,6 @@ static void sunhv_stop_rx(struct uart_port *port)
 {
 {
 }
 }
 
 
-/* port->lock held by caller.  */
-static void sunhv_enable_ms(struct uart_port *port)
-{
-}
-
 /* port->lock is not held.  */
 /* port->lock is not held.  */
 static void sunhv_break_ctl(struct uart_port *port, int break_state)
 static void sunhv_break_ctl(struct uart_port *port, int break_state)
 {
 {
@@ -379,7 +374,6 @@ static struct uart_ops sunhv_pops = {
 	.start_tx	= sunhv_start_tx,
 	.start_tx	= sunhv_start_tx,
 	.send_xchar	= sunhv_send_xchar,
 	.send_xchar	= sunhv_send_xchar,
 	.stop_rx	= sunhv_stop_rx,
 	.stop_rx	= sunhv_stop_rx,
-	.enable_ms	= sunhv_enable_ms,
 	.break_ctl	= sunhv_break_ctl,
 	.break_ctl	= sunhv_break_ctl,
 	.startup	= sunhv_startup,
 	.startup	= sunhv_startup,
 	.shutdown	= sunhv_shutdown,
 	.shutdown	= sunhv_shutdown,

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

@@ -476,12 +476,6 @@ static void sunsab_stop_rx(struct uart_port *port)
 	writeb(up->interrupt_mask1, &up->regs->w.imr0);
 	writeb(up->interrupt_mask1, &up->regs->w.imr0);
 }
 }
 
 
-/* port->lock held by caller.  */
-static void sunsab_enable_ms(struct uart_port *port)
-{
-	/* For now we always receive these interrupts.  */
-}
-
 /* port->lock is not held.  */
 /* port->lock is not held.  */
 static void sunsab_break_ctl(struct uart_port *port, int break_state)
 static void sunsab_break_ctl(struct uart_port *port, int break_state)
 {
 {
@@ -810,7 +804,6 @@ static struct uart_ops sunsab_pops = {
 	.start_tx	= sunsab_start_tx,
 	.start_tx	= sunsab_start_tx,
 	.send_xchar	= sunsab_send_xchar,
 	.send_xchar	= sunsab_send_xchar,
 	.stop_rx	= sunsab_stop_rx,
 	.stop_rx	= sunsab_stop_rx,
-	.enable_ms	= sunsab_enable_ms,
 	.break_ctl	= sunsab_break_ctl,
 	.break_ctl	= sunsab_break_ctl,
 	.startup	= sunsab_startup,
 	.startup	= sunsab_startup,
 	.shutdown	= sunsab_shutdown,
 	.shutdown	= sunsab_shutdown,

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

@@ -314,15 +314,6 @@ static void tilegx_stop_rx(struct uart_port *port)
 	mutex_unlock(&tile_uart->mutex);
 	mutex_unlock(&tile_uart->mutex);
 }
 }
 
 
-
-/*
- * Enable modem status interrupts.
- */
-static void tilegx_enable_ms(struct uart_port *port)
-{
-	/* N/A */
-}
-
 /*
 /*
  * Control the transmission of a break signal.
  * Control the transmission of a break signal.
  */
  */
@@ -614,7 +605,6 @@ static const struct uart_ops tilegx_ops = {
 	.stop_tx	= tilegx_stop_tx,
 	.stop_tx	= tilegx_stop_tx,
 	.start_tx	= tilegx_start_tx,
 	.start_tx	= tilegx_start_tx,
 	.stop_rx	= tilegx_stop_rx,
 	.stop_rx	= tilegx_stop_rx,
-	.enable_ms	= tilegx_enable_ms,
 	.break_ctl	= tilegx_break_ctl,
 	.break_ctl	= tilegx_break_ctl,
 	.startup	= tilegx_startup,
 	.startup	= tilegx_startup,
 	.shutdown	= tilegx_shutdown,
 	.shutdown	= tilegx_shutdown,

+ 0 - 6
drivers/tty/serial/timbuart.c

@@ -244,11 +244,6 @@ static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
 	*ier |= CTS_DELTA;
 	*ier |= CTS_DELTA;
 }
 }
 
 
-static void timbuart_enable_ms(struct uart_port *port)
-{
-	/* N/A */
-}
-
 static void timbuart_break_ctl(struct uart_port *port, int ctl)
 static void timbuart_break_ctl(struct uart_port *port, int ctl)
 {
 {
 	/* N/A */
 	/* N/A */
@@ -405,7 +400,6 @@ static struct uart_ops timbuart_ops = {
 	.start_tx = timbuart_start_tx,
 	.start_tx = timbuart_start_tx,
 	.flush_buffer = timbuart_flush_buffer,
 	.flush_buffer = timbuart_flush_buffer,
 	.stop_rx = timbuart_stop_rx,
 	.stop_rx = timbuart_stop_rx,
-	.enable_ms = timbuart_enable_ms,
 	.break_ctl = timbuart_break_ctl,
 	.break_ctl = timbuart_break_ctl,
 	.startup = timbuart_startup,
 	.startup = timbuart_startup,
 	.shutdown = timbuart_shutdown,
 	.shutdown = timbuart_shutdown,

+ 0 - 6
drivers/tty/serial/uartlite.c

@@ -250,11 +250,6 @@ static void ulite_stop_rx(struct uart_port *port)
 		| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
 		| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
 }
 }
 
 
-static void ulite_enable_ms(struct uart_port *port)
-{
-	/* N/A */
-}
-
 static void ulite_break_ctl(struct uart_port *port, int ctl)
 static void ulite_break_ctl(struct uart_port *port, int ctl)
 {
 {
 	/* N/A */
 	/* N/A */
@@ -395,7 +390,6 @@ static struct uart_ops ulite_ops = {
 	.stop_tx	= ulite_stop_tx,
 	.stop_tx	= ulite_stop_tx,
 	.start_tx	= ulite_start_tx,
 	.start_tx	= ulite_start_tx,
 	.stop_rx	= ulite_stop_rx,
 	.stop_rx	= ulite_stop_rx,
-	.enable_ms	= ulite_enable_ms,
 	.break_ctl	= ulite_break_ctl,
 	.break_ctl	= ulite_break_ctl,
 	.startup	= ulite_startup,
 	.startup	= ulite_startup,
 	.shutdown	= ulite_shutdown,
 	.shutdown	= ulite_shutdown,

+ 0 - 11
drivers/tty/serial/ucc_uart.c

@@ -435,16 +435,6 @@ static void qe_uart_stop_rx(struct uart_port *port)
 	clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
 	clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
 }
 }
 
 
-/*
- * Enable status change interrupts
- *
- * We don't support status change interrupts, but we need to define this
- * function otherwise the kernel will panic.
- */
-static void qe_uart_enable_ms(struct uart_port *port)
-{
-}
-
 /* Start or stop sending  break signal
 /* Start or stop sending  break signal
  *
  *
  * This function controls the sending of a break signal.  If break_state=1,
  * This function controls the sending of a break signal.  If break_state=1,
@@ -1102,7 +1092,6 @@ static struct uart_ops qe_uart_pops = {
 	.stop_tx	= qe_uart_stop_tx,
 	.stop_tx	= qe_uart_stop_tx,
 	.start_tx       = qe_uart_start_tx,
 	.start_tx       = qe_uart_start_tx,
 	.stop_rx	= qe_uart_stop_rx,
 	.stop_rx	= qe_uart_stop_rx,
-	.enable_ms      = qe_uart_enable_ms,
 	.break_ctl      = qe_uart_break_ctl,
 	.break_ctl      = qe_uart_break_ctl,
 	.startup	= qe_uart_startup,
 	.startup	= qe_uart_startup,
 	.shutdown       = qe_uart_shutdown,
 	.shutdown       = qe_uart_shutdown,

+ 0 - 6
drivers/tty/serial/xilinx_uartps.c

@@ -918,11 +918,6 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	/* N/A */
 	/* N/A */
 }
 }
 
 
-static void cdns_uart_enable_ms(struct uart_port *port)
-{
-	/* N/A */
-}
-
 #ifdef CONFIG_CONSOLE_POLL
 #ifdef CONFIG_CONSOLE_POLL
 static int cdns_uart_poll_get_char(struct uart_port *port)
 static int cdns_uart_poll_get_char(struct uart_port *port)
 {
 {
@@ -974,7 +969,6 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c)
 static struct uart_ops cdns_uart_ops = {
 static struct uart_ops cdns_uart_ops = {
 	.set_mctrl	= cdns_uart_set_mctrl,
 	.set_mctrl	= cdns_uart_set_mctrl,
 	.get_mctrl	= cdns_uart_get_mctrl,
 	.get_mctrl	= cdns_uart_get_mctrl,
-	.enable_ms	= cdns_uart_enable_ms,
 	.start_tx	= cdns_uart_start_tx,
 	.start_tx	= cdns_uart_start_tx,
 	.stop_tx	= cdns_uart_stop_tx,
 	.stop_tx	= cdns_uart_stop_tx,
 	.stop_rx	= cdns_uart_stop_rx,
 	.stop_rx	= cdns_uart_stop_rx,

+ 3 - 7
drivers/tty/synclink.c

@@ -3267,7 +3267,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 	DECLARE_WAITQUEUE(wait, current);
 	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		retval;
 	bool		do_clocal = false;
 	bool		do_clocal = false;
-	bool		extra_count = false;
 	unsigned long	flags;
 	unsigned long	flags;
 	int		dcd;
 	int		dcd;
 	struct tty_port *port = &info->port;
 	struct tty_port *port = &info->port;
@@ -3300,10 +3299,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			 __FILE__,__LINE__, tty->driver->name, port->count );
 			 __FILE__,__LINE__, tty->driver->name, port->count );
 
 
 	spin_lock_irqsave(&info->irq_spinlock, flags);
 	spin_lock_irqsave(&info->irq_spinlock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
+	port->count--;
 	spin_unlock_irqrestore(&info->irq_spinlock, flags);
 	spin_unlock_irqrestore(&info->irq_spinlock, flags);
 	port->blocked_open++;
 	port->blocked_open++;
 	
 	
@@ -3342,7 +3338,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 	remove_wait_queue(&port->open_wait, &wait);
 	remove_wait_queue(&port->open_wait, &wait);
 	
 	
 	/* FIXME: Racy on hangup during close wait */
 	/* FIXME: Racy on hangup during close wait */
-	if (extra_count)
+	if (!tty_hung_up_p(filp))
 		port->count++;
 		port->count++;
 	port->blocked_open--;
 	port->blocked_open--;
 	
 	
@@ -3403,7 +3399,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 
 
 	/* If port is closing, signal caller to try again */
 	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
+	if (info->port.flags & ASYNC_CLOSING){
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 				     !(info->port.flags & ASYNC_CLOSING));
 				     !(info->port.flags & ASYNC_CLOSING));
 		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
 		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?

+ 3 - 7
drivers/tty/synclink_gt.c

@@ -673,7 +673,7 @@ static int open(struct tty_struct *tty, struct file *filp)
 	DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
 	DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
 
 
 	/* If port is closing, signal caller to try again */
 	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
+	if (info->port.flags & ASYNC_CLOSING){
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 					     !(info->port.flags & ASYNC_CLOSING));
 					     !(info->port.flags & ASYNC_CLOSING));
 		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
 		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
@@ -3273,7 +3273,6 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 	DECLARE_WAITQUEUE(wait, current);
 	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		retval;
 	bool		do_clocal = false;
 	bool		do_clocal = false;
-	bool		extra_count = false;
 	unsigned long	flags;
 	unsigned long	flags;
 	int		cd;
 	int		cd;
 	struct tty_port *port = &info->port;
 	struct tty_port *port = &info->port;
@@ -3300,10 +3299,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 	add_wait_queue(&port->open_wait, &wait);
 	add_wait_queue(&port->open_wait, &wait);
 
 
 	spin_lock_irqsave(&info->lock, flags);
 	spin_lock_irqsave(&info->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
+	port->count--;
 	spin_unlock_irqrestore(&info->lock, flags);
 	spin_unlock_irqrestore(&info->lock, flags);
 	port->blocked_open++;
 	port->blocked_open++;
 
 
@@ -3338,7 +3334,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 	set_current_state(TASK_RUNNING);
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->open_wait, &wait);
 	remove_wait_queue(&port->open_wait, &wait);
 
 
-	if (extra_count)
+	if (!tty_hung_up_p(filp))
 		port->count++;
 		port->count++;
 	port->blocked_open--;
 	port->blocked_open--;
 
 

+ 3 - 8
drivers/tty/synclinkmp.c

@@ -753,7 +753,7 @@ static int open(struct tty_struct *tty, struct file *filp)
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 			 __FILE__,__LINE__,tty->driver->name, info->port.count);
 
 
 	/* If port is closing, signal caller to try again */
 	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
+	if (info->port.flags & ASYNC_CLOSING){
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 		wait_event_interruptible_tty(tty, info->port.close_wait,
 					     !(info->port.flags & ASYNC_CLOSING));
 					     !(info->port.flags & ASYNC_CLOSING));
 		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
 		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
@@ -3288,7 +3288,6 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 	DECLARE_WAITQUEUE(wait, current);
 	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		retval;
 	bool		do_clocal = false;
 	bool		do_clocal = false;
-	bool		extra_count = false;
 	unsigned long	flags;
 	unsigned long	flags;
 	int		cd;
 	int		cd;
 	struct tty_port *port = &info->port;
 	struct tty_port *port = &info->port;
@@ -3322,10 +3321,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 			 __FILE__,__LINE__, tty->driver->name, port->count );
 			 __FILE__,__LINE__, tty->driver->name, port->count );
 
 
 	spin_lock_irqsave(&info->lock, flags);
 	spin_lock_irqsave(&info->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
+	port->count--;
 	spin_unlock_irqrestore(&info->lock, flags);
 	spin_unlock_irqrestore(&info->lock, flags);
 	port->blocked_open++;
 	port->blocked_open++;
 
 
@@ -3362,8 +3358,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 
 
 	set_current_state(TASK_RUNNING);
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->open_wait, &wait);
 	remove_wait_queue(&port->open_wait, &wait);
-
-	if (extra_count)
+	if (!tty_hung_up_p(filp))
 		port->count++;
 		port->count++;
 	port->blocked_open--;
 	port->blocked_open--;
 
 

+ 14 - 25
drivers/tty/tty_io.c

@@ -156,20 +156,6 @@ static void release_tty(struct tty_struct *tty, int idx);
 static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 
 
-/**
- *	alloc_tty_struct	-	allocate a tty object
- *
- *	Return a new empty tty structure. The data fields have not
- *	been initialized in any way but has been zeroed
- *
- *	Locking: none
- */
-
-struct tty_struct *alloc_tty_struct(void)
-{
-	return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
-}
-
 /**
 /**
  *	free_tty_struct		-	free a disused tty
  *	free_tty_struct		-	free a disused tty
  *	@tty: tty struct to free
  *	@tty: tty struct to free
@@ -688,7 +674,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
 			for (n = 0; n < closecount; n++)
 			for (n = 0; n < closecount; n++)
 				tty->ops->close(tty, cons_filp);
 				tty->ops->close(tty, cons_filp);
 	} else if (tty->ops->hangup)
 	} else if (tty->ops->hangup)
-		(tty->ops->hangup)(tty);
+		tty->ops->hangup(tty);
 	/*
 	/*
 	 * We don't want to have driver/ldisc interactions beyond
 	 * We don't want to have driver/ldisc interactions beyond
 	 * the ones we did here. The driver layer expects no
 	 * the ones we did here. The driver layer expects no
@@ -1455,12 +1441,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
 	if (!try_module_get(driver->owner))
 	if (!try_module_get(driver->owner))
 		return ERR_PTR(-ENODEV);
 		return ERR_PTR(-ENODEV);
 
 
-	tty = alloc_tty_struct();
+	tty = alloc_tty_struct(driver, idx);
 	if (!tty) {
 	if (!tty) {
 		retval = -ENOMEM;
 		retval = -ENOMEM;
 		goto err_module_put;
 		goto err_module_put;
 	}
 	}
-	initialize_tty_struct(tty, driver, idx);
 
 
 	tty_lock(tty);
 	tty_lock(tty);
 	retval = tty_driver_install_tty(driver, tty);
 	retval = tty_driver_install_tty(driver, tty);
@@ -3003,19 +2988,21 @@ static struct device *tty_get_device(struct tty_struct *tty)
 
 
 
 
 /**
 /**
- *	initialize_tty_struct
- *	@tty: tty to initialize
+ *	alloc_tty_struct
  *
  *
- *	This subroutine initializes a tty structure that has been newly
- *	allocated.
+ *	This subroutine allocates and initializes a tty structure.
  *
  *
- *	Locking: none - tty in question must not be exposed at this point
+ *	Locking: none - tty in question is not exposed at this point
  */
  */
 
 
-void initialize_tty_struct(struct tty_struct *tty,
-		struct tty_driver *driver, int idx)
+struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
 {
 {
-	memset(tty, 0, sizeof(struct tty_struct));
+	struct tty_struct *tty;
+
+	tty = kzalloc(sizeof(*tty), GFP_KERNEL);
+	if (!tty)
+		return NULL;
+
 	kref_init(&tty->kref);
 	kref_init(&tty->kref);
 	tty->magic = TTY_MAGIC;
 	tty->magic = TTY_MAGIC;
 	tty_ldisc_init(tty);
 	tty_ldisc_init(tty);
@@ -3039,6 +3026,8 @@ void initialize_tty_struct(struct tty_struct *tty,
 	tty->index = idx;
 	tty->index = idx;
 	tty_line_name(driver, idx, tty->name);
 	tty_line_name(driver, idx, tty->name);
 	tty->dev = tty_get_device(tty);
 	tty->dev = tty_get_device(tty);
+
+	return tty;
 }
 }
 
 
 /**
 /**

+ 36 - 7
drivers/tty/tty_port.c

@@ -227,6 +227,8 @@ out:
  *
  *
  *	Perform port level tty hangup flag and count changes. Drop the tty
  *	Perform port level tty hangup flag and count changes. Drop the tty
  *	reference.
  *	reference.
+ *
+ *	Caller holds tty lock.
  */
  */
 
 
 void tty_port_hangup(struct tty_port *port)
 void tty_port_hangup(struct tty_port *port)
@@ -348,6 +350,11 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts);
  *	do carrier detect and the dtr_rts method if it supports software
  *	do carrier detect and the dtr_rts method if it supports software
  *	management of these lines. Note that the dtr/rts raise is done each
  *	management of these lines. Note that the dtr/rts raise is done each
  *	iteration as a hangup may have previously dropped them while we wait.
  *	iteration as a hangup may have previously dropped them while we wait.
+ *
+ *	Caller holds tty lock.
+ *
+ *      NB: May drop and reacquire tty lock when blocking, so tty and tty_port
+ *      may have changed state (eg., may have been hung up).
  */
  */
 
 
 int tty_port_block_til_ready(struct tty_port *port,
 int tty_port_block_til_ready(struct tty_port *port,
@@ -358,7 +365,7 @@ int tty_port_block_til_ready(struct tty_port *port,
 	DEFINE_WAIT(wait);
 	DEFINE_WAIT(wait);
 
 
 	/* block if port is in the process of being closed */
 	/* block if port is in the process of being closed */
-	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
+	if (port->flags & ASYNC_CLOSING) {
 		wait_event_interruptible_tty(tty, port->close_wait,
 		wait_event_interruptible_tty(tty, port->close_wait,
 				!(port->flags & ASYNC_CLOSING));
 				!(port->flags & ASYNC_CLOSING));
 		if (port->flags & ASYNC_HUP_NOTIFY)
 		if (port->flags & ASYNC_HUP_NOTIFY)
@@ -392,8 +399,7 @@ int tty_port_block_til_ready(struct tty_port *port,
 
 
 	/* The port lock protects the port counts */
 	/* The port lock protects the port counts */
 	spin_lock_irqsave(&port->lock, flags);
 	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp))
-		port->count--;
+	port->count--;
 	port->blocked_open++;
 	port->blocked_open++;
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 
@@ -458,6 +464,10 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
 	schedule_timeout_interruptible(timeout);
 	schedule_timeout_interruptible(timeout);
 }
 }
 
 
+/* Caller holds tty lock.
+ * NB: may drop and reacquire tty lock (in tty_wait_until_sent_from_close())
+ * so tty and tty port may have changed state (but not hung up or reopened).
+ */
 int tty_port_close_start(struct tty_port *port,
 int tty_port_close_start(struct tty_port *port,
 				struct tty_struct *tty, struct file *filp)
 				struct tty_struct *tty, struct file *filp)
 {
 {
@@ -486,9 +496,10 @@ int tty_port_close_start(struct tty_port *port,
 		return 0;
 		return 0;
 	}
 	}
 	set_bit(ASYNCB_CLOSING, &port->flags);
 	set_bit(ASYNCB_CLOSING, &port->flags);
-	tty->closing = 1;
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 
+	tty->closing = 1;
+
 	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 		/* Don't block on a stalled port, just pull the chain */
 		/* Don't block on a stalled port, just pull the chain */
 		if (tty->flow_stopped)
 		if (tty->flow_stopped)
@@ -506,13 +517,15 @@ int tty_port_close_start(struct tty_port *port,
 }
 }
 EXPORT_SYMBOL(tty_port_close_start);
 EXPORT_SYMBOL(tty_port_close_start);
 
 
+/* Caller holds tty lock */
 void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&port->lock, flags);
 	tty->closing = 0;
 	tty->closing = 0;
 
 
+	spin_lock_irqsave(&port->lock, flags);
+
 	if (port->blocked_open) {
 	if (port->blocked_open) {
 		spin_unlock_irqrestore(&port->lock, flags);
 		spin_unlock_irqrestore(&port->lock, flags);
 		if (port->close_delay) {
 		if (port->close_delay) {
@@ -528,6 +541,15 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 }
 }
 EXPORT_SYMBOL(tty_port_close_end);
 EXPORT_SYMBOL(tty_port_close_end);
 
 
+/**
+ * tty_port_close
+ *
+ * Caller holds tty lock
+ *
+ * NB: may drop and reacquire tty lock (in tty_port_close_start()->
+ * tty_wait_until_sent_from_close()) so tty and tty_port may have changed
+ * state (but not hung up or reopened).
+ */
 void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 							struct file *filp)
 							struct file *filp)
 {
 {
@@ -558,12 +580,19 @@ int tty_port_install(struct tty_port *port, struct tty_driver *driver,
 }
 }
 EXPORT_SYMBOL_GPL(tty_port_install);
 EXPORT_SYMBOL_GPL(tty_port_install);
 
 
+/**
+ * tty_port_open
+ *
+ * Caller holds tty lock.
+ *
+ * NB: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
+ * tty and tty_port may have changed state (eg., may be hung up now)
+ */
 int tty_port_open(struct tty_port *port, struct tty_struct *tty,
 int tty_port_open(struct tty_port *port, struct tty_struct *tty,
 							struct file *filp)
 							struct file *filp)
 {
 {
 	spin_lock_irq(&port->lock);
 	spin_lock_irq(&port->lock);
-	if (!tty_hung_up_p(filp))
-		++port->count;
+	++port->count;
 	spin_unlock_irq(&port->lock);
 	spin_unlock_irq(&port->lock);
 	tty_port_tty_set(port, tty);
 	tty_port_tty_set(port, tty);
 
 

+ 7 - 0
include/linux/serial_8250.h

@@ -74,8 +74,10 @@ struct uart_8250_port {
 	struct list_head	list;		/* ports on this IRQ */
 	struct list_head	list;		/* ports on this IRQ */
 	unsigned short		capabilities;	/* port capabilities */
 	unsigned short		capabilities;	/* port capabilities */
 	unsigned short		bugs;		/* port bugs */
 	unsigned short		bugs;		/* port bugs */
+	bool			fifo_bug;	/* min RX trigger if enabled */
 	unsigned int		tx_loadsz;	/* transmit fifo load size */
 	unsigned int		tx_loadsz;	/* transmit fifo load size */
 	unsigned char		acr;
 	unsigned char		acr;
+	unsigned char		fcr;
 	unsigned char		ier;
 	unsigned char		ier;
 	unsigned char		lcr;
 	unsigned char		lcr;
 	unsigned char		mcr;
 	unsigned char		mcr;
@@ -100,6 +102,11 @@ struct uart_8250_port {
 	void			(*dl_write)(struct uart_8250_port *, int);
 	void			(*dl_write)(struct uart_8250_port *, int);
 };
 };
 
 
+static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up)
+{
+	return container_of(up, struct uart_8250_port, port);
+}
+
 int serial8250_register_8250_port(struct uart_8250_port *);
 int serial8250_register_8250_port(struct uart_8250_port *);
 void serial8250_unregister_port(int line);
 void serial8250_unregister_port(int line);
 void serial8250_suspend_port(int line);
 void serial8250_suspend_port(int line);

+ 2 - 0
include/linux/serial_core.h

@@ -199,6 +199,8 @@ struct uart_port {
 	unsigned char		suspended;
 	unsigned char		suspended;
 	unsigned char		irq_wake;
 	unsigned char		irq_wake;
 	unsigned char		unused[2];
 	unsigned char		unused[2];
+	struct attribute_group	*attr_group;		/* port specific attributes */
+	const struct attribute_group **tty_groups;	/* all attributes (serial core use only) */
 	void			*private_data;		/* generic platform data pointer */
 	void			*private_data;		/* generic platform data pointer */
 };
 };
 
 

+ 1 - 3
include/linux/tty.h

@@ -477,13 +477,11 @@ extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 			unsigned int cmd, unsigned long arg);
 			unsigned int cmd, unsigned long arg);
 extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
 extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
 extern void tty_default_fops(struct file_operations *fops);
 extern void tty_default_fops(struct file_operations *fops);
-extern struct tty_struct *alloc_tty_struct(void);
+extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
 extern int tty_alloc_file(struct file *file);
 extern int tty_alloc_file(struct file *file);
 extern void tty_add_file(struct tty_struct *tty, struct file *file);
 extern void tty_add_file(struct tty_struct *tty, struct file *file);
 extern void tty_free_file(struct file *file);
 extern void tty_free_file(struct file *file);
 extern void free_tty_struct(struct tty_struct *tty);
 extern void free_tty_struct(struct tty_struct *tty);
-extern void initialize_tty_struct(struct tty_struct *tty,
-		struct tty_driver *driver, int idx);
 extern void deinitialize_tty_struct(struct tty_struct *tty);
 extern void deinitialize_tty_struct(struct tty_struct *tty);
 extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
 extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
 extern int tty_release(struct inode *inode, struct file *filp);
 extern int tty_release(struct inode *inode, struct file *filp);

+ 5 - 3
include/linux/tty_driver.h

@@ -35,14 +35,14 @@
  * 	This routine is mandatory; if this routine is not filled in,
  * 	This routine is mandatory; if this routine is not filled in,
  * 	the attempted open will fail with ENODEV.
  * 	the attempted open will fail with ENODEV.
  *
  *
- *	Required method.
- *     
+ *	Required method. Called with tty lock held.
+ *
  * void (*close)(struct tty_struct * tty, struct file * filp);
  * void (*close)(struct tty_struct * tty, struct file * filp);
  *
  *
  * 	This routine is called when a particular tty device is closed.
  * 	This routine is called when a particular tty device is closed.
  *	Note: called even if the corresponding open() failed.
  *	Note: called even if the corresponding open() failed.
  *
  *
- *	Required method.
+ *	Required method. Called with tty lock held.
  *
  *
  * void (*shutdown)(struct tty_struct * tty);
  * void (*shutdown)(struct tty_struct * tty);
  *
  *
@@ -172,6 +172,8 @@
  *
  *
  *	Optional:
  *	Optional:
  *
  *
+ *	Called with tty lock held.
+ *
  * int (*break_ctl)(struct tty_struct *tty, int state);
  * int (*break_ctl)(struct tty_struct *tty, int state);
  *
  *
  * 	This optional routine requests the tty driver to turn on or
  * 	This optional routine requests the tty driver to turn on or

+ 5 - 0
include/uapi/linux/serial_reg.h

@@ -88,6 +88,11 @@
 #define UART_FCR6_T_TRIGGER_30	0x30 /* Mask for transmit trigger set at 30 */
 #define UART_FCR6_T_TRIGGER_30	0x30 /* Mask for transmit trigger set at 30 */
 #define UART_FCR7_64BYTE	0x20 /* Go into 64 byte mode (TI16C750) */
 #define UART_FCR7_64BYTE	0x20 /* Go into 64 byte mode (TI16C750) */
 
 
+#define UART_FCR_R_TRIG_SHIFT		6
+#define UART_FCR_R_TRIG_BITS(x)		\
+	(((x) & UART_FCR_TRIGGER_MASK) >> UART_FCR_R_TRIG_SHIFT)
+#define UART_FCR_R_TRIG_MAX_STATE	4
+
 #define UART_LCR	3	/* Out: Line Control Register */
 #define UART_LCR	3	/* Out: Line Control Register */
 /*
 /*
  * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting 
  * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting 

+ 2 - 4
net/irda/ircomm/ircomm_tty.c

@@ -320,8 +320,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
 	      __FILE__, __LINE__, tty->driver->name, port->count);
 	      __FILE__, __LINE__, tty->driver->name, port->count);
 
 
 	spin_lock_irqsave(&port->lock, flags);
 	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp))
-		port->count--;
+	port->count--;
 	port->blocked_open++;
 	port->blocked_open++;
 	spin_unlock_irqrestore(&port->lock, flags);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 
@@ -458,8 +457,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
 	/*
 	/*
 	 * If the port is the middle of closing, bail out now
 	 * If the port is the middle of closing, bail out now
 	 */
 	 */
-	if (tty_hung_up_p(filp) ||
-	    test_bit(ASYNCB_CLOSING, &self->port.flags)) {
+	if (test_bit(ASYNCB_CLOSING, &self->port.flags)) {
 
 
 		/* Hm, why are we blocking on ASYNC_CLOSING if we
 		/* Hm, why are we blocking on ASYNC_CLOSING if we
 		 * do return -EAGAIN/-ERESTARTSYS below anyway?
 		 * do return -EAGAIN/-ERESTARTSYS below anyway?