Эх сурвалжийг харах

Merge branch 'depends/tty-omap-serial' into next/cleanup

This part of the tty tree (unfortunately with all the preceding patches
as well) is a dependency for some of the OMAP cleanups, so we've pulled
it in as a dependency based on agreement with Greg.

Signed-off-by: Olof Johansson <olof@lixom.net>
Olof Johansson 12 жил өмнө
parent
commit
a73403d85a
100 өөрчлөгдсөн 4984 нэмэгдсэн , 3870 устгасан
  1. 9 0
      Documentation/ABI/testing/sysfs-tty
  2. 14 0
      Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
  3. 2 0
      Documentation/devicetree/bindings/tty/serial/of-serial.txt
  4. 0 2
      Documentation/serial/00-INDEX
  5. 0 520
      Documentation/serial/computone.txt
  6. 1 0
      arch/alpha/kernel/srmcons.c
  7. 12 6
      arch/arm/mach-omap2/serial.c
  8. 0 21
      arch/arm/mach-ux500/board-mop500.c
  9. 9 41
      arch/arm/plat-omap/include/plat/omap-serial.h
  10. 2 1
      arch/ia64/hp/sim/simserial.c
  11. 4 0
      arch/m68k/emu/nfcon.c
  12. 15 15
      arch/mips/cavium-octeon/serial.c
  13. 32 0
      arch/mips/sni/a20r.c
  14. 1 0
      arch/parisc/kernel/pdc_cons.c
  15. 2 1
      arch/um/drivers/line.c
  16. 1 0
      arch/xtensa/platforms/iss/console.c
  17. 1 1
      drivers/bluetooth/hci_ath.c
  18. 8 8
      drivers/char/mwave/mwavedd.c
  19. 60 71
      drivers/char/pcmcia/synclink_cs.c
  20. 13 20
      drivers/char/ttyprintk.c
  21. 2 1
      drivers/isdn/capi/capi.c
  22. 4 3
      drivers/isdn/gigaset/interface.c
  23. 24 17
      drivers/isdn/i4l/isdn_tty.c
  24. 8 8
      drivers/misc/ibmasm/uart.c
  25. 59 69
      drivers/misc/pti.c
  26. 12 12
      drivers/mmc/card/sdio_uart.c
  27. 12 10
      drivers/net/ethernet/sgi/ioc3-eth.c
  28. 5 5
      drivers/net/irda/irtty-sir.c
  29. 9 10
      drivers/net/usb/hso.c
  30. 1 0
      drivers/parport/parport_gsc.c
  31. 10 1
      drivers/parport/parport_serial.c
  32. 22 6
      drivers/s390/char/con3215.c
  33. 1 0
      drivers/s390/char/sclp_tty.c
  34. 1 0
      drivers/s390/char/sclp_vt220.c
  35. 24 10
      drivers/s390/char/tty3270.c
  36. 7 7
      drivers/staging/ipack/devices/ipoctal.c
  37. 8 10
      drivers/staging/serqt_usb2/serqt_usb2.c
  38. 1 2
      drivers/staging/speakup/serialio.h
  39. 23 22
      drivers/tty/amiserial.c
  40. 1 0
      drivers/tty/bfin_jtag_comm.c
  41. 52 50
      drivers/tty/cyclades.c
  42. 5 4
      drivers/tty/ehv_bytechan.c
  43. 25 6
      drivers/tty/hvc/hvc_console.c
  44. 49 33
      drivers/tty/hvc/hvcs.c
  45. 2 0
      drivers/tty/hvc/hvsi.c
  46. 1 1
      drivers/tty/hvc/hvsi_lib.c
  47. 1 1
      drivers/tty/ipwireless/tty.c
  48. 7 6
      drivers/tty/isicom.c
  49. 28 11
      drivers/tty/moxa.c
  50. 46 17
      drivers/tty/mxser.c
  51. 86 56
      drivers/tty/n_gsm.c
  52. 5 5
      drivers/tty/n_r3964.c
  53. 24 5
      drivers/tty/n_tty.c
  54. 2 2
      drivers/tty/nozomi.c
  55. 122 112
      drivers/tty/pty.c
  56. 11 11
      drivers/tty/rocket.c
  57. 13 10
      drivers/tty/serial/68328serial.c
  58. 33 51
      drivers/tty/serial/8250/8250.c
  59. 1 33
      drivers/tty/serial/8250/8250.h
  60. 11 11
      drivers/tty/serial/8250/8250_acorn.c
  61. 19 19
      drivers/tty/serial/8250/8250_dw.c
  62. 13 13
      drivers/tty/serial/8250/8250_gsc.c
  63. 13 13
      drivers/tty/serial/8250/8250_hp300.c
  64. 139 66
      drivers/tty/serial/8250/8250_pci.c
  65. 14 14
      drivers/tty/serial/8250/8250_pnp.c
  66. 15 15
      drivers/tty/serial/8250/serial_cs.c
  67. 47 3
      drivers/tty/serial/Kconfig
  68. 3 1
      drivers/tty/serial/Makefile
  69. 3 3
      drivers/tty/serial/altera_uart.c
  70. 4 11
      drivers/tty/serial/amba-pl010.c
  71. 57 32
      drivers/tty/serial/amba-pl011.c
  72. 1 1
      drivers/tty/serial/bfin_uart.c
  73. 24 21
      drivers/tty/serial/crisv10.c
  74. 2 2
      drivers/tty/serial/ifx6x60.c
  75. 4 1
      drivers/tty/serial/imx.c
  76. 2 1
      drivers/tty/serial/ioc3_serial.c
  77. 3 2
      drivers/tty/serial/ioc4_serial.c
  78. 4 4
      drivers/tty/serial/jsm/jsm_tty.c
  79. 823 0
      drivers/tty/serial/lpc32xx_hs.c
  80. 2 34
      drivers/tty/serial/m32r_sio.c
  81. 1 11
      drivers/tty/serial/max3100.c
  82. 0 1215
      drivers/tty/serial/max3107.c
  83. 0 441
      drivers/tty/serial/max3107.h
  84. 1260 0
      drivers/tty/serial/max310x.c
  85. 6 2
      drivers/tty/serial/mpc52xx_uart.c
  86. 1 1
      drivers/tty/serial/msm_serial.c
  87. 5 3
      drivers/tty/serial/msm_smd_tty.c
  88. 4 3
      drivers/tty/serial/mxs-auart.c
  89. 12 1
      drivers/tty/serial/of_serial.c
  90. 316 440
      drivers/tty/serial/omap-serial.c
  91. 4 0
      drivers/tty/serial/pch_uart.c
  92. 14 0
      drivers/tty/serial/pxa.c
  93. 25 21
      drivers/tty/serial/samsung.c
  94. 4 0
      drivers/tty/serial/sc26xx.c
  95. 985 0
      drivers/tty/serial/sccnxp.c
  96. 135 88
      drivers/tty/serial/serial_core.c
  97. 2 6
      drivers/tty/serial/sirfsoc_uart.c
  98. 7 1
      drivers/tty/serial/sunsu.c
  99. 47 39
      drivers/tty/synclink.c
  100. 20 17
      drivers/tty/synclink_gt.c

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

@@ -17,3 +17,12 @@ Description:
 		 device, like 'tty1'.
 		 The file supports poll() to detect virtual
 		 console switches.
+
+What:		/sys/class/tty/ttyS0/uartclk
+Date:		Sep 2012
+Contact:	Tomas Hlavacek <tmshlvck@gmail.com>
+Description:
+		 Shows the current uartclk value associated with the
+		 UART port in serial_core, that is bound to TTY like ttyS0.
+		 uartclk = 16 * baud_base
+

+ 14 - 0
Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt

@@ -0,0 +1,14 @@
+* NXP LPC32xx SoC High Speed UART
+
+Required properties:
+- compatible: Should be "nxp,lpc3220-hsuart"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Example:
+
+	uart1: serial@40014000 {
+		compatible = "nxp,lpc3220-hsuart";
+		reg = <0x40014000 0x1000>;
+		interrupts = <26 0>;
+	};

+ 2 - 0
Documentation/devicetree/bindings/tty/serial/of-serial.txt

@@ -25,6 +25,8 @@ Optional properties:
   accesses to the UART (e.g. TI davinci).
 - used-by-rtas : set to indicate that the port is in use by the OpenFirmware
   RTAS and should not be registered.
+- no-loopback-test: set to indicate that the port does not implements loopback
+  test mode
 
 Example:
 

+ 0 - 2
Documentation/serial/00-INDEX

@@ -2,8 +2,6 @@
 	- this file.
 README.cycladesZ
 	- info on Cyclades-Z firmware loading.
-computone.txt
-	- info on Computone Intelliport II/Plus Multiport Serial Driver.
 digiepca.txt
 	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
 hayes-esp.txt

+ 0 - 520
Documentation/serial/computone.txt

@@ -1,520 +0,0 @@
-NOTE: This is an unmaintained driver.  It is not guaranteed to work due to
-changes made in the tty layer in 2.6.  If you wish to take over maintenance of
-this driver, contact Michael Warfield <mhw@wittsend.com>.
-
-Changelog:
-----------
-11-01-2001:	Original Document
-
-10-29-2004:	Minor misspelling & format fix, update status of driver.
-		James Nelson <james4765@gmail.com>
-
-Computone Intelliport II/Plus Multiport Serial Driver
------------------------------------------------------
-
-Release Notes For Linux Kernel 2.2 and higher.
-These notes are for the drivers which have already been integrated into the
-kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4.
-
-Version: 1.2.14
-Date: 11/01/2001
-Historical Author: Andrew Manison <amanison@america.net>
-Primary Author: Doug McNash
-
-This file assumes that you are using the Computone drivers which are
-integrated into the kernel sources.  For updating the drivers or installing
-drivers into kernels which do not already have Computone drivers, please
-refer to the instructions in the README.computone file in the driver patch.
-
-
-1. INTRODUCTION
-
-This driver supports the entire family of Intelliport II/Plus controllers
-with the exception of the MicroChannel controllers.  It does not support
-products previous to the Intelliport II.
-
-This driver was developed on the v2.0.x Linux tree and has been tested up
-to v2.4.14; it will probably not work with earlier v1.X kernels,.
-
-
-2. QUICK INSTALLATION
-
-Hardware - If you have an ISA card, find a free interrupt and io port. 
-		   List those in use with `cat /proc/interrupts` and 
-		   `cat /proc/ioports`.  Set the card dip switches to a free 
-		   address.  You may need to configure your BIOS to reserve an
-		   irq for an ISA card.  PCI and EISA parameters are set
-		   automagically.  Insert card into computer with the power off 
-		   before or after drivers installation.
-
-	Note the hardware address from the Computone ISA cards installed into
-		the system.  These are required for editing ip2.c or editing
-		/etc/modprobe.d/*.conf, or for specification on the modprobe
-		command line.
-
-	Note that the /etc/modules.conf should be used for older (pre-2.6)
-		kernels.
-
-Software -
-
-Module installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
-   Select (m) module for CONFIG_COMPUTONE under character
-   devices.  CONFIG_PCI and CONFIG_MODULES also may need to be set.
-c) Set address on ISA cards then:
-   edit /usr/src/linux/drivers/char/ip2.c if needed 
-	or
-   edit config file in  /etc/modprobe.d/ if needed (module).
-	or both to match this setting.
-d) Run "make modules"
-e) Run "make modules_install"
-f) Run "/sbin/depmod -a"
-g) install driver using `modprobe ip2 <options>` (options listed below)
-h) run ip2mkdev (either the script below or the binary version)
-
-
-Kernel installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
-   Select (y) kernel for CONFIG_COMPUTONE under character
-   devices.  CONFIG_PCI may need to be set if you have PCI bus.
-c) Set address on ISA cards then:
-	   edit /usr/src/linux/drivers/char/ip2.c  
-           (Optional - may be specified on kernel command line now)
-d) Run "make zImage" or whatever target you prefer.
-e) mv /usr/src/linux/arch/x86/boot/zImage to /boot.
-f) Add new config for this kernel into /etc/lilo.conf, run "lilo"
-	or copy to a floppy disk and boot from that floppy disk.
-g) Reboot using this kernel
-h) run ip2mkdev (either the script below or the binary version)
-
-Kernel command line options:
-
-When compiling the driver into the kernel, io and irq may be
-compiled into the driver by editing ip2.c and setting the values for
-io and irq in the appropriate array.  An alternative is to specify
-a command line parameter to the kernel at boot up.
-
-        ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
-
-Note that this order is very different from the specifications for the
-modload parameters which have separate IRQ and IO specifiers.
-
-The io port also selects PCI (1) and EISA (2) boards.
-
-        io=0    No board
-        io=1    PCI board
-        io=2    EISA board
-        else    ISA board io address
-
-You only need to specify the boards which are present.
-
-        Examples:
-
-                2 PCI boards:
-
-                        ip2=1,0,1,0
-
-                1 ISA board at 0x310 irq 5:
-
-                        ip2=0x310,5
-
-This can be added to and "append" option in lilo.conf similar to this:
-
-        append="ip2=1,0,1,0"
-
-
-3. INSTALLATION
-
-Previously, the driver sources were packaged with a set of patch files
-to update the character drivers' makefile and configuration file, and other 
-kernel source files. A build script (ip2build) was included which applies 
-the patches if needed, and build any utilities needed.
-What you receive may be a single patch file in conventional kernel
-patch format build script. That form can also be applied by
-running patch -p1 < ThePatchFile.  Otherwise run ip2build.
- 
-The driver can be installed as a module (recommended) or built into the 
-kernel. This is selected as for other drivers through the `make config`
-command from the root of the Linux source tree. If the driver is built 
-into the kernel you will need to edit the file ip2.c to match the boards 
-you are installing. See that file for instructions. If the driver is 
-installed as a module the configuration can also be specified on the
-modprobe command line as follows:
-
-	modprobe ip2 irq=irq1,irq2,irq3,irq4 io=addr1,addr2,addr3,addr4
-
-where irqnum is one of the valid Intelliport II interrupts (3,4,5,7,10,11,
-12,15) and addr1-4 are the base addresses for up to four controllers. If 
-the irqs are not specified the driver uses the default in ip2.c (which 
-selects polled mode). If no base addresses are specified the defaults in 
-ip2.c are used. If you are autoloading the driver module with kerneld or
-kmod the base addresses and interrupt number must also be set in ip2.c
-and recompile or just insert and options line in /etc/modprobe.d/*.conf or both.
-The options line is equivalent to the command line and takes precedence over
-what is in ip2.c. 
-
-config sample to put /etc/modprobe.d/*.conf:
-	options ip2 io=1,0x328 irq=1,10
-	alias char-major-71 ip2
-	alias char-major-72 ip2
-	alias char-major-73 ip2
-
-The equivalent in ip2.c:
-
-static int io[IP2_MAX_BOARDS]= { 1, 0x328, 0, 0 };
-static int irq[IP2_MAX_BOARDS] = { 1, 10, -1, -1 }; 
-
-The equivalent for the kernel command line (in lilo.conf):
-
-        append="ip2=1,1,0x328,10"
-
-
-Note:	Both io and irq should be updated to reflect YOUR system.  An "io"
-	address of 1 or 2 indicates a PCI or EISA card in the board table.
-	The PCI or EISA irq will be assigned automatically.
-
-Specifying an invalid or in-use irq will default the driver into
-running in polled mode for that card.  If all irq entries are 0 then
-all cards will operate in polled mode.
-
-If you select the driver as part of the kernel run :
-
-	make zlilo (or whatever you do to create a bootable kernel)
-
-If you selected a module run :
-
-	make modules && make modules_install
-
-The utility ip2mkdev (see 5 and 7 below) creates all the device nodes
-required by the driver.  For a device to be created it must be configured
-in the driver and the board must be installed. Only devices corresponding
-to real IntelliPort II ports are created. With multiple boards and expansion
-boxes this will leave gaps in the sequence of device names. ip2mkdev uses
-Linux tty naming conventions: ttyF0 - ttyF255 for normal devices, and
-cuf0 - cuf255 for callout devices.
-
-
-4. USING THE DRIVERS
-
-As noted above, the driver implements the ports in accordance with Linux
-conventions, and the devices should be interchangeable with the standard
-serial devices. (This is a key point for problem reporting: please make
-sure that what you are trying do works on the ttySx/cuax ports first; then 
-tell us what went wrong with the ip2 ports!)
-
-Higher speeds can be obtained using the setserial utility which remaps 
-38,400 bps (extb) to 57,600 bps, 115,200 bps, or a custom speed. 
-Intelliport II installations using the PowerPort expansion module can
-use the custom speed setting to select the highest speeds: 153,600 bps,
-230,400 bps, 307,200 bps, 460,800bps and 921,600 bps. The base for
-custom baud rate configuration is fixed at 921,600 for cards/expansion
-modules with ST654's and 115200 for those with Cirrus CD1400's.  This
-corresponds to the maximum bit rates those chips are capable.  
-For example if the baud base is 921600 and the baud divisor is 18 then
-the custom rate is 921600/18 = 51200 bps.  See the setserial man page for
-complete details. Of course if stty accepts the higher rates now you can
-use that as well as the standard ioctls().
-
-
-5. ip2mkdev and assorted utilities...
-
-Several utilities, including the source for a binary ip2mkdev utility are
-available under .../drivers/char/ip2.  These can be build by changing to
-that directory and typing "make" after the kernel has be built.  If you do
-not wish to compile the binary utilities, the shell script below can be
-cut out and run as "ip2mkdev" to create the necessary device files.  To
-use the ip2mkdev script, you must have procfs enabled and the proc file
-system mounted on /proc.
-
-
-6. NOTES
-
-This is a release version of the driver, but it is impossible to test it
-in all configurations of Linux. If there is any anomalous behaviour that 
-does not match the standard serial port's behaviour please let us know.
-
-
-7. ip2mkdev shell script
-
-Previously, this script was simply attached here.  It is now attached as a
-shar archive to make it easier to extract the script from the documentation.
-To create the ip2mkdev shell script change to a convenient directory (/tmp
-works just fine) and run the following command:
-
-	unshar Documentation/serial/computone.txt
-		(This file)
-
-You should now have a file ip2mkdev in your current working directory with
-permissions set to execute.  Running that script with then create the
-necessary devices for the Computone boards, interfaces, and ports which
-are present on you system at the time it is run.
-
-
-#!/bin/sh
-# This is a shell archive (produced by GNU sharutils 4.2.1).
-# To extract the files from this archive, save it to some FILE, remove
-# everything before the `!/bin/sh' line above, then type `sh FILE'.
-#
-# Made on 2001-10-29 10:32 EST by <mhw@alcove.wittsend.com>.
-# Source directory was `/home2/src/tmp'.
-#
-# Existing files will *not* be overwritten unless `-c' is specified.
-#
-# This shar contains:
-# length mode       name
-# ------ ---------- ------------------------------------------
-#   4251 -rwxr-xr-x ip2mkdev
-#
-save_IFS="${IFS}"
-IFS="${IFS}:"
-gettext_dir=FAILED
-locale_dir=FAILED
-first_param="$1"
-for dir in $PATH
-do
-  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
-     && ($dir/gettext --version >/dev/null 2>&1)
-  then
-    set `$dir/gettext --version 2>&1`
-    if test "$3" = GNU
-    then
-      gettext_dir=$dir
-    fi
-  fi
-  if test "$locale_dir" = FAILED && test -f $dir/shar \
-     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
-  then
-    locale_dir=`$dir/shar --print-text-domain-dir`
-  fi
-done
-IFS="$save_IFS"
-if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
-then
-  echo=echo
-else
-  TEXTDOMAINDIR=$locale_dir
-  export TEXTDOMAINDIR
-  TEXTDOMAIN=sharutils
-  export TEXTDOMAIN
-  echo="$gettext_dir/gettext -s"
-fi
-if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
-  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
-elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
-  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
-elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
-  shar_touch='touch -am $3$4$5$6$2 "$8"'
-else
-  shar_touch=:
-  echo
-  $echo 'WARNING: not restoring timestamps.  Consider getting and'
-  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
-  echo
-fi
-rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
-#
-if mkdir _sh17581; then
-  $echo 'x -' 'creating lock directory'
-else
-  $echo 'failed to create lock directory'
-  exit 1
-fi
-# ============= ip2mkdev ==============
-if test -f 'ip2mkdev' && test "$first_param" != -c; then
-  $echo 'x -' SKIPPING 'ip2mkdev' '(file already exists)'
-else
-  $echo 'x -' extracting 'ip2mkdev' '(text)'
-  sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' &&
-#!/bin/sh -
-#
-#	ip2mkdev
-#
-#	Make or remove devices as needed for Computone Intelliport drivers
-#
-#	First rule!  If the dev file exists and you need it, don't mess
-#	with it.  That prevents us from screwing up open ttys, ownership
-#	and permissions on a running system!
-#
-#	This script will NOT remove devices that no longer exist if their
-#	board or interface box has been removed.  If you want to get rid
-#	of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*"
-#	before running this script.  Running this script will then recreate
-#	all the valid devices.
-#
-#	Michael H. Warfield
-#	/\/\|=mhw=|\/\/
-#	mhw@wittsend.com
-#
-#	Updated 10/29/2000 for version 1.2.13 naming convention
-#		under devfs.	/\/\|=mhw=|\/\/
-#
-#	Updated 03/09/2000 for devfs support in ip2 drivers. /\/\|=mhw=|\/\/
-#
-X
-if test -d /dev/ip2 ; then
-#	This is devfs mode...  We don't do anything except create symlinks
-#	from the real devices to the old names!
-X	cd /dev
-X	echo "Creating symbolic links to devfs devices"
-X	for i in `ls ip2` ; do
-X		if test ! -L ip2$i ; then
-X			# Remove it incase it wasn't a symlink (old device)
-X			rm -f ip2$i
-X			ln -s ip2/$i ip2$i
-X		fi
-X	done
-X	for i in `( cd tts ; ls F* )` ; do
-X		if test ! -L tty$i ; then
-X			# Remove it incase it wasn't a symlink (old device)
-X			rm -f tty$i
-X			ln -s tts/$i tty$i
-X		fi
-X	done
-X	for i in `( cd cua ; ls F* )` ; do
-X		DEVNUMBER=`expr $i : 'F\(.*\)'`
-X		if test ! -L cuf$DEVNUMBER ; then
-X			# Remove it incase it wasn't a symlink (old device)
-X			rm -f cuf$DEVNUMBER
-X			ln -s cua/$i cuf$DEVNUMBER
-X		fi
-X	done
-X	exit 0
-fi
-X
-if test ! -f /proc/tty/drivers
-then
-X	echo "\
-Unable to check driver status.
-Make sure proc file system is mounted."
-X
-X	exit 255
-fi
-X
-if test ! -f /proc/tty/driver/ip2
-then
-X	echo "\
-Unable to locate ip2 proc file.
-Attempting to load driver"
-X
-X	if /sbin/insmod ip2
-X	then
-X		if test ! -f /proc/tty/driver/ip2
-X		then
-X			echo "\
-Unable to locate ip2 proc file after loading driver.
-Driver initialization failure or driver version error.
-"
-X		exit 255
-X		fi
-X	else
-X		echo "Unable to load ip2 driver."
-X		exit 255
-X	fi
-fi
-X
-# Ok...  So we got the driver loaded and we can locate the procfs files.
-# Next we need our major numbers.
-X
-TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tt/!d' -e 's/.*tt[^ 	]*[ 	]*\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/drivers`
-CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu[^ 	]*[ 	]*\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/drivers`
-BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/driver/ip2`
-X
-echo "\
-TTYMAJOR = $TTYMAJOR
-CUAMAJOR = $CUAMAJOR
-BRDMAJOR = $BRDMAJOR
-"
-X
-# Ok...  Now we should know our major numbers, if appropriate...
-# Now we need our boards and start the device loops.
-X
-grep '^Board [0-9]:' /proc/tty/driver/ip2 | while read token number type alltherest
-do
-X	# The test for blank "type" will catch the stats lead-in lines
-X	# if they exist in the file
-X	if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = ""
-X	then
-X		continue
-X	fi
-X
-X	BOARDNO=`expr "$number" : '\([0-9]\):'`
-X	PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '`
-X	MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '`
-X
-X	if test "$BOARDNO" = "" -o "$PORTS" = ""
-X	then
-#	This may be a bug.  We should at least get this much information
-X		echo "Unable to process board line"
-X		continue
-X	fi
-X
-X	if test "$MINORS" = ""
-X	then
-#	Silently skip this one.  This board seems to have no boxes
-X		continue
-X	fi
-X
-X	echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS"
-X
-X	if test "$BRDMAJOR" != ""
-X	then
-X		BRDMINOR=`expr $BOARDNO \* 4`
-X		STSMINOR=`expr $BRDMINOR + 1`
-X		if test ! -c /dev/ip2ipl$BOARDNO ; then
-X			mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR
-X		fi
-X		if test ! -c /dev/ip2stat$BOARDNO ; then
-X			mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR
-X		fi
-X	fi
-X
-X	if test "$TTYMAJOR" != ""
-X	then
-X		PORTNO=$BOARDBASE
-X
-X		for PORTNO in $MINORS
-X		do
-X			if test ! -c /dev/ttyF$PORTNO ; then
-X				# We got the hardware but no device - make it
-X				mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
-X			fi	
-X		done
-X	fi
-X
-X	if test "$CUAMAJOR" != ""
-X	then
-X		PORTNO=$BOARDBASE
-X
-X		for PORTNO in $MINORS
-X		do
-X			if test ! -c /dev/cuf$PORTNO ; then
-X				# We got the hardware but no device - make it
-X				mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
-X			fi	
-X		done
-X	fi
-done
-X
-Xexit 0
-SHAR_EOF
-  (set 20 01 10 29 10 32 01 'ip2mkdev'; eval "$shar_touch") &&
-  chmod 0755 'ip2mkdev' ||
-  $echo 'restore of' 'ip2mkdev' 'failed'
-  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
-  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
-    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
-    || $echo 'ip2mkdev:' 'MD5 check failed'
-cb5717134509f38bad9fde6b1f79b4a4  ip2mkdev
-SHAR_EOF
-  else
-    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`"
-    test 4251 -eq "$shar_count" ||
-    $echo 'ip2mkdev:' 'original size' '4251,' 'current size' "$shar_count!"
-  fi
-fi
-rm -fr _sh17581
-exit 0

+ 1 - 0
arch/alpha/kernel/srmcons.c

@@ -223,6 +223,7 @@ srmcons_init(void)
 		driver->subtype = SYSTEM_TYPE_SYSCONS;
 		driver->init_termios = tty_std_termios;
 		tty_set_operations(driver, &srmcons_ops);
+		tty_port_link_device(&srmcons_singleton.port, driver, 0);
 		err = tty_register_driver(driver);
 		if (err) {
 			put_tty_driver(driver);

+ 12 - 6
arch/arm/mach-omap2/serial.c

@@ -80,8 +80,9 @@ static struct omap_uart_port_info omap_serial_default_info[] __initdata = {
 };
 
 #ifdef CONFIG_PM
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 
 	if (!od)
@@ -98,15 +99,17 @@ static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
  * in Smartidle Mode When Configured for DMA Operations.
  * WA: configure uart in force idle mode.
  */
-static void omap_uart_set_noidle(struct platform_device *pdev)
+static void omap_uart_set_noidle(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 
 	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
 }
 
-static void omap_uart_set_smartidle(struct platform_device *pdev)
+static void omap_uart_set_smartidle(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 	u8 idlemode;
 
@@ -119,10 +122,10 @@ static void omap_uart_set_smartidle(struct platform_device *pdev)
 }
 
 #else
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
 {}
-static void omap_uart_set_noidle(struct platform_device *pdev) {}
-static void omap_uart_set_smartidle(struct platform_device *pdev) {}
+static void omap_uart_set_noidle(struct device *dev) {}
+static void omap_uart_set_smartidle(struct device *dev) {}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_OMAP_MUX
@@ -303,6 +306,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 	omap_up.dma_rx_timeout = info->dma_rx_timeout;
 	omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
 	omap_up.autosuspend_timeout = info->autosuspend_timeout;
+	omap_up.DTR_gpio = info->DTR_gpio;
+	omap_up.DTR_inverted = info->DTR_inverted;
+	omap_up.DTR_present = info->DTR_present;
 
 	pdata = &omap_up;
 	pdata_size = sizeof(struct omap_uart_port_info);

+ 0 - 21
arch/arm/mach-ux500/board-mop500.c

@@ -524,33 +524,12 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
 };
 #endif
 
-#define PRCC_K_SOFTRST_SET      0x18
-#define PRCC_K_SOFTRST_CLEAR    0x1C
-static void ux500_uart0_reset(void)
-{
-	void __iomem *prcc_rst_set, *prcc_rst_clr;
-
-	prcc_rst_set = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
-			PRCC_K_SOFTRST_SET);
-	prcc_rst_clr = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
-			PRCC_K_SOFTRST_CLEAR);
-
-	/* Activate soft reset PRCC_K_SOFTRST_CLEAR */
-	writel((readl(prcc_rst_clr) | 0x1), prcc_rst_clr);
-	udelay(1);
-
-	/* Release soft reset PRCC_K_SOFTRST_SET */
-	writel((readl(prcc_rst_set) | 0x1), prcc_rst_set);
-	udelay(1);
-}
-
 static struct amba_pl011_data uart0_plat = {
 #ifdef CONFIG_STE_DMA40
 	.dma_filter = stedma40_filter,
 	.dma_rx_param = &uart0_dma_cfg_rx,
 	.dma_tx_param = &uart0_dma_cfg_tx,
 #endif
-	.reset = ux500_uart0_reset,
 };
 
 static struct amba_pl011_data uart1_plat = {

+ 9 - 41
arch/arm/plat-omap/include/plat/omap-serial.h

@@ -18,7 +18,7 @@
 #define __OMAP_SERIAL_H__
 
 #include <linux/serial_core.h>
-#include <linux/platform_device.h>
+#include <linux/device.h>
 #include <linux/pm_qos.h>
 
 #include <plat/mux.h>
@@ -42,10 +42,10 @@
 #define OMAP_UART_WER_MOD_WKUP	0X7F
 
 /* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX		0x04
+#define OMAP_UART_SW_TX		0x8
 
 /* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX		0x04
+#define OMAP_UART_SW_RX		0x2
 
 #define OMAP_UART_SYSC_RESET	0X07
 #define OMAP_UART_TCR_TRIG	0X0F
@@ -69,11 +69,14 @@ struct omap_uart_port_info {
 	unsigned int		dma_rx_timeout;
 	unsigned int		autosuspend_timeout;
 	unsigned int		dma_rx_poll_rate;
+	int			DTR_gpio;
+	int			DTR_inverted;
+	int			DTR_present;
 
 	int (*get_context_loss_count)(struct device *);
-	void (*set_forceidle)(struct platform_device *);
-	void (*set_noidle)(struct platform_device *);
-	void (*enable_wakeup)(struct platform_device *, bool);
+	void (*set_forceidle)(struct device *);
+	void (*set_noidle)(struct device *);
+	void (*enable_wakeup)(struct device *, bool);
 };
 
 struct uart_omap_dma {
@@ -102,39 +105,4 @@ struct uart_omap_dma {
 	unsigned int		rx_timeout;
 };
 
-struct uart_omap_port {
-	struct uart_port	port;
-	struct uart_omap_dma	uart_dma;
-	struct platform_device	*pdev;
-
-	unsigned char		ier;
-	unsigned char		lcr;
-	unsigned char		mcr;
-	unsigned char		fcr;
-	unsigned char		efr;
-	unsigned char		dll;
-	unsigned char		dlh;
-	unsigned char		mdr1;
-	unsigned char		scr;
-
-	int			use_dma;
-	/*
-	 * Some bits in registers are cleared on a read, so they must
-	 * be saved whenever the register is read but the bits will not
-	 * be immediately processed.
-	 */
-	unsigned int		lsr_break_flag;
-	unsigned char		msr_saved_flags;
-	char			name[20];
-	unsigned long		port_activity;
-	u32			context_loss_cnt;
-	u32			errata;
-	u8			wakeups_enabled;
-
-	struct pm_qos_request	pm_qos_request;
-	u32			latency;
-	u32			calc_latency;
-	struct work_struct	qos_work;
-};
-
 #endif /* __OMAP_SERIAL_H__ */

+ 2 - 1
arch/ia64/hp/sim/simserial.c

@@ -338,7 +338,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 	}
 }
@@ -545,6 +545,7 @@ static int __init simrs_init(void)
 	/* the port is imaginary */
 	printk(KERN_INFO "ttyS0 at 0x03f8 (irq = %d) is a 16550\n", state->irq);
 
+	tty_port_link_device(&state->port, hp_simserial_driver, 0);
 	retval = tty_register_driver(hp_simserial_driver);
 	if (retval) {
 		printk(KERN_ERR "Couldn't register simserial driver\n");

+ 4 - 0
arch/m68k/emu/nfcon.c

@@ -19,6 +19,7 @@
 #include <asm/natfeat.h>
 
 static int stderr_id;
+static struct tty_port nfcon_tty_port;
 static struct tty_driver *nfcon_tty_driver;
 
 static void nfputs(const char *str, unsigned int count)
@@ -119,6 +120,8 @@ static int __init nfcon_init(void)
 {
 	int res;
 
+	tty_port_init(&nfcon_tty_port);
+
 	stderr_id = nf_get_id("NF_STDERR");
 	if (!stderr_id)
 		return -ENODEV;
@@ -135,6 +138,7 @@ static int __init nfcon_init(void)
 	nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
 
 	tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
+	tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0);
 	res = tty_register_driver(nfcon_tty_driver);
 	if (res) {
 		pr_err("failed to register nfcon tty driver\n");

+ 15 - 15
arch/mips/cavium-octeon/serial.c

@@ -47,40 +47,40 @@ static int __devinit octeon_serial_probe(struct platform_device *pdev)
 {
 	int irq, res;
 	struct resource *res_mem;
-	struct uart_port port;
+	struct uart_8250_port up;
 
 	/* All adaptors have an irq.  */
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 		return irq;
 
-	memset(&port, 0, sizeof(port));
+	memset(&up, 0, sizeof(up));
 
-	port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
-	port.type = PORT_OCTEON;
-	port.iotype = UPIO_MEM;
-	port.regshift = 3;
-	port.dev = &pdev->dev;
+	up.port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+	up.port.type = PORT_OCTEON;
+	up.port.iotype = UPIO_MEM;
+	up.port.regshift = 3;
+	up.port.dev = &pdev->dev;
 
 	if (octeon_is_simulation())
 		/* Make simulator output fast*/
-		port.uartclk = 115200 * 16;
+		up.port.uartclk = 115200 * 16;
 	else
-		port.uartclk = octeon_get_io_clock_rate();
+		up.port.uartclk = octeon_get_io_clock_rate();
 
-	port.serial_in = octeon_serial_in;
-	port.serial_out = octeon_serial_out;
-	port.irq = irq;
+	up.port.serial_in = octeon_serial_in;
+	up.port.serial_out = octeon_serial_out;
+	up.port.irq = irq;
 
 	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res_mem == NULL) {
 		dev_err(&pdev->dev, "found no memory resource\n");
 		return -ENXIO;
 	}
-	port.mapbase = res_mem->start;
-	port.membase = ioremap(res_mem->start, resource_size(res_mem));
+	up.port.mapbase = res_mem->start;
+	up.port.membase = ioremap(res_mem->start, resource_size(res_mem));
 
-	res = serial8250_register_port(&port);
+	res = serial8250_register_8250_port(&up);
 
 	return res >= 0 ? 0 : res;
 }

+ 32 - 0
arch/mips/sni/a20r.c

@@ -133,6 +133,38 @@ static struct platform_device sc26xx_pdev = {
 	}
 };
 
+#warning "Please try migrate to use new driver SCCNXP and report the status" \
+	 "in the linux-serial mailing list."
+
+/* The code bellow is a replacement of SC26XX to SCCNXP */
+#if 0
+#include <linux/platform_data/sccnxp.h>
+
+static struct sccnxp_pdata sccnxp_data = {
+	.reg_shift	= 2,
+	.frequency	= 3686400,
+	.mctrl_cfg[0]	= MCTRL_SIG(DTR_OP, LINE_OP7) |
+			  MCTRL_SIG(RTS_OP, LINE_OP3) |
+			  MCTRL_SIG(DSR_IP, LINE_IP5) |
+			  MCTRL_SIG(DCD_IP, LINE_IP6),
+	.mctrl_cfg[1]	= MCTRL_SIG(DTR_OP, LINE_OP2) |
+			  MCTRL_SIG(RTS_OP, LINE_OP1) |
+			  MCTRL_SIG(DSR_IP, LINE_IP0) |
+			  MCTRL_SIG(CTS_IP, LINE_IP1) |
+			  MCTRL_SIG(DCD_IP, LINE_IP2) |
+			  MCTRL_SIG(RNG_IP, LINE_IP3),
+};
+
+static struct platform_device sc2681_pdev = {
+	.name		= "sc2681",
+	.resource	= sc2xxx_rsrc,
+	.num_resources	= ARRAY_SIZE(sc2xxx_rsrc),
+	.dev	= {
+		.platform_data	= &sccnxp_data,
+	},
+};
+#endif
+
 static u32 a20r_ack_hwint(void)
 {
 	u32 status = read_c0_status();

+ 1 - 0
arch/parisc/kernel/pdc_cons.c

@@ -202,6 +202,7 @@ static int __init pdc_console_tty_driver_init(void)
 	pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
 		TTY_DRIVER_RESET_TERMIOS;
 	tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
+	tty_port_link_device(&tty_port, pdc_console_tty_driver, 0);
 
 	err = tty_register_driver(pdc_console_tty_driver);
 	if (err) {

+ 2 - 1
arch/um/drivers/line.c

@@ -409,7 +409,8 @@ int setup_one_line(struct line *lines, int n, char *init,
 		line->valid = 1;
 		err = parse_chan_pair(new, line, n, opts, error_out);
 		if (!err) {
-			struct device *d = tty_register_device(driver, n, NULL);
+			struct device *d = tty_port_register_device(&line->port,
+					driver, n, NULL);
 			if (IS_ERR(d)) {
 				*error_out = "Failed to register device";
 				err = PTR_ERR(d);

+ 1 - 0
arch/xtensa/platforms/iss/console.c

@@ -223,6 +223,7 @@ int __init rs_init(void)
 	serial_driver->flags = TTY_DRIVER_REAL_RAW;
 
 	tty_set_operations(serial_driver, &serial_ops);
+	tty_port_link_device(&serial_port, serial_driver, 0);
 
 	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");

+ 1 - 1
drivers/bluetooth/hci_ath.c

@@ -58,7 +58,7 @@ static int ath_wakeup_ar3k(struct tty_struct *tty)
 		return status;
 
 	/* Disable Automatic RTSCTS */
-	memcpy(&ktermios, tty->termios, sizeof(ktermios));
+	ktermios = tty->termios;
 	ktermios.c_cflag &= ~CRTSCTS;
 	tty_set_termios(tty, &ktermios);
 

+ 8 - 8
drivers/char/mwave/mwavedd.c

@@ -430,7 +430,7 @@ static ssize_t mwave_write(struct file *file, const char __user *buf,
 
 static int register_serial_portandirq(unsigned int port, int irq)
 {
-	struct uart_port uart;
+	struct uart_8250_port uart;
 	
 	switch ( port ) {
 		case 0x3f8:
@@ -462,14 +462,14 @@ static int register_serial_portandirq(unsigned int port, int irq)
 	} /* switch */
 	/* irq is okay */
 
-	memset(&uart, 0, sizeof(struct uart_port));
+	memset(&uart, 0, sizeof(uart));
 	
-	uart.uartclk =  1843200;
-	uart.iobase = port;
-	uart.irq = irq;
-	uart.iotype = UPIO_PORT;
-	uart.flags =  UPF_SHARE_IRQ;
-	return serial8250_register_port(&uart);
+	uart.port.uartclk =  1843200;
+	uart.port.iobase = port;
+	uart.port.irq = irq;
+	uart.port.iotype = UPIO_PORT;
+	uart.port.flags =  UPF_SHARE_IRQ;
+	return serial8250_register_8250_port(&uart);
 }
 
 

+ 60 - 71
drivers/char/pcmcia/synclink_cs.c

@@ -1050,7 +1050,7 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
-	if (info->port.flags & ASYNC_CTS_FLOW) {
+	if (tty_port_cts_enabled(&info->port)) {
 		if (tty->hw_stopped) {
 			if (info->serial_signals & SerialSignal_CTS) {
 				if (debug_level >= DEBUG_LEVEL_ISR)
@@ -1344,7 +1344,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty)
 	/* TODO:disable interrupts instead of reset to preserve signal states */
 	reset_device(info);
 
- 	if (!tty || tty->termios->c_cflag & HUPCL) {
+ 	if (!tty || tty->termios.c_cflag & HUPCL) {
  		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
 		set_signals(info);
 	}
@@ -1385,7 +1385,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty)
 	port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);
 	get_signals(info);
 
-	if (info->netcount || (tty && (tty->termios->c_cflag & CREAD)))
+	if (info->netcount || (tty && (tty->termios.c_cflag & CREAD)))
 		rx_start(info);
 
 	spin_unlock_irqrestore(&info->lock,flags);
@@ -1398,14 +1398,14 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
 	unsigned cflag;
 	int bits_per_char;
 
-	if (!tty || !tty->termios)
+	if (!tty)
 		return;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_change_params(%s)\n",
 			 __FILE__,__LINE__, info->device_name );
 
-	cflag = tty->termios->c_cflag;
+	cflag = tty->termios.c_cflag;
 
 	/* if B0 rate (hangup) specified then negate DTR and RTS */
 	/* otherwise assert DTR and RTS */
@@ -1728,7 +1728,7 @@ static void mgslpc_throttle(struct tty_struct * tty)
 	if (I_IXOFF(tty))
 		mgslpc_send_xchar(tty, STOP_CHAR(tty));
 
- 	if (tty->termios->c_cflag & CRTSCTS) {
+ 	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->lock,flags);
 		info->serial_signals &= ~SerialSignal_RTS;
 	 	set_signals(info);
@@ -1757,7 +1757,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty)
 			mgslpc_send_xchar(tty, START_CHAR(tty));
 	}
 
- 	if (tty->termios->c_cflag & CRTSCTS) {
+ 	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->lock,flags);
 		info->serial_signals |= SerialSignal_RTS;
 	 	set_signals(info);
@@ -2293,8 +2293,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 			tty->driver->name );
 
 	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag)
+	if ((tty->termios.c_cflag == old_termios->c_cflag)
+	    && (RELEVANT_IFLAG(tty->termios.c_iflag)
 		== RELEVANT_IFLAG(old_termios->c_iflag)))
 	  return;
 
@@ -2302,7 +2302,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 
 	/* Handle transition to B0 status */
 	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
+	    !(tty->termios.c_cflag & CBAUD)) {
 		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
 		spin_lock_irqsave(&info->lock,flags);
 	 	set_signals(info);
@@ -2311,9 +2311,9 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
+	    tty->termios.c_cflag & CBAUD) {
 		info->serial_signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) ||
+ 		if (!(tty->termios.c_cflag & CRTSCTS) ||
  		    !test_bit(TTY_THROTTLED, &tty->flags)) {
 			info->serial_signals |= SerialSignal_RTS;
  		}
@@ -2324,7 +2324,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 
 	/* Handle turning off CRTSCTS */
 	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		tx_release(tty);
 	}
@@ -2731,6 +2731,8 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
 #if SYNCLINK_GENERIC_HDLC
 	hdlcdev_init(info);
 #endif
+	tty_port_register_device(&info->port, serial_driver, info->line,
+			&info->p_dev->dev);
 }
 
 static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
@@ -2744,6 +2746,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
 				last->next_device = info->next_device;
 			else
 				mgslpc_device_list = info->next_device;
+			tty_unregister_device(serial_driver, info->line);
 #if SYNCLINK_GENERIC_HDLC
 			hdlcdev_exit(info);
 #endif
@@ -2798,77 +2801,63 @@ static const struct tty_operations mgslpc_ops = {
 	.proc_fops = &mgslpc_proc_fops,
 };
 
-static void synclink_cs_cleanup(void)
+static int __init synclink_cs_init(void)
 {
 	int rc;
 
-	while(mgslpc_device_list)
-		mgslpc_remove_device(mgslpc_device_list);
-
-	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
-			printk("%s(%d) failed to unregister tty driver err=%d\n",
-			       __FILE__,__LINE__,rc);
-		put_tty_driver(serial_driver);
+	if (break_on_load) {
+		mgslpc_get_text_ptr();
+		BREAKPOINT();
 	}
 
-	pcmcia_unregister_driver(&mgslpc_driver);
-}
-
-static int __init synclink_cs_init(void)
-{
-    int rc;
-
-    if (break_on_load) {
-	    mgslpc_get_text_ptr();
-	    BREAKPOINT();
-    }
-
-    if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
-	    return rc;
-
-    serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT);
-    if (!serial_driver) {
-	    rc = -ENOMEM;
-	    goto error;
-    }
+	serial_driver = tty_alloc_driver(MAX_DEVICE_COUNT,
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_DYNAMIC_DEV);
+	if (IS_ERR(serial_driver)) {
+		rc = PTR_ERR(serial_driver);
+		goto err;
+	}
 
-    /* Initialize the tty_driver structure */
-
-    serial_driver->driver_name = "synclink_cs";
-    serial_driver->name = "ttySLP";
-    serial_driver->major = ttymajor;
-    serial_driver->minor_start = 64;
-    serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-    serial_driver->subtype = SERIAL_TYPE_NORMAL;
-    serial_driver->init_termios = tty_std_termios;
-    serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    serial_driver->flags = TTY_DRIVER_REAL_RAW;
-    tty_set_operations(serial_driver, &mgslpc_ops);
-
-    if ((rc = tty_register_driver(serial_driver)) < 0) {
-	    printk("%s(%d):Couldn't register serial driver\n",
-		   __FILE__,__LINE__);
-	    put_tty_driver(serial_driver);
-	    serial_driver = NULL;
-	    goto error;
-    }
+	/* Initialize the tty_driver structure */
+	serial_driver->driver_name = "synclink_cs";
+	serial_driver->name = "ttySLP";
+	serial_driver->major = ttymajor;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+	B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	tty_set_operations(serial_driver, &mgslpc_ops);
+
+	rc = tty_register_driver(serial_driver);
+	if (rc < 0) {
+		printk(KERN_ERR "%s(%d):Couldn't register serial driver\n",
+				__FILE__, __LINE__);
+		goto err_put_tty;
+	}
 
-    printk("%s %s, tty major#%d\n",
-	   driver_name, driver_version,
-	   serial_driver->major);
+	rc = pcmcia_register_driver(&mgslpc_driver);
+	if (rc < 0)
+		goto err_unreg_tty;
 
-    return 0;
+	printk(KERN_INFO "%s %s, tty major#%d\n", driver_name, driver_version,
+			serial_driver->major);
 
-error:
-    synclink_cs_cleanup();
-    return rc;
+	return 0;
+err_unreg_tty:
+	tty_unregister_driver(serial_driver);
+err_put_tty:
+	put_tty_driver(serial_driver);
+err:
+	return rc;
 }
 
 static void __exit synclink_cs_exit(void)
 {
-	synclink_cs_cleanup();
+	pcmcia_unregister_driver(&mgslpc_driver);
+	tty_unregister_driver(serial_driver);
+	put_tty_driver(serial_driver);
 }
 
 module_init(synclink_cs_init);

+ 13 - 20
drivers/char/ttyprintk.c

@@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count)
 				tmp[tpk_curr + 1] = '\0';
 				printk(KERN_INFO "%s%s", tpk_tag, tmp);
 				tpk_curr = 0;
-				if (buf[i + 1] == '\n')
+				if ((i + 1) < count && buf[i + 1] == '\n')
 					i++;
 				break;
 			case '\n':
@@ -178,11 +178,17 @@ static struct tty_driver *ttyprintk_driver;
 static int __init ttyprintk_init(void)
 {
 	int ret = -ENOMEM;
-	void *rp;
 
-	ttyprintk_driver = alloc_tty_driver(1);
-	if (!ttyprintk_driver)
-		return ret;
+	tty_port_init(&tpk_port.port);
+	tpk_port.port.ops = &null_ops;
+	mutex_init(&tpk_port.port_write_mutex);
+
+	ttyprintk_driver = tty_alloc_driver(1,
+			TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_UNNUMBERED_NODE);
+	if (IS_ERR(ttyprintk_driver))
+		return PTR_ERR(ttyprintk_driver);
 
 	ttyprintk_driver->driver_name = "ttyprintk";
 	ttyprintk_driver->name = "ttyprintk";
@@ -191,9 +197,8 @@ static int __init ttyprintk_init(void)
 	ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
 	ttyprintk_driver->init_termios = tty_std_termios;
 	ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
-	ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
-		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 	tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+	tty_port_link_device(&tpk_port.port, ttyprintk_driver, 0);
 
 	ret = tty_register_driver(ttyprintk_driver);
 	if (ret < 0) {
@@ -201,22 +206,10 @@ static int __init ttyprintk_init(void)
 		goto error;
 	}
 
-	/* create our unnumbered device */
-	rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
-				ttyprintk_driver->name);
-	if (IS_ERR(rp)) {
-		printk(KERN_ERR "Couldn't create ttyprintk device\n");
-		ret = PTR_ERR(rp);
-		goto error;
-	}
-
-	tty_port_init(&tpk_port.port);
-	tpk_port.port.ops = &null_ops;
-	mutex_init(&tpk_port.port_write_mutex);
-
 	return 0;
 
 error:
+	tty_unregister_driver(ttyprintk_driver);
 	put_tty_driver(ttyprintk_driver);
 	ttyprintk_driver = NULL;
 	return ret;

+ 2 - 1
drivers/isdn/capi/capi.c

@@ -234,7 +234,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
 
 	mp->minor = minor;
 
-	dev = tty_register_device(capinc_tty_driver, minor, NULL);
+	dev = tty_port_register_device(&mp->port, capinc_tty_driver, minor,
+			NULL);
 	if (IS_ERR(dev))
 		goto err_out2;
 

+ 4 - 3
drivers/isdn/gigaset/interface.c

@@ -446,8 +446,8 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
 		goto out;
 	}
 
-	iflag = tty->termios->c_iflag;
-	cflag = tty->termios->c_cflag;
+	iflag = tty->termios.c_iflag;
+	cflag = tty->termios.c_cflag;
 	old_cflag = old ? old->c_cflag : cflag;
 	gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
 		cs->minor_index, iflag, cflag, old_cflag);
@@ -524,7 +524,8 @@ void gigaset_if_init(struct cardstate *cs)
 	tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs);
 
 	mutex_lock(&cs->mutex);
-	cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
+	cs->tty_dev = tty_port_register_device(&cs->port, drv->tty,
+			cs->minor_index, NULL);
 
 	if (!IS_ERR(cs->tty_dev))
 		dev_set_drvdata(cs->tty_dev, cs);

+ 24 - 17
drivers/isdn/i4l/isdn_tty.c

@@ -1009,15 +1009,15 @@ isdn_tty_change_speed(modem_info *info)
 		quot;
 	int i;
 
-	if (!port->tty || !port->tty->termios)
+	if (!port->tty)
 		return;
-	cflag = port->tty->termios->c_cflag;
+	cflag = port->tty->termios.c_cflag;
 
 	quot = i = cflag & CBAUD;
 	if (i & CBAUDEX) {
 		i &= ~CBAUDEX;
 		if (i < 1 || i > 2)
-			port->tty->termios->c_cflag &= ~CBAUDEX;
+			port->tty->termios.c_cflag &= ~CBAUDEX;
 		else
 			i += 15;
 	}
@@ -1097,7 +1097,7 @@ isdn_tty_shutdown(modem_info *info)
 #endif
 	isdn_unlock_drivers();
 	info->msr &= ~UART_MSR_RI;
-	if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
+	if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) {
 		info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
 		if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
 			isdn_tty_modem_reset_regs(info, 0);
@@ -1469,13 +1469,13 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	if (!old_termios)
 		isdn_tty_change_speed(info);
 	else {
-		if (tty->termios->c_cflag == old_termios->c_cflag &&
-		    tty->termios->c_ispeed == old_termios->c_ispeed &&
-		    tty->termios->c_ospeed == old_termios->c_ospeed)
+		if (tty->termios.c_cflag == old_termios->c_cflag &&
+		    tty->termios.c_ispeed == old_termios->c_ispeed &&
+		    tty->termios.c_ospeed == old_termios->c_ospeed)
 			return;
 		isdn_tty_change_speed(info);
 		if ((old_termios->c_cflag & CRTSCTS) &&
-		    !(tty->termios->c_cflag & CRTSCTS))
+		    !(tty->termios.c_cflag & CRTSCTS))
 			tty->hw_stopped = 0;
 	}
 }
@@ -1486,6 +1486,18 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
  * ------------------------------------------------------------
  */
 
+static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	modem_info *info = &dev->mdm.info[tty->index];
+
+	if (isdn_tty_paranoia_check(info, tty->name, __func__))
+		return -ENODEV;
+
+	tty->driver_data = info;
+
+	return tty_port_install(&info->port, driver, tty);
+}
+
 /*
  * This routine is called whenever a serial port is opened.  It
  * enables interrupts for a serial port, linking in its async structure into
@@ -1495,22 +1507,16 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 static int
 isdn_tty_open(struct tty_struct *tty, struct file *filp)
 {
-	struct tty_port *port;
-	modem_info *info;
+	modem_info *info = tty->driver_data;
+	struct tty_port *port = &info->port;
 	int retval;
 
-	info = &dev->mdm.info[tty->index];
-	if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
-		return -ENODEV;
-	port = &info->port;
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
 	       port->count);
 #endif
 	port->count++;
-	tty->driver_data = info;
 	port->tty = tty;
-	tty->port = port;
 	/*
 	 * Start up serial port
 	 */
@@ -1738,6 +1744,7 @@ modem_write_profile(atemu *m)
 }
 
 static const struct tty_operations modem_ops = {
+	.install = isdn_tty_install,
 	.open = isdn_tty_open,
 	.close = isdn_tty_close,
 	.write = isdn_tty_write,
@@ -1782,7 +1789,7 @@ isdn_tty_modem_init(void)
 	m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
 	m->tty_modem->init_termios = tty_std_termios;
 	m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	m->tty_modem->flags = TTY_DRIVER_REAL_RAW;
 	m->tty_modem->driver_name = "isdn_tty";
 	tty_set_operations(m->tty_modem, &modem_ops);
 	retval = tty_register_driver(m->tty_modem);

+ 8 - 8
drivers/misc/ibmasm/uart.c

@@ -33,7 +33,7 @@
 
 void ibmasm_register_uart(struct service_processor *sp)
 {
-	struct uart_port uport;
+	struct uart_8250_port uart;
 	void __iomem *iomem_base;
 
 	iomem_base = sp->base_address + SCOUT_COM_B_BASE;
@@ -47,14 +47,14 @@ void ibmasm_register_uart(struct service_processor *sp)
 		return;
 	}
 
-	memset(&uport, 0, sizeof(struct uart_port));
-	uport.irq	= sp->irq;
-	uport.uartclk	= 3686400;
-	uport.flags	= UPF_SHARE_IRQ;
-	uport.iotype	= UPIO_MEM;
-	uport.membase	= iomem_base;
+	memset(&uart, 0, sizeof(uart));
+	uart.port.irq		= sp->irq;
+	uart.port.uartclk	= 3686400;
+	uart.port.flags		= UPF_SHARE_IRQ;
+	uart.port.iotype	= UPIO_MEM;
+	uart.port.membase	= iomem_base;
 
-	sp->serial_line = serial8250_register_port(&uport);
+	sp->serial_line = serial8250_register_8250_port(&uart);
 	if (sp->serial_line < 0) {
 		dev_err(sp->dev, "Failed to register serial port\n");
 		return;

+ 59 - 69
drivers/misc/pti.c

@@ -60,7 +60,7 @@ struct pti_tty {
 };
 
 struct pti_dev {
-	struct tty_port port;
+	struct tty_port port[PTITTY_MINOR_NUM];
 	unsigned long pti_addr;
 	unsigned long aperture_base;
 	void __iomem *pti_ioaddr;
@@ -76,7 +76,7 @@ struct pti_dev {
  */
 static DEFINE_MUTEX(alloclock);
 
-static struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] __devinitconst = {
 		{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
 		{0}
 };
@@ -393,25 +393,6 @@ void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count)
 }
 EXPORT_SYMBOL_GPL(pti_writedata);
 
-/**
- * pti_pci_remove()- Driver exit method to remove PTI from
- *		   PCI bus.
- * @pdev: variable containing pci info of PTI.
- */
-static void __devexit pti_pci_remove(struct pci_dev *pdev)
-{
-	struct pti_dev *drv_data;
-
-	drv_data = pci_get_drvdata(pdev);
-	if (drv_data != NULL) {
-		pci_iounmap(pdev, drv_data->pti_ioaddr);
-		pci_set_drvdata(pdev, NULL);
-		kfree(drv_data);
-		pci_release_region(pdev, 1);
-		pci_disable_device(pdev);
-	}
-}
-
 /*
  * for the tty_driver_*() basic function descriptions, see tty_driver.h.
  * Specific header comments made for PTI-related specifics.
@@ -446,7 +427,7 @@ static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp)
 	 * also removes a locking requirement for the actual write
 	 * procedure.
 	 */
-	return tty_port_open(&drv_data->port, tty, filp);
+	return tty_port_open(tty->port, tty, filp);
 }
 
 /**
@@ -462,7 +443,7 @@ static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp)
  */
 static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp)
 {
-	tty_port_close(&drv_data->port, tty, filp);
+	tty_port_close(tty->port, tty, filp);
 }
 
 /**
@@ -818,6 +799,7 @@ static const struct tty_port_operations tty_port_ops = {
 static int __devinit pti_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
+	unsigned int a;
 	int retval = -EINVAL;
 	int pci_bar = 1;
 
@@ -830,7 +812,7 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev,
 			__func__, __LINE__);
 		pr_err("%s(%d): Error value returned: %d\n",
 			__func__, __LINE__, retval);
-		return retval;
+		goto err;
 	}
 
 	retval = pci_enable_device(pdev);
@@ -838,17 +820,16 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev,
 		dev_err(&pdev->dev,
 			"%s: pci_enable_device() returned error %d\n",
 			__func__, retval);
-		return retval;
+		goto err_unreg_misc;
 	}
 
 	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
-
 	if (drv_data == NULL) {
 		retval = -ENOMEM;
 		dev_err(&pdev->dev,
 			"%s(%d): kmalloc() returned NULL memory.\n",
 			__func__, __LINE__);
-		return retval;
+		goto err_disable_pci;
 	}
 	drv_data->pti_addr = pci_resource_start(pdev, pci_bar);
 
@@ -857,33 +838,65 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev,
 		dev_err(&pdev->dev,
 			"%s(%d): pci_request_region() returned error %d\n",
 			__func__, __LINE__, retval);
-		kfree(drv_data);
-		return retval;
+		goto err_free_dd;
 	}
 	drv_data->aperture_base = drv_data->pti_addr+APERTURE_14;
 	drv_data->pti_ioaddr =
 		ioremap_nocache((u32)drv_data->aperture_base,
 		APERTURE_LEN);
 	if (!drv_data->pti_ioaddr) {
-		pci_release_region(pdev, pci_bar);
 		retval = -ENOMEM;
-		kfree(drv_data);
-		return retval;
+		goto err_rel_reg;
 	}
 
 	pci_set_drvdata(pdev, drv_data);
 
-	tty_port_init(&drv_data->port);
-	drv_data->port.ops = &tty_port_ops;
+	for (a = 0; a < PTITTY_MINOR_NUM; a++) {
+		struct tty_port *port = &drv_data->port[a];
+		tty_port_init(port);
+		port->ops = &tty_port_ops;
 
-	tty_register_device(pti_tty_driver, 0, &pdev->dev);
-	tty_register_device(pti_tty_driver, 1, &pdev->dev);
+		tty_port_register_device(port, pti_tty_driver, a, &pdev->dev);
+	}
 
 	register_console(&pti_console);
 
+	return 0;
+err_rel_reg:
+	pci_release_region(pdev, pci_bar);
+err_free_dd:
+	kfree(drv_data);
+err_disable_pci:
+	pci_disable_device(pdev);
+err_unreg_misc:
+	misc_deregister(&pti_char_driver);
+err:
 	return retval;
 }
 
+/**
+ * pti_pci_remove()- Driver exit method to remove PTI from
+ *		   PCI bus.
+ * @pdev: variable containing pci info of PTI.
+ */
+static void __devexit pti_pci_remove(struct pci_dev *pdev)
+{
+	struct pti_dev *drv_data = pci_get_drvdata(pdev);
+
+	unregister_console(&pti_console);
+
+	tty_unregister_device(pti_tty_driver, 0);
+	tty_unregister_device(pti_tty_driver, 1);
+
+	iounmap(drv_data->pti_ioaddr);
+	pci_set_drvdata(pdev, NULL);
+	kfree(drv_data);
+	pci_release_region(pdev, 1);
+	pci_disable_device(pdev);
+
+	misc_deregister(&pti_char_driver);
+}
+
 static struct pci_driver pti_pci_driver = {
 	.name		= PCINAME,
 	.id_table	= pci_ids,
@@ -933,25 +946,24 @@ static int __init pti_init(void)
 		pr_err("%s(%d): Error value returned: %d\n",
 			__func__, __LINE__, retval);
 
-		pti_tty_driver = NULL;
-		return retval;
+		goto put_tty;
 	}
 
 	retval = pci_register_driver(&pti_pci_driver);
-
 	if (retval) {
 		pr_err("%s(%d): PCI registration failed of pti driver\n",
 			__func__, __LINE__);
 		pr_err("%s(%d): Error value returned: %d\n",
 			__func__, __LINE__, retval);
-
-		tty_unregister_driver(pti_tty_driver);
-		pr_err("%s(%d): Unregistering TTY part of pti driver\n",
-			__func__, __LINE__);
-		pti_tty_driver = NULL;
-		return retval;
+		goto unreg_tty;
 	}
 
+	return 0;
+unreg_tty:
+	tty_unregister_driver(pti_tty_driver);
+put_tty:
+	put_tty_driver(pti_tty_driver);
+	pti_tty_driver = NULL;
 	return retval;
 }
 
@@ -960,31 +972,9 @@ static int __init pti_init(void)
  */
 static void __exit pti_exit(void)
 {
-	int retval;
-
-	tty_unregister_device(pti_tty_driver, 0);
-	tty_unregister_device(pti_tty_driver, 1);
-
-	retval = tty_unregister_driver(pti_tty_driver);
-	if (retval) {
-		pr_err("%s(%d): TTY unregistration failed of pti driver\n",
-			__func__, __LINE__);
-		pr_err("%s(%d): Error value returned: %d\n",
-			__func__, __LINE__, retval);
-	}
-
+	tty_unregister_driver(pti_tty_driver);
 	pci_unregister_driver(&pti_pci_driver);
-
-	retval = misc_deregister(&pti_char_driver);
-	if (retval) {
-		pr_err("%s(%d): CHAR unregistration failed of pti driver\n",
-			__func__, __LINE__);
-		pr_err("%s(%d): Error value returned: %d\n",
-			__func__, __LINE__, retval);
-	}
-
-	unregister_console(&pti_console);
-	return;
+	put_tty_driver(pti_tty_driver);
 }
 
 module_init(pti_init);

+ 12 - 12
drivers/mmc/card/sdio_uart.c

@@ -518,7 +518,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
 	if (status & UART_MSR_DCTS) {
 		port->icount.cts++;
 		tty = tty_port_tty_get(&port->port);
-		if (tty && (tty->termios->c_cflag & CRTSCTS)) {
+		if (tty && (tty->termios.c_cflag & CRTSCTS)) {
 			int cts = (status & UART_MSR_CTS);
 			if (tty->hw_stopped) {
 				if (cts) {
@@ -671,12 +671,12 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
 	port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;
 	port->mctrl = TIOCM_OUT2;
 
-	sdio_uart_change_speed(port, tty->termios, NULL);
+	sdio_uart_change_speed(port, &tty->termios, NULL);
 
-	if (tty->termios->c_cflag & CBAUD)
+	if (tty->termios.c_cflag & CBAUD)
 		sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
 
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
 			tty->hw_stopped = 1;
 
@@ -850,7 +850,7 @@ static void sdio_uart_throttle(struct tty_struct *tty)
 {
 	struct sdio_uart_port *port = tty->driver_data;
 
-	if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
+	if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS))
 		return;
 
 	if (sdio_uart_claim_func(port) != 0)
@@ -861,7 +861,7 @@ static void sdio_uart_throttle(struct tty_struct *tty)
 		sdio_uart_start_tx(port);
 	}
 
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		sdio_uart_clear_mctrl(port, TIOCM_RTS);
 
 	sdio_uart_irq(port->func);
@@ -872,7 +872,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty)
 {
 	struct sdio_uart_port *port = tty->driver_data;
 
-	if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
+	if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS))
 		return;
 
 	if (sdio_uart_claim_func(port) != 0)
@@ -887,7 +887,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty)
 		}
 	}
 
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		sdio_uart_set_mctrl(port, TIOCM_RTS);
 
 	sdio_uart_irq(port->func);
@@ -898,12 +898,12 @@ static void sdio_uart_set_termios(struct tty_struct *tty,
 						struct ktermios *old_termios)
 {
 	struct sdio_uart_port *port = tty->driver_data;
-	unsigned int cflag = tty->termios->c_cflag;
+	unsigned int cflag = tty->termios.c_cflag;
 
 	if (sdio_uart_claim_func(port) != 0)
 		return;
 
-	sdio_uart_change_speed(port, tty->termios, old_termios);
+	sdio_uart_change_speed(port, &tty->termios, old_termios);
 
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
@@ -1132,8 +1132,8 @@ static int sdio_uart_probe(struct sdio_func *func,
 		kfree(port);
 	} else {
 		struct device *dev;
-		dev = tty_register_device(sdio_uart_tty_driver,
-						port->index, &func->dev);
+		dev = tty_port_register_device(&port->port,
+				sdio_uart_tty_driver, port->index, &func->dev);
 		if (IS_ERR(dev)) {
 			sdio_uart_port_remove(port);
 			ret = PTR_ERR(dev);

+ 12 - 10
drivers/net/ethernet/sgi/ioc3-eth.c

@@ -1147,15 +1147,17 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
 {
 #define COSMISC_CONSTANT 6
 
-	struct uart_port port = {
-		.irq		= 0,
-		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
-		.iotype		= UPIO_MEM,
-		.regshift	= 0,
-		.uartclk	= (22000000 << 1) / COSMISC_CONSTANT,
-
-		.membase	= (unsigned char __iomem *) uart,
-		.mapbase	= (unsigned long) uart,
+	struct uart_8250_port port = {
+	        .port = {
+			.irq		= 0,
+			.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+			.iotype		= UPIO_MEM,
+			.regshift	= 0,
+			.uartclk	= (22000000 << 1) / COSMISC_CONSTANT,
+
+			.membase	= (unsigned char __iomem *) uart,
+			.mapbase	= (unsigned long) uart,
+                }
 	};
 	unsigned char lcr;
 
@@ -1164,7 +1166,7 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
 	uart->iu_scr = COSMISC_CONSTANT,
 	uart->iu_lcr = lcr;
 	uart->iu_lcr;
-	serial8250_register_port(&port);
+	serial8250_register_8250_port(&port);
 }
 
 static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)

+ 5 - 5
drivers/net/irda/irtty-sir.c

@@ -124,8 +124,8 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
 	tty = priv->tty;
 
 	mutex_lock(&tty->termios_mutex);
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
+	old_termios = tty->termios;
+	cflag = tty->termios.c_cflag;
 	tty_encode_baud_rate(tty, speed, speed);
 	if (tty->ops->set_termios)
 		tty->ops->set_termios(tty, &old_termios);
@@ -281,15 +281,15 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
 	int cflag;
 
 	mutex_lock(&tty->termios_mutex);
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
+	old_termios = tty->termios;
+	cflag = tty->termios.c_cflag;
 	
 	if (stop)
 		cflag &= ~CREAD;
 	else
 		cflag |= CREAD;
 
-	tty->termios->c_cflag = cflag;
+	tty->termios.c_cflag = cflag;
 	if (tty->ops->set_termios)
 		tty->ops->set_termios(tty, &old_termios);
 	mutex_unlock(&tty->termios_mutex);

+ 9 - 10
drivers/net/usb/hso.c

@@ -1107,7 +1107,6 @@ static void _hso_serial_set_termios(struct tty_struct *tty,
 				    struct ktermios *old)
 {
 	struct hso_serial *serial = tty->driver_data;
-	struct ktermios *termios;
 
 	if (!serial) {
 		printk(KERN_ERR "%s: no tty structures", __func__);
@@ -1119,16 +1118,15 @@ static void _hso_serial_set_termios(struct tty_struct *tty,
 	/*
 	 *	Fix up unsupported bits
 	 */
-	termios = tty->termios;
-	termios->c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
+	tty->termios.c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
 
-	termios->c_cflag &=
+	tty->termios.c_cflag &=
 		~(CSIZE		/* no size */
 		| PARENB	/* disable parity bit */
 		| CBAUD		/* clear current baud rate */
 		| CBAUDEX);	/* clear current buad rate */
 
-	termios->c_cflag |= CS8;	/* character size 8 bits */
+	tty->termios.c_cflag |= CS8;	/* character size 8 bits */
 
 	/* baud rate 115200 */
 	tty_encode_baud_rate(tty, 115200, 115200);
@@ -1425,14 +1423,14 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)
 
 	if (old)
 		D5("Termios called with: cflags new[%d] - old[%d]",
-		   tty->termios->c_cflag, old->c_cflag);
+		   tty->termios.c_cflag, old->c_cflag);
 
 	/* the actual setup */
 	spin_lock_irqsave(&serial->serial_lock, flags);
 	if (serial->port.count)
 		_hso_serial_set_termios(tty, old);
 	else
-		tty->termios = old;
+		tty->termios = *old;
 	spin_unlock_irqrestore(&serial->serial_lock, flags);
 
 	/* done */
@@ -2289,9 +2287,11 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
 	if (minor < 0)
 		goto exit;
 
+	tty_port_init(&serial->port);
+
 	/* register our minor number */
-	serial->parent->dev = tty_register_device(tty_drv, minor,
-					&serial->parent->interface->dev);
+	serial->parent->dev = tty_port_register_device(&serial->port, tty_drv,
+			minor, &serial->parent->interface->dev);
 	dev = serial->parent->dev;
 	dev_set_drvdata(dev, serial->parent);
 	i = device_create_file(dev, &dev_attr_hsotype);
@@ -2300,7 +2300,6 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
 	serial->minor = minor;
 	serial->magic = HSO_SERIAL_MAGIC;
 	spin_lock_init(&serial->serial_lock);
-	tty_port_init(&serial->port);
 	serial->num_rx_urbs = num_urbs;
 
 	/* RX, allocate urb and initialize */

+ 1 - 0
drivers/parport/parport_gsc.c

@@ -271,6 +271,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
 	if (!parport_SPP_supported (p)) {
 		/* No port. */
 		kfree (priv);
+		kfree(ops);
 		return NULL;
 	}
 	parport_PS2_supported (p);

+ 10 - 1
drivers/parport/parport_serial.c

@@ -62,6 +62,7 @@ enum parport_pc_pci_cards {
 	timedia_9079a,
 	timedia_9079b,
 	timedia_9079c,
+	wch_ch353_2s1p,
 };
 
 /* each element directly indexed from enum list, above */
@@ -145,6 +146,7 @@ static struct parport_pc_pci cards[] __devinitdata = {
 	/* timedia_9079a */             { 1, { { 2, 3 }, } },
 	/* timedia_9079b */             { 1, { { 2, 3 }, } },
 	/* timedia_9079c */             { 1, { { 2, 3 }, } },
+	/* wch_ch353_2s1p*/             { 1, { { 2, -1}, } },
 };
 
 static struct pci_device_id parport_serial_pci_tbl[] = {
@@ -243,7 +245,8 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
 	{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
 	{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
 	{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
-
+	/* WCH CARDS */
+	{ 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p},
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
@@ -460,6 +463,12 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
 		.base_baud	= 921600,
 		.uart_offset	= 8,
 	},
+	[wch_ch353_2s1p] = {
+		.flags          = FL_BASE0|FL_BASE_BARS,
+		.num_ports      = 2,
+		.base_baud      = 115200,
+		.uart_offset    = 8,
+	},
 };
 
 struct parport_serial_private {

+ 22 - 6
drivers/s390/char/con3215.c

@@ -716,10 +716,17 @@ static int raw3215_probe (struct ccw_device *cdev)
 static void raw3215_remove (struct ccw_device *cdev)
 {
 	struct raw3215_info *raw;
+	unsigned int line;
 
 	ccw_device_set_offline(cdev);
 	raw = dev_get_drvdata(&cdev->dev);
 	if (raw) {
+		spin_lock(&raw3215_device_lock);
+		for (line = 0; line < NR_3215; line++)
+			if (raw3215[line] == raw)
+				break;
+		raw3215[line] = NULL;
+		spin_unlock(&raw3215_device_lock);
 		dev_set_drvdata(&cdev->dev, NULL);
 		raw3215_free_info(raw);
 	}
@@ -935,6 +942,19 @@ static int __init con3215_init(void)
 console_initcall(con3215_init);
 #endif
 
+static int tty3215_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	struct raw3215_info *raw;
+
+	raw = raw3215[tty->index];
+	if (raw == NULL)
+		return -ENODEV;
+
+	tty->driver_data = raw;
+
+	return tty_port_install(&raw->port, driver, tty);
+}
+
 /*
  * tty3215_open
  *
@@ -942,14 +962,9 @@ console_initcall(con3215_init);
  */
 static int tty3215_open(struct tty_struct *tty, struct file * filp)
 {
-	struct raw3215_info *raw;
+	struct raw3215_info *raw = tty->driver_data;
 	int retval;
 
-	raw = raw3215[tty->index];
-	if (raw == NULL)
-		return -ENODEV;
-
-	tty->driver_data = raw;
 	tty_port_tty_set(&raw->port, tty);
 
 	tty->low_latency = 0;  /* don't use bottom half for pushing chars */
@@ -1110,6 +1125,7 @@ static void tty3215_start(struct tty_struct *tty)
 }
 
 static const struct tty_operations tty3215_ops = {
+	.install = tty3215_install,
 	.open = tty3215_open,
 	.close = tty3215_close,
 	.write = tty3215_write,

+ 1 - 0
drivers/s390/char/sclp_tty.c

@@ -567,6 +567,7 @@ sclp_tty_init(void)
 	driver->init_termios.c_lflag = ISIG | ECHO;
 	driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(driver, &sclp_ops);
+	tty_port_link_device(&sclp_port, driver, 0);
 	rc = tty_register_driver(driver);
 	if (rc) {
 		put_tty_driver(driver);

+ 1 - 0
drivers/s390/char/sclp_vt220.c

@@ -691,6 +691,7 @@ static int __init sclp_vt220_tty_init(void)
 	driver->init_termios = tty_std_termios;
 	driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(driver, &sclp_vt220_ops);
+	tty_port_link_device(&sclp_vt220_port, driver, 0);
 
 	rc = tty_register_driver(driver);
 	if (rc)

+ 24 - 10
drivers/s390/char/tty3270.c

@@ -842,17 +842,14 @@ static struct raw3270_fn tty3270_fn = {
 };
 
 /*
- * This routine is called whenever a 3270 tty is opened.
+ * This routine is called whenever a 3270 tty is opened first time.
  */
-static int
-tty3270_open(struct tty_struct *tty, struct file * filp)
+static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
 {
 	struct raw3270_view *view;
 	struct tty3270 *tp;
 	int i, rc;
 
-	if (tty->count > 1)
-		return 0;
 	/* Check if the tty3270 is already there. */
 	view = raw3270_find_view(&tty3270_fn,
 				  tty->index + RAW3270_FIRSTMINOR);
@@ -865,7 +862,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
 		/* why to reassign? */
 		tty_port_tty_set(&tp->port, tty);
 		tp->inattr = TF_INPUT;
-		return 0;
+		return tty_port_install(&tp->port, driver, tty);
 	}
 	if (tty3270_max_index < tty->index + 1)
 		tty3270_max_index = tty->index + 1;
@@ -895,7 +892,6 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
 
 	tty_port_tty_set(&tp->port, tty);
 	tty->low_latency = 0;
-	tty->driver_data = tp;
 	tty->winsize.ws_row = tp->view.rows - 2;
 	tty->winsize.ws_col = tp->view.cols;
 
@@ -915,6 +911,15 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
 	kbd_ascebc(tp->kbd, tp->view.ascebc);
 
 	raw3270_activate_view(&tp->view);
+
+	rc = tty_port_install(&tp->port, driver, tty);
+	if (rc) {
+		raw3270_put_view(&tp->view);
+		return rc;
+	}
+
+	tty->driver_data = tp;
+
 	return 0;
 }
 
@@ -932,10 +937,17 @@ tty3270_close(struct tty_struct *tty, struct file * filp)
 	if (tp) {
 		tty->driver_data = NULL;
 		tty_port_tty_set(&tp->port, NULL);
-		raw3270_put_view(&tp->view);
 	}
 }
 
+static void tty3270_cleanup(struct tty_struct *tty)
+{
+	struct tty3270 *tp = tty->driver_data;
+
+	if (tp)
+		raw3270_put_view(&tp->view);
+}
+
 /*
  * We always have room.
  */
@@ -1737,7 +1749,8 @@ static long tty3270_compat_ioctl(struct tty_struct *tty,
 #endif
 
 static const struct tty_operations tty3270_ops = {
-	.open = tty3270_open,
+	.install = tty3270_install,
+	.cleanup = tty3270_cleanup,
 	.close = tty3270_close,
 	.write = tty3270_write,
 	.put_char = tty3270_put_char,
@@ -1781,7 +1794,7 @@ static int __init tty3270_init(void)
 	driver->type = TTY_DRIVER_TYPE_SYSTEM;
 	driver->subtype = SYSTEM_TYPE_TTY;
 	driver->init_termios = tty_std_termios;
-	driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV;
+	driver->flags = TTY_DRIVER_RESET_TERMIOS;
 	tty_set_operations(driver, &tty3270_ops);
 	ret = tty_register_driver(driver);
 	if (ret) {
@@ -1800,6 +1813,7 @@ tty3270_exit(void)
 	driver = tty3270_driver;
 	tty3270_driver = NULL;
 	tty_unregister_driver(driver);
+	put_tty_driver(driver);
 	tty3270_del_views();
 }
 

+ 7 - 7
drivers/staging/ipack/devices/ipoctal.c

@@ -502,7 +502,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
 		ipoctal->pointer_read[i] = 0;
 		ipoctal->pointer_write[i] = 0;
 		ipoctal->nb_bytes[i] = 0;
-		tty_register_device(tty, i, NULL);
+		tty_port_register_device(&ipoctal->tty_port[i], tty, i, NULL);
 
 		/*
 		 * Enable again the RX. TX will be enabled when
@@ -617,7 +617,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
 	struct ipoctal *ipoctal = tty->driver_data;
 	speed_t baud;
 
-	cflag = tty->termios->c_cflag;
+	cflag = tty->termios.c_cflag;
 
 	/* Disable and reset everything before change the setup */
 	ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
@@ -643,7 +643,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
 	default:
 		mr1 |= MR1_CHRL_8_BITS;
 		/* By default, select CS8 */
-		tty->termios->c_cflag = (cflag & ~CSIZE) | CS8;
+		tty->termios.c_cflag = (cflag & ~CSIZE) | CS8;
 		break;
 	}
 
@@ -657,7 +657,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
 		mr1 |= MR1_PARITY_OFF;
 
 	/* Mark or space parity is not supported */
-	tty->termios->c_cflag &= ~CMSPAR;
+	tty->termios.c_cflag &= ~CMSPAR;
 
 	/* Set stop bits */
 	if (cflag & CSTOPB)
@@ -690,10 +690,10 @@ static void ipoctal_set_termios(struct tty_struct *tty,
 	}
 
 	baud = tty_get_baud_rate(tty);
-	tty_termios_encode_baud_rate(tty->termios, baud, baud);
+	tty_termios_encode_baud_rate(&tty->termios, baud, baud);
 
 	/* Set baud rate */
-	switch (tty->termios->c_ospeed) {
+	switch (baud) {
 	case 75:
 		csr |= TX_CLK_75 | RX_CLK_75;
 		break;
@@ -734,7 +734,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
 	default:
 		csr |= TX_CLK_38400 | RX_CLK_38400;
 		/* In case of default, we establish 38400 bps */
-		tty_termios_encode_baud_rate(tty->termios, 38400, 38400);
+		tty_termios_encode_baud_rate(&tty->termios, 38400, 38400);
 		break;
 	}
 

+ 8 - 10
drivers/staging/serqt_usb2/serqt_usb2.c

@@ -315,10 +315,8 @@ static void qt_read_bulk_callback(struct urb *urb)
 	}
 
 	tty = tty_port_tty_get(&port->port);
-	if (!tty) {
-		dbg("%s - bad tty pointer - exiting", __func__);
+	if (!tty)
 		return;
-	}
 
 	data = urb->transfer_buffer;
 
@@ -364,7 +362,7 @@ static void qt_read_bulk_callback(struct urb *urb)
 		goto exit;
 	}
 
-	if (tty && RxCount) {
+	if (RxCount) {
 		flag_data = 0;
 		for (i = 0; i < RxCount; ++i) {
 			/* Look ahead code here */
@@ -428,7 +426,7 @@ static void qt_read_bulk_callback(struct urb *urb)
 		dbg("%s - failed resubmitting read urb, error %d",
 		    __func__, result);
 	else {
-		if (tty && RxCount) {
+		if (RxCount) {
 			tty_flip_buffer_push(tty);
 			tty_schedule_flip(tty);
 		}
@@ -897,8 +895,6 @@ static int qt_open(struct tty_struct *tty,
 	 * Put this here to make it responsive to stty and defaults set by
 	 * the tty layer
 	 */
-	/* FIXME: is this needed? */
-	/* qt_set_termios(tty, port, NULL); */
 
 	/*  Check to see if we've set up our endpoint info yet */
 	if (port0->open_ports == 1) {
@@ -1195,7 +1191,7 @@ static void qt_set_termios(struct tty_struct *tty,
 			   struct usb_serial_port *port,
 			   struct ktermios *old_termios)
 {
-	struct ktermios *termios = tty->termios;
+	struct ktermios *termios = &tty->termios;
 	unsigned char new_LCR = 0;
 	unsigned int cflag = termios->c_cflag;
 	unsigned int index;
@@ -1204,7 +1200,7 @@ static void qt_set_termios(struct tty_struct *tty,
 
 	index = tty->index - port->serial->minor;
 
-	switch (cflag) {
+	switch (cflag & CSIZE) {
 	case CS5:
 		new_LCR |= SERIAL_5_DATA;
 		break;
@@ -1215,6 +1211,8 @@ static void qt_set_termios(struct tty_struct *tty,
 		new_LCR |= SERIAL_7_DATA;
 		break;
 	default:
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= CS8;
 	case CS8:
 		new_LCR |= SERIAL_8_DATA;
 		break;
@@ -1301,7 +1299,7 @@ static void qt_set_termios(struct tty_struct *tty,
 			dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n");
 
 	}
-	tty->termios->c_cflag &= ~CMSPAR;
+	termios->c_cflag &= ~CMSPAR;
 	/* FIXME: Error cases should be returning the actual bits changed only */
 }
 

+ 1 - 2
drivers/staging/speakup/serialio.h

@@ -1,8 +1,7 @@
 #ifndef _SPEAKUP_SERIAL_H
 #define _SPEAKUP_SERIAL_H
 
-#include <linux/serial.h>	/* for rs_table, serial constants &
-				   serial_uart_config */
+#include <linux/serial.h>	/* for rs_table, serial constants */
 #include <linux/serial_reg.h>	/* for more serial constants */
 #ifndef __sparc__
 #include <asm/serial.h>

+ 23 - 22
drivers/tty/amiserial.c

@@ -420,7 +420,7 @@ static void check_modem_status(struct serial_state *info)
 				tty_hangup(port->tty);
 		}
 	}
-	if (port->flags & ASYNC_CTS_FLOW) {
+	if (tty_port_cts_enabled(port)) {
 		if (port->tty->hw_stopped) {
 			if (!(status & SER_CTS)) {
 #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
@@ -646,7 +646,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info)
 	custom.adkcon = AC_UARTBRK;
 	mb();
 
-	if (tty->termios->c_cflag & HUPCL)
+	if (tty->termios.c_cflag & HUPCL)
 		info->MCR &= ~(SER_DTR|SER_RTS);
 	rtsdtr_ctrl(info->MCR);
 
@@ -670,7 +670,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
 	int	bits;
 	unsigned long	flags;
 
-	cflag = tty->termios->c_cflag;
+	cflag = tty->termios.c_cflag;
 
 	/* Byte size is always 8 bits plus parity bit if requested */
 
@@ -707,8 +707,8 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
 	/* If the quotient is zero refuse the change */
 	if (!quot && old_termios) {
 		/* FIXME: Will need updating for new tty in the end */
-		tty->termios->c_cflag &= ~CBAUD;
-		tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+		tty->termios.c_cflag &= ~CBAUD;
+		tty->termios.c_cflag |= (old_termios->c_cflag & CBAUD);
 		baud = tty_get_baud_rate(tty);
 		if (!baud)
 			baud = 9600;
@@ -984,7 +984,7 @@ static void rs_throttle(struct tty_struct * tty)
 	if (I_IXOFF(tty))
 		rs_send_xchar(tty, STOP_CHAR(tty));
 
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		info->MCR &= ~SER_RTS;
 
 	local_irq_save(flags);
@@ -1012,7 +1012,7 @@ static void rs_unthrottle(struct tty_struct * tty)
 		else
 			rs_send_xchar(tty, START_CHAR(tty));
 	}
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		info->MCR |= SER_RTS;
 	local_irq_save(flags);
 	rtsdtr_ctrl(info->MCR);
@@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
 	if (!retinfo)
 		return -EFAULT;
 	memset(&tmp, 0, sizeof(tmp));
-	tty_lock();
+	tty_lock(tty);
 	tmp.line = tty->index;
 	tmp.port = state->port;
 	tmp.flags = state->tport.flags;
@@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
 	tmp.close_delay = state->tport.close_delay;
 	tmp.closing_wait = state->tport.closing_wait;
 	tmp.custom_divisor = state->custom_divisor;
-	tty_unlock();
+	tty_unlock(tty);
 	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
 		return -EFAULT;
 	return 0;
@@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
 	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
 		return -EFAULT;
 
-	tty_lock();
+	tty_lock(tty);
 	change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
 		new_serial.custom_divisor != state->custom_divisor;
 	if (new_serial.irq || new_serial.port != state->port ||
 			new_serial.xmit_fifo_size != state->xmit_fifo_size) {
-		tty_unlock();
+		tty_unlock(tty);
 		return -EINVAL;
 	}
   
@@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
 		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
 		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
 		     (port->flags & ~ASYNC_USR_MASK))) {
-			tty_unlock();
+			tty_unlock(tty);
 			return -EPERM;
 		}
 		port->flags = ((port->flags & ~ASYNC_USR_MASK) |
@@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
 	}
 
 	if (new_serial.baud_base < 9600) {
-		tty_unlock();
+		tty_unlock(tty);
 		return -EINVAL;
 	}
 
@@ -1116,7 +1116,7 @@ check_and_exit:
 		}
 	} else
 		retval = startup(tty, state);
-	tty_unlock();
+	tty_unlock(tty);
 	return retval;
 }
 
@@ -1330,7 +1330,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
 	struct serial_state *info = tty->driver_data;
 	unsigned long flags;
-	unsigned int cflag = tty->termios->c_cflag;
+	unsigned int cflag = tty->termios.c_cflag;
 
 	change_speed(tty, info, old_termios);
 
@@ -1347,7 +1347,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	if (!(old_termios->c_cflag & CBAUD) &&
 	    (cflag & CBAUD)) {
 		info->MCR |= SER_DTR;
-		if (!(tty->termios->c_cflag & CRTSCTS) || 
+		if (!(tty->termios.c_cflag & CRTSCTS) || 
 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
 			info->MCR |= SER_RTS;
 		}
@@ -1358,7 +1358,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		rs_start(tty);
 	}
@@ -1371,7 +1371,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	 * or not.  Hence, this may change.....
 	 */
 	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
+	    (tty->termios.c_cflag & CLOCAL))
 		wake_up_interruptible(&info->open_wait);
 #endif
 }
@@ -1710,10 +1710,6 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
 	serial_driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(serial_driver, &serial_ops);
 
-	error = tty_register_driver(serial_driver);
-	if (error)
-		goto fail_put_tty_driver;
-
 	state = rs_table;
 	state->port = (int)&custom.serdatr; /* Just to give it a value */
 	state->custom_divisor = 0;
@@ -1724,6 +1720,11 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
 	state->icount.overrun = state->icount.brk = 0;
 	tty_port_init(&state->tport);
 	state->tport.ops = &amiga_port_ops;
+	tty_port_link_device(&state->tport, serial_driver, 0);
+
+	error = tty_register_driver(serial_driver);
+	if (error)
+		goto fail_put_tty_driver;
 
 	printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n");
 

+ 1 - 0
drivers/tty/bfin_jtag_comm.c

@@ -263,6 +263,7 @@ static int __init bfin_jc_init(void)
 	bfin_jc_driver->subtype      = SERIAL_TYPE_NORMAL;
 	bfin_jc_driver->init_termios = tty_std_termios;
 	tty_set_operations(bfin_jc_driver, &bfin_jc_ops);
+	tty_port_link_device(&port, bfin_jc_driver, 0);
 
 	ret = tty_register_driver(bfin_jc_driver);
 	if (ret)

+ 52 - 50
drivers/tty/cyclades.c

@@ -727,7 +727,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 		else
 			tty_hangup(tty);
 	}
-	if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
+	if ((mdm_change & CyCTS) && tty_port_cts_enabled(&info->port)) {
 		if (tty->hw_stopped) {
 			if (mdm_status & CyCTS) {
 				/* cy_start isn't used
@@ -1459,7 +1459,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 			info->port.xmit_buf = NULL;
 			free_page((unsigned long)temp);
 		}
-		if (tty->termios->c_cflag & HUPCL)
+		if (tty->termios.c_cflag & HUPCL)
 			cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
 
 		cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
@@ -1488,7 +1488,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 			free_page((unsigned long)temp);
 		}
 
-		if (tty->termios->c_cflag & HUPCL)
+		if (tty->termios.c_cflag & HUPCL)
 			tty_port_lower_dtr_rts(&info->port);
 
 		set_bit(TTY_IO_ERROR, &tty->flags);
@@ -1599,7 +1599,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)) {
-		wait_event_interruptible_tty(info->port.close_wait,
+		wait_event_interruptible_tty(tty, info->port.close_wait,
 				!(info->port.flags & ASYNC_CLOSING));
 		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
 	}
@@ -1999,14 +1999,11 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 	int baud, baud_rate = 0;
 	int i;
 
-	if (!tty->termios) /* XXX can this happen at all? */
-		return;
-
 	if (info->line == -1)
 		return;
 
-	cflag = tty->termios->c_cflag;
-	iflag = tty->termios->c_iflag;
+	cflag = tty->termios.c_cflag;
+	iflag = tty->termios.c_iflag;
 
 	/*
 	 * Set up the tty->alt_speed kludge
@@ -2825,7 +2822,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	cy_set_line_char(info, tty);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
+			!(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		cy_start(tty);
 	}
@@ -2837,7 +2834,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	 * or not.  Hence, this may change.....
 	 */
 	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
+	    (tty->termios.c_cflag & CLOCAL))
 		wake_up_interruptible(&info->port.open_wait);
 #endif
 }				/* cy_set_termios */
@@ -2899,7 +2896,7 @@ static void cy_throttle(struct tty_struct *tty)
 			info->throttle = 1;
 	}
 
-	if (tty->termios->c_cflag & CRTSCTS) {
+	if (tty->termios.c_cflag & CRTSCTS) {
 		if (!cy_is_Z(card)) {
 			spin_lock_irqsave(&card->card_lock, flags);
 			cyy_change_rts_dtr(info, 0, TIOCM_RTS);
@@ -2938,7 +2935,7 @@ static void cy_unthrottle(struct tty_struct *tty)
 			cy_send_xchar(tty, START_CHAR(tty));
 	}
 
-	if (tty->termios->c_cflag & CRTSCTS) {
+	if (tty->termios.c_cflag & CRTSCTS) {
 		card = info->card;
 		if (!cy_is_Z(card)) {
 			spin_lock_irqsave(&card->card_lock, flags);
@@ -3289,9 +3286,10 @@ static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
 static int __init cy_detect_isa(void)
 {
 #ifdef CONFIG_ISA
+	struct cyclades_card *card;
 	unsigned short cy_isa_irq, nboard;
 	void __iomem *cy_isa_address;
-	unsigned short i, j, cy_isa_nchan;
+	unsigned short i, j, k, cy_isa_nchan;
 	int isparam = 0;
 
 	nboard = 0;
@@ -3349,7 +3347,8 @@ static int __init cy_detect_isa(void)
 		}
 		/* fill the next cy_card structure available */
 		for (j = 0; j < NR_CARDS; j++) {
-			if (cy_card[j].base_addr == NULL)
+			card = &cy_card[j];
+			if (card->base_addr == NULL)
 				break;
 		}
 		if (j == NR_CARDS) {	/* no more cy_cards available */
@@ -3363,7 +3362,7 @@ static int __init cy_detect_isa(void)
 
 		/* allocate IRQ */
 		if (request_irq(cy_isa_irq, cyy_interrupt,
-				0, "Cyclom-Y", &cy_card[j])) {
+				0, "Cyclom-Y", card)) {
 			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
 				"could not allocate IRQ#%d.\n",
 				(unsigned long)cy_isa_address, cy_isa_irq);
@@ -3372,16 +3371,16 @@ static int __init cy_detect_isa(void)
 		}
 
 		/* set cy_card */
-		cy_card[j].base_addr = cy_isa_address;
-		cy_card[j].ctl_addr.p9050 = NULL;
-		cy_card[j].irq = (int)cy_isa_irq;
-		cy_card[j].bus_index = 0;
-		cy_card[j].first_line = cy_next_channel;
-		cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
-		cy_card[j].nports = cy_isa_nchan;
-		if (cy_init_card(&cy_card[j])) {
-			cy_card[j].base_addr = NULL;
-			free_irq(cy_isa_irq, &cy_card[j]);
+		card->base_addr = cy_isa_address;
+		card->ctl_addr.p9050 = NULL;
+		card->irq = (int)cy_isa_irq;
+		card->bus_index = 0;
+		card->first_line = cy_next_channel;
+		card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+		card->nports = cy_isa_nchan;
+		if (cy_init_card(card)) {
+			card->base_addr = NULL;
+			free_irq(cy_isa_irq, card);
 			iounmap(cy_isa_address);
 			continue;
 		}
@@ -3393,9 +3392,10 @@ static int __init cy_detect_isa(void)
 			(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
 			cy_isa_irq, cy_isa_nchan, cy_next_channel);
 
-		for (j = cy_next_channel;
-				j < cy_next_channel + cy_isa_nchan; j++)
-			tty_register_device(cy_serial_driver, j, NULL);
+		for (k = 0, j = cy_next_channel;
+				j < cy_next_channel + cy_isa_nchan; j++, k++)
+			tty_port_register_device(&card->ports[k].port,
+					cy_serial_driver, j, NULL);
 		cy_next_channel += cy_isa_nchan;
 	}
 	return nboard;
@@ -3695,10 +3695,11 @@ err:
 static int __devinit cy_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
+	struct cyclades_card *card;
 	void __iomem *addr0 = NULL, *addr2 = NULL;
 	char *card_name = NULL;
 	u32 uninitialized_var(mailbox);
-	unsigned int device_id, nchan = 0, card_no, i;
+	unsigned int device_id, nchan = 0, card_no, i, j;
 	unsigned char plx_ver;
 	int retval, irq;
 
@@ -3829,7 +3830,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 	}
 	/* fill the next cy_card structure available */
 	for (card_no = 0; card_no < NR_CARDS; card_no++) {
-		if (cy_card[card_no].base_addr == NULL)
+		card = &cy_card[card_no];
+		if (card->base_addr == NULL)
 			break;
 	}
 	if (card_no == NR_CARDS) {	/* no more cy_cards available */
@@ -3843,27 +3845,26 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
 		/* allocate IRQ */
 		retval = request_irq(irq, cyy_interrupt,
-				IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
+				IRQF_SHARED, "Cyclom-Y", card);
 		if (retval) {
 			dev_err(&pdev->dev, "could not allocate IRQ\n");
 			goto err_unmap;
 		}
-		cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
+		card->num_chips = nchan / CyPORTS_PER_CHIP;
 	} else {
 		struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
 		struct ZFW_CTRL __iomem *zfw_ctrl;
 
 		zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
 
-		cy_card[card_no].hw_ver = mailbox;
-		cy_card[card_no].num_chips = (unsigned int)-1;
-		cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
+		card->hw_ver = mailbox;
+		card->num_chips = (unsigned int)-1;
+		card->board_ctrl = &zfw_ctrl->board_ctrl;
 #ifdef CONFIG_CYZ_INTR
 		/* allocate IRQ only if board has an IRQ */
 		if (irq != 0 && irq != 255) {
 			retval = request_irq(irq, cyz_interrupt,
-					IRQF_SHARED, "Cyclades-Z",
-					&cy_card[card_no]);
+					IRQF_SHARED, "Cyclades-Z", card);
 			if (retval) {
 				dev_err(&pdev->dev, "could not allocate IRQ\n");
 				goto err_unmap;
@@ -3873,17 +3874,17 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 	}
 
 	/* set cy_card */
-	cy_card[card_no].base_addr = addr2;
-	cy_card[card_no].ctl_addr.p9050 = addr0;
-	cy_card[card_no].irq = irq;
-	cy_card[card_no].bus_index = 1;
-	cy_card[card_no].first_line = cy_next_channel;
-	cy_card[card_no].nports = nchan;
-	retval = cy_init_card(&cy_card[card_no]);
+	card->base_addr = addr2;
+	card->ctl_addr.p9050 = addr0;
+	card->irq = irq;
+	card->bus_index = 1;
+	card->first_line = cy_next_channel;
+	card->nports = nchan;
+	retval = cy_init_card(card);
 	if (retval)
 		goto err_null;
 
-	pci_set_drvdata(pdev, &cy_card[card_no]);
+	pci_set_drvdata(pdev, card);
 
 	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
 			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
@@ -3909,14 +3910,15 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 
 	dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
 		"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
-	for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
-		tty_register_device(cy_serial_driver, i, &pdev->dev);
+	for (j = 0, i = cy_next_channel; i < cy_next_channel + nchan; i++, j++)
+		tty_port_register_device(&card->ports[j].port,
+				cy_serial_driver, i, &pdev->dev);
 	cy_next_channel += nchan;
 
 	return 0;
 err_null:
-	cy_card[card_no].base_addr = NULL;
-	free_irq(irq, &cy_card[card_no]);
+	card->base_addr = NULL;
+	free_irq(irq, card);
 err_unmap:
 	iounmap(addr0);
 	if (addr2)

+ 5 - 4
drivers/tty/ehv_bytechan.c

@@ -738,16 +738,17 @@ static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
 		goto error;
 	}
 
-	bc->dev = tty_register_device(ehv_bc_driver, i, &pdev->dev);
+	tty_port_init(&bc->port);
+	bc->port.ops = &ehv_bc_tty_port_ops;
+
+	bc->dev = tty_port_register_device(&bc->port, ehv_bc_driver, i,
+			&pdev->dev);
 	if (IS_ERR(bc->dev)) {
 		ret = PTR_ERR(bc->dev);
 		dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret);
 		goto error;
 	}
 
-	tty_port_init(&bc->port);
-	bc->port.ops = &ehv_bc_tty_port_ops;
-
 	dev_set_drvdata(&pdev->dev, bc);
 
 	dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n",

+ 25 - 6
drivers/tty/hvc/hvc_console.c

@@ -299,20 +299,33 @@ static void hvc_unthrottle(struct tty_struct *tty)
 	hvc_kick();
 }
 
+static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	struct hvc_struct *hp;
+	int rc;
+
+	/* Auto increments kref reference if found. */
+	if (!(hp = hvc_get_by_index(tty->index)))
+		return -ENODEV;
+
+	tty->driver_data = hp;
+
+	rc = tty_port_install(&hp->port, driver, tty);
+	if (rc)
+		tty_port_put(&hp->port);
+	return rc;
+}
+
 /*
  * The TTY interface won't be used until after the vio layer has exposed the vty
  * adapter to the kernel.
  */
 static int hvc_open(struct tty_struct *tty, struct file * filp)
 {
-	struct hvc_struct *hp;
+	struct hvc_struct *hp = tty->driver_data;
 	unsigned long flags;
 	int rc = 0;
 
-	/* Auto increments kref reference if found. */
-	if (!(hp = hvc_get_by_index(tty->index)))
-		return -ENODEV;
-
 	spin_lock_irqsave(&hp->port.lock, flags);
 	/* Check and then increment for fast path open. */
 	if (hp->port.count++ > 0) {
@@ -322,7 +335,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
 	} /* else count == 0 */
 	spin_unlock_irqrestore(&hp->port.lock, flags);
 
-	tty->driver_data = hp;
 	tty_port_tty_set(&hp->port, tty);
 
 	if (hp->ops->notifier_add)
@@ -389,6 +401,11 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 				hp->vtermno, hp->port.count);
 		spin_unlock_irqrestore(&hp->port.lock, flags);
 	}
+}
+
+static void hvc_cleanup(struct tty_struct *tty)
+{
+	struct hvc_struct *hp = tty->driver_data;
 
 	tty_port_put(&hp->port);
 }
@@ -792,8 +809,10 @@ static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch)
 #endif
 
 static const struct tty_operations hvc_ops = {
+	.install = hvc_install,
 	.open = hvc_open,
 	.close = hvc_close,
+	.cleanup = hvc_cleanup,
 	.write = hvc_write,
 	.hangup = hvc_hangup,
 	.unthrottle = hvc_unthrottle,

+ 49 - 33
drivers/tty/hvc/hvcs.c

@@ -1102,27 +1102,20 @@ static struct hvcs_struct *hvcs_get_by_index(int index)
 	return NULL;
 }
 
-/*
- * This is invoked via the tty_open interface when a user app connects to the
- * /dev node.
- */
-static int hvcs_open(struct tty_struct *tty, struct file *filp)
+static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)
 {
 	struct hvcs_struct *hvcsd;
-	int rc, retval = 0;
-	unsigned long flags;
-	unsigned int irq;
 	struct vio_dev *vdev;
-	unsigned long unit_address;
-
-	if (tty->driver_data)
-		goto fast_open;
+	unsigned long unit_address, flags;
+	unsigned int irq;
+	int retval;
 
 	/*
 	 * Is there a vty-server that shares the same index?
 	 * This function increments the kref index.
 	 */
-	if (!(hvcsd = hvcs_get_by_index(tty->index))) {
+	hvcsd = hvcs_get_by_index(tty->index);
+	if (!hvcsd) {
 		printk(KERN_WARNING "HVCS: open failed, no device associated"
 				" with tty->index %d.\n", tty->index);
 		return -ENODEV;
@@ -1130,11 +1123,16 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
 
-	if (hvcsd->connected == 0)
-		if ((retval = hvcs_partner_connect(hvcsd)))
-			goto error_release;
+	if (hvcsd->connected == 0) {
+		retval = hvcs_partner_connect(hvcsd);
+		if (retval) {
+			spin_unlock_irqrestore(&hvcsd->lock, flags);
+			printk(KERN_WARNING "HVCS: partner connect failed.\n");
+			goto err_put;
+		}
+	}
 
-	hvcsd->port.count = 1;
+	hvcsd->port.count = 0;
 	hvcsd->port.tty = tty;
 	tty->driver_data = hvcsd;
 
@@ -1155,37 +1153,48 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
 	 * This must be done outside of the spinlock because it requests irqs
 	 * and will grab the spinlock and free the connection if it fails.
 	 */
-	if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
-		tty_port_put(&hvcsd->port);
+	retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev);
+	if (retval) {
 		printk(KERN_WARNING "HVCS: enable device failed.\n");
-		return rc;
+		goto err_put;
 	}
 
-	goto open_success;
+	retval = tty_port_install(&hvcsd->port, driver, tty);
+	if (retval)
+		goto err_irq;
 
-fast_open:
-	hvcsd = tty->driver_data;
+	return 0;
+err_irq:
+	spin_lock_irqsave(&hvcsd->lock, flags);
+	vio_disable_interrupts(hvcsd->vdev);
+	spin_unlock_irqrestore(&hvcsd->lock, flags);
+	free_irq(irq, hvcsd);
+err_put:
+	tty_port_put(&hvcsd->port);
+
+	return retval;
+}
+
+/*
+ * This is invoked via the tty_open interface when a user app connects to the
+ * /dev node.
+ */
+static int hvcs_open(struct tty_struct *tty, struct file *filp)
+{
+	struct hvcs_struct *hvcsd = tty->driver_data;
+	unsigned long flags;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
-	tty_port_get(&hvcsd->port);
 	hvcsd->port.count++;
 	hvcsd->todo_mask |= HVCS_SCHED_READ;
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-open_success:
 	hvcs_kick();
 
 	printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
 		hvcsd->vdev->unit_address );
 
 	return 0;
-
-error_release:
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	tty_port_put(&hvcsd->port);
-
-	printk(KERN_WARNING "HVCS: partner connect failed.\n");
-	return retval;
 }
 
 static void hvcs_close(struct tty_struct *tty, struct file *filp)
@@ -1236,7 +1245,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
 		tty->driver_data = NULL;
 
 		free_irq(irq, hvcsd);
-		tty_port_put(&hvcsd->port);
 		return;
 	} else if (hvcsd->port.count < 0) {
 		printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
@@ -1245,6 +1253,12 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
 	}
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
+}
+
+static void hvcs_cleanup(struct tty_struct * tty)
+{
+	struct hvcs_struct *hvcsd = tty->driver_data;
+
 	tty_port_put(&hvcsd->port);
 }
 
@@ -1431,8 +1445,10 @@ static int hvcs_chars_in_buffer(struct tty_struct *tty)
 }
 
 static const struct tty_operations hvcs_ops = {
+	.install = hvcs_install,
 	.open = hvcs_open,
 	.close = hvcs_close,
+	.cleanup = hvcs_cleanup,
 	.hangup = hvcs_hangup,
 	.write = hvcs_write,
 	.write_room = hvcs_write_room,

+ 2 - 0
drivers/tty/hvc/hvsi.c

@@ -1080,6 +1080,8 @@ static int __init hvsi_init(void)
 		struct hvsi_struct *hp = &hvsi_ports[i];
 		int ret = 1;
 
+		tty_port_link_device(&hp->port, hvsi_driver, i);
+
 		ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
 		if (ret)
 			printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",

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

@@ -400,7 +400,7 @@ void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp)
 		spin_unlock_irqrestore(&hp->lock, flags);
 
 		/* Clear our own DTR */
-		if (!pv->tty || (pv->tty->termios->c_cflag & HUPCL))
+		if (!pv->tty || (pv->tty->termios.c_cflag & HUPCL))
 			hvsilib_write_mctrl(pv, 0);
 
 		/* Tear down the connection */

+ 1 - 1
drivers/tty/ipwireless/tty.c

@@ -476,7 +476,7 @@ static int add_tty(int j,
 	mutex_init(&ttys[j]->ipw_tty_mutex);
 	tty_port_init(&ttys[j]->port);
 
-	tty_register_device(ipw_tty_driver, j, NULL);
+	tty_port_register_device(&ttys[j]->port, ipw_tty_driver, j, NULL);
 	ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
 
 	if (secondary_channel_idx != -1)

+ 7 - 6
drivers/tty/isicom.c

@@ -600,7 +600,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
 					port->status &= ~ISI_DCD;
 			}
 
-			if (port->port.flags & ASYNC_CTS_FLOW) {
+			if (tty_port_cts_enabled(&port->port)) {
 				if (tty->hw_stopped) {
 					if (header & ISI_CTS) {
 						port->port.tty->hw_stopped = 0;
@@ -702,7 +702,7 @@ static void isicom_config_port(struct tty_struct *tty)
 
 		/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
 		if (baud < 1 || baud > 4)
-			tty->termios->c_cflag &= ~CBAUDEX;
+			tty->termios.c_cflag &= ~CBAUDEX;
 		else
 			baud += 15;
 	}
@@ -1196,8 +1196,8 @@ static void isicom_set_termios(struct tty_struct *tty,
 	if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
 		return;
 
-	if (tty->termios->c_cflag == old_termios->c_cflag &&
-			tty->termios->c_iflag == old_termios->c_iflag)
+	if (tty->termios.c_cflag == old_termios->c_cflag &&
+			tty->termios.c_iflag == old_termios->c_iflag)
 		return;
 
 	spin_lock_irqsave(&port->card->card_lock, flags);
@@ -1205,7 +1205,7 @@ static void isicom_set_termios(struct tty_struct *tty,
 	spin_unlock_irqrestore(&port->card->card_lock, flags);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
+			!(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		isicom_start(tty);
 	}
@@ -1611,7 +1611,8 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
 		goto errunri;
 
 	for (index = 0; index < board->port_count; index++)
-		tty_register_device(isicom_normal, board->index * 16 + index,
+		tty_port_register_device(&board->ports[index].port,
+				isicom_normal, board->index * 16 + index,
 				&pdev->dev);
 
 	return 0;

+ 28 - 11
drivers/tty/moxa.c

@@ -169,6 +169,7 @@ static DEFINE_SPINLOCK(moxa_lock);
 static unsigned long baseaddr[MAX_BOARDS];
 static unsigned int type[MAX_BOARDS];
 static unsigned int numports[MAX_BOARDS];
+static struct tty_port moxa_service_port;
 
 MODULE_AUTHOR("William Chen");
 MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
@@ -367,10 +368,10 @@ static int moxa_ioctl(struct tty_struct *tty,
 					tmp.dcd = 1;
 
 				ttyp = tty_port_tty_get(&p->port);
-				if (!ttyp || !ttyp->termios)
+				if (!ttyp)
 					tmp.cflag = p->cflag;
 				else
-					tmp.cflag = ttyp->termios->c_cflag;
+					tmp.cflag = ttyp->termios.c_cflag;
 				tty_kref_put(ttyp);
 copy:
 				if (copy_to_user(argm, &tmp, sizeof(tmp)))
@@ -834,7 +835,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
 	const struct firmware *fw;
 	const char *file;
 	struct moxa_port *p;
-	unsigned int i;
+	unsigned int i, first_idx;
 	int ret;
 
 	brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
@@ -887,6 +888,11 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
 		mod_timer(&moxaTimer, jiffies + HZ / 50);
 	spin_unlock_bh(&moxa_lock);
 
+	first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
+	for (i = 0; i < brd->numPorts; i++)
+		tty_port_register_device(&brd->ports[i].port, moxaDriver,
+				first_idx + i, dev);
+
 	return 0;
 err_free:
 	kfree(brd->ports);
@@ -896,7 +902,7 @@ err:
 
 static void moxa_board_deinit(struct moxa_board_conf *brd)
 {
-	unsigned int a, opened;
+	unsigned int a, opened, first_idx;
 
 	mutex_lock(&moxa_openlock);
 	spin_lock_bh(&moxa_lock);
@@ -925,6 +931,10 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
 		mutex_lock(&moxa_openlock);
 	}
 
+	first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
+	for (a = 0; a < brd->numPorts; a++)
+		tty_unregister_device(moxaDriver, first_idx + a);
+
 	iounmap(brd->basemem);
 	brd->basemem = NULL;
 	kfree(brd->ports);
@@ -967,6 +977,7 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
 	board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
 	if (board->basemem == NULL) {
 		dev_err(&pdev->dev, "can't remap io space 2\n");
+		retval = -ENOMEM;
 		goto err_reg;
 	}
 
@@ -1031,9 +1042,14 @@ static int __init moxa_init(void)
 
 	printk(KERN_INFO "MOXA Intellio family driver version %s\n",
 			MOXA_VERSION);
-	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
-	if (!moxaDriver)
-		return -ENOMEM;
+
+	tty_port_init(&moxa_service_port);
+
+	moxaDriver = tty_alloc_driver(MAX_PORTS + 1,
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_DYNAMIC_DEV);
+	if (IS_ERR(moxaDriver))
+		return PTR_ERR(moxaDriver);
 
 	moxaDriver->name = "ttyMX";
 	moxaDriver->major = ttymajor;
@@ -1044,8 +1060,9 @@ static int __init moxa_init(void)
 	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
 	moxaDriver->init_termios.c_ispeed = 9600;
 	moxaDriver->init_termios.c_ospeed = 9600;
-	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(moxaDriver, &moxa_ops);
+	/* Having one more port only for ioctls is ugly */
+	tty_port_link_device(&moxa_service_port, moxaDriver, MAX_PORTS);
 
 	if (tty_register_driver(moxaDriver)) {
 		printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
@@ -1178,7 +1195,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
 	mutex_lock(&ch->port.mutex);
 	if (!(ch->port.flags & ASYNC_INITIALIZED)) {
 		ch->statusflags = 0;
-		moxa_set_tty_param(tty, tty->termios);
+		moxa_set_tty_param(tty, &tty->termios);
 		MoxaPortLineCtrl(ch, 1, 1);
 		MoxaPortEnable(ch);
 		MoxaSetFifo(ch, ch->type == PORT_16550A);
@@ -1193,7 +1210,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
 static void moxa_close(struct tty_struct *tty, struct file *filp)
 {
 	struct moxa_port *ch = tty->driver_data;
-	ch->cflag = tty->termios->c_cflag;
+	ch->cflag = tty->termios.c_cflag;
 	tty_port_close(&ch->port, tty, filp);
 }
 
@@ -1464,7 +1481,7 @@ static void moxa_poll(unsigned long ignored)
 
 static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
 {
-	register struct ktermios *ts = tty->termios;
+	register struct ktermios *ts = &tty->termios;
 	struct moxa_port *ch = tty->driver_data;
 	int rts, cts, txflow, rxflow, xany, baud;
 

+ 46 - 17
drivers/tty/mxser.c

@@ -643,7 +643,7 @@ static int mxser_change_speed(struct tty_struct *tty,
 	int ret = 0;
 	unsigned char status;
 
-	cflag = tty->termios->c_cflag;
+	cflag = tty->termios.c_cflag;
 	if (!info->ioaddr)
 		return ret;
 
@@ -830,7 +830,7 @@ static void mxser_check_modem_status(struct tty_struct *tty,
 			wake_up_interruptible(&port->port.open_wait);
 	}
 
-	if (port->port.flags & ASYNC_CTS_FLOW) {
+	if (tty_port_cts_enabled(&port->port)) {
 		if (tty->hw_stopped) {
 			if (status & UART_MSR_CTS) {
 				tty->hw_stopped = 0;
@@ -1520,10 +1520,10 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 				
 				tty = tty_port_tty_get(port);
 
-				if (!tty || !tty->termios)
+				if (!tty)
 					ms.cflag = ip->normal_termios.c_cflag;
 				else
-					ms.cflag = tty->termios->c_cflag;
+					ms.cflag = tty->termios.c_cflag;
 				tty_kref_put(tty);
 				spin_lock_irq(&ip->slock);
 				status = inb(ip->ioaddr + UART_MSR);
@@ -1589,13 +1589,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 
 				tty = tty_port_tty_get(&ip->port);
 
-				if (!tty || !tty->termios) {
+				if (!tty) {
 					cflag = ip->normal_termios.c_cflag;
 					iflag = ip->normal_termios.c_iflag;
 					me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
 				} else {
-					cflag = tty->termios->c_cflag;
-					iflag = tty->termios->c_iflag;
+					cflag = tty->termios.c_cflag;
+					iflag = tty->termios.c_iflag;
 					me->baudrate[p] = tty_get_baud_rate(tty);
 				}
 				tty_kref_put(tty);
@@ -1853,7 +1853,7 @@ static void mxser_stoprx(struct tty_struct *tty)
 		}
 	}
 
-	if (tty->termios->c_cflag & CRTSCTS) {
+	if (tty->termios.c_cflag & CRTSCTS) {
 		info->MCR &= ~UART_MCR_RTS;
 		outb(info->MCR, info->ioaddr + UART_MCR);
 	}
@@ -1890,7 +1890,7 @@ static void mxser_unthrottle(struct tty_struct *tty)
 		}
 	}
 
-	if (tty->termios->c_cflag & CRTSCTS) {
+	if (tty->termios.c_cflag & CRTSCTS) {
 		info->MCR |= UART_MCR_RTS;
 		outb(info->MCR, info->ioaddr + UART_MCR);
 	}
@@ -1939,14 +1939,14 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
 	spin_unlock_irqrestore(&info->slock, flags);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
+			!(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		mxser_start(tty);
 	}
 
 	/* Handle sw stopped */
 	if ((old_termios->c_iflag & IXON) &&
-			!(tty->termios->c_iflag & IXON)) {
+			!(tty->termios.c_iflag & IXON)) {
 		tty->stopped = 0;
 
 		if (info->board->chip_flag) {
@@ -2337,11 +2337,36 @@ static struct tty_port_operations mxser_port_ops = {
  * The MOXA Smartio/Industio serial driver boot-time initialization code!
  */
 
+static bool allow_overlapping_vector;
+module_param(allow_overlapping_vector, bool, S_IRUGO);
+MODULE_PARM_DESC(allow_overlapping_vector, "whether we allow ISA cards to be configured such that vector overlabs IO ports (default=no)");
+
+static bool mxser_overlapping_vector(struct mxser_board *brd)
+{
+	return allow_overlapping_vector &&
+		brd->vector >= brd->ports[0].ioaddr &&
+		brd->vector < brd->ports[0].ioaddr + 8 * brd->info->nports;
+}
+
+static int mxser_request_vector(struct mxser_board *brd)
+{
+	if (mxser_overlapping_vector(brd))
+		return 0;
+	return request_region(brd->vector, 1, "mxser(vector)") ? 0 : -EIO;
+}
+
+static void mxser_release_vector(struct mxser_board *brd)
+{
+	if (mxser_overlapping_vector(brd))
+		return;
+	release_region(brd->vector, 1);
+}
+
 static void mxser_release_ISA_res(struct mxser_board *brd)
 {
 	free_irq(brd->irq, brd);
 	release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-	release_region(brd->vector, 1);
+	mxser_release_vector(brd);
 }
 
 static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2396,7 +2421,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
 
 static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
 {
-	int id, i, bits;
+	int id, i, bits, ret;
 	unsigned short regs[16], irq;
 	unsigned char scratch, scratch2;
 
@@ -2492,13 +2517,15 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
 				8 * brd->info->nports - 1);
 		return -EIO;
 	}
-	if (!request_region(brd->vector, 1, "mxser(vector)")) {
+
+	ret = mxser_request_vector(brd);
+	if (ret) {
 		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
 		printk(KERN_ERR "mxser: can't request interrupt vector region: "
 				"0x%.8lx-0x%.8lx\n",
 				brd->ports[0].ioaddr, brd->ports[0].ioaddr +
 				8 * brd->info->nports - 1);
-		return -EIO;
+		return ret;
 	}
 	return brd->info->nports;
 
@@ -2598,7 +2625,8 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
 		goto err_rel3;
 
 	for (i = 0; i < brd->info->nports; i++)
-		tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
+		tty_port_register_device(&brd->ports[i].port, mxvar_sdriver,
+				brd->idx + i, &pdev->dev);
 
 	pci_set_drvdata(pdev, brd);
 
@@ -2695,7 +2723,8 @@ static int __init mxser_module_init(void)
 
 		brd->idx = m * MXSER_PORTS_PER_BOARD;
 		for (i = 0; i < brd->info->nports; i++)
-			tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
+			tty_port_register_device(&brd->ports[i].port,
+					mxvar_sdriver, brd->idx + i, NULL);
 
 		m++;
 	}

+ 86 - 56
drivers/tty/n_gsm.c

@@ -108,7 +108,7 @@ struct gsm_mux_net {
  */
 
 struct gsm_msg {
-	struct gsm_msg *next;
+	struct list_head list;
 	u8 addr;		/* DLCI address + flags */
 	u8 ctrl;		/* Control byte + flags */
 	unsigned int len;	/* Length of data block (can be zero) */
@@ -245,8 +245,7 @@ struct gsm_mux {
 	unsigned int tx_bytes;		/* TX data outstanding */
 #define TX_THRESH_HI		8192
 #define TX_THRESH_LO		2048
-	struct gsm_msg *tx_head;	/* Pending data packets */
-	struct gsm_msg *tx_tail;
+	struct list_head tx_list;	/* Pending data packets */
 
 	/* Control messages */
 	struct timer_list t2_timer;	/* Retransmit timer for commands */
@@ -663,7 +662,7 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,
 	m->len = len;
 	m->addr = addr;
 	m->ctrl = ctrl;
-	m->next = NULL;
+	INIT_LIST_HEAD(&m->list);
 	return m;
 }
 
@@ -673,22 +672,21 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,
  *
  *	The tty device has called us to indicate that room has appeared in
  *	the transmit queue. Ram more data into the pipe if we have any
+ *	If we have been flow-stopped by a CMD_FCOFF, then we can only
+ *	send messages on DLCI0 until CMD_FCON
  *
  *	FIXME: lock against link layer control transmissions
  */
 
 static void gsm_data_kick(struct gsm_mux *gsm)
 {
-	struct gsm_msg *msg = gsm->tx_head;
+	struct gsm_msg *msg, *nmsg;
 	int len;
 	int skip_sof = 0;
 
-	/* FIXME: We need to apply this solely to data messages */
-	if (gsm->constipated)
-		return;
-
-	while (gsm->tx_head != NULL) {
-		msg = gsm->tx_head;
+	list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) {
+		if (gsm->constipated && msg->addr)
+			continue;
 		if (gsm->encoding != 0) {
 			gsm->txframe[0] = GSM1_SOF;
 			len = gsm_stuff_frame(msg->data,
@@ -711,14 +709,13 @@ static void gsm_data_kick(struct gsm_mux *gsm)
 						len - skip_sof) < 0)
 			break;
 		/* FIXME: Can eliminate one SOF in many more cases */
-		gsm->tx_head = msg->next;
-		if (gsm->tx_head == NULL)
-			gsm->tx_tail = NULL;
 		gsm->tx_bytes -= msg->len;
-		kfree(msg);
 		/* For a burst of frames skip the extra SOF within the
 		   burst */
 		skip_sof = 1;
+
+		list_del(&msg->list);
+		kfree(msg);
 	}
 }
 
@@ -768,11 +765,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
 	msg->data = dp;
 
 	/* Add to the actual output queue */
-	if (gsm->tx_tail)
-		gsm->tx_tail->next = msg;
-	else
-		gsm->tx_head = msg;
-	gsm->tx_tail = msg;
+	list_add_tail(&msg->list, &gsm->tx_list);
 	gsm->tx_bytes += msg->len;
 	gsm_data_kick(gsm);
 }
@@ -875,7 +868,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
 
 	/* dlci->skb is locked by tx_lock */
 	if (dlci->skb == NULL) {
-		dlci->skb = skb_dequeue(&dlci->skb_list);
+		dlci->skb = skb_dequeue_tail(&dlci->skb_list);
 		if (dlci->skb == NULL)
 			return 0;
 		first = 1;
@@ -886,7 +879,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
 	if (len > gsm->mtu) {
 		if (dlci->adaption == 3) {
 			/* Over long frame, bin it */
-			kfree_skb(dlci->skb);
+			dev_kfree_skb_any(dlci->skb);
 			dlci->skb = NULL;
 			return 0;
 		}
@@ -899,8 +892,11 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
 
 	/* FIXME: need a timer or something to kick this so it can't
 	   get stuck with no work outstanding and no buffer free */
-	if (msg == NULL)
+	if (msg == NULL) {
+		skb_queue_tail(&dlci->skb_list, dlci->skb);
+		dlci->skb = NULL;
 		return -ENOMEM;
+	}
 	dp = msg->data;
 
 	if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */
@@ -912,7 +908,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
 	skb_pull(dlci->skb, len);
 	__gsm_data_queue(dlci, msg);
 	if (last) {
-		kfree_skb(dlci->skb);
+		dev_kfree_skb_any(dlci->skb);
 		dlci->skb = NULL;
 	}
 	return size;
@@ -971,16 +967,22 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)
 static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
 {
 	unsigned long flags;
+	int sweep;
+
+	if (dlci->constipated) 
+		return;
 
 	spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
 	/* If we have nothing running then we need to fire up */
+	sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO);
 	if (dlci->gsm->tx_bytes == 0) {
 		if (dlci->net)
 			gsm_dlci_data_output_framed(dlci->gsm, dlci);
 		else
 			gsm_dlci_data_output(dlci->gsm, dlci);
-	} else if (dlci->gsm->tx_bytes < TX_THRESH_LO)
-		gsm_dlci_data_sweep(dlci->gsm);
+	}
+	if (sweep)
+ 		gsm_dlci_data_sweep(dlci->gsm);
 	spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
 }
 
@@ -1027,6 +1029,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
 {
 	int  mlines = 0;
 	u8 brk = 0;
+	int fc;
 
 	/* The modem status command can either contain one octet (v.24 signals)
 	   or two octets (v.24 signals + break signals). The length field will
@@ -1038,19 +1041,21 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
 	else {
 		brk = modem & 0x7f;
 		modem = (modem >> 7) & 0x7f;
-	};
+	}
 
 	/* Flow control/ready to communicate */
-	if (modem & MDM_FC) {
+	fc = (modem & MDM_FC) || !(modem & MDM_RTR);
+	if (fc && !dlci->constipated) {
 		/* Need to throttle our output on this device */
 		dlci->constipated = 1;
-	}
-	if (modem & MDM_RTC) {
-		mlines |= TIOCM_DSR | TIOCM_DTR;
+	} else if (!fc && dlci->constipated) {
 		dlci->constipated = 0;
 		gsm_dlci_data_kick(dlci);
 	}
+
 	/* Map modem bits */
+	if (modem & MDM_RTC)
+		mlines |= TIOCM_DSR | TIOCM_DTR;
 	if (modem & MDM_RTR)
 		mlines |= TIOCM_RTS | TIOCM_CTS;
 	if (modem & MDM_IC)
@@ -1061,7 +1066,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
 	/* Carrier drop -> hangup */
 	if (tty) {
 		if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD))
-			if (!(tty->termios->c_cflag & CLOCAL))
+			if (!(tty->termios.c_cflag & CLOCAL))
 				tty_hangup(tty);
 		if (brk & 0x01)
 			tty_insert_flip_char(tty, 0, TTY_BREAK);
@@ -1190,6 +1195,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
 							u8 *data, int clen)
 {
 	u8 buf[1];
+	unsigned long flags;
+
 	switch (command) {
 	case CMD_CLD: {
 		struct gsm_dlci *dlci = gsm->dlci[0];
@@ -1206,16 +1213,18 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
 		gsm_control_reply(gsm, CMD_TEST, data, clen);
 		break;
 	case CMD_FCON:
-		/* Modem wants us to STFU */
-		gsm->constipated = 1;
-		gsm_control_reply(gsm, CMD_FCON, NULL, 0);
-		break;
-	case CMD_FCOFF:
 		/* Modem can accept data again */
 		gsm->constipated = 0;
-		gsm_control_reply(gsm, CMD_FCOFF, NULL, 0);
+		gsm_control_reply(gsm, CMD_FCON, NULL, 0);
 		/* Kick the link in case it is idling */
+		spin_lock_irqsave(&gsm->tx_lock, flags);
 		gsm_data_kick(gsm);
+		spin_unlock_irqrestore(&gsm->tx_lock, flags);
+		break;
+	case CMD_FCOFF:
+		/* Modem wants us to STFU */
+		gsm->constipated = 1;
+		gsm_control_reply(gsm, CMD_FCOFF, NULL, 0);
 		break;
 	case CMD_MSC:
 		/* Out of band modem line change indicator for a DLCI */
@@ -1668,7 +1677,7 @@ static void gsm_dlci_free(struct kref *ref)
 	dlci->gsm->dlci[dlci->addr] = NULL;
 	kfifo_free(dlci->fifo);
 	while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
-		kfree_skb(dlci->skb);
+		dev_kfree_skb(dlci->skb);
 	kfree(dlci);
 }
 
@@ -2007,7 +2016,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
 {
 	int i;
 	struct gsm_dlci *dlci = gsm->dlci[0];
-	struct gsm_msg *txq;
+	struct gsm_msg *txq, *ntxq;
 	struct gsm_control *gc;
 
 	gsm->dead = 1;
@@ -2042,11 +2051,9 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
 		if (gsm->dlci[i])
 			gsm_dlci_release(gsm->dlci[i]);
 	/* Now wipe the queues */
-	for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) {
-		gsm->tx_head = txq->next;
+	list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
 		kfree(txq);
-	}
-	gsm->tx_tail = NULL;
+	INIT_LIST_HEAD(&gsm->tx_list);
 }
 EXPORT_SYMBOL_GPL(gsm_cleanup_mux);
 
@@ -2157,6 +2164,7 @@ struct gsm_mux *gsm_alloc_mux(void)
 	}
 	spin_lock_init(&gsm->lock);
 	kref_init(&gsm->ref);
+	INIT_LIST_HEAD(&gsm->tx_list);
 
 	gsm->t1 = T1;
 	gsm->t2 = T2;
@@ -2273,7 +2281,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			gsm->error(gsm, *dp, flags);
 			break;
 		default:
-			WARN_ONCE("%s: unknown flag %d\n",
+			WARN_ONCE(1, "%s: unknown flag %d\n",
 			       tty_name(tty, buf), flags);
 			break;
 		}
@@ -2377,12 +2385,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty)
 
 	/* Queue poll */
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	spin_lock_irqsave(&gsm->tx_lock, flags);
 	gsm_data_kick(gsm);
 	if (gsm->tx_bytes < TX_THRESH_LO) {
-		spin_lock_irqsave(&gsm->tx_lock, flags);
 		gsm_dlci_data_sweep(gsm);
-		spin_unlock_irqrestore(&gsm->tx_lock, flags);
 	}
+	spin_unlock_irqrestore(&gsm->tx_lock, flags);
 }
 
 /**
@@ -2868,14 +2876,14 @@ static const struct tty_port_operations gsm_port_ops = {
 	.dtr_rts = gsm_dtr_rts,
 };
 
-
-static int gsmtty_open(struct tty_struct *tty, struct file *filp)
+static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
 {
 	struct gsm_mux *gsm;
 	struct gsm_dlci *dlci;
-	struct tty_port *port;
 	unsigned int line = tty->index;
 	unsigned int mux = line >> 6;
+	bool alloc = false;
+	int ret;
 
 	line = line & 0x3F;
 
@@ -2889,14 +2897,35 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
 	gsm = gsm_mux[mux];
 	if (gsm->dead)
 		return -EL2HLT;
+	/* If DLCI 0 is not yet fully open return an error. This is ok from a locking
+	   perspective as we don't have to worry about this if DLCI0 is lost */
+	if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) 
+		return -EL2NSYNC;
 	dlci = gsm->dlci[line];
-	if (dlci == NULL)
+	if (dlci == NULL) {
+		alloc = true;
 		dlci = gsm_dlci_alloc(gsm, line);
+	}
 	if (dlci == NULL)
 		return -ENOMEM;
-	port = &dlci->port;
-	port->count++;
+	ret = tty_port_install(&dlci->port, driver, tty);
+	if (ret) {
+		if (alloc)
+			dlci_put(dlci);
+		return ret;
+	}
+
 	tty->driver_data = dlci;
+
+	return 0;
+}
+
+static int gsmtty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct gsm_dlci *dlci = tty->driver_data;
+	struct tty_port *port = &dlci->port;
+
+	port->count++;
 	dlci_get(dlci);
 	dlci_get(dlci->gsm->dlci[0]);
 	mux_get(dlci->gsm);
@@ -3043,13 +3072,13 @@ static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old)
 	   the RPN control message. This however rapidly gets nasty as we
 	   then have to remap modem signals each way according to whether
 	   our virtual cable is null modem etc .. */
-	tty_termios_copy_hw(tty->termios, old);
+	tty_termios_copy_hw(&tty->termios, old);
 }
 
 static void gsmtty_throttle(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		dlci->modem_tx &= ~TIOCM_DTR;
 	dlci->throttled = 1;
 	/* Send an MSC with DTR cleared */
@@ -3059,7 +3088,7 @@ static void gsmtty_throttle(struct tty_struct *tty)
 static void gsmtty_unthrottle(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		dlci->modem_tx |= TIOCM_DTR;
 	dlci->throttled = 0;
 	/* Send an MSC with DTR set */
@@ -3085,6 +3114,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
 
 /* Virtual ttys for the demux */
 static const struct tty_operations gsmtty_ops = {
+	.install		= gsmtty_install,
 	.open			= gsmtty_open,
 	.close			= gsmtty_close,
 	.write			= gsmtty_write,

+ 5 - 5
drivers/tty/n_r3964.c

@@ -1065,7 +1065,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 
 	TRACE_L("read()");
 
-	tty_lock();
+	tty_lock(tty);
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
@@ -1077,7 +1077,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 				goto unlock;
 			}
 			/* block until there is a message: */
-			wait_event_interruptible_tty(pInfo->read_wait,
+			wait_event_interruptible_tty(tty, pInfo->read_wait,
 					(pMsg = remove_msg(pInfo, pClient)));
 		}
 
@@ -1107,7 +1107,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 	}
 	ret = -EPERM;
 unlock:
-	tty_unlock();
+	tty_unlock(tty);
 	return ret;
 }
 
@@ -1156,7 +1156,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
 	pHeader->locks = 0;
 	pHeader->owner = NULL;
 
-	tty_lock();
+	tty_lock(tty);
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
@@ -1175,7 +1175,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
 	add_tx_queue(pInfo, pHeader);
 	trigger_transmit(pInfo);
 
-	tty_unlock();
+	tty_unlock(tty);
 
 	return 0;
 }

+ 24 - 5
drivers/tty/n_tty.c

@@ -92,10 +92,18 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 
 static void n_tty_set_room(struct tty_struct *tty)
 {
-	/* tty->read_cnt is not read locked ? */
-	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+	int left;
 	int old_left;
 
+	/* tty->read_cnt is not read locked ? */
+	if (I_PARMRK(tty)) {
+		/* Multiply read_cnt by 3, since each byte might take up to
+		 * three times as many spaces when PARMRK is set (depending on
+		 * its flags, e.g. parity error). */
+		left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+	} else
+		left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
 	/*
 	 * If we are doing input canonicalization, and there are no
 	 * pending newlines, let characters through without limit, so
@@ -1432,6 +1440,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 	 */
 	if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
 		tty_throttle(tty);
+
+        /* FIXME: there is a tiny race here if the receive room check runs
+           before the other work executes and empties the buffer (upping
+           the receiving room and unthrottling. We then throttle and get
+           stuck. This has been observed and traced down by Vincent Pillet/
+           We need to address this when we sort out out the rx path locking */
 }
 
 int is_ignored(int sig)
@@ -1460,7 +1474,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 	BUG_ON(!tty);
 
 	if (old)
-		canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
+		canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
 	if (canon_change) {
 		memset(&tty->read_flags, 0, sizeof tty->read_flags);
 		tty->canon_head = tty->read_tail;
@@ -1728,7 +1742,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 
 do_it_again:
 
-	BUG_ON(!tty->read_buf);
+	if (WARN_ON(!tty->read_buf))
+		return -EAGAIN;
 
 	c = job_control(tty, file);
 	if (c < 0)
@@ -1832,13 +1847,13 @@ do_it_again:
 
 		if (tty->icanon && !L_EXTPROC(tty)) {
 			/* N.B. avoid overrun if nr == 0 */
+			spin_lock_irqsave(&tty->read_lock, flags);
 			while (nr && tty->read_cnt) {
 				int eol;
 
 				eol = test_and_clear_bit(tty->read_tail,
 						tty->read_flags);
 				c = tty->read_buf[tty->read_tail];
-				spin_lock_irqsave(&tty->read_lock, flags);
 				tty->read_tail = ((tty->read_tail+1) &
 						  (N_TTY_BUF_SIZE-1));
 				tty->read_cnt--;
@@ -1856,15 +1871,19 @@ do_it_again:
 					if (tty_put_user(tty, c, b++)) {
 						retval = -EFAULT;
 						b--;
+						spin_lock_irqsave(&tty->read_lock, flags);
 						break;
 					}
 					nr--;
 				}
 				if (eol) {
 					tty_audit_push(tty);
+					spin_lock_irqsave(&tty->read_lock, flags);
 					break;
 				}
+				spin_lock_irqsave(&tty->read_lock, flags);
 			}
+			spin_unlock_irqrestore(&tty->read_lock, flags);
 			if (retval)
 				break;
 		} else {

+ 2 - 2
drivers/tty/nozomi.c

@@ -1473,8 +1473,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 		port->dc = dc;
 		tty_port_init(&port->port);
 		port->port.ops = &noz_tty_port_ops;
-		tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
-							&pdev->dev);
+		tty_dev = tty_port_register_device(&port->port, ntty_driver,
+				dc->index_start + i, &pdev->dev);
 
 		if (IS_ERR(tty_dev)) {
 			ret = PTR_ERR(tty_dev);

+ 122 - 112
drivers/tty/pty.c

@@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
 	wake_up_interruptible(&tty->read_wait);
 	wake_up_interruptible(&tty->write_wait);
 	tty->packet = 0;
+	/* Review - krefs on tty_link ?? */
 	if (!tty->link)
 		return;
 	tty->link->packet = 0;
@@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
 		        mutex_unlock(&devpts_mutex);
 		}
 #endif
-		tty_unlock();
+		tty_unlock(tty);
 		tty_vhangup(tty->link);
-		tty_lock();
+		tty_lock(tty);
 	}
 }
 
@@ -231,8 +232,8 @@ out:
 static void pty_set_termios(struct tty_struct *tty,
 					struct ktermios *old_termios)
 {
-	tty->termios->c_cflag &= ~(CSIZE | PARENB);
-	tty->termios->c_cflag |= (CS8 | CREAD);
+	tty->termios.c_cflag &= ~(CSIZE | PARENB);
+	tty->termios.c_cflag |= (CS8 | CREAD);
 }
 
 /**
@@ -282,60 +283,110 @@ done:
 	return 0;
 }
 
-/* Traditional BSD devices */
-#ifdef CONFIG_LEGACY_PTYS
-
-static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+/**
+ *	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
+ *
+ *	Perform the initial set up for the tty/pty pair. Called from the
+ *	tty layer when the port is first opened.
+ *
+ *	Locking: the caller must hold the tty_mutex
+ */
+static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
+		bool legacy)
 {
 	struct tty_struct *o_tty;
+	struct tty_port *ports[2];
 	int idx = tty->index;
-	int retval;
+	int retval = -ENOMEM;
 
 	o_tty = alloc_tty_struct();
 	if (!o_tty)
-		return -ENOMEM;
+		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;
 	if (!try_module_get(driver->other->owner)) {
 		/* This cannot in fact currently happen */
-		retval = -ENOMEM;
 		goto err_free_tty;
 	}
 	initialize_tty_struct(o_tty, driver->other, idx);
 
-	/* We always use new tty termios data so we can do this
-	   the easy way .. */
-	retval = tty_init_termios(tty);
-	if (retval)
-		goto err_deinit_tty;
-
-	retval = tty_init_termios(o_tty);
-	if (retval)
-		goto err_free_termios;
+	if (legacy) {
+		/* We always use new tty termios data so we can do this
+		   the easy way .. */
+		retval = tty_init_termios(tty);
+		if (retval)
+			goto err_deinit_tty;
+
+		retval = tty_init_termios(o_tty);
+		if (retval)
+			goto err_free_termios;
+
+		driver->other->ttys[idx] = o_tty;
+		driver->ttys[idx] = tty;
+	} else {
+		memset(&tty->termios_locked, 0, sizeof(tty->termios_locked));
+		tty->termios = driver->init_termios;
+		memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked));
+		o_tty->termios = driver->other->init_termios;
+	}
 
 	/*
 	 * Everything allocated ... set up the o_tty structure.
 	 */
-	driver->other->ttys[idx] = o_tty;
 	tty_driver_kref_get(driver->other);
 	if (driver->subtype == PTY_TYPE_MASTER)
 		o_tty->count++;
 	/* Establish the links in both directions */
 	tty->link   = o_tty;
 	o_tty->link = tty;
+	tty_port_init(ports[0]);
+	tty_port_init(ports[1]);
+	o_tty->port = ports[0];
+	tty->port = ports[1];
 
 	tty_driver_kref_get(driver);
 	tty->count++;
-	driver->ttys[idx] = tty;
 	return 0;
 err_free_termios:
-	tty_free_termios(tty);
+	if (legacy)
+		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:
 	return retval;
 }
 
+static void pty_cleanup(struct tty_struct *tty)
+{
+	kfree(tty->port);
+}
+
+/* Traditional BSD devices */
+#ifdef CONFIG_LEGACY_PTYS
+
+static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	return pty_common_install(driver, tty, true);
+}
+
+static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
+{
+	struct tty_struct *pair = tty->link;
+	driver->ttys[tty->index] = NULL;
+	if (pair)
+		pair->driver->ttys[pair->index] = NULL;
+}
+
 static int pty_bsd_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
@@ -366,7 +417,9 @@ static const struct tty_operations master_pty_ops_bsd = {
 	.unthrottle = pty_unthrottle,
 	.set_termios = pty_set_termios,
 	.ioctl = pty_bsd_ioctl,
-	.resize = pty_resize
+	.cleanup = pty_cleanup,
+	.resize = pty_resize,
+	.remove = pty_remove
 };
 
 static const struct tty_operations slave_pty_ops_bsd = {
@@ -379,7 +432,9 @@ static const struct tty_operations slave_pty_ops_bsd = {
 	.chars_in_buffer = pty_chars_in_buffer,
 	.unthrottle = pty_unthrottle,
 	.set_termios = pty_set_termios,
-	.resize = pty_resize
+	.cleanup = pty_cleanup,
+	.resize = pty_resize,
+	.remove = pty_remove
 };
 
 static void __init legacy_pty_init(void)
@@ -389,12 +444,18 @@ static void __init legacy_pty_init(void)
 	if (legacy_count <= 0)
 		return;
 
-	pty_driver = alloc_tty_driver(legacy_count);
-	if (!pty_driver)
+	pty_driver = tty_alloc_driver(legacy_count,
+			TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_DYNAMIC_ALLOC);
+	if (IS_ERR(pty_driver))
 		panic("Couldn't allocate pty driver");
 
-	pty_slave_driver = alloc_tty_driver(legacy_count);
-	if (!pty_slave_driver)
+	pty_slave_driver = tty_alloc_driver(legacy_count,
+			TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_DYNAMIC_ALLOC);
+	if (IS_ERR(pty_slave_driver))
 		panic("Couldn't allocate pty slave driver");
 
 	pty_driver->driver_name = "pty_master";
@@ -410,7 +471,6 @@ static void __init legacy_pty_init(void)
 	pty_driver->init_termios.c_lflag = 0;
 	pty_driver->init_termios.c_ispeed = 38400;
 	pty_driver->init_termios.c_ospeed = 38400;
-	pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
 	pty_driver->other = pty_slave_driver;
 	tty_set_operations(pty_driver, &master_pty_ops_bsd);
 
@@ -424,8 +484,6 @@ static void __init legacy_pty_init(void)
 	pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 	pty_slave_driver->init_termios.c_ispeed = 38400;
 	pty_slave_driver->init_termios.c_ospeed = 38400;
-	pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
-					TTY_DRIVER_REAL_RAW;
 	pty_slave_driver->other = pty_driver;
 	tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
 
@@ -497,78 +555,22 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
 	return tty;
 }
 
-static void pty_unix98_shutdown(struct tty_struct *tty)
-{
-	tty_driver_remove_tty(tty->driver, tty);
-	/* We have our own method as we don't use the tty index */
-	kfree(tty->termios);
-}
-
 /* We have no need to install and remove our tty objects as devpts does all
    the work for us */
 
 static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
 {
-	struct tty_struct *o_tty;
-	int idx = tty->index;
-
-	o_tty = alloc_tty_struct();
-	if (!o_tty)
-		return -ENOMEM;
-	if (!try_module_get(driver->other->owner)) {
-		/* This cannot in fact currently happen */
-		goto err_free_tty;
-	}
-	initialize_tty_struct(o_tty, driver->other, idx);
-
-	tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
-	if (tty->termios == NULL)
-		goto err_free_mem;
-	*tty->termios = driver->init_termios;
-	tty->termios_locked = tty->termios + 1;
-
-	o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
-	if (o_tty->termios == NULL)
-		goto err_free_mem;
-	*o_tty->termios = driver->other->init_termios;
-	o_tty->termios_locked = o_tty->termios + 1;
-
-	tty_driver_kref_get(driver->other);
-	if (driver->subtype == PTY_TYPE_MASTER)
-		o_tty->count++;
-	/* Establish the links in both directions */
-	tty->link   = o_tty;
-	o_tty->link = tty;
-	/*
-	 * All structures have been allocated, so now we install them.
-	 * Failures after this point use release_tty to clean up, so
-	 * there's no need to null out the local pointers.
-	 */
-	tty_driver_kref_get(driver);
-	tty->count++;
-	return 0;
-err_free_mem:
-	deinitialize_tty_struct(o_tty);
-	kfree(o_tty->termios);
-	kfree(tty->termios);
-	module_put(o_tty->driver->owner);
-err_free_tty:
-	free_tty_struct(o_tty);
-	return -ENOMEM;
-}
-
-static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
-{
+	return pty_common_install(driver, tty, false);
 }
 
-static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
+static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
 {
 }
 
 static const struct tty_operations ptm_unix98_ops = {
 	.lookup = ptm_unix98_lookup,
 	.install = pty_unix98_install,
-	.remove = ptm_unix98_remove,
+	.remove = pty_unix98_remove,
 	.open = pty_open,
 	.close = pty_close,
 	.write = pty_write,
@@ -578,14 +580,14 @@ static const struct tty_operations ptm_unix98_ops = {
 	.unthrottle = pty_unthrottle,
 	.set_termios = pty_set_termios,
 	.ioctl = pty_unix98_ioctl,
-	.shutdown = pty_unix98_shutdown,
-	.resize = pty_resize
+	.resize = pty_resize,
+	.cleanup = pty_cleanup
 };
 
 static const struct tty_operations pty_unix98_ops = {
 	.lookup = pts_unix98_lookup,
 	.install = pty_unix98_install,
-	.remove = pts_unix98_remove,
+	.remove = pty_unix98_remove,
 	.open = pty_open,
 	.close = pty_close,
 	.write = pty_write,
@@ -594,7 +596,7 @@ static const struct tty_operations pty_unix98_ops = {
 	.chars_in_buffer = pty_chars_in_buffer,
 	.unthrottle = pty_unthrottle,
 	.set_termios = pty_set_termios,
-	.shutdown = pty_unix98_shutdown
+	.cleanup = pty_cleanup,
 };
 
 /**
@@ -622,26 +624,27 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 		return retval;
 
 	/* find a device that is not in use. */
-	tty_lock();
+	mutex_lock(&devpts_mutex);
 	index = devpts_new_index(inode);
-	tty_unlock();
 	if (index < 0) {
 		retval = index;
 		goto err_file;
 	}
 
+	mutex_unlock(&devpts_mutex);
+
 	mutex_lock(&tty_mutex);
-	mutex_lock(&devpts_mutex);
 	tty = tty_init_dev(ptm_driver, index);
-	mutex_unlock(&devpts_mutex);
-	tty_lock();
-	mutex_unlock(&tty_mutex);
 
 	if (IS_ERR(tty)) {
 		retval = PTR_ERR(tty);
 		goto out;
 	}
 
+	/* The tty returned here is locked so we can safely
+	   drop the mutex */
+	mutex_unlock(&tty_mutex);
+
 	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
 
 	tty_add_file(tty, filp);
@@ -654,16 +657,17 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 	if (retval)
 		goto err_release;
 
-	tty_unlock();
+	tty_unlock(tty);
 	return 0;
 err_release:
-	tty_unlock();
+	tty_unlock(tty);
 	tty_release(inode, filp);
 	return retval;
 out:
+	mutex_unlock(&tty_mutex);
 	devpts_kill_index(inode, index);
-	tty_unlock();
 err_file:
+        mutex_unlock(&devpts_mutex);
 	tty_free_file(filp);
 	return retval;
 }
@@ -672,11 +676,21 @@ static struct file_operations ptmx_fops;
 
 static void __init unix98_pty_init(void)
 {
-	ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
-	if (!ptm_driver)
+	ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
+			TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_DYNAMIC_DEV |
+			TTY_DRIVER_DEVPTS_MEM |
+			TTY_DRIVER_DYNAMIC_ALLOC);
+	if (IS_ERR(ptm_driver))
 		panic("Couldn't allocate Unix98 ptm driver");
-	pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
-	if (!pts_driver)
+	pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
+			TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_DYNAMIC_DEV |
+			TTY_DRIVER_DEVPTS_MEM |
+			TTY_DRIVER_DYNAMIC_ALLOC);
+	if (IS_ERR(pts_driver))
 		panic("Couldn't allocate Unix98 pts driver");
 
 	ptm_driver->driver_name = "pty_master";
@@ -692,8 +706,6 @@ static void __init unix98_pty_init(void)
 	ptm_driver->init_termios.c_lflag = 0;
 	ptm_driver->init_termios.c_ispeed = 38400;
 	ptm_driver->init_termios.c_ospeed = 38400;
-	ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
 	ptm_driver->other = pts_driver;
 	tty_set_operations(ptm_driver, &ptm_unix98_ops);
 
@@ -707,8 +719,6 @@ static void __init unix98_pty_init(void)
 	pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 	pts_driver->init_termios.c_ispeed = 38400;
 	pts_driver->init_termios.c_ospeed = 38400;
-	pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
 	pts_driver->other = ptm_driver;
 	tty_set_operations(pts_driver, &pty_unix98_ops);
 

+ 11 - 11
drivers/tty/rocket.c

@@ -704,8 +704,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
 	spin_lock_init(&info->slock);
 	mutex_init(&info->write_mtx);
 	rp_table[line] = info;
-	tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
-			NULL);
+	tty_port_register_device(&info->port, rocket_driver, line,
+			pci_dev ? &pci_dev->dev : NULL);
 }
 
 /*
@@ -720,7 +720,7 @@ static void configure_r_port(struct tty_struct *tty, struct r_port *info,
 	unsigned rocketMode;
 	int bits, baud, divisor;
 	CHANNEL_t *cp;
-	struct ktermios *t = tty->termios;
+	struct ktermios *t = &tty->termios;
 
 	cp = &info->channel;
 	cflag = t->c_cflag;
@@ -978,7 +978,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
 			tty->alt_speed = 460800;
 
 		configure_r_port(tty, info, NULL);
-		if (tty->termios->c_cflag & CBAUD) {
+		if (tty->termios.c_cflag & CBAUD) {
 			sSetDTR(cp);
 			sSetRTS(cp);
 		}
@@ -1089,35 +1089,35 @@ static void rp_set_termios(struct tty_struct *tty,
 	if (rocket_paranoia_check(info, "rp_set_termios"))
 		return;
 
-	cflag = tty->termios->c_cflag;
+	cflag = tty->termios.c_cflag;
 
 	/*
 	 * This driver doesn't support CS5 or CS6
 	 */
 	if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
-		tty->termios->c_cflag =
+		tty->termios.c_cflag =
 		    ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
 	/* Or CMSPAR */
-	tty->termios->c_cflag &= ~CMSPAR;
+	tty->termios.c_cflag &= ~CMSPAR;
 
 	configure_r_port(tty, info, old_termios);
 
 	cp = &info->channel;
 
 	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
+	if ((old_termios->c_cflag & CBAUD) && !(tty->termios.c_cflag & CBAUD)) {
 		sClrDTR(cp);
 		sClrRTS(cp);
 	}
 
 	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
-		if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
+	if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) {
+		if (!tty->hw_stopped || !(tty->termios.c_cflag & CRTSCTS))
 			sSetRTS(cp);
 		sSetDTR(cp);
 	}
 
-	if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
+	if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		rp_start(tty);
 	}

+ 13 - 10
drivers/tty/serial/68328serial.c

@@ -515,7 +515,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty)
 	unsigned cflag;
 	int	i;
 
-	cflag = tty->termios->c_cflag;
+	cflag = tty->termios.c_cflag;
 	if (!(port = info->port))
 		return;
 
@@ -617,7 +617,7 @@ static void rs_set_ldisc(struct tty_struct *tty)
 	if (serial_paranoia_check(info, tty->name, "rs_set_ldisc"))
 		return;
 
-	info->is_cons = (tty->termios->c_line == N_TTY);
+	info->is_cons = (tty->termios.c_line == N_TTY);
 	
 	printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off");
 }
@@ -985,7 +985,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	change_speed(info, tty);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		rs_start(tty);
 	}
@@ -1070,7 +1070,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 		if (tty->ldisc.close)
 			(tty->ldisc.close)(tty);
 		tty->ldisc = ldiscs[N_TTY];
-		tty->termios->c_line = N_TTY;
+		tty->termios.c_line = N_TTY;
 		if (tty->ldisc.open)
 			(tty->ldisc.open)(tty);
 	}
@@ -1189,12 +1189,6 @@ rs68328_init(void)
 	serial_driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(serial_driver, &rs_ops);
 
-	if (tty_register_driver(serial_driver)) {
-		put_tty_driver(serial_driver);
-		printk(KERN_ERR "Couldn't register serial driver\n");
-		return -ENOMEM;
-	}
-
 	local_irq_save(flags);
 
 	for(i=0;i<NR_PORTS;i++) {
@@ -1224,8 +1218,17 @@ rs68328_init(void)
 			    0,
 			    "M68328_UART", info))
                 panic("Unable to attach 68328 serial interrupt\n");
+
+	    tty_port_link_device(&info->tport, serial_driver, i);
 	}
 	local_irq_restore(flags);
+
+	if (tty_register_driver(serial_driver)) {
+		put_tty_driver(serial_driver);
+		printk(KERN_ERR "Couldn't register serial driver\n");
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 

+ 33 - 51
drivers/tty/serial/8250/8250.c

@@ -2202,6 +2202,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned char cval, fcr = 0;
 	unsigned long flags;
 	unsigned int baud, quot;
+	int fifo_bug = 0;
 
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
@@ -2221,8 +2222,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	if (termios->c_cflag & CSTOPB)
 		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
+	if (termios->c_cflag & PARENB) {
 		cval |= UART_LCR_PARITY;
+		if (up->bugs & UART_BUG_PARITY)
+			fifo_bug = 1;
+	}
 	if (!(termios->c_cflag & PARODD))
 		cval |= UART_LCR_EPAR;
 #ifdef CMSPAR
@@ -2246,7 +2250,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
 		fcr = uart_config[port->type].fcr;
-		if (baud < 2400) {
+		if (baud < 2400 || fifo_bug) {
 			fcr &= ~UART_FCR_TRIGGER_MASK;
 			fcr |= UART_FCR_TRIGGER_1;
 		}
@@ -2336,7 +2340,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 			serial_port_out(port, UART_EFR, efr);
 	}
 
-#ifdef CONFIG_ARCH_OMAP
+#ifdef CONFIG_ARCH_OMAP1
 	/* Workaround to enable 115200 baud on OMAP1510 internal ports */
 	if (cpu_is_omap1510() && is_omap_port(up)) {
 		if (baud == 115200) {
@@ -2426,7 +2430,7 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
 {
 	if (pt->port.iotype == UPIO_AU)
 		return 0x1000;
-#ifdef CONFIG_ARCH_OMAP
+#ifdef CONFIG_ARCH_OMAP1
 	if (is_omap_port(pt))
 		return 0x16 << pt->port.regshift;
 #endif
@@ -2979,36 +2983,36 @@ void serial8250_resume_port(int line)
 static int __devinit serial8250_probe(struct platform_device *dev)
 {
 	struct plat_serial8250_port *p = dev->dev.platform_data;
-	struct uart_port port;
+	struct uart_8250_port uart;
 	int ret, i, irqflag = 0;
 
-	memset(&port, 0, sizeof(struct uart_port));
+	memset(&uart, 0, sizeof(uart));
 
 	if (share_irqs)
 		irqflag = IRQF_SHARED;
 
 	for (i = 0; p && p->flags != 0; p++, i++) {
-		port.iobase		= p->iobase;
-		port.membase		= p->membase;
-		port.irq		= p->irq;
-		port.irqflags		= p->irqflags;
-		port.uartclk		= p->uartclk;
-		port.regshift		= p->regshift;
-		port.iotype		= p->iotype;
-		port.flags		= p->flags;
-		port.mapbase		= p->mapbase;
-		port.hub6		= p->hub6;
-		port.private_data	= p->private_data;
-		port.type		= p->type;
-		port.serial_in		= p->serial_in;
-		port.serial_out		= p->serial_out;
-		port.handle_irq		= p->handle_irq;
-		port.handle_break	= p->handle_break;
-		port.set_termios	= p->set_termios;
-		port.pm			= p->pm;
-		port.dev		= &dev->dev;
-		port.irqflags		|= irqflag;
-		ret = serial8250_register_port(&port);
+		uart.port.iobase	= p->iobase;
+		uart.port.membase	= p->membase;
+		uart.port.irq		= p->irq;
+		uart.port.irqflags	= p->irqflags;
+		uart.port.uartclk	= p->uartclk;
+		uart.port.regshift	= p->regshift;
+		uart.port.iotype	= p->iotype;
+		uart.port.flags		= p->flags;
+		uart.port.mapbase	= p->mapbase;
+		uart.port.hub6		= p->hub6;
+		uart.port.private_data	= p->private_data;
+		uart.port.type		= p->type;
+		uart.port.serial_in	= p->serial_in;
+		uart.port.serial_out	= p->serial_out;
+		uart.port.handle_irq	= p->handle_irq;
+		uart.port.handle_break	= p->handle_break;
+		uart.port.set_termios	= p->set_termios;
+		uart.port.pm		= p->pm;
+		uart.port.dev		= &dev->dev;
+		uart.port.irqflags	|= irqflag;
+		ret = serial8250_register_8250_port(&uart);
 		if (ret < 0) {
 			dev_err(&dev->dev, "unable to register port at index %d "
 				"(IO%lx MEM%llx IRQ%d): %d\n", i,
@@ -3081,7 +3085,7 @@ static struct platform_driver serial8250_isa_driver = {
 static struct platform_device *serial8250_isa_devs;
 
 /*
- * serial8250_register_port and serial8250_unregister_port allows for
+ * serial8250_register_8250_port and serial8250_unregister_port allows for
  * 16x50 serial ports to be configured at run-time, to support PCMCIA
  * modems and PCI multiport cards.
  */
@@ -3155,6 +3159,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 		uart->port.regshift     = up->port.regshift;
 		uart->port.iotype       = up->port.iotype;
 		uart->port.flags        = up->port.flags | UPF_BOOT_AUTOCONF;
+		uart->bugs		= up->bugs;
 		uart->port.mapbase      = up->port.mapbase;
 		uart->port.private_data = up->port.private_data;
 		if (up->port.dev)
@@ -3197,29 +3202,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 }
 EXPORT_SYMBOL(serial8250_register_8250_port);
 
-/**
- *	serial8250_register_port - register a serial port
- *	@port: serial port template
- *
- *	Configure the serial port specified by the request. If the
- *	port exists and is in use, it is hung up and unregistered
- *	first.
- *
- *	The port is then probed and if necessary the IRQ is autodetected
- *	If this fails an error is returned.
- *
- *	On success the port is ready to use and the line number is returned.
- */
-int serial8250_register_port(struct uart_port *port)
-{
-	struct uart_8250_port up;
-
-	memset(&up, 0, sizeof(up));
-	memcpy(&up.port, port, sizeof(*port));
-	return serial8250_register_8250_port(&up);
-}
-EXPORT_SYMBOL(serial8250_register_port);
-
 /**
  *	serial8250_unregister_port - remove a 16x50 serial port at runtime
  *	@line: serial line number

+ 1 - 33
drivers/tty/serial/8250/8250.h

@@ -13,36 +13,6 @@
 
 #include <linux/serial_8250.h>
 
-struct uart_8250_port {
-	struct uart_port	port;
-	struct timer_list	timer;		/* "no irq" timer */
-	struct list_head	list;		/* ports on this IRQ */
-	unsigned short		capabilities;	/* port capabilities */
-	unsigned short		bugs;		/* port bugs */
-	unsigned int		tx_loadsz;	/* transmit fifo load size */
-	unsigned char		acr;
-	unsigned char		ier;
-	unsigned char		lcr;
-	unsigned char		mcr;
-	unsigned char		mcr_mask;	/* mask of user bits */
-	unsigned char		mcr_force;	/* mask of forced bits */
-	unsigned char		cur_iotype;	/* Running I/O type */
-
-	/*
-	 * Some bits in registers are cleared on a read, so they must
-	 * be saved whenever the register is read but the bits will not
-	 * be immediately processed.
-	 */
-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
-	unsigned char		lsr_saved_flags;
-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
-	unsigned char		msr_saved_flags;
-
-	/* 8250 specific callbacks */
-	int			(*dl_read)(struct uart_8250_port *);
-	void			(*dl_write)(struct uart_8250_port *, int);
-};
-
 struct old_serial_port {
 	unsigned int uart;
 	unsigned int baud_base;
@@ -56,9 +26,6 @@ struct old_serial_port {
 	unsigned long irqflags;
 };
 
-/*
- * This replaces serial_uart_config in include/linux/serial.h
- */
 struct serial8250_config {
 	const char	*name;
 	unsigned short	fifo_size;
@@ -78,6 +45,7 @@ struct serial8250_config {
 #define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */
 #define UART_BUG_NOMSR	(1 << 2)	/* UART has buggy MSR status bits (Au1x00) */
 #define UART_BUG_THRE	(1 << 3)	/* UART has buggy THRE reassertion */
+#define UART_BUG_PARITY	(1 << 4)	/* UART mishandles parity if FIFO enabled */
 
 #define PROBE_RSA	(1 << 0)
 #define PROBE_ANY	(~0)

+ 11 - 11
drivers/tty/serial/8250/8250_acorn.c

@@ -43,7 +43,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
 	struct serial_card_info *info;
 	struct serial_card_type *type = id->data;
-	struct uart_port port;
+	struct uart_8250_port uart;
 	unsigned long bus_addr;
 	unsigned int i;
 
@@ -62,19 +62,19 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
 
 	ecard_set_drvdata(ec, info);
 
-	memset(&port, 0, sizeof(struct uart_port));
-	port.irq	= ec->irq;
-	port.flags	= UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
-	port.uartclk	= type->uartclk;
-	port.iotype	= UPIO_MEM;
-	port.regshift	= 2;
-	port.dev	= &ec->dev;
+	memset(&uart, 0, sizeof(struct uart_8250_port));
+	uart.port.irq	= ec->irq;
+	uart.port.flags	= UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	uart.port.uartclk	= type->uartclk;
+	uart.port.iotype	= UPIO_MEM;
+	uart.port.regshift	= 2;
+	uart.port.dev	= &ec->dev;
 
 	for (i = 0; i < info->num_ports; i ++) {
-		port.membase = info->vaddr + type->offset[i];
-		port.mapbase = bus_addr + type->offset[i];
+		uart.port.membase = info->vaddr + type->offset[i];
+		uart.port.mapbase = bus_addr + type->offset[i];
 
-		info->ports[i] = serial8250_register_port(&port);
+		info->ports[i] = serial8250_register_8250_port(&uart);
 	}
 
 	return 0;

+ 19 - 19
drivers/tty/serial/8250/8250_dw.c

@@ -89,7 +89,7 @@ static int dw8250_handle_irq(struct uart_port *p)
 
 static int __devinit dw8250_probe(struct platform_device *pdev)
 {
-	struct uart_port port = {};
+	struct uart_8250_port uart = {};
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	struct device_node *np = pdev->dev.of_node;
@@ -104,28 +104,28 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
-	port.private_data = data;
-
-	spin_lock_init(&port.lock);
-	port.mapbase = regs->start;
-	port.irq = irq->start;
-	port.handle_irq = dw8250_handle_irq;
-	port.type = PORT_8250;
-	port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+	uart.port.private_data = data;
+
+	spin_lock_init(&uart.port.lock);
+	uart.port.mapbase = regs->start;
+	uart.port.irq = irq->start;
+	uart.port.handle_irq = dw8250_handle_irq;
+	uart.port.type = PORT_8250;
+	uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
 		UPF_FIXED_PORT | UPF_FIXED_TYPE;
-	port.dev = &pdev->dev;
+	uart.port.dev = &pdev->dev;
 
-	port.iotype = UPIO_MEM;
-	port.serial_in = dw8250_serial_in;
-	port.serial_out = dw8250_serial_out;
+	uart.port.iotype = UPIO_MEM;
+	uart.port.serial_in = dw8250_serial_in;
+	uart.port.serial_out = dw8250_serial_out;
 	if (!of_property_read_u32(np, "reg-io-width", &val)) {
 		switch (val) {
 		case 1:
 			break;
 		case 4:
-			port.iotype = UPIO_MEM32;
-			port.serial_in = dw8250_serial_in32;
-			port.serial_out = dw8250_serial_out32;
+			uart.port.iotype = UPIO_MEM32;
+			uart.port.serial_in = dw8250_serial_in32;
+			uart.port.serial_out = dw8250_serial_out32;
 			break;
 		default:
 			dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
@@ -135,15 +135,15 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
 	}
 
 	if (!of_property_read_u32(np, "reg-shift", &val))
-		port.regshift = val;
+		uart.port.regshift = val;
 
 	if (of_property_read_u32(np, "clock-frequency", &val)) {
 		dev_err(&pdev->dev, "no clock-frequency property set\n");
 		return -EINVAL;
 	}
-	port.uartclk = val;
+	uart.port.uartclk = val;
 
-	data->line = serial8250_register_port(&port);
+	data->line = serial8250_register_8250_port(&uart);
 	if (data->line < 0)
 		return data->line;
 

+ 13 - 13
drivers/tty/serial/8250/8250_gsc.c

@@ -26,7 +26,7 @@
 
 static int __init serial_init_chip(struct parisc_device *dev)
 {
-	struct uart_port port;
+	struct uart_8250_port uart;
 	unsigned long address;
 	int err;
 
@@ -48,21 +48,21 @@ static int __init serial_init_chip(struct parisc_device *dev)
 	if (dev->id.sversion != 0x8d)
 		address += 0x800;
 
-	memset(&port, 0, sizeof(port));
-	port.iotype	= UPIO_MEM;
+	memset(&uart, 0, sizeof(uart));
+	uart.port.iotype	= UPIO_MEM;
 	/* 7.272727MHz on Lasi.  Assumed the same for Dino, Wax and Timi. */
-	port.uartclk	= 7272727;
-	port.mapbase	= address;
-	port.membase	= ioremap_nocache(address, 16);
-	port.irq	= dev->irq;
-	port.flags	= UPF_BOOT_AUTOCONF;
-	port.dev	= &dev->dev;
-
-	err = serial8250_register_port(&port);
+	uart.port.uartclk	= 7272727;
+	uart.port.mapbase	= address;
+	uart.port.membase	= ioremap_nocache(address, 16);
+	uart.port.irq	= dev->irq;
+	uart.port.flags	= UPF_BOOT_AUTOCONF;
+	uart.port.dev	= &dev->dev;
+
+	err = serial8250_register_8250_port(&uart);
 	if (err < 0) {
 		printk(KERN_WARNING
-			"serial8250_register_port returned error %d\n", err);
-		iounmap(port.membase);
+			"serial8250_register_8250_port returned error %d\n", err);
+		iounmap(uart.port.membase);
 		return err;
 	}
 

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

@@ -171,7 +171,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
 		return 0;
 	}
 #endif
-	memset(&port, 0, sizeof(struct uart_port));
+	memset(&uart, 0, sizeof(uart));
 
 	/* Memory mapped I/O */
 	port.iotype = UPIO_MEM;
@@ -182,7 +182,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
 	port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
 	port.regshift = 1;
 	port.dev = &d->dev;
-	line = serial8250_register_port(&port);
+	line = serial8250_register_8250_port(&uart);
 
 	if (line < 0) {
 		printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
@@ -210,7 +210,7 @@ static int __init hp300_8250_init(void)
 #ifdef CONFIG_HPAPCI
 	int line;
 	unsigned long base;
-	struct uart_port uport;
+	struct uart_8250_port uart;
 	struct hp300_port *port;
 	int i;
 #endif
@@ -248,26 +248,26 @@ static int __init hp300_8250_init(void)
 		if (!port)
 			return -ENOMEM;
 
-		memset(&uport, 0, sizeof(struct uart_port));
+		memset(&uart, 0, sizeof(uart));
 
 		base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
 
 		/* Memory mapped I/O */
-		uport.iotype = UPIO_MEM;
-		uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
+		uart.port.iotype = UPIO_MEM;
+		uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
 			      | UPF_BOOT_AUTOCONF;
 		/* XXX - no interrupt support yet */
-		uport.irq = 0;
-		uport.uartclk = HPAPCI_BAUD_BASE * 16;
-		uport.mapbase = base;
-		uport.membase = (char *)(base + DIO_VIRADDRBASE);
-		uport.regshift = 2;
+		uart.port.irq = 0;
+		uart.port.uartclk = HPAPCI_BAUD_BASE * 16;
+		uart.port.mapbase = base;
+		uart.port.membase = (char *)(base + DIO_VIRADDRBASE);
+		uart.port.regshift = 2;
 
-		line = serial8250_register_port(&uport);
+		line = serial8250_register_8250_port(&uart);
 
 		if (line < 0) {
 			printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
-			       " %d irq %d failed\n", i, uport.irq);
+			       " %d irq %d failed\n", i, uart.port.irq);
 			kfree(port);
 			continue;
 		}

+ 139 - 66
drivers/tty/serial/8250/8250_pci.c

@@ -44,7 +44,7 @@ struct pci_serial_quirk {
 	int	(*init)(struct pci_dev *dev);
 	int	(*setup)(struct serial_private *,
 			 const struct pciserial_board *,
-			 struct uart_port *, int);
+			 struct uart_8250_port *, int);
 	void	(*exit)(struct pci_dev *dev);
 };
 
@@ -59,7 +59,7 @@ struct serial_private {
 };
 
 static int pci_default_setup(struct serial_private*,
-	  const struct pciserial_board*, struct uart_port*, int);
+	  const struct pciserial_board*, struct uart_8250_port *, int);
 
 static void moan_device(const char *str, struct pci_dev *dev)
 {
@@ -74,7 +74,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
 }
 
 static int
-setup_port(struct serial_private *priv, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_8250_port *port,
 	   int bar, int offset, int regshift)
 {
 	struct pci_dev *dev = priv->dev;
@@ -93,17 +93,17 @@ setup_port(struct serial_private *priv, struct uart_port *port,
 		if (!priv->remapped_bar[bar])
 			return -ENOMEM;
 
-		port->iotype = UPIO_MEM;
-		port->iobase = 0;
-		port->mapbase = base + offset;
-		port->membase = priv->remapped_bar[bar] + offset;
-		port->regshift = regshift;
+		port->port.iotype = UPIO_MEM;
+		port->port.iobase = 0;
+		port->port.mapbase = base + offset;
+		port->port.membase = priv->remapped_bar[bar] + offset;
+		port->port.regshift = regshift;
 	} else {
-		port->iotype = UPIO_PORT;
-		port->iobase = base + offset;
-		port->mapbase = 0;
-		port->membase = NULL;
-		port->regshift = 0;
+		port->port.iotype = UPIO_PORT;
+		port->port.iobase = base + offset;
+		port->port.mapbase = 0;
+		port->port.membase = NULL;
+		port->port.regshift = 0;
 	}
 	return 0;
 }
@@ -113,7 +113,7 @@ setup_port(struct serial_private *priv, struct uart_port *port,
  */
 static int addidata_apci7800_setup(struct serial_private *priv,
 				const struct pciserial_board *board,
-				struct uart_port *port, int idx)
+				struct uart_8250_port *port, int idx)
 {
 	unsigned int bar = 0, offset = board->first_offset;
 	bar = FL_GET_BASE(board->flags);
@@ -140,7 +140,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,
  */
 static int
 afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
-	      struct uart_port *port, int idx)
+	      struct uart_8250_port *port, int idx)
 {
 	unsigned int bar, offset = board->first_offset;
 
@@ -195,7 +195,7 @@ static int pci_hp_diva_init(struct pci_dev *dev)
 static int
 pci_hp_diva_setup(struct serial_private *priv,
 		const struct pciserial_board *board,
-		struct uart_port *port, int idx)
+		struct uart_8250_port *port, int idx)
 {
 	unsigned int offset = board->first_offset;
 	unsigned int bar = FL_GET_BASE(board->flags);
@@ -370,7 +370,7 @@ static void __devexit pci_ni8430_exit(struct pci_dev *dev)
 /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
 static int
 sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
-		struct uart_port *port, int idx)
+		struct uart_8250_port *port, int idx)
 {
 	unsigned int bar, offset = board->first_offset;
 
@@ -525,7 +525,7 @@ static int pci_siig_init(struct pci_dev *dev)
 
 static int pci_siig_setup(struct serial_private *priv,
 			  const struct pciserial_board *board,
-			  struct uart_port *port, int idx)
+			  struct uart_8250_port *port, int idx)
 {
 	unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
 
@@ -619,7 +619,7 @@ static int pci_timedia_init(struct pci_dev *dev)
 static int
 pci_timedia_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
-		  struct uart_port *port, int idx)
+		  struct uart_8250_port *port, int idx)
 {
 	unsigned int bar = 0, offset = board->first_offset;
 
@@ -653,7 +653,7 @@ pci_timedia_setup(struct serial_private *priv,
 static int
 titan_400l_800l_setup(struct serial_private *priv,
 		      const struct pciserial_board *board,
-		      struct uart_port *port, int idx)
+		      struct uart_8250_port *port, int idx)
 {
 	unsigned int bar, offset = board->first_offset;
 
@@ -754,7 +754,7 @@ static int pci_ni8430_init(struct pci_dev *dev)
 static int
 pci_ni8430_setup(struct serial_private *priv,
 		 const struct pciserial_board *board,
-		 struct uart_port *port, int idx)
+		 struct uart_8250_port *port, int idx)
 {
 	void __iomem *p;
 	unsigned long base, len;
@@ -781,7 +781,7 @@ pci_ni8430_setup(struct serial_private *priv,
 
 static int pci_netmos_9900_setup(struct serial_private *priv,
 				const struct pciserial_board *board,
-				struct uart_port *port, int idx)
+				struct uart_8250_port *port, int idx)
 {
 	unsigned int bar;
 
@@ -1032,10 +1032,17 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
 	return number_uarts;
 }
 
-static int
-pci_default_setup(struct serial_private *priv,
+static int pci_asix_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
-		  struct uart_port *port, int idx)
+		  struct uart_8250_port *port, int idx)
+{
+	port->bugs |= UART_BUG_PARITY;
+	return pci_default_setup(priv, board, port, idx);
+}
+
+static int pci_default_setup(struct serial_private *priv,
+		  const struct pciserial_board *board,
+		  struct uart_8250_port *port, int idx)
 {
 	unsigned int bar, offset = board->first_offset, maxnr;
 
@@ -1057,15 +1064,15 @@ pci_default_setup(struct serial_private *priv,
 static int
 ce4100_serial_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
-		  struct uart_port *port, int idx)
+		  struct uart_8250_port *port, int idx)
 {
 	int ret;
 
 	ret = setup_port(priv, port, 0, 0, board->reg_shift);
-	port->iotype = UPIO_MEM32;
-	port->type = PORT_XSCALE;
-	port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
-	port->regshift = 2;
+	port->port.iotype = UPIO_MEM32;
+	port->port.type = PORT_XSCALE;
+	port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+	port->port.regshift = 2;
 
 	return ret;
 }
@@ -1073,16 +1080,16 @@ ce4100_serial_setup(struct serial_private *priv,
 static int
 pci_omegapci_setup(struct serial_private *priv,
 		      const struct pciserial_board *board,
-		      struct uart_port *port, int idx)
+		      struct uart_8250_port *port, int idx)
 {
 	return setup_port(priv, port, 2, idx * 8, 0);
 }
 
 static int skip_tx_en_setup(struct serial_private *priv,
 			const struct pciserial_board *board,
-			struct uart_port *port, int idx)
+			struct uart_8250_port *port, int idx)
 {
-	port->flags |= UPF_NO_TXEN_TEST;
+	port->port.flags |= UPF_NO_TXEN_TEST;
 	printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
 			  "[%04x:%04x] subsystem [%04x:%04x]\n",
 			  priv->dev->vendor,
@@ -1131,11 +1138,11 @@ static unsigned int kt_serial_in(struct uart_port *p, int offset)
 
 static int kt_serial_setup(struct serial_private *priv,
 			   const struct pciserial_board *board,
-			   struct uart_port *port, int idx)
+			   struct uart_8250_port *port, int idx)
 {
-	port->flags |= UPF_BUG_THRE;
-	port->serial_in = kt_serial_in;
-	port->handle_break = kt_handle_break;
+	port->port.flags |= UPF_BUG_THRE;
+	port->port.serial_in = kt_serial_in;
+	port->port.handle_break = kt_handle_break;
 	return skip_tx_en_setup(priv, board, port, idx);
 }
 
@@ -1151,9 +1158,19 @@ static int pci_eg20t_init(struct pci_dev *dev)
 static int
 pci_xr17c154_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
-		  struct uart_port *port, int idx)
+		  struct uart_8250_port *port, int idx)
+{
+	port->port.flags |= UPF_EXAR_EFR;
+	return pci_default_setup(priv, board, port, idx);
+}
+
+static int
+pci_wch_ch353_setup(struct serial_private *priv,
+                    const struct pciserial_board *board,
+                    struct uart_8250_port *port, int idx)
 {
-	port->flags |= UPF_EXAR_EFR;
+	port->port.flags |= UPF_FIXED_TYPE;
+	port->port.type = PORT_16550A;
 	return pci_default_setup(priv, board, port, idx);
 }
 
@@ -1187,6 +1204,13 @@ pci_xr17c154_setup(struct serial_private *priv,
 #define PCIE_DEVICE_ID_NEO_2_OX_IBM	0x00F6
 #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA	0xc001
 #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+#define PCI_VENDOR_ID_WCH		0x4348
+#define PCI_DEVICE_ID_WCH_CH353_4S	0x3453
+#define PCI_DEVICE_ID_WCH_CH353_2S1PF	0x5046
+#define PCI_DEVICE_ID_WCH_CH353_2S1P	0x7053
+#define PCI_VENDOR_ID_AGESTAR		0x5372
+#define PCI_DEVICE_ID_AGESTAR_9375	0x6872
+#define PCI_VENDOR_ID_ASIX		0x9710
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584	0x1584
@@ -1726,7 +1750,41 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.setup		= pci_omegapci_setup,
-	 },
+	},
+	/* WCH CH353 2S1P card (16550 clone) */
+	{
+		.vendor         = PCI_VENDOR_ID_WCH,
+		.device         = PCI_DEVICE_ID_WCH_CH353_2S1P,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = pci_wch_ch353_setup,
+	},
+	/* WCH CH353 4S card (16550 clone) */
+	{
+		.vendor         = PCI_VENDOR_ID_WCH,
+		.device         = PCI_DEVICE_ID_WCH_CH353_4S,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = pci_wch_ch353_setup,
+	},
+	/* WCH CH353 2S1PF card (16550 clone) */
+	{
+		.vendor         = PCI_VENDOR_ID_WCH,
+		.device         = PCI_DEVICE_ID_WCH_CH353_2S1PF,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = pci_wch_ch353_setup,
+	},
+	/*
+	 * ASIX devices with FIFO bug
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_ASIX,
+		.device		= PCI_ANY_ID,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_asix_setup,
+	},
 	/*
 	 * Default "match everything" terminator entry
 	 */
@@ -1887,7 +1945,6 @@ enum pci_board_num_t {
 	pbn_panacom,
 	pbn_panacom2,
 	pbn_panacom4,
-	pbn_exsys_4055,
 	pbn_plx_romulus,
 	pbn_oxsemi,
 	pbn_oxsemi_1_4000000,
@@ -2393,13 +2450,6 @@ static struct pciserial_board pci_boards[] __devinitdata = {
 		.reg_shift	= 7,
 	},
 
-	[pbn_exsys_4055] = {
-		.flags		= FL_BASE2,
-		.num_ports	= 4,
-		.base_baud	= 115200,
-		.uart_offset	= 8,
-	},
-
 	/* I think this entry is broken - the first_offset looks wrong --rmk */
 	[pbn_plx_romulus] = {
 		.flags		= FL_BASE2,
@@ -2624,10 +2674,14 @@ static struct pciserial_board pci_boards[] __devinitdata = {
 	},
 };
 
-static const struct pci_device_id softmodem_blacklist[] = {
+static const struct pci_device_id blacklist[] = {
+	/* softmodems */
 	{ PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
 	{ PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
 	{ PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
+
+	/* multi-io cards handled by parport_serial */
+	{ PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
 };
 
 /*
@@ -2638,7 +2692,7 @@ static const struct pci_device_id softmodem_blacklist[] = {
 static int __devinit
 serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
-	const struct pci_device_id *blacklist;
+	const struct pci_device_id *bldev;
 	int num_iomem, num_port, first_port = -1, i;
 
 	/*
@@ -2655,13 +2709,13 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 
 	/*
 	 * Do not access blacklisted devices that are known not to
-	 * feature serial ports.
+	 * feature serial ports or are handled by other modules.
 	 */
-	for (blacklist = softmodem_blacklist;
-	     blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
-	     blacklist++) {
-		if (dev->vendor == blacklist->vendor &&
-		    dev->device == blacklist->device)
+	for (bldev = blacklist;
+	     bldev < blacklist + ARRAY_SIZE(blacklist);
+	     bldev++) {
+		if (dev->vendor == bldev->vendor &&
+		    dev->device == bldev->device)
 			return -ENODEV;
 	}
 
@@ -2728,7 +2782,7 @@ serial_pci_matches(const struct pciserial_board *board,
 struct serial_private *
 pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
 {
-	struct uart_port serial_port;
+	struct uart_8250_port uart;
 	struct serial_private *priv;
 	struct pci_serial_quirk *quirk;
 	int rc, nr_ports, i;
@@ -2768,22 +2822,22 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
 	priv->dev = dev;
 	priv->quirk = quirk;
 
-	memset(&serial_port, 0, sizeof(struct uart_port));
-	serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
-	serial_port.uartclk = board->base_baud * 16;
-	serial_port.irq = get_pci_irq(dev, board);
-	serial_port.dev = &dev->dev;
+	memset(&uart, 0, sizeof(uart));
+	uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	uart.port.uartclk = board->base_baud * 16;
+	uart.port.irq = get_pci_irq(dev, board);
+	uart.port.dev = &dev->dev;
 
 	for (i = 0; i < nr_ports; i++) {
-		if (quirk->setup(priv, board, &serial_port, i))
+		if (quirk->setup(priv, board, &uart, i))
 			break;
 
 #ifdef SERIAL_DEBUG_PCI
 		printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
-		       serial_port.iobase, serial_port.irq, serial_port.iotype);
+		       uart.port.iobase, uart.port.irq, uart.port.iotype);
 #endif
 
-		priv->line[i] = serial8250_register_port(&serial_port);
+		priv->line[i] = serial8250_register_8250_port(&uart);
 		if (priv->line[i] < 0) {
 			printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
 			break;
@@ -3193,7 +3247,7 @@ static struct pci_device_id serial_pci_tbl[] = {
 	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 		PCI_SUBVENDOR_ID_EXSYS,
 		PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
-		pbn_exsys_4055 },
+		pbn_b2_4_115200 },
 	/*
 	 * Megawolf Romulus PCI Serial Card, from Mike Hudson
 	 * (Exoray@isys.ca)
@@ -4178,6 +4232,25 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_omegapci },
 
+	/*
+	 * AgeStar as-prs2-009
+	 */
+	{	PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_b0_bt_2_115200 },
+
+	/*
+	 * WCH CH353 series devices: The 2S1P is handled by parport_serial
+	 * so not listed here.
+	 */
+	{	PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_4S,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_b0_bt_4_115200 },
+
+	{	PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_2S1PF,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_b0_bt_2_115200 },
+
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL

+ 14 - 14
drivers/tty/serial/8250/8250_pnp.c

@@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
 static int __devinit
 serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
-	struct uart_port port;
+	struct uart_8250_port uart;
 	int ret, line, flags = dev_id->driver_data;
 
 	if (flags & UNKNOWN_DEV) {
@@ -433,32 +433,32 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 			return ret;
 	}
 
-	memset(&port, 0, sizeof(struct uart_port));
+	memset(&uart, 0, sizeof(uart));
 	if (pnp_irq_valid(dev, 0))
-		port.irq = pnp_irq(dev, 0);
+		uart.port.irq = pnp_irq(dev, 0);
 	if (pnp_port_valid(dev, 0)) {
-		port.iobase = pnp_port_start(dev, 0);
-		port.iotype = UPIO_PORT;
+		uart.port.iobase = pnp_port_start(dev, 0);
+		uart.port.iotype = UPIO_PORT;
 	} else if (pnp_mem_valid(dev, 0)) {
-		port.mapbase = pnp_mem_start(dev, 0);
-		port.iotype = UPIO_MEM;
-		port.flags = UPF_IOREMAP;
+		uart.port.mapbase = pnp_mem_start(dev, 0);
+		uart.port.iotype = UPIO_MEM;
+		uart.port.flags = UPF_IOREMAP;
 	} else
 		return -ENODEV;
 
 #ifdef SERIAL_DEBUG_PNP
 	printk(KERN_DEBUG
 		"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
-		       port.iobase, port.mapbase, port.irq, port.iotype);
+		       uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype);
 #endif
 
-	port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+	uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
 	if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
-		port.flags |= UPF_SHARE_IRQ;
-	port.uartclk = 1843200;
-	port.dev = &dev->dev;
+		uart.port.flags |= UPF_SHARE_IRQ;
+	uart.port.uartclk = 1843200;
+	uart.port.dev = &dev->dev;
 
-	line = serial8250_register_port(&port);
+	line = serial8250_register_8250_port(&uart);
 	if (line < 0)
 		return -ENODEV;
 

+ 15 - 15
drivers/tty/serial/8250/serial_cs.c

@@ -73,7 +73,7 @@ struct serial_quirk {
 	unsigned int prodid;
 	int multi;		/* 1 = multifunction, > 1 = # ports */
 	void (*config)(struct pcmcia_device *);
-	void (*setup)(struct pcmcia_device *, struct uart_port *);
+	void (*setup)(struct pcmcia_device *, struct uart_8250_port *);
 	void (*wakeup)(struct pcmcia_device *);
 	int (*post)(struct pcmcia_device *);
 };
@@ -105,9 +105,9 @@ struct serial_cfg_mem {
  * Elan VPU16551 UART with 14.7456MHz oscillator
  * manfid 0x015D, 0x4C45
  */
-static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
+static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_8250_port *uart)
 {
-	port->uartclk = 14745600;
+	uart->port.uartclk = 14745600;
 }
 
 static int quirk_post_ibm(struct pcmcia_device *link)
@@ -343,25 +343,25 @@ static void serial_detach(struct pcmcia_device *link)
 static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
 			unsigned int iobase, int irq)
 {
-	struct uart_port port;
+	struct uart_8250_port uart;
 	int line;
 
-	memset(&port, 0, sizeof (struct uart_port));
-	port.iobase = iobase;
-	port.irq = irq;
-	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
-	port.uartclk = 1843200;
-	port.dev = &handle->dev;
+	memset(&uart, 0, sizeof(uart));
+	uart.port.iobase = iobase;
+	uart.port.irq = irq;
+	uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+	uart.port.uartclk = 1843200;
+	uart.port.dev = &handle->dev;
 	if (buggy_uart)
-		port.flags |= UPF_BUGGY_UART;
+		uart.port.flags |= UPF_BUGGY_UART;
 
 	if (info->quirk && info->quirk->setup)
-		info->quirk->setup(handle, &port);
+		info->quirk->setup(handle, &uart);
 
-	line = serial8250_register_port(&port);
+	line = serial8250_register_8250_port(&uart);
 	if (line < 0) {
-		printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
-		       "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
+		pr_err("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n",
+							(unsigned long)iobase, irq);
 		return -EINVAL;
 	}
 

+ 47 - 3
drivers/tty/serial/Kconfig

@@ -257,12 +257,19 @@ config SERIAL_MAX3100
 	help
 	  MAX3100 chip support
 
-config SERIAL_MAX3107
-	tristate "MAX3107 support"
+config SERIAL_MAX310X
+	bool "MAX310X support"
 	depends on SPI
 	select SERIAL_CORE
+	select REGMAP_SPI if SPI
+	default n
 	help
-	  MAX3107 chip support
+	  This selects support for an advanced UART from Maxim (Dallas).
+	  Supported ICs are MAX3107, MAX3108.
+	  Each IC contains 128 words each of receive and transmit FIFO
+	  that can be controlled through I2C or high-speed SPI.
+
+	  Say Y here if you want to support this ICs.
 
 config SERIAL_DZ
 	bool "DECstation DZ serial driver"
@@ -704,6 +711,25 @@ config SERIAL_PNX8XXX_CONSOLE
 	  If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
 	  and you want to use serial console, say Y. Otherwise, say N.
 
+config SERIAL_HS_LPC32XX
+	tristate "LPC32XX high speed serial port support"
+	depends on ARCH_LPC32XX && OF
+	select SERIAL_CORE
+	help
+	  Support for the LPC32XX high speed serial ports (up to 900kbps).
+	  Those are UARTs completely different from the Standard UARTs on the
+	  LPC32XX SoC.
+	  Choose M or Y here to build this driver.
+
+config SERIAL_HS_LPC32XX_CONSOLE
+	bool "Enable LPC32XX high speed UART serial console"
+	depends on SERIAL_HS_LPC32XX
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you would like to be able to use one of the high speed serial
+	  ports on the LPC32XX as the console, you can do so by answering
+	  Y to this option.
+
 config SERIAL_CORE
 	tristate
 
@@ -1104,6 +1130,24 @@ config SERIAL_SC26XX_CONSOLE
 	help
 	  Support for Console on SC2681/SC2692 serial ports.
 
+config SERIAL_SCCNXP
+	bool "SCCNXP serial port support"
+	depends on !SERIAL_SC26XX
+	select SERIAL_CORE
+	default n
+	help
+	  This selects support for an advanced UART from NXP (Philips).
+	  Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92,
+	  SC28L202, SCC68681 and SCC68692.
+	  Positioned as a replacement for the driver SC26XX.
+
+config SERIAL_SCCNXP_CONSOLE
+	bool "Console on SCCNXP serial port"
+	depends on SERIAL_SCCNXP
+	select SERIAL_CORE_CONSOLE
+	help
+	  Support for console on SCCNXP serial ports.
+
 config SERIAL_BFIN_SPORT
 	tristate "Blackfin SPORT emulate UART"
 	depends on BLACKFIN

+ 3 - 1
drivers/tty/serial/Makefile

@@ -28,12 +28,13 @@ obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o
 obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
 obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
-obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
+obj-$(CONFIG_SERIAL_MAX310X) += max310x.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
 obj-$(CONFIG_SERIAL_MCF) += mcf.o
 obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
+obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o
 obj-$(CONFIG_SERIAL_DZ) += dz.o
 obj-$(CONFIG_SERIAL_ZS) += zs.o
 obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
@@ -47,6 +48,7 @@ obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
 obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
+obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o

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

@@ -591,7 +591,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 	port->ops = &altera_uart_ops;
 	port->flags = UPF_BOOT_AUTOCONF;
 
-	dev_set_drvdata(&pdev->dev, port);
+	platform_set_drvdata(pdev, port);
 
 	uart_add_one_port(&altera_uart_driver, port);
 
@@ -600,11 +600,11 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 
 static int __devexit altera_uart_remove(struct platform_device *pdev)
 {
-	struct uart_port *port = dev_get_drvdata(&pdev->dev);
+	struct uart_port *port = platform_get_drvdata(pdev);
 
 	if (port) {
 		uart_remove_one_port(&altera_uart_driver, port);
-		dev_set_drvdata(&pdev->dev, NULL);
+		platform_set_drvdata(pdev, NULL);
 		port->mapbase = 0;
 	}
 

+ 4 - 11
drivers/tty/serial/amba-pl010.c

@@ -312,16 +312,12 @@ static int pl010_startup(struct uart_port *port)
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 	int retval;
 
-	retval = clk_prepare(uap->clk);
-	if (retval)
-		goto out;
-
 	/*
 	 * Try to enable the clock producer.
 	 */
-	retval = clk_enable(uap->clk);
+	retval = clk_prepare_enable(uap->clk);
 	if (retval)
-		goto clk_unprep;
+		goto out;
 
 	uap->port.uartclk = clk_get_rate(uap->clk);
 
@@ -346,9 +342,7 @@ static int pl010_startup(struct uart_port *port)
 	return 0;
 
  clk_dis:
-	clk_disable(uap->clk);
- clk_unprep:
-	clk_unprepare(uap->clk);
+	clk_disable_unprepare(uap->clk);
  out:
 	return retval;
 }
@@ -375,8 +369,7 @@ static void pl010_shutdown(struct uart_port *port)
 	/*
 	 * Shut down the clock producer
 	 */
-	clk_disable(uap->clk);
-	clk_unprepare(uap->clk);
+	clk_disable_unprepare(uap->clk);
 }
 
 static void

+ 57 - 32
drivers/tty/serial/amba-pl011.c

@@ -52,6 +52,8 @@
 #include <linux/scatterlist.h>
 #include <linux/delay.h>
 #include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/sizes.h>
 
@@ -75,7 +77,6 @@ struct vendor_data {
 	unsigned int		lcrh_tx;
 	unsigned int		lcrh_rx;
 	bool			oversampling;
-	bool			interrupt_may_hang;   /* vendor-specific */
 	bool			dma_threshold;
 	bool			cts_event_workaround;
 };
@@ -96,7 +97,6 @@ static struct vendor_data vendor_st = {
 	.lcrh_tx		= ST_UART011_LCRH_TX,
 	.lcrh_rx		= ST_UART011_LCRH_RX,
 	.oversampling		= true,
-	.interrupt_may_hang	= true,
 	.dma_threshold		= true,
 	.cts_event_workaround	= true,
 };
@@ -147,7 +147,6 @@ struct uart_amba_port {
 	unsigned int		old_cr;		/* state during shutdown */
 	bool			autorts;
 	char			type[12];
-	bool			interrupt_may_hang; /* vendor-specific */
 #ifdef CONFIG_DMA_ENGINE
 	/* DMA stuff */
 	bool			using_tx_dma;
@@ -1215,14 +1214,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	return IRQ_RETVAL(handled);
 }
 
-static unsigned int pl01x_tx_empty(struct uart_port *port)
+static unsigned int pl011_tx_empty(struct uart_port *port)
 {
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 	unsigned int status = readw(uap->port.membase + UART01x_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
-static unsigned int pl01x_get_mctrl(struct uart_port *port)
+static unsigned int pl011_get_mctrl(struct uart_port *port)
 {
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 	unsigned int result = 0;
@@ -1285,7 +1284,7 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
 }
 
 #ifdef CONFIG_CONSOLE_POLL
-static int pl010_get_poll_char(struct uart_port *port)
+static int pl011_get_poll_char(struct uart_port *port)
 {
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 	unsigned int status;
@@ -1297,7 +1296,7 @@ static int pl010_get_poll_char(struct uart_port *port)
 	return readw(uap->port.membase + UART01x_DR);
 }
 
-static void pl010_put_poll_char(struct uart_port *port,
+static void pl011_put_poll_char(struct uart_port *port,
 			 unsigned char ch)
 {
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -1324,16 +1323,12 @@ static int pl011_startup(struct uart_port *port)
 				"could not set default pins\n");
 	}
 
-	retval = clk_prepare(uap->clk);
-	if (retval)
-		goto out;
-
 	/*
 	 * Try to enable the clock producer.
 	 */
-	retval = clk_enable(uap->clk);
+	retval = clk_prepare_enable(uap->clk);
 	if (retval)
-		goto clk_unprep;
+		goto out;
 
 	uap->port.uartclk = clk_get_rate(uap->clk);
 
@@ -1411,9 +1406,7 @@ static int pl011_startup(struct uart_port *port)
 	return 0;
 
  clk_dis:
-	clk_disable(uap->clk);
- clk_unprep:
-	clk_unprepare(uap->clk);
+	clk_disable_unprepare(uap->clk);
  out:
 	return retval;
 }
@@ -1473,8 +1466,7 @@ static void pl011_shutdown(struct uart_port *port)
 	/*
 	 * Shut down the clock producer
 	 */
-	clk_disable(uap->clk);
-	clk_unprepare(uap->clk);
+	clk_disable_unprepare(uap->clk);
 	/* Optionally let pins go into sleep states */
 	if (!IS_ERR(uap->pins_sleep)) {
 		retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep);
@@ -1637,7 +1629,7 @@ static const char *pl011_type(struct uart_port *port)
 /*
  * Release the memory region(s) being used by 'port'
  */
-static void pl010_release_port(struct uart_port *port)
+static void pl011_release_port(struct uart_port *port)
 {
 	release_mem_region(port->mapbase, SZ_4K);
 }
@@ -1645,7 +1637,7 @@ static void pl010_release_port(struct uart_port *port)
 /*
  * Request the memory region(s) being used by 'port'
  */
-static int pl010_request_port(struct uart_port *port)
+static int pl011_request_port(struct uart_port *port)
 {
 	return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")
 			!= NULL ? 0 : -EBUSY;
@@ -1654,18 +1646,18 @@ static int pl010_request_port(struct uart_port *port)
 /*
  * Configure/autoconfigure the port.
  */
-static void pl010_config_port(struct uart_port *port, int flags)
+static void pl011_config_port(struct uart_port *port, int flags)
 {
 	if (flags & UART_CONFIG_TYPE) {
 		port->type = PORT_AMBA;
-		pl010_request_port(port);
+		pl011_request_port(port);
 	}
 }
 
 /*
  * verify the new serial_struct (for TIOCSSERIAL).
  */
-static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
+static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
 	int ret = 0;
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
@@ -1678,9 +1670,9 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
 }
 
 static struct uart_ops amba_pl011_pops = {
-	.tx_empty	= pl01x_tx_empty,
+	.tx_empty	= pl011_tx_empty,
 	.set_mctrl	= pl011_set_mctrl,
-	.get_mctrl	= pl01x_get_mctrl,
+	.get_mctrl	= pl011_get_mctrl,
 	.stop_tx	= pl011_stop_tx,
 	.start_tx	= pl011_start_tx,
 	.stop_rx	= pl011_stop_rx,
@@ -1691,13 +1683,13 @@ static struct uart_ops amba_pl011_pops = {
 	.flush_buffer	= pl011_dma_flush_buffer,
 	.set_termios	= pl011_set_termios,
 	.type		= pl011_type,
-	.release_port	= pl010_release_port,
-	.request_port	= pl010_request_port,
-	.config_port	= pl010_config_port,
-	.verify_port	= pl010_verify_port,
+	.release_port	= pl011_release_port,
+	.request_port	= pl011_request_port,
+	.config_port	= pl011_config_port,
+	.verify_port	= pl011_verify_port,
 #ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char = pl010_get_poll_char,
-	.poll_put_char = pl010_put_poll_char,
+	.poll_get_char = pl011_get_poll_char,
+	.poll_put_char = pl011_put_poll_char,
 #endif
 };
 
@@ -1869,6 +1861,38 @@ static struct uart_driver amba_reg = {
 	.cons			= AMBA_CONSOLE,
 };
 
+static int pl011_probe_dt_alias(int index, struct device *dev)
+{
+	struct device_node *np;
+	static bool seen_dev_with_alias = false;
+	static bool seen_dev_without_alias = false;
+	int ret = index;
+
+	if (!IS_ENABLED(CONFIG_OF))
+		return ret;
+
+	np = dev->of_node;
+	if (!np)
+		return ret;
+
+	ret = of_alias_get_id(np, "serial");
+	if (IS_ERR_VALUE(ret)) {
+		seen_dev_without_alias = true;
+		ret = index;
+	} else {
+		seen_dev_with_alias = true;
+		if (ret >= ARRAY_SIZE(amba_ports) || amba_ports[ret] != NULL) {
+			dev_warn(dev, "requested serial port %d  not available.\n", ret);
+			ret = index;
+		}
+	}
+
+	if (seen_dev_with_alias && seen_dev_without_alias)
+		dev_warn(dev, "aliased and non-aliased serial devices found in device tree. Serial port enumeration may be unpredictable.\n");
+
+	return ret;
+}
+
 static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct uart_amba_port *uap;
@@ -1891,6 +1915,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		goto out;
 	}
 
+	i = pl011_probe_dt_alias(i, &dev->dev);
+
 	base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!base) {
 		ret = -ENOMEM;
@@ -1923,7 +1949,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	uap->lcrh_tx = vendor->lcrh_tx;
 	uap->old_cr = 0;
 	uap->fifosize = vendor->fifosize;
-	uap->interrupt_may_hang = vendor->interrupt_may_hang;
 	uap->port.dev = &dev->dev;
 	uap->port.mapbase = dev->res.start;
 	uap->port.membase = base;

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

@@ -182,7 +182,7 @@ static void bfin_serial_start_tx(struct uart_port *port)
 	 * To avoid losting RX interrupt, we reset IR function
 	 * before sending data.
 	 */
-	if (tty->termios->c_line == N_IRDA)
+	if (tty->termios.c_line == N_IRDA)
 		bfin_serial_reset_irda(port);
 
 #ifdef CONFIG_SERIAL_BFIN_DMA

+ 24 - 21
drivers/tty/serial/crisv10.c

@@ -955,7 +955,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] =
 /* Calculate the chartime depending on baudrate, numbor of bits etc. */
 static void update_char_time(struct e100_serial * info)
 {
-	tcflag_t cflags = info->port.tty->termios->c_cflag;
+	tcflag_t cflags = info->port.tty->termios.c_cflag;
 	int bits;
 
 	/* calc. number of bits / data byte */
@@ -1473,7 +1473,7 @@ rs_stop(struct tty_struct *tty)
 		xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char,
 				STOP_CHAR(info->port.tty));
 		xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop);
-		if (tty->termios->c_iflag & IXON ) {
+		if (tty->termios.c_iflag & IXON ) {
 			xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
 		}
 
@@ -1496,7 +1496,7 @@ rs_start(struct tty_struct *tty)
 					 info->xmit.tail,SERIAL_XMIT_SIZE)));
 		xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty));
 		xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
-		if (tty->termios->c_iflag & IXON ) {
+		if (tty->termios.c_iflag & IXON ) {
 			xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
 		}
 
@@ -2929,7 +2929,7 @@ shutdown(struct e100_serial * info)
 			descr[i].buf = 0;
 		}
 
-	if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
+	if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) {
 		/* hang up DTR and RTS if HUPCL is enabled */
 		e100_dtr(info, 0);
 		e100_rts(info, 0); /* could check CRTSCTS before doing this */
@@ -2953,12 +2953,12 @@ change_speed(struct e100_serial *info)
 	unsigned long flags;
 	/* first some safety checks */
 
-	if (!info->port.tty || !info->port.tty->termios)
+	if (!info->port.tty)
 		return;
 	if (!info->ioport)
 		return;
 
-	cflag = info->port.tty->termios->c_cflag;
+	cflag = info->port.tty->termios.c_cflag;
 
 	/* possibly, the tx/rx should be disabled first to do this safely */
 
@@ -3088,7 +3088,7 @@ change_speed(struct e100_serial *info)
 	info->ioport[REG_REC_CTRL] = info->rx_ctrl;
 	xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty));
 	xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
-	if (info->port.tty->termios->c_iflag & IXON ) {
+	if (info->port.tty->termios.c_iflag & IXON ) {
 		DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n",
 				STOP_CHAR(info->port.tty)));
 		xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
@@ -3355,7 +3355,7 @@ rs_throttle(struct tty_struct * tty)
 	DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty)));
 
 	/* Do RTS before XOFF since XOFF might take some time */
-	if (tty->termios->c_cflag & CRTSCTS) {
+	if (tty->termios.c_cflag & CRTSCTS) {
 		/* Turn off RTS line */
 		e100_rts(info, 0);
 	}
@@ -3377,7 +3377,7 @@ rs_unthrottle(struct tty_struct * tty)
 	DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty)));
 	DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count));
 	/* Do RTS before XOFF since XOFF might take some time */
-	if (tty->termios->c_cflag & CRTSCTS) {
+	if (tty->termios.c_cflag & CRTSCTS) {
 		/* Assert RTS line  */
 		e100_rts(info, 1);
 	}
@@ -3748,7 +3748,7 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		rs_start(tty);
 	}
@@ -3815,7 +3815,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
 	 * separate termios for callout and dialin.
 	 */
 	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
+		info->normal_termios = tty->termios;
 	/*
 	 * Now we wait for the transmit buffer to clear; and we notify
 	 * the line discipline to only process XON/XOFF characters.
@@ -3976,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	 */
 	if (tty_hung_up_p(filp) ||
 	    (info->flags & ASYNC_CLOSING)) {
-		wait_event_interruptible_tty(info->close_wait,
+		wait_event_interruptible_tty(tty, info->close_wait,
 			!(info->flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
 		if (info->flags & ASYNC_HUP_NOTIFY)
@@ -3998,7 +3998,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 		return 0;
 	}
 
-	if (tty->termios->c_cflag & CLOCAL) {
+	if (tty->termios.c_cflag & CLOCAL) {
 			do_clocal = 1;
 	}
 
@@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 		printk("block_til_ready blocking: ttyS%d, count = %d\n",
 		       info->line, info->count);
 #endif
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&info->open_wait, &wait);
@@ -4115,7 +4115,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
 	 */
 	if (tty_hung_up_p(filp) ||
 	    (info->flags & ASYNC_CLOSING)) {
-		wait_event_interruptible_tty(info->close_wait,
+		wait_event_interruptible_tty(tty, info->close_wait,
 			!(info->flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
 		return ((info->flags & ASYNC_HUP_NOTIFY) ?
@@ -4219,7 +4219,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
 	}
 
 	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
+		tty->termios = info->normal_termios;
 		change_speed(info);
 	}
 
@@ -4443,14 +4443,12 @@ static int __init rs_init(void)
 		B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
 	driver->init_termios.c_ispeed = 115200;
 	driver->init_termios.c_ospeed = 115200;
-	driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	driver->flags = TTY_DRIVER_REAL_RAW;
 
 	tty_set_operations(driver, &rs_ops);
         serial_driver = driver;
-	if (tty_register_driver(driver))
-		panic("Couldn't register serial driver\n");
-	/* do some initializing for the separate ports */
 
+	/* do some initializing for the separate ports */
 	for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
 		if (info->enabled) {
 			if (cris_request_io_interface(info->io_if,
@@ -4502,7 +4500,12 @@ static int __init rs_init(void)
 			printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n",
 			       serial_driver->name, info->line, info->ioport);
 		}
+		tty_port_link_device(&info->port, driver, i);
 	}
+
+	if (tty_register_driver(driver))
+		panic("Couldn't register serial driver\n");
+
 #ifdef CONFIG_ETRAX_FAST_TIMER
 #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
 	memset(fast_timers, 0, sizeof(fast_timers));

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

@@ -800,8 +800,8 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
 	tty_port_init(pport);
 	pport->ops = &ifx_tty_port_ops;
 	ifx_dev->minor = IFX_SPI_TTY_ID;
-	ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor,
-					       &ifx_dev->spi_dev->dev);
+	ifx_dev->tty_dev = tty_port_register_device(pport, tty_drv,
+			ifx_dev->minor, &ifx_dev->spi_dev->dev);
 	if (IS_ERR(ifx_dev->tty_dev)) {
 		dev_dbg(&ifx_dev->spi_dev->dev,
 			"%s: registering tty device failed", __func__);

+ 4 - 1
drivers/tty/serial/imx.c

@@ -206,7 +206,7 @@ struct imx_port {
 	unsigned short		trcv_delay; /* transceiver delay */
 	struct clk		*clk_ipg;
 	struct clk		*clk_per;
-	struct imx_uart_data	*devdata;
+	const struct imx_uart_data *devdata;
 };
 
 struct imx_port_ucrs {
@@ -1505,18 +1505,21 @@ static int serial_imx_probe(struct platform_device *pdev)
 	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 	if (IS_ERR(pinctrl)) {
 		ret = PTR_ERR(pinctrl);
+		dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret);
 		goto unmap;
 	}
 
 	sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(sport->clk_ipg)) {
 		ret = PTR_ERR(sport->clk_ipg);
+		dev_err(&pdev->dev, "failed to get ipg clk: %d\n", ret);
 		goto unmap;
 	}
 
 	sport->clk_per = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(sport->clk_per)) {
 		ret = PTR_ERR(sport->clk_per);
+		dev_err(&pdev->dev, "failed to get per clk: %d\n", ret);
 		goto unmap;
 	}
 

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

@@ -1120,13 +1120,14 @@ static inline int do_read(struct uart_port *the_port, char *buf, int len)
 	struct ioc3_port *port = get_ioc3_port(the_port);
 	struct ring *inring;
 	struct ring_entry *entry;
-	struct port_hooks *hooks = port->ip_hooks;
+	struct port_hooks *hooks;
 	int byte_num;
 	char *sc;
 	int loop_counter;
 
 	BUG_ON(!(len >= 0));
 	BUG_ON(!port);
+	hooks = port->ip_hooks;
 
 	/* There is a nasty timing issue in the IOC3. When the rx_timer
 	 * expires or the rx_high condition arises, we take an interrupt.

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

@@ -1803,7 +1803,7 @@ static inline int ic4_startup_local(struct uart_port *the_port)
 	ioc4_set_proto(port, the_port->mapbase);
 
 	/* set the speed of the serial port */
-	ioc4_change_speed(the_port, state->port.tty->termios,
+	ioc4_change_speed(the_port, &state->port.tty->termios,
 			  (struct ktermios *)0);
 
 	return 0;
@@ -2069,13 +2069,14 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf,
 	struct ioc4_port *port = get_ioc4_port(the_port, 0);
 	struct ring *inring;
 	struct ring_entry *entry;
-	struct hooks *hooks = port->ip_hooks;
+	struct hooks *hooks;
 	int byte_num;
 	char *sc;
 	int loop_counter;
 
 	BUG_ON(!(len >= 0));
 	BUG_ON(!port);
+	hooks = port->ip_hooks;
 
 	/* There is a nasty timing issue in the IOC4. When the rx_timer
 	 * expires or the rx_high condition arises, we take an interrupt.

+ 4 - 4
drivers/tty/serial/jsm/jsm_tty.c

@@ -161,7 +161,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch)
 	struct ktermios *termios;
 
 	spin_lock_irqsave(&port->lock, lock_flags);
-	termios = port->state->port.tty->termios;
+	termios = &port->state->port.tty->termios;
 	if (ch == termios->c_cc[VSTART])
 		channel->ch_bd->bd_ops->send_start_character(channel);
 
@@ -250,7 +250,7 @@ static int jsm_tty_open(struct uart_port *port)
 	channel->ch_cached_lsr = 0;
 	channel->ch_stops_sent = 0;
 
-	termios = port->state->port.tty->termios;
+	termios = &port->state->port.tty->termios;
 	channel->ch_c_cflag	= termios->c_cflag;
 	channel->ch_c_iflag	= termios->c_iflag;
 	channel->ch_c_oflag	= termios->c_oflag;
@@ -283,7 +283,7 @@ static void jsm_tty_close(struct uart_port *port)
 	jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
 
 	bd = channel->ch_bd;
-	ts = port->state->port.tty->termios;
+	ts = &port->state->port.tty->termios;
 
 	channel->ch_flags &= ~(CH_STOPI);
 
@@ -567,7 +567,7 @@ void jsm_input(struct jsm_channel *ch)
 	 *input data and return immediately.
 	 */
 	if (!tp ||
-		!(tp->termios->c_cflag & CREAD) ) {
+		!(tp->termios.c_cflag & CREAD) ) {
 
 		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
 			"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);

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

@@ -0,0 +1,823 @@
+/*
+ * High Speed Serial Ports on NXP LPC32xx SoC
+ *
+ * Authors: Kevin Wells <kevin.wells@nxp.com>
+ *          Roland Stigge <stigge@antcom.de>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/nmi.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <mach/platform.h>
+#include <mach/hardware.h>
+
+/*
+ * High Speed UART register offsets
+ */
+#define LPC32XX_HSUART_FIFO(x)			((x) + 0x00)
+#define LPC32XX_HSUART_LEVEL(x)			((x) + 0x04)
+#define LPC32XX_HSUART_IIR(x)			((x) + 0x08)
+#define LPC32XX_HSUART_CTRL(x)			((x) + 0x0C)
+#define LPC32XX_HSUART_RATE(x)			((x) + 0x10)
+
+#define LPC32XX_HSU_BREAK_DATA			(1 << 10)
+#define LPC32XX_HSU_ERROR_DATA			(1 << 9)
+#define LPC32XX_HSU_RX_EMPTY			(1 << 8)
+
+#define LPC32XX_HSU_TX_LEV(n)			(((n) >> 8) & 0xFF)
+#define LPC32XX_HSU_RX_LEV(n)			((n) & 0xFF)
+
+#define LPC32XX_HSU_TX_INT_SET			(1 << 6)
+#define LPC32XX_HSU_RX_OE_INT			(1 << 5)
+#define LPC32XX_HSU_BRK_INT			(1 << 4)
+#define LPC32XX_HSU_FE_INT			(1 << 3)
+#define LPC32XX_HSU_RX_TIMEOUT_INT		(1 << 2)
+#define LPC32XX_HSU_RX_TRIG_INT			(1 << 1)
+#define LPC32XX_HSU_TX_INT			(1 << 0)
+
+#define LPC32XX_HSU_HRTS_INV			(1 << 21)
+#define LPC32XX_HSU_HRTS_TRIG_8B		(0x0 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_16B		(0x1 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_32B		(0x2 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_48B		(0x3 << 19)
+#define LPC32XX_HSU_HRTS_EN			(1 << 18)
+#define LPC32XX_HSU_TMO_DISABLED		(0x0 << 16)
+#define LPC32XX_HSU_TMO_INACT_4B		(0x1 << 16)
+#define LPC32XX_HSU_TMO_INACT_8B		(0x2 << 16)
+#define LPC32XX_HSU_TMO_INACT_16B		(0x3 << 16)
+#define LPC32XX_HSU_HCTS_INV			(1 << 15)
+#define LPC32XX_HSU_HCTS_EN			(1 << 14)
+#define LPC32XX_HSU_OFFSET(n)			((n) << 9)
+#define LPC32XX_HSU_BREAK			(1 << 8)
+#define LPC32XX_HSU_ERR_INT_EN			(1 << 7)
+#define LPC32XX_HSU_RX_INT_EN			(1 << 6)
+#define LPC32XX_HSU_TX_INT_EN			(1 << 5)
+#define LPC32XX_HSU_RX_TL1B			(0x0 << 2)
+#define LPC32XX_HSU_RX_TL4B			(0x1 << 2)
+#define LPC32XX_HSU_RX_TL8B			(0x2 << 2)
+#define LPC32XX_HSU_RX_TL16B			(0x3 << 2)
+#define LPC32XX_HSU_RX_TL32B			(0x4 << 2)
+#define LPC32XX_HSU_RX_TL48B			(0x5 << 2)
+#define LPC32XX_HSU_TX_TLEMPTY			(0x0 << 0)
+#define LPC32XX_HSU_TX_TL0B			(0x0 << 0)
+#define LPC32XX_HSU_TX_TL4B			(0x1 << 0)
+#define LPC32XX_HSU_TX_TL8B			(0x2 << 0)
+#define LPC32XX_HSU_TX_TL16B			(0x3 << 0)
+
+#define MODNAME "lpc32xx_hsuart"
+
+struct lpc32xx_hsuart_port {
+	struct uart_port port;
+};
+
+#define FIFO_READ_LIMIT 128
+#define MAX_PORTS 3
+#define LPC32XX_TTY_NAME "ttyTX"
+static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS];
+
+#ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE
+static void wait_for_xmit_empty(struct uart_port *port)
+{
+	unsigned int timeout = 10000;
+
+	do {
+		if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
+							port->membase))) == 0)
+			break;
+		if (--timeout == 0)
+			break;
+		udelay(1);
+	} while (1);
+}
+
+static void wait_for_xmit_ready(struct uart_port *port)
+{
+	unsigned int timeout = 10000;
+
+	while (1) {
+		if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
+							port->membase))) < 32)
+			break;
+		if (--timeout == 0)
+			break;
+		udelay(1);
+	}
+}
+
+static void lpc32xx_hsuart_console_putchar(struct uart_port *port, int ch)
+{
+	wait_for_xmit_ready(port);
+	writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase));
+}
+
+static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
+					 unsigned int count)
+{
+	struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index];
+	unsigned long flags;
+	int locked = 1;
+
+	touch_nmi_watchdog();
+	local_irq_save(flags);
+	if (up->port.sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock(&up->port.lock);
+	else
+		spin_lock(&up->port.lock);
+
+	uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);
+	wait_for_xmit_empty(&up->port);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
+}
+
+static int __init lpc32xx_hsuart_console_setup(struct console *co,
+					       char *options)
+{
+	struct uart_port *port;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index >= MAX_PORTS)
+		co->index = 0;
+
+	port = &lpc32xx_hs_ports[co->index].port;
+	if (!port->membase)
+		return -ENODEV;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver lpc32xx_hsuart_reg;
+static struct console lpc32xx_hsuart_console = {
+	.name		= LPC32XX_TTY_NAME,
+	.write		= lpc32xx_hsuart_console_write,
+	.device		= uart_console_device,
+	.setup		= lpc32xx_hsuart_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &lpc32xx_hsuart_reg,
+};
+
+static int __init lpc32xx_hsuart_console_init(void)
+{
+	register_console(&lpc32xx_hsuart_console);
+	return 0;
+}
+console_initcall(lpc32xx_hsuart_console_init);
+
+#define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console)
+#else
+#define LPC32XX_HSUART_CONSOLE NULL
+#endif
+
+static struct uart_driver lpc32xx_hs_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= MODNAME,
+	.dev_name	= LPC32XX_TTY_NAME,
+	.nr		= MAX_PORTS,
+	.cons		= LPC32XX_HSUART_CONSOLE,
+};
+static int uarts_registered;
+
+static unsigned int __serial_get_clock_div(unsigned long uartclk,
+					   unsigned long rate)
+{
+	u32 div, goodrate, hsu_rate, l_hsu_rate, comprate;
+	u32 rate_diff;
+
+	/* Find the closest divider to get the desired clock rate */
+	div = uartclk / rate;
+	goodrate = hsu_rate = (div / 14) - 1;
+	if (hsu_rate != 0)
+		hsu_rate--;
+
+	/* Tweak divider */
+	l_hsu_rate = hsu_rate + 3;
+	rate_diff = 0xFFFFFFFF;
+
+	while (hsu_rate < l_hsu_rate) {
+		comprate = uartclk / ((hsu_rate + 1) * 14);
+		if (abs(comprate - rate) < rate_diff) {
+			goodrate = hsu_rate;
+			rate_diff = abs(comprate - rate);
+		}
+
+		hsu_rate++;
+	}
+	if (hsu_rate > 0xFF)
+		hsu_rate = 0xFF;
+
+	return goodrate;
+}
+
+static void __serial_uart_flush(struct uart_port *port)
+{
+	u32 tmp;
+	int cnt = 0;
+
+	while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) &&
+	       (cnt++ < FIFO_READ_LIMIT))
+		tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+}
+
+static void __serial_lpc32xx_rx(struct uart_port *port)
+{
+	unsigned int tmp, flag;
+	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+
+	if (!tty) {
+		/* Discard data: no tty available */
+		while (!(readl(LPC32XX_HSUART_FIFO(port->membase)) &
+			 LPC32XX_HSU_RX_EMPTY))
+			;
+
+		return;
+	}
+
+	/* Read data from FIFO and push into terminal */
+	tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+	while (!(tmp & LPC32XX_HSU_RX_EMPTY)) {
+		flag = TTY_NORMAL;
+		port->icount.rx++;
+
+		if (tmp & LPC32XX_HSU_ERROR_DATA) {
+			/* Framing error */
+			writel(LPC32XX_HSU_FE_INT,
+			       LPC32XX_HSUART_IIR(port->membase));
+			port->icount.frame++;
+			flag = TTY_FRAME;
+			tty_insert_flip_char(tty, 0, TTY_FRAME);
+		}
+
+		tty_insert_flip_char(tty, (tmp & 0xFF), flag);
+
+		tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+	}
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+static void __serial_lpc32xx_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+	unsigned int tmp;
+
+	if (port->x_char) {
+		writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase));
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+		goto exit_tx;
+
+	/* Transfer data */
+	while (LPC32XX_HSU_TX_LEV(readl(
+		LPC32XX_HSUART_LEVEL(port->membase))) < 64) {
+		writel((u32) xmit->buf[xmit->tail],
+		       LPC32XX_HSUART_FIFO(port->membase));
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+exit_tx:
+	if (uart_circ_empty(xmit)) {
+		tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+		tmp &= ~LPC32XX_HSU_TX_INT_EN;
+		writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+	}
+}
+
+static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+	u32 status;
+
+	spin_lock(&port->lock);
+
+	/* Read UART status and clear latched interrupts */
+	status = readl(LPC32XX_HSUART_IIR(port->membase));
+
+	if (status & LPC32XX_HSU_BRK_INT) {
+		/* Break received */
+		writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase));
+		port->icount.brk++;
+		uart_handle_break(port);
+	}
+
+	/* Framing error */
+	if (status & LPC32XX_HSU_FE_INT)
+		writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase));
+
+	if (status & LPC32XX_HSU_RX_OE_INT) {
+		/* Receive FIFO overrun */
+		writel(LPC32XX_HSU_RX_OE_INT,
+		       LPC32XX_HSUART_IIR(port->membase));
+		port->icount.overrun++;
+		if (tty) {
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+			tty_schedule_flip(tty);
+		}
+	}
+
+	/* Data received? */
+	if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) {
+		__serial_lpc32xx_rx(port);
+		if (tty)
+			tty_flip_buffer_push(tty);
+	}
+
+	/* Transmit data request? */
+	if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) {
+		writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase));
+		__serial_lpc32xx_tx(port);
+	}
+
+	spin_unlock(&port->lock);
+	tty_kref_put(tty);
+
+	return IRQ_HANDLED;
+}
+
+/* port->lock is not held.  */
+static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port)
+{
+	unsigned int ret = 0;
+
+	if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0)
+		ret = TIOCSER_TEMT;
+
+	return ret;
+}
+
+/* port->lock held by caller.  */
+static void serial_lpc32xx_set_mctrl(struct uart_port *port,
+				     unsigned int mctrl)
+{
+	/* No signals are supported on HS UARTs */
+}
+
+/* port->lock is held by caller and interrupts are disabled.  */
+static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port)
+{
+	/* No signals are supported on HS UARTs */
+	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* port->lock held by caller.  */
+static void serial_lpc32xx_stop_tx(struct uart_port *port)
+{
+	u32 tmp;
+
+	tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+	tmp &= ~LPC32XX_HSU_TX_INT_EN;
+	writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+}
+
+/* port->lock held by caller.  */
+static void serial_lpc32xx_start_tx(struct uart_port *port)
+{
+	u32 tmp;
+
+	__serial_lpc32xx_tx(port);
+	tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+	tmp |= LPC32XX_HSU_TX_INT_EN;
+	writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+}
+
+/* port->lock held by caller.  */
+static void serial_lpc32xx_stop_rx(struct uart_port *port)
+{
+	u32 tmp;
+
+	tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+	tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
+	writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+	writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT |
+		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)
+{
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&port->lock, flags);
+	tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+	if (break_state != 0)
+		tmp |= LPC32XX_HSU_BREAK;
+	else
+		tmp &= ~LPC32XX_HSU_BREAK;
+	writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */
+static void lpc32xx_loopback_set(resource_size_t mapbase, int state)
+{
+	int bit;
+	u32 tmp;
+
+	switch (mapbase) {
+	case LPC32XX_HS_UART1_BASE:
+		bit = 0;
+		break;
+	case LPC32XX_HS_UART2_BASE:
+		bit = 1;
+		break;
+	case LPC32XX_HS_UART7_BASE:
+		bit = 6;
+		break;
+	default:
+		WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase);
+		return;
+	}
+
+	tmp = readl(LPC32XX_UARTCTL_CLOOP);
+	if (state)
+		tmp |= (1 << bit);
+	else
+		tmp &= ~(1 << bit);
+	writel(tmp, LPC32XX_UARTCTL_CLOOP);
+}
+
+/* port->lock is not held.  */
+static int serial_lpc32xx_startup(struct uart_port *port)
+{
+	int retval;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	__serial_uart_flush(port);
+
+	writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
+		LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
+	       LPC32XX_HSUART_IIR(port->membase));
+
+	writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
+
+	/*
+	 * Set receiver timeout, HSU offset of 20, no break, no interrupts,
+	 * and default FIFO trigger levels
+	 */
+	tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+		LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
+	writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+	lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	retval = request_irq(port->irq, serial_lpc32xx_interrupt,
+			     0, MODNAME, port);
+	if (!retval)
+		writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN),
+		       LPC32XX_HSUART_CTRL(port->membase));
+
+	return retval;
+}
+
+/* port->lock is not held.  */
+static void serial_lpc32xx_shutdown(struct uart_port *port)
+{
+	u32 tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+		LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
+	writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+	lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	free_irq(port->irq, port);
+}
+
+/* port->lock is not held.  */
+static void serial_lpc32xx_set_termios(struct uart_port *port,
+				       struct ktermios *termios,
+				       struct ktermios *old)
+{
+	unsigned long flags;
+	unsigned int baud, quot;
+	u32 tmp;
+
+	/* Always 8-bit, no parity, 1 stop bit */
+	termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
+	termios->c_cflag |= CS8;
+
+	termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS);
+
+	baud = uart_get_baud_rate(port, termios, old, 0,
+				  port->uartclk / 14);
+
+	quot = __serial_get_clock_div(port->uartclk, baud);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Ignore characters? */
+	tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+	if ((termios->c_cflag & CREAD) == 0)
+		tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
+	else
+		tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN;
+	writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+	writel(quot, LPC32XX_HSUART_RATE(port->membase));
+
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	/* Don't rewrite B0 */
+	if (tty_termios_baud_rate(termios))
+		tty_termios_encode_baud_rate(termios, baud, baud);
+}
+
+static const char *serial_lpc32xx_type(struct uart_port *port)
+{
+	return MODNAME;
+}
+
+static void serial_lpc32xx_release_port(struct uart_port *port)
+{
+	if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
+		if (port->flags & UPF_IOREMAP) {
+			iounmap(port->membase);
+			port->membase = NULL;
+		}
+
+		release_mem_region(port->mapbase, SZ_4K);
+	}
+}
+
+static int serial_lpc32xx_request_port(struct uart_port *port)
+{
+	int ret = -ENODEV;
+
+	if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
+		ret = 0;
+
+		if (!request_mem_region(port->mapbase, SZ_4K, MODNAME))
+			ret = -EBUSY;
+		else if (port->flags & UPF_IOREMAP) {
+			port->membase = ioremap(port->mapbase, SZ_4K);
+			if (!port->membase) {
+				release_mem_region(port->mapbase, SZ_4K);
+				ret = -ENOMEM;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static void serial_lpc32xx_config_port(struct uart_port *port, int uflags)
+{
+	int ret;
+
+	ret = serial_lpc32xx_request_port(port);
+	if (ret < 0)
+		return;
+	port->type = PORT_UART00;
+	port->fifosize = 64;
+
+	__serial_uart_flush(port);
+
+	writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
+		LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
+	       LPC32XX_HSUART_IIR(port->membase));
+
+	writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
+
+	/* Set receiver timeout, HSU offset of 20, no break, no interrupts,
+	   and default FIFO trigger levels */
+	writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+	       LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B,
+	       LPC32XX_HSUART_CTRL(port->membase));
+}
+
+static int serial_lpc32xx_verify_port(struct uart_port *port,
+				      struct serial_struct *ser)
+{
+	int ret = 0;
+
+	if (ser->type != PORT_UART00)
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static struct uart_ops serial_lpc32xx_pops = {
+	.tx_empty	= serial_lpc32xx_tx_empty,
+	.set_mctrl	= serial_lpc32xx_set_mctrl,
+	.get_mctrl	= serial_lpc32xx_get_mctrl,
+	.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,
+	.set_termios	= serial_lpc32xx_set_termios,
+	.type		= serial_lpc32xx_type,
+	.release_port	= serial_lpc32xx_release_port,
+	.request_port	= serial_lpc32xx_request_port,
+	.config_port	= serial_lpc32xx_config_port,
+	.verify_port	= serial_lpc32xx_verify_port,
+};
+
+/*
+ * Register a set of serial devices attached to a platform device
+ */
+static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
+{
+	struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
+	int ret = 0;
+	struct resource *res;
+
+	if (uarts_registered >= MAX_PORTS) {
+		dev_err(&pdev->dev,
+			"Error: Number of possible ports exceeded (%d)!\n",
+			uarts_registered + 1);
+		return -ENXIO;
+	}
+
+	memset(p, 0, sizeof(*p));
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Error getting mem resource for HS UART port %d\n",
+			uarts_registered);
+		return -ENXIO;
+	}
+	p->port.mapbase = res->start;
+	p->port.membase = NULL;
+
+	p->port.irq = platform_get_irq(pdev, 0);
+	if (p->port.irq < 0) {
+		dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n",
+			uarts_registered);
+		return p->port.irq;
+	}
+
+	p->port.iotype = UPIO_MEM32;
+	p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;
+	p->port.regshift = 2;
+	p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
+	p->port.dev = &pdev->dev;
+	p->port.ops = &serial_lpc32xx_pops;
+	p->port.line = uarts_registered++;
+	spin_lock_init(&p->port.lock);
+
+	/* send port to loopback mode by default */
+	lpc32xx_loopback_set(p->port.mapbase, 1);
+
+	ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port);
+
+	platform_set_drvdata(pdev, p);
+
+	return ret;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev)
+{
+	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+	uart_remove_one_port(&lpc32xx_hs_reg, &p->port);
+
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int serial_hs_lpc32xx_suspend(struct platform_device *pdev,
+				     pm_message_t state)
+{
+	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+	uart_suspend_port(&lpc32xx_hs_reg, &p->port);
+
+	return 0;
+}
+
+static int serial_hs_lpc32xx_resume(struct platform_device *pdev)
+{
+	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+	uart_resume_port(&lpc32xx_hs_reg, &p->port);
+
+	return 0;
+}
+#else
+#define serial_hs_lpc32xx_suspend	NULL
+#define serial_hs_lpc32xx_resume	NULL
+#endif
+
+static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = {
+	{ .compatible = "nxp,lpc3220-hsuart" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
+
+static struct platform_driver serial_hs_lpc32xx_driver = {
+	.probe		= serial_hs_lpc32xx_probe,
+	.remove		= __devexit_p(serial_hs_lpc32xx_remove),
+	.suspend	= serial_hs_lpc32xx_suspend,
+	.resume		= serial_hs_lpc32xx_resume,
+	.driver		= {
+		.name	= MODNAME,
+		.owner	= THIS_MODULE,
+		.of_match_table	= serial_hs_lpc32xx_dt_ids,
+	},
+};
+
+static int __init lpc32xx_hsuart_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&lpc32xx_hs_reg);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&serial_hs_lpc32xx_driver);
+	if (ret)
+		uart_unregister_driver(&lpc32xx_hs_reg);
+
+	return ret;
+}
+
+static void __exit lpc32xx_hsuart_exit(void)
+{
+	platform_driver_unregister(&serial_hs_lpc32xx_driver);
+	uart_unregister_driver(&lpc32xx_hs_reg);
+}
+
+module_init(lpc32xx_hsuart_init);
+module_exit(lpc32xx_hsuart_exit);
+
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver");
+MODULE_LICENSE("GPL");

+ 2 - 34
drivers/tty/serial/m32r_sio.c

@@ -44,8 +44,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#define PORT_M32R_BASE	PORT_M32R_SIO
-#define PORT_INDEX(x)	(x - PORT_M32R_BASE + 1)
 #define BAUD_RATE	115200
 
 #include <linux/serial_core.h>
@@ -132,22 +130,6 @@ struct irq_info {
 
 static struct irq_info irq_lists[NR_IRQS];
 
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial_uart_config uart_config[] = {
-	[PORT_UNKNOWN] = {
-		.name			= "unknown",
-		.dfl_xmit_fifo_size	= 1,
-		.flags			= 0,
-	},
-	[PORT_INDEX(PORT_M32R_SIO)] = {
-		.name			= "M32RSIO",
-		.dfl_xmit_fifo_size	= 1,
-		.flags			= 0,
-	},
-};
-
 #ifdef CONFIG_SERIAL_M32R_PLDSIO
 
 #define __sio_in(x) inw((unsigned long)(x))
@@ -907,8 +889,7 @@ static void m32r_sio_config_port(struct uart_port *port, int unused)
 
 	spin_lock_irqsave(&up->port.lock, flags);
 
-	up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1);
-	up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
+	up->port.fifosize = 1;
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
@@ -916,23 +897,11 @@ static void m32r_sio_config_port(struct uart_port *port, int unused)
 static int
 m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
-	if (ser->irq >= nr_irqs || ser->irq < 0 ||
-	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-	    ser->type >= ARRAY_SIZE(uart_config))
+	if (ser->irq >= nr_irqs || ser->irq < 0 || ser->baud_base < 9600)
 		return -EINVAL;
 	return 0;
 }
 
-static const char *
-m32r_sio_type(struct uart_port *port)
-{
-	int type = port->type;
-
-	if (type >= ARRAY_SIZE(uart_config))
-		type = 0;
-	return uart_config[type].name;
-}
-
 static struct uart_ops m32r_sio_pops = {
 	.tx_empty	= m32r_sio_tx_empty,
 	.set_mctrl	= m32r_sio_set_mctrl,
@@ -946,7 +915,6 @@ static struct uart_ops m32r_sio_pops = {
 	.shutdown	= m32r_sio_shutdown,
 	.set_termios	= m32r_sio_set_termios,
 	.pm		= m32r_sio_pm,
-	.type		= m32r_sio_type,
 	.release_port	= m32r_sio_release_port,
 	.request_port	= m32r_sio_request_port,
 	.config_port	= m32r_sio_config_port,

+ 1 - 11
drivers/tty/serial/max3100.c

@@ -910,17 +910,7 @@ static struct spi_driver max3100_driver = {
 	.resume		= max3100_resume,
 };
 
-static int __init max3100_init(void)
-{
-	return spi_register_driver(&max3100_driver);
-}
-module_init(max3100_init);
-
-static void __exit max3100_exit(void)
-{
-	spi_unregister_driver(&max3100_driver);
-}
-module_exit(max3100_exit);
+module_spi_driver(max3100_driver);
 
 MODULE_DESCRIPTION("MAX3100 driver");
 MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");

+ 0 - 1215
drivers/tty/serial/max3107.c

@@ -1,1215 +0,0 @@
-/*
- *  max3107.c - spi uart protocol driver for Maxim 3107
- *  Based on max3100.c
- *	by Christian Pellegrin <chripell@evolware.org>
- *  and	max3110.c
- *	by Feng Tang <feng.tang@intel.com>
- *
- *  Copyright (C) Aavamobile 2009
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include <linux/module.h>
-#include "max3107.h"
-
-static const struct baud_table brg26_ext[] = {
-	{ 300,    MAX3107_BRG26_B300 },
-	{ 600,    MAX3107_BRG26_B600 },
-	{ 1200,   MAX3107_BRG26_B1200 },
-	{ 2400,   MAX3107_BRG26_B2400 },
-	{ 4800,   MAX3107_BRG26_B4800 },
-	{ 9600,   MAX3107_BRG26_B9600 },
-	{ 19200,  MAX3107_BRG26_B19200 },
-	{ 57600,  MAX3107_BRG26_B57600 },
-	{ 115200, MAX3107_BRG26_B115200 },
-	{ 230400, MAX3107_BRG26_B230400 },
-	{ 460800, MAX3107_BRG26_B460800 },
-	{ 921600, MAX3107_BRG26_B921600 },
-	{ 0, 0 }
-};
-
-static const struct baud_table brg13_int[] = {
-	{ 300,    MAX3107_BRG13_IB300 },
-	{ 600,    MAX3107_BRG13_IB600 },
-	{ 1200,   MAX3107_BRG13_IB1200 },
-	{ 2400,   MAX3107_BRG13_IB2400 },
-	{ 4800,   MAX3107_BRG13_IB4800 },
-	{ 9600,   MAX3107_BRG13_IB9600 },
-	{ 19200,  MAX3107_BRG13_IB19200 },
-	{ 57600,  MAX3107_BRG13_IB57600 },
-	{ 115200, MAX3107_BRG13_IB115200 },
-	{ 230400, MAX3107_BRG13_IB230400 },
-	{ 460800, MAX3107_BRG13_IB460800 },
-	{ 921600, MAX3107_BRG13_IB921600 },
-	{ 0, 0 }
-};
-
-static u32 get_new_brg(int baud, struct max3107_port *s)
-{
-	int i;
-	const struct baud_table *baud_tbl = s->baud_tbl;
-
-	for (i = 0; i < 13; i++) {
-		if (baud == baud_tbl[i].baud)
-			return baud_tbl[i].new_brg;
-	}
-
-	return 0;
-}
-
-/* Perform SPI transfer for write/read of device register(s) */
-int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
-{
-	struct spi_message spi_msg;
-	struct spi_transfer spi_xfer;
-
-	/* Initialize SPI ,message */
-	spi_message_init(&spi_msg);
-
-	/* Initialize SPI transfer */
-	memset(&spi_xfer, 0, sizeof spi_xfer);
-	spi_xfer.len = len;
-	spi_xfer.tx_buf = tx;
-	spi_xfer.rx_buf = rx;
-	spi_xfer.speed_hz = MAX3107_SPI_SPEED;
-
-	/* Add SPI transfer to SPI message */
-	spi_message_add_tail(&spi_xfer, &spi_msg);
-
-#ifdef DBG_TRACE_SPI_DATA
-	{
-		int i;
-		pr_info("tx len %d:\n", spi_xfer.len);
-		for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
-			pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]);
-		pr_info("\n");
-	}
-#endif
-
-	/* Perform synchronous SPI transfer */
-	if (spi_sync(s->spi, &spi_msg)) {
-		dev_err(&s->spi->dev, "spi_sync failure\n");
-		return -EIO;
-	}
-
-#ifdef DBG_TRACE_SPI_DATA
-	if (spi_xfer.rx_buf) {
-		int i;
-		pr_info("rx len %d:\n", spi_xfer.len);
-		for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
-			pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]);
-		pr_info("\n");
-	}
-#endif
-	return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_rw);
-
-/* Puts received data to circular buffer */
-static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data,
-					int len)
-{
-	struct uart_port *port = &s->port;
-	struct tty_struct *tty;
-
-	if (!port->state)
-		return;
-
-	tty = port->state->port.tty;
-	if (!tty)
-		return;
-
-	/* Insert received data */
-	tty_insert_flip_string(tty, data, len);
-	/* Update RX counter */
-	port->icount.rx += len;
-}
-
-/* Handle data receiving */
-static void max3107_handlerx(struct max3107_port *s, u16 rxlvl)
-{
-	int i;
-	int j;
-	int len;				/* SPI transfer buffer length */
-	u16 *buf;
-	u8 *valid_str;
-
-	if (!s->rx_enabled)
-		/* RX is disabled */
-		return;
-
-	if (rxlvl == 0) {
-		/* RX fifo is empty */
-		return;
-	} else if (rxlvl >= MAX3107_RX_FIFO_SIZE) {
-		dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl);
-		/* Ensure sanity of RX level */
-		rxlvl = MAX3107_RX_FIFO_SIZE;
-	}
-	if ((s->rxbuf == 0) || (s->rxstr == 0)) {
-		dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n");
-		return;
-	}
-	buf = s->rxbuf;
-	valid_str = s->rxstr;
-	while (rxlvl) {
-		pr_debug("rxlvl %d\n", rxlvl);
-		/* Clear buffer */
-		memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2));
-		len = 0;
-		if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) {
-			/* First disable RX FIFO interrupt */
-			pr_debug("Disabling RX INT\n");
-			buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
-			s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT;
-			buf[0] |= s->irqen_reg;
-			len++;
-		}
-		/* Just increase the length by amount of words in FIFO since
-		 * buffer was zeroed and SPI transfer of 0x0000 means reading
-		 * from RX FIFO
-		 */
-		len += rxlvl;
-		/* Append RX level query */
-		buf[len] = MAX3107_RXFIFOLVL_REG;
-		len++;
-
-		/* Perform the SPI transfer */
-		if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) {
-			dev_err(&s->spi->dev, "SPI transfer for RX h failed\n");
-			return;
-		}
-
-		/* Skip RX FIFO interrupt disabling word if it was added */
-		j = ((len - 1) - rxlvl);
-		/* Read received words */
-		for (i = 0; i < rxlvl; i++, j++)
-			valid_str[i] = (u8)buf[j];
-		put_data_to_circ_buf(s, valid_str, rxlvl);
-		/* Get new RX level */
-		rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK);
-	}
-
-	if (s->rx_enabled) {
-		/* RX still enabled, re-enable RX FIFO interrupt */
-		pr_debug("Enabling RX INT\n");
-		buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
-		s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
-		buf[0] |= s->irqen_reg;
-		if (max3107_rw(s, (u8 *)buf, NULL, 2))
-			dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n");
-	}
-
-	/* Push the received data to receivers */
-	if (s->port.state->port.tty)
-		tty_flip_buffer_push(s->port.state->port.tty);
-}
-
-
-/* Handle data sending */
-static void max3107_handletx(struct max3107_port *s)
-{
-	struct circ_buf *xmit = &s->port.state->xmit;
-	int i;
-	unsigned long flags;
-	int len;				/* SPI transfer buffer length */
-	u16 *buf;
-
-	if (!s->tx_fifo_empty)
-		/* Don't send more data before previous data is sent */
-		return;
-
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
-		/* No data to send or TX is stopped */
-		return;
-
-	if (!s->txbuf) {
-		dev_warn(&s->spi->dev, "Txbuf isn't ready\n");
-		return;
-	}
-	buf = s->txbuf;
-	/* Get length of data pending in circular buffer */
-	len = uart_circ_chars_pending(xmit);
-	if (len) {
-		/* Limit to size of TX FIFO */
-		if (len > MAX3107_TX_FIFO_SIZE)
-			len = MAX3107_TX_FIFO_SIZE;
-
-		pr_debug("txlen %d\n", len);
-
-		/* Update TX counter */
-		s->port.icount.tx += len;
-
-		/* TX FIFO will no longer be empty */
-		s->tx_fifo_empty = 0;
-
-		i = 0;
-		if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) {
-			/* First disable TX empty interrupt */
-			pr_debug("Disabling TE INT\n");
-			buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
-			s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT;
-			buf[i] |= s->irqen_reg;
-			i++;
-			len++;
-		}
-		/* Add data to send */
-		spin_lock_irqsave(&s->port.lock, flags);
-		for ( ; i < len ; i++) {
-			buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG);
-			buf[i] |= ((u16)xmit->buf[xmit->tail] &
-						MAX3107_SPI_TX_DATA_MASK);
-			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		}
-		spin_unlock_irqrestore(&s->port.lock, flags);
-		if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) {
-			/* Enable TX empty interrupt */
-			pr_debug("Enabling TE INT\n");
-			buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
-			s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT;
-			buf[i] |= s->irqen_reg;
-			i++;
-			len++;
-		}
-		if (!s->tx_enabled) {
-			/* Enable TX */
-			pr_debug("Enable TX\n");
-			buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
-			spin_lock_irqsave(&s->data_lock, flags);
-			s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT;
-			buf[i] |= s->mode1_reg;
-			spin_unlock_irqrestore(&s->data_lock, flags);
-			s->tx_enabled = 1;
-			i++;
-			len++;
-		}
-
-		/* Perform the SPI transfer */
-		if (max3107_rw(s, (u8 *)buf, NULL, len*2)) {
-			dev_err(&s->spi->dev,
-				"SPI transfer TX handling failed\n");
-			return;
-		}
-	}
-
-	/* Indicate wake up if circular buffer is getting low on data */
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&s->port);
-
-}
-
-/* Handle interrupts
- * Also reads and returns current RX FIFO level
- */
-static u16 handle_interrupt(struct max3107_port *s)
-{
-	u16 buf[4];	/* Buffer for SPI transfers */
-	u8 irq_status;
-	u16 rx_level;
-	unsigned long flags;
-
-	/* Read IRQ status register */
-	buf[0] = MAX3107_IRQSTS_REG;
-	/* Read status IRQ status register */
-	buf[1] = MAX3107_STS_IRQSTS_REG;
-	/* Read LSR IRQ status register */
-	buf[2] = MAX3107_LSR_IRQSTS_REG;
-	/* Query RX level */
-	buf[3] = MAX3107_RXFIFOLVL_REG;
-
-	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) {
-		dev_err(&s->spi->dev,
-			"SPI transfer for INTR handling failed\n");
-		return 0;
-	}
-
-	irq_status = (u8)buf[0];
-	pr_debug("IRQSTS %x\n", irq_status);
-	rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK);
-
-	if (irq_status & MAX3107_IRQ_LSR_BIT) {
-		/* LSR interrupt */
-		if (buf[2] & MAX3107_LSR_RXTO_BIT)
-			/* RX timeout interrupt,
-			 * handled by normal RX handling
-			 */
-			pr_debug("RX TO INT\n");
-	}
-
-	if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) {
-		/* Tx empty interrupt,
-		 * disable TX and set tx_fifo_empty flag
-		 */
-		pr_debug("TE INT, disabling TX\n");
-		buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
-		spin_lock_irqsave(&s->data_lock, flags);
-		s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
-		buf[0] |= s->mode1_reg;
-		spin_unlock_irqrestore(&s->data_lock, flags);
-		if (max3107_rw(s, (u8 *)buf, NULL, 2))
-			dev_err(&s->spi->dev, "SPI transfer TX dis failed\n");
-		s->tx_enabled = 0;
-		s->tx_fifo_empty = 1;
-	}
-
-	if (irq_status & MAX3107_IRQ_RXFIFO_BIT)
-		/* RX FIFO interrupt,
-		 * handled by normal RX handling
-		 */
-		pr_debug("RFIFO INT\n");
-
-	/* Return RX level */
-	return rx_level;
-}
-
-/* Trigger work thread*/
-static void max3107_dowork(struct max3107_port *s)
-{
-	if (!work_pending(&s->work) && !freezing(current) && !s->suspended)
-		queue_work(s->workqueue, &s->work);
-	else
-		dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n");
-}
-
-/* Work thread */
-static void max3107_work(struct work_struct *w)
-{
-	struct max3107_port *s = container_of(w, struct max3107_port, work);
-	u16 rxlvl = 0;
-	int len;	/* SPI transfer buffer length */
-	u16 buf[5];	/* Buffer for SPI transfers */
-	unsigned long flags;
-
-	/* Start by reading current RX FIFO level */
-	buf[0] = MAX3107_RXFIFOLVL_REG;
-	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
-		dev_err(&s->spi->dev, "SPI transfer RX lev failed\n");
-		rxlvl = 0;
-	} else {
-		rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK);
-	}
-
-	do {
-		pr_debug("rxlvl %d\n", rxlvl);
-
-		/* Handle RX */
-		max3107_handlerx(s, rxlvl);
-		rxlvl = 0;
-
-		if (s->handle_irq) {
-			/* Handle pending interrupts
-			 * We also get new RX FIFO level since new data may
-			 * have been received while pushing received data to
-			 * receivers
-			 */
-			s->handle_irq = 0;
-			rxlvl = handle_interrupt(s);
-		}
-
-		/* Handle TX */
-		max3107_handletx(s);
-
-		/* Handle configuration changes */
-		len = 0;
-		spin_lock_irqsave(&s->data_lock, flags);
-		if (s->mode1_commit) {
-			pr_debug("mode1_commit\n");
-			buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
-			buf[len++] |= s->mode1_reg;
-			s->mode1_commit = 0;
-		}
-		if (s->lcr_commit) {
-			pr_debug("lcr_commit\n");
-			buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG);
-			buf[len++] |= s->lcr_reg;
-			s->lcr_commit = 0;
-		}
-		if (s->brg_commit) {
-			pr_debug("brg_commit\n");
-			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG);
-			buf[len++] |= ((s->brg_cfg >> 16) &
-						MAX3107_SPI_TX_DATA_MASK);
-			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG);
-			buf[len++] |= ((s->brg_cfg >> 8) &
-						MAX3107_SPI_TX_DATA_MASK);
-			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG);
-			buf[len++] |= ((s->brg_cfg) & 0xff);
-			s->brg_commit = 0;
-		}
-		spin_unlock_irqrestore(&s->data_lock, flags);
-
-		if (len > 0) {
-			if (max3107_rw(s, (u8 *)buf, NULL, len * 2))
-				dev_err(&s->spi->dev,
-					"SPI transfer config failed\n");
-		}
-
-		/* Reloop if interrupt handling indicated data in RX FIFO */
-	} while (rxlvl);
-
-}
-
-/* Set sleep mode */
-static void max3107_set_sleep(struct max3107_port *s, int mode)
-{
-	u16 buf[1];	/* Buffer for SPI transfer */
-	unsigned long flags;
-	pr_debug("enter, mode %d\n", mode);
-
-	buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
-	spin_lock_irqsave(&s->data_lock, flags);
-	switch (mode) {
-	case MAX3107_DISABLE_FORCED_SLEEP:
-			s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT;
-			break;
-	case MAX3107_ENABLE_FORCED_SLEEP:
-			s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT;
-			break;
-	case MAX3107_DISABLE_AUTOSLEEP:
-			s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT;
-			break;
-	case MAX3107_ENABLE_AUTOSLEEP:
-			s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT;
-			break;
-	default:
-		spin_unlock_irqrestore(&s->data_lock, flags);
-		dev_warn(&s->spi->dev, "invalid sleep mode\n");
-		return;
-	}
-	buf[0] |= s->mode1_reg;
-	spin_unlock_irqrestore(&s->data_lock, flags);
-
-	if (max3107_rw(s, (u8 *)buf, NULL, 2))
-		dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n");
-
-	if (mode == MAX3107_DISABLE_AUTOSLEEP ||
-			mode == MAX3107_DISABLE_FORCED_SLEEP)
-		msleep(MAX3107_WAKEUP_DELAY);
-}
-
-/* Perform full register initialization */
-static void max3107_register_init(struct max3107_port *s)
-{
-	u16 buf[11];	/* Buffer for SPI transfers */
-
-	/* 1. Configure baud rate, 9600 as default */
-	s->baud = 9600;
-	/* the below is default*/
-	if (s->ext_clk) {
-		s->brg_cfg = MAX3107_BRG26_B9600;
-		s->baud_tbl = (struct baud_table *)brg26_ext;
-	} else {
-		s->brg_cfg = MAX3107_BRG13_IB9600;
-		s->baud_tbl = (struct baud_table *)brg13_int;
-	}
-
-	if (s->pdata->init)
-		s->pdata->init(s);
-
-	buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG)
-		| ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK);
-	buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG)
-		| ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK);
-	buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG)
-		| ((s->brg_cfg) & 0xff);
-
-	/* 2. Configure LCR register, 8N1 mode by default */
-	s->lcr_reg = MAX3107_LCR_WORD_LEN_8;
-	buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG)
-		| s->lcr_reg;
-
-	/* 3. Configure MODE 1 register */
-	s->mode1_reg = 0;
-	/* Enable IRQ pin */
-	s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT;
-	/* Disable TX */
-	s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
-	s->tx_enabled = 0;
-	/* RX is enabled */
-	s->rx_enabled = 1;
-	buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG)
-		| s->mode1_reg;
-
-	/* 4. Configure MODE 2 register */
-	buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
-	if (s->loopback) {
-		/* Enable loopback */
-		buf[5] |= MAX3107_MODE2_LOOPBACK_BIT;
-	}
-	/* Reset FIFOs */
-	buf[5] |= MAX3107_MODE2_FIFORST_BIT;
-	s->tx_fifo_empty = 1;
-
-	/* 5. Configure FIFO trigger level register */
-	buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG);
-	/* RX FIFO trigger for 16 words, TX FIFO trigger not used */
-	buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0));
-
-	/* 6. Configure flow control levels */
-	buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG);
-	/* Flow control halt level 96, resume level 48 */
-	buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96));
-
-	/* 7. Configure flow control */
-	buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG);
-	/* Enable auto CTS and auto RTS flow control */
-	buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT);
-
-	/* 8. Configure RX timeout register */
-	buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG);
-	/* Timeout after 48 character intervals */
-	buf[9] |= 0x0030;
-
-	/* 9. Configure LSR interrupt enable register */
-	buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG);
-	/* Enable RX timeout interrupt */
-	buf[10] |= MAX3107_LSR_RXTO_BIT;
-
-	/* Perform SPI transfer */
-	if (max3107_rw(s, (u8 *)buf, NULL, 22))
-		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-
-	/* 10. Clear IRQ status register by reading it */
-	buf[0] = MAX3107_IRQSTS_REG;
-
-	/* 11. Configure interrupt enable register */
-	/* Enable LSR interrupt */
-	s->irqen_reg = MAX3107_IRQ_LSR_BIT;
-	/* Enable RX FIFO interrupt */
-	s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
-	buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG)
-		| s->irqen_reg;
-
-	/* 12. Clear FIFO reset that was set in step 6 */
-	buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
-	if (s->loopback) {
-		/* Keep loopback enabled */
-		buf[2] |= MAX3107_MODE2_LOOPBACK_BIT;
-	}
-
-	/* Perform SPI transfer */
-	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6))
-		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-
-}
-
-/* IRQ handler */
-static irqreturn_t max3107_irq(int irqno, void *dev_id)
-{
-	struct max3107_port *s = dev_id;
-
-	if (irqno != s->spi->irq) {
-		/* Unexpected IRQ */
-		return IRQ_NONE;
-	}
-
-	/* Indicate irq */
-	s->handle_irq = 1;
-
-	/* Trigger work thread */
-	max3107_dowork(s);
-
-	return IRQ_HANDLED;
-}
-
-/* HW suspension function
- *
- * Currently autosleep is used to decrease current consumption, alternative
- * approach would be to set the chip to reset mode if UART is not being
- * used but that would mess the GPIOs
- *
- */
-void max3107_hw_susp(struct max3107_port *s, int suspend)
-{
-	pr_debug("enter, suspend %d\n", suspend);
-
-	if (suspend) {
-		/* Suspend requested,
-		 * enable autosleep to decrease current consumption
-		 */
-		s->suspended = 1;
-		max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP);
-	} else {
-		/* Resume requested,
-		 * disable autosleep
-		 */
-		s->suspended = 0;
-		max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP);
-	}
-}
-EXPORT_SYMBOL_GPL(max3107_hw_susp);
-
-/* Modem status IRQ enabling */
-static void max3107_enable_ms(struct uart_port *port)
-{
-	/* Modem status not supported */
-}
-
-/* Data send function */
-static void max3107_start_tx(struct uart_port *port)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-
-	/* Trigger work thread for sending data */
-	max3107_dowork(s);
-}
-
-/* Function for checking that there is no pending transfers */
-static unsigned int max3107_tx_empty(struct uart_port *port)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-
-	pr_debug("returning %d\n",
-		  (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit)));
-	return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit);
-}
-
-/* Function for stopping RX */
-static void max3107_stop_rx(struct uart_port *port)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-	unsigned long flags;
-
-	/* Set RX disabled in MODE 1 register */
-	spin_lock_irqsave(&s->data_lock, flags);
-	s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT;
-	s->mode1_commit = 1;
-	spin_unlock_irqrestore(&s->data_lock, flags);
-	/* Set RX disabled */
-	s->rx_enabled = 0;
-	/* Trigger work thread for doing the actual configuration change */
-	max3107_dowork(s);
-}
-
-/* Function for returning control pin states */
-static unsigned int max3107_get_mctrl(struct uart_port *port)
-{
-	/* DCD and DSR are not wired and CTS/RTS is handled automatically
-	 * so just indicate DSR and CAR asserted
-	 */
-	return TIOCM_DSR | TIOCM_CAR;
-}
-
-/* Function for setting control pin states */
-static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	/* DCD and DSR are not wired and CTS/RTS is hadnled automatically
-	 * so do nothing
-	 */
-}
-
-/* Function for configuring UART parameters */
-static void max3107_set_termios(struct uart_port *port,
-				struct ktermios *termios,
-				struct ktermios *old)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-	struct tty_struct *tty;
-	int baud;
-	u16 new_lcr = 0;
-	u32 new_brg = 0;
-	unsigned long flags;
-
-	if (!port->state)
-		return;
-
-	tty = port->state->port.tty;
-	if (!tty)
-		return;
-
-	/* Get new LCR register values */
-	/* Word size */
-	if ((termios->c_cflag & CSIZE) == CS7)
-		new_lcr |= MAX3107_LCR_WORD_LEN_7;
-	else
-		new_lcr |= MAX3107_LCR_WORD_LEN_8;
-
-	/* Parity */
-	if (termios->c_cflag & PARENB) {
-		new_lcr |= MAX3107_LCR_PARITY_BIT;
-		if (!(termios->c_cflag & PARODD))
-			new_lcr |= MAX3107_LCR_EVENPARITY_BIT;
-	}
-
-	/* Stop bits */
-	if (termios->c_cflag & CSTOPB) {
-		/* 2 stop bits */
-		new_lcr |= MAX3107_LCR_STOPLEN_BIT;
-	}
-
-	/* Mask termios capabilities we don't support */
-	termios->c_cflag &= ~CMSPAR;
-
-	/* Set status ignore mask */
-	s->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		s->port.ignore_status_mask |= MAX3107_ALL_ERRORS;
-
-	/* Set low latency to immediately handle pushed data */
-	s->port.state->port.tty->low_latency = 1;
-
-	/* Get new baud rate generator configuration */
-	baud = tty_get_baud_rate(tty);
-
-	spin_lock_irqsave(&s->data_lock, flags);
-	new_brg = get_new_brg(baud, s);
-	/* if can't find the corrent config, use previous */
-	if (!new_brg) {
-		baud = s->baud;
-		new_brg = s->brg_cfg;
-	}
-	spin_unlock_irqrestore(&s->data_lock, flags);
-	tty_termios_encode_baud_rate(termios, baud, baud);
-	s->baud = baud;
-
-	/* Update timeout according to new baud rate */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	spin_lock_irqsave(&s->data_lock, flags);
-	if (s->lcr_reg != new_lcr) {
-		s->lcr_reg = new_lcr;
-		s->lcr_commit = 1;
-	}
-	if (s->brg_cfg != new_brg) {
-		s->brg_cfg = new_brg;
-		s->brg_commit = 1;
-	}
-	spin_unlock_irqrestore(&s->data_lock, flags);
-
-	/* Trigger work thread for doing the actual configuration change */
-	max3107_dowork(s);
-}
-
-/* Port shutdown function */
-static void max3107_shutdown(struct uart_port *port)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-
-	if (s->suspended && s->pdata->hw_suspend)
-		s->pdata->hw_suspend(s, 0);
-
-	/* Free the interrupt */
-	free_irq(s->spi->irq, s);
-
-	if (s->workqueue) {
-		/* Flush and destroy work queue */
-		flush_workqueue(s->workqueue);
-		destroy_workqueue(s->workqueue);
-		s->workqueue = NULL;
-	}
-
-	/* Suspend HW */
-	if (s->pdata->hw_suspend)
-		s->pdata->hw_suspend(s, 1);
-}
-
-/* Port startup function */
-static int max3107_startup(struct uart_port *port)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-
-	/* Initialize work queue */
-	s->workqueue = create_freezable_workqueue("max3107");
-	if (!s->workqueue) {
-		dev_err(&s->spi->dev, "Workqueue creation failed\n");
-		return -EBUSY;
-	}
-	INIT_WORK(&s->work, max3107_work);
-
-	/* Setup IRQ */
-	if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING,
-			"max3107", s)) {
-		dev_err(&s->spi->dev, "IRQ reguest failed\n");
-		destroy_workqueue(s->workqueue);
-		s->workqueue = NULL;
-		return -EBUSY;
-	}
-
-	/* Resume HW */
-	if (s->pdata->hw_suspend)
-		s->pdata->hw_suspend(s, 0);
-
-	/* Init registers */
-	max3107_register_init(s);
-
-	return 0;
-}
-
-/* Port type function */
-static const char *max3107_type(struct uart_port *port)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-	return s->spi->modalias;
-}
-
-/* Port release function */
-static void max3107_release_port(struct uart_port *port)
-{
-	/* Do nothing */
-}
-
-/* Port request function */
-static int max3107_request_port(struct uart_port *port)
-{
-	/* Do nothing */
-	return 0;
-}
-
-/* Port config function */
-static void max3107_config_port(struct uart_port *port, int flags)
-{
-	struct max3107_port *s = container_of(port, struct max3107_port, port);
-	s->port.type = PORT_MAX3107;
-}
-
-/* Port verify function */
-static int max3107_verify_port(struct uart_port *port,
-				struct serial_struct *ser)
-{
-	if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107)
-		return 0;
-
-	return -EINVAL;
-}
-
-/* Port stop TX function */
-static void max3107_stop_tx(struct uart_port *port)
-{
-	/* Do nothing */
-}
-
-/* Port break control function */
-static void max3107_break_ctl(struct uart_port *port, int break_state)
-{
-	/* We don't support break control, do nothing */
-}
-
-
-/* Port functions */
-static struct uart_ops max3107_ops = {
-	.tx_empty       = max3107_tx_empty,
-	.set_mctrl      = max3107_set_mctrl,
-	.get_mctrl      = max3107_get_mctrl,
-	.stop_tx        = max3107_stop_tx,
-	.start_tx       = max3107_start_tx,
-	.stop_rx        = max3107_stop_rx,
-	.enable_ms      = max3107_enable_ms,
-	.break_ctl      = max3107_break_ctl,
-	.startup        = max3107_startup,
-	.shutdown       = max3107_shutdown,
-	.set_termios    = max3107_set_termios,
-	.type           = max3107_type,
-	.release_port   = max3107_release_port,
-	.request_port   = max3107_request_port,
-	.config_port    = max3107_config_port,
-	.verify_port    = max3107_verify_port,
-};
-
-/* UART driver data */
-static struct uart_driver max3107_uart_driver = {
-	.owner          = THIS_MODULE,
-	.driver_name    = "ttyMAX",
-	.dev_name       = "ttyMAX",
-	.nr             = 1,
-};
-
-static int driver_registered = 0;
-
-
-
-/* 'Generic' platform data */
-static struct max3107_plat generic_plat_data = {
-	.loopback               = 0,
-	.ext_clk                = 1,
-	.hw_suspend		= max3107_hw_susp,
-	.polled_mode            = 0,
-	.poll_time              = 0,
-};
-
-
-/*******************************************************************/
-
-/**
- *	max3107_probe		-	SPI bus probe entry point
- *	@spi: the spi device
- *
- *	SPI wants us to probe this device and if appropriate claim it.
- *	Perform any platform specific requirements and then initialise
- *	the device.
- */
-
-int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
-{
-	struct max3107_port *s;
-	u16 buf[2];	/* Buffer for SPI transfers */
-	int retval;
-
-	pr_info("enter max3107 probe\n");
-
-	/* Allocate port structure */
-	s = kzalloc(sizeof(*s), GFP_KERNEL);
-	if (!s) {
-		pr_err("Allocating port structure failed\n");
-		return -ENOMEM;
-	}
-
-	s->pdata = pdata;
-
-	/* SPI Rx buffer
-	 * +2 for RX FIFO interrupt
-	 * disabling and RX level query
-	 */
-	s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
-	if (!s->rxbuf) {
-		pr_err("Allocating RX buffer failed\n");
-		retval = -ENOMEM;
-		goto err_free4;
-	}
-	s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
-	if (!s->rxstr) {
-		pr_err("Allocating RX buffer failed\n");
-		retval = -ENOMEM;
-		goto err_free3;
-	}
-	/* SPI Tx buffer
-	 * SPI transfer buffer
-	 * +3 for TX FIFO empty
-	 * interrupt disabling and
-	 * enabling and TX enabling
-	 */
-	s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
-	if (!s->txbuf) {
-		pr_err("Allocating TX buffer failed\n");
-		retval = -ENOMEM;
-		goto err_free2;
-	}
-	/* Initialize shared data lock */
-	spin_lock_init(&s->data_lock);
-
-	/* SPI intializations */
-	dev_set_drvdata(&spi->dev, s);
-	spi->mode = SPI_MODE_0;
-	spi->dev.platform_data = pdata;
-	spi->bits_per_word = 16;
-	s->ext_clk = pdata->ext_clk;
-	s->loopback = pdata->loopback;
-	spi_setup(spi);
-	s->spi = spi;
-
-	/* Check REV ID to ensure we are talking to what we expect */
-	buf[0] = MAX3107_REVID_REG;
-	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
-		dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
-		retval = -EIO;
-		goto err_free1;
-	}
-	if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
-		(buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
-		dev_err(&s->spi->dev, "REVID %x does not match\n",
-				(buf[0] & MAX3107_SPI_RX_DATA_MASK));
-		retval = -ENODEV;
-		goto err_free1;
-	}
-
-	/* Disable all interrupts */
-	buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000);
-	buf[0] |= 0x0000;
-
-	/* Configure clock source */
-	buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG);
-	if (s->ext_clk) {
-		/* External clock */
-		buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT;
-	}
-
-	/* PLL bypass ON */
-	buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT;
-
-	/* Perform SPI transfer */
-	if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
-		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-		retval = -EIO;
-		goto err_free1;
-	}
-
-	/* Register UART driver */
-	if (!driver_registered) {
-		retval = uart_register_driver(&max3107_uart_driver);
-		if (retval) {
-			dev_err(&s->spi->dev, "Registering UART driver failed\n");
-			goto err_free1;
-		}
-		driver_registered = 1;
-	}
-
-	/* Initialize UART port data */
-	s->port.fifosize = 128;
-	s->port.ops = &max3107_ops;
-	s->port.line = 0;
-	s->port.dev = &spi->dev;
-	s->port.uartclk = 9600;
-	s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
-	s->port.irq = s->spi->irq;
-	s->port.type = PORT_MAX3107;
-
-	/* Add UART port */
-	retval = uart_add_one_port(&max3107_uart_driver, &s->port);
-	if (retval < 0) {
-		dev_err(&s->spi->dev, "Adding UART port failed\n");
-		goto err_free1;
-	}
-
-	if (pdata->configure) {
-		retval = pdata->configure(s);
-		if (retval < 0)
-			goto err_free1;
-	}
-
-	/* Go to suspend mode */
-	if (pdata->hw_suspend)
-		pdata->hw_suspend(s, 1);
-
-	return 0;
-
-err_free1:
-	kfree(s->txbuf);
-err_free2:
-	kfree(s->rxstr);
-err_free3:
-	kfree(s->rxbuf);
-err_free4:
-	kfree(s);
-	return retval;
-}
-EXPORT_SYMBOL_GPL(max3107_probe);
-
-/* Driver remove function */
-int max3107_remove(struct spi_device *spi)
-{
-	struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
-	pr_info("enter max3107 remove\n");
-
-	/* Remove port */
-	if (uart_remove_one_port(&max3107_uart_driver, &s->port))
-		dev_warn(&s->spi->dev, "Removing UART port failed\n");
-
-
-	/* Free TxRx buffer */
-	kfree(s->rxbuf);
-	kfree(s->rxstr);
-	kfree(s->txbuf);
-
-	/* Free port structure */
-	kfree(s);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_remove);
-
-/* Driver suspend function */
-int max3107_suspend(struct spi_device *spi, pm_message_t state)
-{
-#ifdef CONFIG_PM
-	struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
-	pr_debug("enter suspend\n");
-
-	/* Suspend UART port */
-	uart_suspend_port(&max3107_uart_driver, &s->port);
-
-	/* Go to suspend mode */
-	if (s->pdata->hw_suspend)
-		s->pdata->hw_suspend(s, 1);
-#endif	/* CONFIG_PM */
-	return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_suspend);
-
-/* Driver resume function */
-int max3107_resume(struct spi_device *spi)
-{
-#ifdef CONFIG_PM
-	struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
-	pr_debug("enter resume\n");
-
-	/* Resume from suspend */
-	if (s->pdata->hw_suspend)
-		s->pdata->hw_suspend(s, 0);
-
-	/* Resume UART port */
-	uart_resume_port(&max3107_uart_driver, &s->port);
-#endif	/* CONFIG_PM */
-	return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_resume);
-
-static int max3107_probe_generic(struct spi_device *spi)
-{
-	return max3107_probe(spi, &generic_plat_data);
-}
-
-/* Spi driver data */
-static struct spi_driver max3107_driver = {
-	.driver = {
-		.name		= "max3107",
-		.owner		= THIS_MODULE,
-	},
-	.probe		= max3107_probe_generic,
-	.remove		= __devexit_p(max3107_remove),
-	.suspend	= max3107_suspend,
-	.resume		= max3107_resume,
-};
-
-/* Driver init function */
-static int __init max3107_init(void)
-{
-	pr_info("enter max3107 init\n");
-	return spi_register_driver(&max3107_driver);
-}
-
-/* Driver exit function */
-static void __exit max3107_exit(void)
-{
-	pr_info("enter max3107 exit\n");
-	/* Unregister UART driver */
-	if (driver_registered)
-		uart_unregister_driver(&max3107_uart_driver);
-	spi_unregister_driver(&max3107_driver);
-}
-
-module_init(max3107_init);
-module_exit(max3107_exit);
-
-MODULE_DESCRIPTION("MAX3107 driver");
-MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("spi:max3107");
-MODULE_LICENSE("GPL v2");

+ 0 - 441
drivers/tty/serial/max3107.h

@@ -1,441 +0,0 @@
-/*
- * max3107.h - spi uart protocol driver header for Maxim 3107
- *
- * Copyright (C) Aavamobile 2009
- * Based on serial_max3100.h by Christian Pellegrin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef _MAX3107_H
-#define _MAX3107_H
-
-/* Serial error status definitions */
-#define MAX3107_PARITY_ERROR	1
-#define MAX3107_FRAME_ERROR	2
-#define MAX3107_OVERRUN_ERROR	4
-#define MAX3107_ALL_ERRORS	(MAX3107_PARITY_ERROR | \
-				 MAX3107_FRAME_ERROR | \
-				 MAX3107_OVERRUN_ERROR)
-
-/* GPIO definitions */
-#define MAX3107_GPIO_BASE	88
-#define MAX3107_GPIO_COUNT	4
-
-
-/* GPIO connected to chip's reset pin */
-#define MAX3107_RESET_GPIO	87
-
-
-/* Chip reset delay */
-#define MAX3107_RESET_DELAY	10
-
-/* Chip wakeup delay */
-#define MAX3107_WAKEUP_DELAY	50
-
-
-/* Sleep mode definitions */
-#define MAX3107_DISABLE_FORCED_SLEEP	0
-#define MAX3107_ENABLE_FORCED_SLEEP	1
-#define MAX3107_DISABLE_AUTOSLEEP	2
-#define MAX3107_ENABLE_AUTOSLEEP	3
-
-
-/* Definitions for register access with SPI transfers
- *
- * SPI transfer format:
- *
- * Master to slave bits xzzzzzzzyyyyyyyy
- * Slave to master bits aaaaaaaabbbbbbbb
- *
- * where:
- * x = 0 for reads, 1 for writes
- * z = register address
- * y = new register value if write, 0 if read
- * a = unspecified
- * b = register value if read, unspecified if write
- */
-
-/* SPI speed */
-#define MAX3107_SPI_SPEED	(3125000 * 2)
-
-/* Write bit */
-#define MAX3107_WRITE_BIT	(1 << 15)
-
-/* SPI TX data mask */
-#define MAX3107_SPI_RX_DATA_MASK	(0x00ff)
-
-/* SPI RX data mask */
-#define MAX3107_SPI_TX_DATA_MASK	(0x00ff)
-
-/* Register access masks */
-#define MAX3107_RHR_REG			(0x0000) /* RX FIFO */
-#define MAX3107_THR_REG			(0x0000) /* TX FIFO */
-#define MAX3107_IRQEN_REG		(0x0100) /* IRQ enable */
-#define MAX3107_IRQSTS_REG		(0x0200) /* IRQ status */
-#define MAX3107_LSR_IRQEN_REG		(0x0300) /* LSR IRQ enable */
-#define MAX3107_LSR_IRQSTS_REG		(0x0400) /* LSR IRQ status */
-#define MAX3107_SPCHR_IRQEN_REG		(0x0500) /* Special char IRQ enable */
-#define MAX3107_SPCHR_IRQSTS_REG	(0x0600) /* Special char IRQ status */
-#define MAX3107_STS_IRQEN_REG		(0x0700) /* Status IRQ enable */
-#define MAX3107_STS_IRQSTS_REG		(0x0800) /* Status IRQ status */
-#define MAX3107_MODE1_REG		(0x0900) /* MODE1 */
-#define MAX3107_MODE2_REG		(0x0a00) /* MODE2 */
-#define MAX3107_LCR_REG			(0x0b00) /* LCR */
-#define MAX3107_RXTO_REG		(0x0c00) /* RX timeout */
-#define MAX3107_HDPIXDELAY_REG		(0x0d00) /* Auto transceiver delays */
-#define MAX3107_IRDA_REG		(0x0e00) /* IRDA settings */
-#define MAX3107_FLOWLVL_REG		(0x0f00) /* Flow control levels */
-#define MAX3107_FIFOTRIGLVL_REG		(0x1000) /* FIFO IRQ trigger levels */
-#define MAX3107_TXFIFOLVL_REG		(0x1100) /* TX FIFO level */
-#define MAX3107_RXFIFOLVL_REG		(0x1200) /* RX FIFO level */
-#define MAX3107_FLOWCTRL_REG		(0x1300) /* Flow control */
-#define MAX3107_XON1_REG		(0x1400) /* XON1 character */
-#define MAX3107_XON2_REG		(0x1500) /* XON2 character */
-#define MAX3107_XOFF1_REG		(0x1600) /* XOFF1 character */
-#define MAX3107_XOFF2_REG		(0x1700) /* XOFF2 character */
-#define MAX3107_GPIOCFG_REG		(0x1800) /* GPIO config */
-#define MAX3107_GPIODATA_REG		(0x1900) /* GPIO data */
-#define MAX3107_PLLCFG_REG		(0x1a00) /* PLL config */
-#define MAX3107_BRGCFG_REG		(0x1b00) /* Baud rate generator conf */
-#define MAX3107_BRGDIVLSB_REG		(0x1c00) /* Baud rate divisor LSB */
-#define MAX3107_BRGDIVMSB_REG		(0x1d00) /* Baud rate divisor MSB */
-#define MAX3107_CLKSRC_REG		(0x1e00) /* Clock source */
-#define MAX3107_REVID_REG		(0x1f00) /* Revision identification */
-
-/* IRQ register bits */
-#define MAX3107_IRQ_LSR_BIT	(1 << 0) /* LSR interrupt */
-#define MAX3107_IRQ_SPCHR_BIT	(1 << 1) /* Special char interrupt */
-#define MAX3107_IRQ_STS_BIT	(1 << 2) /* Status interrupt */
-#define MAX3107_IRQ_RXFIFO_BIT	(1 << 3) /* RX FIFO interrupt */
-#define MAX3107_IRQ_TXFIFO_BIT	(1 << 4) /* TX FIFO interrupt */
-#define MAX3107_IRQ_TXEMPTY_BIT	(1 << 5) /* TX FIFO empty interrupt */
-#define MAX3107_IRQ_RXEMPTY_BIT	(1 << 6) /* RX FIFO empty interrupt */
-#define MAX3107_IRQ_CTS_BIT	(1 << 7) /* CTS interrupt */
-
-/* LSR register bits */
-#define MAX3107_LSR_RXTO_BIT	(1 << 0) /* RX timeout */
-#define MAX3107_LSR_RXOVR_BIT	(1 << 1) /* RX overrun */
-#define MAX3107_LSR_RXPAR_BIT	(1 << 2) /* RX parity error */
-#define MAX3107_LSR_FRERR_BIT	(1 << 3) /* Frame error */
-#define MAX3107_LSR_RXBRK_BIT	(1 << 4) /* RX break */
-#define MAX3107_LSR_RXNOISE_BIT	(1 << 5) /* RX noise */
-#define MAX3107_LSR_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
-#define MAX3107_LSR_CTS_BIT	(1 << 7) /* CTS pin state */
-
-/* Special character register bits */
-#define MAX3107_SPCHR_XON1_BIT		(1 << 0) /* XON1 character */
-#define MAX3107_SPCHR_XON2_BIT		(1 << 1) /* XON2 character */
-#define MAX3107_SPCHR_XOFF1_BIT		(1 << 2) /* XOFF1 character */
-#define MAX3107_SPCHR_XOFF2_BIT		(1 << 3) /* XOFF2 character */
-#define MAX3107_SPCHR_BREAK_BIT		(1 << 4) /* RX break */
-#define MAX3107_SPCHR_MULTIDROP_BIT	(1 << 5) /* 9-bit multidrop addr char */
-#define MAX3107_SPCHR_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
-#define MAX3107_SPCHR_UNDEF7_BIT	(1 << 7) /* Undefined/not used */
-
-/* Status register bits */
-#define MAX3107_STS_GPIO0_BIT		(1 << 0) /* GPIO 0 interrupt */
-#define MAX3107_STS_GPIO1_BIT		(1 << 1) /* GPIO 1 interrupt */
-#define MAX3107_STS_GPIO2_BIT		(1 << 2) /* GPIO 2 interrupt */
-#define MAX3107_STS_GPIO3_BIT		(1 << 3) /* GPIO 3 interrupt */
-#define MAX3107_STS_UNDEF4_BIT		(1 << 4) /* Undefined/not used */
-#define MAX3107_STS_CLKREADY_BIT	(1 << 5) /* Clock ready */
-#define MAX3107_STS_SLEEP_BIT		(1 << 6) /* Sleep interrupt */
-#define MAX3107_STS_UNDEF7_BIT		(1 << 7) /* Undefined/not used */
-
-/* MODE1 register bits */
-#define MAX3107_MODE1_RXDIS_BIT		(1 << 0) /* RX disable */
-#define MAX3107_MODE1_TXDIS_BIT		(1 << 1) /* TX disable */
-#define MAX3107_MODE1_TXHIZ_BIT		(1 << 2) /* TX pin three-state */
-#define MAX3107_MODE1_RTSHIZ_BIT	(1 << 3) /* RTS pin three-state */
-#define MAX3107_MODE1_TRNSCVCTRL_BIT	(1 << 4) /* Transceiver ctrl enable */
-#define MAX3107_MODE1_FORCESLEEP_BIT	(1 << 5) /* Force sleep mode */
-#define MAX3107_MODE1_AUTOSLEEP_BIT	(1 << 6) /* Auto sleep enable */
-#define MAX3107_MODE1_IRQSEL_BIT	(1 << 7) /* IRQ pin enable */
-
-/* MODE2 register bits */
-#define MAX3107_MODE2_RST_BIT		(1 << 0) /* Chip reset */
-#define MAX3107_MODE2_FIFORST_BIT	(1 << 1) /* FIFO reset */
-#define MAX3107_MODE2_RXTRIGINV_BIT	(1 << 2) /* RX FIFO INT invert */
-#define MAX3107_MODE2_RXEMPTINV_BIT	(1 << 3) /* RX FIFO empty INT invert */
-#define MAX3107_MODE2_SPCHR_BIT		(1 << 4) /* Special chr detect enable */
-#define MAX3107_MODE2_LOOPBACK_BIT	(1 << 5) /* Internal loopback enable */
-#define MAX3107_MODE2_MULTIDROP_BIT	(1 << 6) /* 9-bit multidrop enable */
-#define MAX3107_MODE2_ECHOSUPR_BIT	(1 << 7) /* ECHO suppression enable */
-
-/* LCR register bits */
-#define MAX3107_LCR_LENGTH0_BIT		(1 << 0) /* Word length bit 0 */
-#define MAX3107_LCR_LENGTH1_BIT		(1 << 1) /* Word length bit 1
-						  *
-						  * Word length bits table:
-						  * 00 -> 5 bit words
-						  * 01 -> 6 bit words
-						  * 10 -> 7 bit words
-						  * 11 -> 8 bit words
-						  */
-#define MAX3107_LCR_STOPLEN_BIT		(1 << 2) /* STOP length bit
-						  *
-						  * STOP length bit table:
-						  * 0 -> 1 stop bit
-						  * 1 -> 1-1.5 stop bits if
-						  *      word length is 5,
-						  *      2 stop bits otherwise
-						  */
-#define MAX3107_LCR_PARITY_BIT		(1 << 3) /* Parity bit enable */
-#define MAX3107_LCR_EVENPARITY_BIT	(1 << 4) /* Even parity bit enable */
-#define MAX3107_LCR_FORCEPARITY_BIT	(1 << 5) /* 9-bit multidrop parity */
-#define MAX3107_LCR_TXBREAK_BIT		(1 << 6) /* TX break enable */
-#define MAX3107_LCR_RTS_BIT		(1 << 7) /* RTS pin control */
-#define MAX3107_LCR_WORD_LEN_5		(0x0000)
-#define MAX3107_LCR_WORD_LEN_6		(0x0001)
-#define MAX3107_LCR_WORD_LEN_7		(0x0002)
-#define MAX3107_LCR_WORD_LEN_8		(0x0003)
-
-
-/* IRDA register bits */
-#define MAX3107_IRDA_IRDAEN_BIT		(1 << 0) /* IRDA mode enable */
-#define MAX3107_IRDA_SIR_BIT		(1 << 1) /* SIR mode enable */
-#define MAX3107_IRDA_SHORTIR_BIT	(1 << 2) /* Short SIR mode enable */
-#define MAX3107_IRDA_MIR_BIT		(1 << 3) /* MIR mode enable */
-#define MAX3107_IRDA_RXINV_BIT		(1 << 4) /* RX logic inversion enable */
-#define MAX3107_IRDA_TXINV_BIT		(1 << 5) /* TX logic inversion enable */
-#define MAX3107_IRDA_UNDEF6_BIT		(1 << 6) /* Undefined/not used */
-#define MAX3107_IRDA_UNDEF7_BIT		(1 << 7) /* Undefined/not used */
-
-/* Flow control trigger level register masks */
-#define MAX3107_FLOWLVL_HALT_MASK	(0x000f) /* Flow control halt level */
-#define MAX3107_FLOWLVL_RES_MASK	(0x00f0) /* Flow control resume level */
-#define MAX3107_FLOWLVL_HALT(words)	((words/8) & 0x000f)
-#define MAX3107_FLOWLVL_RES(words)	(((words/8) & 0x000f) << 4)
-
-/* FIFO interrupt trigger level register masks */
-#define MAX3107_FIFOTRIGLVL_TX_MASK	(0x000f) /* TX FIFO trigger level */
-#define MAX3107_FIFOTRIGLVL_RX_MASK	(0x00f0) /* RX FIFO trigger level */
-#define MAX3107_FIFOTRIGLVL_TX(words)	((words/8) & 0x000f)
-#define MAX3107_FIFOTRIGLVL_RX(words)	(((words/8) & 0x000f) << 4)
-
-/* Flow control register bits */
-#define MAX3107_FLOWCTRL_AUTORTS_BIT	(1 << 0) /* Auto RTS flow ctrl enable */
-#define MAX3107_FLOWCTRL_AUTOCTS_BIT	(1 << 1) /* Auto CTS flow ctrl enable */
-#define MAX3107_FLOWCTRL_GPIADDR_BIT	(1 << 2) /* Enables that GPIO inputs
-						  * are used in conjunction with
-						  * XOFF2 for definition of
-						  * special character */
-#define MAX3107_FLOWCTRL_SWFLOWEN_BIT	(1 << 3) /* Auto SW flow ctrl enable */
-#define MAX3107_FLOWCTRL_SWFLOW0_BIT	(1 << 4) /* SWFLOW bit 0 */
-#define MAX3107_FLOWCTRL_SWFLOW1_BIT	(1 << 5) /* SWFLOW bit 1
-						  *
-						  * SWFLOW bits 1 & 0 table:
-						  * 00 -> no transmitter flow
-						  *       control
-						  * 01 -> receiver compares
-						  *       XON2 and XOFF2
-						  *       and controls
-						  *       transmitter
-						  * 10 -> receiver compares
-						  *       XON1 and XOFF1
-						  *       and controls
-						  *       transmitter
-						  * 11 -> receiver compares
-						  *       XON1, XON2, XOFF1 and
-						  *       XOFF2 and controls
-						  *       transmitter
-						  */
-#define MAX3107_FLOWCTRL_SWFLOW2_BIT	(1 << 6) /* SWFLOW bit 2 */
-#define MAX3107_FLOWCTRL_SWFLOW3_BIT	(1 << 7) /* SWFLOW bit 3
-						  *
-						  * SWFLOW bits 3 & 2 table:
-						  * 00 -> no received flow
-						  *       control
-						  * 01 -> transmitter generates
-						  *       XON2 and XOFF2
-						  * 10 -> transmitter generates
-						  *       XON1 and XOFF1
-						  * 11 -> transmitter generates
-						  *       XON1, XON2, XOFF1 and
-						  *       XOFF2
-						  */
-
-/* GPIO configuration register bits */
-#define MAX3107_GPIOCFG_GP0OUT_BIT	(1 << 0) /* GPIO 0 output enable */
-#define MAX3107_GPIOCFG_GP1OUT_BIT	(1 << 1) /* GPIO 1 output enable */
-#define MAX3107_GPIOCFG_GP2OUT_BIT	(1 << 2) /* GPIO 2 output enable */
-#define MAX3107_GPIOCFG_GP3OUT_BIT	(1 << 3) /* GPIO 3 output enable */
-#define MAX3107_GPIOCFG_GP0OD_BIT	(1 << 4) /* GPIO 0 open-drain enable */
-#define MAX3107_GPIOCFG_GP1OD_BIT	(1 << 5) /* GPIO 1 open-drain enable */
-#define MAX3107_GPIOCFG_GP2OD_BIT	(1 << 6) /* GPIO 2 open-drain enable */
-#define MAX3107_GPIOCFG_GP3OD_BIT	(1 << 7) /* GPIO 3 open-drain enable */
-
-/* GPIO DATA register bits */
-#define MAX3107_GPIODATA_GP0OUT_BIT	(1 << 0) /* GPIO 0 output value */
-#define MAX3107_GPIODATA_GP1OUT_BIT	(1 << 1) /* GPIO 1 output value */
-#define MAX3107_GPIODATA_GP2OUT_BIT	(1 << 2) /* GPIO 2 output value */
-#define MAX3107_GPIODATA_GP3OUT_BIT	(1 << 3) /* GPIO 3 output value */
-#define MAX3107_GPIODATA_GP0IN_BIT	(1 << 4) /* GPIO 0 input value */
-#define MAX3107_GPIODATA_GP1IN_BIT	(1 << 5) /* GPIO 1 input value */
-#define MAX3107_GPIODATA_GP2IN_BIT	(1 << 6) /* GPIO 2 input value */
-#define MAX3107_GPIODATA_GP3IN_BIT	(1 << 7) /* GPIO 3 input value */
-
-/* PLL configuration register masks */
-#define MAX3107_PLLCFG_PREDIV_MASK	(0x003f) /* PLL predivision value */
-#define MAX3107_PLLCFG_PLLFACTOR_MASK	(0x00c0) /* PLL multiplication factor */
-
-/* Baud rate generator configuration register masks and bits */
-#define MAX3107_BRGCFG_FRACT_MASK	(0x000f) /* Fractional portion of
-						  * Baud rate generator divisor
-						  */
-#define MAX3107_BRGCFG_2XMODE_BIT	(1 << 4) /* Double baud rate */
-#define MAX3107_BRGCFG_4XMODE_BIT	(1 << 5) /* Quadruple baud rate */
-#define MAX3107_BRGCFG_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
-#define MAX3107_BRGCFG_UNDEF7_BIT	(1 << 7) /* Undefined/not used */
-
-/* Clock source register bits */
-#define MAX3107_CLKSRC_INTOSC_BIT	(1 << 0) /* Internal osc enable */
-#define MAX3107_CLKSRC_CRYST_BIT	(1 << 1) /* Crystal osc enable */
-#define MAX3107_CLKSRC_PLL_BIT		(1 << 2) /* PLL enable */
-#define MAX3107_CLKSRC_PLLBYP_BIT	(1 << 3) /* PLL bypass */
-#define MAX3107_CLKSRC_EXTCLK_BIT	(1 << 4) /* External clock enable */
-#define MAX3107_CLKSRC_UNDEF5_BIT	(1 << 5) /* Undefined/not used */
-#define MAX3107_CLKSRC_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
-#define MAX3107_CLKSRC_CLK2RTS_BIT	(1 << 7) /* Baud clk to RTS pin */
-
-
-/* HW definitions */
-#define MAX3107_RX_FIFO_SIZE	128
-#define MAX3107_TX_FIFO_SIZE	128
-#define MAX3107_REVID1		0x00a0
-#define MAX3107_REVID2		0x00a1
-
-
-/* Baud rate generator configuration values for external clock 13MHz */
-#define MAX3107_BRG13_B300	(0x0A9400 | 0x05)
-#define MAX3107_BRG13_B600	(0x054A00 | 0x03)
-#define MAX3107_BRG13_B1200	(0x02A500 | 0x01)
-#define MAX3107_BRG13_B2400	(0x015200 | 0x09)
-#define MAX3107_BRG13_B4800	(0x00A900 | 0x04)
-#define MAX3107_BRG13_B9600	(0x005400 | 0x0A)
-#define MAX3107_BRG13_B19200	(0x002A00 | 0x05)
-#define MAX3107_BRG13_B38400	(0x001500 | 0x03)
-#define MAX3107_BRG13_B57600	(0x000E00 | 0x02)
-#define MAX3107_BRG13_B115200	(0x000700 | 0x01)
-#define MAX3107_BRG13_B230400	(0x000300 | 0x08)
-#define MAX3107_BRG13_B460800	(0x000100 | 0x0c)
-#define MAX3107_BRG13_B921600	(0x000100 | 0x1c)
-
-/* Baud rate generator configuration values for external clock 26MHz */
-#define MAX3107_BRG26_B300	(0x152800 | 0x0A)
-#define MAX3107_BRG26_B600	(0x0A9400 | 0x05)
-#define MAX3107_BRG26_B1200	(0x054A00 | 0x03)
-#define MAX3107_BRG26_B2400	(0x02A500 | 0x01)
-#define MAX3107_BRG26_B4800	(0x015200 | 0x09)
-#define MAX3107_BRG26_B9600	(0x00A900 | 0x04)
-#define MAX3107_BRG26_B19200	(0x005400 | 0x0A)
-#define MAX3107_BRG26_B38400	(0x002A00 | 0x05)
-#define MAX3107_BRG26_B57600	(0x001C00 | 0x03)
-#define MAX3107_BRG26_B115200	(0x000E00 | 0x02)
-#define MAX3107_BRG26_B230400	(0x000700 | 0x01)
-#define MAX3107_BRG26_B460800	(0x000300 | 0x08)
-#define MAX3107_BRG26_B921600	(0x000100 | 0x0C)
-
-/* Baud rate generator configuration values for internal clock */
-#define MAX3107_BRG13_IB300	(0x008000 | 0x00)
-#define MAX3107_BRG13_IB600	(0x004000 | 0x00)
-#define MAX3107_BRG13_IB1200	(0x002000 | 0x00)
-#define MAX3107_BRG13_IB2400	(0x001000 | 0x00)
-#define MAX3107_BRG13_IB4800	(0x000800 | 0x00)
-#define MAX3107_BRG13_IB9600	(0x000400 | 0x00)
-#define MAX3107_BRG13_IB19200	(0x000200 | 0x00)
-#define MAX3107_BRG13_IB38400	(0x000100 | 0x00)
-#define MAX3107_BRG13_IB57600	(0x000000 | 0x0B)
-#define MAX3107_BRG13_IB115200	(0x000000 | 0x05)
-#define MAX3107_BRG13_IB230400	(0x000000 | 0x03)
-#define MAX3107_BRG13_IB460800	(0x000000 | 0x00)
-#define MAX3107_BRG13_IB921600	(0x000000 | 0x00)
-
-
-struct baud_table {
-	int baud;
-	u32 new_brg;
-};
-
-struct max3107_port {
-	/* UART port structure */
-	struct uart_port port;
-
-	/* SPI device structure */
-	struct spi_device *spi;
-
-#if defined(CONFIG_GPIOLIB)
-	/* GPIO chip structure */
-	struct gpio_chip chip;
-#endif
-
-	/* Workqueue that does all the magic */
-	struct workqueue_struct *workqueue;
-	struct work_struct work;
-
-	/* Lock for shared data */
-	spinlock_t data_lock;
-
-	/* Device configuration */
-	int ext_clk;		/* 1 if external clock used */
-	int loopback;		/* Current loopback mode state */
-	int baud;			/* Current baud rate */
-
-	/* State flags */
-	int suspended;		/* Indicates suspend mode */
-	int tx_fifo_empty;	/* Flag for TX FIFO state */
-	int rx_enabled;		/* Flag for receiver state */
-	int tx_enabled;		/* Flag for transmitter state */
-
-	u16 irqen_reg;		/* Current IRQ enable register value */
-	/* Shared data */
-	u16 mode1_reg;		/* Current mode1 register value*/
-	int mode1_commit;	/* Flag for setting new mode1 register value */
-	u16 lcr_reg;		/* Current LCR register value */
-	int lcr_commit;		/* Flag for setting new LCR register value */
-	u32 brg_cfg;		/* Current Baud rate generator config  */
-	int brg_commit;		/* Flag for setting new baud rate generator
-				 * config
-				 */
-	struct baud_table *baud_tbl;
-	int handle_irq;		/* Indicates that IRQ should be handled */
-
-	/* Rx buffer and str*/
-	u16 *rxbuf;
-	u8  *rxstr;
-	/* Tx buffer*/
-	u16 *txbuf;
-
-	struct max3107_plat *pdata;	/* Platform data */
-};
-
-/* Platform data structure */
-struct max3107_plat {
-	/* Loopback mode enable */
-	int loopback;
-	/* External clock enable */
-	int ext_clk;
-	/* Called during the register initialisation */
-	void (*init)(struct max3107_port *s);
-	/* Called when the port is found and configured */
-	int (*configure)(struct max3107_port *s);
-	/* HW suspend function */
-	void (*hw_suspend) (struct max3107_port *s, int suspend);
-	/* Polling mode enable */
-	int polled_mode;
-	/* Polling period if polling mode enabled */
-	int poll_time;
-};
-
-extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len);
-extern void max3107_hw_susp(struct max3107_port *s, int suspend);
-extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata);
-extern int max3107_remove(struct spi_device *spi);
-extern int max3107_suspend(struct spi_device *spi, pm_message_t state);
-extern int max3107_resume(struct spi_device *spi);
-
-#endif /* _LINUX_SERIAL_MAX3107_H */

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

@@ -0,0 +1,1260 @@
+/*
+ *  Maxim (Dallas) MAX3107/8 serial driver
+ *
+ *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ *  Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
+ *  Based on max3110.c, by Feng Tang <feng.tang@intel.com>
+ *  Based on max3107.c, by Aavamobile
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ */
+
+/* TODO: MAX3109 support (Dual) */
+/* TODO: MAX14830 support (Quad) */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/regmap.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_data/max310x.h>
+
+#define MAX310X_MAJOR			204
+#define MAX310X_MINOR			209
+
+/* MAX310X register definitions */
+#define MAX310X_RHR_REG			(0x00) /* RX FIFO */
+#define MAX310X_THR_REG			(0x00) /* TX FIFO */
+#define MAX310X_IRQEN_REG		(0x01) /* IRQ enable */
+#define MAX310X_IRQSTS_REG		(0x02) /* IRQ status */
+#define MAX310X_LSR_IRQEN_REG		(0x03) /* LSR IRQ enable */
+#define MAX310X_LSR_IRQSTS_REG		(0x04) /* LSR IRQ status */
+#define MAX310X_SPCHR_IRQEN_REG		(0x05) /* Special char IRQ enable */
+#define MAX310X_SPCHR_IRQSTS_REG	(0x06) /* Special char IRQ status */
+#define MAX310X_STS_IRQEN_REG		(0x07) /* Status IRQ enable */
+#define MAX310X_STS_IRQSTS_REG		(0x08) /* Status IRQ status */
+#define MAX310X_MODE1_REG		(0x09) /* MODE1 */
+#define MAX310X_MODE2_REG		(0x0a) /* MODE2 */
+#define MAX310X_LCR_REG			(0x0b) /* LCR */
+#define MAX310X_RXTO_REG		(0x0c) /* RX timeout */
+#define MAX310X_HDPIXDELAY_REG		(0x0d) /* Auto transceiver delays */
+#define MAX310X_IRDA_REG		(0x0e) /* IRDA settings */
+#define MAX310X_FLOWLVL_REG		(0x0f) /* Flow control levels */
+#define MAX310X_FIFOTRIGLVL_REG		(0x10) /* FIFO IRQ trigger levels */
+#define MAX310X_TXFIFOLVL_REG		(0x11) /* TX FIFO level */
+#define MAX310X_RXFIFOLVL_REG		(0x12) /* RX FIFO level */
+#define MAX310X_FLOWCTRL_REG		(0x13) /* Flow control */
+#define MAX310X_XON1_REG		(0x14) /* XON1 character */
+#define MAX310X_XON2_REG		(0x15) /* XON2 character */
+#define MAX310X_XOFF1_REG		(0x16) /* XOFF1 character */
+#define MAX310X_XOFF2_REG		(0x17) /* XOFF2 character */
+#define MAX310X_GPIOCFG_REG		(0x18) /* GPIO config */
+#define MAX310X_GPIODATA_REG		(0x19) /* GPIO data */
+#define MAX310X_PLLCFG_REG		(0x1a) /* PLL config */
+#define MAX310X_BRGCFG_REG		(0x1b) /* Baud rate generator conf */
+#define MAX310X_BRGDIVLSB_REG		(0x1c) /* Baud rate divisor LSB */
+#define MAX310X_BRGDIVMSB_REG		(0x1d) /* Baud rate divisor MSB */
+#define MAX310X_CLKSRC_REG		(0x1e) /* Clock source */
+/* Only present in MAX3107 */
+#define MAX3107_REVID_REG		(0x1f) /* Revision identification */
+
+/* IRQ register bits */
+#define MAX310X_IRQ_LSR_BIT		(1 << 0) /* LSR interrupt */
+#define MAX310X_IRQ_SPCHR_BIT		(1 << 1) /* Special char interrupt */
+#define MAX310X_IRQ_STS_BIT		(1 << 2) /* Status interrupt */
+#define MAX310X_IRQ_RXFIFO_BIT		(1 << 3) /* RX FIFO interrupt */
+#define MAX310X_IRQ_TXFIFO_BIT		(1 << 4) /* TX FIFO interrupt */
+#define MAX310X_IRQ_TXEMPTY_BIT		(1 << 5) /* TX FIFO empty interrupt */
+#define MAX310X_IRQ_RXEMPTY_BIT		(1 << 6) /* RX FIFO empty interrupt */
+#define MAX310X_IRQ_CTS_BIT		(1 << 7) /* CTS interrupt */
+
+/* LSR register bits */
+#define MAX310X_LSR_RXTO_BIT		(1 << 0) /* RX timeout */
+#define MAX310X_LSR_RXOVR_BIT		(1 << 1) /* RX overrun */
+#define MAX310X_LSR_RXPAR_BIT		(1 << 2) /* RX parity error */
+#define MAX310X_LSR_FRERR_BIT		(1 << 3) /* Frame error */
+#define MAX310X_LSR_RXBRK_BIT		(1 << 4) /* RX break */
+#define MAX310X_LSR_RXNOISE_BIT		(1 << 5) /* RX noise */
+#define MAX310X_LSR_CTS_BIT		(1 << 7) /* CTS pin state */
+
+/* Special character register bits */
+#define MAX310X_SPCHR_XON1_BIT		(1 << 0) /* XON1 character */
+#define MAX310X_SPCHR_XON2_BIT		(1 << 1) /* XON2 character */
+#define MAX310X_SPCHR_XOFF1_BIT		(1 << 2) /* XOFF1 character */
+#define MAX310X_SPCHR_XOFF2_BIT		(1 << 3) /* XOFF2 character */
+#define MAX310X_SPCHR_BREAK_BIT		(1 << 4) /* RX break */
+#define MAX310X_SPCHR_MULTIDROP_BIT	(1 << 5) /* 9-bit multidrop addr char */
+
+/* Status register bits */
+#define MAX310X_STS_GPIO0_BIT		(1 << 0) /* GPIO 0 interrupt */
+#define MAX310X_STS_GPIO1_BIT		(1 << 1) /* GPIO 1 interrupt */
+#define MAX310X_STS_GPIO2_BIT		(1 << 2) /* GPIO 2 interrupt */
+#define MAX310X_STS_GPIO3_BIT		(1 << 3) /* GPIO 3 interrupt */
+#define MAX310X_STS_CLKREADY_BIT	(1 << 5) /* Clock ready */
+#define MAX310X_STS_SLEEP_BIT		(1 << 6) /* Sleep interrupt */
+
+/* MODE1 register bits */
+#define MAX310X_MODE1_RXDIS_BIT		(1 << 0) /* RX disable */
+#define MAX310X_MODE1_TXDIS_BIT		(1 << 1) /* TX disable */
+#define MAX310X_MODE1_TXHIZ_BIT		(1 << 2) /* TX pin three-state */
+#define MAX310X_MODE1_RTSHIZ_BIT	(1 << 3) /* RTS pin three-state */
+#define MAX310X_MODE1_TRNSCVCTRL_BIT	(1 << 4) /* Transceiver ctrl enable */
+#define MAX310X_MODE1_FORCESLEEP_BIT	(1 << 5) /* Force sleep mode */
+#define MAX310X_MODE1_AUTOSLEEP_BIT	(1 << 6) /* Auto sleep enable */
+#define MAX310X_MODE1_IRQSEL_BIT	(1 << 7) /* IRQ pin enable */
+
+/* MODE2 register bits */
+#define MAX310X_MODE2_RST_BIT		(1 << 0) /* Chip reset */
+#define MAX310X_MODE2_FIFORST_BIT	(1 << 1) /* FIFO reset */
+#define MAX310X_MODE2_RXTRIGINV_BIT	(1 << 2) /* RX FIFO INT invert */
+#define MAX310X_MODE2_RXEMPTINV_BIT	(1 << 3) /* RX FIFO empty INT invert */
+#define MAX310X_MODE2_SPCHR_BIT		(1 << 4) /* Special chr detect enable */
+#define MAX310X_MODE2_LOOPBACK_BIT	(1 << 5) /* Internal loopback enable */
+#define MAX310X_MODE2_MULTIDROP_BIT	(1 << 6) /* 9-bit multidrop enable */
+#define MAX310X_MODE2_ECHOSUPR_BIT	(1 << 7) /* ECHO suppression enable */
+
+/* LCR register bits */
+#define MAX310X_LCR_LENGTH0_BIT		(1 << 0) /* Word length bit 0 */
+#define MAX310X_LCR_LENGTH1_BIT		(1 << 1) /* Word length bit 1
+						  *
+						  * Word length bits table:
+						  * 00 -> 5 bit words
+						  * 01 -> 6 bit words
+						  * 10 -> 7 bit words
+						  * 11 -> 8 bit words
+						  */
+#define MAX310X_LCR_STOPLEN_BIT		(1 << 2) /* STOP length bit
+						  *
+						  * STOP length bit table:
+						  * 0 -> 1 stop bit
+						  * 1 -> 1-1.5 stop bits if
+						  *      word length is 5,
+						  *      2 stop bits otherwise
+						  */
+#define MAX310X_LCR_PARITY_BIT		(1 << 3) /* Parity bit enable */
+#define MAX310X_LCR_EVENPARITY_BIT	(1 << 4) /* Even parity bit enable */
+#define MAX310X_LCR_FORCEPARITY_BIT	(1 << 5) /* 9-bit multidrop parity */
+#define MAX310X_LCR_TXBREAK_BIT		(1 << 6) /* TX break enable */
+#define MAX310X_LCR_RTS_BIT		(1 << 7) /* RTS pin control */
+#define MAX310X_LCR_WORD_LEN_5		(0x00)
+#define MAX310X_LCR_WORD_LEN_6		(0x01)
+#define MAX310X_LCR_WORD_LEN_7		(0x02)
+#define MAX310X_LCR_WORD_LEN_8		(0x03)
+
+/* IRDA register bits */
+#define MAX310X_IRDA_IRDAEN_BIT		(1 << 0) /* IRDA mode enable */
+#define MAX310X_IRDA_SIR_BIT		(1 << 1) /* SIR mode enable */
+#define MAX310X_IRDA_SHORTIR_BIT	(1 << 2) /* Short SIR mode enable */
+#define MAX310X_IRDA_MIR_BIT		(1 << 3) /* MIR mode enable */
+#define MAX310X_IRDA_RXINV_BIT		(1 << 4) /* RX logic inversion enable */
+#define MAX310X_IRDA_TXINV_BIT		(1 << 5) /* TX logic inversion enable */
+
+/* Flow control trigger level register masks */
+#define MAX310X_FLOWLVL_HALT_MASK	(0x000f) /* Flow control halt level */
+#define MAX310X_FLOWLVL_RES_MASK	(0x00f0) /* Flow control resume level */
+#define MAX310X_FLOWLVL_HALT(words)	((words / 8) & 0x0f)
+#define MAX310X_FLOWLVL_RES(words)	(((words / 8) & 0x0f) << 4)
+
+/* FIFO interrupt trigger level register masks */
+#define MAX310X_FIFOTRIGLVL_TX_MASK	(0x0f) /* TX FIFO trigger level */
+#define MAX310X_FIFOTRIGLVL_RX_MASK	(0xf0) /* RX FIFO trigger level */
+#define MAX310X_FIFOTRIGLVL_TX(words)	((words / 8) & 0x0f)
+#define MAX310X_FIFOTRIGLVL_RX(words)	(((words / 8) & 0x0f) << 4)
+
+/* Flow control register bits */
+#define MAX310X_FLOWCTRL_AUTORTS_BIT	(1 << 0) /* Auto RTS flow ctrl enable */
+#define MAX310X_FLOWCTRL_AUTOCTS_BIT	(1 << 1) /* Auto CTS flow ctrl enable */
+#define MAX310X_FLOWCTRL_GPIADDR_BIT	(1 << 2) /* Enables that GPIO inputs
+						  * are used in conjunction with
+						  * XOFF2 for definition of
+						  * special character */
+#define MAX310X_FLOWCTRL_SWFLOWEN_BIT	(1 << 3) /* Auto SW flow ctrl enable */
+#define MAX310X_FLOWCTRL_SWFLOW0_BIT	(1 << 4) /* SWFLOW bit 0 */
+#define MAX310X_FLOWCTRL_SWFLOW1_BIT	(1 << 5) /* SWFLOW bit 1
+						  *
+						  * SWFLOW bits 1 & 0 table:
+						  * 00 -> no transmitter flow
+						  *       control
+						  * 01 -> receiver compares
+						  *       XON2 and XOFF2
+						  *       and controls
+						  *       transmitter
+						  * 10 -> receiver compares
+						  *       XON1 and XOFF1
+						  *       and controls
+						  *       transmitter
+						  * 11 -> receiver compares
+						  *       XON1, XON2, XOFF1 and
+						  *       XOFF2 and controls
+						  *       transmitter
+						  */
+#define MAX310X_FLOWCTRL_SWFLOW2_BIT	(1 << 6) /* SWFLOW bit 2 */
+#define MAX310X_FLOWCTRL_SWFLOW3_BIT	(1 << 7) /* SWFLOW bit 3
+						  *
+						  * SWFLOW bits 3 & 2 table:
+						  * 00 -> no received flow
+						  *       control
+						  * 01 -> transmitter generates
+						  *       XON2 and XOFF2
+						  * 10 -> transmitter generates
+						  *       XON1 and XOFF1
+						  * 11 -> transmitter generates
+						  *       XON1, XON2, XOFF1 and
+						  *       XOFF2
+						  */
+
+/* GPIO configuration register bits */
+#define MAX310X_GPIOCFG_GP0OUT_BIT	(1 << 0) /* GPIO 0 output enable */
+#define MAX310X_GPIOCFG_GP1OUT_BIT	(1 << 1) /* GPIO 1 output enable */
+#define MAX310X_GPIOCFG_GP2OUT_BIT	(1 << 2) /* GPIO 2 output enable */
+#define MAX310X_GPIOCFG_GP3OUT_BIT	(1 << 3) /* GPIO 3 output enable */
+#define MAX310X_GPIOCFG_GP0OD_BIT	(1 << 4) /* GPIO 0 open-drain enable */
+#define MAX310X_GPIOCFG_GP1OD_BIT	(1 << 5) /* GPIO 1 open-drain enable */
+#define MAX310X_GPIOCFG_GP2OD_BIT	(1 << 6) /* GPIO 2 open-drain enable */
+#define MAX310X_GPIOCFG_GP3OD_BIT	(1 << 7) /* GPIO 3 open-drain enable */
+
+/* GPIO DATA register bits */
+#define MAX310X_GPIODATA_GP0OUT_BIT	(1 << 0) /* GPIO 0 output value */
+#define MAX310X_GPIODATA_GP1OUT_BIT	(1 << 1) /* GPIO 1 output value */
+#define MAX310X_GPIODATA_GP2OUT_BIT	(1 << 2) /* GPIO 2 output value */
+#define MAX310X_GPIODATA_GP3OUT_BIT	(1 << 3) /* GPIO 3 output value */
+#define MAX310X_GPIODATA_GP0IN_BIT	(1 << 4) /* GPIO 0 input value */
+#define MAX310X_GPIODATA_GP1IN_BIT	(1 << 5) /* GPIO 1 input value */
+#define MAX310X_GPIODATA_GP2IN_BIT	(1 << 6) /* GPIO 2 input value */
+#define MAX310X_GPIODATA_GP3IN_BIT	(1 << 7) /* GPIO 3 input value */
+
+/* PLL configuration register masks */
+#define MAX310X_PLLCFG_PREDIV_MASK	(0x3f) /* PLL predivision value */
+#define MAX310X_PLLCFG_PLLFACTOR_MASK	(0xc0) /* PLL multiplication factor */
+
+/* Baud rate generator configuration register bits */
+#define MAX310X_BRGCFG_2XMODE_BIT	(1 << 4) /* Double baud rate */
+#define MAX310X_BRGCFG_4XMODE_BIT	(1 << 5) /* Quadruple baud rate */
+
+/* Clock source register bits */
+#define MAX310X_CLKSRC_CRYST_BIT	(1 << 1) /* Crystal osc enable */
+#define MAX310X_CLKSRC_PLL_BIT		(1 << 2) /* PLL enable */
+#define MAX310X_CLKSRC_PLLBYP_BIT	(1 << 3) /* PLL bypass */
+#define MAX310X_CLKSRC_EXTCLK_BIT	(1 << 4) /* External clock enable */
+#define MAX310X_CLKSRC_CLK2RTS_BIT	(1 << 7) /* Baud clk to RTS pin */
+
+/* Misc definitions */
+#define MAX310X_FIFO_SIZE		(128)
+
+/* MAX3107 specific */
+#define MAX3107_REV_ID			(0xa0)
+#define MAX3107_REV_MASK		(0xfe)
+
+/* IRQ status bits definitions */
+#define MAX310X_IRQ_TX			(MAX310X_IRQ_TXFIFO_BIT | \
+					 MAX310X_IRQ_TXEMPTY_BIT)
+#define MAX310X_IRQ_RX			(MAX310X_IRQ_RXFIFO_BIT | \
+					 MAX310X_IRQ_RXEMPTY_BIT)
+
+/* Supported chip types */
+enum {
+	MAX310X_TYPE_MAX3107	= 3107,
+	MAX310X_TYPE_MAX3108	= 3108,
+};
+
+struct max310x_port {
+	struct uart_driver	uart;
+	struct uart_port	port;
+
+	const char		*name;
+	int			uartclk;
+
+	unsigned int		nr_gpio;
+#ifdef CONFIG_GPIOLIB
+	struct gpio_chip	gpio;
+#endif
+
+	struct regmap		*regmap;
+	struct regmap_config	regcfg;
+
+	struct workqueue_struct	*wq;
+	struct work_struct	tx_work;
+
+	struct mutex		max310x_mutex;
+
+	struct max310x_pdata	*pdata;
+};
+
+static bool max3107_8_reg_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX310X_IRQSTS_REG:
+	case MAX310X_LSR_IRQSTS_REG:
+	case MAX310X_SPCHR_IRQSTS_REG:
+	case MAX310X_STS_IRQSTS_REG:
+	case MAX310X_TXFIFOLVL_REG:
+	case MAX310X_RXFIFOLVL_REG:
+	case MAX3107_REVID_REG: /* Only available on MAX3107 */
+		return false;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX310X_RHR_REG:
+	case MAX310X_IRQSTS_REG:
+	case MAX310X_LSR_IRQSTS_REG:
+	case MAX310X_SPCHR_IRQSTS_REG:
+	case MAX310X_STS_IRQSTS_REG:
+	case MAX310X_TXFIFOLVL_REG:
+	case MAX310X_RXFIFOLVL_REG:
+	case MAX310X_GPIODATA_REG:
+		return true;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static bool max310x_reg_precious(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX310X_RHR_REG:
+	case MAX310X_IRQSTS_REG:
+	case MAX310X_SPCHR_IRQSTS_REG:
+	case MAX310X_STS_IRQSTS_REG:
+		return true;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static void max310x_set_baud(struct max310x_port *s, int baud)
+{
+	unsigned int mode = 0, div = s->uartclk / baud;
+
+	if (!(div / 16)) {
+		/* Mode x2 */
+		mode = MAX310X_BRGCFG_2XMODE_BIT;
+		div = (s->uartclk * 2) / baud;
+	}
+
+	if (!(div / 16)) {
+		/* Mode x4 */
+		mode = MAX310X_BRGCFG_4XMODE_BIT;
+		div = (s->uartclk * 4) / baud;
+	}
+
+	regmap_write(s->regmap, MAX310X_BRGDIVMSB_REG,
+		     ((div / 16) >> 8) & 0xff);
+	regmap_write(s->regmap, MAX310X_BRGDIVLSB_REG, (div / 16) & 0xff);
+	regmap_write(s->regmap, MAX310X_BRGCFG_REG, (div % 16) | mode);
+}
+
+static void max310x_wait_pll(struct max310x_port *s)
+{
+	int tryes = 1000;
+
+	/* Wait for PLL only if crystal is used */
+	if (!(s->pdata->driver_flags & MAX310X_EXT_CLK)) {
+		unsigned int sts = 0;
+
+		while (tryes--) {
+			regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &sts);
+			if (sts & MAX310X_STS_CLKREADY_BIT)
+				break;
+		}
+	}
+}
+
+static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
+{
+	/* Use baudrate 115200 for calculate error */
+	long err = f % (115200 * 16);
+
+	if ((*besterr < 0) || (*besterr > err)) {
+		*besterr = err;
+		return 0;
+	}
+
+	return 1;
+}
+
+static int __devinit max310x_set_ref_clk(struct max310x_port *s)
+{
+	unsigned int div, clksrc, pllcfg = 0;
+	long besterr = -1;
+	unsigned long fdiv, fmul, bestfreq = s->pdata->frequency;
+
+	/* First, update error without PLL */
+	max310x_update_best_err(s->pdata->frequency, &besterr);
+
+	/* Try all possible PLL dividers */
+	for (div = 1; (div <= 63) && besterr; div++) {
+		fdiv = DIV_ROUND_CLOSEST(s->pdata->frequency, div);
+
+		/* Try multiplier 6 */
+		fmul = fdiv * 6;
+		if ((fdiv >= 500000) && (fdiv <= 800000))
+			if (!max310x_update_best_err(fmul, &besterr)) {
+				pllcfg = (0 << 6) | div;
+				bestfreq = fmul;
+			}
+		/* Try multiplier 48 */
+		fmul = fdiv * 48;
+		if ((fdiv >= 850000) && (fdiv <= 1200000))
+			if (!max310x_update_best_err(fmul, &besterr)) {
+				pllcfg = (1 << 6) | div;
+				bestfreq = fmul;
+			}
+		/* Try multiplier 96 */
+		fmul = fdiv * 96;
+		if ((fdiv >= 425000) && (fdiv <= 1000000))
+			if (!max310x_update_best_err(fmul, &besterr)) {
+				pllcfg = (2 << 6) | div;
+				bestfreq = fmul;
+			}
+		/* Try multiplier 144 */
+		fmul = fdiv * 144;
+		if ((fdiv >= 390000) && (fdiv <= 667000))
+			if (!max310x_update_best_err(fmul, &besterr)) {
+				pllcfg = (3 << 6) | div;
+				bestfreq = fmul;
+			}
+	}
+
+	/* Configure clock source */
+	if (s->pdata->driver_flags & MAX310X_EXT_CLK)
+		clksrc = MAX310X_CLKSRC_EXTCLK_BIT;
+	else
+		clksrc = MAX310X_CLKSRC_CRYST_BIT;
+
+	/* Configure PLL */
+	if (pllcfg) {
+		clksrc |= MAX310X_CLKSRC_PLL_BIT;
+		regmap_write(s->regmap, MAX310X_PLLCFG_REG, pllcfg);
+	} else
+		clksrc |= MAX310X_CLKSRC_PLLBYP_BIT;
+
+	regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc);
+
+	if (pllcfg)
+		max310x_wait_pll(s);
+
+	dev_dbg(s->port.dev, "Reference clock set to %lu Hz\n", bestfreq);
+
+	return (int)bestfreq;
+}
+
+static void max310x_handle_rx(struct max310x_port *s, unsigned int rxlen)
+{
+	unsigned int sts = 0, ch = 0, flag;
+	struct tty_struct *tty = tty_port_tty_get(&s->port.state->port);
+
+	if (!tty)
+		return;
+
+	if (unlikely(rxlen >= MAX310X_FIFO_SIZE)) {
+		dev_warn(s->port.dev, "Possible RX FIFO overrun %d\n", rxlen);
+		/* Ensure sanity of RX level */
+		rxlen = MAX310X_FIFO_SIZE;
+	}
+
+	dev_dbg(s->port.dev, "RX Len = %u\n", rxlen);
+
+	while (rxlen--) {
+		regmap_read(s->regmap, MAX310X_RHR_REG, &ch);
+		regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &sts);
+
+		sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT |
+		       MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT;
+
+		s->port.icount.rx++;
+		flag = TTY_NORMAL;
+
+		if (unlikely(sts)) {
+			if (sts & MAX310X_LSR_RXBRK_BIT) {
+				s->port.icount.brk++;
+				if (uart_handle_break(&s->port))
+					continue;
+			} else if (sts & MAX310X_LSR_RXPAR_BIT)
+				s->port.icount.parity++;
+			else if (sts & MAX310X_LSR_FRERR_BIT)
+				s->port.icount.frame++;
+			else if (sts & MAX310X_LSR_RXOVR_BIT)
+				s->port.icount.overrun++;
+
+			sts &= s->port.read_status_mask;
+			if (sts & MAX310X_LSR_RXBRK_BIT)
+				flag = TTY_BREAK;
+			else if (sts & MAX310X_LSR_RXPAR_BIT)
+				flag = TTY_PARITY;
+			else if (sts & MAX310X_LSR_FRERR_BIT)
+				flag = TTY_FRAME;
+			else if (sts & MAX310X_LSR_RXOVR_BIT)
+				flag = TTY_OVERRUN;
+		}
+
+		if (uart_handle_sysrq_char(s->port, ch))
+			continue;
+
+		if (sts & s->port.ignore_status_mask)
+			continue;
+
+		uart_insert_char(&s->port, sts, MAX310X_LSR_RXOVR_BIT,
+				 ch, flag);
+	}
+
+	tty_flip_buffer_push(tty);
+
+	tty_kref_put(tty);
+}
+
+static void max310x_handle_tx(struct max310x_port *s)
+{
+	struct circ_buf *xmit = &s->port.state->xmit;
+	unsigned int txlen = 0, to_send;
+
+	if (unlikely(s->port.x_char)) {
+		regmap_write(s->regmap, MAX310X_THR_REG, s->port.x_char);
+		s->port.icount.tx++;
+		s->port.x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
+		return;
+
+	/* Get length of data pending in circular buffer */
+	to_send = uart_circ_chars_pending(xmit);
+	if (likely(to_send)) {
+		/* Limit to size of TX FIFO */
+		regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &txlen);
+		txlen = MAX310X_FIFO_SIZE - txlen;
+		to_send = (to_send > txlen) ? txlen : to_send;
+
+		dev_dbg(s->port.dev, "TX Len = %u\n", to_send);
+
+		/* Add data to send */
+		s->port.icount.tx += to_send;
+		while (to_send--) {
+			regmap_write(s->regmap, MAX310X_THR_REG,
+				     xmit->buf[xmit->tail]);
+			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		};
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&s->port);
+}
+
+static irqreturn_t max310x_ist(int irq, void *dev_id)
+{
+	struct max310x_port *s = (struct max310x_port *)dev_id;
+	unsigned int ists = 0, lsr = 0, rxlen = 0;
+
+	mutex_lock(&s->max310x_mutex);
+
+	for (;;) {
+		/* Read IRQ status & RX FIFO level */
+		regmap_read(s->regmap, MAX310X_IRQSTS_REG, &ists);
+		regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &lsr);
+		regmap_read(s->regmap, MAX310X_RXFIFOLVL_REG, &rxlen);
+		if (!ists && !(lsr & MAX310X_LSR_RXTO_BIT) && !rxlen)
+			break;
+
+		dev_dbg(s->port.dev, "IRQ status: 0x%02x\n", ists);
+
+		if (rxlen)
+			max310x_handle_rx(s, rxlen);
+		if (ists & MAX310X_IRQ_TX)
+			max310x_handle_tx(s);
+		if (ists & MAX310X_IRQ_CTS_BIT)
+			uart_handle_cts_change(&s->port,
+					       !!(lsr & MAX310X_LSR_CTS_BIT));
+	}
+
+	mutex_unlock(&s->max310x_mutex);
+
+	return IRQ_HANDLED;
+}
+
+static void max310x_wq_proc(struct work_struct *ws)
+{
+	struct max310x_port *s = container_of(ws, struct max310x_port, tx_work);
+
+	mutex_lock(&s->max310x_mutex);
+	max310x_handle_tx(s);
+	mutex_unlock(&s->max310x_mutex);
+}
+
+static void max310x_start_tx(struct uart_port *port)
+{
+	struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+	queue_work(s->wq, &s->tx_work);
+}
+
+static void max310x_stop_tx(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static void max310x_stop_rx(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static unsigned int max310x_tx_empty(struct uart_port *port)
+{
+	unsigned int val = 0;
+	struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+	mutex_lock(&s->max310x_mutex);
+	regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &val);
+	mutex_unlock(&s->max310x_mutex);
+
+	return val ? 0 : TIOCSER_TEMT;
+}
+
+static void max310x_enable_ms(struct uart_port *port)
+{
+	/* Modem status not supported */
+}
+
+static unsigned int max310x_get_mctrl(struct uart_port *port)
+{
+	/* DCD and DSR are not wired and CTS/RTS is handled automatically
+	 * so just indicate DSR and CAR asserted
+	 */
+	return TIOCM_DSR | TIOCM_CAR;
+}
+
+static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* DCD and DSR are not wired and CTS/RTS is hadnled automatically
+	 * so do nothing
+	 */
+}
+
+static void max310x_break_ctl(struct uart_port *port, int break_state)
+{
+	struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+	mutex_lock(&s->max310x_mutex);
+	regmap_update_bits(s->regmap, MAX310X_LCR_REG,
+			   MAX310X_LCR_TXBREAK_BIT,
+			   break_state ? MAX310X_LCR_TXBREAK_BIT : 0);
+	mutex_unlock(&s->max310x_mutex);
+}
+
+static void max310x_set_termios(struct uart_port *port,
+				struct ktermios *termios,
+				struct ktermios *old)
+{
+	struct max310x_port *s = container_of(port, struct max310x_port, port);
+	unsigned int lcr, flow = 0;
+	int baud;
+
+	mutex_lock(&s->max310x_mutex);
+
+	/* Mask termios capabilities we don't support */
+	termios->c_cflag &= ~CMSPAR;
+	termios->c_iflag &= ~IXANY;
+
+	/* Word size */
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		lcr = MAX310X_LCR_WORD_LEN_5;
+		break;
+	case CS6:
+		lcr = MAX310X_LCR_WORD_LEN_6;
+		break;
+	case CS7:
+		lcr = MAX310X_LCR_WORD_LEN_7;
+		break;
+	case CS8:
+	default:
+		lcr = MAX310X_LCR_WORD_LEN_8;
+		break;
+	}
+
+	/* Parity */
+	if (termios->c_cflag & PARENB) {
+		lcr |= MAX310X_LCR_PARITY_BIT;
+		if (!(termios->c_cflag & PARODD))
+			lcr |= MAX310X_LCR_EVENPARITY_BIT;
+	}
+
+	/* Stop bits */
+	if (termios->c_cflag & CSTOPB)
+		lcr |= MAX310X_LCR_STOPLEN_BIT; /* 2 stops */
+
+	/* Update LCR register */
+	regmap_write(s->regmap, MAX310X_LCR_REG, lcr);
+
+	/* Set read status mask */
+	port->read_status_mask = MAX310X_LSR_RXOVR_BIT;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= MAX310X_LSR_RXPAR_BIT |
+					  MAX310X_LSR_FRERR_BIT;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= MAX310X_LSR_RXBRK_BIT;
+
+	/* Set status ignore mask */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNBRK)
+		port->ignore_status_mask |= MAX310X_LSR_RXBRK_BIT;
+	if (!(termios->c_cflag & CREAD))
+		port->ignore_status_mask |= MAX310X_LSR_RXPAR_BIT |
+					    MAX310X_LSR_RXOVR_BIT |
+					    MAX310X_LSR_FRERR_BIT |
+					    MAX310X_LSR_RXBRK_BIT;
+
+	/* Configure flow control */
+	regmap_write(s->regmap, MAX310X_XON1_REG, termios->c_cc[VSTART]);
+	regmap_write(s->regmap, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]);
+	if (termios->c_cflag & CRTSCTS)
+		flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT |
+			MAX310X_FLOWCTRL_AUTORTS_BIT;
+	if (termios->c_iflag & IXON)
+		flow |= MAX310X_FLOWCTRL_SWFLOW3_BIT |
+			MAX310X_FLOWCTRL_SWFLOWEN_BIT;
+	if (termios->c_iflag & IXOFF)
+		flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT |
+			MAX310X_FLOWCTRL_SWFLOWEN_BIT;
+	regmap_write(s->regmap, MAX310X_FLOWCTRL_REG, flow);
+
+	/* Get baud rate generator configuration */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 4);
+
+	/* Setup baudrate generator */
+	max310x_set_baud(s, baud);
+
+	/* Update timeout according to new baud rate */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	mutex_unlock(&s->max310x_mutex);
+}
+
+static int max310x_startup(struct uart_port *port)
+{
+	unsigned int val, line = port->line;
+	struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+	if (s->pdata->suspend)
+		s->pdata->suspend(0);
+
+	mutex_lock(&s->max310x_mutex);
+
+	/* Configure baud rate, 9600 as default */
+	max310x_set_baud(s, 9600);
+
+	/* Configure LCR register, 8N1 mode by default */
+	val = MAX310X_LCR_WORD_LEN_8;
+	regmap_write(s->regmap, MAX310X_LCR_REG, val);
+
+	/* Configure MODE1 register */
+	regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
+			   MAX310X_MODE1_TRNSCVCTRL_BIT,
+			   (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
+			   ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
+
+	/* Configure MODE2 register */
+	val = MAX310X_MODE2_RXEMPTINV_BIT;
+	if (s->pdata->uart_flags[line] & MAX310X_LOOPBACK)
+		val |= MAX310X_MODE2_LOOPBACK_BIT;
+	if (s->pdata->uart_flags[line] & MAX310X_ECHO_SUPRESS)
+		val |= MAX310X_MODE2_ECHOSUPR_BIT;
+
+	/* Reset FIFOs */
+	val |= MAX310X_MODE2_FIFORST_BIT;
+	regmap_write(s->regmap, MAX310X_MODE2_REG, val);
+
+	/* Configure FIFO trigger level register */
+	/* RX FIFO trigger for 16 words, TX FIFO trigger for 64 words */
+	val = MAX310X_FIFOTRIGLVL_RX(16) | MAX310X_FIFOTRIGLVL_TX(64);
+	regmap_write(s->regmap, MAX310X_FIFOTRIGLVL_REG, val);
+
+	/* Configure flow control levels */
+	/* Flow control halt level 96, resume level 48 */
+	val = MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96);
+	regmap_write(s->regmap, MAX310X_FLOWLVL_REG, val);
+
+	/* Clear timeout register */
+	regmap_write(s->regmap, MAX310X_RXTO_REG, 0);
+
+	/* Configure LSR interrupt enable register */
+	/* Enable RX timeout interrupt */
+	val = MAX310X_LSR_RXTO_BIT;
+	regmap_write(s->regmap, MAX310X_LSR_IRQEN_REG, val);
+
+	/* Clear FIFO reset */
+	regmap_update_bits(s->regmap, MAX310X_MODE2_REG,
+			   MAX310X_MODE2_FIFORST_BIT, 0);
+
+	/* Clear IRQ status register by reading it */
+	regmap_read(s->regmap, MAX310X_IRQSTS_REG, &val);
+
+	/* Configure interrupt enable register */
+	/* Enable CTS change interrupt */
+	val = MAX310X_IRQ_CTS_BIT;
+	/* Enable RX, TX interrupts */
+	val |= MAX310X_IRQ_RX | MAX310X_IRQ_TX;
+	regmap_write(s->regmap, MAX310X_IRQEN_REG, val);
+
+	mutex_unlock(&s->max310x_mutex);
+
+	return 0;
+}
+
+static void max310x_shutdown(struct uart_port *port)
+{
+	struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+	/* Disable all interrupts */
+	mutex_lock(&s->max310x_mutex);
+	regmap_write(s->regmap, MAX310X_IRQEN_REG, 0);
+	mutex_unlock(&s->max310x_mutex);
+
+	if (s->pdata->suspend)
+		s->pdata->suspend(1);
+}
+
+static const char *max310x_type(struct uart_port *port)
+{
+	struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+	return (port->type == PORT_MAX310X) ? s->name : NULL;
+}
+
+static int max310x_request_port(struct uart_port *port)
+{
+	/* Do nothing */
+	return 0;
+}
+
+static void max310x_release_port(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static void max310x_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_MAX310X;
+}
+
+static int max310x_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	if ((ser->type == PORT_UNKNOWN) || (ser->type == PORT_MAX310X))
+		return 0;
+	if (ser->irq == port->irq)
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct uart_ops max310x_ops = {
+	.tx_empty	= max310x_tx_empty,
+	.set_mctrl	= max310x_set_mctrl,
+	.get_mctrl	= max310x_get_mctrl,
+	.stop_tx	= max310x_stop_tx,
+	.start_tx	= max310x_start_tx,
+	.stop_rx	= max310x_stop_rx,
+	.enable_ms	= max310x_enable_ms,
+	.break_ctl	= max310x_break_ctl,
+	.startup	= max310x_startup,
+	.shutdown	= max310x_shutdown,
+	.set_termios	= max310x_set_termios,
+	.type		= max310x_type,
+	.request_port	= max310x_request_port,
+	.release_port	= max310x_release_port,
+	.config_port	= max310x_config_port,
+	.verify_port	= max310x_verify_port,
+};
+
+static int max310x_suspend(struct spi_device *spi, pm_message_t state)
+{
+	int ret;
+	struct max310x_port *s = dev_get_drvdata(&spi->dev);
+
+	dev_dbg(&spi->dev, "Suspend\n");
+
+	ret = uart_suspend_port(&s->uart, &s->port);
+
+	mutex_lock(&s->max310x_mutex);
+
+	/* Enable sleep mode */
+	regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
+			   MAX310X_MODE1_FORCESLEEP_BIT,
+			   MAX310X_MODE1_FORCESLEEP_BIT);
+
+	mutex_unlock(&s->max310x_mutex);
+
+	if (s->pdata->suspend)
+		s->pdata->suspend(1);
+
+	return ret;
+}
+
+static int max310x_resume(struct spi_device *spi)
+{
+	struct max310x_port *s = dev_get_drvdata(&spi->dev);
+
+	dev_dbg(&spi->dev, "Resume\n");
+
+	if (s->pdata->suspend)
+		s->pdata->suspend(0);
+
+	mutex_lock(&s->max310x_mutex);
+
+	/* Disable sleep mode */
+	regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
+			   MAX310X_MODE1_FORCESLEEP_BIT,
+			   0);
+
+	max310x_wait_pll(s);
+
+	mutex_unlock(&s->max310x_mutex);
+
+	return uart_resume_port(&s->uart, &s->port);
+}
+
+#ifdef CONFIG_GPIOLIB
+static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned int val = 0;
+	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+	mutex_lock(&s->max310x_mutex);
+	regmap_read(s->regmap, MAX310X_GPIODATA_REG, &val);
+	mutex_unlock(&s->max310x_mutex);
+
+	return !!((val >> 4) & (1 << offset));
+}
+
+static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+	mutex_lock(&s->max310x_mutex);
+	regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ?
+							    1 << offset : 0);
+	mutex_unlock(&s->max310x_mutex);
+}
+
+static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+	mutex_lock(&s->max310x_mutex);
+
+	regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset, 0);
+
+	mutex_unlock(&s->max310x_mutex);
+
+	return 0;
+}
+
+static int max310x_gpio_direction_output(struct gpio_chip *chip,
+					 unsigned offset, int value)
+{
+	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+	mutex_lock(&s->max310x_mutex);
+
+	regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset,
+							   1 << offset);
+	regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ?
+							    1 << offset : 0);
+
+	mutex_unlock(&s->max310x_mutex);
+
+	return 0;
+}
+#endif
+
+/* Generic platform data */
+static struct max310x_pdata generic_plat_data = {
+	.driver_flags	= MAX310X_EXT_CLK,
+	.uart_flags[0]	= MAX310X_ECHO_SUPRESS,
+	.frequency	= 26000000,
+};
+
+static int __devinit max310x_probe(struct spi_device *spi)
+{
+	struct max310x_port *s;
+	struct device *dev = &spi->dev;
+	int chiptype = spi_get_device_id(spi)->driver_data;
+	struct max310x_pdata *pdata = dev->platform_data;
+	unsigned int val = 0;
+	int ret;
+
+	/* Check for IRQ */
+	if (spi->irq <= 0) {
+		dev_err(dev, "No IRQ specified\n");
+		return -ENOTSUPP;
+	}
+
+	/* Alloc port structure */
+	s = devm_kzalloc(dev, sizeof(struct max310x_port), GFP_KERNEL);
+	if (!s) {
+		dev_err(dev, "Error allocating port structure\n");
+		return -ENOMEM;
+	}
+	dev_set_drvdata(dev, s);
+
+	if (!pdata) {
+		dev_warn(dev, "No platform data supplied, using defaults\n");
+		pdata = &generic_plat_data;
+	}
+	s->pdata = pdata;
+
+	/* Individual chip settings */
+	switch (chiptype) {
+	case MAX310X_TYPE_MAX3107:
+		s->name = "MAX3107";
+		s->nr_gpio = 4;
+		s->uart.nr = 1;
+		s->regcfg.max_register = 0x1f;
+		break;
+	case MAX310X_TYPE_MAX3108:
+		s->name = "MAX3108";
+		s->nr_gpio = 4;
+		s->uart.nr = 1;
+		s->regcfg.max_register = 0x1e;
+		break;
+	default:
+		dev_err(dev, "Unsupported chip type %i\n", chiptype);
+		return -ENOTSUPP;
+	}
+
+	/* Check input frequency */
+	if ((pdata->driver_flags & MAX310X_EXT_CLK) &&
+	   ((pdata->frequency < 500000) || (pdata->frequency > 35000000)))
+		goto err_freq;
+	/* Check frequency for quartz */
+	if (!(pdata->driver_flags & MAX310X_EXT_CLK) &&
+	   ((pdata->frequency < 1000000) || (pdata->frequency > 4000000)))
+		goto err_freq;
+
+	mutex_init(&s->max310x_mutex);
+
+	/* Setup SPI bus */
+	spi->mode		= SPI_MODE_0;
+	spi->bits_per_word	= 8;
+	spi->max_speed_hz	= 26000000;
+	spi_setup(spi);
+
+	/* Setup regmap */
+	s->regcfg.reg_bits		= 8;
+	s->regcfg.val_bits		= 8;
+	s->regcfg.read_flag_mask	= 0x00;
+	s->regcfg.write_flag_mask	= 0x80;
+	s->regcfg.cache_type		= REGCACHE_RBTREE;
+	s->regcfg.writeable_reg		= max3107_8_reg_writeable;
+	s->regcfg.volatile_reg		= max310x_reg_volatile;
+	s->regcfg.precious_reg		= max310x_reg_precious;
+	s->regmap = devm_regmap_init_spi(spi, &s->regcfg);
+	if (IS_ERR(s->regmap)) {
+		ret = PTR_ERR(s->regmap);
+		dev_err(dev, "Failed to initialize register map\n");
+		goto err_out;
+	}
+
+	/* Reset chip & check SPI function */
+	ret = regmap_write(s->regmap, MAX310X_MODE2_REG, MAX310X_MODE2_RST_BIT);
+	if (ret) {
+		dev_err(dev, "SPI transfer failed\n");
+		goto err_out;
+	}
+	/* Clear chip reset */
+	regmap_write(s->regmap, MAX310X_MODE2_REG, 0);
+
+	switch (chiptype) {
+	case MAX310X_TYPE_MAX3107:
+		/* Check REV ID to ensure we are talking to what we expect */
+		regmap_read(s->regmap, MAX3107_REVID_REG, &val);
+		if (((val & MAX3107_REV_MASK) != MAX3107_REV_ID)) {
+			dev_err(dev, "%s ID 0x%02x does not match\n",
+				s->name, val);
+			ret = -ENODEV;
+			goto err_out;
+		}
+		break;
+	case MAX310X_TYPE_MAX3108:
+		/* MAX3108 have not REV ID register, we just check default value
+		 * from clocksource register to make sure everything works.
+		 */
+		regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
+		if (val != (MAX310X_CLKSRC_EXTCLK_BIT |
+			    MAX310X_CLKSRC_PLLBYP_BIT)) {
+			dev_err(dev, "%s not present\n", s->name);
+			ret = -ENODEV;
+			goto err_out;
+		}
+		break;
+	}
+
+	/* Board specific configure */
+	if (pdata->init)
+		pdata->init();
+	if (pdata->suspend)
+		pdata->suspend(0);
+
+	/* Calculate referecne clock */
+	s->uartclk = max310x_set_ref_clk(s);
+
+	/* Disable all interrupts */
+	regmap_write(s->regmap, MAX310X_IRQEN_REG, 0);
+
+	/* Setup MODE1 register */
+	val = MAX310X_MODE1_IRQSEL_BIT; /* Enable IRQ pin */
+	if (pdata->driver_flags & MAX310X_AUTOSLEEP)
+		val = MAX310X_MODE1_AUTOSLEEP_BIT;
+	regmap_write(s->regmap, MAX310X_MODE1_REG, val);
+
+	/* Setup interrupt */
+	ret = devm_request_threaded_irq(dev, spi->irq, NULL, max310x_ist,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					dev_name(dev), s);
+	if (ret) {
+		dev_err(dev, "Unable to reguest IRQ %i\n", spi->irq);
+		goto err_out;
+	}
+
+	/* Register UART driver */
+	s->uart.owner		= THIS_MODULE;
+	s->uart.driver_name	= dev_name(dev);
+	s->uart.dev_name	= "ttyMAX";
+	s->uart.major		= MAX310X_MAJOR;
+	s->uart.minor		= MAX310X_MINOR;
+	ret = uart_register_driver(&s->uart);
+	if (ret) {
+		dev_err(dev, "Registering UART driver failed\n");
+		goto err_out;
+	}
+
+	/* Initialize workqueue for start TX */
+	s->wq = create_freezable_workqueue(dev_name(dev));
+	INIT_WORK(&s->tx_work, max310x_wq_proc);
+
+	/* Initialize UART port data */
+	s->port.line		= 0;
+	s->port.dev		= dev;
+	s->port.irq		= spi->irq;
+	s->port.type		= PORT_MAX310X;
+	s->port.fifosize	= MAX310X_FIFO_SIZE;
+	s->port.flags		= UPF_SKIP_TEST | UPF_FIXED_TYPE;
+	s->port.iotype		= UPIO_PORT;
+	s->port.membase		= (void __iomem *)0xffffffff; /* Bogus value */
+	s->port.uartclk		= s->uartclk;
+	s->port.ops		= &max310x_ops;
+	uart_add_one_port(&s->uart, &s->port);
+
+#ifdef CONFIG_GPIOLIB
+	/* Setup GPIO cotroller */
+	if (pdata->gpio_base) {
+		s->gpio.owner		= THIS_MODULE;
+		s->gpio.dev		= dev;
+		s->gpio.label		= dev_name(dev);
+		s->gpio.direction_input	= max310x_gpio_direction_input;
+		s->gpio.get		= max310x_gpio_get;
+		s->gpio.direction_output= max310x_gpio_direction_output;
+		s->gpio.set		= max310x_gpio_set;
+		s->gpio.base		= pdata->gpio_base;
+		s->gpio.ngpio		= s->nr_gpio;
+		if (gpiochip_add(&s->gpio)) {
+			/* Indicate that we should not call gpiochip_remove */
+			s->gpio.base = 0;
+		}
+	} else
+		dev_info(dev, "GPIO support not enabled\n");
+#endif
+
+	/* Go to suspend mode */
+	if (pdata->suspend)
+		pdata->suspend(1);
+
+	return 0;
+
+err_freq:
+	dev_err(dev, "Frequency parameter incorrect\n");
+	ret = -EINVAL;
+
+err_out:
+	dev_set_drvdata(dev, NULL);
+
+	return ret;
+}
+
+static int __devexit max310x_remove(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	struct max310x_port *s = dev_get_drvdata(dev);
+	int ret = 0;
+
+	dev_dbg(dev, "Removing port\n");
+
+	devm_free_irq(dev, s->port.irq, s);
+
+	destroy_workqueue(s->wq);
+
+	uart_remove_one_port(&s->uart, &s->port);
+
+	uart_unregister_driver(&s->uart);
+
+#ifdef CONFIG_GPIOLIB
+	if (s->pdata->gpio_base) {
+		ret = gpiochip_remove(&s->gpio);
+		if (ret)
+			dev_err(dev, "Failed to remove gpio chip: %d\n", ret);
+	}
+#endif
+
+	dev_set_drvdata(dev, NULL);
+
+	if (s->pdata->suspend)
+		s->pdata->suspend(1);
+	if (s->pdata->exit)
+		s->pdata->exit();
+
+	return ret;
+}
+
+static const struct spi_device_id max310x_id_table[] = {
+	{ "max3107",	MAX310X_TYPE_MAX3107 },
+	{ "max3108",	MAX310X_TYPE_MAX3108 },
+};
+MODULE_DEVICE_TABLE(spi, max310x_id_table);
+
+static struct spi_driver max310x_driver = {
+	.driver = {
+		.name	= "max310x",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max310x_probe,
+	.remove		= __devexit_p(max310x_remove),
+	.suspend	= max310x_suspend,
+	.resume		= max310x_resume,
+	.id_table	= max310x_id_table,
+};
+module_spi_driver(max310x_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("MAX310X serial driver");

+ 6 - 2
drivers/tty/serial/mpc52xx_uart.c

@@ -775,11 +775,15 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
 	}
 
 	if (new->c_cflag & PARENB) {
+		if (new->c_cflag & CMSPAR)
+			mr1 |= MPC52xx_PSC_MODE_PARFORCE;
+
+		/* With CMSPAR, PARODD also means high parity (same as termios) */
 		mr1 |= (new->c_cflag & PARODD) ?
 			MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
-	} else
+	} else {
 		mr1 |= MPC52xx_PSC_MODE_PARNONE;
-
+	}
 
 	mr2 = 0;
 

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

@@ -896,7 +896,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 			return PTR_ERR(msm_port->clk);
 
 	if (msm_port->is_uartdm)
-		clk_set_rate(msm_port->clk, 7372800);
+		clk_set_rate(msm_port->clk, 1843200);
 
 	port->uartclk = clk_get_rate(msm_port->clk);
 	printk(KERN_INFO "uartclk = %d\n", port->uartclk);

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

@@ -223,9 +223,11 @@ static int __init smd_tty_init(void)
 		return ret;
 
 	for (i = 0; i < smd_tty_channels_len; i++) {
-		tty_port_init(&smd_tty[smd_tty_channels[i].id].port);
-		smd_tty[smd_tty_channels[i].id].port.ops = &smd_tty_port_ops;
-		tty_register_device(smd_tty_driver, smd_tty_channels[i].id, 0);
+		struct tty_port *port = &smd_tty[smd_tty_channels[i].id].port;
+		tty_port_init(port);
+		port->ops = &smd_tty_port_ops;
+		tty_port_register_device(port, smd_tty_driver,
+				smd_tty_channels[i].id, NULL);
 	}
 
 	return 0;

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

@@ -262,7 +262,7 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
 
 	ctrl &= ~AUART_CTRL2_RTSEN;
 	if (mctrl & TIOCM_RTS) {
-		if (u->state->port.flags & ASYNC_CTS_FLOW)
+		if (tty_port_cts_enabled(&u->state->port))
 			ctrl |= AUART_CTRL2_RTSEN;
 	}
 
@@ -457,11 +457,11 @@ static void mxs_auart_shutdown(struct uart_port *u)
 
 	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
 
-	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
-
 	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
 			u->membase + AUART_INTR_CLR);
 
+	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+
 	clk_disable_unprepare(s->clk);
 }
 
@@ -796,6 +796,7 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
 
 	auart_port[pdev->id] = NULL;
 
+	put_device(s->dev);
 	clk_put(s->clk);
 	free_irq(s->irq, s);
 	kfree(s);

+ 12 - 1
drivers/tty/serial/of_serial.c

@@ -105,6 +105,10 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 	port->uartclk = clk;
 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
 		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
+
+	if (of_find_property(np, "no-loopback-test", NULL))
+		port->flags |= UPF_SKIP_TEST;
+
 	port->dev = &ofdev->dev;
 
 	if (type == PORT_TEGRA)
@@ -144,8 +148,15 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
 	switch (port_type) {
 #ifdef CONFIG_SERIAL_8250
 	case PORT_8250 ... PORT_MAX_8250:
-		ret = serial8250_register_port(&port);
+	{
+		/* For now the of bindings don't support the extra
+		   8250 specific bits */
+		struct uart_8250_port port8250;
+		memset(&port8250, 0, sizeof(port8250));
+		port8250.port = port;
+		ret = serial8250_register_8250_port(&port8250);
 		break;
+	}
 #endif
 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
 	case PORT_NWPSERIAL:

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 316 - 440
drivers/tty/serial/omap-serial.c


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

@@ -979,6 +979,10 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
 	priv->tx_dma_use = 1;
 
 	priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+	if (!priv->sg_tx_p) {
+		dev_err(priv->port.dev, "%s:kzalloc Failed\n", __func__);
+		return 0;
+	}
 
 	sg_init_table(priv->sg_tx_p, num); /* Initialize SG table */
 	sg = priv->sg_tx_p;

+ 14 - 0
drivers/tty/serial/pxa.c

@@ -670,9 +670,19 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
 {
 	struct uart_pxa_port *up = serial_pxa_ports[co->index];
 	unsigned int ier;
+	unsigned long flags;
+	int locked = 1;
 
 	clk_prepare_enable(up->clk);
 
+	local_irq_save(flags);
+	if (up->port.sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock(&up->port.lock);
+	else
+		spin_lock(&up->port.lock);
+
 	/*
 	 *	First save the IER then disable the interrupts
 	 */
@@ -688,6 +698,10 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
 	wait_for_xmitr(up);
 	serial_out(up, UART_IER, ier);
 
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
+
 	clk_disable_unprepare(up->clk);
 }
 

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

@@ -82,7 +82,7 @@ static inline const char *s3c24xx_serial_portname(struct uart_port *port)
 
 static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
 {
-	return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE);
+	return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
 }
 
 /*
@@ -268,7 +268,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
 				dbg("break!\n");
 				port->icount.brk++;
 				if (uart_handle_break(port))
-				    goto ignore_char;
+					goto ignore_char;
 			}
 
 			if (uerstat & S3C2410_UERSTAT_FRAME)
@@ -459,7 +459,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
 			  s3c24xx_serial_portname(port), ourport);
 
 	if (ret != 0) {
-		printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
+		dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq);
 		return ret;
 	}
 
@@ -473,7 +473,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
 			  s3c24xx_serial_portname(port), ourport);
 
 	if (ret) {
-		printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
+		dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq);
 		goto err;
 	}
 
@@ -502,7 +502,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
 	ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
 			  s3c24xx_serial_portname(port), ourport);
 	if (ret) {
-		printk(KERN_ERR "cannot get irq %d\n", port->irq);
+		dev_err(port->dev, "cannot get irq %d\n", port->irq);
 		return ret;
 	}
 
@@ -529,7 +529,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
 
 	switch (level) {
 	case 3:
-		if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+		if (!IS_ERR(ourport->baudclk))
 			clk_disable(ourport->baudclk);
 
 		clk_disable(ourport->clk);
@@ -538,12 +538,12 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
 	case 0:
 		clk_enable(ourport->clk);
 
-		if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+		if (!IS_ERR(ourport->baudclk))
 			clk_enable(ourport->baudclk);
 
 		break;
 	default:
-		printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level);
+		dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
 	}
 }
 
@@ -604,7 +604,6 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
 	char clkname[MAX_CLK_NAME_LENGTH];
 	int calc_deviation, deviation = (1 << 30) - 1;
 
-	*best_clk = NULL;
 	clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
 			ourport->info->def_clk_sel;
 	for (cnt = 0; cnt < info->num_clks; cnt++) {
@@ -613,7 +612,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
 
 		sprintf(clkname, "clk_uart_baud%d", cnt);
 		clk = clk_get(ourport->port.dev, clkname);
-		if (IS_ERR_OR_NULL(clk))
+		if (IS_ERR(clk))
 			continue;
 
 		rate = clk_get_rate(clk);
@@ -684,7 +683,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
 {
 	struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
-	struct clk *clk = NULL;
+	struct clk *clk = ERR_PTR(-EINVAL);
 	unsigned long flags;
 	unsigned int baud, quot, clk_sel = 0;
 	unsigned int ulcon;
@@ -705,7 +704,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
 	quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
 	if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
 		quot = port->custom_divisor;
-	if (!clk)
+	if (IS_ERR(clk))
 		return;
 
 	/* check to see if we need  to change clock source */
@@ -713,9 +712,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
 	if (ourport->baudclk != clk) {
 		s3c24xx_serial_setsource(port, clk_sel);
 
-		if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
+		if (!IS_ERR(ourport->baudclk)) {
 			clk_disable(ourport->baudclk);
-			ourport->baudclk  = NULL;
+			ourport->baudclk = ERR_PTR(-EINVAL);
 		}
 
 		clk_enable(clk);
@@ -1036,10 +1035,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
 		if (tty == NULL)
 			goto exit;
 
-		termios = tty->termios;
+		termios = &tty->termios;
 
 		if (termios == NULL) {
-			printk(KERN_WARNING "%s: no termios?\n", __func__);
+			dev_warn(uport->dev, "%s: no termios?\n", __func__);
 			goto exit;
 		}
 
@@ -1114,7 +1113,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 
 	res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
-		printk(KERN_ERR "failed to find memory resource for uart\n");
+		dev_err(port->dev, "failed to find memory resource for uart\n");
 		return -EINVAL;
 	}
 
@@ -1130,7 +1129,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 		ourport->rx_irq = ret;
 		ourport->tx_irq = ret + 1;
 	}
-	
+
 	ret = platform_get_irq(platdev, 1);
 	if (ret > 0)
 		ourport->tx_irq = ret;
@@ -1160,7 +1159,11 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
 	struct uart_port *port = s3c24xx_dev_to_port(dev);
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
 
-	return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name);
+	if (IS_ERR(ourport->baudclk))
+		return -EINVAL;
+
+	return snprintf(buf, PAGE_SIZE, "* %s\n",
+			ourport->baudclk->name ?: "(null)");
 }
 
 static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
@@ -1200,6 +1203,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	ourport->baudclk = ERR_PTR(-EINVAL);
 	ourport->info = ourport->drv_data->info;
 	ourport->cfg = (pdev->dev.platform_data) ?
 			(struct s3c2410_uartcfg *)pdev->dev.platform_data :
@@ -1387,7 +1391,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
 		sprintf(clk_name, "clk_uart_baud%d", clk_sel);
 
 		clk = clk_get(port->dev, clk_name);
-		if (!IS_ERR(clk) && clk != NULL)
+		if (!IS_ERR(clk))
 			rate = clk_get_rate(clk);
 		else
 			rate = 1;
@@ -1679,7 +1683,7 @@ static int __init s3c24xx_serial_modinit(void)
 
 	ret = uart_register_driver(&s3c24xx_uart_drv);
 	if (ret < 0) {
-		printk(KERN_ERR "failed to register UART driver\n");
+		pr_err("Failed to register Samsung UART driver\n");
 		return -1;
 	}
 

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

@@ -20,6 +20,10 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
+#include <linux/io.h>
+
+#warning "Please try migrate to use new driver SCCNXP and report the status" \
+	 "in the linux-serial mailing list."
 
 #if defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ

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

@@ -0,0 +1,985 @@
+/*
+ *  NXP (Philips) SCC+++(SCN+++) serial driver
+ *
+ *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ *  Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#if defined(CONFIG_SERIAL_SCCNXP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/io.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/sccnxp.h>
+
+#define SCCNXP_NAME			"uart-sccnxp"
+#define SCCNXP_MAJOR			204
+#define SCCNXP_MINOR			205
+
+#define SCCNXP_MR_REG			(0x00)
+#	define MR0_BAUD_NORMAL		(0 << 0)
+#	define MR0_BAUD_EXT1		(1 << 0)
+#	define MR0_BAUD_EXT2		(5 << 0)
+#	define MR0_FIFO			(1 << 3)
+#	define MR0_TXLVL		(1 << 4)
+#	define MR1_BITS_5		(0 << 0)
+#	define MR1_BITS_6		(1 << 0)
+#	define MR1_BITS_7		(2 << 0)
+#	define MR1_BITS_8		(3 << 0)
+#	define MR1_PAR_EVN		(0 << 2)
+#	define MR1_PAR_ODD		(1 << 2)
+#	define MR1_PAR_NO		(4 << 2)
+#	define MR2_STOP1		(7 << 0)
+#	define MR2_STOP2		(0xf << 0)
+#define SCCNXP_SR_REG			(0x01)
+#define SCCNXP_CSR_REG			SCCNXP_SR_REG
+#	define SR_RXRDY			(1 << 0)
+#	define SR_FULL			(1 << 1)
+#	define SR_TXRDY			(1 << 2)
+#	define SR_TXEMT			(1 << 3)
+#	define SR_OVR			(1 << 4)
+#	define SR_PE			(1 << 5)
+#	define SR_FE			(1 << 6)
+#	define SR_BRK			(1 << 7)
+#define SCCNXP_CR_REG			(0x02)
+#	define CR_RX_ENABLE		(1 << 0)
+#	define CR_RX_DISABLE		(1 << 1)
+#	define CR_TX_ENABLE		(1 << 2)
+#	define CR_TX_DISABLE		(1 << 3)
+#	define CR_CMD_MRPTR1		(0x01 << 4)
+#	define CR_CMD_RX_RESET		(0x02 << 4)
+#	define CR_CMD_TX_RESET		(0x03 << 4)
+#	define CR_CMD_STATUS_RESET	(0x04 << 4)
+#	define CR_CMD_BREAK_RESET	(0x05 << 4)
+#	define CR_CMD_START_BREAK	(0x06 << 4)
+#	define CR_CMD_STOP_BREAK	(0x07 << 4)
+#	define CR_CMD_MRPTR0		(0x0b << 4)
+#define SCCNXP_RHR_REG			(0x03)
+#define SCCNXP_THR_REG			SCCNXP_RHR_REG
+#define SCCNXP_IPCR_REG			(0x04)
+#define SCCNXP_ACR_REG			SCCNXP_IPCR_REG
+#	define ACR_BAUD0		(0 << 7)
+#	define ACR_BAUD1		(1 << 7)
+#	define ACR_TIMER_MODE		(6 << 4)
+#define SCCNXP_ISR_REG			(0x05)
+#define SCCNXP_IMR_REG			SCCNXP_ISR_REG
+#	define IMR_TXRDY		(1 << 0)
+#	define IMR_RXRDY		(1 << 1)
+#	define ISR_TXRDY(x)		(1 << ((x * 4) + 0))
+#	define ISR_RXRDY(x)		(1 << ((x * 4) + 1))
+#define SCCNXP_IPR_REG			(0x0d)
+#define SCCNXP_OPCR_REG			SCCNXP_IPR_REG
+#define SCCNXP_SOP_REG			(0x0e)
+#define SCCNXP_ROP_REG			(0x0f)
+
+/* Route helpers */
+#define MCTRL_MASK(sig)			(0xf << (sig))
+#define MCTRL_IBIT(cfg, sig)		((((cfg) >> (sig)) & 0xf) - LINE_IP0)
+#define MCTRL_OBIT(cfg, sig)		((((cfg) >> (sig)) & 0xf) - LINE_OP0)
+
+/* Supported chip types */
+enum {
+	SCCNXP_TYPE_SC2681	= 2681,
+	SCCNXP_TYPE_SC2691	= 2691,
+	SCCNXP_TYPE_SC2692	= 2692,
+	SCCNXP_TYPE_SC2891	= 2891,
+	SCCNXP_TYPE_SC2892	= 2892,
+	SCCNXP_TYPE_SC28202	= 28202,
+	SCCNXP_TYPE_SC68681	= 68681,
+	SCCNXP_TYPE_SC68692	= 68692,
+};
+
+struct sccnxp_port {
+	struct uart_driver	uart;
+	struct uart_port	port[SCCNXP_MAX_UARTS];
+
+	const char		*name;
+	int			irq;
+
+	u8			imr;
+	u8			addr_mask;
+	int			freq_std;
+
+	int			flags;
+#define SCCNXP_HAVE_IO		0x00000001
+#define SCCNXP_HAVE_MR0		0x00000002
+
+#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
+	struct console		console;
+#endif
+
+	struct mutex		sccnxp_mutex;
+
+	struct sccnxp_pdata	pdata;
+};
+
+static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift)
+{
+	return readb(base + (reg << shift));
+}
+
+static inline void sccnxp_raw_write(void __iomem *base, u8 reg, u8 shift, u8 v)
+{
+	writeb(v, base + (reg << shift));
+}
+
+static inline u8 sccnxp_read(struct uart_port *port, u8 reg)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	return sccnxp_raw_read(port->membase, reg & s->addr_mask,
+			       port->regshift);
+}
+
+static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	sccnxp_raw_write(port->membase, reg & s->addr_mask, port->regshift, v);
+}
+
+static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg)
+{
+	return sccnxp_read(port, (port->line << 3) + reg);
+}
+
+static inline void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v)
+{
+	sccnxp_write(port, (port->line << 3) + reg, v);
+}
+
+static int sccnxp_update_best_err(int a, int b, int *besterr)
+{
+	int err = abs(a - b);
+
+	if ((*besterr < 0) || (*besterr > err)) {
+		*besterr = err;
+		return 0;
+	}
+
+	return 1;
+}
+
+struct baud_table {
+	u8	csr;
+	u8	acr;
+	u8	mr0;
+	int	baud;
+};
+
+const struct baud_table baud_std[] = {
+	{ 0,	ACR_BAUD0,	MR0_BAUD_NORMAL,	50, },
+	{ 0,	ACR_BAUD1,	MR0_BAUD_NORMAL,	75, },
+	{ 1,	ACR_BAUD0,	MR0_BAUD_NORMAL,	110, },
+	{ 2,	ACR_BAUD0,	MR0_BAUD_NORMAL,	134, },
+	{ 3,	ACR_BAUD1,	MR0_BAUD_NORMAL,	150, },
+	{ 3,	ACR_BAUD0,	MR0_BAUD_NORMAL,	200, },
+	{ 4,	ACR_BAUD0,	MR0_BAUD_NORMAL,	300, },
+	{ 0,	ACR_BAUD1,	MR0_BAUD_EXT1,		450, },
+	{ 1,	ACR_BAUD0,	MR0_BAUD_EXT2,		880, },
+	{ 3,	ACR_BAUD1,	MR0_BAUD_EXT1,		900, },
+	{ 5,	ACR_BAUD0,	MR0_BAUD_NORMAL,	600, },
+	{ 7,	ACR_BAUD0,	MR0_BAUD_NORMAL,	1050, },
+	{ 2,	ACR_BAUD0,	MR0_BAUD_EXT2,		1076, },
+	{ 6,	ACR_BAUD0,	MR0_BAUD_NORMAL,	1200, },
+	{ 10,	ACR_BAUD1,	MR0_BAUD_NORMAL,	1800, },
+	{ 7,	ACR_BAUD1,	MR0_BAUD_NORMAL,	2000, },
+	{ 8,	ACR_BAUD0,	MR0_BAUD_NORMAL,	2400, },
+	{ 5,	ACR_BAUD1,	MR0_BAUD_EXT1,		3600, },
+	{ 9,	ACR_BAUD0,	MR0_BAUD_NORMAL,	4800, },
+	{ 10,	ACR_BAUD0,	MR0_BAUD_NORMAL,	7200, },
+	{ 11,	ACR_BAUD0,	MR0_BAUD_NORMAL,	9600, },
+	{ 8,	ACR_BAUD0,	MR0_BAUD_EXT1,		14400, },
+	{ 12,	ACR_BAUD1,	MR0_BAUD_NORMAL,	19200, },
+	{ 9,	ACR_BAUD0,	MR0_BAUD_EXT1,		28800, },
+	{ 12,	ACR_BAUD0,	MR0_BAUD_NORMAL,	38400, },
+	{ 11,	ACR_BAUD0,	MR0_BAUD_EXT1,		57600, },
+	{ 12,	ACR_BAUD1,	MR0_BAUD_EXT1,		115200, },
+	{ 12,	ACR_BAUD0,	MR0_BAUD_EXT1,		230400, },
+	{ 0, 0, 0, 0 }
+};
+
+static void sccnxp_set_baud(struct uart_port *port, int baud)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+	int div_std, tmp_baud, bestbaud = baud, besterr = -1;
+	u8 i, acr = 0, csr = 0, mr0 = 0;
+
+	/* Find best baud from table */
+	for (i = 0; baud_std[i].baud && besterr; i++) {
+		if (baud_std[i].mr0 && !(s->flags & SCCNXP_HAVE_MR0))
+			continue;
+		div_std = DIV_ROUND_CLOSEST(s->freq_std, baud_std[i].baud);
+		tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std);
+		if (!sccnxp_update_best_err(baud, tmp_baud, &besterr)) {
+			acr = baud_std[i].acr;
+			csr = baud_std[i].csr;
+			mr0 = baud_std[i].mr0;
+			bestbaud = tmp_baud;
+		}
+	}
+
+	if (s->flags & SCCNXP_HAVE_MR0) {
+		/* Enable FIFO, set half level for TX */
+		mr0 |= MR0_FIFO | MR0_TXLVL;
+		/* Update MR0 */
+		sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR0);
+		sccnxp_port_write(port, SCCNXP_MR_REG, mr0);
+	}
+
+	sccnxp_port_write(port, SCCNXP_ACR_REG, acr | ACR_TIMER_MODE);
+	sccnxp_port_write(port, SCCNXP_CSR_REG, (csr << 4) | csr);
+
+	dev_dbg(port->dev, "Baudrate desired: %i, calculated: %i\n",
+		baud, bestbaud);
+}
+
+static void sccnxp_enable_irq(struct uart_port *port, int mask)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	s->imr |= mask << (port->line * 4);
+	sccnxp_write(port, SCCNXP_IMR_REG, s->imr);
+}
+
+static void sccnxp_disable_irq(struct uart_port *port, int mask)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	s->imr &= ~(mask << (port->line * 4));
+	sccnxp_write(port, SCCNXP_IMR_REG, s->imr);
+}
+
+static void sccnxp_set_bit(struct uart_port *port, int sig, int state)
+{
+	u8 bitmask;
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(sig)) {
+		bitmask = 1 << MCTRL_OBIT(s->pdata.mctrl_cfg[port->line], sig);
+		if (state)
+			sccnxp_write(port, SCCNXP_SOP_REG, bitmask);
+		else
+			sccnxp_write(port, SCCNXP_ROP_REG, bitmask);
+	}
+}
+
+static void sccnxp_handle_rx(struct uart_port *port)
+{
+	u8 sr;
+	unsigned int ch, flag;
+	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+
+	if (!tty)
+		return;
+
+	for (;;) {
+		sr = sccnxp_port_read(port, SCCNXP_SR_REG);
+		if (!(sr & SR_RXRDY))
+			break;
+		sr &= SR_PE | SR_FE | SR_OVR | SR_BRK;
+
+		ch = sccnxp_port_read(port, SCCNXP_RHR_REG);
+
+		port->icount.rx++;
+		flag = TTY_NORMAL;
+
+		if (unlikely(sr)) {
+			if (sr & SR_BRK) {
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					continue;
+			} else if (sr & SR_PE)
+				port->icount.parity++;
+			else if (sr & SR_FE)
+				port->icount.frame++;
+			else if (sr & SR_OVR)
+				port->icount.overrun++;
+
+			sr &= port->read_status_mask;
+			if (sr & SR_BRK)
+				flag = TTY_BREAK;
+			else if (sr & SR_PE)
+				flag = TTY_PARITY;
+			else if (sr & SR_FE)
+				flag = TTY_FRAME;
+			else if (sr & SR_OVR)
+				flag = TTY_OVERRUN;
+		}
+
+		if (uart_handle_sysrq_char(port, ch))
+			continue;
+
+		if (sr & port->ignore_status_mask)
+			continue;
+
+		uart_insert_char(port, sr, SR_OVR, ch, flag);
+	}
+
+	tty_flip_buffer_push(tty);
+
+	tty_kref_put(tty);
+}
+
+static void sccnxp_handle_tx(struct uart_port *port)
+{
+	u8 sr;
+	struct circ_buf *xmit = &port->state->xmit;
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	if (unlikely(port->x_char)) {
+		sccnxp_port_write(port, SCCNXP_THR_REG, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		/* Disable TX if FIFO is empty */
+		if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXEMT) {
+			sccnxp_disable_irq(port, IMR_TXRDY);
+
+			/* Set direction to input */
+			if (s->flags & SCCNXP_HAVE_IO)
+				sccnxp_set_bit(port, DIR_OP, 0);
+		}
+		return;
+	}
+
+	while (!uart_circ_empty(xmit)) {
+		sr = sccnxp_port_read(port, SCCNXP_SR_REG);
+		if (!(sr & SR_TXRDY))
+			break;
+
+		sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+}
+
+static irqreturn_t sccnxp_ist(int irq, void *dev_id)
+{
+	int i;
+	u8 isr;
+	struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
+
+	mutex_lock(&s->sccnxp_mutex);
+
+	for (;;) {
+		isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG);
+		isr &= s->imr;
+		if (!isr)
+			break;
+
+		dev_dbg(s->port[0].dev, "IRQ status: 0x%02x\n", isr);
+
+		for (i = 0; i < s->uart.nr; i++) {
+			if (isr & ISR_RXRDY(i))
+				sccnxp_handle_rx(&s->port[i]);
+			if (isr & ISR_TXRDY(i))
+				sccnxp_handle_tx(&s->port[i]);
+		}
+	}
+
+	mutex_unlock(&s->sccnxp_mutex);
+
+	return IRQ_HANDLED;
+}
+
+static void sccnxp_start_tx(struct uart_port *port)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	mutex_lock(&s->sccnxp_mutex);
+
+	/* Set direction to output */
+	if (s->flags & SCCNXP_HAVE_IO)
+		sccnxp_set_bit(port, DIR_OP, 1);
+
+	sccnxp_enable_irq(port, IMR_TXRDY);
+
+	mutex_unlock(&s->sccnxp_mutex);
+}
+
+static void sccnxp_stop_tx(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static void sccnxp_stop_rx(struct uart_port *port)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	mutex_lock(&s->sccnxp_mutex);
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE);
+	mutex_unlock(&s->sccnxp_mutex);
+}
+
+static unsigned int sccnxp_tx_empty(struct uart_port *port)
+{
+	u8 val;
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	mutex_lock(&s->sccnxp_mutex);
+	val = sccnxp_port_read(port, SCCNXP_SR_REG);
+	mutex_unlock(&s->sccnxp_mutex);
+
+	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);
+
+	if (!(s->flags & SCCNXP_HAVE_IO))
+		return;
+
+	mutex_lock(&s->sccnxp_mutex);
+
+	sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR);
+	sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS);
+
+	mutex_unlock(&s->sccnxp_mutex);
+}
+
+static unsigned int sccnxp_get_mctrl(struct uart_port *port)
+{
+	u8 bitmask, ipr;
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+	unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
+
+	if (!(s->flags & SCCNXP_HAVE_IO))
+		return mctrl;
+
+	mutex_lock(&s->sccnxp_mutex);
+
+	ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG);
+
+	if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DSR_IP)) {
+		bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+					  DSR_IP);
+		mctrl &= ~TIOCM_DSR;
+		mctrl |= (ipr & bitmask) ? TIOCM_DSR : 0;
+	}
+	if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(CTS_IP)) {
+		bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+					  CTS_IP);
+		mctrl &= ~TIOCM_CTS;
+		mctrl |= (ipr & bitmask) ? TIOCM_CTS : 0;
+	}
+	if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DCD_IP)) {
+		bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+					  DCD_IP);
+		mctrl &= ~TIOCM_CAR;
+		mctrl |= (ipr & bitmask) ? TIOCM_CAR : 0;
+	}
+	if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(RNG_IP)) {
+		bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+					  RNG_IP);
+		mctrl &= ~TIOCM_RNG;
+		mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0;
+	}
+
+	mutex_unlock(&s->sccnxp_mutex);
+
+	return mctrl;
+}
+
+static void sccnxp_break_ctl(struct uart_port *port, int break_state)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	mutex_lock(&s->sccnxp_mutex);
+	sccnxp_port_write(port, SCCNXP_CR_REG, break_state ?
+			  CR_CMD_START_BREAK : CR_CMD_STOP_BREAK);
+	mutex_unlock(&s->sccnxp_mutex);
+}
+
+static void sccnxp_set_termios(struct uart_port *port,
+			       struct ktermios *termios, struct ktermios *old)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+	u8 mr1, mr2;
+	int baud;
+
+	mutex_lock(&s->sccnxp_mutex);
+
+	/* Mask termios capabilities we don't support */
+	termios->c_cflag &= ~CMSPAR;
+	termios->c_iflag &= ~(IXON | IXOFF | IXANY);
+
+	/* Disable RX & TX, reset break condition, status and FIFOs */
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET |
+					       CR_RX_DISABLE | CR_TX_DISABLE);
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET);
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET);
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET);
+
+	/* Word size */
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		mr1 = MR1_BITS_5;
+		break;
+	case CS6:
+		mr1 = MR1_BITS_6;
+		break;
+	case CS7:
+		mr1 = MR1_BITS_7;
+		break;
+	default:
+	case CS8:
+		mr1 = MR1_BITS_8;
+		break;
+	}
+
+	/* Parity */
+	if (termios->c_cflag & PARENB) {
+		if (termios->c_cflag & PARODD)
+			mr1 |= MR1_PAR_ODD;
+	} else
+		mr1 |= MR1_PAR_NO;
+
+	/* Stop bits */
+	mr2 = (termios->c_cflag & CSTOPB) ? MR2_STOP2 : MR2_STOP1;
+
+	/* Update desired format */
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR1);
+	sccnxp_port_write(port, SCCNXP_MR_REG, mr1);
+	sccnxp_port_write(port, SCCNXP_MR_REG, mr2);
+
+	/* Set read status mask */
+	port->read_status_mask = SR_OVR;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= SR_PE | SR_FE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= SR_BRK;
+
+	/* Set status ignore mask */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNBRK)
+		port->ignore_status_mask |= SR_BRK;
+	if (!(termios->c_cflag & CREAD))
+		port->ignore_status_mask |= SR_PE | SR_OVR | SR_FE | SR_BRK;
+
+	/* Setup baudrate */
+	baud = uart_get_baud_rate(port, termios, old, 50,
+				  (s->flags & SCCNXP_HAVE_MR0) ?
+				  230400 : 38400);
+	sccnxp_set_baud(port, baud);
+
+	/* Update timeout according to new baud rate */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	/* Enable RX & TX */
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
+
+	mutex_unlock(&s->sccnxp_mutex);
+}
+
+static int sccnxp_startup(struct uart_port *port)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	mutex_lock(&s->sccnxp_mutex);
+
+	if (s->flags & SCCNXP_HAVE_IO) {
+		/* Outputs are controlled manually */
+		sccnxp_write(port, SCCNXP_OPCR_REG, 0);
+	}
+
+	/* Reset break condition, status and FIFOs */
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET);
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET);
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET);
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET);
+
+	/* Enable RX & TX */
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
+
+	/* Enable RX interrupt */
+	sccnxp_enable_irq(port, IMR_RXRDY);
+
+	mutex_unlock(&s->sccnxp_mutex);
+
+	return 0;
+}
+
+static void sccnxp_shutdown(struct uart_port *port)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	mutex_lock(&s->sccnxp_mutex);
+
+	/* Disable interrupts */
+	sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
+
+	/* Disable TX & RX */
+	sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE | CR_TX_DISABLE);
+
+	/* Leave direction to input */
+	if (s->flags & SCCNXP_HAVE_IO)
+		sccnxp_set_bit(port, DIR_OP, 0);
+
+	mutex_unlock(&s->sccnxp_mutex);
+}
+
+static const char *sccnxp_type(struct uart_port *port)
+{
+	struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+	return (port->type == PORT_SC26XX) ? s->name : NULL;
+}
+
+static void sccnxp_release_port(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static int sccnxp_request_port(struct uart_port *port)
+{
+	/* Do nothing */
+	return 0;
+}
+
+static void sccnxp_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_SC26XX;
+}
+
+static int sccnxp_verify_port(struct uart_port *port, struct serial_struct *s)
+{
+	if ((s->type == PORT_UNKNOWN) || (s->type == PORT_SC26XX))
+		return 0;
+	if (s->irq == port->irq)
+		return 0;
+
+	return -EINVAL;
+}
+
+static const struct uart_ops sccnxp_ops = {
+	.tx_empty	= sccnxp_tx_empty,
+	.set_mctrl	= sccnxp_set_mctrl,
+	.get_mctrl	= sccnxp_get_mctrl,
+	.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,
+	.set_termios	= sccnxp_set_termios,
+	.type		= sccnxp_type,
+	.release_port	= sccnxp_release_port,
+	.request_port	= sccnxp_request_port,
+	.config_port	= sccnxp_config_port,
+	.verify_port	= sccnxp_verify_port,
+};
+
+#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
+static void sccnxp_console_putchar(struct uart_port *port, int c)
+{
+	int tryes = 100000;
+
+	while (tryes--) {
+		if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXRDY) {
+			sccnxp_port_write(port, SCCNXP_THR_REG, c);
+			break;
+		}
+		barrier();
+	}
+}
+
+static void sccnxp_console_write(struct console *co, const char *c, unsigned n)
+{
+	struct sccnxp_port *s = (struct sccnxp_port *)co->data;
+	struct uart_port *port = &s->port[co->index];
+
+	mutex_lock(&s->sccnxp_mutex);
+	uart_console_write(port, c, n, sccnxp_console_putchar);
+	mutex_unlock(&s->sccnxp_mutex);
+}
+
+static int sccnxp_console_setup(struct console *co, char *options)
+{
+	struct sccnxp_port *s = (struct sccnxp_port *)co->data;
+	struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
+	int baud = 9600, bits = 8, parity = 'n', flow = 'n';
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+#endif
+
+static int __devinit sccnxp_probe(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	int chiptype = pdev->id_entry->driver_data;
+	struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev);
+	int i, ret, fifosize, freq_min, freq_max;
+	struct sccnxp_port *s;
+	void __iomem *membase;
+
+	if (!res) {
+		dev_err(&pdev->dev, "Missing memory resource data\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	dev_set_name(&pdev->dev, SCCNXP_NAME);
+
+	s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL);
+	if (!s) {
+		dev_err(&pdev->dev, "Error allocating port structure\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, s);
+
+	mutex_init(&s->sccnxp_mutex);
+
+	/* Individual chip settings */
+	switch (chiptype) {
+	case SCCNXP_TYPE_SC2681:
+		s->name		= "SC2681";
+		s->uart.nr	= 2;
+		s->freq_std	= 3686400;
+		s->addr_mask	= 0x0f;
+		s->flags	= SCCNXP_HAVE_IO;
+		fifosize	= 3;
+		freq_min	= 1000000;
+		freq_max	= 4000000;
+		break;
+	case SCCNXP_TYPE_SC2691:
+		s->name		= "SC2691";
+		s->uart.nr	= 1;
+		s->freq_std	= 3686400;
+		s->addr_mask	= 0x07;
+		s->flags	= 0;
+		fifosize	= 3;
+		freq_min	= 1000000;
+		freq_max	= 4000000;
+		break;
+	case SCCNXP_TYPE_SC2692:
+		s->name		= "SC2692";
+		s->uart.nr	= 2;
+		s->freq_std	= 3686400;
+		s->addr_mask	= 0x0f;
+		s->flags	= SCCNXP_HAVE_IO;
+		fifosize	= 3;
+		freq_min	= 1000000;
+		freq_max	= 4000000;
+		break;
+	case SCCNXP_TYPE_SC2891:
+		s->name		= "SC2891";
+		s->uart.nr	= 1;
+		s->freq_std	= 3686400;
+		s->addr_mask	= 0x0f;
+		s->flags	= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
+		fifosize	= 16;
+		freq_min	= 100000;
+		freq_max	= 8000000;
+		break;
+	case SCCNXP_TYPE_SC2892:
+		s->name		= "SC2892";
+		s->uart.nr	= 2;
+		s->freq_std	= 3686400;
+		s->addr_mask	= 0x0f;
+		s->flags	= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
+		fifosize	= 16;
+		freq_min	= 100000;
+		freq_max	= 8000000;
+		break;
+	case SCCNXP_TYPE_SC28202:
+		s->name		= "SC28202";
+		s->uart.nr	= 2;
+		s->freq_std	= 14745600;
+		s->addr_mask	= 0x7f;
+		s->flags	= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
+		fifosize	= 256;
+		freq_min	= 1000000;
+		freq_max	= 50000000;
+		break;
+	case SCCNXP_TYPE_SC68681:
+		s->name		= "SC68681";
+		s->uart.nr	= 2;
+		s->freq_std	= 3686400;
+		s->addr_mask	= 0x0f;
+		s->flags	= SCCNXP_HAVE_IO;
+		fifosize	= 3;
+		freq_min	= 1000000;
+		freq_max	= 4000000;
+		break;
+	case SCCNXP_TYPE_SC68692:
+		s->name		= "SC68692";
+		s->uart.nr	= 2;
+		s->freq_std	= 3686400;
+		s->addr_mask	= 0x0f;
+		s->flags	= SCCNXP_HAVE_IO;
+		fifosize	= 3;
+		freq_min	= 1000000;
+		freq_max	= 4000000;
+		break;
+	default:
+		dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype);
+		ret = -ENOTSUPP;
+		goto err_out;
+	}
+
+	if (!pdata) {
+		dev_warn(&pdev->dev,
+			 "No platform data supplied, using defaults\n");
+		s->pdata.frequency = s->freq_std;
+	} else
+		memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
+
+	s->irq = platform_get_irq(pdev, 0);
+	if (s->irq <= 0) {
+		dev_err(&pdev->dev, "Missing irq resource data\n");
+		ret = -ENXIO;
+		goto err_out;
+	}
+
+	/* Check input frequency */
+	if ((s->pdata.frequency < freq_min) ||
+	    (s->pdata.frequency > freq_max)) {
+		dev_err(&pdev->dev, "Frequency out of bounds\n");
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	membase = devm_request_and_ioremap(&pdev->dev, res);
+	if (!membase) {
+		dev_err(&pdev->dev, "Failed to ioremap\n");
+		ret = -EIO;
+		goto err_out;
+	}
+
+	s->uart.owner		= THIS_MODULE;
+	s->uart.dev_name	= "ttySC";
+	s->uart.major		= SCCNXP_MAJOR;
+	s->uart.minor		= SCCNXP_MINOR;
+#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
+	s->uart.cons		= &s->console;
+	s->uart.cons->device	= uart_console_device;
+	s->uart.cons->write	= sccnxp_console_write;
+	s->uart.cons->setup	= sccnxp_console_setup;
+	s->uart.cons->flags	= CON_PRINTBUFFER;
+	s->uart.cons->index	= -1;
+	s->uart.cons->data	= s;
+	strcpy(s->uart.cons->name, "ttySC");
+#endif
+	ret = uart_register_driver(&s->uart);
+	if (ret) {
+		dev_err(&pdev->dev, "Registering UART driver failed\n");
+		goto err_out;
+	}
+
+	for (i = 0; i < s->uart.nr; i++) {
+		s->port[i].line		= i;
+		s->port[i].dev		= &pdev->dev;
+		s->port[i].irq		= s->irq;
+		s->port[i].type		= PORT_SC26XX;
+		s->port[i].fifosize	= fifosize;
+		s->port[i].flags	= UPF_SKIP_TEST | UPF_FIXED_TYPE;
+		s->port[i].iotype	= UPIO_MEM;
+		s->port[i].mapbase	= res->start;
+		s->port[i].membase	= membase;
+		s->port[i].regshift	= s->pdata.reg_shift;
+		s->port[i].uartclk	= s->pdata.frequency;
+		s->port[i].ops		= &sccnxp_ops;
+		uart_add_one_port(&s->uart, &s->port[i]);
+		/* Set direction to input */
+		if (s->flags & SCCNXP_HAVE_IO)
+			sccnxp_set_bit(&s->port[i], DIR_OP, 0);
+	}
+
+	/* Disable interrupts */
+	s->imr = 0;
+	sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0);
+
+	/* Board specific configure */
+	if (s->pdata.init)
+		s->pdata.init();
+
+	ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, sccnxp_ist,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					dev_name(&pdev->dev), s);
+	if (!ret)
+		return 0;
+
+	dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq);
+
+err_out:
+	platform_set_drvdata(pdev, NULL);
+
+	return ret;
+}
+
+static int __devexit sccnxp_remove(struct platform_device *pdev)
+{
+	int i;
+	struct sccnxp_port *s = platform_get_drvdata(pdev);
+
+	devm_free_irq(&pdev->dev, s->irq, s);
+
+	for (i = 0; i < s->uart.nr; i++)
+		uart_remove_one_port(&s->uart, &s->port[i]);
+
+	uart_unregister_driver(&s->uart);
+	platform_set_drvdata(pdev, NULL);
+
+	if (s->pdata.exit)
+		s->pdata.exit();
+
+	return 0;
+}
+
+static const struct platform_device_id sccnxp_id_table[] = {
+	{ "sc2681",	SCCNXP_TYPE_SC2681 },
+	{ "sc2691",	SCCNXP_TYPE_SC2691 },
+	{ "sc2692",	SCCNXP_TYPE_SC2692 },
+	{ "sc2891",	SCCNXP_TYPE_SC2891 },
+	{ "sc2892",	SCCNXP_TYPE_SC2892 },
+	{ "sc28202",	SCCNXP_TYPE_SC28202 },
+	{ "sc68681",	SCCNXP_TYPE_SC68681 },
+	{ "sc68692",	SCCNXP_TYPE_SC68692 },
+};
+MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
+
+static struct platform_driver sccnxp_uart_driver = {
+	.driver = {
+		.name	= SCCNXP_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sccnxp_probe,
+	.remove		= __devexit_p(sccnxp_remove),
+	.id_table	= sccnxp_id_table,
+};
+module_platform_driver(sccnxp_uart_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("SCCNXP serial driver");

+ 135 - 88
drivers/tty/serial/serial_core.c

@@ -159,7 +159,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
 	retval = uport->ops->startup(uport);
 	if (retval == 0) {
 		if (uart_console(uport) && uport->cons->cflag) {
-			tty->termios->c_cflag = uport->cons->cflag;
+			tty->termios.c_cflag = uport->cons->cflag;
 			uport->cons->cflag = 0;
 		}
 		/*
@@ -172,11 +172,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
 			 * Setup the RTS and DTR signals once the
 			 * port is open and ready to respond.
 			 */
-			if (tty->termios->c_cflag & CBAUD)
+			if (tty->termios.c_cflag & CBAUD)
 				uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
 		}
 
-		if (port->flags & ASYNC_CTS_FLOW) {
+		if (tty_port_cts_enabled(port)) {
 			spin_lock_irq(&uport->lock);
 			if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
 				tty->hw_stopped = 1;
@@ -240,7 +240,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
 		/*
 		 * Turn off DTR and RTS early.
 		 */
-		if (!tty || (tty->termios->c_cflag & HUPCL))
+		if (!tty || (tty->termios.c_cflag & HUPCL))
 			uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
 
 		uart_port_shutdown(port);
@@ -440,10 +440,10 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
 	 * If we have no tty, termios, or the port does not exist,
 	 * then we can't set the parameters for this port.
 	 */
-	if (!tty || !tty->termios || uport->type == PORT_UNKNOWN)
+	if (!tty || uport->type == PORT_UNKNOWN)
 		return;
 
-	termios = tty->termios;
+	termios = &tty->termios;
 
 	/*
 	 * Set flags based on termios cflag
@@ -614,7 +614,7 @@ static void uart_throttle(struct tty_struct *tty)
 	if (I_IXOFF(tty))
 		uart_send_xchar(tty, STOP_CHAR(tty));
 
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		uart_clear_mctrl(state->uart_port, TIOCM_RTS);
 }
 
@@ -630,42 +630,48 @@ static void uart_unthrottle(struct tty_struct *tty)
 			uart_send_xchar(tty, START_CHAR(tty));
 	}
 
-	if (tty->termios->c_cflag & CRTSCTS)
+	if (tty->termios.c_cflag & CRTSCTS)
 		uart_set_mctrl(port, TIOCM_RTS);
 }
 
-static int uart_get_info(struct uart_state *state,
-			 struct serial_struct __user *retinfo)
+static void uart_get_info(struct tty_port *port,
+                        struct uart_state *state,
+			struct serial_struct *retinfo)
 {
 	struct uart_port *uport = state->uart_port;
-	struct tty_port *port = &state->port;
-	struct serial_struct tmp;
-
-	memset(&tmp, 0, sizeof(tmp));
 
-	/* Ensure the state we copy is consistent and no hardware changes
-	   occur as we go */
-	mutex_lock(&port->mutex);
+	memset(retinfo, 0, sizeof(*retinfo));
 
-	tmp.type	    = uport->type;
-	tmp.line	    = uport->line;
-	tmp.port	    = uport->iobase;
+	retinfo->type	    = uport->type;
+	retinfo->line	    = uport->line;
+	retinfo->port	    = uport->iobase;
 	if (HIGH_BITS_OFFSET)
-		tmp.port_high = (long) uport->iobase >> HIGH_BITS_OFFSET;
-	tmp.irq		    = uport->irq;
-	tmp.flags	    = uport->flags;
-	tmp.xmit_fifo_size  = uport->fifosize;
-	tmp.baud_base	    = uport->uartclk / 16;
-	tmp.close_delay	    = jiffies_to_msecs(port->close_delay) / 10;
-	tmp.closing_wait    = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+		retinfo->port_high = (long) uport->iobase >> HIGH_BITS_OFFSET;
+	retinfo->irq		    = uport->irq;
+	retinfo->flags	    = uport->flags;
+	retinfo->xmit_fifo_size  = uport->fifosize;
+	retinfo->baud_base	    = uport->uartclk / 16;
+	retinfo->close_delay	    = jiffies_to_msecs(port->close_delay) / 10;
+	retinfo->closing_wait    = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
 				ASYNC_CLOSING_WAIT_NONE :
 				jiffies_to_msecs(port->closing_wait) / 10;
-	tmp.custom_divisor  = uport->custom_divisor;
-	tmp.hub6	    = uport->hub6;
-	tmp.io_type         = uport->iotype;
-	tmp.iomem_reg_shift = uport->regshift;
-	tmp.iomem_base      = (void *)(unsigned long)uport->mapbase;
+	retinfo->custom_divisor  = uport->custom_divisor;
+	retinfo->hub6	    = uport->hub6;
+	retinfo->io_type         = uport->iotype;
+	retinfo->iomem_reg_shift = uport->regshift;
+	retinfo->iomem_base      = (void *)(unsigned long)uport->mapbase;
+}
 
+static int uart_get_info_user(struct uart_state *state,
+			 struct serial_struct __user *retinfo)
+{
+	struct tty_port *port = &state->port;
+	struct serial_struct tmp;
+
+	/* Ensure the state we copy is consistent and no hardware changes
+	   occur as we go */
+	mutex_lock(&port->mutex);
+	uart_get_info(port, state, &tmp);
 	mutex_unlock(&port->mutex);
 
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
@@ -673,42 +679,30 @@ static int uart_get_info(struct uart_state *state,
 	return 0;
 }
 
-static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
-			 struct serial_struct __user *newinfo)
+static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
+			 struct uart_state *state,
+			 struct serial_struct *new_info)
 {
-	struct serial_struct new_serial;
 	struct uart_port *uport = state->uart_port;
-	struct tty_port *port = &state->port;
 	unsigned long new_port;
 	unsigned int change_irq, change_port, closing_wait;
 	unsigned int old_custom_divisor, close_delay;
 	upf_t old_flags, new_flags;
 	int retval = 0;
 
-	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-		return -EFAULT;
-
-	new_port = new_serial.port;
+	new_port = new_info->port;
 	if (HIGH_BITS_OFFSET)
-		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
+		new_port += (unsigned long) new_info->port_high << HIGH_BITS_OFFSET;
 
-	new_serial.irq = irq_canonicalize(new_serial.irq);
-	close_delay = msecs_to_jiffies(new_serial.close_delay * 10);
-	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+	new_info->irq = irq_canonicalize(new_info->irq);
+	close_delay = msecs_to_jiffies(new_info->close_delay * 10);
+	closing_wait = new_info->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
 			ASYNC_CLOSING_WAIT_NONE :
-			msecs_to_jiffies(new_serial.closing_wait * 10);
+			msecs_to_jiffies(new_info->closing_wait * 10);
 
-	/*
-	 * This semaphore protects port->count.  It is also
-	 * very useful to prevent opens.  Also, take the
-	 * port configuration semaphore to make sure that a
-	 * module insertion/removal doesn't change anything
-	 * under us.
-	 */
-	mutex_lock(&port->mutex);
 
 	change_irq  = !(uport->flags & UPF_FIXED_PORT)
-		&& new_serial.irq != uport->irq;
+		&& new_info->irq != uport->irq;
 
 	/*
 	 * Since changing the 'type' of the port changes its resource
@@ -717,29 +711,29 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
 	 */
 	change_port = !(uport->flags & UPF_FIXED_PORT)
 		&& (new_port != uport->iobase ||
-		    (unsigned long)new_serial.iomem_base != uport->mapbase ||
-		    new_serial.hub6 != uport->hub6 ||
-		    new_serial.io_type != uport->iotype ||
-		    new_serial.iomem_reg_shift != uport->regshift ||
-		    new_serial.type != uport->type);
+		    (unsigned long)new_info->iomem_base != uport->mapbase ||
+		    new_info->hub6 != uport->hub6 ||
+		    new_info->io_type != uport->iotype ||
+		    new_info->iomem_reg_shift != uport->regshift ||
+		    new_info->type != uport->type);
 
 	old_flags = uport->flags;
-	new_flags = new_serial.flags;
+	new_flags = new_info->flags;
 	old_custom_divisor = uport->custom_divisor;
 
 	if (!capable(CAP_SYS_ADMIN)) {
 		retval = -EPERM;
 		if (change_irq || change_port ||
-		    (new_serial.baud_base != uport->uartclk / 16) ||
+		    (new_info->baud_base != uport->uartclk / 16) ||
 		    (close_delay != port->close_delay) ||
 		    (closing_wait != port->closing_wait) ||
-		    (new_serial.xmit_fifo_size &&
-		     new_serial.xmit_fifo_size != uport->fifosize) ||
+		    (new_info->xmit_fifo_size &&
+		     new_info->xmit_fifo_size != uport->fifosize) ||
 		    (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
 			goto exit;
 		uport->flags = ((uport->flags & ~UPF_USR_MASK) |
 			       (new_flags & UPF_USR_MASK));
-		uport->custom_divisor = new_serial.custom_divisor;
+		uport->custom_divisor = new_info->custom_divisor;
 		goto check_and_exit;
 	}
 
@@ -747,10 +741,10 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
 	 * Ask the low level driver to verify the settings.
 	 */
 	if (uport->ops->verify_port)
-		retval = uport->ops->verify_port(uport, &new_serial);
+		retval = uport->ops->verify_port(uport, new_info);
 
-	if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
-	    (new_serial.baud_base < 9600))
+	if ((new_info->irq >= nr_irqs) || (new_info->irq < 0) ||
+	    (new_info->baud_base < 9600))
 		retval = -EINVAL;
 
 	if (retval)
@@ -790,11 +784,11 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
 			uport->ops->release_port(uport);
 
 		uport->iobase = new_port;
-		uport->type = new_serial.type;
-		uport->hub6 = new_serial.hub6;
-		uport->iotype = new_serial.io_type;
-		uport->regshift = new_serial.iomem_reg_shift;
-		uport->mapbase = (unsigned long)new_serial.iomem_base;
+		uport->type = new_info->type;
+		uport->hub6 = new_info->hub6;
+		uport->iotype = new_info->io_type;
+		uport->regshift = new_info->iomem_reg_shift;
+		uport->mapbase = (unsigned long)new_info->iomem_base;
 
 		/*
 		 * Claim and map the new regions
@@ -835,16 +829,16 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
 	}
 
 	if (change_irq)
-		uport->irq      = new_serial.irq;
+		uport->irq      = new_info->irq;
 	if (!(uport->flags & UPF_FIXED_PORT))
-		uport->uartclk  = new_serial.baud_base * 16;
+		uport->uartclk  = new_info->baud_base * 16;
 	uport->flags            = (uport->flags & ~UPF_CHANGE_MASK) |
 				 (new_flags & UPF_CHANGE_MASK);
-	uport->custom_divisor   = new_serial.custom_divisor;
+	uport->custom_divisor   = new_info->custom_divisor;
 	port->close_delay     = close_delay;
 	port->closing_wait    = closing_wait;
-	if (new_serial.xmit_fifo_size)
-		uport->fifosize = new_serial.xmit_fifo_size;
+	if (new_info->xmit_fifo_size)
+		uport->fifosize = new_info->xmit_fifo_size;
 	if (port->tty)
 		port->tty->low_latency =
 			(uport->flags & UPF_LOW_LATENCY) ? 1 : 0;
@@ -873,6 +867,28 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
 	} else
 		retval = uart_startup(tty, state, 1);
  exit:
+	return retval;
+}
+
+static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state,
+			 struct serial_struct __user *newinfo)
+{
+	struct serial_struct new_serial;
+	struct tty_port *port = &state->port;
+	int retval;
+
+	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+		return -EFAULT;
+
+	/*
+	 * This semaphore protects port->count.  It is also
+	 * very useful to prevent opens.  Also, take the
+	 * port configuration semaphore to make sure that a
+	 * module insertion/removal doesn't change anything
+	 * under us.
+	 */
+	mutex_lock(&port->mutex);
+	retval = uart_set_info(tty, port, state, &new_serial);
 	mutex_unlock(&port->mutex);
 	return retval;
 }
@@ -1115,11 +1131,11 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd,
 	 */
 	switch (cmd) {
 	case TIOCGSERIAL:
-		ret = uart_get_info(state, uarg);
+		ret = uart_get_info_user(state, uarg);
 		break;
 
 	case TIOCSSERIAL:
-		ret = uart_set_info(tty, state, uarg);
+		ret = uart_set_info_user(tty, state, uarg);
 		break;
 
 	case TIOCSERCONFIG:
@@ -1187,7 +1203,7 @@ static void uart_set_ldisc(struct tty_struct *tty)
 	struct uart_port *uport = state->uart_port;
 
 	if (uport->ops->set_ldisc)
-		uport->ops->set_ldisc(uport, tty->termios->c_line);
+		uport->ops->set_ldisc(uport, tty->termios.c_line);
 }
 
 static void uart_set_termios(struct tty_struct *tty,
@@ -1195,7 +1211,7 @@ static void uart_set_termios(struct tty_struct *tty,
 {
 	struct uart_state *state = tty->driver_data;
 	unsigned long flags;
-	unsigned int cflag = tty->termios->c_cflag;
+	unsigned int cflag = tty->termios.c_cflag;
 
 
 	/*
@@ -1206,9 +1222,9 @@ static void uart_set_termios(struct tty_struct *tty,
 	 */
 #define RELEVANT_IFLAG(iflag)	((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 	if ((cflag ^ old_termios->c_cflag) == 0 &&
-	    tty->termios->c_ospeed == old_termios->c_ospeed &&
-	    tty->termios->c_ispeed == old_termios->c_ispeed &&
-	    RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) {
+	    tty->termios.c_ospeed == old_termios->c_ospeed &&
+	    tty->termios.c_ispeed == old_termios->c_ispeed &&
+	    RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) {
 		return;
 	}
 
@@ -1960,8 +1976,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
 		/*
 		 * If that's unset, use the tty termios setting.
 		 */
-		if (port->tty && port->tty->termios && termios.c_cflag == 0)
-			termios = *(port->tty->termios);
+		if (port->tty && termios.c_cflag == 0)
+			termios = port->tty->termios;
 
 		if (console_suspend_enabled)
 			uart_change_pm(state, 0);
@@ -2293,6 +2309,36 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
 	return p->tty_driver;
 }
 
+static ssize_t uart_get_attr_uartclk(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct tty_port *port = dev_get_drvdata(dev);
+	struct uart_state *state = container_of(port, struct uart_state, port);
+
+	mutex_lock(&state->port.mutex);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+	mutex_unlock(&state->port.mutex);
+
+	return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
+
+static struct attribute *tty_dev_attrs[] = {
+	&dev_attr_uartclk.attr,
+	NULL,
+	};
+
+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
@@ -2346,7 +2392,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 	 * Register the port whether it's detected or not.  This allows
 	 * setserial to be used to alter this ports parameters.
 	 */
-	tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
+	tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
+			uport->line, uport->dev, port, tty_dev_attr_groups);
 	if (likely(!IS_ERR(tty_dev))) {
 		device_set_wakeup_capable(tty_dev, 1);
 	} else {
@@ -2492,7 +2539,7 @@ void uart_handle_cts_change(struct uart_port *uport, unsigned int status)
 
 	uport->icount.cts++;
 
-	if (port->flags & ASYNC_CTS_FLOW) {
+	if (tty_port_cts_enabled(port)) {
 		if (tty->hw_stopped) {
 			if (status) {
 				tty->hw_stopped = 0;

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

@@ -668,7 +668,7 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
 	if (res == NULL) {
 		dev_err(&pdev->dev, "Insufficient resources.\n");
 		ret = -EFAULT;
-		goto irq_err;
+		goto err;
 	}
 	port->irq = res->start;
 
@@ -676,7 +676,7 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
 		sirfport->p = pinctrl_get_select_default(&pdev->dev);
 		ret = IS_ERR(sirfport->p);
 		if (ret)
-			goto pin_err;
+			goto err;
 	}
 
 	port->ops = &sirfsoc_uart_ops;
@@ -695,9 +695,6 @@ port_err:
 	platform_set_drvdata(pdev, NULL);
 	if (sirfport->hw_flow_ctrl)
 		pinctrl_put(sirfport->p);
-pin_err:
-irq_err:
-	devm_iounmap(&pdev->dev, port->membase);
 err:
 	return ret;
 }
@@ -709,7 +706,6 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
 	platform_set_drvdata(pdev, NULL);
 	if (sirfport->hw_flow_ctrl)
 		pinctrl_put(sirfport->p);
-	devm_iounmap(&pdev->dev, port->membase);
 	uart_remove_one_port(&sirfsoc_uart_drv, port);
 	return 0;
 }

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

@@ -58,10 +58,16 @@
 enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT };
 static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" };
 
+struct serial_uart_config {
+	char	*name;
+	int	dfl_xmit_fifo_size;
+	int	flags;
+};
+
 /*
  * Here we define the default xmit fifo size used for each type of UART.
  */
-static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
+static const struct serial_uart_config uart_config[] = {
 	{ "unknown",	1,	0 },
 	{ "8250",	1,	0 },
 	{ "16450",	1,	0 },

+ 47 - 39
drivers/tty/synclink.c

@@ -1359,7 +1359,7 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info )
 			}
 		}
 	
-		if ( (info->port.flags & ASYNC_CTS_FLOW) && 
+		if (tty_port_cts_enabled(&info->port) &&
 		     (status & MISCSTATUS_CTS_LATCHED) ) {
 			if (info->port.tty->hw_stopped) {
 				if (status & MISCSTATUS_CTS) {
@@ -1840,22 +1840,22 @@ static void shutdown(struct mgsl_struct * info)
 	usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
 		TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
 	usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
-	
+
 	/* Disable DMAEN (Port 7, Bit 14) */
 	/* This disconnects the DMA request signal from the ISA bus */
 	/* on the ISA adapter. This has no effect for the PCI adapter */
 	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));
-	
+
 	/* Disable INTEN (Port 6, Bit12) */
 	/* This disconnects the IRQ request signal to the ISA bus */
 	/* on the ISA adapter. This has no effect for the PCI adapter */
 	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12));
-	
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+
+	if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) {
  		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
 		usc_set_serial_signals(info);
 	}
-	
+
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
 	mgsl_release_resources(info);	
@@ -1895,7 +1895,7 @@ static void mgsl_program_hw(struct mgsl_struct *info)
 	usc_EnableInterrupts(info, IO_PIN);
 	usc_get_serial_signals(info);
 		
-	if (info->netcount || info->port.tty->termios->c_cflag & CREAD)
+	if (info->netcount || info->port.tty->termios.c_cflag & CREAD)
 		usc_start_receiver(info);
 		
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
@@ -1908,14 +1908,14 @@ static void mgsl_change_params(struct mgsl_struct *info)
 	unsigned cflag;
 	int bits_per_char;
 
-	if (!info->port.tty || !info->port.tty->termios)
+	if (!info->port.tty)
 		return;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_change_params(%s)\n",
 			 __FILE__,__LINE__, info->device_name );
 			 
-	cflag = info->port.tty->termios->c_cflag;
+	cflag = info->port.tty->termios.c_cflag;
 
 	/* if B0 rate (hangup) specified then negate DTR and RTS */
 	/* otherwise assert DTR and RTS */
@@ -2367,8 +2367,8 @@ static void mgsl_throttle(struct tty_struct * tty)
 	
 	if (I_IXOFF(tty))
 		mgsl_send_xchar(tty, STOP_CHAR(tty));
- 
- 	if (tty->termios->c_cflag & CRTSCTS) {
+
+	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->irq_spinlock,flags);
 		info->serial_signals &= ~SerialSignal_RTS;
 	 	usc_set_serial_signals(info);
@@ -2401,8 +2401,8 @@ static void mgsl_unthrottle(struct tty_struct * tty)
 		else
 			mgsl_send_xchar(tty, START_CHAR(tty));
 	}
-	
- 	if (tty->termios->c_cflag & CRTSCTS) {
+
+	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->irq_spinlock,flags);
 		info->serial_signals |= SerialSignal_RTS;
 	 	usc_set_serial_signals(info);
@@ -3045,7 +3045,7 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio
 
 	/* Handle transition to B0 status */
 	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
+	    !(tty->termios.c_cflag & CBAUD)) {
 		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
 		spin_lock_irqsave(&info->irq_spinlock,flags);
 	 	usc_set_serial_signals(info);
@@ -3054,9 +3054,9 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio
 	
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
+	    tty->termios.c_cflag & CBAUD) {
 		info->serial_signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) || 
+ 		if (!(tty->termios.c_cflag & CRTSCTS) || 
  		    !test_bit(TTY_THROTTLED, &tty->flags)) {
 			info->serial_signals |= SerialSignal_RTS;
  		}
@@ -3067,7 +3067,7 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio
 	
 	/* Handle turning off CRTSCTS */
 	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		mgsl_start(tty);
 	}
@@ -3287,7 +3287,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 		return 0;
 	}
 
-	if (tty->termios->c_cflag & CLOCAL)
+	if (tty->termios.c_cflag & CLOCAL)
 		do_clocal = true;
 
 	/* Wait for carrier detect and the line to become
@@ -3313,7 +3313,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 	port->blocked_open++;
 	
 	while (1) {
-		if (tty->termios->c_cflag & CBAUD)
+		if (tty->termios.c_cflag & CBAUD)
 			tty_port_raise_dtr_rts(port);
 		
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			printk("%s(%d):block_til_ready blocking on %s count=%d\n",
 				 __FILE__,__LINE__, tty->driver->name, port->count );
 				 
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 	
 	set_current_state(TASK_RUNNING);
@@ -3362,6 +3362,29 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 	
 }	/* end of block_til_ready() */
 
+static int mgsl_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	struct mgsl_struct *info;
+	int line = tty->index;
+
+	/* verify range of specified line number */
+	if (line >= mgsl_device_count) {
+		printk("%s(%d):mgsl_open with invalid line #%d.\n",
+			__FILE__, __LINE__, line);
+		return -ENODEV;
+	}
+
+	/* find the info structure for the specified line */
+	info = mgsl_device_list;
+	while (info && info->line != line)
+		info = info->next_device;
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
+		return -ENODEV;
+	tty->driver_data = info;
+
+	return tty_port_install(&info->port, driver, tty);
+}
+
 /* mgsl_open()
  *
  *	Called when a port is opened.  Init and enable port.
@@ -3374,26 +3397,10 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
  */
 static int mgsl_open(struct tty_struct *tty, struct file * filp)
 {
-	struct mgsl_struct	*info;
-	int 			retval, line;
+	struct mgsl_struct *info = tty->driver_data;
 	unsigned long flags;
+	int retval;
 
-	/* verify range of specified line number */	
-	line = tty->index;
-	if (line >= mgsl_device_count) {
-		printk("%s(%d):mgsl_open with invalid line #%d.\n",
-			__FILE__,__LINE__,line);
-		return -ENODEV;
-	}
-
-	/* find the info structure for the specified line */
-	info = mgsl_device_list;
-	while(info && info->line != line)
-		info = info->next_device;
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
-		return -ENODEV;
-	
-	tty->driver_data = info;
 	info->port.tty = tty;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
@@ -4297,6 +4304,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
 }	/* end of mgsl_allocate_device()*/
 
 static const struct tty_operations mgsl_ops = {
+	.install = mgsl_install,
 	.open = mgsl_open,
 	.close = mgsl_close,
 	.write = mgsl_write,

+ 20 - 17
drivers/tty/synclink_gt.c

@@ -785,7 +785,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
 	/* Handle transition to B0 status */
 	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
+	    !(tty->termios.c_cflag & CBAUD)) {
 		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
 		spin_lock_irqsave(&info->lock,flags);
 		set_signals(info);
@@ -794,9 +794,9 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
+	    tty->termios.c_cflag & CBAUD) {
 		info->signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) ||
+ 		if (!(tty->termios.c_cflag & CRTSCTS) ||
  		    !test_bit(TTY_THROTTLED, &tty->flags)) {
 			info->signals |= SerialSignal_RTS;
  		}
@@ -807,7 +807,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
 	/* Handle turning off CRTSCTS */
 	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		tx_release(tty);
 	}
@@ -1372,7 +1372,7 @@ static void throttle(struct tty_struct * tty)
 	DBGINFO(("%s throttle\n", info->device_name));
 	if (I_IXOFF(tty))
 		send_xchar(tty, STOP_CHAR(tty));
- 	if (tty->termios->c_cflag & CRTSCTS) {
+ 	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->lock,flags);
 		info->signals &= ~SerialSignal_RTS;
 	 	set_signals(info);
@@ -1397,7 +1397,7 @@ static void unthrottle(struct tty_struct * tty)
 		else
 			send_xchar(tty, START_CHAR(tty));
 	}
- 	if (tty->termios->c_cflag & CRTSCTS) {
+ 	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->lock,flags);
 		info->signals |= SerialSignal_RTS;
 	 	set_signals(info);
@@ -2053,7 +2053,7 @@ static void cts_change(struct slgt_info *info, unsigned short status)
 	wake_up_interruptible(&info->event_wait_q);
 	info->pending_bh |= BH_STATUS;
 
-	if (info->port.flags & ASYNC_CTS_FLOW) {
+	if (tty_port_cts_enabled(&info->port)) {
 		if (info->port.tty) {
 			if (info->port.tty->hw_stopped) {
 				if (info->signals & SerialSignal_CTS) {
@@ -2493,7 +2493,7 @@ static void shutdown(struct slgt_info *info)
 
 	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
 
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+ 	if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) {
  		info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
 		set_signals(info);
 	}
@@ -2534,7 +2534,7 @@ static void program_hw(struct slgt_info *info)
 	get_signals(info);
 
 	if (info->netcount ||
-	    (info->port.tty && info->port.tty->termios->c_cflag & CREAD))
+	    (info->port.tty && info->port.tty->termios.c_cflag & CREAD))
 		rx_start(info);
 
 	spin_unlock_irqrestore(&info->lock,flags);
@@ -2548,11 +2548,11 @@ static void change_params(struct slgt_info *info)
 	unsigned cflag;
 	int bits_per_char;
 
-	if (!info->port.tty || !info->port.tty->termios)
+	if (!info->port.tty)
 		return;
 	DBGINFO(("%s change_params\n", info->device_name));
 
-	cflag = info->port.tty->termios->c_cflag;
+	cflag = info->port.tty->termios.c_cflag;
 
 	/* if B0 rate (hangup) specified then negate DTR and RTS */
 	/* otherwise assert DTR and RTS */
@@ -3292,7 +3292,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 		return 0;
 	}
 
-	if (tty->termios->c_cflag & CLOCAL)
+	if (tty->termios.c_cflag & CLOCAL)
 		do_clocal = true;
 
 	/* Wait for carrier detect and the line to become
@@ -3314,7 +3314,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 	port->blocked_open++;
 
 	while (1) {
-		if ((tty->termios->c_cflag & CBAUD))
+		if ((tty->termios.c_cflag & CBAUD))
 			tty_port_raise_dtr_rts(port);
 
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 		}
 
 		DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 
 	set_current_state(TASK_RUNNING);
@@ -3689,8 +3689,11 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
 		}
 	}
 
-	for (i=0; i < port_count; ++i)
-		tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
+	for (i = 0; i < port_count; ++i) {
+		struct slgt_info *info = port_array[i];
+		tty_port_register_device(&info->port, serial_driver, info->line,
+				&info->pdev->dev);
+	}
 }
 
 static int __devinit init_one(struct pci_dev *dev,

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно