Merge tag 'tty-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 5 Aug 2014 01:51:19 +0000 (18:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 5 Aug 2014 01:51:19 +0000 (18:51 -0700)
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
  ...

93 files changed:
Documentation/ABI/testing/sysfs-tty
Documentation/devicetree/bindings/serial/efm32-uart.txt
Documentation/devicetree/bindings/serial/fsl-lpuart.txt
Documentation/devicetree/bindings/serial/samsung_uart.txt
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
arch/arc/boot/dts/angel4.dts
arch/arc/plat-arcfpga/Kconfig
arch/arc/plat-arcfpga/platform.c
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos5.dtsi
arch/arm/boot/dts/exynos5260.dtsi
arch/arm/boot/dts/exynos5410.dtsi
arch/arm/boot/dts/exynos5440.dtsi
arch/arm/boot/dts/s3c2416.dtsi
arch/arm/boot/dts/s3c24xx.dtsi
arch/arm/boot/dts/s3c64xx.dtsi
drivers/char/pcmcia/synclink_cs.c
drivers/tty/cyclades.c
drivers/tty/ipwireless/tty.c
drivers/tty/n_gsm.c
drivers/tty/pty.c
drivers/tty/serial/21285.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_fsl.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/Kconfig
drivers/tty/serial/altera_jtaguart.c
drivers/tty/serial/altera_uart.c
drivers/tty/serial/amba-pl010.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/apbuart.c
drivers/tty/serial/ar933x_uart.c
drivers/tty/serial/arc_uart.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/bfin_sport_uart.c
drivers/tty/serial/bfin_uart.c
drivers/tty/serial/clps711x.c
drivers/tty/serial/cpm_uart/cpm_uart_core.c
drivers/tty/serial/crisv10.c
drivers/tty/serial/dz.c
drivers/tty/serial/efm32-uart.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/icom.c
drivers/tty/serial/ioc3_serial.c
drivers/tty/serial/ioc4_serial.c
drivers/tty/serial/jsm/jsm_tty.c
drivers/tty/serial/kgdb_nmi.c
drivers/tty/serial/lantiq.c
drivers/tty/serial/lpc32xx_hs.c
drivers/tty/serial/max310x.c
drivers/tty/serial/mcf.c
drivers/tty/serial/men_z135_uart.c
drivers/tty/serial/mpsc.c
drivers/tty/serial/mrst_max3110.c
drivers/tty/serial/msm_serial.c
drivers/tty/serial/msm_serial.h
drivers/tty/serial/mux.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/nwpserial.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/pxa.c
drivers/tty/serial/samsung.c
drivers/tty/serial/sc16is7xx.c
drivers/tty/serial/sccnxp.c
drivers/tty/serial/serial-tegra.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/serial_txx9.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sirfsoc_uart.c
drivers/tty/serial/sirfsoc_uart.h
drivers/tty/serial/sn_console.c
drivers/tty/serial/st-asc.c
drivers/tty/serial/sunhv.c
drivers/tty/serial/sunsab.c
drivers/tty/serial/tilegx.c
drivers/tty/serial/timbuart.c
drivers/tty/serial/uartlite.c
drivers/tty/serial/ucc_uart.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/synclink.c
drivers/tty/synclink_gt.c
drivers/tty/synclinkmp.c
drivers/tty/tty_io.c
drivers/tty/tty_port.c
include/linux/serial_8250.h
include/linux/serial_core.h
include/linux/tty.h
include/linux/tty_driver.h
include/uapi/linux/serial_reg.h
net/irda/ircomm/ircomm_tty.c

index ad22fb0..9eb3c2b 100644 (file)
@@ -138,3 +138,19 @@ Description:
 
                 These sysfs values expose the TIOCGSERIAL interface via
                 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.
index 3ca0133..8adbab2 100644 (file)
@@ -6,7 +6,7 @@ Required properties:
 - interrupts : Should contain uart interrupt
 
 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]
   Default: 0
 
@@ -16,5 +16,5 @@ uart@0x4000c400 {
        compatible = "energymicro,efm32-uart";
        reg = <0x4000c400 0x400>;
        interrupts = <15>;
-       efm32,location = <0>;
+       energymicro,location = <0>;
 };
index a1d1205..c95005e 100644 (file)
@@ -1,7 +1,11 @@
 * Freescale low power universal asynchronous receiver/transmitter (lpuart)
 
 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
 - interrupts : Should contain uart interrupt
 - clocks : phandle + clock specifier pairs, one for each entry in clock-names
index 2c8a17c..e85f37e 100644 (file)
@@ -1,14 +1,58 @@
 * 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:
-- 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
   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>;
+       };
index f13f1c5..7f76214 100644 (file)
@@ -4,9 +4,18 @@ Required properties:
 - compatible : "snps,dw-apb-uart"
 - reg : offset and length of the register set for the device.
 - 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.
+- 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:
+- resets : phandle to the parent reset controller.
 - reg-shift : quantity to shift the register offsets by.  If this property is
   not present then the register offsets are not shifted.
 - reg-io-width : the size (in bytes) of the IO accesses that should be
@@ -23,3 +32,26 @@ Example:
                reg-shift = <2>;
                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>;
