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:
Olof Johansson 2012-09-16 20:03:42 -07:00
commit a73403d85a
169 changed files with 6343 additions and 8834 deletions

View File

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

View File

@ -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>;
};

View File

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

View File

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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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");

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

985
drivers/tty/serial/sccnxp.c Normal file
View 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");

View File

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

View File

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

View File

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

View File

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

View File

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

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