mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 22:50:41 +00:00
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>
This commit is contained in:
commit
a73403d85a
@ -17,3 +17,12 @@ Description:
|
|||||||
device, like 'tty1'.
|
device, like 'tty1'.
|
||||||
The file supports poll() to detect virtual
|
The file supports poll() to detect virtual
|
||||||
console switches.
|
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
|
||||||
|
|
||||||
|
@ -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>;
|
||||||
|
};
|
@ -25,6 +25,8 @@ Optional properties:
|
|||||||
accesses to the UART (e.g. TI davinci).
|
accesses to the UART (e.g. TI davinci).
|
||||||
- used-by-rtas : set to indicate that the port is in use by the OpenFirmware
|
- used-by-rtas : set to indicate that the port is in use by the OpenFirmware
|
||||||
RTAS and should not be registered.
|
RTAS and should not be registered.
|
||||||
|
- no-loopback-test: set to indicate that the port does not implements loopback
|
||||||
|
test mode
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
- this file.
|
- this file.
|
||||||
README.cycladesZ
|
README.cycladesZ
|
||||||
- info on Cyclades-Z firmware loading.
|
- info on Cyclades-Z firmware loading.
|
||||||
computone.txt
|
|
||||||
- info on Computone Intelliport II/Plus Multiport Serial Driver.
|
|
||||||
digiepca.txt
|
digiepca.txt
|
||||||
- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
|
- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
|
||||||
hayes-esp.txt
|
hayes-esp.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
|
|
@ -223,6 +223,7 @@ srmcons_init(void)
|
|||||||
driver->subtype = SYSTEM_TYPE_SYSCONS;
|
driver->subtype = SYSTEM_TYPE_SYSCONS;
|
||||||
driver->init_termios = tty_std_termios;
|
driver->init_termios = tty_std_termios;
|
||||||
tty_set_operations(driver, &srmcons_ops);
|
tty_set_operations(driver, &srmcons_ops);
|
||||||
|
tty_port_link_device(&srmcons_singleton.port, driver, 0);
|
||||||
err = tty_register_driver(driver);
|
err = tty_register_driver(driver);
|
||||||
if (err) {
|
if (err) {
|
||||||
put_tty_driver(driver);
|
put_tty_driver(driver);
|
||||||
|
@ -80,8 +80,9 @@ static struct omap_uart_port_info omap_serial_default_info[] __initdata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#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);
|
struct omap_device *od = to_omap_device(pdev);
|
||||||
|
|
||||||
if (!od)
|
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.
|
* in Smartidle Mode When Configured for DMA Operations.
|
||||||
* WA: configure uart in force idle mode.
|
* 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);
|
struct omap_device *od = to_omap_device(pdev);
|
||||||
|
|
||||||
omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
|
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);
|
struct omap_device *od = to_omap_device(pdev);
|
||||||
u8 idlemode;
|
u8 idlemode;
|
||||||
|
|
||||||
@ -119,10 +122,10 @@ static void omap_uart_set_smartidle(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#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_noidle(struct device *dev) {}
|
||||||
static void omap_uart_set_smartidle(struct platform_device *pdev) {}
|
static void omap_uart_set_smartidle(struct device *dev) {}
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
#ifdef CONFIG_OMAP_MUX
|
#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_timeout = info->dma_rx_timeout;
|
||||||
omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
|
omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
|
||||||
omap_up.autosuspend_timeout = info->autosuspend_timeout;
|
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 = &omap_up;
|
||||||
pdata_size = sizeof(struct omap_uart_port_info);
|
pdata_size = sizeof(struct omap_uart_port_info);
|
||||||
|
@ -524,33 +524,12 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
|
|||||||
};
|
};
|
||||||
#endif
|
#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 = {
|
static struct amba_pl011_data uart0_plat = {
|
||||||
#ifdef CONFIG_STE_DMA40
|
#ifdef CONFIG_STE_DMA40
|
||||||
.dma_filter = stedma40_filter,
|
.dma_filter = stedma40_filter,
|
||||||
.dma_rx_param = &uart0_dma_cfg_rx,
|
.dma_rx_param = &uart0_dma_cfg_rx,
|
||||||
.dma_tx_param = &uart0_dma_cfg_tx,
|
.dma_tx_param = &uart0_dma_cfg_tx,
|
||||||
#endif
|
#endif
|
||||||
.reset = ux500_uart0_reset,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct amba_pl011_data uart1_plat = {
|
static struct amba_pl011_data uart1_plat = {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#define __OMAP_SERIAL_H__
|
#define __OMAP_SERIAL_H__
|
||||||
|
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/pm_qos.h>
|
#include <linux/pm_qos.h>
|
||||||
|
|
||||||
#include <plat/mux.h>
|
#include <plat/mux.h>
|
||||||
@ -42,10 +42,10 @@
|
|||||||
#define OMAP_UART_WER_MOD_WKUP 0X7F
|
#define OMAP_UART_WER_MOD_WKUP 0X7F
|
||||||
|
|
||||||
/* Enable XON/XOFF flow control on output */
|
/* 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 */
|
/* 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_SYSC_RESET 0X07
|
||||||
#define OMAP_UART_TCR_TRIG 0X0F
|
#define OMAP_UART_TCR_TRIG 0X0F
|
||||||
@ -69,11 +69,14 @@ struct omap_uart_port_info {
|
|||||||
unsigned int dma_rx_timeout;
|
unsigned int dma_rx_timeout;
|
||||||
unsigned int autosuspend_timeout;
|
unsigned int autosuspend_timeout;
|
||||||
unsigned int dma_rx_poll_rate;
|
unsigned int dma_rx_poll_rate;
|
||||||
|
int DTR_gpio;
|
||||||
|
int DTR_inverted;
|
||||||
|
int DTR_present;
|
||||||
|
|
||||||
int (*get_context_loss_count)(struct device *);
|
int (*get_context_loss_count)(struct device *);
|
||||||
void (*set_forceidle)(struct platform_device *);
|
void (*set_forceidle)(struct device *);
|
||||||
void (*set_noidle)(struct platform_device *);
|
void (*set_noidle)(struct device *);
|
||||||
void (*enable_wakeup)(struct platform_device *, bool);
|
void (*enable_wakeup)(struct device *, bool);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uart_omap_dma {
|
struct uart_omap_dma {
|
||||||
@ -102,39 +105,4 @@ struct uart_omap_dma {
|
|||||||
unsigned int rx_timeout;
|
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__ */
|
#endif /* __OMAP_SERIAL_H__ */
|
||||||
|
@ -338,7 +338,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
|
|||||||
{
|
{
|
||||||
/* Handle turning off CRTSCTS */
|
/* Handle turning off CRTSCTS */
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,6 +545,7 @@ static int __init simrs_init(void)
|
|||||||
/* the port is imaginary */
|
/* the port is imaginary */
|
||||||
printk(KERN_INFO "ttyS0 at 0x03f8 (irq = %d) is a 16550\n", state->irq);
|
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);
|
retval = tty_register_driver(hp_simserial_driver);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
printk(KERN_ERR "Couldn't register simserial driver\n");
|
printk(KERN_ERR "Couldn't register simserial driver\n");
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <asm/natfeat.h>
|
#include <asm/natfeat.h>
|
||||||
|
|
||||||
static int stderr_id;
|
static int stderr_id;
|
||||||
|
static struct tty_port nfcon_tty_port;
|
||||||
static struct tty_driver *nfcon_tty_driver;
|
static struct tty_driver *nfcon_tty_driver;
|
||||||
|
|
||||||
static void nfputs(const char *str, unsigned int count)
|
static void nfputs(const char *str, unsigned int count)
|
||||||
@ -119,6 +120,8 @@ static int __init nfcon_init(void)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
tty_port_init(&nfcon_tty_port);
|
||||||
|
|
||||||
stderr_id = nf_get_id("NF_STDERR");
|
stderr_id = nf_get_id("NF_STDERR");
|
||||||
if (!stderr_id)
|
if (!stderr_id)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -135,6 +138,7 @@ static int __init nfcon_init(void)
|
|||||||
nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
|
nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||||
|
|
||||||
tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
|
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);
|
res = tty_register_driver(nfcon_tty_driver);
|
||||||
if (res) {
|
if (res) {
|
||||||
pr_err("failed to register nfcon tty driver\n");
|
pr_err("failed to register nfcon tty driver\n");
|
||||||
|
@ -47,40 +47,40 @@ static int __devinit octeon_serial_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
int irq, res;
|
int irq, res;
|
||||||
struct resource *res_mem;
|
struct resource *res_mem;
|
||||||
struct uart_port port;
|
struct uart_8250_port up;
|
||||||
|
|
||||||
/* All adaptors have an irq. */
|
/* All adaptors have an irq. */
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return irq;
|
return irq;
|
||||||
|
|
||||||
memset(&port, 0, sizeof(port));
|
memset(&up, 0, sizeof(up));
|
||||||
|
|
||||||
port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
up.port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
|
||||||
port.type = PORT_OCTEON;
|
up.port.type = PORT_OCTEON;
|
||||||
port.iotype = UPIO_MEM;
|
up.port.iotype = UPIO_MEM;
|
||||||
port.regshift = 3;
|
up.port.regshift = 3;
|
||||||
port.dev = &pdev->dev;
|
up.port.dev = &pdev->dev;
|
||||||
|
|
||||||
if (octeon_is_simulation())
|
if (octeon_is_simulation())
|
||||||
/* Make simulator output fast*/
|
/* Make simulator output fast*/
|
||||||
port.uartclk = 115200 * 16;
|
up.port.uartclk = 115200 * 16;
|
||||||
else
|
else
|
||||||
port.uartclk = octeon_get_io_clock_rate();
|
up.port.uartclk = octeon_get_io_clock_rate();
|
||||||
|
|
||||||
port.serial_in = octeon_serial_in;
|
up.port.serial_in = octeon_serial_in;
|
||||||
port.serial_out = octeon_serial_out;
|
up.port.serial_out = octeon_serial_out;
|
||||||
port.irq = irq;
|
up.port.irq = irq;
|
||||||
|
|
||||||
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (res_mem == NULL) {
|
if (res_mem == NULL) {
|
||||||
dev_err(&pdev->dev, "found no memory resource\n");
|
dev_err(&pdev->dev, "found no memory resource\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
port.mapbase = res_mem->start;
|
up.port.mapbase = res_mem->start;
|
||||||
port.membase = ioremap(res_mem->start, resource_size(res_mem));
|
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;
|
return res >= 0 ? 0 : res;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
static u32 a20r_ack_hwint(void)
|
||||||
{
|
{
|
||||||
u32 status = read_c0_status();
|
u32 status = read_c0_status();
|
||||||
|
@ -202,6 +202,7 @@ static int __init pdc_console_tty_driver_init(void)
|
|||||||
pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
|
pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
|
||||||
TTY_DRIVER_RESET_TERMIOS;
|
TTY_DRIVER_RESET_TERMIOS;
|
||||||
tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
|
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);
|
err = tty_register_driver(pdc_console_tty_driver);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -409,7 +409,8 @@ int setup_one_line(struct line *lines, int n, char *init,
|
|||||||
line->valid = 1;
|
line->valid = 1;
|
||||||
err = parse_chan_pair(new, line, n, opts, error_out);
|
err = parse_chan_pair(new, line, n, opts, error_out);
|
||||||
if (!err) {
|
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)) {
|
if (IS_ERR(d)) {
|
||||||
*error_out = "Failed to register device";
|
*error_out = "Failed to register device";
|
||||||
err = PTR_ERR(d);
|
err = PTR_ERR(d);
|
||||||
|
@ -223,6 +223,7 @@ int __init rs_init(void)
|
|||||||
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||||
|
|
||||||
tty_set_operations(serial_driver, &serial_ops);
|
tty_set_operations(serial_driver, &serial_ops);
|
||||||
|
tty_port_link_device(&serial_port, serial_driver, 0);
|
||||||
|
|
||||||
if (tty_register_driver(serial_driver))
|
if (tty_register_driver(serial_driver))
|
||||||
panic("Couldn't register serial driver\n");
|
panic("Couldn't register serial driver\n");
|
||||||
|
@ -58,7 +58,7 @@ static int ath_wakeup_ar3k(struct tty_struct *tty)
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
/* Disable Automatic RTSCTS */
|
/* Disable Automatic RTSCTS */
|
||||||
memcpy(&ktermios, tty->termios, sizeof(ktermios));
|
ktermios = tty->termios;
|
||||||
ktermios.c_cflag &= ~CRTSCTS;
|
ktermios.c_cflag &= ~CRTSCTS;
|
||||||
tty_set_termios(tty, &ktermios);
|
tty_set_termios(tty, &ktermios);
|
||||||
|
|
||||||
|
@ -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)
|
static int register_serial_portandirq(unsigned int port, int irq)
|
||||||
{
|
{
|
||||||
struct uart_port uart;
|
struct uart_8250_port uart;
|
||||||
|
|
||||||
switch ( port ) {
|
switch ( port ) {
|
||||||
case 0x3f8:
|
case 0x3f8:
|
||||||
@ -462,14 +462,14 @@ static int register_serial_portandirq(unsigned int port, int irq)
|
|||||||
} /* switch */
|
} /* switch */
|
||||||
/* irq is okay */
|
/* irq is okay */
|
||||||
|
|
||||||
memset(&uart, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
|
|
||||||
uart.uartclk = 1843200;
|
uart.port.uartclk = 1843200;
|
||||||
uart.iobase = port;
|
uart.port.iobase = port;
|
||||||
uart.irq = irq;
|
uart.port.irq = irq;
|
||||||
uart.iotype = UPIO_PORT;
|
uart.port.iotype = UPIO_PORT;
|
||||||
uart.flags = UPF_SHARE_IRQ;
|
uart.port.flags = UPF_SHARE_IRQ;
|
||||||
return serial8250_register_port(&uart);
|
return serial8250_register_8250_port(&uart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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->status_event_wait_q);
|
||||||
wake_up_interruptible(&info->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 (tty->hw_stopped) {
|
||||||
if (info->serial_signals & SerialSignal_CTS) {
|
if (info->serial_signals & SerialSignal_CTS) {
|
||||||
if (debug_level >= DEBUG_LEVEL_ISR)
|
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 */
|
/* TODO:disable interrupts instead of reset to preserve signal states */
|
||||||
reset_device(info);
|
reset_device(info);
|
||||||
|
|
||||||
if (!tty || tty->termios->c_cflag & HUPCL) {
|
if (!tty || tty->termios.c_cflag & HUPCL) {
|
||||||
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
|
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
|
||||||
set_signals(info);
|
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);
|
port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);
|
||||||
get_signals(info);
|
get_signals(info);
|
||||||
|
|
||||||
if (info->netcount || (tty && (tty->termios->c_cflag & CREAD)))
|
if (info->netcount || (tty && (tty->termios.c_cflag & CREAD)))
|
||||||
rx_start(info);
|
rx_start(info);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&info->lock,flags);
|
spin_unlock_irqrestore(&info->lock,flags);
|
||||||
@ -1398,14 +1398,14 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
|
|||||||
unsigned cflag;
|
unsigned cflag;
|
||||||
int bits_per_char;
|
int bits_per_char;
|
||||||
|
|
||||||
if (!tty || !tty->termios)
|
if (!tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (debug_level >= DEBUG_LEVEL_INFO)
|
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||||
printk("%s(%d):mgslpc_change_params(%s)\n",
|
printk("%s(%d):mgslpc_change_params(%s)\n",
|
||||||
__FILE__,__LINE__, info->device_name );
|
__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 */
|
/* if B0 rate (hangup) specified then negate DTR and RTS */
|
||||||
/* otherwise assert DTR and RTS */
|
/* otherwise assert DTR and RTS */
|
||||||
@ -1728,7 +1728,7 @@ static void mgslpc_throttle(struct tty_struct * tty)
|
|||||||
if (I_IXOFF(tty))
|
if (I_IXOFF(tty))
|
||||||
mgslpc_send_xchar(tty, STOP_CHAR(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);
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
info->serial_signals &= ~SerialSignal_RTS;
|
info->serial_signals &= ~SerialSignal_RTS;
|
||||||
set_signals(info);
|
set_signals(info);
|
||||||
@ -1757,7 +1757,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty)
|
|||||||
mgslpc_send_xchar(tty, START_CHAR(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);
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
info->serial_signals |= SerialSignal_RTS;
|
info->serial_signals |= SerialSignal_RTS;
|
||||||
set_signals(info);
|
set_signals(info);
|
||||||
@ -2293,8 +2293,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
|
|||||||
tty->driver->name );
|
tty->driver->name );
|
||||||
|
|
||||||
/* just return if nothing has changed */
|
/* just return if nothing has changed */
|
||||||
if ((tty->termios->c_cflag == old_termios->c_cflag)
|
if ((tty->termios.c_cflag == old_termios->c_cflag)
|
||||||
&& (RELEVANT_IFLAG(tty->termios->c_iflag)
|
&& (RELEVANT_IFLAG(tty->termios.c_iflag)
|
||||||
== RELEVANT_IFLAG(old_termios->c_iflag)))
|
== RELEVANT_IFLAG(old_termios->c_iflag)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2302,7 +2302,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
|
|||||||
|
|
||||||
/* Handle transition to B0 status */
|
/* Handle transition to B0 status */
|
||||||
if (old_termios->c_cflag & CBAUD &&
|
if (old_termios->c_cflag & CBAUD &&
|
||||||
!(tty->termios->c_cflag & CBAUD)) {
|
!(tty->termios.c_cflag & CBAUD)) {
|
||||||
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
|
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
|
||||||
spin_lock_irqsave(&info->lock,flags);
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
set_signals(info);
|
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 */
|
/* Handle transition away from B0 status */
|
||||||
if (!(old_termios->c_cflag & CBAUD) &&
|
if (!(old_termios->c_cflag & CBAUD) &&
|
||||||
tty->termios->c_cflag & CBAUD) {
|
tty->termios.c_cflag & CBAUD) {
|
||||||
info->serial_signals |= SerialSignal_DTR;
|
info->serial_signals |= SerialSignal_DTR;
|
||||||
if (!(tty->termios->c_cflag & CRTSCTS) ||
|
if (!(tty->termios.c_cflag & CRTSCTS) ||
|
||||||
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
||||||
info->serial_signals |= SerialSignal_RTS;
|
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 */
|
/* Handle turning off CRTSCTS */
|
||||||
if (old_termios->c_cflag & CRTSCTS &&
|
if (old_termios->c_cflag & CRTSCTS &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
tx_release(tty);
|
tx_release(tty);
|
||||||
}
|
}
|
||||||
@ -2731,6 +2731,8 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
|
|||||||
#if SYNCLINK_GENERIC_HDLC
|
#if SYNCLINK_GENERIC_HDLC
|
||||||
hdlcdev_init(info);
|
hdlcdev_init(info);
|
||||||
#endif
|
#endif
|
||||||
|
tty_port_register_device(&info->port, serial_driver, info->line,
|
||||||
|
&info->p_dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
|
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;
|
last->next_device = info->next_device;
|
||||||
else
|
else
|
||||||
mgslpc_device_list = info->next_device;
|
mgslpc_device_list = info->next_device;
|
||||||
|
tty_unregister_device(serial_driver, info->line);
|
||||||
#if SYNCLINK_GENERIC_HDLC
|
#if SYNCLINK_GENERIC_HDLC
|
||||||
hdlcdev_exit(info);
|
hdlcdev_exit(info);
|
||||||
#endif
|
#endif
|
||||||
@ -2798,77 +2801,63 @@ static const struct tty_operations mgslpc_ops = {
|
|||||||
.proc_fops = &mgslpc_proc_fops,
|
.proc_fops = &mgslpc_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void synclink_cs_cleanup(void)
|
static int __init synclink_cs_init(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
while(mgslpc_device_list)
|
if (break_on_load) {
|
||||||
mgslpc_remove_device(mgslpc_device_list);
|
mgslpc_get_text_ptr();
|
||||||
|
BREAKPOINT();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pcmcia_unregister_driver(&mgslpc_driver);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init synclink_cs_init(void)
|
/* Initialize the tty_driver structure */
|
||||||
{
|
serial_driver->driver_name = "synclink_cs";
|
||||||
int rc;
|
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);
|
||||||
|
|
||||||
if (break_on_load) {
|
rc = tty_register_driver(serial_driver);
|
||||||
mgslpc_get_text_ptr();
|
if (rc < 0) {
|
||||||
BREAKPOINT();
|
printk(KERN_ERR "%s(%d):Couldn't register serial driver\n",
|
||||||
}
|
__FILE__, __LINE__);
|
||||||
|
goto err_put_tty;
|
||||||
|
}
|
||||||
|
|
||||||
if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
|
rc = pcmcia_register_driver(&mgslpc_driver);
|
||||||
return rc;
|
if (rc < 0)
|
||||||
|
goto err_unreg_tty;
|
||||||
|
|
||||||
serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT);
|
printk(KERN_INFO "%s %s, tty major#%d\n", driver_name, driver_version,
|
||||||
if (!serial_driver) {
|
serial_driver->major);
|
||||||
rc = -ENOMEM;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the tty_driver structure */
|
return 0;
|
||||||
|
err_unreg_tty:
|
||||||
serial_driver->driver_name = "synclink_cs";
|
tty_unregister_driver(serial_driver);
|
||||||
serial_driver->name = "ttySLP";
|
err_put_tty:
|
||||||
serial_driver->major = ttymajor;
|
put_tty_driver(serial_driver);
|
||||||
serial_driver->minor_start = 64;
|
err:
|
||||||
serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
return rc;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
printk("%s %s, tty major#%d\n",
|
|
||||||
driver_name, driver_version,
|
|
||||||
serial_driver->major);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
synclink_cs_cleanup();
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit synclink_cs_exit(void)
|
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);
|
module_init(synclink_cs_init);
|
||||||
|
@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count)
|
|||||||
tmp[tpk_curr + 1] = '\0';
|
tmp[tpk_curr + 1] = '\0';
|
||||||
printk(KERN_INFO "%s%s", tpk_tag, tmp);
|
printk(KERN_INFO "%s%s", tpk_tag, tmp);
|
||||||
tpk_curr = 0;
|
tpk_curr = 0;
|
||||||
if (buf[i + 1] == '\n')
|
if ((i + 1) < count && buf[i + 1] == '\n')
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
@ -178,11 +178,17 @@ static struct tty_driver *ttyprintk_driver;
|
|||||||
static int __init ttyprintk_init(void)
|
static int __init ttyprintk_init(void)
|
||||||
{
|
{
|
||||||
int ret = -ENOMEM;
|
int ret = -ENOMEM;
|
||||||
void *rp;
|
|
||||||
|
|
||||||
ttyprintk_driver = alloc_tty_driver(1);
|
tty_port_init(&tpk_port.port);
|
||||||
if (!ttyprintk_driver)
|
tpk_port.port.ops = &null_ops;
|
||||||
return ret;
|
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->driver_name = "ttyprintk";
|
||||||
ttyprintk_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->type = TTY_DRIVER_TYPE_CONSOLE;
|
||||||
ttyprintk_driver->init_termios = tty_std_termios;
|
ttyprintk_driver->init_termios = tty_std_termios;
|
||||||
ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
|
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_set_operations(ttyprintk_driver, &ttyprintk_ops);
|
||||||
|
tty_port_link_device(&tpk_port.port, ttyprintk_driver, 0);
|
||||||
|
|
||||||
ret = tty_register_driver(ttyprintk_driver);
|
ret = tty_register_driver(ttyprintk_driver);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -201,22 +206,10 @@ static int __init ttyprintk_init(void)
|
|||||||
goto error;
|
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;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
tty_unregister_driver(ttyprintk_driver);
|
||||||
put_tty_driver(ttyprintk_driver);
|
put_tty_driver(ttyprintk_driver);
|
||||||
ttyprintk_driver = NULL;
|
ttyprintk_driver = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -234,7 +234,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
|
|||||||
|
|
||||||
mp->minor = minor;
|
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))
|
if (IS_ERR(dev))
|
||||||
goto err_out2;
|
goto err_out2;
|
||||||
|
|
||||||
|
@ -446,8 +446,8 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
iflag = tty->termios->c_iflag;
|
iflag = tty->termios.c_iflag;
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
old_cflag = old ? old->c_cflag : cflag;
|
old_cflag = old ? old->c_cflag : cflag;
|
||||||
gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
|
gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
|
||||||
cs->minor_index, iflag, cflag, old_cflag);
|
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);
|
tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs);
|
||||||
|
|
||||||
mutex_lock(&cs->mutex);
|
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))
|
if (!IS_ERR(cs->tty_dev))
|
||||||
dev_set_drvdata(cs->tty_dev, cs);
|
dev_set_drvdata(cs->tty_dev, cs);
|
||||||
|
@ -1009,15 +1009,15 @@ isdn_tty_change_speed(modem_info *info)
|
|||||||
quot;
|
quot;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!port->tty || !port->tty->termios)
|
if (!port->tty)
|
||||||
return;
|
return;
|
||||||
cflag = port->tty->termios->c_cflag;
|
cflag = port->tty->termios.c_cflag;
|
||||||
|
|
||||||
quot = i = cflag & CBAUD;
|
quot = i = cflag & CBAUD;
|
||||||
if (i & CBAUDEX) {
|
if (i & CBAUDEX) {
|
||||||
i &= ~CBAUDEX;
|
i &= ~CBAUDEX;
|
||||||
if (i < 1 || i > 2)
|
if (i < 1 || i > 2)
|
||||||
port->tty->termios->c_cflag &= ~CBAUDEX;
|
port->tty->termios.c_cflag &= ~CBAUDEX;
|
||||||
else
|
else
|
||||||
i += 15;
|
i += 15;
|
||||||
}
|
}
|
||||||
@ -1097,7 +1097,7 @@ isdn_tty_shutdown(modem_info *info)
|
|||||||
#endif
|
#endif
|
||||||
isdn_unlock_drivers();
|
isdn_unlock_drivers();
|
||||||
info->msr &= ~UART_MSR_RI;
|
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);
|
info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
|
||||||
if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
|
if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
|
||||||
isdn_tty_modem_reset_regs(info, 0);
|
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)
|
if (!old_termios)
|
||||||
isdn_tty_change_speed(info);
|
isdn_tty_change_speed(info);
|
||||||
else {
|
else {
|
||||||
if (tty->termios->c_cflag == old_termios->c_cflag &&
|
if (tty->termios.c_cflag == old_termios->c_cflag &&
|
||||||
tty->termios->c_ispeed == old_termios->c_ispeed &&
|
tty->termios.c_ispeed == old_termios->c_ispeed &&
|
||||||
tty->termios->c_ospeed == old_termios->c_ospeed)
|
tty->termios.c_ospeed == old_termios->c_ospeed)
|
||||||
return;
|
return;
|
||||||
isdn_tty_change_speed(info);
|
isdn_tty_change_speed(info);
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS))
|
!(tty->termios.c_cflag & CRTSCTS))
|
||||||
tty->hw_stopped = 0;
|
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
|
* This routine is called whenever a serial port is opened. It
|
||||||
* enables interrupts for a serial port, linking in its async structure into
|
* 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
|
static int
|
||||||
isdn_tty_open(struct tty_struct *tty, struct file *filp)
|
isdn_tty_open(struct tty_struct *tty, struct file *filp)
|
||||||
{
|
{
|
||||||
struct tty_port *port;
|
modem_info *info = tty->driver_data;
|
||||||
modem_info *info;
|
struct tty_port *port = &info->port;
|
||||||
int retval;
|
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
|
#ifdef ISDN_DEBUG_MODEM_OPEN
|
||||||
printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
|
printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
|
||||||
port->count);
|
port->count);
|
||||||
#endif
|
#endif
|
||||||
port->count++;
|
port->count++;
|
||||||
tty->driver_data = info;
|
|
||||||
port->tty = tty;
|
port->tty = tty;
|
||||||
tty->port = port;
|
|
||||||
/*
|
/*
|
||||||
* Start up serial port
|
* Start up serial port
|
||||||
*/
|
*/
|
||||||
@ -1738,6 +1744,7 @@ modem_write_profile(atemu *m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct tty_operations modem_ops = {
|
static const struct tty_operations modem_ops = {
|
||||||
|
.install = isdn_tty_install,
|
||||||
.open = isdn_tty_open,
|
.open = isdn_tty_open,
|
||||||
.close = isdn_tty_close,
|
.close = isdn_tty_close,
|
||||||
.write = isdn_tty_write,
|
.write = isdn_tty_write,
|
||||||
@ -1782,7 +1789,7 @@ isdn_tty_modem_init(void)
|
|||||||
m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
|
m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
|
||||||
m->tty_modem->init_termios = tty_std_termios;
|
m->tty_modem->init_termios = tty_std_termios;
|
||||||
m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
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";
|
m->tty_modem->driver_name = "isdn_tty";
|
||||||
tty_set_operations(m->tty_modem, &modem_ops);
|
tty_set_operations(m->tty_modem, &modem_ops);
|
||||||
retval = tty_register_driver(m->tty_modem);
|
retval = tty_register_driver(m->tty_modem);
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
void ibmasm_register_uart(struct service_processor *sp)
|
void ibmasm_register_uart(struct service_processor *sp)
|
||||||
{
|
{
|
||||||
struct uart_port uport;
|
struct uart_8250_port uart;
|
||||||
void __iomem *iomem_base;
|
void __iomem *iomem_base;
|
||||||
|
|
||||||
iomem_base = sp->base_address + SCOUT_COM_B_BASE;
|
iomem_base = sp->base_address + SCOUT_COM_B_BASE;
|
||||||
@ -47,14 +47,14 @@ void ibmasm_register_uart(struct service_processor *sp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&uport, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
uport.irq = sp->irq;
|
uart.port.irq = sp->irq;
|
||||||
uport.uartclk = 3686400;
|
uart.port.uartclk = 3686400;
|
||||||
uport.flags = UPF_SHARE_IRQ;
|
uart.port.flags = UPF_SHARE_IRQ;
|
||||||
uport.iotype = UPIO_MEM;
|
uart.port.iotype = UPIO_MEM;
|
||||||
uport.membase = iomem_base;
|
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) {
|
if (sp->serial_line < 0) {
|
||||||
dev_err(sp->dev, "Failed to register serial port\n");
|
dev_err(sp->dev, "Failed to register serial port\n");
|
||||||
return;
|
return;
|
||||||
|
@ -60,7 +60,7 @@ struct pti_tty {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pti_dev {
|
struct pti_dev {
|
||||||
struct tty_port port;
|
struct tty_port port[PTITTY_MINOR_NUM];
|
||||||
unsigned long pti_addr;
|
unsigned long pti_addr;
|
||||||
unsigned long aperture_base;
|
unsigned long aperture_base;
|
||||||
void __iomem *pti_ioaddr;
|
void __iomem *pti_ioaddr;
|
||||||
@ -76,7 +76,7 @@ struct pti_dev {
|
|||||||
*/
|
*/
|
||||||
static DEFINE_MUTEX(alloclock);
|
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)},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
@ -393,25 +393,6 @@ void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pti_writedata);
|
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.
|
* for the tty_driver_*() basic function descriptions, see tty_driver.h.
|
||||||
* Specific header comments made for PTI-related specifics.
|
* 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
|
* also removes a locking requirement for the actual write
|
||||||
* procedure.
|
* 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)
|
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,
|
static int __devinit pti_pci_probe(struct pci_dev *pdev,
|
||||||
const struct pci_device_id *ent)
|
const struct pci_device_id *ent)
|
||||||
{
|
{
|
||||||
|
unsigned int a;
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
int pci_bar = 1;
|
int pci_bar = 1;
|
||||||
|
|
||||||
@ -830,7 +812,7 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev,
|
|||||||
__func__, __LINE__);
|
__func__, __LINE__);
|
||||||
pr_err("%s(%d): Error value returned: %d\n",
|
pr_err("%s(%d): Error value returned: %d\n",
|
||||||
__func__, __LINE__, retval);
|
__func__, __LINE__, retval);
|
||||||
return retval;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = pci_enable_device(pdev);
|
retval = pci_enable_device(pdev);
|
||||||
@ -838,17 +820,16 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev,
|
|||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s: pci_enable_device() returned error %d\n",
|
"%s: pci_enable_device() returned error %d\n",
|
||||||
__func__, retval);
|
__func__, retval);
|
||||||
return retval;
|
goto err_unreg_misc;
|
||||||
}
|
}
|
||||||
|
|
||||||
drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
|
drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
|
||||||
|
|
||||||
if (drv_data == NULL) {
|
if (drv_data == NULL) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s(%d): kmalloc() returned NULL memory.\n",
|
"%s(%d): kmalloc() returned NULL memory.\n",
|
||||||
__func__, __LINE__);
|
__func__, __LINE__);
|
||||||
return retval;
|
goto err_disable_pci;
|
||||||
}
|
}
|
||||||
drv_data->pti_addr = pci_resource_start(pdev, pci_bar);
|
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,
|
dev_err(&pdev->dev,
|
||||||
"%s(%d): pci_request_region() returned error %d\n",
|
"%s(%d): pci_request_region() returned error %d\n",
|
||||||
__func__, __LINE__, retval);
|
__func__, __LINE__, retval);
|
||||||
kfree(drv_data);
|
goto err_free_dd;
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
drv_data->aperture_base = drv_data->pti_addr+APERTURE_14;
|
drv_data->aperture_base = drv_data->pti_addr+APERTURE_14;
|
||||||
drv_data->pti_ioaddr =
|
drv_data->pti_ioaddr =
|
||||||
ioremap_nocache((u32)drv_data->aperture_base,
|
ioremap_nocache((u32)drv_data->aperture_base,
|
||||||
APERTURE_LEN);
|
APERTURE_LEN);
|
||||||
if (!drv_data->pti_ioaddr) {
|
if (!drv_data->pti_ioaddr) {
|
||||||
pci_release_region(pdev, pci_bar);
|
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
kfree(drv_data);
|
goto err_rel_reg;
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_set_drvdata(pdev, drv_data);
|
pci_set_drvdata(pdev, drv_data);
|
||||||
|
|
||||||
tty_port_init(&drv_data->port);
|
for (a = 0; a < PTITTY_MINOR_NUM; a++) {
|
||||||
drv_data->port.ops = &tty_port_ops;
|
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_port_register_device(port, pti_tty_driver, a, &pdev->dev);
|
||||||
tty_register_device(pti_tty_driver, 1, &pdev->dev);
|
}
|
||||||
|
|
||||||
register_console(&pti_console);
|
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;
|
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 = {
|
static struct pci_driver pti_pci_driver = {
|
||||||
.name = PCINAME,
|
.name = PCINAME,
|
||||||
.id_table = pci_ids,
|
.id_table = pci_ids,
|
||||||
@ -933,25 +946,24 @@ static int __init pti_init(void)
|
|||||||
pr_err("%s(%d): Error value returned: %d\n",
|
pr_err("%s(%d): Error value returned: %d\n",
|
||||||
__func__, __LINE__, retval);
|
__func__, __LINE__, retval);
|
||||||
|
|
||||||
pti_tty_driver = NULL;
|
goto put_tty;
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = pci_register_driver(&pti_pci_driver);
|
retval = pci_register_driver(&pti_pci_driver);
|
||||||
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
pr_err("%s(%d): PCI registration failed of pti driver\n",
|
pr_err("%s(%d): PCI registration failed of pti driver\n",
|
||||||
__func__, __LINE__);
|
__func__, __LINE__);
|
||||||
pr_err("%s(%d): Error value returned: %d\n",
|
pr_err("%s(%d): Error value returned: %d\n",
|
||||||
__func__, __LINE__, retval);
|
__func__, __LINE__, retval);
|
||||||
|
goto unreg_tty;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
unreg_tty:
|
||||||
|
tty_unregister_driver(pti_tty_driver);
|
||||||
|
put_tty:
|
||||||
|
put_tty_driver(pti_tty_driver);
|
||||||
|
pti_tty_driver = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,31 +972,9 @@ static int __init pti_init(void)
|
|||||||
*/
|
*/
|
||||||
static void __exit pti_exit(void)
|
static void __exit pti_exit(void)
|
||||||
{
|
{
|
||||||
int retval;
|
tty_unregister_driver(pti_tty_driver);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_unregister_driver(&pti_pci_driver);
|
pci_unregister_driver(&pti_pci_driver);
|
||||||
|
put_tty_driver(pti_tty_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(pti_init);
|
module_init(pti_init);
|
||||||
|
@ -518,7 +518,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
|
|||||||
if (status & UART_MSR_DCTS) {
|
if (status & UART_MSR_DCTS) {
|
||||||
port->icount.cts++;
|
port->icount.cts++;
|
||||||
tty = tty_port_tty_get(&port->port);
|
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);
|
int cts = (status & UART_MSR_CTS);
|
||||||
if (tty->hw_stopped) {
|
if (tty->hw_stopped) {
|
||||||
if (cts) {
|
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->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;
|
||||||
port->mctrl = TIOCM_OUT2;
|
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);
|
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))
|
if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
|
||||||
tty->hw_stopped = 1;
|
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;
|
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;
|
return;
|
||||||
|
|
||||||
if (sdio_uart_claim_func(port) != 0)
|
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);
|
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_clear_mctrl(port, TIOCM_RTS);
|
||||||
|
|
||||||
sdio_uart_irq(port->func);
|
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;
|
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;
|
return;
|
||||||
|
|
||||||
if (sdio_uart_claim_func(port) != 0)
|
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_set_mctrl(port, TIOCM_RTS);
|
||||||
|
|
||||||
sdio_uart_irq(port->func);
|
sdio_uart_irq(port->func);
|
||||||
@ -898,12 +898,12 @@ static void sdio_uart_set_termios(struct tty_struct *tty,
|
|||||||
struct ktermios *old_termios)
|
struct ktermios *old_termios)
|
||||||
{
|
{
|
||||||
struct sdio_uart_port *port = tty->driver_data;
|
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)
|
if (sdio_uart_claim_func(port) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sdio_uart_change_speed(port, tty->termios, old_termios);
|
sdio_uart_change_speed(port, &tty->termios, old_termios);
|
||||||
|
|
||||||
/* Handle transition to B0 status */
|
/* Handle transition to B0 status */
|
||||||
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
|
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
|
||||||
@ -1132,8 +1132,8 @@ static int sdio_uart_probe(struct sdio_func *func,
|
|||||||
kfree(port);
|
kfree(port);
|
||||||
} else {
|
} else {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
dev = tty_register_device(sdio_uart_tty_driver,
|
dev = tty_port_register_device(&port->port,
|
||||||
port->index, &func->dev);
|
sdio_uart_tty_driver, port->index, &func->dev);
|
||||||
if (IS_ERR(dev)) {
|
if (IS_ERR(dev)) {
|
||||||
sdio_uart_port_remove(port);
|
sdio_uart_port_remove(port);
|
||||||
ret = PTR_ERR(dev);
|
ret = PTR_ERR(dev);
|
||||||
|
@ -1147,15 +1147,17 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
|
|||||||
{
|
{
|
||||||
#define COSMISC_CONSTANT 6
|
#define COSMISC_CONSTANT 6
|
||||||
|
|
||||||
struct uart_port port = {
|
struct uart_8250_port port = {
|
||||||
.irq = 0,
|
.port = {
|
||||||
.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
|
.irq = 0,
|
||||||
.iotype = UPIO_MEM,
|
.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
|
||||||
.regshift = 0,
|
.iotype = UPIO_MEM,
|
||||||
.uartclk = (22000000 << 1) / COSMISC_CONSTANT,
|
.regshift = 0,
|
||||||
|
.uartclk = (22000000 << 1) / COSMISC_CONSTANT,
|
||||||
|
|
||||||
.membase = (unsigned char __iomem *) uart,
|
.membase = (unsigned char __iomem *) uart,
|
||||||
.mapbase = (unsigned long) uart,
|
.mapbase = (unsigned long) uart,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
unsigned char lcr;
|
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_scr = COSMISC_CONSTANT,
|
||||||
uart->iu_lcr = lcr;
|
uart->iu_lcr = lcr;
|
||||||
uart->iu_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)
|
static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
|
||||||
|
@ -124,8 +124,8 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
|
|||||||
tty = priv->tty;
|
tty = priv->tty;
|
||||||
|
|
||||||
mutex_lock(&tty->termios_mutex);
|
mutex_lock(&tty->termios_mutex);
|
||||||
old_termios = *(tty->termios);
|
old_termios = tty->termios;
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
tty_encode_baud_rate(tty, speed, speed);
|
tty_encode_baud_rate(tty, speed, speed);
|
||||||
if (tty->ops->set_termios)
|
if (tty->ops->set_termios)
|
||||||
tty->ops->set_termios(tty, &old_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;
|
int cflag;
|
||||||
|
|
||||||
mutex_lock(&tty->termios_mutex);
|
mutex_lock(&tty->termios_mutex);
|
||||||
old_termios = *(tty->termios);
|
old_termios = tty->termios;
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
if (stop)
|
if (stop)
|
||||||
cflag &= ~CREAD;
|
cflag &= ~CREAD;
|
||||||
else
|
else
|
||||||
cflag |= CREAD;
|
cflag |= CREAD;
|
||||||
|
|
||||||
tty->termios->c_cflag = cflag;
|
tty->termios.c_cflag = cflag;
|
||||||
if (tty->ops->set_termios)
|
if (tty->ops->set_termios)
|
||||||
tty->ops->set_termios(tty, &old_termios);
|
tty->ops->set_termios(tty, &old_termios);
|
||||||
mutex_unlock(&tty->termios_mutex);
|
mutex_unlock(&tty->termios_mutex);
|
||||||
|
@ -1107,7 +1107,6 @@ static void _hso_serial_set_termios(struct tty_struct *tty,
|
|||||||
struct ktermios *old)
|
struct ktermios *old)
|
||||||
{
|
{
|
||||||
struct hso_serial *serial = tty->driver_data;
|
struct hso_serial *serial = tty->driver_data;
|
||||||
struct ktermios *termios;
|
|
||||||
|
|
||||||
if (!serial) {
|
if (!serial) {
|
||||||
printk(KERN_ERR "%s: no tty structures", __func__);
|
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
|
* Fix up unsupported bits
|
||||||
*/
|
*/
|
||||||
termios = tty->termios;
|
tty->termios.c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
|
||||||
termios->c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
|
|
||||||
|
|
||||||
termios->c_cflag &=
|
tty->termios.c_cflag &=
|
||||||
~(CSIZE /* no size */
|
~(CSIZE /* no size */
|
||||||
| PARENB /* disable parity bit */
|
| PARENB /* disable parity bit */
|
||||||
| CBAUD /* clear current baud rate */
|
| CBAUD /* clear current baud rate */
|
||||||
| CBAUDEX); /* clear current buad 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 */
|
/* baud rate 115200 */
|
||||||
tty_encode_baud_rate(tty, 115200, 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)
|
if (old)
|
||||||
D5("Termios called with: cflags new[%d] - old[%d]",
|
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 */
|
/* the actual setup */
|
||||||
spin_lock_irqsave(&serial->serial_lock, flags);
|
spin_lock_irqsave(&serial->serial_lock, flags);
|
||||||
if (serial->port.count)
|
if (serial->port.count)
|
||||||
_hso_serial_set_termios(tty, old);
|
_hso_serial_set_termios(tty, old);
|
||||||
else
|
else
|
||||||
tty->termios = old;
|
tty->termios = *old;
|
||||||
spin_unlock_irqrestore(&serial->serial_lock, flags);
|
spin_unlock_irqrestore(&serial->serial_lock, flags);
|
||||||
|
|
||||||
/* done */
|
/* done */
|
||||||
@ -2289,9 +2287,11 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
|
|||||||
if (minor < 0)
|
if (minor < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
tty_port_init(&serial->port);
|
||||||
|
|
||||||
/* register our minor number */
|
/* register our minor number */
|
||||||
serial->parent->dev = tty_register_device(tty_drv, minor,
|
serial->parent->dev = tty_port_register_device(&serial->port, tty_drv,
|
||||||
&serial->parent->interface->dev);
|
minor, &serial->parent->interface->dev);
|
||||||
dev = serial->parent->dev;
|
dev = serial->parent->dev;
|
||||||
dev_set_drvdata(dev, serial->parent);
|
dev_set_drvdata(dev, serial->parent);
|
||||||
i = device_create_file(dev, &dev_attr_hsotype);
|
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->minor = minor;
|
||||||
serial->magic = HSO_SERIAL_MAGIC;
|
serial->magic = HSO_SERIAL_MAGIC;
|
||||||
spin_lock_init(&serial->serial_lock);
|
spin_lock_init(&serial->serial_lock);
|
||||||
tty_port_init(&serial->port);
|
|
||||||
serial->num_rx_urbs = num_urbs;
|
serial->num_rx_urbs = num_urbs;
|
||||||
|
|
||||||
/* RX, allocate urb and initialize */
|
/* RX, allocate urb and initialize */
|
||||||
|
@ -271,6 +271,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
|
|||||||
if (!parport_SPP_supported (p)) {
|
if (!parport_SPP_supported (p)) {
|
||||||
/* No port. */
|
/* No port. */
|
||||||
kfree (priv);
|
kfree (priv);
|
||||||
|
kfree(ops);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
parport_PS2_supported (p);
|
parport_PS2_supported (p);
|
||||||
|
@ -62,6 +62,7 @@ enum parport_pc_pci_cards {
|
|||||||
timedia_9079a,
|
timedia_9079a,
|
||||||
timedia_9079b,
|
timedia_9079b,
|
||||||
timedia_9079c,
|
timedia_9079c,
|
||||||
|
wch_ch353_2s1p,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* each element directly indexed from enum list, above */
|
/* 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_9079a */ { 1, { { 2, 3 }, } },
|
||||||
/* timedia_9079b */ { 1, { { 2, 3 }, } },
|
/* timedia_9079b */ { 1, { { 2, 3 }, } },
|
||||||
/* timedia_9079c */ { 1, { { 2, 3 }, } },
|
/* timedia_9079c */ { 1, { { 2, 3 }, } },
|
||||||
|
/* wch_ch353_2s1p*/ { 1, { { 2, -1}, } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pci_device_id parport_serial_pci_tbl[] = {
|
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, 0xb079, 0, 0, timedia_9079a },
|
||||||
{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
|
{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
|
||||||
{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
|
{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
|
||||||
|
/* WCH CARDS */
|
||||||
|
{ 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p},
|
||||||
{ 0, } /* terminate list */
|
{ 0, } /* terminate list */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
|
MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
|
||||||
@ -460,6 +463,12 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
|
|||||||
.base_baud = 921600,
|
.base_baud = 921600,
|
||||||
.uart_offset = 8,
|
.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 {
|
struct parport_serial_private {
|
||||||
|
@ -716,10 +716,17 @@ static int raw3215_probe (struct ccw_device *cdev)
|
|||||||
static void raw3215_remove (struct ccw_device *cdev)
|
static void raw3215_remove (struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
struct raw3215_info *raw;
|
struct raw3215_info *raw;
|
||||||
|
unsigned int line;
|
||||||
|
|
||||||
ccw_device_set_offline(cdev);
|
ccw_device_set_offline(cdev);
|
||||||
raw = dev_get_drvdata(&cdev->dev);
|
raw = dev_get_drvdata(&cdev->dev);
|
||||||
if (raw) {
|
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);
|
dev_set_drvdata(&cdev->dev, NULL);
|
||||||
raw3215_free_info(raw);
|
raw3215_free_info(raw);
|
||||||
}
|
}
|
||||||
@ -935,6 +942,19 @@ static int __init con3215_init(void)
|
|||||||
console_initcall(con3215_init);
|
console_initcall(con3215_init);
|
||||||
#endif
|
#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
|
* tty3215_open
|
||||||
*
|
*
|
||||||
@ -942,14 +962,9 @@ console_initcall(con3215_init);
|
|||||||
*/
|
*/
|
||||||
static int tty3215_open(struct tty_struct *tty, struct file * filp)
|
static int tty3215_open(struct tty_struct *tty, struct file * filp)
|
||||||
{
|
{
|
||||||
struct raw3215_info *raw;
|
struct raw3215_info *raw = tty->driver_data;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
raw = raw3215[tty->index];
|
|
||||||
if (raw == NULL)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
tty->driver_data = raw;
|
|
||||||
tty_port_tty_set(&raw->port, tty);
|
tty_port_tty_set(&raw->port, tty);
|
||||||
|
|
||||||
tty->low_latency = 0; /* don't use bottom half for pushing chars */
|
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 = {
|
static const struct tty_operations tty3215_ops = {
|
||||||
|
.install = tty3215_install,
|
||||||
.open = tty3215_open,
|
.open = tty3215_open,
|
||||||
.close = tty3215_close,
|
.close = tty3215_close,
|
||||||
.write = tty3215_write,
|
.write = tty3215_write,
|
||||||
|
@ -567,6 +567,7 @@ sclp_tty_init(void)
|
|||||||
driver->init_termios.c_lflag = ISIG | ECHO;
|
driver->init_termios.c_lflag = ISIG | ECHO;
|
||||||
driver->flags = TTY_DRIVER_REAL_RAW;
|
driver->flags = TTY_DRIVER_REAL_RAW;
|
||||||
tty_set_operations(driver, &sclp_ops);
|
tty_set_operations(driver, &sclp_ops);
|
||||||
|
tty_port_link_device(&sclp_port, driver, 0);
|
||||||
rc = tty_register_driver(driver);
|
rc = tty_register_driver(driver);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
put_tty_driver(driver);
|
put_tty_driver(driver);
|
||||||
|
@ -691,6 +691,7 @@ static int __init sclp_vt220_tty_init(void)
|
|||||||
driver->init_termios = tty_std_termios;
|
driver->init_termios = tty_std_termios;
|
||||||
driver->flags = TTY_DRIVER_REAL_RAW;
|
driver->flags = TTY_DRIVER_REAL_RAW;
|
||||||
tty_set_operations(driver, &sclp_vt220_ops);
|
tty_set_operations(driver, &sclp_vt220_ops);
|
||||||
|
tty_port_link_device(&sclp_vt220_port, driver, 0);
|
||||||
|
|
||||||
rc = tty_register_driver(driver);
|
rc = tty_register_driver(driver);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -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
|
static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||||
tty3270_open(struct tty_struct *tty, struct file * filp)
|
|
||||||
{
|
{
|
||||||
struct raw3270_view *view;
|
struct raw3270_view *view;
|
||||||
struct tty3270 *tp;
|
struct tty3270 *tp;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
if (tty->count > 1)
|
|
||||||
return 0;
|
|
||||||
/* Check if the tty3270 is already there. */
|
/* Check if the tty3270 is already there. */
|
||||||
view = raw3270_find_view(&tty3270_fn,
|
view = raw3270_find_view(&tty3270_fn,
|
||||||
tty->index + RAW3270_FIRSTMINOR);
|
tty->index + RAW3270_FIRSTMINOR);
|
||||||
@ -865,7 +862,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
|
|||||||
/* why to reassign? */
|
/* why to reassign? */
|
||||||
tty_port_tty_set(&tp->port, tty);
|
tty_port_tty_set(&tp->port, tty);
|
||||||
tp->inattr = TF_INPUT;
|
tp->inattr = TF_INPUT;
|
||||||
return 0;
|
return tty_port_install(&tp->port, driver, tty);
|
||||||
}
|
}
|
||||||
if (tty3270_max_index < tty->index + 1)
|
if (tty3270_max_index < tty->index + 1)
|
||||||
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_port_tty_set(&tp->port, tty);
|
||||||
tty->low_latency = 0;
|
tty->low_latency = 0;
|
||||||
tty->driver_data = tp;
|
|
||||||
tty->winsize.ws_row = tp->view.rows - 2;
|
tty->winsize.ws_row = tp->view.rows - 2;
|
||||||
tty->winsize.ws_col = tp->view.cols;
|
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);
|
kbd_ascebc(tp->kbd, tp->view.ascebc);
|
||||||
|
|
||||||
raw3270_activate_view(&tp->view);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -932,10 +937,17 @@ tty3270_close(struct tty_struct *tty, struct file * filp)
|
|||||||
if (tp) {
|
if (tp) {
|
||||||
tty->driver_data = NULL;
|
tty->driver_data = NULL;
|
||||||
tty_port_tty_set(&tp->port, 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.
|
* We always have room.
|
||||||
*/
|
*/
|
||||||
@ -1737,7 +1749,8 @@ static long tty3270_compat_ioctl(struct tty_struct *tty,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct tty_operations tty3270_ops = {
|
static const struct tty_operations tty3270_ops = {
|
||||||
.open = tty3270_open,
|
.install = tty3270_install,
|
||||||
|
.cleanup = tty3270_cleanup,
|
||||||
.close = tty3270_close,
|
.close = tty3270_close,
|
||||||
.write = tty3270_write,
|
.write = tty3270_write,
|
||||||
.put_char = tty3270_put_char,
|
.put_char = tty3270_put_char,
|
||||||
@ -1781,7 +1794,7 @@ static int __init tty3270_init(void)
|
|||||||
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||||
driver->subtype = SYSTEM_TYPE_TTY;
|
driver->subtype = SYSTEM_TYPE_TTY;
|
||||||
driver->init_termios = tty_std_termios;
|
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);
|
tty_set_operations(driver, &tty3270_ops);
|
||||||
ret = tty_register_driver(driver);
|
ret = tty_register_driver(driver);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -1800,6 +1813,7 @@ tty3270_exit(void)
|
|||||||
driver = tty3270_driver;
|
driver = tty3270_driver;
|
||||||
tty3270_driver = NULL;
|
tty3270_driver = NULL;
|
||||||
tty_unregister_driver(driver);
|
tty_unregister_driver(driver);
|
||||||
|
put_tty_driver(driver);
|
||||||
tty3270_del_views();
|
tty3270_del_views();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +502,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|||||||
ipoctal->pointer_read[i] = 0;
|
ipoctal->pointer_read[i] = 0;
|
||||||
ipoctal->pointer_write[i] = 0;
|
ipoctal->pointer_write[i] = 0;
|
||||||
ipoctal->nb_bytes[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
|
* 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;
|
struct ipoctal *ipoctal = tty->driver_data;
|
||||||
speed_t baud;
|
speed_t baud;
|
||||||
|
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
/* Disable and reset everything before change the setup */
|
/* Disable and reset everything before change the setup */
|
||||||
ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
|
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:
|
default:
|
||||||
mr1 |= MR1_CHRL_8_BITS;
|
mr1 |= MR1_CHRL_8_BITS;
|
||||||
/* By default, select CS8 */
|
/* By default, select CS8 */
|
||||||
tty->termios->c_cflag = (cflag & ~CSIZE) | CS8;
|
tty->termios.c_cflag = (cflag & ~CSIZE) | CS8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,7 +657,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
|
|||||||
mr1 |= MR1_PARITY_OFF;
|
mr1 |= MR1_PARITY_OFF;
|
||||||
|
|
||||||
/* Mark or space parity is not supported */
|
/* Mark or space parity is not supported */
|
||||||
tty->termios->c_cflag &= ~CMSPAR;
|
tty->termios.c_cflag &= ~CMSPAR;
|
||||||
|
|
||||||
/* Set stop bits */
|
/* Set stop bits */
|
||||||
if (cflag & CSTOPB)
|
if (cflag & CSTOPB)
|
||||||
@ -690,10 +690,10 @@ static void ipoctal_set_termios(struct tty_struct *tty,
|
|||||||
}
|
}
|
||||||
|
|
||||||
baud = tty_get_baud_rate(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 */
|
/* Set baud rate */
|
||||||
switch (tty->termios->c_ospeed) {
|
switch (baud) {
|
||||||
case 75:
|
case 75:
|
||||||
csr |= TX_CLK_75 | RX_CLK_75;
|
csr |= TX_CLK_75 | RX_CLK_75;
|
||||||
break;
|
break;
|
||||||
@ -734,7 +734,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
|
|||||||
default:
|
default:
|
||||||
csr |= TX_CLK_38400 | RX_CLK_38400;
|
csr |= TX_CLK_38400 | RX_CLK_38400;
|
||||||
/* In case of default, we establish 38400 bps */
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,10 +315,8 @@ static void qt_read_bulk_callback(struct urb *urb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tty = tty_port_tty_get(&port->port);
|
tty = tty_port_tty_get(&port->port);
|
||||||
if (!tty) {
|
if (!tty)
|
||||||
dbg("%s - bad tty pointer - exiting", __func__);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
data = urb->transfer_buffer;
|
data = urb->transfer_buffer;
|
||||||
|
|
||||||
@ -364,7 +362,7 @@ static void qt_read_bulk_callback(struct urb *urb)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty && RxCount) {
|
if (RxCount) {
|
||||||
flag_data = 0;
|
flag_data = 0;
|
||||||
for (i = 0; i < RxCount; ++i) {
|
for (i = 0; i < RxCount; ++i) {
|
||||||
/* Look ahead code here */
|
/* 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",
|
dbg("%s - failed resubmitting read urb, error %d",
|
||||||
__func__, result);
|
__func__, result);
|
||||||
else {
|
else {
|
||||||
if (tty && RxCount) {
|
if (RxCount) {
|
||||||
tty_flip_buffer_push(tty);
|
tty_flip_buffer_push(tty);
|
||||||
tty_schedule_flip(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
|
* Put this here to make it responsive to stty and defaults set by
|
||||||
* the tty layer
|
* 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 */
|
/* Check to see if we've set up our endpoint info yet */
|
||||||
if (port0->open_ports == 1) {
|
if (port0->open_ports == 1) {
|
||||||
@ -1195,7 +1191,7 @@ static void qt_set_termios(struct tty_struct *tty,
|
|||||||
struct usb_serial_port *port,
|
struct usb_serial_port *port,
|
||||||
struct ktermios *old_termios)
|
struct ktermios *old_termios)
|
||||||
{
|
{
|
||||||
struct ktermios *termios = tty->termios;
|
struct ktermios *termios = &tty->termios;
|
||||||
unsigned char new_LCR = 0;
|
unsigned char new_LCR = 0;
|
||||||
unsigned int cflag = termios->c_cflag;
|
unsigned int cflag = termios->c_cflag;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
@ -1204,7 +1200,7 @@ static void qt_set_termios(struct tty_struct *tty,
|
|||||||
|
|
||||||
index = tty->index - port->serial->minor;
|
index = tty->index - port->serial->minor;
|
||||||
|
|
||||||
switch (cflag) {
|
switch (cflag & CSIZE) {
|
||||||
case CS5:
|
case CS5:
|
||||||
new_LCR |= SERIAL_5_DATA;
|
new_LCR |= SERIAL_5_DATA;
|
||||||
break;
|
break;
|
||||||
@ -1215,6 +1211,8 @@ static void qt_set_termios(struct tty_struct *tty,
|
|||||||
new_LCR |= SERIAL_7_DATA;
|
new_LCR |= SERIAL_7_DATA;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= CS8;
|
||||||
case CS8:
|
case CS8:
|
||||||
new_LCR |= SERIAL_8_DATA;
|
new_LCR |= SERIAL_8_DATA;
|
||||||
break;
|
break;
|
||||||
@ -1301,7 +1299,7 @@ static void qt_set_termios(struct tty_struct *tty,
|
|||||||
dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n");
|
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 */
|
/* FIXME: Error cases should be returning the actual bits changed only */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#ifndef _SPEAKUP_SERIAL_H
|
#ifndef _SPEAKUP_SERIAL_H
|
||||||
#define _SPEAKUP_SERIAL_H
|
#define _SPEAKUP_SERIAL_H
|
||||||
|
|
||||||
#include <linux/serial.h> /* for rs_table, serial constants &
|
#include <linux/serial.h> /* for rs_table, serial constants */
|
||||||
serial_uart_config */
|
|
||||||
#include <linux/serial_reg.h> /* for more serial constants */
|
#include <linux/serial_reg.h> /* for more serial constants */
|
||||||
#ifndef __sparc__
|
#ifndef __sparc__
|
||||||
#include <asm/serial.h>
|
#include <asm/serial.h>
|
||||||
|
@ -420,7 +420,7 @@ static void check_modem_status(struct serial_state *info)
|
|||||||
tty_hangup(port->tty);
|
tty_hangup(port->tty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (port->flags & ASYNC_CTS_FLOW) {
|
if (tty_port_cts_enabled(port)) {
|
||||||
if (port->tty->hw_stopped) {
|
if (port->tty->hw_stopped) {
|
||||||
if (!(status & SER_CTS)) {
|
if (!(status & SER_CTS)) {
|
||||||
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
|
#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;
|
custom.adkcon = AC_UARTBRK;
|
||||||
mb();
|
mb();
|
||||||
|
|
||||||
if (tty->termios->c_cflag & HUPCL)
|
if (tty->termios.c_cflag & HUPCL)
|
||||||
info->MCR &= ~(SER_DTR|SER_RTS);
|
info->MCR &= ~(SER_DTR|SER_RTS);
|
||||||
rtsdtr_ctrl(info->MCR);
|
rtsdtr_ctrl(info->MCR);
|
||||||
|
|
||||||
@ -670,7 +670,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
|
|||||||
int bits;
|
int bits;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
/* Byte size is always 8 bits plus parity bit if requested */
|
/* 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 the quotient is zero refuse the change */
|
||||||
if (!quot && old_termios) {
|
if (!quot && old_termios) {
|
||||||
/* FIXME: Will need updating for new tty in the end */
|
/* FIXME: Will need updating for new tty in the end */
|
||||||
tty->termios->c_cflag &= ~CBAUD;
|
tty->termios.c_cflag &= ~CBAUD;
|
||||||
tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
|
tty->termios.c_cflag |= (old_termios->c_cflag & CBAUD);
|
||||||
baud = tty_get_baud_rate(tty);
|
baud = tty_get_baud_rate(tty);
|
||||||
if (!baud)
|
if (!baud)
|
||||||
baud = 9600;
|
baud = 9600;
|
||||||
@ -984,7 +984,7 @@ static void rs_throttle(struct tty_struct * tty)
|
|||||||
if (I_IXOFF(tty))
|
if (I_IXOFF(tty))
|
||||||
rs_send_xchar(tty, STOP_CHAR(tty));
|
rs_send_xchar(tty, STOP_CHAR(tty));
|
||||||
|
|
||||||
if (tty->termios->c_cflag & CRTSCTS)
|
if (tty->termios.c_cflag & CRTSCTS)
|
||||||
info->MCR &= ~SER_RTS;
|
info->MCR &= ~SER_RTS;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
@ -1012,7 +1012,7 @@ static void rs_unthrottle(struct tty_struct * tty)
|
|||||||
else
|
else
|
||||||
rs_send_xchar(tty, START_CHAR(tty));
|
rs_send_xchar(tty, START_CHAR(tty));
|
||||||
}
|
}
|
||||||
if (tty->termios->c_cflag & CRTSCTS)
|
if (tty->termios.c_cflag & CRTSCTS)
|
||||||
info->MCR |= SER_RTS;
|
info->MCR |= SER_RTS;
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
rtsdtr_ctrl(info->MCR);
|
rtsdtr_ctrl(info->MCR);
|
||||||
@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
|
|||||||
if (!retinfo)
|
if (!retinfo)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
memset(&tmp, 0, sizeof(tmp));
|
memset(&tmp, 0, sizeof(tmp));
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
tmp.line = tty->index;
|
tmp.line = tty->index;
|
||||||
tmp.port = state->port;
|
tmp.port = state->port;
|
||||||
tmp.flags = state->tport.flags;
|
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.close_delay = state->tport.close_delay;
|
||||||
tmp.closing_wait = state->tport.closing_wait;
|
tmp.closing_wait = state->tport.closing_wait;
|
||||||
tmp.custom_divisor = state->custom_divisor;
|
tmp.custom_divisor = state->custom_divisor;
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
|
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return 0;
|
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)))
|
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
|
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
|
||||||
new_serial.custom_divisor != state->custom_divisor;
|
new_serial.custom_divisor != state->custom_divisor;
|
||||||
if (new_serial.irq || new_serial.port != state->port ||
|
if (new_serial.irq || new_serial.port != state->port ||
|
||||||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
|
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return -EINVAL;
|
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.xmit_fifo_size != state->xmit_fifo_size) ||
|
||||||
((new_serial.flags & ~ASYNC_USR_MASK) !=
|
((new_serial.flags & ~ASYNC_USR_MASK) !=
|
||||||
(port->flags & ~ASYNC_USR_MASK))) {
|
(port->flags & ~ASYNC_USR_MASK))) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
|
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) {
|
if (new_serial.baud_base < 9600) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,7 +1116,7 @@ check_and_exit:
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
retval = startup(tty, state);
|
retval = startup(tty, state);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return retval;
|
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;
|
struct serial_state *info = tty->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int cflag = tty->termios->c_cflag;
|
unsigned int cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
change_speed(tty, info, old_termios);
|
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) &&
|
if (!(old_termios->c_cflag & CBAUD) &&
|
||||||
(cflag & CBAUD)) {
|
(cflag & CBAUD)) {
|
||||||
info->MCR |= SER_DTR;
|
info->MCR |= SER_DTR;
|
||||||
if (!(tty->termios->c_cflag & CRTSCTS) ||
|
if (!(tty->termios.c_cflag & CRTSCTS) ||
|
||||||
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
||||||
info->MCR |= SER_RTS;
|
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 */
|
/* Handle turning off CRTSCTS */
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
rs_start(tty);
|
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.....
|
* or not. Hence, this may change.....
|
||||||
*/
|
*/
|
||||||
if (!(old_termios->c_cflag & CLOCAL) &&
|
if (!(old_termios->c_cflag & CLOCAL) &&
|
||||||
(tty->termios->c_cflag & CLOCAL))
|
(tty->termios.c_cflag & CLOCAL))
|
||||||
wake_up_interruptible(&info->open_wait);
|
wake_up_interruptible(&info->open_wait);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1710,10 +1710,6 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
|
|||||||
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||||
tty_set_operations(serial_driver, &serial_ops);
|
tty_set_operations(serial_driver, &serial_ops);
|
||||||
|
|
||||||
error = tty_register_driver(serial_driver);
|
|
||||||
if (error)
|
|
||||||
goto fail_put_tty_driver;
|
|
||||||
|
|
||||||
state = rs_table;
|
state = rs_table;
|
||||||
state->port = (int)&custom.serdatr; /* Just to give it a value */
|
state->port = (int)&custom.serdatr; /* Just to give it a value */
|
||||||
state->custom_divisor = 0;
|
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;
|
state->icount.overrun = state->icount.brk = 0;
|
||||||
tty_port_init(&state->tport);
|
tty_port_init(&state->tport);
|
||||||
state->tport.ops = &amiga_port_ops;
|
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");
|
printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n");
|
||||||
|
|
||||||
|
@ -263,6 +263,7 @@ static int __init bfin_jc_init(void)
|
|||||||
bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL;
|
bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||||
bfin_jc_driver->init_termios = tty_std_termios;
|
bfin_jc_driver->init_termios = tty_std_termios;
|
||||||
tty_set_operations(bfin_jc_driver, &bfin_jc_ops);
|
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);
|
ret = tty_register_driver(bfin_jc_driver);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -727,7 +727,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
|
|||||||
else
|
else
|
||||||
tty_hangup(tty);
|
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 (tty->hw_stopped) {
|
||||||
if (mdm_status & CyCTS) {
|
if (mdm_status & CyCTS) {
|
||||||
/* cy_start isn't used
|
/* 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;
|
info->port.xmit_buf = NULL;
|
||||||
free_page((unsigned long)temp);
|
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_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
|
||||||
|
|
||||||
cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
|
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);
|
free_page((unsigned long)temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->termios->c_cflag & HUPCL)
|
if (tty->termios.c_cflag & HUPCL)
|
||||||
tty_port_lower_dtr_rts(&info->port);
|
tty_port_lower_dtr_rts(&info->port);
|
||||||
|
|
||||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
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 the port is the middle of closing, bail out now
|
||||||
*/
|
*/
|
||||||
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
|
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));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
|
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 baud, baud_rate = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!tty->termios) /* XXX can this happen at all? */
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (info->line == -1)
|
if (info->line == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
iflag = tty->termios->c_iflag;
|
iflag = tty->termios.c_iflag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the tty->alt_speed kludge
|
* 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);
|
cy_set_line_char(info, tty);
|
||||||
|
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
cy_start(tty);
|
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.....
|
* or not. Hence, this may change.....
|
||||||
*/
|
*/
|
||||||
if (!(old_termios->c_cflag & CLOCAL) &&
|
if (!(old_termios->c_cflag & CLOCAL) &&
|
||||||
(tty->termios->c_cflag & CLOCAL))
|
(tty->termios.c_cflag & CLOCAL))
|
||||||
wake_up_interruptible(&info->port.open_wait);
|
wake_up_interruptible(&info->port.open_wait);
|
||||||
#endif
|
#endif
|
||||||
} /* cy_set_termios */
|
} /* cy_set_termios */
|
||||||
@ -2899,7 +2896,7 @@ static void cy_throttle(struct tty_struct *tty)
|
|||||||
info->throttle = 1;
|
info->throttle = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->termios->c_cflag & CRTSCTS) {
|
if (tty->termios.c_cflag & CRTSCTS) {
|
||||||
if (!cy_is_Z(card)) {
|
if (!cy_is_Z(card)) {
|
||||||
spin_lock_irqsave(&card->card_lock, flags);
|
spin_lock_irqsave(&card->card_lock, flags);
|
||||||
cyy_change_rts_dtr(info, 0, TIOCM_RTS);
|
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));
|
cy_send_xchar(tty, START_CHAR(tty));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->termios->c_cflag & CRTSCTS) {
|
if (tty->termios.c_cflag & CRTSCTS) {
|
||||||
card = info->card;
|
card = info->card;
|
||||||
if (!cy_is_Z(card)) {
|
if (!cy_is_Z(card)) {
|
||||||
spin_lock_irqsave(&card->card_lock, flags);
|
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)
|
static int __init cy_detect_isa(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ISA
|
#ifdef CONFIG_ISA
|
||||||
|
struct cyclades_card *card;
|
||||||
unsigned short cy_isa_irq, nboard;
|
unsigned short cy_isa_irq, nboard;
|
||||||
void __iomem *cy_isa_address;
|
void __iomem *cy_isa_address;
|
||||||
unsigned short i, j, cy_isa_nchan;
|
unsigned short i, j, k, cy_isa_nchan;
|
||||||
int isparam = 0;
|
int isparam = 0;
|
||||||
|
|
||||||
nboard = 0;
|
nboard = 0;
|
||||||
@ -3349,7 +3347,8 @@ static int __init cy_detect_isa(void)
|
|||||||
}
|
}
|
||||||
/* fill the next cy_card structure available */
|
/* fill the next cy_card structure available */
|
||||||
for (j = 0; j < NR_CARDS; j++) {
|
for (j = 0; j < NR_CARDS; j++) {
|
||||||
if (cy_card[j].base_addr == NULL)
|
card = &cy_card[j];
|
||||||
|
if (card->base_addr == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (j == NR_CARDS) { /* no more cy_cards available */
|
if (j == NR_CARDS) { /* no more cy_cards available */
|
||||||
@ -3363,7 +3362,7 @@ static int __init cy_detect_isa(void)
|
|||||||
|
|
||||||
/* allocate IRQ */
|
/* allocate IRQ */
|
||||||
if (request_irq(cy_isa_irq, cyy_interrupt,
|
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 "
|
printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
|
||||||
"could not allocate IRQ#%d.\n",
|
"could not allocate IRQ#%d.\n",
|
||||||
(unsigned long)cy_isa_address, cy_isa_irq);
|
(unsigned long)cy_isa_address, cy_isa_irq);
|
||||||
@ -3372,16 +3371,16 @@ static int __init cy_detect_isa(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set cy_card */
|
/* set cy_card */
|
||||||
cy_card[j].base_addr = cy_isa_address;
|
card->base_addr = cy_isa_address;
|
||||||
cy_card[j].ctl_addr.p9050 = NULL;
|
card->ctl_addr.p9050 = NULL;
|
||||||
cy_card[j].irq = (int)cy_isa_irq;
|
card->irq = (int)cy_isa_irq;
|
||||||
cy_card[j].bus_index = 0;
|
card->bus_index = 0;
|
||||||
cy_card[j].first_line = cy_next_channel;
|
card->first_line = cy_next_channel;
|
||||||
cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
|
card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
|
||||||
cy_card[j].nports = cy_isa_nchan;
|
card->nports = cy_isa_nchan;
|
||||||
if (cy_init_card(&cy_card[j])) {
|
if (cy_init_card(card)) {
|
||||||
cy_card[j].base_addr = NULL;
|
card->base_addr = NULL;
|
||||||
free_irq(cy_isa_irq, &cy_card[j]);
|
free_irq(cy_isa_irq, card);
|
||||||
iounmap(cy_isa_address);
|
iounmap(cy_isa_address);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -3393,9 +3392,10 @@ static int __init cy_detect_isa(void)
|
|||||||
(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
|
(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
|
||||||
cy_isa_irq, cy_isa_nchan, cy_next_channel);
|
cy_isa_irq, cy_isa_nchan, cy_next_channel);
|
||||||
|
|
||||||
for (j = cy_next_channel;
|
for (k = 0, j = cy_next_channel;
|
||||||
j < cy_next_channel + cy_isa_nchan; j++)
|
j < cy_next_channel + cy_isa_nchan; j++, k++)
|
||||||
tty_register_device(cy_serial_driver, j, NULL);
|
tty_port_register_device(&card->ports[k].port,
|
||||||
|
cy_serial_driver, j, NULL);
|
||||||
cy_next_channel += cy_isa_nchan;
|
cy_next_channel += cy_isa_nchan;
|
||||||
}
|
}
|
||||||
return nboard;
|
return nboard;
|
||||||
@ -3695,10 +3695,11 @@ err:
|
|||||||
static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
||||||
const struct pci_device_id *ent)
|
const struct pci_device_id *ent)
|
||||||
{
|
{
|
||||||
|
struct cyclades_card *card;
|
||||||
void __iomem *addr0 = NULL, *addr2 = NULL;
|
void __iomem *addr0 = NULL, *addr2 = NULL;
|
||||||
char *card_name = NULL;
|
char *card_name = NULL;
|
||||||
u32 uninitialized_var(mailbox);
|
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;
|
unsigned char plx_ver;
|
||||||
int retval, irq;
|
int retval, irq;
|
||||||
|
|
||||||
@ -3829,7 +3830,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
|||||||
}
|
}
|
||||||
/* fill the next cy_card structure available */
|
/* fill the next cy_card structure available */
|
||||||
for (card_no = 0; card_no < NR_CARDS; card_no++) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (card_no == NR_CARDS) { /* no more cy_cards available */
|
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) {
|
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
|
||||||
/* allocate IRQ */
|
/* allocate IRQ */
|
||||||
retval = request_irq(irq, cyy_interrupt,
|
retval = request_irq(irq, cyy_interrupt,
|
||||||
IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
|
IRQF_SHARED, "Cyclom-Y", card);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&pdev->dev, "could not allocate IRQ\n");
|
dev_err(&pdev->dev, "could not allocate IRQ\n");
|
||||||
goto err_unmap;
|
goto err_unmap;
|
||||||
}
|
}
|
||||||
cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
|
card->num_chips = nchan / CyPORTS_PER_CHIP;
|
||||||
} else {
|
} else {
|
||||||
struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
|
struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
|
||||||
struct ZFW_CTRL __iomem *zfw_ctrl;
|
struct ZFW_CTRL __iomem *zfw_ctrl;
|
||||||
|
|
||||||
zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
|
zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
|
||||||
|
|
||||||
cy_card[card_no].hw_ver = mailbox;
|
card->hw_ver = mailbox;
|
||||||
cy_card[card_no].num_chips = (unsigned int)-1;
|
card->num_chips = (unsigned int)-1;
|
||||||
cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
|
card->board_ctrl = &zfw_ctrl->board_ctrl;
|
||||||
#ifdef CONFIG_CYZ_INTR
|
#ifdef CONFIG_CYZ_INTR
|
||||||
/* allocate IRQ only if board has an IRQ */
|
/* allocate IRQ only if board has an IRQ */
|
||||||
if (irq != 0 && irq != 255) {
|
if (irq != 0 && irq != 255) {
|
||||||
retval = request_irq(irq, cyz_interrupt,
|
retval = request_irq(irq, cyz_interrupt,
|
||||||
IRQF_SHARED, "Cyclades-Z",
|
IRQF_SHARED, "Cyclades-Z", card);
|
||||||
&cy_card[card_no]);
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&pdev->dev, "could not allocate IRQ\n");
|
dev_err(&pdev->dev, "could not allocate IRQ\n");
|
||||||
goto err_unmap;
|
goto err_unmap;
|
||||||
@ -3873,17 +3874,17 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set cy_card */
|
/* set cy_card */
|
||||||
cy_card[card_no].base_addr = addr2;
|
card->base_addr = addr2;
|
||||||
cy_card[card_no].ctl_addr.p9050 = addr0;
|
card->ctl_addr.p9050 = addr0;
|
||||||
cy_card[card_no].irq = irq;
|
card->irq = irq;
|
||||||
cy_card[card_no].bus_index = 1;
|
card->bus_index = 1;
|
||||||
cy_card[card_no].first_line = cy_next_channel;
|
card->first_line = cy_next_channel;
|
||||||
cy_card[card_no].nports = nchan;
|
card->nports = nchan;
|
||||||
retval = cy_init_card(&cy_card[card_no]);
|
retval = cy_init_card(card);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto err_null;
|
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 ||
|
if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
|
||||||
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
|
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 "
|
dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
|
||||||
"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
|
"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
|
||||||
for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
|
for (j = 0, i = cy_next_channel; i < cy_next_channel + nchan; i++, j++)
|
||||||
tty_register_device(cy_serial_driver, i, &pdev->dev);
|
tty_port_register_device(&card->ports[j].port,
|
||||||
|
cy_serial_driver, i, &pdev->dev);
|
||||||
cy_next_channel += nchan;
|
cy_next_channel += nchan;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_null:
|
err_null:
|
||||||
cy_card[card_no].base_addr = NULL;
|
card->base_addr = NULL;
|
||||||
free_irq(irq, &cy_card[card_no]);
|
free_irq(irq, card);
|
||||||
err_unmap:
|
err_unmap:
|
||||||
iounmap(addr0);
|
iounmap(addr0);
|
||||||
if (addr2)
|
if (addr2)
|
||||||
|
@ -738,16 +738,17 @@ static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
|
|||||||
goto error;
|
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)) {
|
if (IS_ERR(bc->dev)) {
|
||||||
ret = PTR_ERR(bc->dev);
|
ret = PTR_ERR(bc->dev);
|
||||||
dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret);
|
dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_port_init(&bc->port);
|
|
||||||
bc->port.ops = &ehv_bc_tty_port_ops;
|
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, bc);
|
dev_set_drvdata(&pdev->dev, bc);
|
||||||
|
|
||||||
dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n",
|
dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n",
|
||||||
|
@ -299,20 +299,33 @@ static void hvc_unthrottle(struct tty_struct *tty)
|
|||||||
hvc_kick();
|
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
|
* The TTY interface won't be used until after the vio layer has exposed the vty
|
||||||
* adapter to the kernel.
|
* adapter to the kernel.
|
||||||
*/
|
*/
|
||||||
static int hvc_open(struct tty_struct *tty, struct file * filp)
|
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;
|
unsigned long flags;
|
||||||
int rc = 0;
|
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);
|
spin_lock_irqsave(&hp->port.lock, flags);
|
||||||
/* Check and then increment for fast path open. */
|
/* Check and then increment for fast path open. */
|
||||||
if (hp->port.count++ > 0) {
|
if (hp->port.count++ > 0) {
|
||||||
@ -322,7 +335,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
|
|||||||
} /* else count == 0 */
|
} /* else count == 0 */
|
||||||
spin_unlock_irqrestore(&hp->port.lock, flags);
|
spin_unlock_irqrestore(&hp->port.lock, flags);
|
||||||
|
|
||||||
tty->driver_data = hp;
|
|
||||||
tty_port_tty_set(&hp->port, tty);
|
tty_port_tty_set(&hp->port, tty);
|
||||||
|
|
||||||
if (hp->ops->notifier_add)
|
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);
|
hp->vtermno, hp->port.count);
|
||||||
spin_unlock_irqrestore(&hp->port.lock, flags);
|
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);
|
tty_port_put(&hp->port);
|
||||||
}
|
}
|
||||||
@ -792,8 +809,10 @@ static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct tty_operations hvc_ops = {
|
static const struct tty_operations hvc_ops = {
|
||||||
|
.install = hvc_install,
|
||||||
.open = hvc_open,
|
.open = hvc_open,
|
||||||
.close = hvc_close,
|
.close = hvc_close,
|
||||||
|
.cleanup = hvc_cleanup,
|
||||||
.write = hvc_write,
|
.write = hvc_write,
|
||||||
.hangup = hvc_hangup,
|
.hangup = hvc_hangup,
|
||||||
.unthrottle = hvc_unthrottle,
|
.unthrottle = hvc_unthrottle,
|
||||||
|
@ -1102,27 +1102,20 @@ static struct hvcs_struct *hvcs_get_by_index(int index)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||||
* 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;
|
struct hvcs_struct *hvcsd;
|
||||||
int rc, retval = 0;
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned int irq;
|
|
||||||
struct vio_dev *vdev;
|
struct vio_dev *vdev;
|
||||||
unsigned long unit_address;
|
unsigned long unit_address, flags;
|
||||||
|
unsigned int irq;
|
||||||
if (tty->driver_data)
|
int retval;
|
||||||
goto fast_open;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is there a vty-server that shares the same index?
|
* Is there a vty-server that shares the same index?
|
||||||
* This function increments the kref 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"
|
printk(KERN_WARNING "HVCS: open failed, no device associated"
|
||||||
" with tty->index %d.\n", tty->index);
|
" with tty->index %d.\n", tty->index);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -1130,11 +1123,16 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
|
|||||||
|
|
||||||
spin_lock_irqsave(&hvcsd->lock, flags);
|
spin_lock_irqsave(&hvcsd->lock, flags);
|
||||||
|
|
||||||
if (hvcsd->connected == 0)
|
if (hvcsd->connected == 0) {
|
||||||
if ((retval = hvcs_partner_connect(hvcsd)))
|
retval = hvcs_partner_connect(hvcsd);
|
||||||
goto error_release;
|
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;
|
hvcsd->port.tty = tty;
|
||||||
tty->driver_data = hvcsd;
|
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
|
* This must be done outside of the spinlock because it requests irqs
|
||||||
* and will grab the spinlock and free the connection if it fails.
|
* and will grab the spinlock and free the connection if it fails.
|
||||||
*/
|
*/
|
||||||
if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
|
retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev);
|
||||||
tty_port_put(&hvcsd->port);
|
if (retval) {
|
||||||
printk(KERN_WARNING "HVCS: enable device failed.\n");
|
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:
|
return 0;
|
||||||
hvcsd = tty->driver_data;
|
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);
|
spin_lock_irqsave(&hvcsd->lock, flags);
|
||||||
tty_port_get(&hvcsd->port);
|
|
||||||
hvcsd->port.count++;
|
hvcsd->port.count++;
|
||||||
hvcsd->todo_mask |= HVCS_SCHED_READ;
|
hvcsd->todo_mask |= HVCS_SCHED_READ;
|
||||||
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
||||||
|
|
||||||
open_success:
|
|
||||||
hvcs_kick();
|
hvcs_kick();
|
||||||
|
|
||||||
printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
|
printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
|
||||||
hvcsd->vdev->unit_address );
|
hvcsd->vdev->unit_address );
|
||||||
|
|
||||||
return 0;
|
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)
|
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;
|
tty->driver_data = NULL;
|
||||||
|
|
||||||
free_irq(irq, hvcsd);
|
free_irq(irq, hvcsd);
|
||||||
tty_port_put(&hvcsd->port);
|
|
||||||
return;
|
return;
|
||||||
} else if (hvcsd->port.count < 0) {
|
} else if (hvcsd->port.count < 0) {
|
||||||
printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
|
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);
|
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);
|
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 = {
|
static const struct tty_operations hvcs_ops = {
|
||||||
|
.install = hvcs_install,
|
||||||
.open = hvcs_open,
|
.open = hvcs_open,
|
||||||
.close = hvcs_close,
|
.close = hvcs_close,
|
||||||
|
.cleanup = hvcs_cleanup,
|
||||||
.hangup = hvcs_hangup,
|
.hangup = hvcs_hangup,
|
||||||
.write = hvcs_write,
|
.write = hvcs_write,
|
||||||
.write_room = hvcs_write_room,
|
.write_room = hvcs_write_room,
|
||||||
|
@ -1080,6 +1080,8 @@ static int __init hvsi_init(void)
|
|||||||
struct hvsi_struct *hp = &hvsi_ports[i];
|
struct hvsi_struct *hp = &hvsi_ports[i];
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
|
tty_port_link_device(&hp->port, hvsi_driver, i);
|
||||||
|
|
||||||
ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
|
ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
|
||||||
if (ret)
|
if (ret)
|
||||||
printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
|
printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
|
||||||
|
@ -400,7 +400,7 @@ void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp)
|
|||||||
spin_unlock_irqrestore(&hp->lock, flags);
|
spin_unlock_irqrestore(&hp->lock, flags);
|
||||||
|
|
||||||
/* Clear our own DTR */
|
/* 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);
|
hvsilib_write_mctrl(pv, 0);
|
||||||
|
|
||||||
/* Tear down the connection */
|
/* Tear down the connection */
|
||||||
|
@ -476,7 +476,7 @@ static int add_tty(int j,
|
|||||||
mutex_init(&ttys[j]->ipw_tty_mutex);
|
mutex_init(&ttys[j]->ipw_tty_mutex);
|
||||||
tty_port_init(&ttys[j]->port);
|
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]);
|
ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
|
||||||
|
|
||||||
if (secondary_channel_idx != -1)
|
if (secondary_channel_idx != -1)
|
||||||
|
@ -600,7 +600,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||||||
port->status &= ~ISI_DCD;
|
port->status &= ~ISI_DCD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->port.flags & ASYNC_CTS_FLOW) {
|
if (tty_port_cts_enabled(&port->port)) {
|
||||||
if (tty->hw_stopped) {
|
if (tty->hw_stopped) {
|
||||||
if (header & ISI_CTS) {
|
if (header & ISI_CTS) {
|
||||||
port->port.tty->hw_stopped = 0;
|
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. */
|
/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
|
||||||
if (baud < 1 || baud > 4)
|
if (baud < 1 || baud > 4)
|
||||||
tty->termios->c_cflag &= ~CBAUDEX;
|
tty->termios.c_cflag &= ~CBAUDEX;
|
||||||
else
|
else
|
||||||
baud += 15;
|
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"))
|
if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (tty->termios->c_cflag == old_termios->c_cflag &&
|
if (tty->termios.c_cflag == old_termios->c_cflag &&
|
||||||
tty->termios->c_iflag == old_termios->c_iflag)
|
tty->termios.c_iflag == old_termios->c_iflag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->card->card_lock, flags);
|
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);
|
spin_unlock_irqrestore(&port->card->card_lock, flags);
|
||||||
|
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
isicom_start(tty);
|
isicom_start(tty);
|
||||||
}
|
}
|
||||||
@ -1611,7 +1611,8 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
|
|||||||
goto errunri;
|
goto errunri;
|
||||||
|
|
||||||
for (index = 0; index < board->port_count; index++)
|
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);
|
&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -169,6 +169,7 @@ static DEFINE_SPINLOCK(moxa_lock);
|
|||||||
static unsigned long baseaddr[MAX_BOARDS];
|
static unsigned long baseaddr[MAX_BOARDS];
|
||||||
static unsigned int type[MAX_BOARDS];
|
static unsigned int type[MAX_BOARDS];
|
||||||
static unsigned int numports[MAX_BOARDS];
|
static unsigned int numports[MAX_BOARDS];
|
||||||
|
static struct tty_port moxa_service_port;
|
||||||
|
|
||||||
MODULE_AUTHOR("William Chen");
|
MODULE_AUTHOR("William Chen");
|
||||||
MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
|
MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
|
||||||
@ -367,10 +368,10 @@ static int moxa_ioctl(struct tty_struct *tty,
|
|||||||
tmp.dcd = 1;
|
tmp.dcd = 1;
|
||||||
|
|
||||||
ttyp = tty_port_tty_get(&p->port);
|
ttyp = tty_port_tty_get(&p->port);
|
||||||
if (!ttyp || !ttyp->termios)
|
if (!ttyp)
|
||||||
tmp.cflag = p->cflag;
|
tmp.cflag = p->cflag;
|
||||||
else
|
else
|
||||||
tmp.cflag = ttyp->termios->c_cflag;
|
tmp.cflag = ttyp->termios.c_cflag;
|
||||||
tty_kref_put(ttyp);
|
tty_kref_put(ttyp);
|
||||||
copy:
|
copy:
|
||||||
if (copy_to_user(argm, &tmp, sizeof(tmp)))
|
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 struct firmware *fw;
|
||||||
const char *file;
|
const char *file;
|
||||||
struct moxa_port *p;
|
struct moxa_port *p;
|
||||||
unsigned int i;
|
unsigned int i, first_idx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
|
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);
|
mod_timer(&moxaTimer, jiffies + HZ / 50);
|
||||||
spin_unlock_bh(&moxa_lock);
|
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;
|
return 0;
|
||||||
err_free:
|
err_free:
|
||||||
kfree(brd->ports);
|
kfree(brd->ports);
|
||||||
@ -896,7 +902,7 @@ err:
|
|||||||
|
|
||||||
static void moxa_board_deinit(struct moxa_board_conf *brd)
|
static void moxa_board_deinit(struct moxa_board_conf *brd)
|
||||||
{
|
{
|
||||||
unsigned int a, opened;
|
unsigned int a, opened, first_idx;
|
||||||
|
|
||||||
mutex_lock(&moxa_openlock);
|
mutex_lock(&moxa_openlock);
|
||||||
spin_lock_bh(&moxa_lock);
|
spin_lock_bh(&moxa_lock);
|
||||||
@ -925,6 +931,10 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
|
|||||||
mutex_lock(&moxa_openlock);
|
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);
|
iounmap(brd->basemem);
|
||||||
brd->basemem = NULL;
|
brd->basemem = NULL;
|
||||||
kfree(brd->ports);
|
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);
|
board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
|
||||||
if (board->basemem == NULL) {
|
if (board->basemem == NULL) {
|
||||||
dev_err(&pdev->dev, "can't remap io space 2\n");
|
dev_err(&pdev->dev, "can't remap io space 2\n");
|
||||||
|
retval = -ENOMEM;
|
||||||
goto err_reg;
|
goto err_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,9 +1042,14 @@ static int __init moxa_init(void)
|
|||||||
|
|
||||||
printk(KERN_INFO "MOXA Intellio family driver version %s\n",
|
printk(KERN_INFO "MOXA Intellio family driver version %s\n",
|
||||||
MOXA_VERSION);
|
MOXA_VERSION);
|
||||||
moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
|
|
||||||
if (!moxaDriver)
|
tty_port_init(&moxa_service_port);
|
||||||
return -ENOMEM;
|
|
||||||
|
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->name = "ttyMX";
|
||||||
moxaDriver->major = ttymajor;
|
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_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
|
||||||
moxaDriver->init_termios.c_ispeed = 9600;
|
moxaDriver->init_termios.c_ispeed = 9600;
|
||||||
moxaDriver->init_termios.c_ospeed = 9600;
|
moxaDriver->init_termios.c_ospeed = 9600;
|
||||||
moxaDriver->flags = TTY_DRIVER_REAL_RAW;
|
|
||||||
tty_set_operations(moxaDriver, &moxa_ops);
|
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)) {
|
if (tty_register_driver(moxaDriver)) {
|
||||||
printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
|
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);
|
mutex_lock(&ch->port.mutex);
|
||||||
if (!(ch->port.flags & ASYNC_INITIALIZED)) {
|
if (!(ch->port.flags & ASYNC_INITIALIZED)) {
|
||||||
ch->statusflags = 0;
|
ch->statusflags = 0;
|
||||||
moxa_set_tty_param(tty, tty->termios);
|
moxa_set_tty_param(tty, &tty->termios);
|
||||||
MoxaPortLineCtrl(ch, 1, 1);
|
MoxaPortLineCtrl(ch, 1, 1);
|
||||||
MoxaPortEnable(ch);
|
MoxaPortEnable(ch);
|
||||||
MoxaSetFifo(ch, ch->type == PORT_16550A);
|
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)
|
static void moxa_close(struct tty_struct *tty, struct file *filp)
|
||||||
{
|
{
|
||||||
struct moxa_port *ch = tty->driver_data;
|
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);
|
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)
|
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;
|
struct moxa_port *ch = tty->driver_data;
|
||||||
int rts, cts, txflow, rxflow, xany, baud;
|
int rts, cts, txflow, rxflow, xany, baud;
|
||||||
|
|
||||||
|
@ -643,7 +643,7 @@ static int mxser_change_speed(struct tty_struct *tty,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned char status;
|
unsigned char status;
|
||||||
|
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
if (!info->ioaddr)
|
if (!info->ioaddr)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -830,7 +830,7 @@ static void mxser_check_modem_status(struct tty_struct *tty,
|
|||||||
wake_up_interruptible(&port->port.open_wait);
|
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 (tty->hw_stopped) {
|
||||||
if (status & UART_MSR_CTS) {
|
if (status & UART_MSR_CTS) {
|
||||||
tty->hw_stopped = 0;
|
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);
|
tty = tty_port_tty_get(port);
|
||||||
|
|
||||||
if (!tty || !tty->termios)
|
if (!tty)
|
||||||
ms.cflag = ip->normal_termios.c_cflag;
|
ms.cflag = ip->normal_termios.c_cflag;
|
||||||
else
|
else
|
||||||
ms.cflag = tty->termios->c_cflag;
|
ms.cflag = tty->termios.c_cflag;
|
||||||
tty_kref_put(tty);
|
tty_kref_put(tty);
|
||||||
spin_lock_irq(&ip->slock);
|
spin_lock_irq(&ip->slock);
|
||||||
status = inb(ip->ioaddr + UART_MSR);
|
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);
|
tty = tty_port_tty_get(&ip->port);
|
||||||
|
|
||||||
if (!tty || !tty->termios) {
|
if (!tty) {
|
||||||
cflag = ip->normal_termios.c_cflag;
|
cflag = ip->normal_termios.c_cflag;
|
||||||
iflag = ip->normal_termios.c_iflag;
|
iflag = ip->normal_termios.c_iflag;
|
||||||
me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
|
me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
|
||||||
} else {
|
} else {
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
iflag = tty->termios->c_iflag;
|
iflag = tty->termios.c_iflag;
|
||||||
me->baudrate[p] = tty_get_baud_rate(tty);
|
me->baudrate[p] = tty_get_baud_rate(tty);
|
||||||
}
|
}
|
||||||
tty_kref_put(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;
|
info->MCR &= ~UART_MCR_RTS;
|
||||||
outb(info->MCR, info->ioaddr + UART_MCR);
|
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;
|
info->MCR |= UART_MCR_RTS;
|
||||||
outb(info->MCR, info->ioaddr + UART_MCR);
|
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);
|
spin_unlock_irqrestore(&info->slock, flags);
|
||||||
|
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
mxser_start(tty);
|
mxser_start(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle sw stopped */
|
/* Handle sw stopped */
|
||||||
if ((old_termios->c_iflag & IXON) &&
|
if ((old_termios->c_iflag & IXON) &&
|
||||||
!(tty->termios->c_iflag & IXON)) {
|
!(tty->termios.c_iflag & IXON)) {
|
||||||
tty->stopped = 0;
|
tty->stopped = 0;
|
||||||
|
|
||||||
if (info->board->chip_flag) {
|
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!
|
* 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)
|
static void mxser_release_ISA_res(struct mxser_board *brd)
|
||||||
{
|
{
|
||||||
free_irq(brd->irq, brd);
|
free_irq(brd->irq, brd);
|
||||||
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
|
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,
|
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)
|
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 short regs[16], irq;
|
||||||
unsigned char scratch, scratch2;
|
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);
|
8 * brd->info->nports - 1);
|
||||||
return -EIO;
|
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);
|
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
|
||||||
printk(KERN_ERR "mxser: can't request interrupt vector region: "
|
printk(KERN_ERR "mxser: can't request interrupt vector region: "
|
||||||
"0x%.8lx-0x%.8lx\n",
|
"0x%.8lx-0x%.8lx\n",
|
||||||
brd->ports[0].ioaddr, brd->ports[0].ioaddr +
|
brd->ports[0].ioaddr, brd->ports[0].ioaddr +
|
||||||
8 * brd->info->nports - 1);
|
8 * brd->info->nports - 1);
|
||||||
return -EIO;
|
return ret;
|
||||||
}
|
}
|
||||||
return brd->info->nports;
|
return brd->info->nports;
|
||||||
|
|
||||||
@ -2598,7 +2625,8 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
|||||||
goto err_rel3;
|
goto err_rel3;
|
||||||
|
|
||||||
for (i = 0; i < brd->info->nports; i++)
|
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);
|
pci_set_drvdata(pdev, brd);
|
||||||
|
|
||||||
@ -2695,7 +2723,8 @@ static int __init mxser_module_init(void)
|
|||||||
|
|
||||||
brd->idx = m * MXSER_PORTS_PER_BOARD;
|
brd->idx = m * MXSER_PORTS_PER_BOARD;
|
||||||
for (i = 0; i < brd->info->nports; i++)
|
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++;
|
m++;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ struct gsm_mux_net {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct gsm_msg {
|
struct gsm_msg {
|
||||||
struct gsm_msg *next;
|
struct list_head list;
|
||||||
u8 addr; /* DLCI address + flags */
|
u8 addr; /* DLCI address + flags */
|
||||||
u8 ctrl; /* Control byte + flags */
|
u8 ctrl; /* Control byte + flags */
|
||||||
unsigned int len; /* Length of data block (can be zero) */
|
unsigned int len; /* Length of data block (can be zero) */
|
||||||
@ -245,8 +245,7 @@ struct gsm_mux {
|
|||||||
unsigned int tx_bytes; /* TX data outstanding */
|
unsigned int tx_bytes; /* TX data outstanding */
|
||||||
#define TX_THRESH_HI 8192
|
#define TX_THRESH_HI 8192
|
||||||
#define TX_THRESH_LO 2048
|
#define TX_THRESH_LO 2048
|
||||||
struct gsm_msg *tx_head; /* Pending data packets */
|
struct list_head tx_list; /* Pending data packets */
|
||||||
struct gsm_msg *tx_tail;
|
|
||||||
|
|
||||||
/* Control messages */
|
/* Control messages */
|
||||||
struct timer_list t2_timer; /* Retransmit timer for commands */
|
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->len = len;
|
||||||
m->addr = addr;
|
m->addr = addr;
|
||||||
m->ctrl = ctrl;
|
m->ctrl = ctrl;
|
||||||
m->next = NULL;
|
INIT_LIST_HEAD(&m->list);
|
||||||
return m;
|
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 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
|
* 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
|
* FIXME: lock against link layer control transmissions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void gsm_data_kick(struct gsm_mux *gsm)
|
static void gsm_data_kick(struct gsm_mux *gsm)
|
||||||
{
|
{
|
||||||
struct gsm_msg *msg = gsm->tx_head;
|
struct gsm_msg *msg, *nmsg;
|
||||||
int len;
|
int len;
|
||||||
int skip_sof = 0;
|
int skip_sof = 0;
|
||||||
|
|
||||||
/* FIXME: We need to apply this solely to data messages */
|
list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) {
|
||||||
if (gsm->constipated)
|
if (gsm->constipated && msg->addr)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
while (gsm->tx_head != NULL) {
|
|
||||||
msg = gsm->tx_head;
|
|
||||||
if (gsm->encoding != 0) {
|
if (gsm->encoding != 0) {
|
||||||
gsm->txframe[0] = GSM1_SOF;
|
gsm->txframe[0] = GSM1_SOF;
|
||||||
len = gsm_stuff_frame(msg->data,
|
len = gsm_stuff_frame(msg->data,
|
||||||
@ -711,14 +709,13 @@ static void gsm_data_kick(struct gsm_mux *gsm)
|
|||||||
len - skip_sof) < 0)
|
len - skip_sof) < 0)
|
||||||
break;
|
break;
|
||||||
/* FIXME: Can eliminate one SOF in many more cases */
|
/* 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;
|
gsm->tx_bytes -= msg->len;
|
||||||
kfree(msg);
|
|
||||||
/* For a burst of frames skip the extra SOF within the
|
/* For a burst of frames skip the extra SOF within the
|
||||||
burst */
|
burst */
|
||||||
skip_sof = 1;
|
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;
|
msg->data = dp;
|
||||||
|
|
||||||
/* Add to the actual output queue */
|
/* Add to the actual output queue */
|
||||||
if (gsm->tx_tail)
|
list_add_tail(&msg->list, &gsm->tx_list);
|
||||||
gsm->tx_tail->next = msg;
|
|
||||||
else
|
|
||||||
gsm->tx_head = msg;
|
|
||||||
gsm->tx_tail = msg;
|
|
||||||
gsm->tx_bytes += msg->len;
|
gsm->tx_bytes += msg->len;
|
||||||
gsm_data_kick(gsm);
|
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 */
|
/* dlci->skb is locked by tx_lock */
|
||||||
if (dlci->skb == NULL) {
|
if (dlci->skb == NULL) {
|
||||||
dlci->skb = skb_dequeue(&dlci->skb_list);
|
dlci->skb = skb_dequeue_tail(&dlci->skb_list);
|
||||||
if (dlci->skb == NULL)
|
if (dlci->skb == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
first = 1;
|
first = 1;
|
||||||
@ -886,7 +879,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
|
|||||||
if (len > gsm->mtu) {
|
if (len > gsm->mtu) {
|
||||||
if (dlci->adaption == 3) {
|
if (dlci->adaption == 3) {
|
||||||
/* Over long frame, bin it */
|
/* Over long frame, bin it */
|
||||||
kfree_skb(dlci->skb);
|
dev_kfree_skb_any(dlci->skb);
|
||||||
dlci->skb = NULL;
|
dlci->skb = NULL;
|
||||||
return 0;
|
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
|
/* FIXME: need a timer or something to kick this so it can't
|
||||||
get stuck with no work outstanding and no buffer free */
|
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;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
dp = msg->data;
|
dp = msg->data;
|
||||||
|
|
||||||
if (dlci->adaption == 4) { /* Interruptible framed (Packetised 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);
|
skb_pull(dlci->skb, len);
|
||||||
__gsm_data_queue(dlci, msg);
|
__gsm_data_queue(dlci, msg);
|
||||||
if (last) {
|
if (last) {
|
||||||
kfree_skb(dlci->skb);
|
dev_kfree_skb_any(dlci->skb);
|
||||||
dlci->skb = NULL;
|
dlci->skb = NULL;
|
||||||
}
|
}
|
||||||
return size;
|
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)
|
static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int sweep;
|
||||||
|
|
||||||
|
if (dlci->constipated)
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
|
spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
|
||||||
/* If we have nothing running then we need to fire up */
|
/* 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->gsm->tx_bytes == 0) {
|
||||||
if (dlci->net)
|
if (dlci->net)
|
||||||
gsm_dlci_data_output_framed(dlci->gsm, dlci);
|
gsm_dlci_data_output_framed(dlci->gsm, dlci);
|
||||||
else
|
else
|
||||||
gsm_dlci_data_output(dlci->gsm, dlci);
|
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);
|
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;
|
int mlines = 0;
|
||||||
u8 brk = 0;
|
u8 brk = 0;
|
||||||
|
int fc;
|
||||||
|
|
||||||
/* The modem status command can either contain one octet (v.24 signals)
|
/* The modem status command can either contain one octet (v.24 signals)
|
||||||
or two octets (v.24 signals + break signals). The length field will
|
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 {
|
else {
|
||||||
brk = modem & 0x7f;
|
brk = modem & 0x7f;
|
||||||
modem = (modem >> 7) & 0x7f;
|
modem = (modem >> 7) & 0x7f;
|
||||||
};
|
}
|
||||||
|
|
||||||
/* Flow control/ready to communicate */
|
/* 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 */
|
/* Need to throttle our output on this device */
|
||||||
dlci->constipated = 1;
|
dlci->constipated = 1;
|
||||||
}
|
} else if (!fc && dlci->constipated) {
|
||||||
if (modem & MDM_RTC) {
|
|
||||||
mlines |= TIOCM_DSR | TIOCM_DTR;
|
|
||||||
dlci->constipated = 0;
|
dlci->constipated = 0;
|
||||||
gsm_dlci_data_kick(dlci);
|
gsm_dlci_data_kick(dlci);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map modem bits */
|
/* Map modem bits */
|
||||||
|
if (modem & MDM_RTC)
|
||||||
|
mlines |= TIOCM_DSR | TIOCM_DTR;
|
||||||
if (modem & MDM_RTR)
|
if (modem & MDM_RTR)
|
||||||
mlines |= TIOCM_RTS | TIOCM_CTS;
|
mlines |= TIOCM_RTS | TIOCM_CTS;
|
||||||
if (modem & MDM_IC)
|
if (modem & MDM_IC)
|
||||||
@ -1061,7 +1066,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
|
|||||||
/* Carrier drop -> hangup */
|
/* Carrier drop -> hangup */
|
||||||
if (tty) {
|
if (tty) {
|
||||||
if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD))
|
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);
|
tty_hangup(tty);
|
||||||
if (brk & 0x01)
|
if (brk & 0x01)
|
||||||
tty_insert_flip_char(tty, 0, TTY_BREAK);
|
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 *data, int clen)
|
||||||
{
|
{
|
||||||
u8 buf[1];
|
u8 buf[1];
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case CMD_CLD: {
|
case CMD_CLD: {
|
||||||
struct gsm_dlci *dlci = gsm->dlci[0];
|
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);
|
gsm_control_reply(gsm, CMD_TEST, data, clen);
|
||||||
break;
|
break;
|
||||||
case CMD_FCON:
|
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 */
|
/* Modem can accept data again */
|
||||||
gsm->constipated = 0;
|
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 */
|
/* Kick the link in case it is idling */
|
||||||
|
spin_lock_irqsave(&gsm->tx_lock, flags);
|
||||||
gsm_data_kick(gsm);
|
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;
|
break;
|
||||||
case CMD_MSC:
|
case CMD_MSC:
|
||||||
/* Out of band modem line change indicator for a DLCI */
|
/* 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;
|
dlci->gsm->dlci[dlci->addr] = NULL;
|
||||||
kfifo_free(dlci->fifo);
|
kfifo_free(dlci->fifo);
|
||||||
while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
|
while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
|
||||||
kfree_skb(dlci->skb);
|
dev_kfree_skb(dlci->skb);
|
||||||
kfree(dlci);
|
kfree(dlci);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2007,7 +2016,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct gsm_dlci *dlci = gsm->dlci[0];
|
struct gsm_dlci *dlci = gsm->dlci[0];
|
||||||
struct gsm_msg *txq;
|
struct gsm_msg *txq, *ntxq;
|
||||||
struct gsm_control *gc;
|
struct gsm_control *gc;
|
||||||
|
|
||||||
gsm->dead = 1;
|
gsm->dead = 1;
|
||||||
@ -2042,11 +2051,9 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
|
|||||||
if (gsm->dlci[i])
|
if (gsm->dlci[i])
|
||||||
gsm_dlci_release(gsm->dlci[i]);
|
gsm_dlci_release(gsm->dlci[i]);
|
||||||
/* Now wipe the queues */
|
/* Now wipe the queues */
|
||||||
for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) {
|
list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
|
||||||
gsm->tx_head = txq->next;
|
|
||||||
kfree(txq);
|
kfree(txq);
|
||||||
}
|
INIT_LIST_HEAD(&gsm->tx_list);
|
||||||
gsm->tx_tail = NULL;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gsm_cleanup_mux);
|
EXPORT_SYMBOL_GPL(gsm_cleanup_mux);
|
||||||
|
|
||||||
@ -2157,6 +2164,7 @@ struct gsm_mux *gsm_alloc_mux(void)
|
|||||||
}
|
}
|
||||||
spin_lock_init(&gsm->lock);
|
spin_lock_init(&gsm->lock);
|
||||||
kref_init(&gsm->ref);
|
kref_init(&gsm->ref);
|
||||||
|
INIT_LIST_HEAD(&gsm->tx_list);
|
||||||
|
|
||||||
gsm->t1 = T1;
|
gsm->t1 = T1;
|
||||||
gsm->t2 = T2;
|
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);
|
gsm->error(gsm, *dp, flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ONCE("%s: unknown flag %d\n",
|
WARN_ONCE(1, "%s: unknown flag %d\n",
|
||||||
tty_name(tty, buf), flags);
|
tty_name(tty, buf), flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2377,12 +2385,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty)
|
|||||||
|
|
||||||
/* Queue poll */
|
/* Queue poll */
|
||||||
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||||
|
spin_lock_irqsave(&gsm->tx_lock, flags);
|
||||||
gsm_data_kick(gsm);
|
gsm_data_kick(gsm);
|
||||||
if (gsm->tx_bytes < TX_THRESH_LO) {
|
if (gsm->tx_bytes < TX_THRESH_LO) {
|
||||||
spin_lock_irqsave(&gsm->tx_lock, flags);
|
|
||||||
gsm_dlci_data_sweep(gsm);
|
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,
|
.dtr_rts = gsm_dtr_rts,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||||
static int gsmtty_open(struct tty_struct *tty, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct gsm_mux *gsm;
|
struct gsm_mux *gsm;
|
||||||
struct gsm_dlci *dlci;
|
struct gsm_dlci *dlci;
|
||||||
struct tty_port *port;
|
|
||||||
unsigned int line = tty->index;
|
unsigned int line = tty->index;
|
||||||
unsigned int mux = line >> 6;
|
unsigned int mux = line >> 6;
|
||||||
|
bool alloc = false;
|
||||||
|
int ret;
|
||||||
|
|
||||||
line = line & 0x3F;
|
line = line & 0x3F;
|
||||||
|
|
||||||
@ -2889,14 +2897,35 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
|
|||||||
gsm = gsm_mux[mux];
|
gsm = gsm_mux[mux];
|
||||||
if (gsm->dead)
|
if (gsm->dead)
|
||||||
return -EL2HLT;
|
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];
|
dlci = gsm->dlci[line];
|
||||||
if (dlci == NULL)
|
if (dlci == NULL) {
|
||||||
|
alloc = true;
|
||||||
dlci = gsm_dlci_alloc(gsm, line);
|
dlci = gsm_dlci_alloc(gsm, line);
|
||||||
|
}
|
||||||
if (dlci == NULL)
|
if (dlci == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
port = &dlci->port;
|
ret = tty_port_install(&dlci->port, driver, tty);
|
||||||
port->count++;
|
if (ret) {
|
||||||
|
if (alloc)
|
||||||
|
dlci_put(dlci);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
tty->driver_data = dlci;
|
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);
|
||||||
dlci_get(dlci->gsm->dlci[0]);
|
dlci_get(dlci->gsm->dlci[0]);
|
||||||
mux_get(dlci->gsm);
|
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
|
the RPN control message. This however rapidly gets nasty as we
|
||||||
then have to remap modem signals each way according to whether
|
then have to remap modem signals each way according to whether
|
||||||
our virtual cable is null modem etc .. */
|
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)
|
static void gsmtty_throttle(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct gsm_dlci *dlci = tty->driver_data;
|
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->modem_tx &= ~TIOCM_DTR;
|
||||||
dlci->throttled = 1;
|
dlci->throttled = 1;
|
||||||
/* Send an MSC with DTR cleared */
|
/* 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)
|
static void gsmtty_unthrottle(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct gsm_dlci *dlci = tty->driver_data;
|
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->modem_tx |= TIOCM_DTR;
|
||||||
dlci->throttled = 0;
|
dlci->throttled = 0;
|
||||||
/* Send an MSC with DTR set */
|
/* 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 */
|
/* Virtual ttys for the demux */
|
||||||
static const struct tty_operations gsmtty_ops = {
|
static const struct tty_operations gsmtty_ops = {
|
||||||
|
.install = gsmtty_install,
|
||||||
.open = gsmtty_open,
|
.open = gsmtty_open,
|
||||||
.close = gsmtty_close,
|
.close = gsmtty_close,
|
||||||
.write = gsmtty_write,
|
.write = gsmtty_write,
|
||||||
|
@ -1065,7 +1065,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
|
|||||||
|
|
||||||
TRACE_L("read()");
|
TRACE_L("read()");
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
|
|
||||||
pClient = findClient(pInfo, task_pid(current));
|
pClient = findClient(pInfo, task_pid(current));
|
||||||
if (pClient) {
|
if (pClient) {
|
||||||
@ -1077,7 +1077,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
/* block until there is a message: */
|
/* 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)));
|
(pMsg = remove_msg(pInfo, pClient)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,7 +1107,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
|
|||||||
}
|
}
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
unlock:
|
unlock:
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,7 +1156,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
|
|||||||
pHeader->locks = 0;
|
pHeader->locks = 0;
|
||||||
pHeader->owner = NULL;
|
pHeader->owner = NULL;
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
|
|
||||||
pClient = findClient(pInfo, task_pid(current));
|
pClient = findClient(pInfo, task_pid(current));
|
||||||
if (pClient) {
|
if (pClient) {
|
||||||
@ -1175,7 +1175,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
|
|||||||
add_tx_queue(pInfo, pHeader);
|
add_tx_queue(pInfo, pHeader);
|
||||||
trigger_transmit(pInfo);
|
trigger_transmit(pInfo);
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
static void n_tty_set_room(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
/* tty->read_cnt is not read locked ? */
|
int left;
|
||||||
int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
|
|
||||||
int old_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
|
* If we are doing input canonicalization, and there are no
|
||||||
* pending newlines, let characters through without limit, so
|
* 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)
|
if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
|
||||||
tty_throttle(tty);
|
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)
|
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);
|
BUG_ON(!tty);
|
||||||
|
|
||||||
if (old)
|
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) {
|
if (canon_change) {
|
||||||
memset(&tty->read_flags, 0, sizeof tty->read_flags);
|
memset(&tty->read_flags, 0, sizeof tty->read_flags);
|
||||||
tty->canon_head = tty->read_tail;
|
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:
|
do_it_again:
|
||||||
|
|
||||||
BUG_ON(!tty->read_buf);
|
if (WARN_ON(!tty->read_buf))
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
c = job_control(tty, file);
|
c = job_control(tty, file);
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
@ -1832,13 +1847,13 @@ do_it_again:
|
|||||||
|
|
||||||
if (tty->icanon && !L_EXTPROC(tty)) {
|
if (tty->icanon && !L_EXTPROC(tty)) {
|
||||||
/* N.B. avoid overrun if nr == 0 */
|
/* N.B. avoid overrun if nr == 0 */
|
||||||
|
spin_lock_irqsave(&tty->read_lock, flags);
|
||||||
while (nr && tty->read_cnt) {
|
while (nr && tty->read_cnt) {
|
||||||
int eol;
|
int eol;
|
||||||
|
|
||||||
eol = test_and_clear_bit(tty->read_tail,
|
eol = test_and_clear_bit(tty->read_tail,
|
||||||
tty->read_flags);
|
tty->read_flags);
|
||||||
c = tty->read_buf[tty->read_tail];
|
c = tty->read_buf[tty->read_tail];
|
||||||
spin_lock_irqsave(&tty->read_lock, flags);
|
|
||||||
tty->read_tail = ((tty->read_tail+1) &
|
tty->read_tail = ((tty->read_tail+1) &
|
||||||
(N_TTY_BUF_SIZE-1));
|
(N_TTY_BUF_SIZE-1));
|
||||||
tty->read_cnt--;
|
tty->read_cnt--;
|
||||||
@ -1856,15 +1871,19 @@ do_it_again:
|
|||||||
if (tty_put_user(tty, c, b++)) {
|
if (tty_put_user(tty, c, b++)) {
|
||||||
retval = -EFAULT;
|
retval = -EFAULT;
|
||||||
b--;
|
b--;
|
||||||
|
spin_lock_irqsave(&tty->read_lock, flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nr--;
|
nr--;
|
||||||
}
|
}
|
||||||
if (eol) {
|
if (eol) {
|
||||||
tty_audit_push(tty);
|
tty_audit_push(tty);
|
||||||
|
spin_lock_irqsave(&tty->read_lock, flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
spin_lock_irqsave(&tty->read_lock, flags);
|
||||||
}
|
}
|
||||||
|
spin_unlock_irqrestore(&tty->read_lock, flags);
|
||||||
if (retval)
|
if (retval)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1473,8 +1473,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
|
|||||||
port->dc = dc;
|
port->dc = dc;
|
||||||
tty_port_init(&port->port);
|
tty_port_init(&port->port);
|
||||||
port->port.ops = &noz_tty_port_ops;
|
port->port.ops = &noz_tty_port_ops;
|
||||||
tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
|
tty_dev = tty_port_register_device(&port->port, ntty_driver,
|
||||||
&pdev->dev);
|
dc->index_start + i, &pdev->dev);
|
||||||
|
|
||||||
if (IS_ERR(tty_dev)) {
|
if (IS_ERR(tty_dev)) {
|
||||||
ret = PTR_ERR(tty_dev);
|
ret = PTR_ERR(tty_dev);
|
||||||
|
@ -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->read_wait);
|
||||||
wake_up_interruptible(&tty->write_wait);
|
wake_up_interruptible(&tty->write_wait);
|
||||||
tty->packet = 0;
|
tty->packet = 0;
|
||||||
|
/* Review - krefs on tty_link ?? */
|
||||||
if (!tty->link)
|
if (!tty->link)
|
||||||
return;
|
return;
|
||||||
tty->link->packet = 0;
|
tty->link->packet = 0;
|
||||||
@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
|
|||||||
mutex_unlock(&devpts_mutex);
|
mutex_unlock(&devpts_mutex);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
tty_vhangup(tty->link);
|
tty_vhangup(tty->link);
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,8 +232,8 @@ out:
|
|||||||
static void pty_set_termios(struct tty_struct *tty,
|
static void pty_set_termios(struct tty_struct *tty,
|
||||||
struct ktermios *old_termios)
|
struct ktermios *old_termios)
|
||||||
{
|
{
|
||||||
tty->termios->c_cflag &= ~(CSIZE | PARENB);
|
tty->termios.c_cflag &= ~(CSIZE | PARENB);
|
||||||
tty->termios->c_cflag |= (CS8 | CREAD);
|
tty->termios.c_cflag |= (CS8 | CREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,60 +283,110 @@ done:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Traditional BSD devices */
|
/**
|
||||||
#ifdef CONFIG_LEGACY_PTYS
|
* pty_common_install - set up the pty pair
|
||||||
|
* @driver: the pty driver
|
||||||
static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
|
* @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_struct *o_tty;
|
||||||
|
struct tty_port *ports[2];
|
||||||
int idx = tty->index;
|
int idx = tty->index;
|
||||||
int retval;
|
int retval = -ENOMEM;
|
||||||
|
|
||||||
o_tty = alloc_tty_struct();
|
o_tty = alloc_tty_struct();
|
||||||
if (!o_tty)
|
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)) {
|
if (!try_module_get(driver->other->owner)) {
|
||||||
/* This cannot in fact currently happen */
|
/* This cannot in fact currently happen */
|
||||||
retval = -ENOMEM;
|
|
||||||
goto err_free_tty;
|
goto err_free_tty;
|
||||||
}
|
}
|
||||||
initialize_tty_struct(o_tty, driver->other, idx);
|
initialize_tty_struct(o_tty, driver->other, idx);
|
||||||
|
|
||||||
/* We always use new tty termios data so we can do this
|
if (legacy) {
|
||||||
the easy way .. */
|
/* We always use new tty termios data so we can do this
|
||||||
retval = tty_init_termios(tty);
|
the easy way .. */
|
||||||
if (retval)
|
retval = tty_init_termios(tty);
|
||||||
goto err_deinit_tty;
|
if (retval)
|
||||||
|
goto err_deinit_tty;
|
||||||
|
|
||||||
retval = tty_init_termios(o_tty);
|
retval = tty_init_termios(o_tty);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto err_free_termios;
|
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.
|
* Everything allocated ... set up the o_tty structure.
|
||||||
*/
|
*/
|
||||||
driver->other->ttys[idx] = o_tty;
|
|
||||||
tty_driver_kref_get(driver->other);
|
tty_driver_kref_get(driver->other);
|
||||||
if (driver->subtype == PTY_TYPE_MASTER)
|
if (driver->subtype == PTY_TYPE_MASTER)
|
||||||
o_tty->count++;
|
o_tty->count++;
|
||||||
/* Establish the links in both directions */
|
/* Establish the links in both directions */
|
||||||
tty->link = o_tty;
|
tty->link = o_tty;
|
||||||
o_tty->link = 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_driver_kref_get(driver);
|
||||||
tty->count++;
|
tty->count++;
|
||||||
driver->ttys[idx] = tty;
|
|
||||||
return 0;
|
return 0;
|
||||||
err_free_termios:
|
err_free_termios:
|
||||||
tty_free_termios(tty);
|
if (legacy)
|
||||||
|
tty_free_termios(tty);
|
||||||
err_deinit_tty:
|
err_deinit_tty:
|
||||||
deinitialize_tty_struct(o_tty);
|
deinitialize_tty_struct(o_tty);
|
||||||
module_put(o_tty->driver->owner);
|
module_put(o_tty->driver->owner);
|
||||||
err_free_tty:
|
err_free_tty:
|
||||||
|
kfree(ports[0]);
|
||||||
|
kfree(ports[1]);
|
||||||
free_tty_struct(o_tty);
|
free_tty_struct(o_tty);
|
||||||
|
err:
|
||||||
return retval;
|
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,
|
static int pty_bsd_ioctl(struct tty_struct *tty,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@ -366,7 +417,9 @@ static const struct tty_operations master_pty_ops_bsd = {
|
|||||||
.unthrottle = pty_unthrottle,
|
.unthrottle = pty_unthrottle,
|
||||||
.set_termios = pty_set_termios,
|
.set_termios = pty_set_termios,
|
||||||
.ioctl = pty_bsd_ioctl,
|
.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 = {
|
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,
|
.chars_in_buffer = pty_chars_in_buffer,
|
||||||
.unthrottle = pty_unthrottle,
|
.unthrottle = pty_unthrottle,
|
||||||
.set_termios = pty_set_termios,
|
.set_termios = pty_set_termios,
|
||||||
.resize = pty_resize
|
.cleanup = pty_cleanup,
|
||||||
|
.resize = pty_resize,
|
||||||
|
.remove = pty_remove
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init legacy_pty_init(void)
|
static void __init legacy_pty_init(void)
|
||||||
@ -389,12 +444,18 @@ static void __init legacy_pty_init(void)
|
|||||||
if (legacy_count <= 0)
|
if (legacy_count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pty_driver = alloc_tty_driver(legacy_count);
|
pty_driver = tty_alloc_driver(legacy_count,
|
||||||
if (!pty_driver)
|
TTY_DRIVER_RESET_TERMIOS |
|
||||||
|
TTY_DRIVER_REAL_RAW |
|
||||||
|
TTY_DRIVER_DYNAMIC_ALLOC);
|
||||||
|
if (IS_ERR(pty_driver))
|
||||||
panic("Couldn't allocate pty driver");
|
panic("Couldn't allocate pty driver");
|
||||||
|
|
||||||
pty_slave_driver = alloc_tty_driver(legacy_count);
|
pty_slave_driver = tty_alloc_driver(legacy_count,
|
||||||
if (!pty_slave_driver)
|
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");
|
panic("Couldn't allocate pty slave driver");
|
||||||
|
|
||||||
pty_driver->driver_name = "pty_master";
|
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_lflag = 0;
|
||||||
pty_driver->init_termios.c_ispeed = 38400;
|
pty_driver->init_termios.c_ispeed = 38400;
|
||||||
pty_driver->init_termios.c_ospeed = 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;
|
pty_driver->other = pty_slave_driver;
|
||||||
tty_set_operations(pty_driver, &master_pty_ops_bsd);
|
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_cflag = B38400 | CS8 | CREAD;
|
||||||
pty_slave_driver->init_termios.c_ispeed = 38400;
|
pty_slave_driver->init_termios.c_ispeed = 38400;
|
||||||
pty_slave_driver->init_termios.c_ospeed = 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;
|
pty_slave_driver->other = pty_driver;
|
||||||
tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
|
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;
|
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
|
/* We have no need to install and remove our tty objects as devpts does all
|
||||||
the work for us */
|
the work for us */
|
||||||
|
|
||||||
static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
|
static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct tty_struct *o_tty;
|
return pty_common_install(driver, tty, false);
|
||||||
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)
|
static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct tty_operations ptm_unix98_ops = {
|
static const struct tty_operations ptm_unix98_ops = {
|
||||||
.lookup = ptm_unix98_lookup,
|
.lookup = ptm_unix98_lookup,
|
||||||
.install = pty_unix98_install,
|
.install = pty_unix98_install,
|
||||||
.remove = ptm_unix98_remove,
|
.remove = pty_unix98_remove,
|
||||||
.open = pty_open,
|
.open = pty_open,
|
||||||
.close = pty_close,
|
.close = pty_close,
|
||||||
.write = pty_write,
|
.write = pty_write,
|
||||||
@ -578,14 +580,14 @@ static const struct tty_operations ptm_unix98_ops = {
|
|||||||
.unthrottle = pty_unthrottle,
|
.unthrottle = pty_unthrottle,
|
||||||
.set_termios = pty_set_termios,
|
.set_termios = pty_set_termios,
|
||||||
.ioctl = pty_unix98_ioctl,
|
.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 = {
|
static const struct tty_operations pty_unix98_ops = {
|
||||||
.lookup = pts_unix98_lookup,
|
.lookup = pts_unix98_lookup,
|
||||||
.install = pty_unix98_install,
|
.install = pty_unix98_install,
|
||||||
.remove = pts_unix98_remove,
|
.remove = pty_unix98_remove,
|
||||||
.open = pty_open,
|
.open = pty_open,
|
||||||
.close = pty_close,
|
.close = pty_close,
|
||||||
.write = pty_write,
|
.write = pty_write,
|
||||||
@ -594,7 +596,7 @@ static const struct tty_operations pty_unix98_ops = {
|
|||||||
.chars_in_buffer = pty_chars_in_buffer,
|
.chars_in_buffer = pty_chars_in_buffer,
|
||||||
.unthrottle = pty_unthrottle,
|
.unthrottle = pty_unthrottle,
|
||||||
.set_termios = pty_set_termios,
|
.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;
|
return retval;
|
||||||
|
|
||||||
/* find a device that is not in use. */
|
/* find a device that is not in use. */
|
||||||
tty_lock();
|
mutex_lock(&devpts_mutex);
|
||||||
index = devpts_new_index(inode);
|
index = devpts_new_index(inode);
|
||||||
tty_unlock();
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
retval = index;
|
retval = index;
|
||||||
goto err_file;
|
goto err_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&tty_mutex);
|
|
||||||
mutex_lock(&devpts_mutex);
|
|
||||||
tty = tty_init_dev(ptm_driver, index);
|
|
||||||
mutex_unlock(&devpts_mutex);
|
mutex_unlock(&devpts_mutex);
|
||||||
tty_lock();
|
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_lock(&tty_mutex);
|
||||||
|
tty = tty_init_dev(ptm_driver, index);
|
||||||
|
|
||||||
if (IS_ERR(tty)) {
|
if (IS_ERR(tty)) {
|
||||||
retval = PTR_ERR(tty);
|
retval = PTR_ERR(tty);
|
||||||
goto out;
|
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 */
|
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
|
||||||
|
|
||||||
tty_add_file(tty, filp);
|
tty_add_file(tty, filp);
|
||||||
@ -654,16 +657,17 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
|||||||
if (retval)
|
if (retval)
|
||||||
goto err_release;
|
goto err_release;
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return 0;
|
return 0;
|
||||||
err_release:
|
err_release:
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
tty_release(inode, filp);
|
tty_release(inode, filp);
|
||||||
return retval;
|
return retval;
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&tty_mutex);
|
||||||
devpts_kill_index(inode, index);
|
devpts_kill_index(inode, index);
|
||||||
tty_unlock();
|
|
||||||
err_file:
|
err_file:
|
||||||
|
mutex_unlock(&devpts_mutex);
|
||||||
tty_free_file(filp);
|
tty_free_file(filp);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -672,11 +676,21 @@ static struct file_operations ptmx_fops;
|
|||||||
|
|
||||||
static void __init unix98_pty_init(void)
|
static void __init unix98_pty_init(void)
|
||||||
{
|
{
|
||||||
ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
|
ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
|
||||||
if (!ptm_driver)
|
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");
|
panic("Couldn't allocate Unix98 ptm driver");
|
||||||
pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
|
pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
|
||||||
if (!pts_driver)
|
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");
|
panic("Couldn't allocate Unix98 pts driver");
|
||||||
|
|
||||||
ptm_driver->driver_name = "pty_master";
|
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_lflag = 0;
|
||||||
ptm_driver->init_termios.c_ispeed = 38400;
|
ptm_driver->init_termios.c_ispeed = 38400;
|
||||||
ptm_driver->init_termios.c_ospeed = 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;
|
ptm_driver->other = pts_driver;
|
||||||
tty_set_operations(ptm_driver, &ptm_unix98_ops);
|
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_cflag = B38400 | CS8 | CREAD;
|
||||||
pts_driver->init_termios.c_ispeed = 38400;
|
pts_driver->init_termios.c_ispeed = 38400;
|
||||||
pts_driver->init_termios.c_ospeed = 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;
|
pts_driver->other = ptm_driver;
|
||||||
tty_set_operations(pts_driver, &pty_unix98_ops);
|
tty_set_operations(pts_driver, &pty_unix98_ops);
|
||||||
|
|
||||||
|
@ -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);
|
spin_lock_init(&info->slock);
|
||||||
mutex_init(&info->write_mtx);
|
mutex_init(&info->write_mtx);
|
||||||
rp_table[line] = info;
|
rp_table[line] = info;
|
||||||
tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
|
tty_port_register_device(&info->port, rocket_driver, line,
|
||||||
NULL);
|
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;
|
unsigned rocketMode;
|
||||||
int bits, baud, divisor;
|
int bits, baud, divisor;
|
||||||
CHANNEL_t *cp;
|
CHANNEL_t *cp;
|
||||||
struct ktermios *t = tty->termios;
|
struct ktermios *t = &tty->termios;
|
||||||
|
|
||||||
cp = &info->channel;
|
cp = &info->channel;
|
||||||
cflag = t->c_cflag;
|
cflag = t->c_cflag;
|
||||||
@ -978,7 +978,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
|
|||||||
tty->alt_speed = 460800;
|
tty->alt_speed = 460800;
|
||||||
|
|
||||||
configure_r_port(tty, info, NULL);
|
configure_r_port(tty, info, NULL);
|
||||||
if (tty->termios->c_cflag & CBAUD) {
|
if (tty->termios.c_cflag & CBAUD) {
|
||||||
sSetDTR(cp);
|
sSetDTR(cp);
|
||||||
sSetRTS(cp);
|
sSetRTS(cp);
|
||||||
}
|
}
|
||||||
@ -1089,35 +1089,35 @@ static void rp_set_termios(struct tty_struct *tty,
|
|||||||
if (rocket_paranoia_check(info, "rp_set_termios"))
|
if (rocket_paranoia_check(info, "rp_set_termios"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This driver doesn't support CS5 or CS6
|
* This driver doesn't support CS5 or CS6
|
||||||
*/
|
*/
|
||||||
if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
|
if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
|
||||||
tty->termios->c_cflag =
|
tty->termios.c_cflag =
|
||||||
((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
|
((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
|
||||||
/* Or CMSPAR */
|
/* Or CMSPAR */
|
||||||
tty->termios->c_cflag &= ~CMSPAR;
|
tty->termios.c_cflag &= ~CMSPAR;
|
||||||
|
|
||||||
configure_r_port(tty, info, old_termios);
|
configure_r_port(tty, info, old_termios);
|
||||||
|
|
||||||
cp = &info->channel;
|
cp = &info->channel;
|
||||||
|
|
||||||
/* Handle transition to B0 status */
|
/* 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);
|
sClrDTR(cp);
|
||||||
sClrRTS(cp);
|
sClrRTS(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle transition away from B0 status */
|
/* Handle transition away from B0 status */
|
||||||
if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
|
if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) {
|
||||||
if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
|
if (!tty->hw_stopped || !(tty->termios.c_cflag & CRTSCTS))
|
||||||
sSetRTS(cp);
|
sSetRTS(cp);
|
||||||
sSetDTR(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;
|
tty->hw_stopped = 0;
|
||||||
rp_start(tty);
|
rp_start(tty);
|
||||||
}
|
}
|
||||||
|
@ -515,7 +515,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty)
|
|||||||
unsigned cflag;
|
unsigned cflag;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios.c_cflag;
|
||||||
if (!(port = info->port))
|
if (!(port = info->port))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -617,7 +617,7 @@ static void rs_set_ldisc(struct tty_struct *tty)
|
|||||||
if (serial_paranoia_check(info, tty->name, "rs_set_ldisc"))
|
if (serial_paranoia_check(info, tty->name, "rs_set_ldisc"))
|
||||||
return;
|
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");
|
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);
|
change_speed(info, tty);
|
||||||
|
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
rs_start(tty);
|
rs_start(tty);
|
||||||
}
|
}
|
||||||
@ -1070,7 +1070,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
|
|||||||
if (tty->ldisc.close)
|
if (tty->ldisc.close)
|
||||||
(tty->ldisc.close)(tty);
|
(tty->ldisc.close)(tty);
|
||||||
tty->ldisc = ldiscs[N_TTY];
|
tty->ldisc = ldiscs[N_TTY];
|
||||||
tty->termios->c_line = N_TTY;
|
tty->termios.c_line = N_TTY;
|
||||||
if (tty->ldisc.open)
|
if (tty->ldisc.open)
|
||||||
(tty->ldisc.open)(tty);
|
(tty->ldisc.open)(tty);
|
||||||
}
|
}
|
||||||
@ -1189,12 +1189,6 @@ rs68328_init(void)
|
|||||||
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
serial_driver->flags = TTY_DRIVER_REAL_RAW;
|
||||||
tty_set_operations(serial_driver, &rs_ops);
|
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);
|
local_irq_save(flags);
|
||||||
|
|
||||||
for(i=0;i<NR_PORTS;i++) {
|
for(i=0;i<NR_PORTS;i++) {
|
||||||
@ -1224,8 +1218,17 @@ rs68328_init(void)
|
|||||||
0,
|
0,
|
||||||
"M68328_UART", info))
|
"M68328_UART", info))
|
||||||
panic("Unable to attach 68328 serial interrupt\n");
|
panic("Unable to attach 68328 serial interrupt\n");
|
||||||
|
|
||||||
|
tty_port_link_device(&info->tport, serial_driver, i);
|
||||||
}
|
}
|
||||||
local_irq_restore(flags);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2202,6 +2202,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||||||
unsigned char cval, fcr = 0;
|
unsigned char cval, fcr = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int baud, quot;
|
unsigned int baud, quot;
|
||||||
|
int fifo_bug = 0;
|
||||||
|
|
||||||
switch (termios->c_cflag & CSIZE) {
|
switch (termios->c_cflag & CSIZE) {
|
||||||
case CS5:
|
case CS5:
|
||||||
@ -2221,8 +2222,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||||||
|
|
||||||
if (termios->c_cflag & CSTOPB)
|
if (termios->c_cflag & CSTOPB)
|
||||||
cval |= UART_LCR_STOP;
|
cval |= UART_LCR_STOP;
|
||||||
if (termios->c_cflag & PARENB)
|
if (termios->c_cflag & PARENB) {
|
||||||
cval |= UART_LCR_PARITY;
|
cval |= UART_LCR_PARITY;
|
||||||
|
if (up->bugs & UART_BUG_PARITY)
|
||||||
|
fifo_bug = 1;
|
||||||
|
}
|
||||||
if (!(termios->c_cflag & PARODD))
|
if (!(termios->c_cflag & PARODD))
|
||||||
cval |= UART_LCR_EPAR;
|
cval |= UART_LCR_EPAR;
|
||||||
#ifdef CMSPAR
|
#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) {
|
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
|
||||||
fcr = uart_config[port->type].fcr;
|
fcr = uart_config[port->type].fcr;
|
||||||
if (baud < 2400) {
|
if (baud < 2400 || fifo_bug) {
|
||||||
fcr &= ~UART_FCR_TRIGGER_MASK;
|
fcr &= ~UART_FCR_TRIGGER_MASK;
|
||||||
fcr |= UART_FCR_TRIGGER_1;
|
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);
|
serial_port_out(port, UART_EFR, efr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_OMAP
|
#ifdef CONFIG_ARCH_OMAP1
|
||||||
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
|
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
|
||||||
if (cpu_is_omap1510() && is_omap_port(up)) {
|
if (cpu_is_omap1510() && is_omap_port(up)) {
|
||||||
if (baud == 115200) {
|
if (baud == 115200) {
|
||||||
@ -2426,7 +2430,7 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
|
|||||||
{
|
{
|
||||||
if (pt->port.iotype == UPIO_AU)
|
if (pt->port.iotype == UPIO_AU)
|
||||||
return 0x1000;
|
return 0x1000;
|
||||||
#ifdef CONFIG_ARCH_OMAP
|
#ifdef CONFIG_ARCH_OMAP1
|
||||||
if (is_omap_port(pt))
|
if (is_omap_port(pt))
|
||||||
return 0x16 << pt->port.regshift;
|
return 0x16 << pt->port.regshift;
|
||||||
#endif
|
#endif
|
||||||
@ -2979,36 +2983,36 @@ void serial8250_resume_port(int line)
|
|||||||
static int __devinit serial8250_probe(struct platform_device *dev)
|
static int __devinit serial8250_probe(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
struct plat_serial8250_port *p = dev->dev.platform_data;
|
struct plat_serial8250_port *p = dev->dev.platform_data;
|
||||||
struct uart_port port;
|
struct uart_8250_port uart;
|
||||||
int ret, i, irqflag = 0;
|
int ret, i, irqflag = 0;
|
||||||
|
|
||||||
memset(&port, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
|
|
||||||
if (share_irqs)
|
if (share_irqs)
|
||||||
irqflag = IRQF_SHARED;
|
irqflag = IRQF_SHARED;
|
||||||
|
|
||||||
for (i = 0; p && p->flags != 0; p++, i++) {
|
for (i = 0; p && p->flags != 0; p++, i++) {
|
||||||
port.iobase = p->iobase;
|
uart.port.iobase = p->iobase;
|
||||||
port.membase = p->membase;
|
uart.port.membase = p->membase;
|
||||||
port.irq = p->irq;
|
uart.port.irq = p->irq;
|
||||||
port.irqflags = p->irqflags;
|
uart.port.irqflags = p->irqflags;
|
||||||
port.uartclk = p->uartclk;
|
uart.port.uartclk = p->uartclk;
|
||||||
port.regshift = p->regshift;
|
uart.port.regshift = p->regshift;
|
||||||
port.iotype = p->iotype;
|
uart.port.iotype = p->iotype;
|
||||||
port.flags = p->flags;
|
uart.port.flags = p->flags;
|
||||||
port.mapbase = p->mapbase;
|
uart.port.mapbase = p->mapbase;
|
||||||
port.hub6 = p->hub6;
|
uart.port.hub6 = p->hub6;
|
||||||
port.private_data = p->private_data;
|
uart.port.private_data = p->private_data;
|
||||||
port.type = p->type;
|
uart.port.type = p->type;
|
||||||
port.serial_in = p->serial_in;
|
uart.port.serial_in = p->serial_in;
|
||||||
port.serial_out = p->serial_out;
|
uart.port.serial_out = p->serial_out;
|
||||||
port.handle_irq = p->handle_irq;
|
uart.port.handle_irq = p->handle_irq;
|
||||||
port.handle_break = p->handle_break;
|
uart.port.handle_break = p->handle_break;
|
||||||
port.set_termios = p->set_termios;
|
uart.port.set_termios = p->set_termios;
|
||||||
port.pm = p->pm;
|
uart.port.pm = p->pm;
|
||||||
port.dev = &dev->dev;
|
uart.port.dev = &dev->dev;
|
||||||
port.irqflags |= irqflag;
|
uart.port.irqflags |= irqflag;
|
||||||
ret = serial8250_register_port(&port);
|
ret = serial8250_register_8250_port(&uart);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&dev->dev, "unable to register port at index %d "
|
dev_err(&dev->dev, "unable to register port at index %d "
|
||||||
"(IO%lx MEM%llx IRQ%d): %d\n", i,
|
"(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;
|
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
|
* 16x50 serial ports to be configured at run-time, to support PCMCIA
|
||||||
* modems and PCI multiport cards.
|
* 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.regshift = up->port.regshift;
|
||||||
uart->port.iotype = up->port.iotype;
|
uart->port.iotype = up->port.iotype;
|
||||||
uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
|
uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
|
||||||
|
uart->bugs = up->bugs;
|
||||||
uart->port.mapbase = up->port.mapbase;
|
uart->port.mapbase = up->port.mapbase;
|
||||||
uart->port.private_data = up->port.private_data;
|
uart->port.private_data = up->port.private_data;
|
||||||
if (up->port.dev)
|
if (up->port.dev)
|
||||||
@ -3197,29 +3202,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(serial8250_register_8250_port);
|
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
|
* serial8250_unregister_port - remove a 16x50 serial port at runtime
|
||||||
* @line: serial line number
|
* @line: serial line number
|
||||||
|
@ -13,36 +13,6 @@
|
|||||||
|
|
||||||
#include <linux/serial_8250.h>
|
#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 {
|
struct old_serial_port {
|
||||||
unsigned int uart;
|
unsigned int uart;
|
||||||
unsigned int baud_base;
|
unsigned int baud_base;
|
||||||
@ -56,9 +26,6 @@ struct old_serial_port {
|
|||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* This replaces serial_uart_config in include/linux/serial.h
|
|
||||||
*/
|
|
||||||
struct serial8250_config {
|
struct serial8250_config {
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned short fifo_size;
|
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_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_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
|
||||||
#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
|
#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_RSA (1 << 0)
|
||||||
#define PROBE_ANY (~0)
|
#define PROBE_ANY (~0)
|
||||||
|
@ -43,7 +43,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
|
|||||||
{
|
{
|
||||||
struct serial_card_info *info;
|
struct serial_card_info *info;
|
||||||
struct serial_card_type *type = id->data;
|
struct serial_card_type *type = id->data;
|
||||||
struct uart_port port;
|
struct uart_8250_port uart;
|
||||||
unsigned long bus_addr;
|
unsigned long bus_addr;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -62,19 +62,19 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
|
|||||||
|
|
||||||
ecard_set_drvdata(ec, info);
|
ecard_set_drvdata(ec, info);
|
||||||
|
|
||||||
memset(&port, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(struct uart_8250_port));
|
||||||
port.irq = ec->irq;
|
uart.port.irq = ec->irq;
|
||||||
port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
|
uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
|
||||||
port.uartclk = type->uartclk;
|
uart.port.uartclk = type->uartclk;
|
||||||
port.iotype = UPIO_MEM;
|
uart.port.iotype = UPIO_MEM;
|
||||||
port.regshift = 2;
|
uart.port.regshift = 2;
|
||||||
port.dev = &ec->dev;
|
uart.port.dev = &ec->dev;
|
||||||
|
|
||||||
for (i = 0; i < info->num_ports; i ++) {
|
for (i = 0; i < info->num_ports; i ++) {
|
||||||
port.membase = info->vaddr + type->offset[i];
|
uart.port.membase = info->vaddr + type->offset[i];
|
||||||
port.mapbase = bus_addr + 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;
|
return 0;
|
||||||
|
@ -89,7 +89,7 @@ static int dw8250_handle_irq(struct uart_port *p)
|
|||||||
|
|
||||||
static int __devinit dw8250_probe(struct platform_device *pdev)
|
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 *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||||
struct device_node *np = pdev->dev.of_node;
|
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);
|
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
port.private_data = data;
|
uart.port.private_data = data;
|
||||||
|
|
||||||
spin_lock_init(&port.lock);
|
spin_lock_init(&uart.port.lock);
|
||||||
port.mapbase = regs->start;
|
uart.port.mapbase = regs->start;
|
||||||
port.irq = irq->start;
|
uart.port.irq = irq->start;
|
||||||
port.handle_irq = dw8250_handle_irq;
|
uart.port.handle_irq = dw8250_handle_irq;
|
||||||
port.type = PORT_8250;
|
uart.port.type = PORT_8250;
|
||||||
port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
|
uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
|
||||||
UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||||
port.dev = &pdev->dev;
|
uart.port.dev = &pdev->dev;
|
||||||
|
|
||||||
port.iotype = UPIO_MEM;
|
uart.port.iotype = UPIO_MEM;
|
||||||
port.serial_in = dw8250_serial_in;
|
uart.port.serial_in = dw8250_serial_in;
|
||||||
port.serial_out = dw8250_serial_out;
|
uart.port.serial_out = dw8250_serial_out;
|
||||||
if (!of_property_read_u32(np, "reg-io-width", &val)) {
|
if (!of_property_read_u32(np, "reg-io-width", &val)) {
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 1:
|
case 1:
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
port.iotype = UPIO_MEM32;
|
uart.port.iotype = UPIO_MEM32;
|
||||||
port.serial_in = dw8250_serial_in32;
|
uart.port.serial_in = dw8250_serial_in32;
|
||||||
port.serial_out = dw8250_serial_out32;
|
uart.port.serial_out = dw8250_serial_out32;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
|
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))
|
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)) {
|
if (of_property_read_u32(np, "clock-frequency", &val)) {
|
||||||
dev_err(&pdev->dev, "no clock-frequency property set\n");
|
dev_err(&pdev->dev, "no clock-frequency property set\n");
|
||||||
return -EINVAL;
|
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)
|
if (data->line < 0)
|
||||||
return data->line;
|
return data->line;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
static int __init serial_init_chip(struct parisc_device *dev)
|
static int __init serial_init_chip(struct parisc_device *dev)
|
||||||
{
|
{
|
||||||
struct uart_port port;
|
struct uart_8250_port uart;
|
||||||
unsigned long address;
|
unsigned long address;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -48,21 +48,21 @@ static int __init serial_init_chip(struct parisc_device *dev)
|
|||||||
if (dev->id.sversion != 0x8d)
|
if (dev->id.sversion != 0x8d)
|
||||||
address += 0x800;
|
address += 0x800;
|
||||||
|
|
||||||
memset(&port, 0, sizeof(port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
port.iotype = UPIO_MEM;
|
uart.port.iotype = UPIO_MEM;
|
||||||
/* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
|
/* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
|
||||||
port.uartclk = 7272727;
|
uart.port.uartclk = 7272727;
|
||||||
port.mapbase = address;
|
uart.port.mapbase = address;
|
||||||
port.membase = ioremap_nocache(address, 16);
|
uart.port.membase = ioremap_nocache(address, 16);
|
||||||
port.irq = dev->irq;
|
uart.port.irq = dev->irq;
|
||||||
port.flags = UPF_BOOT_AUTOCONF;
|
uart.port.flags = UPF_BOOT_AUTOCONF;
|
||||||
port.dev = &dev->dev;
|
uart.port.dev = &dev->dev;
|
||||||
|
|
||||||
err = serial8250_register_port(&port);
|
err = serial8250_register_8250_port(&uart);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"serial8250_register_port returned error %d\n", err);
|
"serial8250_register_8250_port returned error %d\n", err);
|
||||||
iounmap(port.membase);
|
iounmap(uart.port.membase);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
memset(&port, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
|
|
||||||
/* Memory mapped I/O */
|
/* Memory mapped I/O */
|
||||||
port.iotype = UPIO_MEM;
|
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.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
|
||||||
port.regshift = 1;
|
port.regshift = 1;
|
||||||
port.dev = &d->dev;
|
port.dev = &d->dev;
|
||||||
line = serial8250_register_port(&port);
|
line = serial8250_register_8250_port(&uart);
|
||||||
|
|
||||||
if (line < 0) {
|
if (line < 0) {
|
||||||
printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
|
printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
|
||||||
@ -210,7 +210,7 @@ static int __init hp300_8250_init(void)
|
|||||||
#ifdef CONFIG_HPAPCI
|
#ifdef CONFIG_HPAPCI
|
||||||
int line;
|
int line;
|
||||||
unsigned long base;
|
unsigned long base;
|
||||||
struct uart_port uport;
|
struct uart_8250_port uart;
|
||||||
struct hp300_port *port;
|
struct hp300_port *port;
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
@ -248,26 +248,26 @@ static int __init hp300_8250_init(void)
|
|||||||
if (!port)
|
if (!port)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
memset(&uport, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
|
|
||||||
base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
|
base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
|
||||||
|
|
||||||
/* Memory mapped I/O */
|
/* Memory mapped I/O */
|
||||||
uport.iotype = UPIO_MEM;
|
uart.port.iotype = UPIO_MEM;
|
||||||
uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
|
uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
|
||||||
| UPF_BOOT_AUTOCONF;
|
| UPF_BOOT_AUTOCONF;
|
||||||
/* XXX - no interrupt support yet */
|
/* XXX - no interrupt support yet */
|
||||||
uport.irq = 0;
|
uart.port.irq = 0;
|
||||||
uport.uartclk = HPAPCI_BAUD_BASE * 16;
|
uart.port.uartclk = HPAPCI_BAUD_BASE * 16;
|
||||||
uport.mapbase = base;
|
uart.port.mapbase = base;
|
||||||
uport.membase = (char *)(base + DIO_VIRADDRBASE);
|
uart.port.membase = (char *)(base + DIO_VIRADDRBASE);
|
||||||
uport.regshift = 2;
|
uart.port.regshift = 2;
|
||||||
|
|
||||||
line = serial8250_register_port(&uport);
|
line = serial8250_register_8250_port(&uart);
|
||||||
|
|
||||||
if (line < 0) {
|
if (line < 0) {
|
||||||
printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
|
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);
|
kfree(port);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ struct pci_serial_quirk {
|
|||||||
int (*init)(struct pci_dev *dev);
|
int (*init)(struct pci_dev *dev);
|
||||||
int (*setup)(struct serial_private *,
|
int (*setup)(struct serial_private *,
|
||||||
const struct pciserial_board *,
|
const struct pciserial_board *,
|
||||||
struct uart_port *, int);
|
struct uart_8250_port *, int);
|
||||||
void (*exit)(struct pci_dev *dev);
|
void (*exit)(struct pci_dev *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ struct serial_private {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int pci_default_setup(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)
|
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
|
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)
|
int bar, int offset, int regshift)
|
||||||
{
|
{
|
||||||
struct pci_dev *dev = priv->dev;
|
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])
|
if (!priv->remapped_bar[bar])
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
port->iotype = UPIO_MEM;
|
port->port.iotype = UPIO_MEM;
|
||||||
port->iobase = 0;
|
port->port.iobase = 0;
|
||||||
port->mapbase = base + offset;
|
port->port.mapbase = base + offset;
|
||||||
port->membase = priv->remapped_bar[bar] + offset;
|
port->port.membase = priv->remapped_bar[bar] + offset;
|
||||||
port->regshift = regshift;
|
port->port.regshift = regshift;
|
||||||
} else {
|
} else {
|
||||||
port->iotype = UPIO_PORT;
|
port->port.iotype = UPIO_PORT;
|
||||||
port->iobase = base + offset;
|
port->port.iobase = base + offset;
|
||||||
port->mapbase = 0;
|
port->port.mapbase = 0;
|
||||||
port->membase = NULL;
|
port->port.membase = NULL;
|
||||||
port->regshift = 0;
|
port->port.regshift = 0;
|
||||||
}
|
}
|
||||||
return 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,
|
static int addidata_apci7800_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
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;
|
unsigned int bar = 0, offset = board->first_offset;
|
||||||
bar = FL_GET_BASE(board->flags);
|
bar = FL_GET_BASE(board->flags);
|
||||||
@ -140,7 +140,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
|
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;
|
unsigned int bar, offset = board->first_offset;
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ static int pci_hp_diva_init(struct pci_dev *dev)
|
|||||||
static int
|
static int
|
||||||
pci_hp_diva_setup(struct serial_private *priv,
|
pci_hp_diva_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
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 offset = board->first_offset;
|
||||||
unsigned int bar = FL_GET_BASE(board->flags);
|
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 */
|
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
|
||||||
static int
|
static int
|
||||||
sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
|
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;
|
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,
|
static int pci_siig_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
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;
|
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
|
static int
|
||||||
pci_timedia_setup(struct serial_private *priv,
|
pci_timedia_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
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;
|
unsigned int bar = 0, offset = board->first_offset;
|
||||||
|
|
||||||
@ -653,7 +653,7 @@ pci_timedia_setup(struct serial_private *priv,
|
|||||||
static int
|
static int
|
||||||
titan_400l_800l_setup(struct serial_private *priv,
|
titan_400l_800l_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
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;
|
unsigned int bar, offset = board->first_offset;
|
||||||
|
|
||||||
@ -754,7 +754,7 @@ static int pci_ni8430_init(struct pci_dev *dev)
|
|||||||
static int
|
static int
|
||||||
pci_ni8430_setup(struct serial_private *priv,
|
pci_ni8430_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
{
|
{
|
||||||
void __iomem *p;
|
void __iomem *p;
|
||||||
unsigned long base, len;
|
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,
|
static int pci_netmos_9900_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
{
|
{
|
||||||
unsigned int bar;
|
unsigned int bar;
|
||||||
|
|
||||||
@ -1032,10 +1032,17 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
|
|||||||
return number_uarts;
|
return number_uarts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int pci_asix_setup(struct serial_private *priv,
|
||||||
pci_default_setup(struct serial_private *priv,
|
|
||||||
const struct pciserial_board *board,
|
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;
|
unsigned int bar, offset = board->first_offset, maxnr;
|
||||||
|
|
||||||
@ -1057,15 +1064,15 @@ pci_default_setup(struct serial_private *priv,
|
|||||||
static int
|
static int
|
||||||
ce4100_serial_setup(struct serial_private *priv,
|
ce4100_serial_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setup_port(priv, port, 0, 0, board->reg_shift);
|
ret = setup_port(priv, port, 0, 0, board->reg_shift);
|
||||||
port->iotype = UPIO_MEM32;
|
port->port.iotype = UPIO_MEM32;
|
||||||
port->type = PORT_XSCALE;
|
port->port.type = PORT_XSCALE;
|
||||||
port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
|
port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
|
||||||
port->regshift = 2;
|
port->port.regshift = 2;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1073,16 +1080,16 @@ ce4100_serial_setup(struct serial_private *priv,
|
|||||||
static int
|
static int
|
||||||
pci_omegapci_setup(struct serial_private *priv,
|
pci_omegapci_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
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);
|
return setup_port(priv, port, 2, idx * 8, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int skip_tx_en_setup(struct serial_private *priv,
|
static int skip_tx_en_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
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 "
|
printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
|
||||||
"[%04x:%04x] subsystem [%04x:%04x]\n",
|
"[%04x:%04x] subsystem [%04x:%04x]\n",
|
||||||
priv->dev->vendor,
|
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,
|
static int kt_serial_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
{
|
{
|
||||||
port->flags |= UPF_BUG_THRE;
|
port->port.flags |= UPF_BUG_THRE;
|
||||||
port->serial_in = kt_serial_in;
|
port->port.serial_in = kt_serial_in;
|
||||||
port->handle_break = kt_handle_break;
|
port->port.handle_break = kt_handle_break;
|
||||||
return skip_tx_en_setup(priv, board, port, idx);
|
return skip_tx_en_setup(priv, board, port, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1151,9 +1158,19 @@ static int pci_eg20t_init(struct pci_dev *dev)
|
|||||||
static int
|
static int
|
||||||
pci_xr17c154_setup(struct serial_private *priv,
|
pci_xr17c154_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
{
|
{
|
||||||
port->flags |= UPF_EXAR_EFR;
|
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->port.flags |= UPF_FIXED_TYPE;
|
||||||
|
port->port.type = PORT_16550A;
|
||||||
return pci_default_setup(priv, board, port, idx);
|
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 PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
|
||||||
#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
|
#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
|
||||||
#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
|
#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 */
|
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
|
||||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
||||||
@ -1726,7 +1750,41 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|||||||
.subvendor = PCI_ANY_ID,
|
.subvendor = PCI_ANY_ID,
|
||||||
.subdevice = PCI_ANY_ID,
|
.subdevice = PCI_ANY_ID,
|
||||||
.setup = pci_omegapci_setup,
|
.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
|
* Default "match everything" terminator entry
|
||||||
*/
|
*/
|
||||||
@ -1887,7 +1945,6 @@ enum pci_board_num_t {
|
|||||||
pbn_panacom,
|
pbn_panacom,
|
||||||
pbn_panacom2,
|
pbn_panacom2,
|
||||||
pbn_panacom4,
|
pbn_panacom4,
|
||||||
pbn_exsys_4055,
|
|
||||||
pbn_plx_romulus,
|
pbn_plx_romulus,
|
||||||
pbn_oxsemi,
|
pbn_oxsemi,
|
||||||
pbn_oxsemi_1_4000000,
|
pbn_oxsemi_1_4000000,
|
||||||
@ -2393,13 +2450,6 @@ static struct pciserial_board pci_boards[] __devinitdata = {
|
|||||||
.reg_shift = 7,
|
.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 */
|
/* I think this entry is broken - the first_offset looks wrong --rmk */
|
||||||
[pbn_plx_romulus] = {
|
[pbn_plx_romulus] = {
|
||||||
.flags = FL_BASE2,
|
.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(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
|
||||||
{ PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
|
{ PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
|
||||||
{ PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
|
{ 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
|
static int __devinit
|
||||||
serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
|
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;
|
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
|
* 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;
|
for (bldev = blacklist;
|
||||||
blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
|
bldev < blacklist + ARRAY_SIZE(blacklist);
|
||||||
blacklist++) {
|
bldev++) {
|
||||||
if (dev->vendor == blacklist->vendor &&
|
if (dev->vendor == bldev->vendor &&
|
||||||
dev->device == blacklist->device)
|
dev->device == bldev->device)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2728,7 +2782,7 @@ serial_pci_matches(const struct pciserial_board *board,
|
|||||||
struct serial_private *
|
struct serial_private *
|
||||||
pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
|
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 serial_private *priv;
|
||||||
struct pci_serial_quirk *quirk;
|
struct pci_serial_quirk *quirk;
|
||||||
int rc, nr_ports, i;
|
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->dev = dev;
|
||||||
priv->quirk = quirk;
|
priv->quirk = quirk;
|
||||||
|
|
||||||
memset(&serial_port, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
|
uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
|
||||||
serial_port.uartclk = board->base_baud * 16;
|
uart.port.uartclk = board->base_baud * 16;
|
||||||
serial_port.irq = get_pci_irq(dev, board);
|
uart.port.irq = get_pci_irq(dev, board);
|
||||||
serial_port.dev = &dev->dev;
|
uart.port.dev = &dev->dev;
|
||||||
|
|
||||||
for (i = 0; i < nr_ports; i++) {
|
for (i = 0; i < nr_ports; i++) {
|
||||||
if (quirk->setup(priv, board, &serial_port, i))
|
if (quirk->setup(priv, board, &uart, i))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef SERIAL_DEBUG_PCI
|
#ifdef SERIAL_DEBUG_PCI
|
||||||
printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
|
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
|
#endif
|
||||||
|
|
||||||
priv->line[i] = serial8250_register_port(&serial_port);
|
priv->line[i] = serial8250_register_8250_port(&uart);
|
||||||
if (priv->line[i] < 0) {
|
if (priv->line[i] < 0) {
|
||||||
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
|
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
|
||||||
break;
|
break;
|
||||||
@ -3193,7 +3247,7 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|||||||
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
||||||
PCI_SUBVENDOR_ID_EXSYS,
|
PCI_SUBVENDOR_ID_EXSYS,
|
||||||
PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
|
PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
|
||||||
pbn_exsys_4055 },
|
pbn_b2_4_115200 },
|
||||||
/*
|
/*
|
||||||
* Megawolf Romulus PCI Serial Card, from Mike Hudson
|
* Megawolf Romulus PCI Serial Card, from Mike Hudson
|
||||||
* (Exoray@isys.ca)
|
* (Exoray@isys.ca)
|
||||||
@ -4178,6 +4232,25 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||||
pbn_omegapci },
|
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,
|
* These entries match devices with class COMMUNICATION_SERIAL,
|
||||||
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
|
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
|
||||||
|
@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
|
|||||||
static int __devinit
|
static int __devinit
|
||||||
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
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;
|
int ret, line, flags = dev_id->driver_data;
|
||||||
|
|
||||||
if (flags & UNKNOWN_DEV) {
|
if (flags & UNKNOWN_DEV) {
|
||||||
@ -433,32 +433,32 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&port, 0, sizeof(struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
if (pnp_irq_valid(dev, 0))
|
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)) {
|
if (pnp_port_valid(dev, 0)) {
|
||||||
port.iobase = pnp_port_start(dev, 0);
|
uart.port.iobase = pnp_port_start(dev, 0);
|
||||||
port.iotype = UPIO_PORT;
|
uart.port.iotype = UPIO_PORT;
|
||||||
} else if (pnp_mem_valid(dev, 0)) {
|
} else if (pnp_mem_valid(dev, 0)) {
|
||||||
port.mapbase = pnp_mem_start(dev, 0);
|
uart.port.mapbase = pnp_mem_start(dev, 0);
|
||||||
port.iotype = UPIO_MEM;
|
uart.port.iotype = UPIO_MEM;
|
||||||
port.flags = UPF_IOREMAP;
|
uart.port.flags = UPF_IOREMAP;
|
||||||
} else
|
} else
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
#ifdef SERIAL_DEBUG_PNP
|
#ifdef SERIAL_DEBUG_PNP
|
||||||
printk(KERN_DEBUG
|
printk(KERN_DEBUG
|
||||||
"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
|
"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
|
#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)
|
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
|
||||||
port.flags |= UPF_SHARE_IRQ;
|
uart.port.flags |= UPF_SHARE_IRQ;
|
||||||
port.uartclk = 1843200;
|
uart.port.uartclk = 1843200;
|
||||||
port.dev = &dev->dev;
|
uart.port.dev = &dev->dev;
|
||||||
|
|
||||||
line = serial8250_register_port(&port);
|
line = serial8250_register_8250_port(&uart);
|
||||||
if (line < 0)
|
if (line < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ struct serial_quirk {
|
|||||||
unsigned int prodid;
|
unsigned int prodid;
|
||||||
int multi; /* 1 = multifunction, > 1 = # ports */
|
int multi; /* 1 = multifunction, > 1 = # ports */
|
||||||
void (*config)(struct pcmcia_device *);
|
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 *);
|
void (*wakeup)(struct pcmcia_device *);
|
||||||
int (*post)(struct pcmcia_device *);
|
int (*post)(struct pcmcia_device *);
|
||||||
};
|
};
|
||||||
@ -105,9 +105,9 @@ struct serial_cfg_mem {
|
|||||||
* Elan VPU16551 UART with 14.7456MHz oscillator
|
* Elan VPU16551 UART with 14.7456MHz oscillator
|
||||||
* manfid 0x015D, 0x4C45
|
* 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)
|
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,
|
static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
|
||||||
unsigned int iobase, int irq)
|
unsigned int iobase, int irq)
|
||||||
{
|
{
|
||||||
struct uart_port port;
|
struct uart_8250_port uart;
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
memset(&port, 0, sizeof (struct uart_port));
|
memset(&uart, 0, sizeof(uart));
|
||||||
port.iobase = iobase;
|
uart.port.iobase = iobase;
|
||||||
port.irq = irq;
|
uart.port.irq = irq;
|
||||||
port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
|
uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
|
||||||
port.uartclk = 1843200;
|
uart.port.uartclk = 1843200;
|
||||||
port.dev = &handle->dev;
|
uart.port.dev = &handle->dev;
|
||||||
if (buggy_uart)
|
if (buggy_uart)
|
||||||
port.flags |= UPF_BUGGY_UART;
|
uart.port.flags |= UPF_BUGGY_UART;
|
||||||
|
|
||||||
if (info->quirk && info->quirk->setup)
|
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) {
|
if (line < 0) {
|
||||||
printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
|
pr_err("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n",
|
||||||
"0x%04lx, irq %d failed\n", (u_long)iobase, irq);
|
(unsigned long)iobase, irq);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,12 +257,19 @@ config SERIAL_MAX3100
|
|||||||
help
|
help
|
||||||
MAX3100 chip support
|
MAX3100 chip support
|
||||||
|
|
||||||
config SERIAL_MAX3107
|
config SERIAL_MAX310X
|
||||||
tristate "MAX3107 support"
|
bool "MAX310X support"
|
||||||
depends on SPI
|
depends on SPI
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
|
select REGMAP_SPI if SPI
|
||||||
|
default n
|
||||||
help
|
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
|
config SERIAL_DZ
|
||||||
bool "DECstation DZ serial driver"
|
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
|
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.
|
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
|
config SERIAL_CORE
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
@ -1104,6 +1130,24 @@ config SERIAL_SC26XX_CONSOLE
|
|||||||
help
|
help
|
||||||
Support for Console on SC2681/SC2692 serial ports.
|
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
|
config SERIAL_BFIN_SPORT
|
||||||
tristate "Blackfin SPORT emulate UART"
|
tristate "Blackfin SPORT emulate UART"
|
||||||
depends on BLACKFIN
|
depends on BLACKFIN
|
||||||
|
@ -28,12 +28,13 @@ obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o
|
|||||||
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
|
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
|
||||||
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
|
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
|
||||||
obj-$(CONFIG_SERIAL_MAX3100) += max3100.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_IP22_ZILOG) += ip22zilog.o
|
||||||
obj-$(CONFIG_SERIAL_MUX) += mux.o
|
obj-$(CONFIG_SERIAL_MUX) += mux.o
|
||||||
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
|
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
|
||||||
obj-$(CONFIG_SERIAL_MCF) += mcf.o
|
obj-$(CONFIG_SERIAL_MCF) += mcf.o
|
||||||
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.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_DZ) += dz.o
|
||||||
obj-$(CONFIG_SERIAL_ZS) += zs.o
|
obj-$(CONFIG_SERIAL_ZS) += zs.o
|
||||||
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.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_SERIAL_SB1250_DUART) += sb1250-duart.o
|
||||||
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
|
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
|
||||||
obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
|
obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
|
||||||
|
obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
|
||||||
obj-$(CONFIG_SERIAL_JSM) += jsm/
|
obj-$(CONFIG_SERIAL_JSM) += jsm/
|
||||||
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
|
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
|
||||||
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
|
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
|
||||||
|
@ -591,7 +591,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
|
|||||||
port->ops = &altera_uart_ops;
|
port->ops = &altera_uart_ops;
|
||||||
port->flags = UPF_BOOT_AUTOCONF;
|
port->flags = UPF_BOOT_AUTOCONF;
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, port);
|
platform_set_drvdata(pdev, port);
|
||||||
|
|
||||||
uart_add_one_port(&altera_uart_driver, 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)
|
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) {
|
if (port) {
|
||||||
uart_remove_one_port(&altera_uart_driver, port);
|
uart_remove_one_port(&altera_uart_driver, port);
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
port->mapbase = 0;
|
port->mapbase = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,16 +312,12 @@ static int pl010_startup(struct uart_port *port)
|
|||||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = clk_prepare(uap->clk);
|
|
||||||
if (retval)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to enable the clock producer.
|
* Try to enable the clock producer.
|
||||||
*/
|
*/
|
||||||
retval = clk_enable(uap->clk);
|
retval = clk_prepare_enable(uap->clk);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto clk_unprep;
|
goto out;
|
||||||
|
|
||||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||||
|
|
||||||
@ -346,9 +342,7 @@ static int pl010_startup(struct uart_port *port)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
clk_dis:
|
clk_dis:
|
||||||
clk_disable(uap->clk);
|
clk_disable_unprepare(uap->clk);
|
||||||
clk_unprep:
|
|
||||||
clk_unprepare(uap->clk);
|
|
||||||
out:
|
out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -375,8 +369,7 @@ static void pl010_shutdown(struct uart_port *port)
|
|||||||
/*
|
/*
|
||||||
* Shut down the clock producer
|
* Shut down the clock producer
|
||||||
*/
|
*/
|
||||||
clk_disable(uap->clk);
|
clk_disable_unprepare(uap->clk);
|
||||||
clk_unprepare(uap->clk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -52,6 +52,8 @@
|
|||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/pinctrl/consumer.h>
|
#include <linux/pinctrl/consumer.h>
|
||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
@ -75,7 +77,6 @@ struct vendor_data {
|
|||||||
unsigned int lcrh_tx;
|
unsigned int lcrh_tx;
|
||||||
unsigned int lcrh_rx;
|
unsigned int lcrh_rx;
|
||||||
bool oversampling;
|
bool oversampling;
|
||||||
bool interrupt_may_hang; /* vendor-specific */
|
|
||||||
bool dma_threshold;
|
bool dma_threshold;
|
||||||
bool cts_event_workaround;
|
bool cts_event_workaround;
|
||||||
};
|
};
|
||||||
@ -96,7 +97,6 @@ static struct vendor_data vendor_st = {
|
|||||||
.lcrh_tx = ST_UART011_LCRH_TX,
|
.lcrh_tx = ST_UART011_LCRH_TX,
|
||||||
.lcrh_rx = ST_UART011_LCRH_RX,
|
.lcrh_rx = ST_UART011_LCRH_RX,
|
||||||
.oversampling = true,
|
.oversampling = true,
|
||||||
.interrupt_may_hang = true,
|
|
||||||
.dma_threshold = true,
|
.dma_threshold = true,
|
||||||
.cts_event_workaround = true,
|
.cts_event_workaround = true,
|
||||||
};
|
};
|
||||||
@ -147,7 +147,6 @@ struct uart_amba_port {
|
|||||||
unsigned int old_cr; /* state during shutdown */
|
unsigned int old_cr; /* state during shutdown */
|
||||||
bool autorts;
|
bool autorts;
|
||||||
char type[12];
|
char type[12];
|
||||||
bool interrupt_may_hang; /* vendor-specific */
|
|
||||||
#ifdef CONFIG_DMA_ENGINE
|
#ifdef CONFIG_DMA_ENGINE
|
||||||
/* DMA stuff */
|
/* DMA stuff */
|
||||||
bool using_tx_dma;
|
bool using_tx_dma;
|
||||||
@ -1215,14 +1214,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
|
|||||||
return IRQ_RETVAL(handled);
|
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;
|
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||||
unsigned int status = readw(uap->port.membase + UART01x_FR);
|
unsigned int status = readw(uap->port.membase + UART01x_FR);
|
||||||
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
|
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;
|
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||||
unsigned int result = 0;
|
unsigned int result = 0;
|
||||||
@ -1285,7 +1284,7 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#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;
|
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
@ -1297,7 +1296,7 @@ static int pl010_get_poll_char(struct uart_port *port)
|
|||||||
return readw(uap->port.membase + UART01x_DR);
|
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)
|
unsigned char ch)
|
||||||
{
|
{
|
||||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
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");
|
"could not set default pins\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = clk_prepare(uap->clk);
|
|
||||||
if (retval)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to enable the clock producer.
|
* Try to enable the clock producer.
|
||||||
*/
|
*/
|
||||||
retval = clk_enable(uap->clk);
|
retval = clk_prepare_enable(uap->clk);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto clk_unprep;
|
goto out;
|
||||||
|
|
||||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||||
|
|
||||||
@ -1411,9 +1406,7 @@ static int pl011_startup(struct uart_port *port)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
clk_dis:
|
clk_dis:
|
||||||
clk_disable(uap->clk);
|
clk_disable_unprepare(uap->clk);
|
||||||
clk_unprep:
|
|
||||||
clk_unprepare(uap->clk);
|
|
||||||
out:
|
out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -1473,8 +1466,7 @@ static void pl011_shutdown(struct uart_port *port)
|
|||||||
/*
|
/*
|
||||||
* Shut down the clock producer
|
* Shut down the clock producer
|
||||||
*/
|
*/
|
||||||
clk_disable(uap->clk);
|
clk_disable_unprepare(uap->clk);
|
||||||
clk_unprepare(uap->clk);
|
|
||||||
/* Optionally let pins go into sleep states */
|
/* Optionally let pins go into sleep states */
|
||||||
if (!IS_ERR(uap->pins_sleep)) {
|
if (!IS_ERR(uap->pins_sleep)) {
|
||||||
retval = pinctrl_select_state(uap->pinctrl, 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'
|
* 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);
|
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'
|
* 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")
|
return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")
|
||||||
!= NULL ? 0 : -EBUSY;
|
!= NULL ? 0 : -EBUSY;
|
||||||
@ -1654,18 +1646,18 @@ static int pl010_request_port(struct uart_port *port)
|
|||||||
/*
|
/*
|
||||||
* Configure/autoconfigure the 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) {
|
if (flags & UART_CONFIG_TYPE) {
|
||||||
port->type = PORT_AMBA;
|
port->type = PORT_AMBA;
|
||||||
pl010_request_port(port);
|
pl011_request_port(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* verify the new serial_struct (for TIOCSSERIAL).
|
* 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;
|
int ret = 0;
|
||||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
|
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 = {
|
static struct uart_ops amba_pl011_pops = {
|
||||||
.tx_empty = pl01x_tx_empty,
|
.tx_empty = pl011_tx_empty,
|
||||||
.set_mctrl = pl011_set_mctrl,
|
.set_mctrl = pl011_set_mctrl,
|
||||||
.get_mctrl = pl01x_get_mctrl,
|
.get_mctrl = pl011_get_mctrl,
|
||||||
.stop_tx = pl011_stop_tx,
|
.stop_tx = pl011_stop_tx,
|
||||||
.start_tx = pl011_start_tx,
|
.start_tx = pl011_start_tx,
|
||||||
.stop_rx = pl011_stop_rx,
|
.stop_rx = pl011_stop_rx,
|
||||||
@ -1691,13 +1683,13 @@ static struct uart_ops amba_pl011_pops = {
|
|||||||
.flush_buffer = pl011_dma_flush_buffer,
|
.flush_buffer = pl011_dma_flush_buffer,
|
||||||
.set_termios = pl011_set_termios,
|
.set_termios = pl011_set_termios,
|
||||||
.type = pl011_type,
|
.type = pl011_type,
|
||||||
.release_port = pl010_release_port,
|
.release_port = pl011_release_port,
|
||||||
.request_port = pl010_request_port,
|
.request_port = pl011_request_port,
|
||||||
.config_port = pl010_config_port,
|
.config_port = pl011_config_port,
|
||||||
.verify_port = pl010_verify_port,
|
.verify_port = pl011_verify_port,
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
.poll_get_char = pl010_get_poll_char,
|
.poll_get_char = pl011_get_poll_char,
|
||||||
.poll_put_char = pl010_put_poll_char,
|
.poll_put_char = pl011_put_poll_char,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1869,6 +1861,38 @@ static struct uart_driver amba_reg = {
|
|||||||
.cons = AMBA_CONSOLE,
|
.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)
|
static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||||
{
|
{
|
||||||
struct uart_amba_port *uap;
|
struct uart_amba_port *uap;
|
||||||
@ -1891,6 +1915,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i = pl011_probe_dt_alias(i, &dev->dev);
|
||||||
|
|
||||||
base = ioremap(dev->res.start, resource_size(&dev->res));
|
base = ioremap(dev->res.start, resource_size(&dev->res));
|
||||||
if (!base) {
|
if (!base) {
|
||||||
ret = -ENOMEM;
|
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->lcrh_tx = vendor->lcrh_tx;
|
||||||
uap->old_cr = 0;
|
uap->old_cr = 0;
|
||||||
uap->fifosize = vendor->fifosize;
|
uap->fifosize = vendor->fifosize;
|
||||||
uap->interrupt_may_hang = vendor->interrupt_may_hang;
|
|
||||||
uap->port.dev = &dev->dev;
|
uap->port.dev = &dev->dev;
|
||||||
uap->port.mapbase = dev->res.start;
|
uap->port.mapbase = dev->res.start;
|
||||||
uap->port.membase = base;
|
uap->port.membase = base;
|
||||||
|
@ -182,7 +182,7 @@ static void bfin_serial_start_tx(struct uart_port *port)
|
|||||||
* To avoid losting RX interrupt, we reset IR function
|
* To avoid losting RX interrupt, we reset IR function
|
||||||
* before sending data.
|
* before sending data.
|
||||||
*/
|
*/
|
||||||
if (tty->termios->c_line == N_IRDA)
|
if (tty->termios.c_line == N_IRDA)
|
||||||
bfin_serial_reset_irda(port);
|
bfin_serial_reset_irda(port);
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_DMA
|
#ifdef CONFIG_SERIAL_BFIN_DMA
|
||||||
|
@ -955,7 +955,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] =
|
|||||||
/* Calculate the chartime depending on baudrate, numbor of bits etc. */
|
/* Calculate the chartime depending on baudrate, numbor of bits etc. */
|
||||||
static void update_char_time(struct e100_serial * info)
|
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;
|
int bits;
|
||||||
|
|
||||||
/* calc. number of bits / data byte */
|
/* calc. number of bits / data byte */
|
||||||
@ -1473,7 +1473,7 @@ rs_stop(struct tty_struct *tty)
|
|||||||
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char,
|
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char,
|
||||||
STOP_CHAR(info->port.tty));
|
STOP_CHAR(info->port.tty));
|
||||||
xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop);
|
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);
|
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)));
|
info->xmit.tail,SERIAL_XMIT_SIZE)));
|
||||||
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty));
|
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty));
|
||||||
xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
|
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);
|
xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2929,7 +2929,7 @@ shutdown(struct e100_serial * info)
|
|||||||
descr[i].buf = 0;
|
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 */
|
/* hang up DTR and RTS if HUPCL is enabled */
|
||||||
e100_dtr(info, 0);
|
e100_dtr(info, 0);
|
||||||
e100_rts(info, 0); /* could check CRTSCTS before doing this */
|
e100_rts(info, 0); /* could check CRTSCTS before doing this */
|
||||||
@ -2953,12 +2953,12 @@ change_speed(struct e100_serial *info)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
/* first some safety checks */
|
/* first some safety checks */
|
||||||
|
|
||||||
if (!info->port.tty || !info->port.tty->termios)
|
if (!info->port.tty)
|
||||||
return;
|
return;
|
||||||
if (!info->ioport)
|
if (!info->ioport)
|
||||||
return;
|
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 */
|
/* 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;
|
info->ioport[REG_REC_CTRL] = info->rx_ctrl;
|
||||||
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty));
|
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty));
|
||||||
xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
|
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",
|
DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n",
|
||||||
STOP_CHAR(info->port.tty)));
|
STOP_CHAR(info->port.tty)));
|
||||||
xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
|
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)));
|
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 */
|
/* 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 */
|
/* Turn off RTS line */
|
||||||
e100_rts(info, 0);
|
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 ldisc %d\n", tty->ldisc.chars_in_buffer(tty)));
|
||||||
DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count));
|
DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count));
|
||||||
/* Do RTS before XOFF since XOFF might take some time */
|
/* 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 */
|
/* Assert RTS line */
|
||||||
e100_rts(info, 1);
|
e100_rts(info, 1);
|
||||||
}
|
}
|
||||||
@ -3748,7 +3748,7 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
|
|||||||
|
|
||||||
/* Handle turning off CRTSCTS */
|
/* Handle turning off CRTSCTS */
|
||||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
rs_start(tty);
|
rs_start(tty);
|
||||||
}
|
}
|
||||||
@ -3815,7 +3815,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
|
|||||||
* separate termios for callout and dialin.
|
* separate termios for callout and dialin.
|
||||||
*/
|
*/
|
||||||
if (info->flags & ASYNC_NORMAL_ACTIVE)
|
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
|
* Now we wait for the transmit buffer to clear; and we notify
|
||||||
* the line discipline to only process XON/XOFF characters.
|
* 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) ||
|
if (tty_hung_up_p(filp) ||
|
||||||
(info->flags & ASYNC_CLOSING)) {
|
(info->flags & ASYNC_CLOSING)) {
|
||||||
wait_event_interruptible_tty(info->close_wait,
|
wait_event_interruptible_tty(tty, info->close_wait,
|
||||||
!(info->flags & ASYNC_CLOSING));
|
!(info->flags & ASYNC_CLOSING));
|
||||||
#ifdef SERIAL_DO_RESTART
|
#ifdef SERIAL_DO_RESTART
|
||||||
if (info->flags & ASYNC_HUP_NOTIFY)
|
if (info->flags & ASYNC_HUP_NOTIFY)
|
||||||
@ -3998,7 +3998,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->termios->c_cflag & CLOCAL) {
|
if (tty->termios.c_cflag & CLOCAL) {
|
||||||
do_clocal = 1;
|
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",
|
printk("block_til_ready blocking: ttyS%d, count = %d\n",
|
||||||
info->line, info->count);
|
info->line, info->count);
|
||||||
#endif
|
#endif
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&info->open_wait, &wait);
|
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) ||
|
if (tty_hung_up_p(filp) ||
|
||||||
(info->flags & ASYNC_CLOSING)) {
|
(info->flags & ASYNC_CLOSING)) {
|
||||||
wait_event_interruptible_tty(info->close_wait,
|
wait_event_interruptible_tty(tty, info->close_wait,
|
||||||
!(info->flags & ASYNC_CLOSING));
|
!(info->flags & ASYNC_CLOSING));
|
||||||
#ifdef SERIAL_DO_RESTART
|
#ifdef SERIAL_DO_RESTART
|
||||||
return ((info->flags & ASYNC_HUP_NOTIFY) ?
|
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)) {
|
if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
|
||||||
*tty->termios = info->normal_termios;
|
tty->termios = info->normal_termios;
|
||||||
change_speed(info);
|
change_speed(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4443,14 +4443,12 @@ static int __init rs_init(void)
|
|||||||
B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
|
B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
|
||||||
driver->init_termios.c_ispeed = 115200;
|
driver->init_termios.c_ispeed = 115200;
|
||||||
driver->init_termios.c_ospeed = 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);
|
tty_set_operations(driver, &rs_ops);
|
||||||
serial_driver = driver;
|
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++) {
|
for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
|
||||||
if (info->enabled) {
|
if (info->enabled) {
|
||||||
if (cris_request_io_interface(info->io_if,
|
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",
|
printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n",
|
||||||
serial_driver->name, info->line, info->ioport);
|
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_FAST_TIMER
|
||||||
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
|
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
|
||||||
memset(fast_timers, 0, sizeof(fast_timers));
|
memset(fast_timers, 0, sizeof(fast_timers));
|
||||||
|
@ -800,8 +800,8 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
|
|||||||
tty_port_init(pport);
|
tty_port_init(pport);
|
||||||
pport->ops = &ifx_tty_port_ops;
|
pport->ops = &ifx_tty_port_ops;
|
||||||
ifx_dev->minor = IFX_SPI_TTY_ID;
|
ifx_dev->minor = IFX_SPI_TTY_ID;
|
||||||
ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor,
|
ifx_dev->tty_dev = tty_port_register_device(pport, tty_drv,
|
||||||
&ifx_dev->spi_dev->dev);
|
ifx_dev->minor, &ifx_dev->spi_dev->dev);
|
||||||
if (IS_ERR(ifx_dev->tty_dev)) {
|
if (IS_ERR(ifx_dev->tty_dev)) {
|
||||||
dev_dbg(&ifx_dev->spi_dev->dev,
|
dev_dbg(&ifx_dev->spi_dev->dev,
|
||||||
"%s: registering tty device failed", __func__);
|
"%s: registering tty device failed", __func__);
|
||||||
|
@ -206,7 +206,7 @@ struct imx_port {
|
|||||||
unsigned short trcv_delay; /* transceiver delay */
|
unsigned short trcv_delay; /* transceiver delay */
|
||||||
struct clk *clk_ipg;
|
struct clk *clk_ipg;
|
||||||
struct clk *clk_per;
|
struct clk *clk_per;
|
||||||
struct imx_uart_data *devdata;
|
const struct imx_uart_data *devdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct imx_port_ucrs {
|
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);
|
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
||||||
if (IS_ERR(pinctrl)) {
|
if (IS_ERR(pinctrl)) {
|
||||||
ret = PTR_ERR(pinctrl);
|
ret = PTR_ERR(pinctrl);
|
||||||
|
dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret);
|
||||||
goto unmap;
|
goto unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||||
if (IS_ERR(sport->clk_ipg)) {
|
if (IS_ERR(sport->clk_ipg)) {
|
||||||
ret = PTR_ERR(sport->clk_ipg);
|
ret = PTR_ERR(sport->clk_ipg);
|
||||||
|
dev_err(&pdev->dev, "failed to get ipg clk: %d\n", ret);
|
||||||
goto unmap;
|
goto unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
sport->clk_per = devm_clk_get(&pdev->dev, "per");
|
sport->clk_per = devm_clk_get(&pdev->dev, "per");
|
||||||
if (IS_ERR(sport->clk_per)) {
|
if (IS_ERR(sport->clk_per)) {
|
||||||
ret = PTR_ERR(sport->clk_per);
|
ret = PTR_ERR(sport->clk_per);
|
||||||
|
dev_err(&pdev->dev, "failed to get per clk: %d\n", ret);
|
||||||
goto unmap;
|
goto unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 ioc3_port *port = get_ioc3_port(the_port);
|
||||||
struct ring *inring;
|
struct ring *inring;
|
||||||
struct ring_entry *entry;
|
struct ring_entry *entry;
|
||||||
struct port_hooks *hooks = port->ip_hooks;
|
struct port_hooks *hooks;
|
||||||
int byte_num;
|
int byte_num;
|
||||||
char *sc;
|
char *sc;
|
||||||
int loop_counter;
|
int loop_counter;
|
||||||
|
|
||||||
BUG_ON(!(len >= 0));
|
BUG_ON(!(len >= 0));
|
||||||
BUG_ON(!port);
|
BUG_ON(!port);
|
||||||
|
hooks = port->ip_hooks;
|
||||||
|
|
||||||
/* There is a nasty timing issue in the IOC3. When the rx_timer
|
/* There is a nasty timing issue in the IOC3. When the rx_timer
|
||||||
* expires or the rx_high condition arises, we take an interrupt.
|
* expires or the rx_high condition arises, we take an interrupt.
|
||||||
|
@ -1803,7 +1803,7 @@ static inline int ic4_startup_local(struct uart_port *the_port)
|
|||||||
ioc4_set_proto(port, the_port->mapbase);
|
ioc4_set_proto(port, the_port->mapbase);
|
||||||
|
|
||||||
/* set the speed of the serial port */
|
/* 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);
|
(struct ktermios *)0);
|
||||||
|
|
||||||
return 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 ioc4_port *port = get_ioc4_port(the_port, 0);
|
||||||
struct ring *inring;
|
struct ring *inring;
|
||||||
struct ring_entry *entry;
|
struct ring_entry *entry;
|
||||||
struct hooks *hooks = port->ip_hooks;
|
struct hooks *hooks;
|
||||||
int byte_num;
|
int byte_num;
|
||||||
char *sc;
|
char *sc;
|
||||||
int loop_counter;
|
int loop_counter;
|
||||||
|
|
||||||
BUG_ON(!(len >= 0));
|
BUG_ON(!(len >= 0));
|
||||||
BUG_ON(!port);
|
BUG_ON(!port);
|
||||||
|
hooks = port->ip_hooks;
|
||||||
|
|
||||||
/* There is a nasty timing issue in the IOC4. When the rx_timer
|
/* There is a nasty timing issue in the IOC4. When the rx_timer
|
||||||
* expires or the rx_high condition arises, we take an interrupt.
|
* expires or the rx_high condition arises, we take an interrupt.
|
||||||
|
@ -161,7 +161,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch)
|
|||||||
struct ktermios *termios;
|
struct ktermios *termios;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, lock_flags);
|
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])
|
if (ch == termios->c_cc[VSTART])
|
||||||
channel->ch_bd->bd_ops->send_start_character(channel);
|
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_cached_lsr = 0;
|
||||||
channel->ch_stops_sent = 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_cflag = termios->c_cflag;
|
||||||
channel->ch_c_iflag = termios->c_iflag;
|
channel->ch_c_iflag = termios->c_iflag;
|
||||||
channel->ch_c_oflag = termios->c_oflag;
|
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");
|
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
|
||||||
|
|
||||||
bd = channel->ch_bd;
|
bd = channel->ch_bd;
|
||||||
ts = port->state->port.tty->termios;
|
ts = &port->state->port.tty->termios;
|
||||||
|
|
||||||
channel->ch_flags &= ~(CH_STOPI);
|
channel->ch_flags &= ~(CH_STOPI);
|
||||||
|
|
||||||
@ -567,7 +567,7 @@ void jsm_input(struct jsm_channel *ch)
|
|||||||
*input data and return immediately.
|
*input data and return immediately.
|
||||||
*/
|
*/
|
||||||
if (!tp ||
|
if (!tp ||
|
||||||
!(tp->termios->c_cflag & CREAD) ) {
|
!(tp->termios.c_cflag & CREAD) ) {
|
||||||
|
|
||||||
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
|
||||||
"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
|
"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
|
||||||
|
823
drivers/tty/serial/lpc32xx_hs.c
Normal file
823
drivers/tty/serial/lpc32xx_hs.c
Normal file
@ -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");
|
@ -44,8 +44,6 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/irq.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
|
#define BAUD_RATE 115200
|
||||||
|
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
@ -132,22 +130,6 @@ struct irq_info {
|
|||||||
|
|
||||||
static struct irq_info irq_lists[NR_IRQS];
|
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
|
#ifdef CONFIG_SERIAL_M32R_PLDSIO
|
||||||
|
|
||||||
#define __sio_in(x) inw((unsigned long)(x))
|
#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);
|
spin_lock_irqsave(&up->port.lock, flags);
|
||||||
|
|
||||||
up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1);
|
up->port.fifosize = 1;
|
||||||
up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
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
|
static int
|
||||||
m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
|
m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||||
{
|
{
|
||||||
if (ser->irq >= nr_irqs || ser->irq < 0 ||
|
if (ser->irq >= nr_irqs || ser->irq < 0 || ser->baud_base < 9600)
|
||||||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
|
|
||||||
ser->type >= ARRAY_SIZE(uart_config))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
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 = {
|
static struct uart_ops m32r_sio_pops = {
|
||||||
.tx_empty = m32r_sio_tx_empty,
|
.tx_empty = m32r_sio_tx_empty,
|
||||||
.set_mctrl = m32r_sio_set_mctrl,
|
.set_mctrl = m32r_sio_set_mctrl,
|
||||||
@ -946,7 +915,6 @@ static struct uart_ops m32r_sio_pops = {
|
|||||||
.shutdown = m32r_sio_shutdown,
|
.shutdown = m32r_sio_shutdown,
|
||||||
.set_termios = m32r_sio_set_termios,
|
.set_termios = m32r_sio_set_termios,
|
||||||
.pm = m32r_sio_pm,
|
.pm = m32r_sio_pm,
|
||||||
.type = m32r_sio_type,
|
|
||||||
.release_port = m32r_sio_release_port,
|
.release_port = m32r_sio_release_port,
|
||||||
.request_port = m32r_sio_request_port,
|
.request_port = m32r_sio_request_port,
|
||||||
.config_port = m32r_sio_config_port,
|
.config_port = m32r_sio_config_port,
|
||||||
|
@ -910,17 +910,7 @@ static struct spi_driver max3100_driver = {
|
|||||||
.resume = max3100_resume,
|
.resume = max3100_resume,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init max3100_init(void)
|
module_spi_driver(max3100_driver);
|
||||||
{
|
|
||||||
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_DESCRIPTION("MAX3100 driver");
|
MODULE_DESCRIPTION("MAX3100 driver");
|
||||||
MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
|
MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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
drivers/tty/serial/max310x.c
Normal file
1260
drivers/tty/serial/max310x.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -775,11 +775,15 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (new->c_cflag & PARENB) {
|
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) ?
|
mr1 |= (new->c_cflag & PARODD) ?
|
||||||
MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
|
MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
|
||||||
} else
|
} else {
|
||||||
mr1 |= MPC52xx_PSC_MODE_PARNONE;
|
mr1 |= MPC52xx_PSC_MODE_PARNONE;
|
||||||
|
}
|
||||||
|
|
||||||
mr2 = 0;
|
mr2 = 0;
|
||||||
|
|
||||||
|
@ -896,7 +896,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(msm_port->clk);
|
return PTR_ERR(msm_port->clk);
|
||||||
|
|
||||||
if (msm_port->is_uartdm)
|
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);
|
port->uartclk = clk_get_rate(msm_port->clk);
|
||||||
printk(KERN_INFO "uartclk = %d\n", port->uartclk);
|
printk(KERN_INFO "uartclk = %d\n", port->uartclk);
|
||||||
|
@ -223,9 +223,11 @@ static int __init smd_tty_init(void)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for (i = 0; i < smd_tty_channels_len; i++) {
|
for (i = 0; i < smd_tty_channels_len; i++) {
|
||||||
tty_port_init(&smd_tty[smd_tty_channels[i].id].port);
|
struct tty_port *port = &smd_tty[smd_tty_channels[i].id].port;
|
||||||
smd_tty[smd_tty_channels[i].id].port.ops = &smd_tty_port_ops;
|
tty_port_init(port);
|
||||||
tty_register_device(smd_tty_driver, smd_tty_channels[i].id, 0);
|
port->ops = &smd_tty_port_ops;
|
||||||
|
tty_port_register_device(port, smd_tty_driver,
|
||||||
|
smd_tty_channels[i].id, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -262,7 +262,7 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
|
|||||||
|
|
||||||
ctrl &= ~AUART_CTRL2_RTSEN;
|
ctrl &= ~AUART_CTRL2_RTSEN;
|
||||||
if (mctrl & TIOCM_RTS) {
|
if (mctrl & TIOCM_RTS) {
|
||||||
if (u->state->port.flags & ASYNC_CTS_FLOW)
|
if (tty_port_cts_enabled(&u->state->port))
|
||||||
ctrl |= AUART_CTRL2_RTSEN;
|
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_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,
|
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
|
||||||
u->membase + AUART_INTR_CLR);
|
u->membase + AUART_INTR_CLR);
|
||||||
|
|
||||||
|
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
|
||||||
|
|
||||||
clk_disable_unprepare(s->clk);
|
clk_disable_unprepare(s->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,6 +796,7 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
auart_port[pdev->id] = NULL;
|
auart_port[pdev->id] = NULL;
|
||||||
|
|
||||||
|
put_device(s->dev);
|
||||||
clk_put(s->clk);
|
clk_put(s->clk);
|
||||||
free_irq(s->irq, s);
|
free_irq(s->irq, s);
|
||||||
kfree(s);
|
kfree(s);
|
||||||
|
@ -105,6 +105,10 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
|
|||||||
port->uartclk = clk;
|
port->uartclk = clk;
|
||||||
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
|
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
|
||||||
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||||
|
|
||||||
|
if (of_find_property(np, "no-loopback-test", NULL))
|
||||||
|
port->flags |= UPF_SKIP_TEST;
|
||||||
|
|
||||||
port->dev = &ofdev->dev;
|
port->dev = &ofdev->dev;
|
||||||
|
|
||||||
if (type == PORT_TEGRA)
|
if (type == PORT_TEGRA)
|
||||||
@ -144,8 +148,15 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
|
|||||||
switch (port_type) {
|
switch (port_type) {
|
||||||
#ifdef CONFIG_SERIAL_8250
|
#ifdef CONFIG_SERIAL_8250
|
||||||
case PORT_8250 ... PORT_MAX_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;
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
|
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
|
||||||
case PORT_NWPSERIAL:
|
case PORT_NWPSERIAL:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -979,6 +979,10 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
|
|||||||
priv->tx_dma_use = 1;
|
priv->tx_dma_use = 1;
|
||||||
|
|
||||||
priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
|
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_init_table(priv->sg_tx_p, num); /* Initialize SG table */
|
||||||
sg = priv->sg_tx_p;
|
sg = priv->sg_tx_p;
|
||||||
|
@ -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];
|
struct uart_pxa_port *up = serial_pxa_ports[co->index];
|
||||||
unsigned int ier;
|
unsigned int ier;
|
||||||
|
unsigned long flags;
|
||||||
|
int locked = 1;
|
||||||
|
|
||||||
clk_prepare_enable(up->clk);
|
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
|
* 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);
|
wait_for_xmitr(up);
|
||||||
serial_out(up, UART_IER, ier);
|
serial_out(up, UART_IER, ier);
|
||||||
|
|
||||||
|
if (locked)
|
||||||
|
spin_unlock(&up->port.lock);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
clk_disable_unprepare(up->clk);
|
clk_disable_unprepare(up->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
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");
|
dbg("break!\n");
|
||||||
port->icount.brk++;
|
port->icount.brk++;
|
||||||
if (uart_handle_break(port))
|
if (uart_handle_break(port))
|
||||||
goto ignore_char;
|
goto ignore_char;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uerstat & S3C2410_UERSTAT_FRAME)
|
if (uerstat & S3C2410_UERSTAT_FRAME)
|
||||||
@ -459,7 +459,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
|
|||||||
s3c24xx_serial_portname(port), ourport);
|
s3c24xx_serial_portname(port), ourport);
|
||||||
|
|
||||||
if (ret != 0) {
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +473,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
|
|||||||
s3c24xx_serial_portname(port), ourport);
|
s3c24xx_serial_portname(port), ourport);
|
||||||
|
|
||||||
if (ret) {
|
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;
|
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,
|
ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
|
||||||
s3c24xx_serial_portname(port), ourport);
|
s3c24xx_serial_portname(port), ourport);
|
||||||
if (ret) {
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
|||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case 3:
|
case 3:
|
||||||
if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
|
if (!IS_ERR(ourport->baudclk))
|
||||||
clk_disable(ourport->baudclk);
|
clk_disable(ourport->baudclk);
|
||||||
|
|
||||||
clk_disable(ourport->clk);
|
clk_disable(ourport->clk);
|
||||||
@ -538,12 +538,12 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
|||||||
case 0:
|
case 0:
|
||||||
clk_enable(ourport->clk);
|
clk_enable(ourport->clk);
|
||||||
|
|
||||||
if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
|
if (!IS_ERR(ourport->baudclk))
|
||||||
clk_enable(ourport->baudclk);
|
clk_enable(ourport->baudclk);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
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];
|
char clkname[MAX_CLK_NAME_LENGTH];
|
||||||
int calc_deviation, deviation = (1 << 30) - 1;
|
int calc_deviation, deviation = (1 << 30) - 1;
|
||||||
|
|
||||||
*best_clk = NULL;
|
|
||||||
clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
|
clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
|
||||||
ourport->info->def_clk_sel;
|
ourport->info->def_clk_sel;
|
||||||
for (cnt = 0; cnt < info->num_clks; cnt++) {
|
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);
|
sprintf(clkname, "clk_uart_baud%d", cnt);
|
||||||
clk = clk_get(ourport->port.dev, clkname);
|
clk = clk_get(ourport->port.dev, clkname);
|
||||||
if (IS_ERR_OR_NULL(clk))
|
if (IS_ERR(clk))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rate = clk_get_rate(clk);
|
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 s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
|
||||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||||
struct clk *clk = NULL;
|
struct clk *clk = ERR_PTR(-EINVAL);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int baud, quot, clk_sel = 0;
|
unsigned int baud, quot, clk_sel = 0;
|
||||||
unsigned int ulcon;
|
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);
|
quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
|
||||||
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
|
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
|
||||||
quot = port->custom_divisor;
|
quot = port->custom_divisor;
|
||||||
if (!clk)
|
if (IS_ERR(clk))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* check to see if we need to change clock source */
|
/* 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) {
|
if (ourport->baudclk != clk) {
|
||||||
s3c24xx_serial_setsource(port, clk_sel);
|
s3c24xx_serial_setsource(port, clk_sel);
|
||||||
|
|
||||||
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
|
if (!IS_ERR(ourport->baudclk)) {
|
||||||
clk_disable(ourport->baudclk);
|
clk_disable(ourport->baudclk);
|
||||||
ourport->baudclk = NULL;
|
ourport->baudclk = ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
clk_enable(clk);
|
clk_enable(clk);
|
||||||
@ -1036,10 +1035,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
|
|||||||
if (tty == NULL)
|
if (tty == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
termios = tty->termios;
|
termios = &tty->termios;
|
||||||
|
|
||||||
if (termios == NULL) {
|
if (termios == NULL) {
|
||||||
printk(KERN_WARNING "%s: no termios?\n", __func__);
|
dev_warn(uport->dev, "%s: no termios?\n", __func__);
|
||||||
goto exit;
|
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);
|
res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
|
||||||
if (res == NULL) {
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,7 +1129,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
|||||||
ourport->rx_irq = ret;
|
ourport->rx_irq = ret;
|
||||||
ourport->tx_irq = ret + 1;
|
ourport->tx_irq = ret + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = platform_get_irq(platdev, 1);
|
ret = platform_get_irq(platdev, 1);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
ourport->tx_irq = ret;
|
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 uart_port *port = s3c24xx_dev_to_port(dev);
|
||||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
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);
|
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;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ourport->baudclk = ERR_PTR(-EINVAL);
|
||||||
ourport->info = ourport->drv_data->info;
|
ourport->info = ourport->drv_data->info;
|
||||||
ourport->cfg = (pdev->dev.platform_data) ?
|
ourport->cfg = (pdev->dev.platform_data) ?
|
||||||
(struct s3c2410_uartcfg *)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);
|
sprintf(clk_name, "clk_uart_baud%d", clk_sel);
|
||||||
|
|
||||||
clk = clk_get(port->dev, clk_name);
|
clk = clk_get(port->dev, clk_name);
|
||||||
if (!IS_ERR(clk) && clk != NULL)
|
if (!IS_ERR(clk))
|
||||||
rate = clk_get_rate(clk);
|
rate = clk_get_rate(clk);
|
||||||
else
|
else
|
||||||
rate = 1;
|
rate = 1;
|
||||||
@ -1679,7 +1683,7 @@ static int __init s3c24xx_serial_modinit(void)
|
|||||||
|
|
||||||
ret = uart_register_driver(&s3c24xx_uart_drv);
|
ret = uart_register_driver(&s3c24xx_uart_drv);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "failed to register UART driver\n");
|
pr_err("Failed to register Samsung UART driver\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/irq.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)
|
#if defined(CONFIG_MAGIC_SYSRQ)
|
||||||
#define SUPPORT_SYSRQ
|
#define SUPPORT_SYSRQ
|
||||||
|
985
drivers/tty/serial/sccnxp.c
Normal file
985
drivers/tty/serial/sccnxp.c
Normal file
@ -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");
|
@ -159,7 +159,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
|
|||||||
retval = uport->ops->startup(uport);
|
retval = uport->ops->startup(uport);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
if (uart_console(uport) && uport->cons->cflag) {
|
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;
|
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
|
* Setup the RTS and DTR signals once the
|
||||||
* port is open and ready to respond.
|
* 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);
|
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);
|
spin_lock_irq(&uport->lock);
|
||||||
if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
|
if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
|
||||||
tty->hw_stopped = 1;
|
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.
|
* 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_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
||||||
|
|
||||||
uart_port_shutdown(port);
|
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,
|
* If we have no tty, termios, or the port does not exist,
|
||||||
* then we can't set the parameters for this port.
|
* 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;
|
return;
|
||||||
|
|
||||||
termios = tty->termios;
|
termios = &tty->termios;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set flags based on termios cflag
|
* Set flags based on termios cflag
|
||||||
@ -614,7 +614,7 @@ static void uart_throttle(struct tty_struct *tty)
|
|||||||
if (I_IXOFF(tty))
|
if (I_IXOFF(tty))
|
||||||
uart_send_xchar(tty, STOP_CHAR(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);
|
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));
|
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);
|
uart_set_mctrl(port, TIOCM_RTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_get_info(struct uart_state *state,
|
static void uart_get_info(struct tty_port *port,
|
||||||
struct serial_struct __user *retinfo)
|
struct uart_state *state,
|
||||||
|
struct serial_struct *retinfo)
|
||||||
{
|
{
|
||||||
struct uart_port *uport = state->uart_port;
|
struct uart_port *uport = state->uart_port;
|
||||||
|
|
||||||
|
memset(retinfo, 0, sizeof(*retinfo));
|
||||||
|
|
||||||
|
retinfo->type = uport->type;
|
||||||
|
retinfo->line = uport->line;
|
||||||
|
retinfo->port = uport->iobase;
|
||||||
|
if (HIGH_BITS_OFFSET)
|
||||||
|
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;
|
||||||
|
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 tty_port *port = &state->port;
|
||||||
struct serial_struct tmp;
|
struct serial_struct tmp;
|
||||||
|
|
||||||
memset(&tmp, 0, sizeof(tmp));
|
|
||||||
|
|
||||||
/* Ensure the state we copy is consistent and no hardware changes
|
/* Ensure the state we copy is consistent and no hardware changes
|
||||||
occur as we go */
|
occur as we go */
|
||||||
mutex_lock(&port->mutex);
|
mutex_lock(&port->mutex);
|
||||||
|
uart_get_info(port, state, &tmp);
|
||||||
tmp.type = uport->type;
|
|
||||||
tmp.line = uport->line;
|
|
||||||
tmp.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 ?
|
|
||||||
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;
|
|
||||||
|
|
||||||
mutex_unlock(&port->mutex);
|
mutex_unlock(&port->mutex);
|
||||||
|
|
||||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||||
@ -673,42 +679,30 @@ static int uart_get_info(struct uart_state *state,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
|
static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
||||||
struct serial_struct __user *newinfo)
|
struct uart_state *state,
|
||||||
|
struct serial_struct *new_info)
|
||||||
{
|
{
|
||||||
struct serial_struct new_serial;
|
|
||||||
struct uart_port *uport = state->uart_port;
|
struct uart_port *uport = state->uart_port;
|
||||||
struct tty_port *port = &state->port;
|
|
||||||
unsigned long new_port;
|
unsigned long new_port;
|
||||||
unsigned int change_irq, change_port, closing_wait;
|
unsigned int change_irq, change_port, closing_wait;
|
||||||
unsigned int old_custom_divisor, close_delay;
|
unsigned int old_custom_divisor, close_delay;
|
||||||
upf_t old_flags, new_flags;
|
upf_t old_flags, new_flags;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
|
new_port = new_info->port;
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
new_port = new_serial.port;
|
|
||||||
if (HIGH_BITS_OFFSET)
|
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);
|
new_info->irq = irq_canonicalize(new_info->irq);
|
||||||
close_delay = msecs_to_jiffies(new_serial.close_delay * 10);
|
close_delay = msecs_to_jiffies(new_info->close_delay * 10);
|
||||||
closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
|
closing_wait = new_info->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
|
||||||
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)
|
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
|
* 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)
|
change_port = !(uport->flags & UPF_FIXED_PORT)
|
||||||
&& (new_port != uport->iobase ||
|
&& (new_port != uport->iobase ||
|
||||||
(unsigned long)new_serial.iomem_base != uport->mapbase ||
|
(unsigned long)new_info->iomem_base != uport->mapbase ||
|
||||||
new_serial.hub6 != uport->hub6 ||
|
new_info->hub6 != uport->hub6 ||
|
||||||
new_serial.io_type != uport->iotype ||
|
new_info->io_type != uport->iotype ||
|
||||||
new_serial.iomem_reg_shift != uport->regshift ||
|
new_info->iomem_reg_shift != uport->regshift ||
|
||||||
new_serial.type != uport->type);
|
new_info->type != uport->type);
|
||||||
|
|
||||||
old_flags = uport->flags;
|
old_flags = uport->flags;
|
||||||
new_flags = new_serial.flags;
|
new_flags = new_info->flags;
|
||||||
old_custom_divisor = uport->custom_divisor;
|
old_custom_divisor = uport->custom_divisor;
|
||||||
|
|
||||||
if (!capable(CAP_SYS_ADMIN)) {
|
if (!capable(CAP_SYS_ADMIN)) {
|
||||||
retval = -EPERM;
|
retval = -EPERM;
|
||||||
if (change_irq || change_port ||
|
if (change_irq || change_port ||
|
||||||
(new_serial.baud_base != uport->uartclk / 16) ||
|
(new_info->baud_base != uport->uartclk / 16) ||
|
||||||
(close_delay != port->close_delay) ||
|
(close_delay != port->close_delay) ||
|
||||||
(closing_wait != port->closing_wait) ||
|
(closing_wait != port->closing_wait) ||
|
||||||
(new_serial.xmit_fifo_size &&
|
(new_info->xmit_fifo_size &&
|
||||||
new_serial.xmit_fifo_size != uport->fifosize) ||
|
new_info->xmit_fifo_size != uport->fifosize) ||
|
||||||
(((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
|
(((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
|
||||||
goto exit;
|
goto exit;
|
||||||
uport->flags = ((uport->flags & ~UPF_USR_MASK) |
|
uport->flags = ((uport->flags & ~UPF_USR_MASK) |
|
||||||
(new_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;
|
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.
|
* Ask the low level driver to verify the settings.
|
||||||
*/
|
*/
|
||||||
if (uport->ops->verify_port)
|
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) ||
|
if ((new_info->irq >= nr_irqs) || (new_info->irq < 0) ||
|
||||||
(new_serial.baud_base < 9600))
|
(new_info->baud_base < 9600))
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
|
|
||||||
if (retval)
|
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->ops->release_port(uport);
|
||||||
|
|
||||||
uport->iobase = new_port;
|
uport->iobase = new_port;
|
||||||
uport->type = new_serial.type;
|
uport->type = new_info->type;
|
||||||
uport->hub6 = new_serial.hub6;
|
uport->hub6 = new_info->hub6;
|
||||||
uport->iotype = new_serial.io_type;
|
uport->iotype = new_info->io_type;
|
||||||
uport->regshift = new_serial.iomem_reg_shift;
|
uport->regshift = new_info->iomem_reg_shift;
|
||||||
uport->mapbase = (unsigned long)new_serial.iomem_base;
|
uport->mapbase = (unsigned long)new_info->iomem_base;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Claim and map the new regions
|
* 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)
|
if (change_irq)
|
||||||
uport->irq = new_serial.irq;
|
uport->irq = new_info->irq;
|
||||||
if (!(uport->flags & UPF_FIXED_PORT))
|
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) |
|
uport->flags = (uport->flags & ~UPF_CHANGE_MASK) |
|
||||||
(new_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->close_delay = close_delay;
|
||||||
port->closing_wait = closing_wait;
|
port->closing_wait = closing_wait;
|
||||||
if (new_serial.xmit_fifo_size)
|
if (new_info->xmit_fifo_size)
|
||||||
uport->fifosize = new_serial.xmit_fifo_size;
|
uport->fifosize = new_info->xmit_fifo_size;
|
||||||
if (port->tty)
|
if (port->tty)
|
||||||
port->tty->low_latency =
|
port->tty->low_latency =
|
||||||
(uport->flags & UPF_LOW_LATENCY) ? 1 : 0;
|
(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
|
} else
|
||||||
retval = uart_startup(tty, state, 1);
|
retval = uart_startup(tty, state, 1);
|
||||||
exit:
|
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);
|
mutex_unlock(&port->mutex);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -1115,11 +1131,11 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd,
|
|||||||
*/
|
*/
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case TIOCGSERIAL:
|
case TIOCGSERIAL:
|
||||||
ret = uart_get_info(state, uarg);
|
ret = uart_get_info_user(state, uarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCSSERIAL:
|
case TIOCSSERIAL:
|
||||||
ret = uart_set_info(tty, state, uarg);
|
ret = uart_set_info_user(tty, state, uarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCSERCONFIG:
|
case TIOCSERCONFIG:
|
||||||
@ -1187,7 +1203,7 @@ static void uart_set_ldisc(struct tty_struct *tty)
|
|||||||
struct uart_port *uport = state->uart_port;
|
struct uart_port *uport = state->uart_port;
|
||||||
|
|
||||||
if (uport->ops->set_ldisc)
|
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,
|
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;
|
struct uart_state *state = tty->driver_data;
|
||||||
unsigned long flags;
|
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))
|
#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
|
||||||
if ((cflag ^ old_termios->c_cflag) == 0 &&
|
if ((cflag ^ old_termios->c_cflag) == 0 &&
|
||||||
tty->termios->c_ospeed == old_termios->c_ospeed &&
|
tty->termios.c_ospeed == old_termios->c_ospeed &&
|
||||||
tty->termios->c_ispeed == old_termios->c_ispeed &&
|
tty->termios.c_ispeed == old_termios->c_ispeed &&
|
||||||
RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) {
|
RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) {
|
||||||
return;
|
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 that's unset, use the tty termios setting.
|
||||||
*/
|
*/
|
||||||
if (port->tty && port->tty->termios && termios.c_cflag == 0)
|
if (port->tty && termios.c_cflag == 0)
|
||||||
termios = *(port->tty->termios);
|
termios = port->tty->termios;
|
||||||
|
|
||||||
if (console_suspend_enabled)
|
if (console_suspend_enabled)
|
||||||
uart_change_pm(state, 0);
|
uart_change_pm(state, 0);
|
||||||
@ -2293,6 +2309,36 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
|
|||||||
return p->tty_driver;
|
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
|
* uart_add_one_port - attach a driver-defined port structure
|
||||||
* @drv: pointer to the uart low level driver structure for this port
|
* @drv: pointer to the uart low level driver structure for this port
|
||||||
@ -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
|
* Register the port whether it's detected or not. This allows
|
||||||
* setserial to be used to alter this ports parameters.
|
* 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))) {
|
if (likely(!IS_ERR(tty_dev))) {
|
||||||
device_set_wakeup_capable(tty_dev, 1);
|
device_set_wakeup_capable(tty_dev, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -2492,7 +2539,7 @@ void uart_handle_cts_change(struct uart_port *uport, unsigned int status)
|
|||||||
|
|
||||||
uport->icount.cts++;
|
uport->icount.cts++;
|
||||||
|
|
||||||
if (port->flags & ASYNC_CTS_FLOW) {
|
if (tty_port_cts_enabled(port)) {
|
||||||
if (tty->hw_stopped) {
|
if (tty->hw_stopped) {
|
||||||
if (status) {
|
if (status) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
|
@ -668,7 +668,7 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
|
|||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
dev_err(&pdev->dev, "Insufficient resources.\n");
|
dev_err(&pdev->dev, "Insufficient resources.\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto irq_err;
|
goto err;
|
||||||
}
|
}
|
||||||
port->irq = res->start;
|
port->irq = res->start;
|
||||||
|
|
||||||
@ -676,7 +676,7 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
|
|||||||
sirfport->p = pinctrl_get_select_default(&pdev->dev);
|
sirfport->p = pinctrl_get_select_default(&pdev->dev);
|
||||||
ret = IS_ERR(sirfport->p);
|
ret = IS_ERR(sirfport->p);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto pin_err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
port->ops = &sirfsoc_uart_ops;
|
port->ops = &sirfsoc_uart_ops;
|
||||||
@ -695,9 +695,6 @@ port_err:
|
|||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
if (sirfport->hw_flow_ctrl)
|
if (sirfport->hw_flow_ctrl)
|
||||||
pinctrl_put(sirfport->p);
|
pinctrl_put(sirfport->p);
|
||||||
pin_err:
|
|
||||||
irq_err:
|
|
||||||
devm_iounmap(&pdev->dev, port->membase);
|
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -709,7 +706,6 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
|
|||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
if (sirfport->hw_flow_ctrl)
|
if (sirfport->hw_flow_ctrl)
|
||||||
pinctrl_put(sirfport->p);
|
pinctrl_put(sirfport->p);
|
||||||
devm_iounmap(&pdev->dev, port->membase);
|
|
||||||
uart_remove_one_port(&sirfsoc_uart_drv, port);
|
uart_remove_one_port(&sirfsoc_uart_drv, port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -58,10 +58,16 @@
|
|||||||
enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT };
|
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)" };
|
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.
|
* 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 },
|
{ "unknown", 1, 0 },
|
||||||
{ "8250", 1, 0 },
|
{ "8250", 1, 0 },
|
||||||
{ "16450", 1, 0 },
|
{ "16450", 1, 0 },
|
||||||
|
@ -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) ) {
|
(status & MISCSTATUS_CTS_LATCHED) ) {
|
||||||
if (info->port.tty->hw_stopped) {
|
if (info->port.tty->hw_stopped) {
|
||||||
if (status & MISCSTATUS_CTS) {
|
if (status & MISCSTATUS_CTS) {
|
||||||
@ -1840,22 +1840,22 @@ static void shutdown(struct mgsl_struct * info)
|
|||||||
usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
|
usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
|
||||||
TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
|
TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
|
||||||
usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
|
usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
|
||||||
|
|
||||||
/* Disable DMAEN (Port 7, Bit 14) */
|
/* Disable DMAEN (Port 7, Bit 14) */
|
||||||
/* This disconnects the DMA request signal from the ISA bus */
|
/* This disconnects the DMA request signal from the ISA bus */
|
||||||
/* on the ISA adapter. This has no effect for the PCI adapter */
|
/* on the ISA adapter. This has no effect for the PCI adapter */
|
||||||
usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));
|
usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));
|
||||||
|
|
||||||
/* Disable INTEN (Port 6, Bit12) */
|
/* Disable INTEN (Port 6, Bit12) */
|
||||||
/* This disconnects the IRQ request signal to the ISA bus */
|
/* This disconnects the IRQ request signal to the ISA bus */
|
||||||
/* on the ISA adapter. This has no effect for the PCI adapter */
|
/* on the ISA adapter. This has no effect for the PCI adapter */
|
||||||
usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12));
|
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);
|
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
|
||||||
usc_set_serial_signals(info);
|
usc_set_serial_signals(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
||||||
|
|
||||||
mgsl_release_resources(info);
|
mgsl_release_resources(info);
|
||||||
@ -1895,7 +1895,7 @@ static void mgsl_program_hw(struct mgsl_struct *info)
|
|||||||
usc_EnableInterrupts(info, IO_PIN);
|
usc_EnableInterrupts(info, IO_PIN);
|
||||||
usc_get_serial_signals(info);
|
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);
|
usc_start_receiver(info);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
||||||
@ -1908,14 +1908,14 @@ static void mgsl_change_params(struct mgsl_struct *info)
|
|||||||
unsigned cflag;
|
unsigned cflag;
|
||||||
int bits_per_char;
|
int bits_per_char;
|
||||||
|
|
||||||
if (!info->port.tty || !info->port.tty->termios)
|
if (!info->port.tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (debug_level >= DEBUG_LEVEL_INFO)
|
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||||
printk("%s(%d):mgsl_change_params(%s)\n",
|
printk("%s(%d):mgsl_change_params(%s)\n",
|
||||||
__FILE__,__LINE__, info->device_name );
|
__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 */
|
/* if B0 rate (hangup) specified then negate DTR and RTS */
|
||||||
/* otherwise assert DTR and RTS */
|
/* otherwise assert DTR and RTS */
|
||||||
@ -2367,8 +2367,8 @@ static void mgsl_throttle(struct tty_struct * tty)
|
|||||||
|
|
||||||
if (I_IXOFF(tty))
|
if (I_IXOFF(tty))
|
||||||
mgsl_send_xchar(tty, STOP_CHAR(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);
|
spin_lock_irqsave(&info->irq_spinlock,flags);
|
||||||
info->serial_signals &= ~SerialSignal_RTS;
|
info->serial_signals &= ~SerialSignal_RTS;
|
||||||
usc_set_serial_signals(info);
|
usc_set_serial_signals(info);
|
||||||
@ -2401,8 +2401,8 @@ static void mgsl_unthrottle(struct tty_struct * tty)
|
|||||||
else
|
else
|
||||||
mgsl_send_xchar(tty, START_CHAR(tty));
|
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);
|
spin_lock_irqsave(&info->irq_spinlock,flags);
|
||||||
info->serial_signals |= SerialSignal_RTS;
|
info->serial_signals |= SerialSignal_RTS;
|
||||||
usc_set_serial_signals(info);
|
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 */
|
/* Handle transition to B0 status */
|
||||||
if (old_termios->c_cflag & CBAUD &&
|
if (old_termios->c_cflag & CBAUD &&
|
||||||
!(tty->termios->c_cflag & CBAUD)) {
|
!(tty->termios.c_cflag & CBAUD)) {
|
||||||
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
|
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
|
||||||
spin_lock_irqsave(&info->irq_spinlock,flags);
|
spin_lock_irqsave(&info->irq_spinlock,flags);
|
||||||
usc_set_serial_signals(info);
|
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 */
|
/* Handle transition away from B0 status */
|
||||||
if (!(old_termios->c_cflag & CBAUD) &&
|
if (!(old_termios->c_cflag & CBAUD) &&
|
||||||
tty->termios->c_cflag & CBAUD) {
|
tty->termios.c_cflag & CBAUD) {
|
||||||
info->serial_signals |= SerialSignal_DTR;
|
info->serial_signals |= SerialSignal_DTR;
|
||||||
if (!(tty->termios->c_cflag & CRTSCTS) ||
|
if (!(tty->termios.c_cflag & CRTSCTS) ||
|
||||||
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
||||||
info->serial_signals |= SerialSignal_RTS;
|
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 */
|
/* Handle turning off CRTSCTS */
|
||||||
if (old_termios->c_cflag & CRTSCTS &&
|
if (old_termios->c_cflag & CRTSCTS &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
mgsl_start(tty);
|
mgsl_start(tty);
|
||||||
}
|
}
|
||||||
@ -3287,7 +3287,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->termios->c_cflag & CLOCAL)
|
if (tty->termios.c_cflag & CLOCAL)
|
||||||
do_clocal = true;
|
do_clocal = true;
|
||||||
|
|
||||||
/* Wait for carrier detect and the line to become
|
/* 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++;
|
port->blocked_open++;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (tty->termios->c_cflag & CBAUD)
|
if (tty->termios.c_cflag & CBAUD)
|
||||||
tty_port_raise_dtr_rts(port);
|
tty_port_raise_dtr_rts(port);
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
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",
|
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
|
||||||
__FILE__,__LINE__, tty->driver->name, port->count );
|
__FILE__,__LINE__, tty->driver->name, port->count );
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
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() */
|
} /* 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()
|
/* mgsl_open()
|
||||||
*
|
*
|
||||||
* Called when a port is opened. Init and enable port.
|
* 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)
|
static int mgsl_open(struct tty_struct *tty, struct file * filp)
|
||||||
{
|
{
|
||||||
struct mgsl_struct *info;
|
struct mgsl_struct *info = tty->driver_data;
|
||||||
int retval, line;
|
|
||||||
unsigned long flags;
|
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;
|
info->port.tty = tty;
|
||||||
|
|
||||||
if (debug_level >= DEBUG_LEVEL_INFO)
|
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||||
@ -4297,6 +4304,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
|
|||||||
} /* end of mgsl_allocate_device()*/
|
} /* end of mgsl_allocate_device()*/
|
||||||
|
|
||||||
static const struct tty_operations mgsl_ops = {
|
static const struct tty_operations mgsl_ops = {
|
||||||
|
.install = mgsl_install,
|
||||||
.open = mgsl_open,
|
.open = mgsl_open,
|
||||||
.close = mgsl_close,
|
.close = mgsl_close,
|
||||||
.write = mgsl_write,
|
.write = mgsl_write,
|
||||||
|
@ -785,7 +785,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
|
|||||||
|
|
||||||
/* Handle transition to B0 status */
|
/* Handle transition to B0 status */
|
||||||
if (old_termios->c_cflag & CBAUD &&
|
if (old_termios->c_cflag & CBAUD &&
|
||||||
!(tty->termios->c_cflag & CBAUD)) {
|
!(tty->termios.c_cflag & CBAUD)) {
|
||||||
info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
|
info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
|
||||||
spin_lock_irqsave(&info->lock,flags);
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
set_signals(info);
|
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 */
|
/* Handle transition away from B0 status */
|
||||||
if (!(old_termios->c_cflag & CBAUD) &&
|
if (!(old_termios->c_cflag & CBAUD) &&
|
||||||
tty->termios->c_cflag & CBAUD) {
|
tty->termios.c_cflag & CBAUD) {
|
||||||
info->signals |= SerialSignal_DTR;
|
info->signals |= SerialSignal_DTR;
|
||||||
if (!(tty->termios->c_cflag & CRTSCTS) ||
|
if (!(tty->termios.c_cflag & CRTSCTS) ||
|
||||||
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
||||||
info->signals |= SerialSignal_RTS;
|
info->signals |= SerialSignal_RTS;
|
||||||
}
|
}
|
||||||
@ -807,7 +807,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
|
|||||||
|
|
||||||
/* Handle turning off CRTSCTS */
|
/* Handle turning off CRTSCTS */
|
||||||
if (old_termios->c_cflag & CRTSCTS &&
|
if (old_termios->c_cflag & CRTSCTS &&
|
||||||
!(tty->termios->c_cflag & CRTSCTS)) {
|
!(tty->termios.c_cflag & CRTSCTS)) {
|
||||||
tty->hw_stopped = 0;
|
tty->hw_stopped = 0;
|
||||||
tx_release(tty);
|
tx_release(tty);
|
||||||
}
|
}
|
||||||
@ -1372,7 +1372,7 @@ static void throttle(struct tty_struct * tty)
|
|||||||
DBGINFO(("%s throttle\n", info->device_name));
|
DBGINFO(("%s throttle\n", info->device_name));
|
||||||
if (I_IXOFF(tty))
|
if (I_IXOFF(tty))
|
||||||
send_xchar(tty, STOP_CHAR(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);
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
info->signals &= ~SerialSignal_RTS;
|
info->signals &= ~SerialSignal_RTS;
|
||||||
set_signals(info);
|
set_signals(info);
|
||||||
@ -1397,7 +1397,7 @@ static void unthrottle(struct tty_struct * tty)
|
|||||||
else
|
else
|
||||||
send_xchar(tty, START_CHAR(tty));
|
send_xchar(tty, START_CHAR(tty));
|
||||||
}
|
}
|
||||||
if (tty->termios->c_cflag & CRTSCTS) {
|
if (tty->termios.c_cflag & CRTSCTS) {
|
||||||
spin_lock_irqsave(&info->lock,flags);
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
info->signals |= SerialSignal_RTS;
|
info->signals |= SerialSignal_RTS;
|
||||||
set_signals(info);
|
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);
|
wake_up_interruptible(&info->event_wait_q);
|
||||||
info->pending_bh |= BH_STATUS;
|
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) {
|
||||||
if (info->port.tty->hw_stopped) {
|
if (info->port.tty->hw_stopped) {
|
||||||
if (info->signals & SerialSignal_CTS) {
|
if (info->signals & SerialSignal_CTS) {
|
||||||
@ -2493,7 +2493,7 @@ static void shutdown(struct slgt_info *info)
|
|||||||
|
|
||||||
slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
|
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);
|
info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
|
||||||
set_signals(info);
|
set_signals(info);
|
||||||
}
|
}
|
||||||
@ -2534,7 +2534,7 @@ static void program_hw(struct slgt_info *info)
|
|||||||
get_signals(info);
|
get_signals(info);
|
||||||
|
|
||||||
if (info->netcount ||
|
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);
|
rx_start(info);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&info->lock,flags);
|
spin_unlock_irqrestore(&info->lock,flags);
|
||||||
@ -2548,11 +2548,11 @@ static void change_params(struct slgt_info *info)
|
|||||||
unsigned cflag;
|
unsigned cflag;
|
||||||
int bits_per_char;
|
int bits_per_char;
|
||||||
|
|
||||||
if (!info->port.tty || !info->port.tty->termios)
|
if (!info->port.tty)
|
||||||
return;
|
return;
|
||||||
DBGINFO(("%s change_params\n", info->device_name));
|
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 */
|
/* if B0 rate (hangup) specified then negate DTR and RTS */
|
||||||
/* otherwise assert 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->termios->c_cflag & CLOCAL)
|
if (tty->termios.c_cflag & CLOCAL)
|
||||||
do_clocal = true;
|
do_clocal = true;
|
||||||
|
|
||||||
/* Wait for carrier detect and the line to become
|
/* 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++;
|
port->blocked_open++;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if ((tty->termios->c_cflag & CBAUD))
|
if ((tty->termios.c_cflag & CBAUD))
|
||||||
tty_port_raise_dtr_rts(port);
|
tty_port_raise_dtr_rts(port);
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
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));
|
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
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)
|
for (i = 0; i < port_count; ++i) {
|
||||||
tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
|
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,
|
static int __devinit init_one(struct pci_dev *dev,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user