+       };
index 5bb2fda..6b57475 100644 (file)
@@ -17,7 +17,7 @@
        interrupt-parent = <&intc>;
 
        chosen {
-               bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0";
+               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
        };
 
        aliases {
index e27bb5c..b9f34cf 100644 (file)
@@ -41,11 +41,4 @@ config ISS_SMP_EXTN
          -XTL (To enable CPU start/stop/set-PC for another CPU)
          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
index 61c7e59..b8d0d45 100644 (file)
 #include <plat/smp.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)
 {
        pr_info("[plat-arcfpga]: registering early dev resources\n");
 
-       arc_fpga_serial_init();
-
 #ifdef CONFIG_ISS_SMP_EXTN
        iss_model_init_early_smp();
 #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)
 {
-       pr_info("[plat-arcfpga]: registering device resources\n");
-
        /*
         * 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 ------------------------------
index aaaac79..94d5998 100644 (file)
@@ -39,6 +39,8 @@
                i2c5 = &i2c_5;
                i2c6 = &i2c_6;
                i2c7 = &i2c_7;
+               serial0 = &serial_0;
+               serial1 = &serial_1;
        };
 
        cpus {
index 17b22e9..93bcc1f 100644 (file)
                fimc1 = &fimc_1;
                fimc2 = &fimc_2;
                fimc3 = &fimc_3;
+               serial0 = &serial_0;
+               serial1 = &serial_1;
+               serial2 = &serial_2;
+               serial3 = &serial_3;
        };
 
        clock_audss: clock-controller@03810000 {
                status = "disabled";
        };
 
-       serial@13800000 {
+       serial_0: serial@13800000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x13800000 0x100>;
                interrupts = <0 52 0>;
                status = "disabled";
        };
 
-       serial@13810000 {
+       serial_1: serial@13810000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x13810000 0x100>;
                interrupts = <0 53 0>;
                status = "disabled";
        };
 
-       serial@13820000 {
+       serial_2: serial@13820000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x13820000 0x100>;
                interrupts = <0 54 0>;
                status = "disabled";
        };
 
-       serial@13830000 {
+       serial_3: serial@13830000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x13830000 0x100>;
                interrupts = <0 55 0>;
index 79d0608..ff2d2cb 100644 (file)
 / {
        interrupt-parent = <&gic>;
 
+       aliases {
+               serial0 = &serial_0;
+               serial1 = &serial_1;
+               serial2 = &serial_2;
+               serial3 = &serial_3;
+       };
+
        chipid@10000000 {
                compatible = "samsung,exynos4210-chipid";
                reg = <0x10000000 0x100>;
                interrupts = <1 9 0xf04>;
        };
 
-       serial@12C00000 {
+       serial_0: serial@12C00000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C00000 0x100>;
                interrupts = <0 51 0>;
        };
 
-       serial@12C10000 {
+       serial_1: serial@12C10000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C10000 0x100>;
                interrupts = <0 52 0>;
        };
 
-       serial@12C20000 {
+       serial_2: serial@12C20000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C20000 0x100>;
                interrupts = <0 53 0>;
        };
 
-       serial@12C30000 {
+       serial_3: serial@12C30000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C30000 0x100>;
                interrupts = <0 54 0>;
index 5398a60..4539a0a 100644 (file)
                pinctrl0 = &pinctrl_0;
                pinctrl1 = &pinctrl_1;
                pinctrl2 = &pinctrl_2;
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
        };
 
        cpus {
index 3839c26..52070e5 100644 (file)
        compatible = "samsung,exynos5410", "samsung,exynos5";
        interrupt-parent = <&gic>;
 
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
index ae3a17c..8f3373c 100644 (file)
@@ -18,6 +18,8 @@
        interrupt-parent = <&gic>;
 
        aliases {
+               serial0 = &serial_0;
+               serial1 = &serial_1;
                spi0 = &spi_0;
                tmuctrl0 = &tmuctrl_0;
                tmuctrl1 = &tmuctrl_1;
                >;
        };
 
-       serial@B0000 {
+       serial_0: serial@B0000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0xB0000 0x1000>;
                interrupts = <0 2 0>;
                clock-names = "uart", "clk_uart_baud0";
        };
 
-       serial@C0000 {
+       serial_1: serial@C0000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0xC0000 0x1000>;
                interrupts = <0 3 0>;
index 955e4a4..30b8f7e 100644 (file)
        model = "Samsung S3C2416 SoC";
        compatible = "samsung,s3c2416";
 
+       aliases {
+               serial3 = &uart3;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -68,7 +72,7 @@
                                <&clocks SCLK_UART>;
        };
 
-       serial@5000C000 {
+       uart3: serial@5000C000 {
                compatible = "samsung,s3c2440-uart";
                reg = <0x5000C000 0x4000>;
                interrupts = <1 18 24 4>, <1 18 25 4>;
index 2d1d7dc..5ed43b8 100644 (file)
@@ -16,6 +16,9 @@
 
        aliases {
                pinctrl0 = &pinctrl_0;
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
        };
 
        intc:interrupt-controller@4a000000 {
                #pwm-cells = <4>;
        };
 
-       serial@50000000 {
+       uart0: serial@50000000 {
                compatible = "samsung,s3c2410-uart";
                reg = <0x50000000 0x4000>;
                interrupts = <1 28 0 4>, <1 28 1 4>;
                status = "disabled";
        };
 
-       serial@50004000 {
+       uart1: serial@50004000 {
                compatible = "samsung,s3c2410-uart";
                reg = <0x50004000 0x4000>;
                interrupts = <1 23 3 4>, <1 23 4 4>;
                status = "disabled";
        };
 
-       serial@50008000 {
+       uart2: serial@50008000 {
                compatible = "samsung,s3c2410-uart";
                reg = <0x50008000 0x4000>;
                interrupts = <1 15 6 4>, <1 15 7 4>;
index 4e3be4d..ff5bdaa 100644 (file)
        aliases {
                i2c0 = &i2c0;
                pinctrl0 = &pinctrl0;
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
        };
 
        cpus {
index 8320abd..0ea9986 100644 (file)
@@ -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",
                         __FILE__, __LINE__, info->device_name, port->count);
 
-       WARN_ON(!port->count);
-
        if (tty_port_close_start(port, tty, filp) == 0)
                goto cleanup;
 
@@ -2510,7 +2508,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
                         __FILE__, __LINE__, tty->driver->name, port->count);
 
        /* 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,
                                             !(port->flags & ASYNC_CLOSING));
                retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
index a57bb5a..fd66f57 100644 (file)
@@ -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 (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,
                                !(info->port.flags & ASYNC_CLOSING));
                return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
index 17ee3bf..345cebb 100644 (file)
@@ -93,11 +93,6 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
                return -ENODEV;
 
        mutex_lock(&tty->ipw_tty_mutex);
-
-       if (tty->closing) {
-               mutex_unlock(&tty->ipw_tty_mutex);
-               return -ENODEV;
-       }
        if (tty->port.count == 0)
                tty->tx_bytes_queued = 0;
 
index 2ebe47b..152443a 100644 (file)
@@ -2088,9 +2088,7 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
        struct gsm_dlci *dlci;
        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);
        spin_lock_init(&gsm->control_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)
 {
-       int ret, i;
-       int base = gsm->num << 6; /* Base for this MUX */
+       int ret, i, base;
 
        gsm->tty = tty_kref_get(tty);
        gsm->output = gsmld_output;
@@ -2241,6 +2238,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
        else {
                /* Don't register device 0 - this is the control channel and not
                   a usable tty interface */
+               base = gsm->num << 6; /* Base for this MUX */
                for (i = 1; i < NUM_DLCI; i++)
                        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)
 {
        struct gsm_mux *gsm;
+       int ret;
 
        if (tty->ops->write == NULL)
                return -EINVAL;
@@ -2382,7 +2381,13 @@ static int gsmld_open(struct tty_struct *tty)
 
        /* Attach the initial passive connection */
        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;
 }
 
 /**
index 25c9bc7..9bbdb1d 100644 (file)
@@ -316,7 +316,7 @@ done:
  *     pty_common_install              -       set up the pty pair
  *     @driver: the pty driver
  *     @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
  *     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 retval = -ENOMEM;
 
-       o_tty = alloc_tty_struct();
-       if (!o_tty)
-               goto err;
        ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
        ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
        if (!ports[0] || !ports[1])
-               goto err_free_tty;
+               goto err;
        if (!try_module_get(driver->other->owner)) {
                /* 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) {
                /* We always use new tty termios data so we can do this
@@ -387,12 +386,12 @@ err_free_termios:
                tty_free_termios(tty);
 err_deinit_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);
+err_put_module:
+       module_put(driver->other->owner);
 err:
+       kfree(ports[0]);
+       kfree(ports[1]);
        return retval;
 }
 
index c7e8b60..9b208bd 100644 (file)
@@ -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)
 {
        struct uart_port *port = dev_id;
@@ -345,7 +341,6 @@ static struct uart_ops serial21285_ops = {
        .stop_tx        = serial21285_stop_tx,
        .start_tx       = serial21285_start_tx,
        .stop_rx        = serial21285_stop_rx,
-       .enable_ms      = serial21285_enable_ms,
        .break_ctl      = serial21285_break_ctl,
        .startup        = serial21285_startup,
        .shutdown       = serial21285_shutdown,
index 1ebf853..1b08c91 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
 #include <linux/dmaengine.h>
 
 struct uart_8250_dma {
@@ -60,6 +61,7 @@ struct serial8250_config {
        unsigned short  fifo_size;
        unsigned short  tx_loadsz;
        unsigned char   fcr;
+       unsigned char   rxtrig_bytes[UART_FCR_R_TRIG_MAX_STATE];
        unsigned int    flags;
 };
 
index 7a91c6d..1d42dba 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/tty.h>
 #include <linux/ratelimit.h>
 #include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
@@ -161,6 +160,7 @@ static const struct serial8250_config uart_config[] = {
                .fifo_size      = 16,
                .tx_loadsz      = 16,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .rxtrig_bytes   = {1, 4, 8, 14},
                .flags          = UART_CAP_FIFO,
        },
        [PORT_CIRRUS] = {
@@ -180,6 +180,7 @@ static const struct serial8250_config uart_config[] = {
                .tx_loadsz      = 16,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
                                  UART_FCR_T_TRIG_00,
+               .rxtrig_bytes   = {8, 16, 24, 28},
                .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
        },
        [PORT_16750] = {
@@ -188,6 +189,7 @@ static const struct serial8250_config uart_config[] = {
                .tx_loadsz      = 64,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
                                  UART_FCR7_64BYTE,
+               .rxtrig_bytes   = {1, 16, 32, 56},
                .flags          = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
        },
        [PORT_STARTECH] = {
@@ -209,6 +211,7 @@ static const struct serial8250_config uart_config[] = {
                .tx_loadsz      = 32,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
                                  UART_FCR_T_TRIG_10,
+               .rxtrig_bytes   = {8, 16, 56, 60},
                .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
        },
        [PORT_16850] = {
@@ -266,6 +269,7 @@ static const struct serial8250_config uart_config[] = {
                .tx_loadsz      = 8,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
                                  UART_FCR_T_TRIG_01,
+               .rxtrig_bytes   = {1, 4, 8, 14},
                .flags          = UART_CAP_FIFO | UART_CAP_RTOIE,
        },
        [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)
 {
-       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_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)
 {
-       unsigned char fcr;
-
        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);
 
@@ -1277,8 +1277,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
 
 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);
 
@@ -1293,8 +1292,7 @@ static void serial8250_stop_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)) {
                return;
@@ -1322,8 +1320,7 @@ static void serial8250_start_tx(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->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)
 {
-       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 */
        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 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;
 
        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)
 {
-       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 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)
 {
-       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 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)
 {
-       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;
 
        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)
 {
-       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;
 
        spin_lock_irqsave(&port->lock, flags);
@@ -1911,8 +1902,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
                         unsigned char c)
 {
        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
@@ -1941,8 +1931,7 @@ static void serial8250_put_poll_char(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 char lsr, iir;
        int retval;
@@ -2194,8 +2183,7 @@ dont_test_tx_en:
 
 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;
 
        /*
@@ -2268,12 +2256,10 @@ void
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
                          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 int baud, quot;
-       int fifo_bug = 0;
 
        switch (termios->c_cflag & CSIZE) {
        case CS5:
@@ -2296,7 +2282,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
        if (termios->c_cflag & PARENB) {
                cval |= UART_LCR_PARITY;
                if (up->bugs & UART_BUG_PARITY)
-                       fifo_bug = 1;
+                       up->fifo_bug = true;
        }
        if (!(termios->c_cflag & PARODD))
                cval |= UART_LCR_EPAR;
@@ -2320,10 +2306,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
                quot++;
 
        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.
         */
        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 */
        up->lcr = cval;                                 /* Save LCR */
        if (port->type != PORT_16750) {
                /* 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, fcr);           /* set fcr */
+               serial_port_out(port, UART_FCR, up->fcr);       /* set fcr */
        }
        serial8250_set_mctrl(port, port->mctrl);
        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,
                      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);
 }
@@ -2630,8 +2615,7 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
 
 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);
        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)
 {
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
+       struct uart_8250_port *up = up_to_u8250p(port);
        int ret;
 
        if (port->type == PORT_8250_CIR)
@@ -2657,10 +2640,149 @@ static int serial8250_request_port(struct uart_port *port)
        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 =
-               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 ret;
 
@@ -2705,6 +2827,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)
        if ((port->type == PORT_XR17V35X) ||
           (port->type == PORT_XR17D15X))
                port->handle_irq = exar_handle_irq;
+
+       register_dev_spec_attr_grp(up);
+       up->fcr = uart_config[up->port.type].fcr;
 }
 
 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)
 {
-       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);
        serial_port_out(port, UART_TX, ch);
index 51b307a..4db7987 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/clk.h>
+#include <linux/reset.h>
 #include <linux/pm_runtime.h>
 
 #include <asm/byteorder.h>
@@ -59,73 +60,17 @@ struct dw8250_data {
        int                     last_mcr;
        int                     line;
        struct clk              *clk;
+       struct clk              *pclk;
+       struct reset_control    *rst;
        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_EN                 (1 << 0)
 #define BYT_PRV_CLK_M_VAL_SHIFT                1
 #define BYT_PRV_CLK_N_VAL_SHIFT                16
 #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)
 {
        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)
 {
-       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);
 }
 
