summaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-23 12:23:20 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-23 12:23:20 -0700
commit99dff5856220a02b8711f2e8746413ea6e53ccf6 (patch)
treed8bae7ccdf8f7ad5221b053bb74a6220df996b3a /drivers/tty
parentbb74e8ca352eecefdc5c1a9ebab01f18aa2f6f3c (diff)
parentd9a0fbfd7bc5d2c42f0fa9bcbdab62c4942d0388 (diff)
downloadop-kernel-dev-99dff5856220a02b8711f2e8746413ea6e53ccf6.zip
op-kernel-dev-99dff5856220a02b8711f2e8746413ea6e53ccf6.tar.gz
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (48 commits) serial: 8250_pci: add support for Cronyx Omega PCI multiserial board. tty/serial: Fix break handling for PORT_TEGRA tty/serial: Add explicit PORT_TEGRA type n_tracerouter and n_tracesink ldisc additions. Intel PTI implementaiton of MIPI 1149.7. Kernel documentation for the PTI feature. export kernel call get_task_comm(). tty: Remove to support serial for S5P6442 pch_phub: Support new device ML7223 8250_pci: Add support for the Digi/IBM PCIe 2-port Adapter ASoC: Update cx20442 for TTY API change pch_uart: Support new device ML7223 IOH parport: Use request_muxed_region for IT87 probe and lock tty/serial: add support for Xilinx PS UART n_gsm: Use print_hex_dump_bytes drivers/tty/moxa.c: Put correct tty value TTY: tty_io, annotate locking functions TTY: serial_core, remove superfluous set_task_state TTY: serial_core, remove invalid test Char: moxa, fix locking in moxa_write ... Fix up trivial conflicts in drivers/bluetooth/hci_ldisc.c and drivers/tty/serial/Makefile. I did the hci_ldisc thing as an evil merge, cleaning things up.
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/Kconfig31
-rw-r--r--drivers/tty/Makefile2
-rw-r--r--drivers/tty/amiserial.c2
-rw-r--r--drivers/tty/cyclades.c5
-rw-r--r--drivers/tty/ipwireless/Makefile2
-rw-r--r--drivers/tty/moxa.c18
-rw-r--r--drivers/tty/n_gsm.c41
-rw-r--r--drivers/tty/n_hdlc.c18
-rw-r--r--drivers/tty/n_r3964.c10
-rw-r--r--drivers/tty/n_tracerouter.c243
-rw-r--r--drivers/tty/n_tracesink.c238
-rw-r--r--drivers/tty/n_tracesink.h36
-rw-r--r--drivers/tty/n_tty.c61
-rw-r--r--drivers/tty/nozomi.c29
-rw-r--r--drivers/tty/pty.c35
-rw-r--r--drivers/tty/rocket.c47
-rw-r--r--drivers/tty/serial/21285.c2
-rw-r--r--drivers/tty/serial/8250.c44
-rw-r--r--drivers/tty/serial/8250.h3
-rw-r--r--drivers/tty/serial/8250_accent.c2
-rw-r--r--drivers/tty/serial/8250_boca.c2
-rw-r--r--drivers/tty/serial/8250_exar_st16c554.c2
-rw-r--r--drivers/tty/serial/8250_fourport.c2
-rw-r--r--drivers/tty/serial/8250_hub6.c2
-rw-r--r--drivers/tty/serial/8250_mca.c2
-rw-r--r--drivers/tty/serial/8250_pci.c53
-rw-r--r--drivers/tty/serial/8250_pnp.c2
-rw-r--r--drivers/tty/serial/Kconfig27
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/altera_uart.c26
-rw-r--r--drivers/tty/serial/amba-pl010.c2
-rw-r--r--drivers/tty/serial/amba-pl011.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c2
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart.h2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h2
-rw-r--r--drivers/tty/serial/ifx6x60.c2
-rw-r--r--drivers/tty/serial/imx.c2
-rw-r--r--drivers/tty/serial/msm_serial.c2
-rw-r--r--drivers/tty/serial/msm_serial.h2
-rw-r--r--drivers/tty/serial/msm_smd_tty.c3
-rw-r--r--drivers/tty/serial/netx-serial.c2
-rw-r--r--drivers/tty/serial/pch_uart.c8
-rw-r--r--drivers/tty/serial/pmac_zilog.c2
-rw-r--r--drivers/tty/serial/pxa.c2
-rw-r--r--drivers/tty/serial/s3c2400.c3
-rw-r--r--drivers/tty/serial/s3c2410.c3
-rw-r--r--drivers/tty/serial/s3c2412.c3
-rw-r--r--drivers/tty/serial/s3c2440.c3
-rw-r--r--drivers/tty/serial/s3c24a0.c3
-rw-r--r--drivers/tty/serial/s3c6400.c3
-rw-r--r--drivers/tty/serial/s5pv210.c3
-rw-r--r--drivers/tty/serial/sa1100.c2
-rw-r--r--drivers/tty/serial/samsung.c3
-rw-r--r--drivers/tty/serial/samsung.h3
-rw-r--r--drivers/tty/serial/sb1250-duart.c2
-rw-r--r--drivers/tty/serial/serial_core.c90
-rw-r--r--drivers/tty/serial/serial_ks8695.c2
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c2
-rw-r--r--drivers/tty/serial/vt8500_serial.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c1113
-rw-r--r--drivers/tty/synclink.c2
-rw-r--r--drivers/tty/tty_buffer.c15
-rw-r--r--drivers/tty/tty_io.c53
-rw-r--r--drivers/tty/tty_ioctl.c2
-rw-r--r--drivers/tty/tty_ldisc.c13
-rw-r--r--drivers/tty/tty_mutex.c3
-rw-r--r--drivers/tty/vt/keyboard.c2
-rw-r--r--drivers/tty/vt/selection.c5
-rw-r--r--drivers/tty/vt/vc_screen.c2
-rw-r--r--drivers/tty/vt/vt.c13
-rw-r--r--drivers/tty/vt/vt_ioctl.c25
77 files changed, 1975 insertions, 435 deletions
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index 3fd7199..bd7cc05 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -319,3 +319,34 @@ config N_GSM
This line discipline provides support for the GSM MUX protocol and
presents the mux as a set of 61 individual tty devices.
+config TRACE_ROUTER
+ tristate "Trace data router for MIPI P1149.7 cJTAG standard"
+ depends on TRACE_SINK
+ default n
+ help
+ The trace router uses the Linux tty line discipline framework to
+ route trace data coming from a tty port (say UART for example) to
+ the trace sink line discipline driver and to another tty port (say
+ USB). This is part of a solution for the MIPI P1149.7, compact JTAG,
+ standard, which is for debugging mobile devices. The PTI driver in
+ drivers/misc/pti.c defines the majority of this MIPI solution.
+
+ You should select this driver if the target kernel is meant for
+ a mobile device containing a modem. Then you will need to select
+ "Trace data sink for MIPI P1149.7 cJTAG standard" line discipline
+ driver.
+
+config TRACE_SINK
+ tristate "Trace data sink for MIPI P1149.7 cJTAG standard"
+ default n
+ help
+ The trace sink uses the Linux line discipline framework to receive
+ trace data coming from the trace router line discipline driver
+ to a user-defined tty port target, like USB.
+ This is to provide a way to extract modem trace data on
+ devices that do not have a PTI HW module, or just need modem
+ trace data to come out of a different HW output port.
+ This is part of a solution for the P1149.7, compact JTAG, standard.
+
+ If you select this option, you need to select
+ "Trace data router for MIPI P1149.7 cJTAG standard".
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 690522f..ea89b0b 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_AUDIT) += tty_audit.o
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_N_GSM) += n_gsm.o
+obj-$(CONFIG_TRACE_ROUTER) += n_tracerouter.o
+obj-$(CONFIG_TRACE_SINK) += n_tracesink.o
obj-$(CONFIG_R3964) += n_r3964.o
obj-y += vt/
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index f214e50..2205795 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/amiserial.c
- *
* Serial driver for the amiga builtin port.
*
* This code was created by taking serial.c version 4.30 from kernel
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index c99728f..bfa05e8 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -3,8 +3,6 @@
#undef Z_EXT_CHARS_IN_BUFFER
/*
- * linux/drivers/char/cyclades.c
- *
* This file contains the driver for the Cyclades async multiport
* serial boards.
*
@@ -1445,13 +1443,11 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
{
struct cyclades_card *card;
unsigned long flags;
- int channel;
if (!(info->port.flags & ASYNC_INITIALIZED))
return;
card = info->card;
- channel = info->line - card->first_line;
if (!cy_is_Z(card)) {
spin_lock_irqsave(&card->card_lock, flags);
@@ -1476,6 +1472,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
spin_unlock_irqrestore(&card->card_lock, flags);
} else {
#ifdef CY_DEBUG_OPEN
+ int channel = info->line - card->first_line;
printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
"base_addr %p\n", card, channel, card->base_addr);
#endif
diff --git a/drivers/tty/ipwireless/Makefile b/drivers/tty/ipwireless/Makefile
index db80873d..fe2e173 100644
--- a/drivers/tty/ipwireless/Makefile
+++ b/drivers/tty/ipwireless/Makefile
@@ -1,6 +1,4 @@
#
-# drivers/char/pcmcia/ipwireless/Makefile
-#
# Makefile for the IPWireless driver
#
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index 35b0c38..ba679ce 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -371,7 +371,7 @@ static int moxa_ioctl(struct tty_struct *tty,
tmp.cflag = p->cflag;
else
tmp.cflag = ttyp->termios->c_cflag;
- tty_kref_put(tty);
+ tty_kref_put(ttyp);
copy:
if (copy_to_user(argm, &tmp, sizeof(tmp)))
return -EFAULT;
@@ -1129,7 +1129,6 @@ static void moxa_shutdown(struct tty_port *port)
struct moxa_port *ch = container_of(port, struct moxa_port, port);
MoxaPortDisable(ch);
MoxaPortFlushData(ch, 2);
- clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
}
static int moxa_carrier_raised(struct tty_port *port)
@@ -1155,7 +1154,6 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
struct moxa_board_conf *brd;
struct moxa_port *ch;
int port;
- int retval;
port = tty->index;
if (port == MAX_PORTS) {
@@ -1190,10 +1188,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
mutex_unlock(&ch->port.mutex);
mutex_unlock(&moxa_openlock);
- retval = tty_port_block_til_ready(&ch->port, tty, filp);
- if (retval == 0)
- set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags);
- return retval;
+ return tty_port_block_til_ready(&ch->port, tty, filp);
}
static void moxa_close(struct tty_struct *tty, struct file *filp)
@@ -1207,14 +1202,15 @@ static int moxa_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
struct moxa_port *ch = tty->driver_data;
+ unsigned long flags;
int len;
if (ch == NULL)
return 0;
- spin_lock_bh(&moxa_lock);
+ spin_lock_irqsave(&moxa_lock, flags);
len = MoxaPortWriteData(tty, buf, count);
- spin_unlock_bh(&moxa_lock);
+ spin_unlock_irqrestore(&moxa_lock, flags);
set_bit(LOWWAIT, &ch->statusflags);
return len;
@@ -1281,10 +1277,8 @@ static int moxa_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct moxa_port *ch;
- int port;
int dtr, rts;
- port = tty->index;
mutex_lock(&moxa_openlock);
ch = tty->driver_data;
if (!ch) {
@@ -1756,11 +1750,9 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
speed_t baud)
{
void __iomem *ofsAddr;
- tcflag_t cflag;
tcflag_t mode = 0;
ofsAddr = port->tableAddr;
- cflag = termio->c_cflag; /* termio->c_cflag */
mode = termio->c_cflag & CSIZE;
if (mode == CS5)
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 77623b9..a4c42a7 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -526,19 +526,6 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len)
return olen;
}
-static void hex_packet(const unsigned char *p, int len)
-{
- int i;
- for (i = 0; i < len; i++) {
- if (i && (i % 16) == 0) {
- pr_cont("\n");
- pr_debug("");
- }
- pr_cont("%02X ", *p++);
- }
- pr_cont("\n");
-}
-
/**
* gsm_send - send a control frame
* @gsm: our GSM mux
@@ -685,10 +672,10 @@ static void gsm_data_kick(struct gsm_mux *gsm)
len = msg->len + 2;
}
- if (debug & 4) {
- pr_debug("gsm_data_kick:\n");
- hex_packet(gsm->txframe, len);
- }
+ if (debug & 4)
+ print_hex_dump_bytes("gsm_data_kick: ",
+ DUMP_PREFIX_OFFSET,
+ gsm->txframe, len);
if (gsm->output(gsm, gsm->txframe + skip_sof,
len - skip_sof) < 0)
@@ -2095,10 +2082,9 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags);
return -ENOSPC;
}
- if (debug & 4) {
- pr_debug("-->%d bytes out\n", len);
- hex_packet(data, len);
- }
+ if (debug & 4)
+ print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET,
+ data, len);
gsm->tty->ops->write(gsm->tty, data, len);
return len;
}
@@ -2142,8 +2128,8 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
gsm->tty = NULL;
}
-static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
- char *fp, int count)
+static unsigned int gsmld_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
{
struct gsm_mux *gsm = tty->disc_data;
const unsigned char *dp;
@@ -2152,10 +2138,9 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char buf[64];
char flags;
- if (debug & 4) {
- pr_debug("Inbytes %dd\n", count);
- hex_packet(cp, count);
- }
+ if (debug & 4)
+ print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
+ cp, count);
for (i = count, dp = cp, f = fp; i; i--, dp++) {
flags = *f++;
@@ -2177,6 +2162,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
/* FASYNC if needed ? */
/* If clogged call tty_throttle(tty); */
+
+ return count;
}
/**
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index cea5603..cac6663 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -188,8 +188,8 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
poll_table *wait);
static int n_hdlc_tty_open(struct tty_struct *tty);
static void n_hdlc_tty_close(struct tty_struct *tty);
-static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp,
- char *fp, int count);
+static unsigned int n_hdlc_tty_receive(struct tty_struct *tty,
+ const __u8 *cp, char *fp, int count);
static void n_hdlc_tty_wakeup(struct tty_struct *tty);
#define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f)))
@@ -509,8 +509,8 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)
* Called by tty low level driver when receive data is available. Data is
* interpreted as one HDLC frame.
*/
-static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
- char *flags, int count)
+static unsigned int n_hdlc_tty_receive(struct tty_struct *tty,
+ const __u8 *data, char *flags, int count)
{
register struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
register struct n_hdlc_buf *buf;
@@ -521,20 +521,20 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
/* This can happen if stuff comes in on the backup tty */
if (!n_hdlc || tty != n_hdlc->tty)
- return;
+ return -ENODEV;
/* verify line is using HDLC discipline */
if (n_hdlc->magic != HDLC_MAGIC) {
printk("%s(%d) line not using HDLC discipline\n",
__FILE__,__LINE__);
- return;
+ return -EINVAL;
}
if ( count>maxframe ) {
if (debuglevel >= DEBUG_LEVEL_INFO)
printk("%s(%d) rx count>maxframesize, data discarded\n",
__FILE__,__LINE__);
- return;
+ return -EINVAL;
}
/* get a free HDLC buffer */
@@ -550,7 +550,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
if (debuglevel >= DEBUG_LEVEL_INFO)
printk("%s(%d) no more rx buffers, data discarded\n",
__FILE__,__LINE__);
- return;
+ return -EINVAL;
}
/* copy received data to HDLC buffer */
@@ -565,6 +565,8 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
if (n_hdlc->tty->fasync != NULL)
kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN);
+ return count;
+
} /* end of n_hdlc_tty_receive() */
/**
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 5c6c314..a4bc39c 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -139,8 +139,8 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
struct poll_table_struct *wait);
-static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
- char *fp, int count);
+static unsigned int r3964_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count);
static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
.owner = THIS_MODULE,
@@ -1239,8 +1239,8 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
return result;
}
-static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
- char *fp, int count)
+static unsigned int r3964_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
{
struct r3964_info *pInfo = tty->disc_data;
const unsigned char *p;
@@ -1257,6 +1257,8 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
}
+
+ return count;
}
MODULE_LICENSE("GPL");
diff --git a/drivers/tty/n_tracerouter.c b/drivers/tty/n_tracerouter.c
new file mode 100644
index 0000000..1f063d3
--- /dev/null
+++ b/drivers/tty/n_tracerouter.c
@@ -0,0 +1,243 @@
+/*
+ * n_tracerouter.c - Trace data router through tty space
+ *
+ * Copyright (C) Intel 2011
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This trace router uses the Linux line discipline framework to route
+ * trace data coming from a HW Modem to a PTI (Parallel Trace Module) port.
+ * The solution is not specific to a HW modem and this line disciple can
+ * be used to route any stream of data in kernel space.
+ * This is part of a solution for the P1149.7, compact JTAG, standard.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/tty.h>
+#include <linux/tty_ldisc.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <asm-generic/bug.h>
+#include "n_tracesink.h"
+
+/*
+ * Other ldisc drivers use 65536 which basically means,
+ * 'I can always accept 64k' and flow control is off.
+ * This number is deemed appropriate for this driver.
+ */
+#define RECEIVE_ROOM 65536
+#define DRIVERNAME "n_tracerouter"
+
+/*
+ * struct to hold private configuration data for this ldisc.
+ * opencalled is used to hold if this ldisc has been opened.
+ * kref_tty holds the tty reference the ldisc sits on top of.
+ */
+struct tracerouter_data {
+ u8 opencalled;
+ struct tty_struct *kref_tty;
+};
+static struct tracerouter_data *tr_data;
+
+/* lock for when tty reference is being used */
+static DEFINE_MUTEX(routelock);
+
+/**
+ * n_tracerouter_open() - Called when a tty is opened by a SW entity.
+ * @tty: terminal device to the ldisc.
+ *
+ * Return:
+ * 0 for success.
+ *
+ * Caveats: This should only be opened one time per SW entity.
+ */
+static int n_tracerouter_open(struct tty_struct *tty)
+{
+ int retval = -EEXIST;
+
+ mutex_lock(&routelock);
+ if (tr_data->opencalled == 0) {
+
+ tr_data->kref_tty = tty_kref_get(tty);
+ if (tr_data->kref_tty == NULL) {
+ retval = -EFAULT;
+ } else {
+ tr_data->opencalled = 1;
+ tty->disc_data = tr_data;
+ tty->receive_room = RECEIVE_ROOM;
+ tty_driver_flush_buffer(tty);
+ retval = 0;
+ }
+ }
+ mutex_unlock(&routelock);
+ return retval;
+}
+
+/**
+ * n_tracerouter_close() - close connection
+ * @tty: terminal device to the ldisc.
+ *
+ * Called when a software entity wants to close a connection.
+ */
+static void n_tracerouter_close(struct tty_struct *tty)
+{
+ struct tracerouter_data *tptr = tty->disc_data;
+
+ mutex_lock(&routelock);
+ WARN_ON(tptr->kref_tty != tr_data->kref_tty);
+ tty_driver_flush_buffer(tty);
+ tty_kref_put(tr_data->kref_tty);
+ tr_data->kref_tty = NULL;
+ tr_data->opencalled = 0;
+ tty->disc_data = NULL;
+ mutex_unlock(&routelock);
+}
+
+/**
+ * n_tracerouter_read() - read request from user space
+ * @tty: terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf: pointer to the data buffer that gets eventually returned.
+ * @nr: number of bytes of the data buffer that is returned.
+ *
+ * function that allows read() functionality in userspace. By default if this
+ * is not implemented it returns -EIO. This module is functioning like a
+ * router via n_tracerouter_receivebuf(), and there is no real requirement
+ * to implement this function. However, an error return value other than
+ * -EIO should be used just to show that there was an intent not to have
+ * this function implemented. Return value based on read() man pages.
+ *
+ * Return:
+ * -EINVAL
+ */
+static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file,
+ unsigned char __user *buf, size_t nr) {
+ return -EINVAL;
+}
+
+/**
+ * n_tracerouter_write() - Function that allows write() in userspace.
+ * @tty: terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf: pointer to the data buffer that gets eventually returned.
+ * @nr: number of bytes of the data buffer that is returned.
+ *
+ * By default if this is not implemented, it returns -EIO.
+ * This should not be implemented, ever, because
+ * 1. this driver is functioning like a router via
+ * n_tracerouter_receivebuf()
+ * 2. No writes to HW will ever go through this line discpline driver.
+ * However, an error return value other than -EIO should be used
+ * just to show that there was an intent not to have this function
+ * implemented. Return value based on write() man pages.
+ *
+ * Return:
+ * -EINVAL
+ */
+static ssize_t n_tracerouter_write(struct tty_struct *tty, struct file *file,
+ const unsigned char *buf, size_t nr) {
+ return -EINVAL;
+}
+
+/**
+ * n_tracerouter_receivebuf() - Routing function for driver.
+ * @tty: terminal device passed into the ldisc. It's assumed
+ * tty will never be NULL.
+ * @cp: buffer, block of characters to be eventually read by
+ * someone, somewhere (user read() call or some kernel function).
+ * @fp: flag buffer.
+ * @count: number of characters (aka, bytes) in cp.
+ *
+ * This function takes the input buffer, cp, and passes it to
+ * an external API function for processing.
+ */
+static void n_tracerouter_receivebuf(struct tty_struct *tty,
+ const unsigned char *cp,
+ char *fp, int count)
+{
+ mutex_lock(&routelock);
+ n_tracesink_datadrain((u8 *) cp, count);
+ mutex_unlock(&routelock);
+}
+
+/*
+ * Flush buffer is not impelemented as the ldisc has no internal buffering
+ * so the tty_driver_flush_buffer() is sufficient for this driver's needs.
+ */
+
+static struct tty_ldisc_ops tty_ptirouter_ldisc = {
+ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = DRIVERNAME,
+ .open = n_tracerouter_open,
+ .close = n_tracerouter_close,
+ .read = n_tracerouter_read,
+ .write = n_tracerouter_write,
+ .receive_buf = n_tracerouter_receivebuf
+};
+
+/**
+ * n_tracerouter_init - module initialisation
+ *
+ * Registers this module as a line discipline driver.
+ *
+ * Return:
+ * 0 for success, any other value error.
+ */
+static int __init n_tracerouter_init(void)
+{
+ int retval;
+
+ tr_data = kzalloc(sizeof(struct tracerouter_data), GFP_KERNEL);
+ if (tr_data == NULL)
+ return -ENOMEM;
+
+
+ /* Note N_TRACEROUTER is defined in linux/tty.h */
+ retval = tty_register_ldisc(N_TRACEROUTER, &tty_ptirouter_ldisc);
+ if (retval < 0) {
+ pr_err("%s: Registration failed: %d\n", __func__, retval);
+ kfree(tr_data);
+ }
+ return retval;
+}
+
+/**
+ * n_tracerouter_exit - module unload
+ *
+ * Removes this module as a line discipline driver.
+ */
+static void __exit n_tracerouter_exit(void)
+{
+ int retval = tty_unregister_ldisc(N_TRACEROUTER);
+
+ if (retval < 0)
+ pr_err("%s: Unregistration failed: %d\n", __func__, retval);
+ else
+ kfree(tr_data);
+}
+
+module_init(n_tracerouter_init);
+module_exit(n_tracerouter_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jay Freyensee");
+MODULE_ALIAS_LDISC(N_TRACEROUTER);
+MODULE_DESCRIPTION("Trace router ldisc driver");
diff --git a/drivers/tty/n_tracesink.c b/drivers/tty/n_tracesink.c
new file mode 100644
index 0000000..ddce58b
--- /dev/null
+++ b/drivers/tty/n_tracesink.c
@@ -0,0 +1,238 @@
+/*
+ * n_tracesink.c - Trace data router and sink path through tty space.
+ *
+ * Copyright (C) Intel 2011
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The trace sink uses the Linux line discipline framework to receive
+ * trace data coming from the PTI source line discipline driver
+ * to a user-desired tty port, like USB.
+ * This is to provide a way to extract modem trace data on
+ * devices that do not have a PTI HW module, or just need modem
+ * trace data to come out of a different HW output port.
+ * This is part of a solution for the P1149.7, compact JTAG, standard.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/tty.h>
+#include <linux/tty_ldisc.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <asm-generic/bug.h>
+#include "n_tracesink.h"
+
+/*
+ * Other ldisc drivers use 65536 which basically means,
+ * 'I can always accept 64k' and flow control is off.
+ * This number is deemed appropriate for this driver.
+ */
+#define RECEIVE_ROOM 65536
+#define DRIVERNAME "n_tracesink"
+
+/*
+ * there is a quirk with this ldisc is he can write data
+ * to a tty from anyone calling his kernel API, which
+ * meets customer requirements in the drivers/misc/pti.c
+ * project. So he needs to know when he can and cannot write when
+ * the API is called. In theory, the API can be called
+ * after an init() but before a successful open() which
+ * would crash the system if tty is not checked.
+ */
+static struct tty_struct *this_tty;
+static DEFINE_MUTEX(writelock);
+
+/**
+ * n_tracesink_open() - Called when a tty is opened by a SW entity.
+ * @tty: terminal device to the ldisc.
+ *
+ * Return:
+ * 0 for success,
+ * -EFAULT = couldn't get a tty kref n_tracesink will sit
+ * on top of
+ * -EEXIST = open() called successfully once and it cannot
+ * be called again.
+ *
+ * Caveats: open() should only be successful the first time a
+ * SW entity calls it.
+ */
+static int n_tracesink_open(struct tty_struct *tty)
+{
+ int retval = -EEXIST;
+
+ mutex_lock(&writelock);
+ if (this_tty == NULL) {
+ this_tty = tty_kref_get(tty);
+ if (this_tty == NULL) {
+ retval = -EFAULT;
+ } else {
+ tty->disc_data = this_tty;
+ tty_driver_flush_buffer(tty);
+ retval = 0;
+ }
+ }
+ mutex_unlock(&writelock);
+
+ return retval;
+}
+
+/**
+ * n_tracesink_close() - close connection
+ * @tty: terminal device to the ldisc.
+ *
+ * Called when a software entity wants to close a connection.
+ */
+static void n_tracesink_close(struct tty_struct *tty)
+{
+ mutex_lock(&writelock);
+ tty_driver_flush_buffer(tty);
+ tty_kref_put(this_tty);
+ this_tty = NULL;
+ tty->disc_data = NULL;
+ mutex_unlock(&writelock);
+}
+
+/**
+ * n_tracesink_read() - read request from user space
+ * @tty: terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf: pointer to the data buffer that gets eventually returned.
+ * @nr: number of bytes of the data buffer that is returned.
+ *
+ * function that allows read() functionality in userspace. By default if this
+ * is not implemented it returns -EIO. This module is functioning like a
+ * router via n_tracesink_receivebuf(), and there is no real requirement
+ * to implement this function. However, an error return value other than
+ * -EIO should be used just to show that there was an intent not to have
+ * this function implemented. Return value based on read() man pages.
+ *
+ * Return:
+ * -EINVAL
+ */
+static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file,
+ unsigned char __user *buf, size_t nr) {
+ return -EINVAL;
+}
+
+/**
+ * n_tracesink_write() - Function that allows write() in userspace.
+ * @tty: terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf: pointer to the data buffer that gets eventually returned.
+ * @nr: number of bytes of the data buffer that is returned.
+ *
+ * By default if this is not implemented, it returns -EIO.
+ * This should not be implemented, ever, because
+ * 1. this driver is functioning like a router via
+ * n_tracesink_receivebuf()
+ * 2. No writes to HW will ever go through this line discpline driver.
+ * However, an error return value other than -EIO should be used
+ * just to show that there was an intent not to have this function
+ * implemented. Return value based on write() man pages.
+ *
+ * Return:
+ * -EINVAL
+ */
+static ssize_t n_tracesink_write(struct tty_struct *tty, struct file *file,
+ const unsigned char *buf, size_t nr) {
+ return -EINVAL;
+}
+
+/**
+ * n_tracesink_datadrain() - Kernel API function used to route
+ * trace debugging data to user-defined
+ * port like USB.
+ *
+ * @buf: Trace debuging data buffer to write to tty target
+ * port. Null value will return with no write occurring.
+ * @count: Size of buf. Value of 0 or a negative number will
+ * return with no write occuring.
+ *
+ * Caveat: If this line discipline does not set the tty it sits
+ * on top of via an open() call, this API function will not
+ * call the tty's write() call because it will have no pointer
+ * to call the write().
+ */
+void n_tracesink_datadrain(u8 *buf, int count)
+{
+ mutex_lock(&writelock);
+
+ if ((buf != NULL) && (count > 0) && (this_tty != NULL))
+ this_tty->ops->write(this_tty, buf, count);
+
+ mutex_unlock(&writelock);
+}
+EXPORT_SYMBOL_GPL(n_tracesink_datadrain);
+
+/*
+ * Flush buffer is not impelemented as the ldisc has no internal buffering
+ * so the tty_driver_flush_buffer() is sufficient for this driver's needs.
+ */
+
+/*
+ * tty_ldisc function operations for this driver.
+ */
+static struct tty_ldisc_ops tty_n_tracesink = {
+ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = DRIVERNAME,
+ .open = n_tracesink_open,
+ .close = n_tracesink_close,
+ .read = n_tracesink_read,
+ .write = n_tracesink_write
+};
+
+/**
+ * n_tracesink_init- module initialisation
+ *
+ * Registers this module as a line discipline driver.
+ *
+ * Return:
+ * 0 for success, any other value error.
+ */
+static int __init n_tracesink_init(void)
+{
+ /* Note N_TRACESINK is defined in linux/tty.h */
+ int retval = tty_register_ldisc(N_TRACESINK, &tty_n_tracesink);
+
+ if (retval < 0)
+ pr_err("%s: Registration failed: %d\n", __func__, retval);
+
+ return retval;
+}
+
+/**
+ * n_tracesink_exit - module unload
+ *
+ * Removes this module as a line discipline driver.
+ */
+static void __exit n_tracesink_exit(void)
+{
+ int retval = tty_unregister_ldisc(N_TRACESINK);
+
+ if (retval < 0)
+ pr_err("%s: Unregistration failed: %d\n", __func__, retval);
+}
+
+module_init(n_tracesink_init);
+module_exit(n_tracesink_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jay Freyensee");
+MODULE_ALIAS_LDISC(N_TRACESINK);
+MODULE_DESCRIPTION("Trace sink ldisc driver");
diff --git a/drivers/tty/n_tracesink.h b/drivers/tty/n_tracesink.h
new file mode 100644
index 0000000..a68bb44
--- /dev/null
+++ b/drivers/tty/n_tracesink.h
@@ -0,0 +1,36 @@
+/*
+ * n_tracesink.h - Kernel driver API to route trace data in kernel space.
+ *
+ * Copyright (C) Intel 2011
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The PTI (Parallel Trace Interface) driver directs trace data routed from
+ * various parts in the system out through the Intel Penwell PTI port and
+ * out of the mobile device for analysis with a debugging tool
+ * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7,
+ * compact JTAG, standard.
+ *
+ * This header file is used by n_tracerouter to be able to send the
+ * data of it's tty port to the tty port this module sits. This
+ * mechanism can also be used independent of the PTI module.
+ *
+ */
+
+#ifndef N_TRACESINK_H_
+#define N_TRACESINK_H_
+
+void n_tracesink_datadrain(u8 *buf, int count);
+
+#endif
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 0ad3288..95d0a9c 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -81,38 +81,6 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
return put_user(x, ptr);
}
-/**
- * n_tty_set__room - receive space
- * @tty: terminal
- *
- * Called by the driver to find out how much data it is
- * permitted to feed to the line discipline without any being lost
- * and thus to manage flow control. Not serialized. Answers for the
- * "instant".
- */
-
-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 old_left;
-
- /*
- * If we are doing input canonicalization, and there are no
- * pending newlines, let characters through without limit, so
- * that erase characters will be handled. Other excess
- * characters will be beeped.
- */
- if (left <= 0)
- left = tty->icanon && !tty->canon_data;
- old_left = tty->receive_room;
- tty->receive_room = left;
-
- /* Did this open up the receive buffer? We may need to flip */
- if (left && !old_left)
- schedule_work(&tty->buf.work);
-}
-
static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
{
if (tty->read_cnt < N_TTY_BUF_SIZE) {
@@ -184,7 +152,6 @@ static void reset_buffer_flags(struct tty_struct *tty)
tty->canon_head = tty->canon_data = tty->erasing = 0;
memset(&tty->read_flags, 0, sizeof tty->read_flags);
- n_tty_set_room(tty);
check_unthrottle(tty);
}
@@ -1360,17 +1327,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
* calls one at a time and in order (or using flush_to_ldisc)
*/
-static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
- char *fp, int count)
+static unsigned int n_tty_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
{
const unsigned char *p;
char *f, flags = TTY_NORMAL;
int i;
char buf[64];
unsigned long cpuflags;
+ int left;
+ int ret = 0;
if (!tty->read_buf)
- return;
+ return 0;
if (tty->real_raw) {
spin_lock_irqsave(&tty->read_lock, cpuflags);
@@ -1380,6 +1349,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
memcpy(tty->read_buf + tty->read_head, cp, i);
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
tty->read_cnt += i;
+ ret += i;
cp += i;
count -= i;
@@ -1389,8 +1359,10 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
memcpy(tty->read_buf + tty->read_head, cp, i);
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
tty->read_cnt += i;
+ ret += i;
spin_unlock_irqrestore(&tty->read_lock, cpuflags);
} else {
+ ret = count;
for (i = count, p = cp, f = fp; i; i--, p++) {
if (f)
flags = *f++;
@@ -1418,8 +1390,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
tty->ops->flush_chars(tty);
}
- n_tty_set_room(tty);
-
if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
L_EXTPROC(tty)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
@@ -1432,8 +1402,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
* mode. We don't want to throttle the driver if we're in
* canonical mode and don't have a newline yet!
*/
- if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
+ left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
+ if (left < TTY_THRESHOLD_THROTTLE)
tty_throttle(tty);
+
+ return ret;
}
int is_ignored(int sig)
@@ -1477,7 +1451,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
tty->raw = 1;
tty->real_raw = 1;
- n_tty_set_room(tty);
return;
}
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@@ -1530,7 +1503,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
else
tty->real_raw = 0;
}
- n_tty_set_room(tty);
/* The termios change make the tty ready for I/O */
wake_up_interruptible(&tty->write_wait);
wake_up_interruptible(&tty->read_wait);
@@ -1812,8 +1784,6 @@ do_it_again:
retval = -ERESTARTSYS;
break;
}
- /* FIXME: does n_tty_set_room need locking ? */
- n_tty_set_room(tty);
timeout = schedule_timeout(timeout);
continue;
}
@@ -1885,10 +1855,8 @@ do_it_again:
* longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
* we won't get any more characters.
*/
- if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
- n_tty_set_room(tty);
+ if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
check_unthrottle(tty);
- }
if (b - buf >= minimum)
break;
@@ -1910,7 +1878,6 @@ do_it_again:
} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
goto do_it_again;
- n_tty_set_room(tty);
return retval;
}
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index fd0a9852..b1aecc7 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -364,8 +364,6 @@ struct port {
u8 toggle_ul;
u16 token_dl;
- /* mutex to ensure one access patch to this port */
- struct mutex tty_sem;
wait_queue_head_t tty_wait;
struct async_icount tty_icount;
@@ -1431,8 +1429,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
}
for (i = PORT_MDM; i < MAX_PORT; i++) {
- if (kfifo_alloc(&dc->port[i].fifo_ul,
- FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) {
+ if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_UL,
+ GFP_KERNEL)) {
dev_err(&pdev->dev,
"Could not allocate kfifo buffer\n");
ret = -ENOMEM;
@@ -1474,7 +1472,6 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
struct device *tty_dev;
struct port *port = &dc->port[i];
port->dc = dc;
- mutex_init(&port->tty_sem);
tty_port_init(&port->port);
port->port.ops = &noz_tty_port_ops;
tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
@@ -1688,13 +1685,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
if (!dc || !port)
return -ENODEV;
- mutex_lock(&port->tty_sem);
-
- if (unlikely(!port->port.count)) {
- DBG1(" ");
- goto exit;
- }
-
rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count);
/* notify card */
@@ -1719,7 +1709,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
spin_unlock_irqrestore(&dc->spin_mutex, flags);
exit:
- mutex_unlock(&port->tty_sem);
return rval;
}
@@ -1738,12 +1727,9 @@ static int ntty_write_room(struct tty_struct *tty)
int room = 4096;
const struct nozomi *dc = get_dc_by_tty(tty);
- if (dc) {
- mutex_lock(&port->tty_sem);
- if (port->port.count)
- room = kfifo_avail(&port->fifo_ul);
- mutex_unlock(&port->tty_sem);
- }
+ if (dc)
+ room = kfifo_avail(&port->fifo_ul);
+
return room;
}
@@ -1889,11 +1875,6 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
goto exit_in_buffer;
}
- if (unlikely(!port->port.count)) {
- dev_err(&dc->pdev->dev, "No tty open?\n");
- goto exit_in_buffer;
- }
-
rval = kfifo_len(&port->fifo_ul);
exit_in_buffer:
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 2107747..98b6e3b 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/pty.c
- *
* Copyright (C) 1991, 1992 Linus Torvalds
*
* Added support for a Unix98-style ptmx device.
@@ -295,8 +293,8 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENOMEM;
if (!try_module_get(driver->other->owner)) {
/* This cannot in fact currently happen */
- free_tty_struct(o_tty);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto err_free_tty;
}
initialize_tty_struct(o_tty, driver->other, idx);
@@ -304,13 +302,11 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
the easy way .. */
retval = tty_init_termios(tty);
if (retval)
- goto free_mem_out;
+ goto err_deinit_tty;
retval = tty_init_termios(o_tty);
- if (retval) {
- tty_free_termios(tty);
- goto free_mem_out;
- }
+ if (retval)
+ goto err_free_termios;
/*
* Everything allocated ... set up the o_tty structure.
@@ -327,10 +323,14 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
tty->count++;
driver->ttys[idx] = tty;
return 0;
-free_mem_out:
+err_free_termios:
+ tty_free_termios(tty);
+err_deinit_tty:
+ deinitialize_tty_struct(o_tty);
module_put(o_tty->driver->owner);
+err_free_tty:
free_tty_struct(o_tty);
- return -ENOMEM;
+ return retval;
}
static int pty_bsd_ioctl(struct tty_struct *tty,
@@ -559,20 +559,19 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENOMEM;
if (!try_module_get(driver->other->owner)) {
/* This cannot in fact currently happen */
- free_tty_struct(o_tty);
- return -ENOMEM;
+ 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 free_mem_out;
+ 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 free_mem_out;
+ goto err_free_mem;
*o_tty->termios = driver->other->init_termios;
o_tty->termios_locked = o_tty->termios + 1;
@@ -591,11 +590,13 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
tty->count++;
pty_count++;
return 0;
-free_mem_out:
+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);
- kfree(tty->termios);
return -ENOMEM;
}
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 036feeb..13043e8 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -1380,7 +1380,6 @@ static void rp_send_xchar(struct tty_struct *tty, char ch)
static void rp_throttle(struct tty_struct *tty)
{
struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
#ifdef ROCKET_DEBUG_THROTTLE
printk(KERN_INFO "throttle %s: %d....\n", tty->name,
@@ -1390,7 +1389,6 @@ static void rp_throttle(struct tty_struct *tty)
if (rocket_paranoia_check(info, "rp_throttle"))
return;
- cp = &info->channel;
if (I_IXOFF(tty))
rp_send_xchar(tty, STOP_CHAR(tty));
@@ -1400,7 +1398,6 @@ static void rp_throttle(struct tty_struct *tty)
static void rp_unthrottle(struct tty_struct *tty)
{
struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
#ifdef ROCKET_DEBUG_THROTTLE
printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
tty->ldisc.chars_in_buffer(tty));
@@ -1409,7 +1406,6 @@ static void rp_unthrottle(struct tty_struct *tty)
if (rocket_paranoia_check(info, "rp_throttle"))
return;
- cp = &info->channel;
if (I_IXOFF(tty))
rp_send_xchar(tty, START_CHAR(tty));
@@ -1722,13 +1718,10 @@ static int rp_write_room(struct tty_struct *tty)
static int rp_chars_in_buffer(struct tty_struct *tty)
{
struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
return 0;
- cp = &info->channel;
-
#ifdef ROCKET_DEBUG_WRITE
printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt);
#endif
@@ -1779,7 +1772,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
{
int num_aiops, aiop, max_num_aiops, num_chan, chan;
unsigned int aiopio[MAX_AIOPS_PER_BOARD];
- char *str, *board_type;
CONTROLLER_t *ctlp;
int fast_clock = 0;
@@ -1800,7 +1792,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
/* Depending on the model, set up some config variables */
switch (dev->device) {
case PCI_DEVICE_ID_RP4QUAD:
- str = "Quadcable";
max_num_aiops = 1;
ports_per_aiop = 4;
rocketModel[i].model = MODEL_RP4QUAD;
@@ -1808,42 +1799,36 @@ static __init int register_PCI(int i, struct pci_dev *dev)
rocketModel[i].numPorts = 4;
break;
case PCI_DEVICE_ID_RP8OCTA:
- str = "Octacable";
max_num_aiops = 1;
rocketModel[i].model = MODEL_RP8OCTA;
strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_URP8OCTA:
- str = "Octacable";
max_num_aiops = 1;
rocketModel[i].model = MODEL_UPCI_RP8OCTA;
strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_RP8INTF:
- str = "8";
max_num_aiops = 1;
rocketModel[i].model = MODEL_RP8INTF;
strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_URP8INTF:
- str = "8";
max_num_aiops = 1;
rocketModel[i].model = MODEL_UPCI_RP8INTF;
strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_RP8J:
- str = "8J";
max_num_aiops = 1;
rocketModel[i].model = MODEL_RP8J;
strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_RP4J:
- str = "4J";
max_num_aiops = 1;
ports_per_aiop = 4;
rocketModel[i].model = MODEL_RP4J;
@@ -1851,56 +1836,48 @@ static __init int register_PCI(int i, struct pci_dev *dev)
rocketModel[i].numPorts = 4;
break;
case PCI_DEVICE_ID_RP8SNI:
- str = "8 (DB78 Custom)";
max_num_aiops = 1;
rocketModel[i].model = MODEL_RP8SNI;
strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_RP16SNI:
- str = "16 (DB78 Custom)";
max_num_aiops = 2;
rocketModel[i].model = MODEL_RP16SNI;
strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
rocketModel[i].numPorts = 16;
break;
case PCI_DEVICE_ID_RP16INTF:
- str = "16";
max_num_aiops = 2;
rocketModel[i].model = MODEL_RP16INTF;
strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
rocketModel[i].numPorts = 16;
break;
case PCI_DEVICE_ID_URP16INTF:
- str = "16";
max_num_aiops = 2;
rocketModel[i].model = MODEL_UPCI_RP16INTF;
strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
rocketModel[i].numPorts = 16;
break;
case PCI_DEVICE_ID_CRP16INTF:
- str = "16";
max_num_aiops = 2;
rocketModel[i].model = MODEL_CPCI_RP16INTF;
strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
rocketModel[i].numPorts = 16;
break;
case PCI_DEVICE_ID_RP32INTF:
- str = "32";
max_num_aiops = 4;
rocketModel[i].model = MODEL_RP32INTF;
strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
rocketModel[i].numPorts = 32;
break;
case PCI_DEVICE_ID_URP32INTF:
- str = "32";
max_num_aiops = 4;
rocketModel[i].model = MODEL_UPCI_RP32INTF;
strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
rocketModel[i].numPorts = 32;
break;
case PCI_DEVICE_ID_RPP4:
- str = "Plus Quadcable";
max_num_aiops = 1;
ports_per_aiop = 4;
altChanRingIndicator++;
@@ -1910,7 +1887,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
rocketModel[i].numPorts = 4;
break;
case PCI_DEVICE_ID_RPP8:
- str = "Plus Octacable";
max_num_aiops = 2;
ports_per_aiop = 4;
altChanRingIndicator++;
@@ -1920,7 +1896,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_RP2_232:
- str = "Plus 2 (RS-232)";
max_num_aiops = 1;
ports_per_aiop = 2;
altChanRingIndicator++;
@@ -1930,7 +1905,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
rocketModel[i].numPorts = 2;
break;
case PCI_DEVICE_ID_RP2_422:
- str = "Plus 2 (RS-422)";
max_num_aiops = 1;
ports_per_aiop = 2;
altChanRingIndicator++;
@@ -1943,7 +1917,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
max_num_aiops = 1;
ports_per_aiop = 6;
- str = "6-port";
/* If revision is 1, the rocketmodem flash must be loaded.
* If it is 2 it is a "socketed" version. */
@@ -1961,7 +1934,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
case PCI_DEVICE_ID_RP4M:
max_num_aiops = 1;
ports_per_aiop = 4;
- str = "4-port";
if (dev->revision == 1) {
rcktpt_type[i] = ROCKET_TYPE_MODEMII;
rocketModel[i].loadrm2 = 1;
@@ -1974,7 +1946,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
rocketModel[i].numPorts = 4;
break;
default:
- str = "(unknown/unsupported)";
max_num_aiops = 0;
break;
}
@@ -2000,14 +1971,12 @@ static __init int register_PCI(int i, struct pci_dev *dev)
if (!
(sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
PCI_GPIO_CTRL_8PORT)) {
- str = "Quadcable";
ports_per_aiop = 4;
rocketModel[i].numPorts = 4;
}
}
break;
case PCI_DEVICE_ID_UPCI_RM3_8PORT:
- str = "8 ports";
max_num_aiops = 1;
rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
@@ -2018,7 +1987,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
break;
case PCI_DEVICE_ID_UPCI_RM3_4PORT:
- str = "4 ports";
max_num_aiops = 1;
rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
@@ -2032,21 +2000,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
break;
}
- switch (rcktpt_type[i]) {
- case ROCKET_TYPE_MODEM:
- board_type = "RocketModem";
- break;
- case ROCKET_TYPE_MODEMII:
- board_type = "RocketModem II";
- break;
- case ROCKET_TYPE_MODEMIII:
- board_type = "RocketModem III";
- break;
- default:
- board_type = "RocketPort";
- break;
- }
-
if (fast_clock) {
sClockPrescale = 0x12; /* mod 2 (divide by 3) */
rp_baud_base[i] = 921600;
diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c
index d89aa38..1b37626 100644
--- a/drivers/tty/serial/21285.c
+++ b/drivers/tty/serial/21285.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/21285.c
- *
* Driver for the serial port on the 21285 StrongArm-110 core logic chip.
*
* Based on drivers/char/serial.c
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 6611535..b40f7b9 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/8250.c
- *
* Driver for 8250/16550-type serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -273,7 +271,7 @@ static const struct serial8250_config uart_config[] = {
.fifo_size = 32,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_UUE,
+ .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
},
[PORT_RM9000] = {
.name = "RM9000",
@@ -303,6 +301,14 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
+ [PORT_TEGRA] = {
+ .name = "Tegra",
+ .fifo_size = 32,
+ .tx_loadsz = 8,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_01,
+ .flags = UART_CAP_FIFO | UART_CAP_RTOIE,
+ },
};
#if defined(CONFIG_MIPS_ALCHEMY)
@@ -1427,6 +1433,27 @@ static void serial8250_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
+/*
+ * Clear the Tegra rx fifo after a break
+ *
+ * FIXME: This needs to become a port specific callback once we have a
+ * framework for this
+ */
+static void clear_rx_fifo(struct uart_8250_port *up)
+{
+ unsigned int status, tmout = 10000;
+ do {
+ status = serial_in(up, UART_LSR);
+ if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
+ status = serial_in(up, UART_RX);
+ else
+ break;
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while (1);
+}
+
static void
receive_chars(struct uart_8250_port *up, unsigned int *status)
{
@@ -1462,6 +1489,13 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
lsr &= ~(UART_LSR_FE | UART_LSR_PE);
up->port.icount.brk++;
/*
+ * If tegra port then clear the rx fifo to
+ * accept another break/character.
+ */
+ if (up->port.type == PORT_TEGRA)
+ clear_rx_fifo(up);
+
+ /*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
@@ -2405,7 +2439,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
UART_ENABLE_MS(&up->port, termios->c_cflag))
up->ier |= UART_IER_MSI;
if (up->capabilities & UART_CAP_UUE)
- up->ier |= UART_IER_UUE | UART_IER_RTOIE;
+ up->ier |= UART_IER_UUE;
+ if (up->capabilities & UART_CAP_RTOIE)
+ up->ier |= UART_IER_RTOIE;
serial_out(up, UART_IER, up->ier);
diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h
index 6e19ea3..6edf4a6 100644
--- a/drivers/tty/serial/8250.h
+++ b/drivers/tty/serial/8250.h
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/8250.h
- *
* Driver for 8250/16550-type serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -44,6 +42,7 @@ struct serial8250_config {
#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */
#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
+#define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */
#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250_accent.c
index 9c10262..34b51c6 100644
--- a/drivers/tty/serial/8250_accent.c
+++ b/drivers/tty/serial/8250_accent.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/8250_accent.c
- *
* Copyright (C) 2005 Russell King.
* Data taken from include/asm-i386/serial.h
*
diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250_boca.c
index 3bfe0f7..d125dc1 100644
--- a/drivers/tty/serial/8250_boca.c
+++ b/drivers/tty/serial/8250_boca.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/8250_boca.c
- *
* Copyright (C) 2005 Russell King.
* Data taken from include/asm-i386/serial.h
*
diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250_exar_st16c554.c
index 567143a..bf53aab 100644
--- a/drivers/tty/serial/8250_exar_st16c554.c
+++ b/drivers/tty/serial/8250_exar_st16c554.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/8250_exar.c
- *
* Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
* Based on 8250_boca.
*
diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250_fourport.c
index 6375d68..be15826 100644
--- a/drivers/tty/serial/8250_fourport.c
+++ b/drivers/tty/serial/8250_fourport.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/8250_fourport.c
- *
* Copyright (C) 2005 Russell King.
* Data taken from include/asm-i386/serial.h
*
diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250_hub6.c
index 7609150..a5c778e 100644
--- a/drivers/tty/serial/8250_hub6.c
+++ b/drivers/tty/serial/8250_hub6.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/8250_hub6.c
- *
* Copyright (C) 2005 Russell King.
* Data taken from include/asm-i386/serial.h
*
diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250_mca.c
index d10be94..d20abf0 100644
--- a/drivers/tty/serial/8250_mca.c
+++ b/drivers/tty/serial/8250_mca.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/8250_mca.c
- *
* Copyright (C) 2005 Russell King.
* Data taken from include/asm-i386/serial.h
*
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
index 738cec9..4b4968a 100644
--- a/drivers/tty/serial/8250_pci.c
+++ b/drivers/tty/serial/8250_pci.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/8250_pci.c
- *
* Probe module for 8250/16550-type PCI serial ports.
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -973,6 +971,14 @@ ce4100_serial_setup(struct serial_private *priv,
return ret;
}
+static int
+pci_omegapci_setup(struct serial_private *priv,
+ struct pciserial_board *board,
+ struct uart_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)
@@ -1012,6 +1018,8 @@ static int skip_tx_en_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_TITAN_200EI 0xA016
#define PCI_DEVICE_ID_TITAN_200EISI 0xA017
#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538
+#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
+#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1412,7 +1420,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_default_setup,
},
/*
- * For Oxford Semiconductor and Mainpine
+ * For Oxford Semiconductor Tornado based devices
*/
{
.vendor = PCI_VENDOR_ID_OXSEMI,
@@ -1430,6 +1438,24 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.init = pci_oxsemi_tornado_init,
.setup = pci_default_setup,
},
+ {
+ .vendor = PCI_VENDOR_ID_DIGI,
+ .device = PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ .subvendor = PCI_SUBVENDOR_ID_IBM,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ /*
+ * Cronyx Omega PCI (PLX-chip based)
+ */
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_omegapci_setup,
+ },
/*
* Default "match everything" terminator entry
*/
@@ -1617,6 +1643,7 @@ enum pci_board_num_t {
pbn_ADDIDATA_PCIe_4_3906250,
pbn_ADDIDATA_PCIe_8_3906250,
pbn_ce4100_1_115200,
+ pbn_omegapci,
};
/*
@@ -2312,6 +2339,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 921600,
.reg_shift = 2,
},
+ [pbn_omegapci] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 0x200,
+ },
};
static const struct pci_device_id softmodem_blacklist[] = {
@@ -3075,6 +3108,14 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
pbn_oxsemi_8_4000000 },
+
+ /*
+ * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+
/*
* SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
* from skokodyn@yahoo.com
@@ -3801,6 +3842,12 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_ce4100_1_115200 },
+ /*
+ * Cronyx Omega PCI
+ */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_omegapci },
/*
* These entries match devices with class COMMUNICATION_SERIAL,
diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250_pnp.c
index 4822cb5..fc301f6 100644
--- a/drivers/tty/serial/8250_pnp.c
+++ b/drivers/tty/serial/8250_pnp.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/8250_pnp.c
- *
* Probe module for 8250/16550-type ISAPNP serial ports.
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index b1f0f83..636144c 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -537,7 +537,7 @@ config SERIAL_S3C6400
config SERIAL_S5PV210
tristate "Samsung S5PV210 Serial port support"
- depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_EXYNOS4210)
+ depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210)
select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210)
default y
help
@@ -1585,7 +1585,7 @@ config SERIAL_IFX6X60
Support for the IFX6x60 modem devices on Intel MID platforms.
config SERIAL_PCH_UART
- tristate "Intel EG20T PCH UART/OKI SEMICONDUCTOR ML7213 IOH"
+ tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART"
depends on PCI
select SERIAL_CORE
help
@@ -1593,10 +1593,12 @@ config SERIAL_PCH_UART
which is an IOH(Input/Output Hub) for x86 embedded processor.
Enabling PCH_DMA, this PCH UART works as DMA mode.
- This driver also can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/
- Output Hub) which is for IVI(In-Vehicle Infotainment) use.
- ML7213 is companion chip for Intel Atom E6xx series.
- ML7213 is completely compatible for Intel EG20T PCH.
+ This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+ Output Hub), ML7213 and ML7223.
+ ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
+ for MP(Media Phone) use.
+ ML7213/ML7223 is companion chip for Intel Atom E6xx series.
+ ML7213/ML7223 is completely compatible for Intel EG20T PCH.
config SERIAL_MSM_SMD
bool "Enable tty device interface for some SMD ports"
@@ -1620,4 +1622,17 @@ config SERIAL_MXS_AUART_CONSOLE
help
Enable a MXS AUART port to be the system console.
+config SERIAL_XILINX_PS_UART
+ tristate "Xilinx PS UART support"
+ select SERIAL_CORE
+ help
+ This driver supports the Xilinx PS UART port.
+
+config SERIAL_XILINX_PS_UART_CONSOLE
+ bool "Xilinx PS UART console support"
+ depends on SERIAL_XILINX_PS_UART=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Enable a Xilinx PS UART port to be the system console.
+
endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3527604..cb2628f 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -95,3 +95,4 @@ obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o
obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
+obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 6d5b036..50bc5a5 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -540,11 +540,14 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
int i = pdev->id;
int ret;
- /* -1 emphasizes that the platform must have one port, no .N suffix */
- if (i == -1)
- i = 0;
+ /* if id is -1 scan for a free id and use that one */
+ if (i == -1) {
+ for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++)
+ if (altera_uart_ports[i].port.mapbase == 0)
+ break;
+ }
- if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
+ if (i < 0 || i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
return -EINVAL;
port = &altera_uart_ports[i].port;
@@ -587,6 +590,8 @@ 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);
+
uart_add_one_port(&altera_uart_driver, port);
return 0;
@@ -594,14 +599,13 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
static int __devexit altera_uart_remove(struct platform_device *pdev)
{
- struct uart_port *port;
- int i = pdev->id;
+ struct uart_port *port = dev_get_drvdata(&pdev->dev);
- if (i == -1)
- i = 0;
-
- port = &altera_uart_ports[i].port;
- uart_remove_one_port(&altera_uart_driver, port);
+ if (port) {
+ uart_remove_one_port(&altera_uart_driver, port);
+ dev_set_drvdata(&pdev->dev, NULL);
+ port->mapbase = 0;
+ }
return 0;
}
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index d742dd2..c0d10c4 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/amba.c
- *
* Driver for AMBA serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6deee4e..8dc0541 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/amba.c
- *
* Driver for AMBA serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index f119d17..652bdac 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/atmel_serial.c
- *
* Driver for Atmel AT91 / AT32 Serial ports
* Copyright (C) 2003 Rick Bronson
*
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index b6acd19..e6c3dbd 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/clps711x.c
- *
* Driver for CLPS711x serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h
index b754dcf..cf34d26 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart.h
+++ b/drivers/tty/serial/cpm_uart/cpm_uart.h
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/cpm_uart.h
- *
* Driver for CPM (SCC/SMC) serial ports
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index a9a6a5f..9488da7 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/cpm_uart.c
- *
* Driver for CPM (SCC/SMC) serial ports; core driver
*
* Based on arch/ppc/cpm2_io/uart.c by Dan Malek
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c
index 3fc1d66..18f7957 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/cpm_uart.c
- *
* Driver for CPM (SCC/SMC) serial ports; CPM1 definitions
*
* Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h
index 10eecd6..60c7e94 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/cpm_uart/cpm_uart_cpm1.h
- *
* Driver for CPM (SCC/SMC) serial ports
*
* definitions for cpm1
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c
index 814ac00..a4927e6 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/cpm_uart_cpm2.c
- *
* Driver for CPM (SCC/SMC) serial ports; CPM2 definitions
*
* Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h
index 7194c63..51e651a 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/cpm_uart/cpm_uart_cpm2.h
- *
* Driver for CPM (SCC/SMC) serial ports
*
* definitions for cpm2
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 8ee5a41..5315525 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -41,7 +41,6 @@
#include <linux/tty.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
-#include <linux/tty.h>
#include <linux/kfifo.h>
#include <linux/tty_flip.h>
#include <linux/timer.h>
@@ -56,7 +55,6 @@
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/tty.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/spi/ifx_modem.h>
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 62df72d..a544731 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/imx.c
- *
* Driver for Motorola IMX serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index bfee9b4..e6ba838 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1,5 +1,5 @@
/*
- * drivers/serial/msm_serial.c - driver for msm7k serial device and console
+ * Driver for msm7k serial device and console
*
* Copyright (C) 2007 Google, Inc.
* Author: Robert Love <rlove@google.com>
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index 9b8dc5d..e4acef5 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -1,6 +1,4 @@
/*
- * drivers/serial/msm_serial.h
- *
* Copyright (C) 2007 Google, Inc.
* Author: Robert Love <rlove@google.com>
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c
index beeff1e..4f41dcd 100644
--- a/drivers/tty/serial/msm_smd_tty.c
+++ b/drivers/tty/serial/msm_smd_tty.c
@@ -1,5 +1,4 @@
-/* drivers/tty/serial/msm_smd_tty.c
- *
+/*
* Copyright (C) 2007 Google, Inc.
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c
index 7735c9f..d40da78 100644
--- a/drivers/tty/serial/netx-serial.c
+++ b/drivers/tty/serial/netx-serial.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/netx-serial.c
- *
* Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 26403b8..c63d0d1 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -253,6 +253,8 @@ enum pch_uart_num_t {
pch_ml7213_uart0,
pch_ml7213_uart1,
pch_ml7213_uart2,
+ pch_ml7223_uart0,
+ pch_ml7223_uart1,
};
static struct pch_uart_driver_data drv_dat[] = {
@@ -263,6 +265,8 @@ static struct pch_uart_driver_data drv_dat[] = {
[pch_ml7213_uart0] = {PCH_UART_8LINE, 0},
[pch_ml7213_uart1] = {PCH_UART_2LINE, 1},
[pch_ml7213_uart2] = {PCH_UART_2LINE, 2},
+ [pch_ml7223_uart0] = {PCH_UART_8LINE, 0},
+ [pch_ml7223_uart1] = {PCH_UART_2LINE, 1},
};
static unsigned int default_baud = 9600;
@@ -1534,6 +1538,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
.driver_data = pch_ml7213_uart1},
{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029),
.driver_data = pch_ml7213_uart2},
+ {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800C),
+ .driver_data = pch_ml7223_uart0},
+ {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D),
+ .driver_data = pch_ml7223_uart1},
{0,},
};
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index e1c8d4f..5acd24a 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/pmac_zilog.c
- *
* Driver for PowerMac Z85c30 based ESCC cell found in the
* "macio" ASICs of various PowerMac models
*
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 1102a39..4302e6e 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/serial/pxa.c
- *
* Based on drivers/serial/8250.c by Russell King.
*
* Author: Nicolas Pitre
diff --git a/drivers/tty/serial/s3c2400.c b/drivers/tty/serial/s3c2400.c
index fed1a9a..d13051b 100644
--- a/drivers/tty/serial/s3c2400.c
+++ b/drivers/tty/serial/s3c2400.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c240.c
- *
+/*
* Driver for Samsung SoC onboard UARTs.
*
* Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics
diff --git a/drivers/tty/serial/s3c2410.c b/drivers/tty/serial/s3c2410.c
index 73f089d..bffe6ff 100644
--- a/drivers/tty/serial/s3c2410.c
+++ b/drivers/tty/serial/s3c2410.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c2410.c
- *
+/*
* Driver for Samsung S3C2410 SoC onboard UARTs.
*
* Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
diff --git a/drivers/tty/serial/s3c2412.c b/drivers/tty/serial/s3c2412.c
index 1700b1a..7e2b950 100644
--- a/drivers/tty/serial/s3c2412.c
+++ b/drivers/tty/serial/s3c2412.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c2412.c
- *
+/*
* Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs.
*
* Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
diff --git a/drivers/tty/serial/s3c2440.c b/drivers/tty/serial/s3c2440.c
index 094cc39..9e10d41 100644
--- a/drivers/tty/serial/s3c2440.c
+++ b/drivers/tty/serial/s3c2440.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c2440.c
- *
+/*
* Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs.
*
* Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
diff --git a/drivers/tty/serial/s3c24a0.c b/drivers/tty/serial/s3c24a0.c
index fad6083..914eff2 100644
--- a/drivers/tty/serial/s3c24a0.c
+++ b/drivers/tty/serial/s3c24a0.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c24a0.c
- *
+/*
* Driver for Samsung S3C24A0 SoC onboard UARTs.
*
* Based on drivers/serial/s3c2410.c
diff --git a/drivers/tty/serial/s3c6400.c b/drivers/tty/serial/s3c6400.c
index 4be92ab..ded26c4 100644
--- a/drivers/tty/serial/s3c6400.c
+++ b/drivers/tty/serial/s3c6400.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c6400.c
- *
+/*
* Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs.
*
* Copyright 2008 Openmoko, Inc.
diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c
index 6ebccd7..fb2619f9 100644
--- a/drivers/tty/serial/s5pv210.c
+++ b/drivers/tty/serial/s5pv210.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s5pv210.c
- *
+/*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index 2199d81..ef7a21a 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/sa1100.c
- *
* Driver for SA11x0 serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 9e2fa8d..f66f648 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/samsuing.c
- *
+/*
* Driver core for Samsung SoC onboard UARTs.
*
* Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index 0ac06a0..5b098cd 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/samsung.h
- *
+/*
* Driver for Samsung SoC onboard UARTs.
*
* Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c
index 602d984..ea2340b 100644
--- a/drivers/tty/serial/sb1250-duart.c
+++ b/drivers/tty/serial/sb1250-duart.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/sb1250-duart.c
- *
* Support for the asynchronous serial interface (DUART) included
* in the BCM1250 and derived System-On-a-Chip (SOC) devices.
*
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 733fe8e..db7912c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/core.c
- *
* Driver core for serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -172,12 +170,16 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in
retval = uport->ops->startup(uport);
if (retval == 0) {
- if (init_hw) {
- /*
- * Initialise the hardware port settings.
- */
- uart_change_speed(tty, state, NULL);
+ if (uart_console(uport) && uport->cons->cflag) {
+ tty->termios->c_cflag = uport->cons->cflag;
+ uport->cons->cflag = 0;
+ }
+ /*
+ * Initialise the hardware port settings.
+ */
+ uart_change_speed(tty, state, NULL);
+ if (init_hw) {
/*
* Setup the RTS and DTR signals once the
* port is open and ready to respond.
@@ -1240,17 +1242,6 @@ static void uart_set_termios(struct tty_struct *tty,
}
spin_unlock_irqrestore(&state->uart_port->lock, flags);
}
-#if 0
- /*
- * No need to wake up processes in open wait, since they
- * sample the CLOCAL flag once, and don't recheck it.
- * XXX It's not clear whether the current behavior is correct
- * or not. Hence, this may change.....
- */
- if (!(old_termios->c_cflag & CLOCAL) &&
- (tty->termios->c_cflag & CLOCAL))
- wake_up_interruptible(&state->uart_port.open_wait);
-#endif
}
/*
@@ -1423,7 +1414,6 @@ static void __uart_wait_until_sent(struct uart_port *port, int timeout)
if (time_after(jiffies, expire))
break;
}
- set_current_state(TASK_RUNNING); /* might not be needed */
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -1466,45 +1456,6 @@ static void uart_hangup(struct tty_struct *tty)
mutex_unlock(&port->mutex);
}
-/**
- * uart_update_termios - update the terminal hw settings
- * @tty: tty associated with UART
- * @state: UART to update
- *
- * Copy across the serial console cflag setting into the termios settings
- * for the initial open of the port. This allows continuity between the
- * kernel settings, and the settings init adopts when it opens the port
- * for the first time.
- */
-static void uart_update_termios(struct tty_struct *tty,
- struct uart_state *state)
-{
- struct uart_port *port = state->uart_port;
-
- if (uart_console(port) && port->cons->cflag) {
- tty->termios->c_cflag = port->cons->cflag;
- port->cons->cflag = 0;
- }
-
- /*
- * If the device failed to grab its irq resources,
- * or some other error occurred, don't try to talk
- * to the port hardware.
- */
- if (!(tty->flags & (1 << TTY_IO_ERROR))) {
- /*
- * Make termios settings take effect.
- */
- uart_change_speed(tty, state, NULL);
-
- /*
- * And finally enable the RTS and DTR signals.
- */
- if (tty->termios->c_cflag & CBAUD)
- uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
- }
-}
-
static int uart_carrier_raised(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
@@ -1524,16 +1475,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff)
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
- if (onoff) {
+ if (onoff)
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
-
- /*
- * If this is the first open to succeed,
- * adjust things to suit.
- */
- if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags))
- uart_update_termios(port->tty, state);
- }
else
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
}
@@ -1586,15 +1529,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
pr_debug("uart_open(%d) called\n", line);
/*
- * tty->driver->num won't change, so we won't fail here with
- * tty->driver_data set to something non-NULL (and therefore
- * we won't get caught by uart_close()).
- */
- retval = -ENODEV;
- if (line >= tty->driver->num)
- goto fail;
-
- /*
* We take the semaphore inside uart_get to guarantee that we won't
* be re-entered while allocating the state structure, or while we
* request any IRQs that the driver may need. This also has the nice
@@ -1972,13 +1906,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
struct tty_port *port = &state->port;
struct device *tty_dev;
struct uart_match match = {uport, drv};
- struct tty_struct *tty;
mutex_lock(&port->mutex);
- /* Must be inside the mutex lock until we convert to tty_port */
- tty = port->tty;
-
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
if (device_may_wakeup(tty_dev)) {
if (!enable_irq_wake(uport->irq))
diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c
index b196202..2430319 100644
--- a/drivers/tty/serial/serial_ks8695.c
+++ b/drivers/tty/serial/serial_ks8695.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/serial_ks8695.c
- *
* Driver for KS8695 serial ports
*
* Based on drivers/serial/serial_amba.c, by Kam Lee.
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index c50e9fb..8e3fc19 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/serial_txx9.c
- *
* Derived from many drivers using generic_serial interface,
* especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c
* (was in Linux/VR tree) by Jim Pick.
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 920a6f9..f35b8fb 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/sh-sci.c
- *
* SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
*
* Copyright (C) 2002 - 2011 Paul Mundt
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 322bf56..37fc4e3 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/vt8500_serial.c
- *
* Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
*
* Based on msm_serial.c, which is:
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
new file mode 100644
index 0000000..19cc1e8
--- /dev/null
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -0,0 +1,1113 @@
+/*
+ * Xilinx PS UART driver
+ *
+ * 2011 (c) Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any
+ * later version.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#define XUARTPS_TTY_NAME "ttyPS"
+#define XUARTPS_NAME "xuartps"
+#define XUARTPS_MAJOR 0 /* use dynamic node allocation */
+#define XUARTPS_MINOR 0 /* works best with devtmpfs */
+#define XUARTPS_NR_PORTS 2
+#define XUARTPS_FIFO_SIZE 16 /* FIFO size */
+#define XUARTPS_REGISTER_SPACE 0xFFF
+
+#define xuartps_readl(offset) ioread32(port->membase + offset)
+#define xuartps_writel(val, offset) iowrite32(val, port->membase + offset)
+
+/********************************Register Map********************************/
+/** UART
+ *
+ * Register offsets for the UART.
+ *
+ */
+#define XUARTPS_CR_OFFSET 0x00 /* Control Register [8:0] */
+#define XUARTPS_MR_OFFSET 0x04 /* Mode Register [10:0] */
+#define XUARTPS_IER_OFFSET 0x08 /* Interrupt Enable [10:0] */
+#define XUARTPS_IDR_OFFSET 0x0C /* Interrupt Disable [10:0] */
+#define XUARTPS_IMR_OFFSET 0x10 /* Interrupt Mask [10:0] */
+#define XUARTPS_ISR_OFFSET 0x14 /* Interrupt Status [10:0]*/
+#define XUARTPS_BAUDGEN_OFFSET 0x18 /* Baud Rate Generator [15:0] */
+#define XUARTPS_RXTOUT_OFFSET 0x1C /* RX Timeout [7:0] */
+#define XUARTPS_RXWM_OFFSET 0x20 /* RX FIFO Trigger Level [5:0] */
+#define XUARTPS_MODEMCR_OFFSET 0x24 /* Modem Control [5:0] */
+#define XUARTPS_MODEMSR_OFFSET 0x28 /* Modem Status [8:0] */
+#define XUARTPS_SR_OFFSET 0x2C /* Channel Status [11:0] */
+#define XUARTPS_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
+#define XUARTPS_BAUDDIV_OFFSET 0x34 /* Baud Rate Divider [7:0] */
+#define XUARTPS_FLOWDEL_OFFSET 0x38 /* Flow Delay [15:0] */
+#define XUARTPS_IRRX_PWIDTH_OFFSET 0x3C /* IR Minimum Received Pulse
+ Width [15:0] */
+#define XUARTPS_IRTX_PWIDTH_OFFSET 0x40 /* IR Transmitted pulse
+ Width [7:0] */
+#define XUARTPS_TXWM_OFFSET 0x44 /* TX FIFO Trigger Level [5:0] */
+
+/** Control Register
+ *
+ * The Control register (CR) controls the major functions of the device.
+ *
+ * Control Register Bit Definitions
+ */
+#define XUARTPS_CR_STOPBRK 0x00000100 /* Stop TX break */
+#define XUARTPS_CR_STARTBRK 0x00000080 /* Set TX break */
+#define XUARTPS_CR_TX_DIS 0x00000020 /* TX disabled. */
+#define XUARTPS_CR_TX_EN 0x00000010 /* TX enabled */
+#define XUARTPS_CR_RX_DIS 0x00000008 /* RX disabled. */
+#define XUARTPS_CR_RX_EN 0x00000004 /* RX enabled */
+#define XUARTPS_CR_TXRST 0x00000002 /* TX logic reset */
+#define XUARTPS_CR_RXRST 0x00000001 /* RX logic reset */
+#define XUARTPS_CR_RST_TO 0x00000040 /* Restart Timeout Counter */
+
+/** Mode Register
+ *
+ * The mode register (MR) defines the mode of transfer as well as the data
+ * format. If this register is modified during transmission or reception,
+ * data validity cannot be guaranteed.
+ *
+ * Mode Register Bit Definitions
+ *
+ */
+#define XUARTPS_MR_CLKSEL 0x00000001 /* Pre-scalar selection */
+#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200 /* Local loop back mode */
+#define XUARTPS_MR_CHMODE_NORM 0x00000000 /* Normal mode */
+
+#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080 /* 2 stop bits */
+#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000 /* 1 stop bit */
+
+#define XUARTPS_MR_PARITY_NONE 0x00000020 /* No parity mode */
+#define XUARTPS_MR_PARITY_MARK 0x00000018 /* Mark parity mode */
+#define XUARTPS_MR_PARITY_SPACE 0x00000010 /* Space parity mode */
+#define XUARTPS_MR_PARITY_ODD 0x00000008 /* Odd parity mode */
+#define XUARTPS_MR_PARITY_EVEN 0x00000000 /* Even parity mode */
+
+#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006 /* 6 bits data */
+#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004 /* 7 bits data */
+#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000 /* 8 bits data */
+
+/** Interrupt Registers
+ *
+ * Interrupt control logic uses the interrupt enable register (IER) and the
+ * interrupt disable register (IDR) to set the value of the bits in the
+ * interrupt mask register (IMR). The IMR determines whether to pass an
+ * interrupt to the interrupt status register (ISR).
+ * Writing a 1 to IER Enables an interrupt, writing a 1 to IDR disables an
+ * interrupt. IMR and ISR are read only, and IER and IDR are write only.
+ * Reading either IER or IDR returns 0x00.
+ *
+ * All four registers have the same bit definitions.
+ */
+#define XUARTPS_IXR_TOUT 0x00000100 /* RX Timeout error interrupt */
+#define XUARTPS_IXR_PARITY 0x00000080 /* Parity error interrupt */
+#define XUARTPS_IXR_FRAMING 0x00000040 /* Framing error interrupt */
+#define XUARTPS_IXR_OVERRUN 0x00000020 /* Overrun error interrupt */
+#define XUARTPS_IXR_TXFULL 0x00000010 /* TX FIFO Full interrupt */
+#define XUARTPS_IXR_TXEMPTY 0x00000008 /* TX FIFO empty interrupt */
+#define XUARTPS_ISR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt */
+#define XUARTPS_IXR_RXTRIG 0x00000001 /* RX FIFO trigger interrupt */
+#define XUARTPS_IXR_RXFULL 0x00000004 /* RX FIFO full interrupt. */
+#define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */
+#define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */
+
+/** Channel Status Register
+ *
+ * The channel status register (CSR) is provided to enable the control logic
+ * to monitor the status of bits in the channel interrupt status register,
+ * even if these are masked out by the interrupt mask register.
+ */
+#define XUARTPS_SR_RXEMPTY 0x00000002 /* RX FIFO empty */
+#define XUARTPS_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
+#define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */
+#define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */
+
+/**
+ * xuartps_isr - Interrupt handler
+ * @irq: Irq number
+ * @dev_id: Id of the port
+ *
+ * Returns IRQHANDLED
+ **/
+static irqreturn_t xuartps_isr(int irq, void *dev_id)
+{
+ struct uart_port *port = (struct uart_port *)dev_id;
+ struct tty_struct *tty;
+ unsigned long flags;
+ unsigned int isrstatus, numbytes;
+ unsigned int data;
+ char status = TTY_NORMAL;
+
+ /* Get the tty which could be NULL so don't assume it's valid */
+ tty = tty_port_tty_get(&port->state->port);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Read the interrupt status register to determine which
+ * interrupt(s) is/are active.
+ */
+ isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET);
+
+ /* drop byte with parity error if IGNPAR specified */
+ if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY)
+ isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT);
+
+ isrstatus &= port->read_status_mask;
+ isrstatus &= ~port->ignore_status_mask;
+
+ if ((isrstatus & XUARTPS_IXR_TOUT) ||
+ (isrstatus & XUARTPS_IXR_RXTRIG)) {
+ /* Receive Timeout Interrupt */
+ while ((xuartps_readl(XUARTPS_SR_OFFSET) &
+ XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
+ data = xuartps_readl(XUARTPS_FIFO_OFFSET);
+ port->icount.rx++;
+
+ if (isrstatus & XUARTPS_IXR_PARITY) {
+ port->icount.parity++;
+ status = TTY_PARITY;
+ } else if (isrstatus & XUARTPS_IXR_FRAMING) {
+ port->icount.frame++;
+ status = TTY_FRAME;
+ } else if (isrstatus & XUARTPS_IXR_OVERRUN)
+ port->icount.overrun++;
+
+ if (tty)
+ uart_insert_char(port, isrstatus,
+ XUARTPS_IXR_OVERRUN, data,
+ status);
+ }
+ spin_unlock(&port->lock);
+ if (tty)
+ tty_flip_buffer_push(tty);
+ spin_lock(&port->lock);
+ }
+
+ /* Dispatch an appropriate handler */
+ if ((isrstatus & XUARTPS_IXR_TXEMPTY) == XUARTPS_IXR_TXEMPTY) {
+ if (uart_circ_empty(&port->state->xmit)) {
+ xuartps_writel(XUARTPS_IXR_TXEMPTY,
+ XUARTPS_IDR_OFFSET);
+ } else {
+ numbytes = port->fifosize;
+ /* Break if no more data available in the UART buffer */
+ while (numbytes--) {
+ if (uart_circ_empty(&port->state->xmit))
+ break;
+ /* Get the data from the UART circular buffer
+ * and write it to the xuartps's TX_FIFO
+ * register.
+ */
+ xuartps_writel(
+ port->state->xmit.buf[port->state->xmit.
+ tail], XUARTPS_FIFO_OFFSET);
+
+ port->icount.tx++;
+
+ /* Adjust the tail of the UART buffer and wrap
+ * the buffer if it reaches limit.
+ */
+ port->state->xmit.tail =
+ (port->state->xmit.tail + 1) & \
+ (UART_XMIT_SIZE - 1);
+ }
+
+ if (uart_circ_chars_pending(
+ &port->state->xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+ }
+ }
+
+ xuartps_writel(isrstatus, XUARTPS_ISR_OFFSET);
+
+ /* be sure to release the lock and tty before leaving */
+ spin_unlock_irqrestore(&port->lock, flags);
+ tty_kref_put(tty);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * xuartps_set_baud_rate - Calculate and set the baud rate
+ * @port: Handle to the uart port structure
+ * @baud: Baud rate to set
+ *
+ * Returns baud rate, requested baud when possible, or actual baud when there
+ * was too much error
+ **/
+static unsigned int xuartps_set_baud_rate(struct uart_port *port,
+ unsigned int baud)
+{
+ unsigned int sel_clk;
+ unsigned int calc_baud = 0;
+ unsigned int brgr_val, brdiv_val;
+ unsigned int bauderror;
+
+ /* Formula to obtain baud rate is
+ * baud_tx/rx rate = sel_clk/CD * (BDIV + 1)
+ * input_clk = (Uart User Defined Clock or Apb Clock)
+ * depends on UCLKEN in MR Reg
+ * sel_clk = input_clk or input_clk/8;
+ * depends on CLKS in MR reg
+ * CD and BDIV depends on values in
+ * baud rate generate register
+ * baud rate clock divisor register
+ */
+ sel_clk = port->uartclk;
+ if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL)
+ sel_clk = sel_clk / 8;
+
+ /* Find the best values for baud generation */
+ for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) {
+
+ brgr_val = sel_clk / (baud * (brdiv_val + 1));
+ if (brgr_val < 2 || brgr_val > 65535)
+ continue;
+
+ calc_baud = sel_clk / (brgr_val * (brdiv_val + 1));
+
+ if (baud > calc_baud)
+ bauderror = baud - calc_baud;
+ else
+ bauderror = calc_baud - baud;
+
+ /* use the values when percent error is acceptable */
+ if (((bauderror * 100) / baud) < 3) {
+ calc_baud = baud;
+ break;
+ }
+ }
+
+ /* Set the values for the new baud rate */
+ xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET);
+ xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET);
+
+ return calc_baud;
+}
+
+/*----------------------Uart Operations---------------------------*/
+
+/**
+ * xuartps_start_tx - Start transmitting bytes
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_start_tx(struct uart_port *port)
+{
+ unsigned int status, numbytes = port->fifosize;
+
+ if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port))
+ return;
+
+ status = xuartps_readl(XUARTPS_CR_OFFSET);
+ /* Set the TX enable bit and clear the TX disable bit to enable the
+ * transmitter.
+ */
+ xuartps_writel((status & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN,
+ XUARTPS_CR_OFFSET);
+
+ while (numbytes-- && ((xuartps_readl(XUARTPS_SR_OFFSET)
+ & XUARTPS_SR_TXFULL)) != XUARTPS_SR_TXFULL) {
+
+ /* Break if no more data available in the UART buffer */
+ if (uart_circ_empty(&port->state->xmit))
+ break;
+
+ /* Get the data from the UART circular buffer and
+ * write it to the xuartps's TX_FIFO register.
+ */
+ xuartps_writel(
+ port->state->xmit.buf[port->state->xmit.tail],
+ XUARTPS_FIFO_OFFSET);
+ port->icount.tx++;
+
+ /* Adjust the tail of the UART buffer and wrap
+ * the buffer if it reaches limit.
+ */
+ port->state->xmit.tail = (port->state->xmit.tail + 1) &
+ (UART_XMIT_SIZE - 1);
+ }
+
+ /* Enable the TX Empty interrupt */
+ xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET);
+
+ if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+}
+
+/**
+ * xuartps_stop_tx - Stop TX
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_stop_tx(struct uart_port *port)
+{
+ unsigned int regval;
+
+ regval = xuartps_readl(XUARTPS_CR_OFFSET);
+ regval |= XUARTPS_CR_TX_DIS;
+ /* Disable the transmitter */
+ xuartps_writel(regval, XUARTPS_CR_OFFSET);
+}
+
+/**
+ * xuartps_stop_rx - Stop RX
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_stop_rx(struct uart_port *port)
+{
+ unsigned int regval;
+
+ regval = xuartps_readl(XUARTPS_CR_OFFSET);
+ regval |= XUARTPS_CR_RX_DIS;
+ /* Disable the receiver */
+ xuartps_writel(regval, XUARTPS_CR_OFFSET);
+}
+
+/**
+ * xuartps_tx_empty - Check whether TX is empty
+ * @port: Handle to the uart port structure
+ *
+ * Returns TIOCSER_TEMT on success, 0 otherwise
+ **/
+static unsigned int xuartps_tx_empty(struct uart_port *port)
+{
+ unsigned int status;
+
+ status = xuartps_readl(XUARTPS_ISR_OFFSET) & XUARTPS_IXR_TXEMPTY;
+ return status ? TIOCSER_TEMT : 0;
+}
+
+/**
+ * xuartps_break_ctl - Based on the input ctl we have to start or stop
+ * transmitting char breaks
+ * @port: Handle to the uart port structure
+ * @ctl: Value based on which start or stop decision is taken
+ *
+ **/
+static void xuartps_break_ctl(struct uart_port *port, int ctl)
+{
+ unsigned int status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ status = xuartps_readl(XUARTPS_CR_OFFSET);
+
+ if (ctl == -1)
+ xuartps_writel(XUARTPS_CR_STARTBRK | status,
+ XUARTPS_CR_OFFSET);
+ else {
+ if ((status & XUARTPS_CR_STOPBRK) == 0)
+ xuartps_writel(XUARTPS_CR_STOPBRK | status,
+ XUARTPS_CR_OFFSET);
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/**
+ * xuartps_set_termios - termios operations, handling data length, parity,
+ * stop bits, flow control, baud rate
+ * @port: Handle to the uart port structure
+ * @termios: Handle to the input termios structure
+ * @old: Values of the previously saved termios structure
+ *
+ **/
+static void xuartps_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old)
+{
+ unsigned int cval = 0;
+ unsigned int baud;
+ unsigned long flags;
+ unsigned int ctrl_reg, mode_reg;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Empty the receive FIFO 1st before making changes */
+ while ((xuartps_readl(XUARTPS_SR_OFFSET) &
+ XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
+ xuartps_readl(XUARTPS_FIFO_OFFSET);
+ }
+
+ /* Disable the TX and RX to set baud rate */
+ xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
+ (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS),
+ XUARTPS_CR_OFFSET);
+
+ /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */
+ baud = uart_get_baud_rate(port, termios, old, 0, 10000000);
+ baud = xuartps_set_baud_rate(port, baud);
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ /* Set TX/RX Reset */
+ xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
+ (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
+ XUARTPS_CR_OFFSET);
+
+ ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
+
+ /* Clear the RX disable and TX disable bits and then set the TX enable
+ * bit and RX enable bit to enable the transmitter and receiver.
+ */
+ xuartps_writel(
+ (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS))
+ | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
+ XUARTPS_CR_OFFSET);
+
+ xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
+
+ port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG |
+ XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT;
+ port->ignore_status_mask = 0;
+
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= XUARTPS_IXR_PARITY |
+ XUARTPS_IXR_FRAMING;
+
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= XUARTPS_IXR_PARITY |
+ XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN;
+
+ /* ignore all characters if CREAD is not set */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= XUARTPS_IXR_RXTRIG |
+ XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY |
+ XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN;
+
+ mode_reg = xuartps_readl(XUARTPS_MR_OFFSET);
+
+ /* Handling Data Size */
+ switch (termios->c_cflag & CSIZE) {
+ case CS6:
+ cval |= XUARTPS_MR_CHARLEN_6_BIT;
+ break;
+ case CS7:
+ cval |= XUARTPS_MR_CHARLEN_7_BIT;
+ break;
+ default:
+ case CS8:
+ cval |= XUARTPS_MR_CHARLEN_8_BIT;
+ termios->c_cflag &= ~CSIZE;
+ termios->c_cflag |= CS8;
+ break;
+ }
+
+ /* Handling Parity and Stop Bits length */
+ if (termios->c_cflag & CSTOPB)
+ cval |= XUARTPS_MR_STOPMODE_2_BIT; /* 2 STOP bits */
+ else
+ cval |= XUARTPS_MR_STOPMODE_1_BIT; /* 1 STOP bit */
+
+ if (termios->c_cflag & PARENB) {
+ /* Mark or Space parity */
+ if (termios->c_cflag & CMSPAR) {
+ if (termios->c_cflag & PARODD)
+ cval |= XUARTPS_MR_PARITY_MARK;
+ else
+ cval |= XUARTPS_MR_PARITY_SPACE;
+ } else if (termios->c_cflag & PARODD)
+ cval |= XUARTPS_MR_PARITY_ODD;
+ else
+ cval |= XUARTPS_MR_PARITY_EVEN;
+ } else
+ cval |= XUARTPS_MR_PARITY_NONE;
+ xuartps_writel(cval , XUARTPS_MR_OFFSET);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/**
+ * xuartps_startup - Called when an application opens a xuartps port
+ * @port: Handle to the uart port structure
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int xuartps_startup(struct uart_port *port)
+{
+ unsigned int retval = 0, status = 0;
+
+ retval = request_irq(port->irq, xuartps_isr, 0, XUARTPS_NAME,
+ (void *)port);
+ if (retval)
+ return retval;
+
+ /* Disable the TX and RX */
+ xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS,
+ XUARTPS_CR_OFFSET);
+
+ /* Set the Control Register with TX/RX Enable, TX/RX Reset,
+ * no break chars.
+ */
+ xuartps_writel(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST,
+ XUARTPS_CR_OFFSET);
+
+ status = xuartps_readl(XUARTPS_CR_OFFSET);
+
+ /* Clear the RX disable and TX disable bits and then set the TX enable
+ * bit and RX enable bit to enable the transmitter and receiver.
+ */
+ xuartps_writel((status & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS))
+ | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN |
+ XUARTPS_CR_STOPBRK), XUARTPS_CR_OFFSET);
+
+ /* Set the Mode Register with normal mode,8 data bits,1 stop bit,
+ * no parity.
+ */
+ xuartps_writel(XUARTPS_MR_CHMODE_NORM | XUARTPS_MR_STOPMODE_1_BIT
+ | XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT,
+ XUARTPS_MR_OFFSET);
+
+ /* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */
+ xuartps_writel(14, XUARTPS_RXWM_OFFSET);
+
+ /* Receive Timeout register is enabled with value of 10 */
+ xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
+
+
+ /* Set the Interrupt Registers with desired interrupts */
+ xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
+ XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
+ XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
+ xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
+ XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
+ XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET);
+
+ return retval;
+}
+
+/**
+ * xuartps_shutdown - Called when an application closes a xuartps port
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_shutdown(struct uart_port *port)
+{
+ int status;
+
+ /* Disable interrupts */
+ status = xuartps_readl(XUARTPS_IMR_OFFSET);
+ xuartps_writel(status, XUARTPS_IDR_OFFSET);
+
+ /* Disable the TX and RX */
+ xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS,
+ XUARTPS_CR_OFFSET);
+ free_irq(port->irq, port);
+}
+
+/**
+ * xuartps_type - Set UART type to xuartps port
+ * @port: Handle to the uart port structure
+ *
+ * Returns string on success, NULL otherwise
+ **/
+static const char *xuartps_type(struct uart_port *port)
+{
+ return port->type == PORT_XUARTPS ? XUARTPS_NAME : NULL;
+}
+
+/**
+ * xuartps_verify_port - Verify the port params
+ * @port: Handle to the uart port structure
+ * @ser: Handle to the structure whose members are compared
+ *
+ * Returns 0 if success otherwise -EINVAL
+ **/
+static int xuartps_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_XUARTPS)
+ return -EINVAL;
+ if (port->irq != ser->irq)
+ return -EINVAL;
+ if (ser->io_type != UPIO_MEM)
+ return -EINVAL;
+ if (port->iobase != ser->port)
+ return -EINVAL;
+ if (ser->hub6 != 0)
+ return -EINVAL;
+ return 0;
+}
+
+/**
+ * xuartps_request_port - Claim the memory region attached to xuartps port,
+ * called when the driver adds a xuartps port via
+ * uart_add_one_port()
+ * @port: Handle to the uart port structure
+ *
+ * Returns 0, -ENOMEM if request fails
+ **/
+static int xuartps_request_port(struct uart_port *port)
+{
+ if (!request_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE,
+ XUARTPS_NAME)) {
+ return -ENOMEM;
+ }
+
+ port->membase = ioremap(port->mapbase, XUARTPS_REGISTER_SPACE);
+ if (!port->membase) {
+ dev_err(port->dev, "Unable to map registers\n");
+ release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * xuartps_release_port - Release the memory region attached to a xuartps
+ * port, called when the driver removes a xuartps
+ * port via uart_remove_one_port().
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE);
+ iounmap(port->membase);
+ port->membase = NULL;
+}
+
+/**
+ * xuartps_config_port - Configure xuartps, called when the driver adds a
+ * xuartps port
+ * @port: Handle to the uart port structure
+ * @flags: If any
+ *
+ **/
+static void xuartps_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE && xuartps_request_port(port) == 0)
+ port->type = PORT_XUARTPS;
+}
+
+/**
+ * xuartps_get_mctrl - Get the modem control state
+ *
+ * @port: Handle to the uart port structure
+ *
+ * Returns the modem control state
+ *
+ **/
+static unsigned int xuartps_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void xuartps_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* N/A */
+}
+
+static void xuartps_enable_ms(struct uart_port *port)
+{
+ /* N/A */
+}
+
+/** The UART operations structure
+ */
+static struct uart_ops xuartps_ops = {
+ .set_mctrl = xuartps_set_mctrl,
+ .get_mctrl = xuartps_get_mctrl,
+ .enable_ms = xuartps_enable_ms,
+
+ .start_tx = xuartps_start_tx, /* Start transmitting */
+ .stop_tx = xuartps_stop_tx, /* Stop transmission */
+ .stop_rx = xuartps_stop_rx, /* Stop reception */
+ .tx_empty = xuartps_tx_empty, /* Transmitter busy? */
+ .break_ctl = xuartps_break_ctl, /* Start/stop
+ * transmitting break
+ */
+ .set_termios = xuartps_set_termios, /* Set termios */
+ .startup = xuartps_startup, /* App opens xuartps */
+ .shutdown = xuartps_shutdown, /* App closes xuartps */
+ .type = xuartps_type, /* Set UART type */
+ .verify_port = xuartps_verify_port, /* Verification of port
+ * params
+ */
+ .request_port = xuartps_request_port, /* Claim resources
+ * associated with a
+ * xuartps port
+ */
+ .release_port = xuartps_release_port, /* Release resources
+ * associated with a
+ * xuartps port
+ */
+ .config_port = xuartps_config_port, /* Configure when driver
+ * adds a xuartps port
+ */
+};
+
+static struct uart_port xuartps_port[2];
+
+/**
+ * xuartps_get_port - Configure the port from the platform device resource
+ * info
+ *
+ * Returns a pointer to a uart_port or NULL for failure
+ **/
+static struct uart_port *xuartps_get_port(void)
+{
+ struct uart_port *port;
+ int id;
+
+ /* Find the next unused port */
+ for (id = 0; id < XUARTPS_NR_PORTS; id++)
+ if (xuartps_port[id].mapbase == 0)
+ break;
+
+ if (id >= XUARTPS_NR_PORTS)
+ return NULL;
+
+ port = &xuartps_port[id];
+
+ /* At this point, we've got an empty uart_port struct, initialize it */
+ spin_lock_init(&port->lock);
+ port->membase = NULL;
+ port->iobase = 1; /* mark port in use */
+ port->irq = 0;
+ port->type = PORT_UNKNOWN;
+ port->iotype = UPIO_MEM32;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->ops = &xuartps_ops;
+ port->fifosize = XUARTPS_FIFO_SIZE;
+ port->line = id;
+ port->dev = NULL;
+ return port;
+}
+
+/*-----------------------Console driver operations--------------------------*/
+
+#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
+/**
+ * xuartps_console_wait_tx - Wait for the TX to be full
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_console_wait_tx(struct uart_port *port)
+{
+ while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY)
+ != XUARTPS_SR_TXEMPTY)
+ barrier();
+}
+
+/**
+ * xuartps_console_putchar - write the character to the FIFO buffer
+ * @port: Handle to the uart port structure
+ * @ch: Character to be written
+ *
+ **/
+static void xuartps_console_putchar(struct uart_port *port, int ch)
+{
+ xuartps_console_wait_tx(port);
+ xuartps_writel(ch, XUARTPS_FIFO_OFFSET);
+}
+
+/**
+ * xuartps_console_write - perform write operation
+ * @port: Handle to the uart port structure
+ * @s: Pointer to character array
+ * @count: No of characters
+ **/
+static void xuartps_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_port *port = &xuartps_port[co->index];
+ unsigned long flags;
+ unsigned int imr;
+ int locked = 1;
+
+ if (oops_in_progress)
+ locked = spin_trylock_irqsave(&port->lock, flags);
+ else
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* save and disable interrupt */
+ imr = xuartps_readl(XUARTPS_IMR_OFFSET);
+ xuartps_writel(imr, XUARTPS_IDR_OFFSET);
+
+ uart_console_write(port, s, count, xuartps_console_putchar);
+ xuartps_console_wait_tx(port);
+
+ /* restore interrupt state, it seems like there may be a h/w bug
+ * in that the interrupt enable register should not need to be
+ * written based on the data sheet
+ */
+ xuartps_writel(~imr, XUARTPS_IDR_OFFSET);
+ xuartps_writel(imr, XUARTPS_IER_OFFSET);
+
+ if (locked)
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/**
+ * xuartps_console_setup - Initialize the uart to default config
+ * @co: Console handle
+ * @options: Initial settings of uart
+ *
+ * Returns 0, -ENODEV if no device
+ **/
+static int __init xuartps_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port = &xuartps_port[co->index];
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index < 0 || co->index >= XUARTPS_NR_PORTS)
+ return -EINVAL;
+
+ if (!port->mapbase) {
+ pr_debug("console on ttyPS%i not present\n", co->index);
+ 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 xuartps_uart_driver;
+
+static struct console xuartps_console = {
+ .name = XUARTPS_TTY_NAME,
+ .write = xuartps_console_write,
+ .device = uart_console_device,
+ .setup = xuartps_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */
+ .data = &xuartps_uart_driver,
+};
+
+/**
+ * xuartps_console_init - Initialization call
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int __init xuartps_console_init(void)
+{
+ register_console(&xuartps_console);
+ return 0;
+}
+
+console_initcall(xuartps_console_init);
+
+#endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */
+
+/** Structure Definitions
+ */
+static struct uart_driver xuartps_uart_driver = {
+ .owner = THIS_MODULE, /* Owner */
+ .driver_name = XUARTPS_NAME, /* Driver name */
+ .dev_name = XUARTPS_TTY_NAME, /* Node name */
+ .major = XUARTPS_MAJOR, /* Major number */
+ .minor = XUARTPS_MINOR, /* Minor number */
+ .nr = XUARTPS_NR_PORTS, /* Number of UART ports */
+#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
+ .cons = &xuartps_console, /* Console */
+#endif
+};
+
+/* ---------------------------------------------------------------------
+ * Platform bus binding
+ */
+/**
+ * xuartps_probe - Platform driver probe
+ * @pdev: Pointer to the platform device structure
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int __devinit xuartps_probe(struct platform_device *pdev)
+{
+ int rc;
+ struct uart_port *port;
+ struct resource *res, *res2;
+ int clk = 0;
+
+#ifdef CONFIG_OF
+ const unsigned int *prop;
+
+ prop = of_get_property(pdev->dev.of_node, "clock", NULL);
+ if (prop)
+ clk = be32_to_cpup(prop);
+#else
+ clk = *((unsigned int *)(pdev->dev.platform_data));
+#endif
+ if (!clk) {
+ dev_err(&pdev->dev, "no clock specified\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res2)
+ return -ENODEV;
+
+ /* Initialize the port structure */
+ port = xuartps_get_port();
+
+ if (!port) {
+ dev_err(&pdev->dev, "Cannot get uart_port structure\n");
+ return -ENODEV;
+ } else {
+ /* Register the port.
+ * This function also registers this device with the tty layer
+ * and triggers invocation of the config_port() entry point.
+ */
+ port->mapbase = res->start;
+ port->irq = res2->start;
+ port->dev = &pdev->dev;
+ port->uartclk = clk;
+ dev_set_drvdata(&pdev->dev, port);
+ rc = uart_add_one_port(&xuartps_uart_driver, port);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "uart_add_one_port() failed; err=%i\n", rc);
+ dev_set_drvdata(&pdev->dev, NULL);
+ return rc;
+ }
+ return 0;
+ }
+}
+
+/**
+ * xuartps_remove - called when the platform driver is unregistered
+ * @pdev: Pointer to the platform device structure
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int __devexit xuartps_remove(struct platform_device *pdev)
+{
+ struct uart_port *port = dev_get_drvdata(&pdev->dev);
+ int rc = 0;
+
+ /* Remove the xuartps port from the serial core */
+ if (port) {
+ rc = uart_remove_one_port(&xuartps_uart_driver, port);
+ dev_set_drvdata(&pdev->dev, NULL);
+ port->mapbase = 0;
+ }
+ return rc;
+}
+
+/**
+ * xuartps_suspend - suspend event
+ * @pdev: Pointer to the platform device structure
+ * @state: State of the device
+ *
+ * Returns 0
+ **/
+static int xuartps_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /* Call the API provided in serial_core.c file which handles
+ * the suspend.
+ */
+ uart_suspend_port(&xuartps_uart_driver, &xuartps_port[pdev->id]);
+ return 0;
+}
+
+/**
+ * xuartps_resume - Resume after a previous suspend
+ * @pdev: Pointer to the platform device structure
+ *
+ * Returns 0
+ **/
+static int xuartps_resume(struct platform_device *pdev)
+{
+ uart_resume_port(&xuartps_uart_driver, &xuartps_port[pdev->id]);
+ return 0;
+}
+
+/* Match table for of_platform binding */
+
+#ifdef CONFIG_OF
+static struct of_device_id xuartps_of_match[] __devinitdata = {
+ { .compatible = "xlnx,xuartps", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, xuartps_of_match);
+#else
+#define xuartps_of_match NULL
+#endif
+
+static struct platform_driver xuartps_platform_driver = {
+ .probe = xuartps_probe, /* Probe method */
+ .remove = __exit_p(xuartps_remove), /* Detach method */
+ .suspend = xuartps_suspend, /* Suspend */
+ .resume = xuartps_resume, /* Resume after a suspend */
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = XUARTPS_NAME, /* Driver name */
+ .of_match_table = xuartps_of_match,
+ },
+};
+
+/* ---------------------------------------------------------------------
+ * Module Init and Exit
+ */
+/**
+ * xuartps_init - Initial driver registration call
+ *
+ * Returns whether the registration was successful or not
+ **/
+static int __init xuartps_init(void)
+{
+ int retval = 0;
+
+ /* Register the xuartps driver with the serial core */
+ retval = uart_register_driver(&xuartps_uart_driver);
+ if (retval)
+ return retval;
+
+ /* Register the platform driver */
+ retval = platform_driver_register(&xuartps_platform_driver);
+ if (retval)
+ uart_unregister_driver(&xuartps_uart_driver);
+
+ return retval;
+}
+
+/**
+ * xuartps_exit - Driver unregistration call
+ **/
+static void __exit xuartps_exit(void)
+{
+ /* The order of unregistration is important. Unregister the
+ * UART driver before the platform driver crashes the system.
+ */
+
+ /* Unregister the platform driver */
+ platform_driver_unregister(&xuartps_platform_driver);
+
+ /* Unregister the xuartps driver */
+ uart_unregister_driver(&xuartps_uart_driver);
+}
+
+module_init(xuartps_init);
+module_exit(xuartps_exit);
+
+MODULE_DESCRIPTION("Driver for PS UART");
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 27da23d..272e417 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/synclink.c
- *
* $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $
*
* Device driver for Microgate SyncLink ISA and PCI
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index f1a7918..46de2e0 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -416,6 +416,7 @@ static void flush_to_ldisc(struct work_struct *work)
struct tty_buffer *head, *tail = tty->buf.tail;
int seen_tail = 0;
while ((head = tty->buf.head) != NULL) {
+ int copied;
int count;
char *char_buf;
unsigned char *flag_buf;
@@ -442,17 +443,19 @@ static void flush_to_ldisc(struct work_struct *work)
line discipline as we want to empty the queue */
if (test_bit(TTY_FLUSHPENDING, &tty->flags))
break;
- if (!tty->receive_room || seen_tail)
- break;
- if (count > tty->receive_room)
- count = tty->receive_room;
char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read;
- head->read += count;
spin_unlock_irqrestore(&tty->buf.lock, flags);
- disc->ops->receive_buf(tty, char_buf,
+ copied = disc->ops->receive_buf(tty, char_buf,
flag_buf, count);
spin_lock_irqsave(&tty->buf.lock, flags);
+
+ head->read += copied;
+
+ if (copied == 0 || seen_tail) {
+ schedule_work(&tty->buf.work);
+ break;
+ }
}
clear_bit(TTY_FLUSHING, &tty->flags);
}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index d7d50b4..6556f74 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/tty_io.c
- *
* Copyright (C) 1991, 1992 Linus Torvalds
*/
@@ -964,12 +962,14 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
}
void tty_write_unlock(struct tty_struct *tty)
+ __releases(&tty->atomic_write_lock)
{
mutex_unlock(&tty->atomic_write_lock);
wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
}
int tty_write_lock(struct tty_struct *tty, int ndelay)
+ __acquires(&tty->atomic_write_lock)
{
if (!mutex_trylock(&tty->atomic_write_lock)) {
if (ndelay)
@@ -1391,16 +1391,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
return ERR_PTR(-ENODEV);
tty = alloc_tty_struct();
- if (!tty)
- goto fail_no_mem;
+ if (!tty) {
+ retval = -ENOMEM;
+ goto err_module_put;
+ }
initialize_tty_struct(tty, driver, idx);
retval = tty_driver_install_tty(driver, tty);
- if (retval < 0) {
- free_tty_struct(tty);
- module_put(driver->owner);
- return ERR_PTR(retval);
- }
+ if (retval < 0)
+ goto err_deinit_tty;
/*
* Structures all installed ... call the ldisc open routines.
@@ -1409,15 +1408,18 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
*/
retval = tty_ldisc_setup(tty, tty->link);
if (retval)
- goto release_mem_out;
+ goto err_release_tty;
return tty;
-fail_no_mem:
+err_deinit_tty:
+ deinitialize_tty_struct(tty);
+ free_tty_struct(tty);
+err_module_put:
module_put(driver->owner);
- return ERR_PTR(-ENOMEM);
+ return ERR_PTR(retval);
/* call the tty release_tty routine to clean out this slot */
-release_mem_out:
+err_release_tty:
if (printk_ratelimit())
printk(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
@@ -1892,6 +1894,7 @@ got_driver:
retval = tty_add_file(tty, filp);
if (retval) {
tty_unlock();
+ tty_release(inode, filp);
return retval;
}
@@ -1902,12 +1905,10 @@ got_driver:
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "opening %s...", tty->name);
#endif
- if (!retval) {
- if (tty->ops->open)
- retval = tty->ops->open(tty, filp);
- else
- retval = -ENODEV;
- }
+ if (tty->ops->open)
+ retval = tty->ops->open(tty, filp);
+ else
+ retval = -ENODEV;
filp->f_flags = saved_flags;
if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) &&
@@ -2888,6 +2889,20 @@ void initialize_tty_struct(struct tty_struct *tty,
}
/**
+ * deinitialize_tty_struct
+ * @tty: tty to deinitialize
+ *
+ * This subroutine deinitializes a tty structure that has been newly
+ * allocated but tty_release cannot be called on that yet.
+ *
+ * Locking: none - tty in question must not be exposed at this point
+ */
+void deinitialize_tty_struct(struct tty_struct *tty)
+{
+ tty_ldisc_deinit(tty);
+}
+
+/**
* tty_put_char - write one character to a tty
* @tty: tty
* @ch: character
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 620c971..53f2442 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/tty_ioctl.c
- *
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
*
* Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index e19e136..5d01d32 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -956,6 +956,19 @@ void tty_ldisc_init(struct tty_struct *tty)
tty_ldisc_assign(tty, ld);
}
+/**
+ * tty_ldisc_init - ldisc cleanup for new tty
+ * @tty: tty that was allocated recently
+ *
+ * The tty structure must not becompletely set up (tty_ldisc_setup) when
+ * this call is made.
+ */
+void tty_ldisc_deinit(struct tty_struct *tty)
+{
+ put_ldisc(tty->ldisc);
+ tty_ldisc_assign(tty, NULL);
+}
+
void tty_ldisc_begin(void)
{
/* Setup the default TTY line discipline. */
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 1336975..3b2bb77 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -1,6 +1,3 @@
-/*
- * drivers/char/tty_lock.c
- */
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index d6b342b..3761ccf 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/keyboard.c
- *
* Written for linux by Johan Myreen as a translation from
* the assembly version by Linus (with diacriticals added)
*
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index adf0ad2..67b1d0d 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/selection.c
- *
* This module exports the functions:
*
* 'int set_selection(struct tiocl_selection __user *, struct tty_struct *)'
@@ -334,8 +332,7 @@ int paste_selection(struct tty_struct *tty)
continue;
}
count = sel_buffer_lth - pasted;
- count = min(count, tty->receive_room);
- tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
+ count = tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
NULL, count);
pasted += count;
}
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index 1564261..66825c9 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/vc_screen.c
- *
* Provide access to virtual console memory.
* /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
* /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4bea1ef..b3915b7 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/vt.c
- *
* Copyright (C) 1991, 1992 Linus Torvalds
*/
@@ -858,7 +856,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
{
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned long end;
- unsigned int old_cols, old_rows, old_row_size, old_screen_size;
+ unsigned int old_rows, old_row_size;
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
unsigned int user;
unsigned short *newscreen;
@@ -887,9 +885,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
return -ENOMEM;
old_rows = vc->vc_rows;
- old_cols = vc->vc_cols;
old_row_size = vc->vc_size_row;
- old_screen_size = vc->vc_screenbuf_size;
err = resize_screen(vc, new_cols, new_rows, user);
if (err) {
@@ -1197,6 +1193,13 @@ static void csi_J(struct vc_data *vc, int vpar)
vc->vc_x + 1);
}
break;
+ case 3: /* erase scroll-back buffer (and whole display) */
+ scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
+ vc->vc_screenbuf_size >> 1);
+ set_origin(vc);
+ if (CON_IS_VISIBLE(vc))
+ update_screen(vc);
+ /* fall through */
case 2: /* erase whole display */
count = vc->vc_cols * vc->vc_rows;
start = (unsigned short *)vc->vc_origin;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 937d172..5e096f4 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/char/vt_ioctl.c
- *
* Copyright (C) 1992 obz under the linux copyright
*
* Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
@@ -698,10 +696,23 @@ int vt_ioctl(struct tty_struct *tty,
break;
case KDGKBMODE:
- uival = ((kbd->kbdmode == VC_RAW) ? K_RAW :
- (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
- (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
- K_XLATE);
+ switch (kbd->kbdmode) {
+ case VC_RAW:
+ uival = K_RAW;
+ break;
+ case VC_MEDIUMRAW:
+ uival = K_MEDIUMRAW;
+ break;
+ case VC_UNICODE:
+ uival = K_UNICODE;
+ break;
+ case VC_OFF:
+ uival = K_OFF;
+ break;
+ default:
+ uival = K_XLATE;
+ break;
+ }
goto setint;
/* this could be folded into KDSKBMODE, but for compatibility
@@ -1499,7 +1510,6 @@ long vt_compat_ioctl(struct tty_struct *tty,
{
struct vc_data *vc = tty->driver_data;
struct console_font_op op; /* used in multiple places here */
- struct kbd_struct *kbd;
unsigned int console;
void __user *up = (void __user *)arg;
int perm;
@@ -1522,7 +1532,6 @@ long vt_compat_ioctl(struct tty_struct *tty,
if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
perm = 1;
- kbd = kbd_table + console;
switch (cmd) {
/*
* these need special handlers for incompatible data structures
OpenPOWER on IntegriCloud