@@ -242,6 +188,32 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
                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)
 {
        struct dw8250_data *data = param;
@@ -286,6 +258,7 @@ static int dw8250_probe_of(struct uart_port *p,
                           struct dw8250_data *data)
 {
        struct device_node      *np = p->dev->of_node;
+       struct uart_8250_port *up = up_to_u8250p(p);
        u32                     val;
        bool has_ucv = true;
 
@@ -299,7 +272,7 @@ static int dw8250_probe_of(struct uart_port *p,
                p->membase += 7;
 #endif
                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;
                data->usr_reg = 0x27;
                has_ucv = false;
@@ -318,7 +291,7 @@ static int dw8250_probe_of(struct uart_port *p,
                }
        }
        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))
                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,
                             struct dw8250_data *data)
 {
-       const struct acpi_device_id *id;
        struct uart_port *p = &up->port;
-       struct dw8250_acpi_desc *acpi_desc;
 
        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->serial_in = dw8250_serial_in32;
        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->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;
 }
@@ -402,11 +364,40 @@ static int dw8250_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        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)) {
-               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.tx_chan_id = -1;
@@ -422,18 +413,21 @@ static int dw8250_probe(struct platform_device *pdev)
        if (pdev->dev.of_node) {
                err = dw8250_probe_of(&uart.port, data);
                if (err)
-                       return err;
+                       goto err_reset;
        } else if (ACPI_HANDLE(&pdev->dev)) {
                err = dw8250_probe_acpi(&uart, data);
                if (err)
-                       return err;
+                       goto err_reset;
        } else {
-               return -ENODEV;
+               err = -ENODEV;
+               goto err_reset;
        }
 
        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);
 
@@ -441,6 +435,20 @@ static int dw8250_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
 
        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)
@@ -451,6 +459,12 @@ static int dw8250_remove(struct platform_device *pdev)
 
        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))
                clk_disable_unprepare(data->clk);
 
@@ -488,6 +502,9 @@ static int dw8250_runtime_suspend(struct device *dev)
        if (!IS_ERR(data->clk))
                clk_disable_unprepare(data->clk);
 
+       if (!IS_ERR(data->pclk))
+               clk_disable_unprepare(data->pclk);
+
        return 0;
 }
 
@@ -495,6 +512,9 @@ static int dw8250_runtime_resume(struct device *dev)
 {
        struct dw8250_data *data = dev_get_drvdata(dev);
 
+       if (!IS_ERR(data->pclk))
+               clk_prepare_enable(data->pclk);
+
        if (!IS_ERR(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);
 
-static struct dw8250_acpi_desc byt_8250_desc = {
-       .set_termios = byt_set_termios,
-};
-
 static const struct acpi_device_id dw8250_acpi_match[] = {
        { "INT33C4", 0 },
        { "INT33C5", 0 },
        { "INT3434", 0 },
        { "INT3435", 0 },
-       { "80860F0A", (kernel_ulong_t)&byt_8250_desc},
+       { "80860F0A", },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
index f4d3c47..c0533a5 100644 (file)
@@ -28,8 +28,7 @@ int fsl8250_handle_irq(struct uart_port *port)
        unsigned char lsr, orig_lsr;
        unsigned long flags;
        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);
 
index 33137b3..61830b1 100644 (file)
@@ -1581,8 +1581,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
 
 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
         * 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)
 {
-       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;
 
        /*
index fb57159..26cec64 100644 (file)
@@ -238,7 +238,6 @@ config SERIAL_SAMSUNG_UARTS_4
 config SERIAL_SAMSUNG_UARTS
        int
        depends on PLAT_SAMSUNG
-       default 6 if CPU_S5P6450
        default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
        default 3
        help
@@ -774,7 +773,7 @@ config SERIAL_HS_LPC32XX
 
 config SERIAL_HS_LPC32XX_CONSOLE
        bool "Enable LPC32XX high speed UART serial console"
-       depends on SERIAL_HS_LPC32XX
+       depends on SERIAL_HS_LPC32XX=y
        select SERIAL_CORE_CONSOLE
        help
          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"
        depends on SERIAL_ARC=y
        select SERIAL_CORE_CONSOLE
+       select SERIAL_EARLYCON
        help
          Enable system Console on ARC UART
 
index 59b3da9..d22e3d9 100644 (file)
@@ -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,
                                        struct ktermios *termios,
                                        struct ktermios *old)
@@ -291,7 +287,6 @@ static struct uart_ops altera_jtaguart_ops = {
        .start_tx       = altera_jtaguart_start_tx,
        .stop_tx        = altera_jtaguart_stop_tx,
        .stop_rx        = altera_jtaguart_stop_rx,
-       .enable_ms      = altera_jtaguart_enable_ms,
        .break_ctl      = altera_jtaguart_break_ctl,
        .startup        = altera_jtaguart_startup,
        .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_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 flags;
 
@@ -330,9 +324,8 @@ static void altera_jtaguart_console_putc(struct console *co, const char c)
        spin_unlock_irqrestore(&port->lock, flags);
 }
 #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;
 
        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,
                                          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,
index 3233766..6a24323 100644 (file)
@@ -163,10 +163,6 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
        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,
                                    struct ktermios *termios,
                                    struct ktermios *old)
@@ -415,7 +411,6 @@ static struct uart_ops altera_uart_ops = {
        .start_tx       = altera_uart_start_tx,
        .stop_tx        = altera_uart_stop_tx,
        .stop_rx        = altera_uart_stop_rx,
-       .enable_ms      = altera_uart_enable_ms,
        .break_ctl      = altera_uart_break_ctl,
        .startup        = altera_uart_startup,
        .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)
 
-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) &
                 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;
 
-       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)
index 971af1e..2064d31 100644 (file)
@@ -46,8 +46,7 @@
 #include <linux/amba/serial.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 
 #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)
                        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.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);
        ret = uart_add_one_port(&amba_reg, &uap->port);
-       if (ret) {
+       if (ret)
                amba_ports[i] = NULL;
-               clk_put(uap->clk);
- unmap:
-               iounmap(base);
- free:
-               kfree(uap);
-       }
- out:
+
        return ret;
 }
 
@@ -750,9 +737,6 @@ static int pl010_remove(struct amba_device *dev)
                if (amba_ports[i] == uap)
                        amba_ports[i] = NULL;
 
-       iounmap(uap->port.membase);
-       clk_put(uap->clk);
-       kfree(uap);
        return 0;
 }
 
index 0e26dcb..8572f2a 100644 (file)
@@ -1484,7 +1484,7 @@ static int pl011_hwinit(struct uart_port *port)
         */
        retval = clk_prepare_enable(uap->clk);
        if (retval)
-               goto out;
+               return retval;
 
        uap->port.uartclk = clk_get_rate(uap->clk);
 
@@ -1507,8 +1507,6 @@ static int pl011_hwinit(struct uart_port *port)
                        plat->init();
        }
        return 0;
- out:
-       return retval;
 }
 
 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)
                        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),
                           GFP_KERNEL);
-       if (uap == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (uap == NULL)
+               return -ENOMEM;
 
        i = pl011_probe_dt_alias(i, &dev->dev);
 
        base = devm_ioremap(&dev->dev, dev->res.start,
                            resource_size(&dev->res));
-       if (!base) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!base)
+               return -ENOMEM;
 
        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->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);
                pl011_dma_remove(uap);
        }
- out:
+
        return ret;
 }
 
index de11ab8..a34a0ce 100644 (file)
@@ -71,11 +71,6 @@ static void apbuart_stop_rx(struct uart_port *port)
        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)
 {
        unsigned int status, ch, rsr, flag;
@@ -337,7 +332,6 @@ static struct uart_ops grlib_apbuart_ops = {
        .stop_tx = apbuart_stop_tx,
        .start_tx = apbuart_start_tx,
        .stop_rx = apbuart_stop_rx,
-       .enable_ms = apbuart_enable_ms,
        .break_ctl = apbuart_break_ctl,
        .startup = apbuart_startup,
        .shutdown = apbuart_shutdown,
index acd03af..0be1c45 100644 (file)
@@ -176,10 +176,6 @@ static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
        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))
  */
@@ -495,7 +491,6 @@ static struct uart_ops ar933x_uart_ops = {
        .stop_tx        = ar933x_uart_stop_tx,
        .start_tx       = ar933x_uart_start_tx,
        .stop_rx        = ar933x_uart_stop_rx,
-       .enable_ms      = ar933x_uart_enable_ms,
        .break_ctl      = ar933x_uart_break_ctl,
        .startup        = ar933x_uart_startup,
        .shutdown       = ar933x_uart_shutdown,
index 008c223..a59d1d7 100644 (file)
@@ -37,8 +37,8 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.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
@@ -72,7 +72,7 @@
 #define RXOERR  0x02   /* OverFlow Err: Char recv but RXFULL still set */
 
 /* 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_GET(u, r)    readb(RBASE(u, r))
 
 struct arc_uart_port {
        struct uart_port port;
        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)
@@ -129,19 +128,15 @@ static struct uart_driver arc_uart_driver = {
 
 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)
 {
-       struct arc_uart_port *uart = to_arc_port(port);
-
-       while (!(UART_GET_STATUS(uart) & TXEMPTY))
+       while (!(UART_GET_STATUS(port) & TXEMPTY))
                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)
 {
-       struct arc_uart_port *uart = to_arc_port(port);
        unsigned int stat;
 
-       stat = UART_GET_STATUS(uart);
+       stat = UART_GET_STATUS(port);
        if (stat & TXEMPTY)
                return TIOCSER_TEMT;
 
@@ -166,24 +160,24 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
  *     = by uart_start( ) before calling us
  *     = 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;
        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;
        } else if (!uart_circ_empty(xmit)) {
                ch = xmit->buf[xmit->tail];
                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();
-               UART_SET_DATA(uart, ch);
+               UART_SET_DATA(port, ch);
                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
         */
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&uart->port);
+               uart_write_wakeup(port);
 
        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)
 {
-       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;
 
@@ -229,15 +221,15 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
                 */
                if (unlikely(status & (RXOERR | RXFERR))) {
                        if (status & RXOERR) {
-                               uart->port.icount.overrun++;
+                               port->icount.overrun++;
                                flg = TTY_OVERRUN;
-                               UART_CLR_STATUS(uart, RXOERR);
+                               UART_CLR_STATUS(port, RXOERR);
                        }
 
                        if (status & RXFERR) {
-                               uart->port.icount.frame++;
+                               port->icount.frame++;
                                flg = TTY_FRAME;
-                               UART_CLR_STATUS(uart, RXFERR);
+                               UART_CLR_STATUS(port, RXFERR);
                        }
                } else
                        flg = TTY_NORMAL;
@@ -245,16 +237,16 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
                if (status & RXEMPTY)
                        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)
 {
-       struct arc_uart_port *uart = dev_id;
+       struct uart_port *port = dev_id;
        unsigned int status;
 
-       status = UART_GET_STATUS(uart);
+       status = UART_GET_STATUS(port);
 
        /*
         * 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) {
 
                /* 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)) {
@@ -310,14 +302,14 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
                /* Unconditionally disable further Tx-Interrupts.
                 * 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;
@@ -340,13 +332,6 @@ static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
        /* 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)
 {
        /* 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)
 {
-       struct arc_uart_port *uart = to_arc_port(port);
-
        /* 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;
        }
 
-       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;
 }
@@ -373,8 +355,7 @@ static int arc_serial_startup(struct uart_port *port)
 /* This is not really needed */
 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
@@ -398,25 +379,14 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
        uartl = hw_val & 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);
 
-       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;
@@ -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)
 {
-       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)
@@ -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)
 {
-       struct arc_uart_port *uart = to_arc_port(port);
-
        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)
 {
-       struct arc_uart_port *uart = to_arc_port(port);
-
-       while (!(UART_GET_STATUS(uart) & TXEMPTY))
+       while (!(UART_GET_STATUS(port) & TXEMPTY))
                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)
 {
-       struct arc_uart_port *uart = to_arc_port(port);
        unsigned char chr;
 
-       while (!(UART_GET_STATUS(uart) & RXEMPTY))
+       while (!(UART_GET_STATUS(port) & RXEMPTY))
                cpu_relax();
 
-       chr = UART_GET_DATA(uart);
+       chr = UART_GET_DATA(port);
        return chr;
 }
 #endif
@@ -510,7 +471,6 @@ static struct uart_ops arc_serial_pops = {
        .stop_tx        = arc_serial_stop_tx,
        .start_tx       = arc_serial_start_tx,
        .stop_rx        = arc_serial_stop_rx,
-       .enable_ms      = arc_serial_enable_ms,
        .break_ctl      = arc_serial_break_ctl,
        .startup        = arc_serial_startup,
        .shutdown       = arc_serial_shutdown,
@@ -526,71 +486,6 @@ static struct uart_ops arc_serial_pops = {
 #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
 
 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)
 {
-       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
 };
 
-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;
 }
+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 */
 
 static int arc_serial_probe(struct platform_device *pdev)
 {
-       int rc, dev_id;
        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 */
        if (!np)
@@ -702,12 +597,43 @@ static int arc_serial_probe(struct platform_device *pdev)
        if (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)
@@ -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)
 {
        int ret;
index c4f7503..7b63677 100644 (file)
@@ -706,7 +706,7 @@ static void atmel_release_tx_dma(struct uart_port *port)
                dmaengine_terminate_all(chan);
                dma_release_channel(chan);
                dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1,
-                               DMA_MEM_TO_DEV);
+                               DMA_TO_DEVICE);
        }
 
        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,
                                &atmel_port->sg_tx,
                                1,
-                               DMA_MEM_TO_DEV);
+                               DMA_TO_DEVICE);
 
        if (!nent) {
                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);
                dma_release_channel(chan);
                dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1,
-                               DMA_DEV_TO_MEM);
+                               DMA_FROM_DEVICE);
        }
 
        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,
                                        &atmel_port->sg_rx,
                                        1,
-                                       DMA_DEV_TO_MEM);
+                                       DMA_FROM_DEVICE);
 
        if (!nent) {
                dev_dbg(port->dev, "need to release resource of dma\n");
index 4f22970..7810aa2 100644 (file)
@@ -426,11 +426,6 @@ static void sport_stop_rx(struct uart_port *port)
        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)
 {
        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);
 
+#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) {
        case CS8:
                up->csize = 8;
@@ -587,7 +589,6 @@ struct uart_ops sport_uart_ops = {
        .stop_tx        = sport_stop_tx,
        .start_tx       = sport_start_tx,
        .stop_rx        = sport_stop_rx,
-       .enable_ms      = sport_enable_ms,
        .break_ctl      = sport_break_ctl,
        .startup        = sport_startup,
        .shutdown       = sport_shutdown,
@@ -813,10 +814,8 @@ static int sport_uart_probe(struct platform_device *pdev)
                res = platform_get_resource(pdev, IORESOURCE_IO, 0);
                if (res == NULL)
                        sport->cts_pin = -1;
-               else {
+               else
                        sport->cts_pin = res->start;
-                       sport->port.flags |= ASYNC_CTS_FLOW;
-               }
 
                res = platform_get_resource(pdev, IORESOURCE_IO, 1);
                if (res == NULL)
index ac86a20..dec0fd7 100644 (file)
@@ -200,14 +200,6 @@ static void bfin_serial_stop_rx(struct uart_port *port)
        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)
 # define UART_GET_ANOMALY_THRESHOLD(uart)    ((uart)->anomaly_threshold)
 # 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 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) {
        case CS8:
                lcr = WLS(8);
@@ -1014,7 +1013,6 @@ static struct uart_ops bfin_serial_pops = {
        .stop_tx        = bfin_serial_stop_tx,
        .start_tx       = bfin_serial_start_tx,
        .stop_rx        = bfin_serial_stop_rx,
-       .enable_ms      = bfin_serial_enable_ms,
        .break_ctl      = bfin_serial_break_ctl,
        .startup        = bfin_serial_startup,
        .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);
                if (res == NULL)
                        uart->cts_pin = -1;
-               else {
+               else
                        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);
                if (res == NULL)
index 14aaea0..f5b4c3d 100644 (file)
@@ -352,7 +352,6 @@ static const struct uart_ops uart_clps711x_ops = {
        .stop_tx        = uart_clps711x_stop_tx,
        .start_tx       = uart_clps711x_start_tx,
        .stop_rx        = uart_clps711x_nop_void,
-       .enable_ms      = uart_clps711x_nop_void,
        .break_ctl      = uart_clps711x_break_ctl,
        .set_ldisc      = uart_clps711x_set_ldisc,
        .startup        = uart_clps711x_startup,
index aa60e6d..533852e 100644 (file)
@@ -201,14 +201,6 @@ static void cpm_uart_stop_rx(struct uart_port *port)
                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.
  */
@@ -1122,7 +1114,6 @@ static struct uart_ops cpm_uart_pops = {
        .stop_tx        = cpm_uart_stop_tx,
        .start_tx       = cpm_uart_start_tx,
        .stop_rx        = cpm_uart_stop_rx,
-       .enable_ms      = cpm_uart_enable_ms,
        .break_ctl      = cpm_uart_break_ctl,
        .startup        = cpm_uart_startup,
        .shutdown       = cpm_uart_shutdown,
index d567ac5..58e6f61 100644 (file)
@@ -3831,14 +3831,13 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
        DECLARE_WAITQUEUE(wait, current);
        unsigned long   flags;
        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
         * 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,
                        !(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
@@ -3879,10 +3878,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
               info->line, info->port.count);
 #endif
        local_irq_save(flags);
-       if (!tty_hung_up_p(filp)) {
-               extra_count++;
-               info->port.count--;
-       }
+       info->port.count--;
        local_irq_restore(flags);
        info->port.blocked_open++;
        while (1) {
@@ -3921,7 +3917,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&info->port.open_wait, &wait);
-       if (extra_count)
+       if (!tty_hung_up_p(filp))
                info->port.count++;
        info->port.blocked_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 (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,
                        !(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
index cdbbc78..c121f16 100644 (file)
@@ -151,11 +151,6 @@ static void dz_stop_rx(struct uart_port *uport)
        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,
        .start_tx       = dz_start_tx,
        .stop_rx        = dz_stop_rx,
-       .enable_ms      = dz_enable_ms,
        .break_ctl      = dz_break_ctl,
        .startup        = dz_startup,
        .shutdown       = dz_shutdown,
index 3b0ee9a..55d9c00 100644 (file)
@@ -185,11 +185,6 @@ static void efm32_uart_stop_rx(struct uart_port *port)
        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)
 {
        /* not possible without fiddling with gpios */
@@ -499,7 +494,6 @@ static struct uart_ops efm32_uart_pops = {
        .stop_tx = efm32_uart_stop_tx,
        .start_tx = efm32_uart_start_tx,
        .stop_rx = efm32_uart_stop_rx,
-       .enable_ms = efm32_uart_enable_ms,
        .break_ctl = efm32_uart_break_ctl,
        .startup = efm32_uart_startup,
        .shutdown = efm32_uart_shutdown,
@@ -671,10 +665,16 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
        if (!np)
                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)
                /* fall back to old and (wrongly) generic property "location" */
                ret = of_property_read_u32(np, "location", &location);
+
        if (!ret) {
                if (location > 5) {
                        dev_err(&pdev->dev, "invalid location\n");
index 49385c8..6dd53af 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  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
  * it under the terms of the GNU General Public License as published by
 #define UARTSFIFO_TXOF         0x02
 #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 DRIVER_NAME    "fsl-lpuart"
@@ -130,6 +235,7 @@ struct lpuart_port {
        struct clk              *clk;
        unsigned int            txfifo_size;
        unsigned int            rxfifo_size;
+       bool                    lpuart32;
 
        bool                    lpuart_dma_use;
        struct dma_chan         *dma_tx_chan;
@@ -154,6 +260,9 @@ static struct of_device_id lpuart_dt_ids[] = {
        {
                .compatible = "fsl,vf610-lpuart",
        },
+       {
+               .compatible = "fsl,ls1021a-lpuart",
+       },
        { /* sentinel */ }
 };
 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_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)
 {
        unsigned char temp;
@@ -171,6 +290,15 @@ static void lpuart_stop_tx(struct uart_port *port)
        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)
 {
        unsigned char temp;
@@ -179,8 +307,12 @@ static void lpuart_stop_rx(struct uart_port *port)
        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,
@@ -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,
                                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;
        sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
                                        tx_bus_addr, sport->dma_tx_bytes,
@@ -269,7 +401,7 @@ static void lpuart_prepare_tx(struct lpuart_port *sport)
        if (!count)
                return;
 
-       if (count < DMA_MAXBURST)
+       if (count < sport->txfifo_size)
                writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
                                sport->port.membase + UARTCR5);
        else {
@@ -405,6 +537,30 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
                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)
 {
        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)
 {
        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);
        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;
        }
 
        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;
        }
 
-       lpuart_transmit_buffer(sport);
+       if (sport->lpuart32)
+               lpuart32_transmit_buffer(sport);
+       else
+               lpuart_transmit_buffer(sport);
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&sport->port);
@@ -514,6 +691,70 @@ out:
        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)
 {
        struct lpuart_port *sport = dev_id;
@@ -538,6 +779,26 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
        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 */
 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;
 }
 
+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)
 {
        unsigned int temp = 0;
@@ -560,6 +827,21 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port)
        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)
 {
        unsigned char temp;
@@ -576,6 +858,22 @@ static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
        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)
 {
        unsigned char temp;
@@ -588,6 +886,18 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
        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)
 {
        unsigned char val, cr2;
@@ -599,15 +909,7 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
                        UARTCR2_RIE | UARTCR2_RE);
        writeb(cr2, sport->port.membase + UARTCR2);
 
-       /* determine FIFO size and enable FIFO mode */
        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,
                        sport->port.membase + UARTPFIFO);
 
@@ -622,6 +924,31 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
        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)
 {
        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_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
        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;
        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_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;
 }
 
@@ -772,7 +1092,16 @@ static int lpuart_startup(struct uart_port *port)
        unsigned long flags;
        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)) {
                sport->lpuart_dma_use = false;
        } else {
@@ -798,6 +1127,40 @@ static int lpuart_startup(struct uart_port *port)
        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)
 {
        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
 lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
                   struct ktermios *old)
@@ -922,6 +1304,17 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
        /* update the per-port timeout */
        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 */
        while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
                barrier();
@@ -948,6 +1341,125 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
        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)
 {
        return "FSL_LPUART";
@@ -996,7 +1508,6 @@ static struct uart_ops lpuart_pops = {
        .stop_tx        = lpuart_stop_tx,
        .start_tx       = lpuart_start_tx,
        .stop_rx        = lpuart_stop_rx,
-       .enable_ms      = lpuart_enable_ms,
        .break_ctl      = lpuart_break_ctl,
        .startup        = lpuart_startup,
        .shutdown       = lpuart_shutdown,
@@ -1008,6 +1519,24 @@ static struct uart_ops lpuart_pops = {
        .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];
 
 #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);
 }
 
+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
 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);
 }
 
+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),
  * 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);
 }
 
+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)
 {
        struct lpuart_port *sport;
@@ -1116,9 +1717,15 @@ static int __init lpuart_console_setup(struct console *co, char *options)
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
        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);
 }
@@ -1134,9 +1741,21 @@ static struct console lpuart_console = {
        .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 LPUART32_CONSOLE       (&lpuart32_console)
 #else
 #define LPUART_CONSOLE NULL
+#define LPUART32_CONSOLE       NULL
 #endif
 
 static struct uart_driver lpuart_reg = {
@@ -1166,7 +1785,7 @@ static int lpuart_probe(struct platform_device *pdev)
                return ret;
        }
        sport->port.line = ret;
-
+       sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENODEV;
@@ -1180,7 +1799,10 @@ static int lpuart_probe(struct platform_device *pdev)
        sport->port.type = PORT_LPUART;
        sport->port.iotype = UPIO_MEM;
        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->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);
 
+       if (sport->lpuart32)
+               lpuart_reg.cons = LPUART32_CONSOLE;
+       else
+               lpuart_reg.cons = LPUART_CONSOLE;
+
        ret = uart_add_one_port(&lpuart_reg, &sport->port);
        if (ret) {
                clk_disable_unprepare(sport->clk);
index 6742380..d4620fe 100644 (file)
@@ -1052,11 +1052,6 @@ static void icom_stop_rx(struct uart_port *port)
        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)
 {
        unsigned char cmdReg;
@@ -1300,7 +1295,6 @@ static struct uart_ops icom_ops = {
        .start_tx = icom_start_tx,
        .send_xchar = icom_send_xchar,
        .stop_rx = icom_stop_rx,
-       .enable_ms = icom_enable_ms,
        .break_ctl = icom_break,
        .startup = icom_open,
        .shutdown = icom_close,
index 6e4c715..abd7ea2 100644 (file)
@@ -1880,7 +1880,6 @@ static struct uart_ops ioc3_ops = {
        .stop_tx = ic3_stop_tx,
        .start_tx = ic3_start_tx,
        .stop_rx = ic3_stop_rx,
-       .enable_ms = null_void_function,
        .break_ctl = ic3_break_ctl,
        .startup = ic3_startup,
        .shutdown = ic3_shutdown,
index 1274499..aa28209 100644 (file)
@@ -2597,7 +2597,6 @@ static struct uart_ops ioc4_ops = {
        .stop_tx        = ic4_stop_tx,
        .start_tx       = ic4_start_tx,
        .stop_rx        = null_void_function,
-       .enable_ms      = null_void_function,
        .break_ctl      = ic4_break_ctl,
        .startup        = ic4_startup,
        .shutdown       = ic4_shutdown,
index 27bb750..3e5c156 100644 (file)
@@ -177,11 +177,6 @@ static void jsm_tty_stop_rx(struct uart_port *port)
        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)
 {
        unsigned long lock_flags;
@@ -354,7 +349,6 @@ static struct uart_ops jsm_ops = {
        .start_tx       = jsm_tty_start_tx,
        .send_xchar     = jsm_tty_send_xchar,
        .stop_rx        = jsm_tty_stop_rx,
-       .enable_ms      = jsm_tty_enable_ms,
        .break_ctl      = jsm_tty_break,
        .startup        = jsm_tty_open,
        .shutdown       = jsm_tty_close,
index cfadf29..6ec7501 100644 (file)
@@ -42,7 +42,7 @@ static char *kgdb_nmi_magic = "$3#33";
 module_param_named(magic, kgdb_nmi_magic, charp, 0600);
 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)
 {
@@ -136,7 +136,7 @@ static int kgdb_nmi_poll_one_knock(void)
                n = 0;
        }
 
-       if (kgdb_nmi_tty_enabled) {
+       if (atomic_read(&kgdb_nmi_num_readers)) {
                kgdb_tty_recv(c);
                return 0;
        }
@@ -197,7 +197,8 @@ static void kgdb_nmi_tty_receiver(unsigned long data)
        priv->timer.expires = jiffies + (HZ/100);
        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;
 
        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)
 {
        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)
 {
        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);
 }
@@ -313,12 +324,6 @@ static const struct tty_operations kgdb_nmi_tty_ops = {
        .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 ret;
@@ -348,19 +353,10 @@ int kgdb_register_nmi_console(void)
                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);
        arch_kgdb_ops.enable_nmi(1);
 
        return 0;
-err_kdb_reg:
-       tty_unregister_driver(kgdb_nmi_tty_driver);
 err_drv_reg:
        put_tty_driver(kgdb_nmi_tty_driver);
        return ret;
@@ -375,8 +371,6 @@ int kgdb_unregister_nmi_console(void)
                return 0;
        arch_kgdb_ops.enable_nmi(0);
 
-       kdb_unregister("nmi_console");
-
        ret = unregister_console(&kgdb_nmi_console);
        if (ret)
                return ret;
index 88d01e0..4675fe1 100644 (file)
@@ -154,11 +154,6 @@ lqasc_stop_rx(struct uart_port *port)
        ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
 }
 
-static void
-lqasc_enable_ms(struct uart_port *port)
-{
-}
-
 static int
 lqasc_rx_chars(struct uart_port *port)
 {
@@ -568,7 +563,6 @@ static struct uart_ops lqasc_pops = {
        .stop_tx =      lqasc_stop_tx,
        .start_tx =     lqasc_start_tx,
        .stop_rx =      lqasc_stop_rx,
-       .enable_ms =    lqasc_enable_ms,
        .break_ctl =    lqasc_break_ctl,
        .startup =      lqasc_startup,
        .shutdown =     lqasc_shutdown,
@@ -709,7 +703,7 @@ lqasc_probe(struct platform_device *pdev)
        port = &ltq_port->port;
 
        port->iotype    = SERIAL_IO_MEM;
-       port->flags     = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
+       port->flags     = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
        port->ops       = &lqasc_pops;
        port->fifosize  = 16;
        port->type      = PORT_LTQ_ASC,
index 701644f..6f0f892 100644 (file)
@@ -427,12 +427,6 @@ static void serial_lpc32xx_stop_rx(struct uart_port *port)
                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.  */
 static void serial_lpc32xx_break_ctl(struct uart_port *port,
                                     int break_state)
@@ -658,7 +652,6 @@ static struct uart_ops serial_lpc32xx_pops = {
        .stop_tx        = serial_lpc32xx_stop_tx,
        .start_tx       = serial_lpc32xx_start_tx,
        .stop_rx        = serial_lpc32xx_stop_rx,
-       .enable_ms      = serial_lpc32xx_enable_ms,
        .break_ctl      = serial_lpc32xx_break_ctl,
        .startup        = serial_lpc32xx_startup,
        .shutdown       = serial_lpc32xx_shutdown,
index ba285cd..82573dc 100644 (file)
@@ -1008,7 +1008,6 @@ static const struct uart_ops max310x_ops = {
        .stop_tx        = max310x_null_void,
        .start_tx       = max310x_start_tx,
        .stop_rx        = max310x_null_void,
-       .enable_ms      = max310x_null_void,
        .break_ctl      = max310x_break_ctl,
        .startup        = max310x_startup,
        .shutdown       = max310x_shutdown,
index a6f0857..bc896dc 100644 (file)
@@ -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)
 {
        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,
        .stop_tx        = mcf_stop_tx,
        .stop_rx        = mcf_stop_rx,
-       .enable_ms      = mcf_enable_ms,
        .break_ctl      = mcf_break_ctl,
        .startup        = mcf_startup,
        .shutdown       = mcf_shutdown,
@@ -544,7 +537,7 @@ int __init early_mcf_setup(struct mcf_platform_uart *platp)
                port->iotype = SERIAL_IO_MEM;
                port->irq = platp[i].irq;
                port->uartclk = MCF_BUSCLK;
-               port->flags = ASYNC_BOOT_AUTOCONF;
+               port->flags = UPF_BOOT_AUTOCONF;
                port->ops = &mcf_uart_ops;
        }
 
@@ -669,7 +662,7 @@ static int mcf_probe(struct platform_device *pdev)
                port->irq = platp[i].irq;
                port->uartclk = MCF_BUSCLK;
                port->ops = &mcf_uart_ops;
-               port->flags = ASYNC_BOOT_AUTOCONF;
+               port->flags = UPF_BOOT_AUTOCONF;
 
                uart_add_one_port(&mcf_driver, port);
        }
index c9d1854..30e9e60 100644 (file)
@@ -308,9 +308,6 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
        if (port->x_char)
                goto out;
 
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
-
        /* calculate bytes to copy */
        qlen = uart_circ_chars_pending(xmit);
        if (qlen <= 0)
@@ -357,6 +354,9 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
 
        port->icount.tx += n;
 
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+
 irq_en:
        if (!uart_circ_empty(xmit))
                men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
index 759c6a6..ae49856 100644 (file)
@@ -1336,10 +1336,6 @@ static void mpsc_stop_rx(struct uart_port *port)
        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)
 {
        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,
        .start_tx       = mpsc_start_tx,
        .stop_rx        = mpsc_stop_rx,
-       .enable_ms      = mpsc_enable_ms,
        .break_ctl      = mpsc_break_ctl,
        .startup        = mpsc_startup,
        .shutdown       = mpsc_shutdown,
index db0448a..1504a14 100644 (file)
@@ -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 = {
        .tx_empty       = serial_m3110_tx_empty,
        .set_mctrl      = serial_m3110_set_mctrl,
@@ -709,7 +705,6 @@ static struct uart_ops serial_m3110_ops = {
        .stop_tx        = serial_m3110_stop_tx,
        .start_tx       = serial_m3110_start_tx,
        .stop_rx        = serial_m3110_stop_rx,
-       .enable_ms      = serial_m3110_enable_ms,
        .break_ctl      = serial_m3110_break_ctl,
        .startup        = serial_m3110_startup,
        .shutdown       = serial_m3110_shutdown,
index 72000a6..0da0b54 100644 (file)
@@ -125,14 +125,14 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
        port->icount.rx += count;
 
        while (count > 0) {
-               unsigned int c;
+               unsigned char buf[4];
 
                sr = msm_read(port, UART_SR);
                if ((sr & UART_SR_RX_READY) == 0) {
                        msm_port->old_snap_state -= count;
                        break;
                }
-               c = msm_read(port, UARTDM_RF);
+               ioread32_rep(port->membase + UARTDM_RF, buf, 1);
                if (sr & UART_SR_RX_BREAK) {
                        port->icount.brk++;
                        if (uart_handle_break(port))
@@ -141,8 +141,7 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
                        port->icount.frame++;
 
                /* 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;
        }
 
@@ -219,6 +218,12 @@ static void handle_tx(struct uart_port *port)
        struct msm_port *msm_port = UART_TO_MSM(port);
        unsigned int tx_count, num_chars;
        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 = 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)
                        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->x_char = 0;
        } 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) {
                int i;
                char buf[4] = { 0 };
-               unsigned int *bf = (unsigned int *)&buf;
 
                if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
                        break;
@@ -255,7 +258,7 @@ static void handle_tx(struct uart_port *port)
                        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);
                tf_pointer += num_chars;
        }
@@ -861,12 +864,18 @@ static void msm_console_write(struct console *co, const char *s,
        struct msm_port *msm_port;
        int num_newlines = 0;
        bool replaced = false;
+       void __iomem *tf;
 
        BUG_ON(co->index < 0 || co->index >= UART_NR);
 
        port = get_port_from_line(co->index);
        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 */
        for (i = 0; i < count; i++)
                if (s[i] == '\n')
@@ -882,7 +891,6 @@ static void msm_console_write(struct console *co, const char *s,
                int j;
                unsigned int num_chars;
                char buf[4] = { 0 };
-               unsigned int *bf = (unsigned int *)&buf;
 
                if (msm_port->is_uartdm)
                        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))
                        cpu_relax();
 
-               msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
+               iowrite32_rep(tf, buf, 1);
                i += num_chars;
        }
        spin_unlock(&port->lock);
@@ -917,7 +925,7 @@ static int __init msm_console_setup(struct console *co, char *options)
 {
        struct uart_port *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))
                return -ENXIO;
@@ -1057,7 +1065,7 @@ static int msm_serial_remove(struct platform_device *pdev)
        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-uartdm" },
        {}
index d98d45e..73d3abe 100644 (file)
 static inline
 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
 unsigned int msm_read(struct uart_port *port, unsigned int off)
 {
-       return __raw_readl(port->membase + off);
+       return readl_relaxed(port->membase + off);
 }
 
 /*
index be127d0..dd26511 100644 (file)
@@ -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.
  * @port: Ptr to the uart_port.
@@ -449,7 +439,6 @@ static struct uart_ops mux_pops = {
        .stop_tx =              mux_stop_tx,
        .start_tx =             mux_start_tx,
        .stop_rx =              mux_stop_rx,
-       .enable_ms =            mux_enable_ms,
        .break_ctl =            mux_break_ctl,
        .startup =              mux_startup,
        .shutdown =             mux_shutdown,
index 86de447..b5c3292 100644 (file)
@@ -815,17 +815,11 @@ static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
                             u->membase + AUART_LINECTRL_CLR);
 }
 
-static void mxs_auart_enable_ms(struct uart_port *port)
-{
-       /* just empty */
-}
-
 static struct uart_ops mxs_auart_ops = {
        .tx_empty       = mxs_auart_tx_empty,
        .start_tx       = mxs_auart_start_tx,
        .stop_tx        = mxs_auart_stop_tx,
        .stop_rx        = mxs_auart_stop_rx,
-       .enable_ms      = mxs_auart_enable_ms,
        .break_ctl      = mxs_auart_break_ctl,
        .set_mctrl      = mxs_auart_set_mctrl,
        .get_mctrl      = mxs_auart_get_mctrl,
index 693bc6c..c06366b 100644 (file)
@@ -240,11 +240,6 @@ static void nwpserial_break_ctl(struct uart_port *port, int ctl)
        /* N/A */
 }
 
-static void nwpserial_enable_ms(struct uart_port *port)
-{
-       /* N/A */
-}
-
 static void nwpserial_stop_rx(struct uart_port *port)
 {
        struct nwpserial_port *up;
@@ -315,7 +310,6 @@ static struct uart_ops nwpserial_pops = {
        .stop_tx      = nwpserial_stop_tx,
        .start_tx     = nwpserial_start_tx,
        .stop_rx      = nwpserial_stop_rx,
-       .enable_ms    = nwpserial_enable_ms,
        .break_ctl    = nwpserial_break_ctl,
        .startup      = nwpserial_startup,
        .shutdown     = nwpserial_shutdown,
index 0cb6a8e..ea4ffc2 100644 (file)
@@ -736,9 +736,10 @@ static void pch_request_dma(struct uart_port *port)
        dma_cap_zero(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 */
        param = &priv->param_tx;
        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,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        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__);
                return 0;
        }
index c638c53..21b7d8b 100644 (file)
@@ -778,7 +778,7 @@ static struct uart_ops serial_pxa_pops = {
        .request_port   = serial_pxa_request_port,
        .config_port    = serial_pxa_config_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_put_char = serial_pxa_put_poll_char,
 #endif
index c1d3ebd..4aff02d 100644 (file)
@@ -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)
 {
        return to_ourport(port)->info;
@@ -952,7 +948,6 @@ static struct uart_ops s3c24xx_serial_ops = {
        .stop_tx        = s3c24xx_serial_stop_tx,
        .start_tx       = s3c24xx_serial_start_tx,
        .stop_rx        = s3c24xx_serial_stop_rx,
-       .enable_ms      = s3c24xx_serial_enable_ms,
        .break_ctl      = s3c24xx_serial_break_ctl,
        .startup        = s3c24xx_serial_startup,
        .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);
        }
 
-       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);
 
        /* 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)
 {
+       struct device_node *np = pdev->dev.of_node;
        struct s3c24xx_uart_port *ourport;
+       int index = probe_index;
        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);
        if (!ourport->drv_data) {
@@ -1293,9 +1296,15 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
                        dev_get_platdata(&pdev->dev) :
                        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++;
 
@@ -1303,7 +1312,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 
        ret = s3c24xx_serial_init_port(ourport, pdev);
        if (ret < 0)
-               goto probe_err;
+               return ret;
 
        if (!s3c24xx_uart_drv.state) {
                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");
 
        return 0;
-
- probe_err:
-       return ret;
 }
 
 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:
                        *bits = 7;
                        break;
-               default:
                case S3C2410_LCON_CS8:
+               default:
                        *bits = 8;
                        break;
                }
@@ -1712,9 +1718,7 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
 #define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
 #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 = {
        .info = &(struct s3c24xx_uart_info) {
                .name           = "Samsung S3C6400 UART",
index 1b6a77c..3284c31 100644 (file)
@@ -991,7 +991,6 @@ static const struct uart_ops sc16is7xx_ops = {
        .stop_tx        = sc16is7xx_stop_tx,
        .start_tx       = sc16is7xx_start_tx,
        .stop_rx        = sc16is7xx_stop_rx,
-       .enable_ms      = sc16is7xx_null_void,
        .break_ctl      = sc16is7xx_break_ctl,
        .startup        = sc16is7xx_startup,
        .shutdown       = sc16is7xx_shutdown,
@@ -1061,7 +1060,6 @@ static int sc16is7xx_probe(struct device *dev,
                           struct regmap *regmap, int irq, unsigned long flags)
 {
        unsigned long freq, *pfreq = dev_get_platdata(dev);
-       struct clk *clk;
        int i, ret;
        struct sc16is7xx_port *s;
 
@@ -1077,14 +1075,14 @@ static int sc16is7xx_probe(struct device *dev,
                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)
                        freq = *pfreq;
                else
-                       return PTR_ERR(clk);
+                       return PTR_ERR(s->clk);
        } else {
-               freq = clk_get_rate(clk);
+               freq = clk_get_rate(s->clk);
        }
 
        s->regmap = regmap;
index e84b6a3..75850f7 100644 (file)
@@ -533,11 +533,6 @@ static unsigned int sccnxp_tx_empty(struct uart_port *port)
        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)
 {
        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,
        .start_tx       = sccnxp_start_tx,
        .stop_rx        = sccnxp_stop_rx,
-       .enable_ms      = sccnxp_enable_ms,
        .break_ctl      = sccnxp_break_ctl,
        .startup        = sccnxp_startup,
        .shutdown       = sccnxp_shutdown,
index d5c2a28..53d7c31 100644 (file)
@@ -482,6 +482,9 @@ static void tegra_uart_stop_tx(struct uart_port *u)
        struct dma_tx_state state;
        int count;
 
+       if (tup->tx_in_progress != TEGRA_UART_TX_DMA)
+               return;
+
        dmaengine_terminate_all(tup->tx_dma_chan);
        dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
        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_tx_status(tup->rx_dma_chan,  tup->rx_cookie, &state);
+       async_tx_ack(tup->rx_dma_desc);
        count = tup->rx_bytes_requested - state.residue;
 
        /* If we are here, DMA is stopped */
index fbf6c5a..8bb19da 100644 (file)
@@ -243,6 +243,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
                /*
                 * 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))
                        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;
 
        termios = &tty->termios;
+       uport->ops->set_termios(uport, termios, old_termios);
 
        /*
         * 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);
        else
                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,
@@ -1050,6 +1052,15 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
        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
  * - 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);
        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);
 
        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);
+       /* reload cflag from termios; port driver may have overriden flags */
+       cflag = tty->termios.c_cflag;
 
        /* Handle transition to B0 status */
        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_port_tty_set(port, NULL);
-       spin_lock_irqsave(&port->lock, flags);
        tty->closing = 0;
+       spin_lock_irqsave(&port->lock, flags);
 
        if (port->blocked_open) {
                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;
        int mctrl;
        spin_lock_irq(&uport->lock);
-       uport->ops->enable_ms(uport);
+       uart_enable_ms(uport);
        mctrl = uport->ops->get_mctrl(uport);
        spin_unlock_irq(&uport->lock);
        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;
        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.
         */
@@ -2563,12 +2564,6 @@ static const struct attribute_group tty_dev_attr_group = {
        .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
  *     @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;
        int ret = 0;
        struct device *tty_dev;
+       int num_groups;
 
        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);
 
+       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
         * setserial to be used to alter this port's parameters.
         */
        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))) {
                device_set_wakeup_capable(tty_dev, 1);
        } else {
@@ -2702,6 +2712,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
         */
        if (uport->type != PORT_UNKNOWN)
                uport->ops->release_port(uport);
+       kfree(uport->tty_groups);
 
        /*
         * Indicate that there isn't a port here anymore.
index ea85460..af11564 100644 (file)
@@ -142,7 +142,6 @@ struct uart_txx9_port {
 #define TXX9_SIFCR_RDIL_12     0x00000180
 #define TXX9_SIFCR_RDIL_MAX    0x00000180
 #define TXX9_SIFCR_TDIL_MASK   0x00000018
-#define TXX9_SIFCR_TDIL_MASK   0x00000018
 #define TXX9_SIFCR_TDIL_1      0x00000000
 #define TXX9_SIFCR_TDIL_4      0x00000001
 #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;
 }
 
-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)
 {
        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,
        .start_tx       = serial_txx9_start_tx,
        .stop_rx        = serial_txx9_stop_rx,
-       .enable_ms      = serial_txx9_enable_ms,
        .break_ctl      = serial_txx9_break_ctl,
        .startup        = serial_txx9_startup,
        .shutdown       = serial_txx9_shutdown,
index 88236da..3081e46 100644 (file)
@@ -1560,13 +1560,6 @@ static void sci_stop_rx(struct uart_port *port)
        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)
 {
        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);
 }
 
+/* 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 */
 static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
                                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 recv_max_margin = 0;
 
        /* Find the combination of sample rate and clock select with the
           smallest deviation from the desired baud rate. */
        for (sr = 8; sr <= 32; sr++) {
                for (c = 0; c <= 3; c++) {
                        /* 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;
-                       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) {
                                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 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;
        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.
         * 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);
        if (likely(baud && port->uartclk)) {
                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,
-                                           &cks);
+                                           &cks, frame_len);
                } else {
                        t = sci_scbrr_calc(s, baud, port->uartclk);
                        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);
 
-       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);
 
@@ -2080,7 +2115,6 @@ static struct uart_ops sci_uart_ops = {
        .start_tx       = sci_start_tx,
        .stop_tx        = sci_stop_tx,
        .stop_rx        = sci_stop_rx,
-       .enable_ms      = sci_enable_ms,
        .break_ctl      = sci_break_ctl,
        .startup        = sci_startup,
        .shutdown       = sci_shutdown,
index 9b4d71c..4102192 100644 (file)
@@ -290,7 +290,8 @@ static void sirfsoc_uart_start_tx(struct uart_port *port)
        if (sirfport->tx_dma_chan)
                sirfsoc_uart_tx_with_dma(sirfport);
        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);
                if (!sirfport->is_marco)
                        wr_regl(port, ureg->sirfsoc_int_en_reg,
index 69a62eb..6a7ebf7 100644 (file)
@@ -449,4 +449,4 @@ struct sirfsoc_uart_port {
 
 /* I/O Mode */
 #define SIRFSOC_UART_IO_RX_MAX_CNT             256
-#define SIRFSOC_UART_IO_TX_REASONABLE_CNT      6
+#define SIRFSOC_UART_IO_TX_REASONABLE_CNT      256
index f51ffdc..33e94e5 100644 (file)
@@ -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
  * @port: Port to shut down - we ignore
@@ -396,7 +387,6 @@ static struct uart_ops sn_console_ops = {
        .stop_tx = snp_stop_tx,
        .start_tx = snp_start_tx,
        .stop_rx = snp_stop_rx,
-       .enable_ms = snp_enable_ms,
        .break_ctl = snp_break_ctl,
        .startup = snp_startup,
        .shutdown = snp_shutdown,
index f48b1cc..8b2d735 100644 (file)
@@ -411,12 +411,6 @@ static void asc_stop_rx(struct uart_port *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 */
 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 =   ------------------------
                 *                          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;
        }
 
@@ -644,7 +638,6 @@ static struct uart_ops asc_uart_ops = {
        .start_tx       = asc_start_tx,
        .stop_tx        = asc_stop_tx,
        .stop_rx        = asc_stop_rx,
-       .enable_ms      = asc_enable_ms,
        .break_ctl      = asc_break_ctl,
        .startup        = asc_startup,
        .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
         * 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)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
index dc697ce..20521db 100644 (file)
@@ -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.  */
 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,
        .send_xchar     = sunhv_send_xchar,
        .stop_rx        = sunhv_stop_rx,
-       .enable_ms      = sunhv_enable_ms,
        .break_ctl      = sunhv_break_ctl,
        .startup        = sunhv_startup,
        .shutdown       = sunhv_shutdown,
index 2f57df9..bb09920 100644 (file)
@@ -476,12 +476,6 @@ static void sunsab_stop_rx(struct uart_port *port)
        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.  */
 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,
        .send_xchar     = sunsab_send_xchar,
        .stop_rx        = sunsab_stop_rx,
-       .enable_ms      = sunsab_enable_ms,
        .break_ctl      = sunsab_break_ctl,
        .startup        = sunsab_startup,
        .shutdown       = sunsab_shutdown,
index 613ccf0..453215f 100644 (file)
@@ -314,15 +314,6 @@ static void tilegx_stop_rx(struct uart_port *port)
        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.
  */
@@ -614,7 +605,6 @@ static const struct uart_ops tilegx_ops = {
        .stop_tx        = tilegx_stop_tx,
        .start_tx       = tilegx_start_tx,
        .stop_rx        = tilegx_stop_rx,
-       .enable_ms      = tilegx_enable_ms,
        .break_ctl      = tilegx_break_ctl,
        .startup        = tilegx_startup,
        .shutdown       = tilegx_shutdown,
index f87097a..0d11d50 100644 (file)
@@ -244,11 +244,6 @@ static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
        *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)
 {
        /* N/A */
@@ -405,7 +400,6 @@ static struct uart_ops timbuart_ops = {
        .start_tx = timbuart_start_tx,
        .flush_buffer = timbuart_flush_buffer,
        .stop_rx = timbuart_stop_rx,
-       .enable_ms = timbuart_enable_ms,
        .break_ctl = timbuart_break_ctl,
        .startup = timbuart_startup,
        .shutdown = timbuart_shutdown,
index dce27f3..9fc22f4 100644 (file)
@@ -250,11 +250,6 @@ static void ulite_stop_rx(struct uart_port *port)
                | 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)
 {
        /* N/A */
@@ -395,7 +390,6 @@ static struct uart_ops ulite_ops = {
        .stop_tx        = ulite_stop_tx,
        .start_tx       = ulite_start_tx,
        .stop_rx        = ulite_stop_rx,
-       .enable_ms      = ulite_enable_ms,
        .break_ctl      = ulite_break_ctl,
        .startup        = ulite_startup,
        .shutdown       = ulite_shutdown,
index 1c52074..c107a0f 100644 (file)
@@ -435,16 +435,6 @@ static void qe_uart_stop_rx(struct uart_port *port)
        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
  *
  * 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,
        .start_tx       = qe_uart_start_tx,
        .stop_rx        = qe_uart_stop_rx,
-       .enable_ms      = qe_uart_enable_ms,
        .break_ctl      = qe_uart_break_ctl,
        .startup        = qe_uart_startup,
        .shutdown       = qe_uart_shutdown,
index 8809775..01951d2 100644 (file)
@@ -918,11 +918,6 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
        /* N/A */
 }
 
-static void cdns_uart_enable_ms(struct uart_port *port)
-{
-       /* N/A */
-}
-
 #ifdef CONFIG_CONSOLE_POLL
 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 = {
        .set_mctrl      = cdns_uart_set_mctrl,
        .get_mctrl      = cdns_uart_get_mctrl,
-       .enable_ms      = cdns_uart_enable_ms,
        .start_tx       = cdns_uart_start_tx,
        .stop_tx        = cdns_uart_stop_tx,
        .stop_rx        = cdns_uart_stop_rx,
index d48e040..b799170 100644 (file)
@@ -3267,7 +3267,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        DECLARE_WAITQUEUE(wait, current);
        int             retval;
        bool            do_clocal = false;
-       bool            extra_count = false;
        unsigned long   flags;
        int             dcd;
        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 );
 
        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);
        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);
        
        /* FIXME: Racy on hangup during close wait */
-       if (extra_count)
+       if (!tty_hung_up_p(filp))
                port->count++;
        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);
 
        /* 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,
                                     !(info->port.flags & ASYNC_CLOSING));
                retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
index c359a91..ba1dbcd 100644 (file)
@@ -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));
 
        /* 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,
                                             !(info->port.flags & ASYNC_CLOSING));
                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);
        int             retval;
        bool            do_clocal = false;
-       bool            extra_count = false;
        unsigned long   flags;
        int             cd;
        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);
 
        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);
        port->blocked_open++;
 
@@ -3338,7 +3334,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->open_wait, &wait);
 
-       if (extra_count)
+       if (!tty_hung_up_p(filp))
                port->count++;
        port->blocked_open--;
 
index 53ba853..c3f9091 100644 (file)
@@ -753,7 +753,7 @@ static int open(struct tty_struct *tty, struct file *filp)
                         __FILE__,__LINE__,tty->driver->name, info->port.count);
 
        /* 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,
                                             !(info->port.flags & ASYNC_CLOSING));
                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);
        int             retval;
        bool            do_clocal = false;
-       bool            extra_count = false;
        unsigned long   flags;
        int             cd;
        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 );
 
        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);
        port->blocked_open++;
 
@@ -3362,8 +3358,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->open_wait, &wait);
-
-       if (extra_count)
+       if (!tty_hung_up_p(filp))
                port->count++;
        port->blocked_open--;
 
index 3411071..8fbad34 100644 (file)
@@ -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);
 
-/**
- *     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
  *     @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++)
                                tty->ops->close(tty, cons_filp);
        } else if (tty->ops->hangup)
-               (tty->ops->hangup)(tty);
+               tty->ops->hangup(tty);
        /*
         * We don't want to have driver/ldisc interactions beyond
         * 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))
                return ERR_PTR(-ENODEV);
 
-       tty = alloc_tty_struct();
+       tty = alloc_tty_struct(driver, idx);
        if (!tty) {
                retval = -ENOMEM;
                goto err_module_put;
        }
-       initialize_tty_struct(tty, driver, idx);
 
        tty_lock(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);
        tty->magic = TTY_MAGIC;
        tty_ldisc_init(tty);
@@ -3039,6 +3026,8 @@ void initialize_tty_struct(struct tty_struct *tty,
        tty->index = idx;
        tty_line_name(driver, idx, tty->name);
        tty->dev = tty_get_device(tty);
+
+       return tty;
 }
 
 /**
index 3f746c8..1b93357 100644 (file)
@@ -227,6 +227,8 @@ out:
  *
  *     Perform port level tty hangup flag and count changes. Drop the tty
  *     reference.
+ *
+ *     Caller holds tty lock.
  */
 
 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
  *     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.
+ *
+ *     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,
@@ -358,7 +365,7 @@ int tty_port_block_til_ready(struct tty_port *port,
        DEFINE_WAIT(wait);
 
        /* 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,
                                !(port->flags & ASYNC_CLOSING));
                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 */
        spin_lock_irqsave(&port->lock, flags);
-       if (!tty_hung_up_p(filp))
-               port->count--;
+       port->count--;
        port->blocked_open++;
        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);
 }
 
+/* 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,
                                struct tty_struct *tty, struct file *filp)
 {
@@ -486,9 +496,10 @@ int tty_port_close_start(struct tty_port *port,
                return 0;
        }
        set_bit(ASYNCB_CLOSING, &port->flags);
-       tty->closing = 1;
        spin_unlock_irqrestore(&port->lock, flags);
 
+       tty->closing = 1;
+
        if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
                /* Don't block on a stalled port, just pull the chain */
                if (tty->flow_stopped)
@@ -506,13 +517,15 @@ int tty_port_close_start(struct tty_port *port,
 }
 EXPORT_SYMBOL(tty_port_close_start);
 
+/* Caller holds tty lock */
 void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&port->lock, flags);
        tty->closing = 0;
 
+       spin_lock_irqsave(&port->lock, flags);
+
        if (port->blocked_open) {
                spin_unlock_irqrestore(&port->lock, flags);
                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);
 
+/**
+ * tty_port_close
+ *
+ * Caller holds tty lock
+ *
+ * NB: may drop and reacquire tty lock (in tty_port_close_start()->
+ * tty_wait_until_sent_from_close()) so tty and tty_port may have changed
+ * state (but not hung up or reopened).
+ */
 void tty_port_close(struct tty_port *port, struct tty_struct *tty,
                                                        struct file *filp)
 {
@@ -558,12 +580,19 @@ int tty_port_install(struct tty_port *port, struct tty_driver *driver,
 }
 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,
                                                        struct file *filp)
 {
        spin_lock_irq(&port->lock);
-       if (!tty_hung_up_p(filp))
-               ++port->count;
+       ++port->count;
        spin_unlock_irq(&port->lock);
        tty_port_tty_set(port, tty);
 
index af47a8a..f93649e 100644 (file)
@@ -74,8 +74,10 @@ struct uart_8250_port {
        struct list_head        list;           /* ports on this IRQ */
        unsigned short          capabilities;   /* port capabilities */
        unsigned short          bugs;           /* port bugs */
+       bool                    fifo_bug;       /* min RX trigger if enabled */
        unsigned int            tx_loadsz;      /* transmit fifo load size */
        unsigned char           acr;
+       unsigned char           fcr;
        unsigned char           ier;
        unsigned char           lcr;
        unsigned char           mcr;
@@ -100,6 +102,11 @@ struct uart_8250_port {
        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 *);
 void serial8250_unregister_port(int line);
 void serial8250_suspend_port(int line);
index 5bbb809..cf3a1e7 100644 (file)
@@ -199,6 +199,8 @@ struct uart_port {
        unsigned char           suspended;
        unsigned char           irq_wake;
        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 */
 };
 
index 1c3316a..8413294 100644 (file)
@@ -477,13 +477,11 @@ extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
                        unsigned int cmd, 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 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 void tty_add_file(struct tty_struct *tty, struct file *file);
 extern void tty_free_file(struct file *file);
 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 struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
 extern int tty_release(struct inode *inode, struct file *filp);
index 756a609..e48c608 100644 (file)
  *     This routine is mandatory; if this routine is not filled in,
  *     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);
  *
  *     This routine is called when a particular tty device is closed.
  *     Note: called even if the corresponding open() failed.
  *
- *     Required method.
+ *     Required method. Called with tty lock held.
  *
  * void (*shutdown)(struct tty_struct * tty);
  *
  *
  *     Optional:
  *
+ *     Called with tty lock held.
+ *
  * int (*break_ctl)(struct tty_struct *tty, int state);
  *
  *     This optional routine requests the tty driver to turn on or
index 99b4705..df6c9ab 100644 (file)
 #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_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 */
 /*
  * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting 
index 2ba8b97..61ceb4c 100644 (file)
@@ -320,8 +320,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
              __FILE__, __LINE__, tty->driver->name, port->count);
 
        spin_lock_irqsave(&port->lock, flags);
-       if (!tty_hung_up_p(filp))
-               port->count--;
+       port->count--;
        port->blocked_open++;
        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 (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
                 * do return -EAGAIN/-ERESTARTSYS below anyway?