aboutsummaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/21285.c8
-rw-r--r--drivers/serial/8250.c35
-rw-r--r--drivers/serial/8250.h1
-rw-r--r--drivers/serial/Kconfig21
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/amba-pl010.c6
-rw-r--r--drivers/serial/amba-pl011.c6
-rw-r--r--drivers/serial/atmel_serial.c14
-rw-r--r--drivers/serial/bcm63xx_uart.c890
-rw-r--r--drivers/serial/bfin_5xx.c24
-rw-r--r--drivers/serial/bfin_sport_uart.c6
-rw-r--r--drivers/serial/clps711x.c4
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c4
-rw-r--r--drivers/serial/crisv10.c1
-rw-r--r--drivers/serial/dz.c6
-rw-r--r--drivers/serial/icom.c74
-rw-r--r--drivers/serial/imx.c16
-rw-r--r--drivers/serial/ioc3_serial.c54
-rw-r--r--drivers/serial/ioc4_serial.c68
-rw-r--r--drivers/serial/ip22zilog.c14
-rw-r--r--drivers/serial/jsm/jsm_neo.c2
-rw-r--r--drivers/serial/jsm/jsm_tty.c20
-rw-r--r--drivers/serial/m32r_sio.c6
-rw-r--r--drivers/serial/max3100.c17
-rw-r--r--drivers/serial/mcf.c4
-rw-r--r--drivers/serial/mpc52xx_uart.c4
-rw-r--r--drivers/serial/mpsc.c4
-rw-r--r--drivers/serial/msm_serial.c6
-rw-r--r--drivers/serial/mux.c4
-rw-r--r--drivers/serial/netx-serial.c6
-rw-r--r--drivers/serial/nwpserial.c4
-rw-r--r--drivers/serial/pmac_zilog.c20
-rw-r--r--drivers/serial/pnx8xxx_uart.c8
-rw-r--r--drivers/serial/pxa.c26
-rw-r--r--drivers/serial/sa1100.c10
-rw-r--r--drivers/serial/samsung.c8
-rw-r--r--drivers/serial/sb1250-duart.c6
-rw-r--r--drivers/serial/sc26xx.c10
-rw-r--r--drivers/serial/serial_core.c880
-rw-r--r--drivers/serial/serial_cs.c1
-rw-r--r--drivers/serial/serial_ks8695.c6
-rw-r--r--drivers/serial/serial_lh7a40x.c6
-rw-r--r--drivers/serial/serial_txx9.c43
-rw-r--r--drivers/serial/sh-sci.c10
-rw-r--r--drivers/serial/sn_console.c22
-rw-r--r--drivers/serial/sunhv.c8
-rw-r--r--drivers/serial/sunsab.c10
-rw-r--r--drivers/serial/sunsu.c6
-rw-r--r--drivers/serial/sunzilog.c14
-rw-r--r--drivers/serial/timbuart.c10
-rw-r--r--drivers/serial/uartlite.c19
-rw-r--r--drivers/serial/ucc_uart.c4
-rw-r--r--drivers/serial/vr41xx_siu.c6
-rw-r--r--drivers/serial/zs.c6
54 files changed, 1716 insertions, 753 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index cb6d85d7ff4..1e3d19397a5 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -86,7 +86,7 @@ static void serial21285_enable_ms(struct uart_port *port)
static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
- struct tty_struct *tty = port->info->port.tty;
+ struct tty_struct *tty = port->state->port.tty;
unsigned int status, ch, flag, rxs, max_count = 256;
status = *CSR_UARTFLG;
@@ -124,7 +124,7 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
- struct circ_buf *xmit = &port->info->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
int count = 256;
if (port->x_char) {
@@ -235,8 +235,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud);
- if (port->info && port->info->port.tty) {
- struct tty_struct *tty = port->info->port.tty;
+ if (port->state && port->state->port.tty) {
+ struct tty_struct *tty = port->state->port.tty;
unsigned int b = port->uartclk / (16 * quot);
tty_encode_baud_rate(tty, b, b);
}
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index fb867a9f55e..b1ae774016f 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -64,6 +64,8 @@ static int serial_index(struct uart_port *port)
return (serial8250_reg.minor - 64) + port->line;
}
+static unsigned int skip_txen_test; /* force skip of txen test at init time */
+
/*
* Debugging.
*/
@@ -1382,7 +1384,7 @@ static void serial8250_enable_ms(struct uart_port *port)
static void
receive_chars(struct uart_8250_port *up, unsigned int *status)
{
- struct tty_struct *tty = up->port.info->port.tty;
+ struct tty_struct *tty = up->port.state->port.tty;
unsigned char ch, lsr = *status;
int max_count = 256;
char flag;
@@ -1457,7 +1459,7 @@ ignore_char:
static void transmit_chars(struct uart_8250_port *up)
{
- struct circ_buf *xmit = &up->port.info->xmit;
+ struct circ_buf *xmit = &up->port.state->xmit;
int count;
if (up->port.x_char) {
@@ -1500,7 +1502,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
status |= up->msr_saved_flags;
up->msr_saved_flags = 0;
if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
- up->port.info != NULL) {
+ up->port.state != NULL) {
if (status & UART_MSR_TERI)
up->port.icount.rng++;
if (status & UART_MSR_DDSR)
@@ -1510,7 +1512,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
if (status & UART_MSR_DCTS)
uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
- wake_up_interruptible(&up->port.info->delta_msr_wait);
+ wake_up_interruptible(&up->port.state->port.delta_msr_wait);
}
return status;
@@ -1677,7 +1679,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
INIT_LIST_HEAD(&up->list);
i->head = &up->list;
spin_unlock_irq(&i->lock);
-
+ irq_flags |= up->port.irqflags;
ret = request_irq(up->port.irq, serial8250_interrupt,
irq_flags, "serial", i);
if (ret < 0)
@@ -1764,7 +1766,7 @@ static void serial8250_backup_timeout(unsigned long data)
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
spin_unlock_irqrestore(&up->port.lock, flags);
if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
- (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
+ (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
(lsr & UART_LSR_THRE)) {
iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
iir |= UART_IIR_THRI;
@@ -2026,7 +2028,7 @@ static int serial8250_startup(struct uart_port *port)
* allow register changes to become visible.
*/
spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_SHARE_IRQ)
+ if (up->port.irqflags & IRQF_SHARED)
disable_irq_nosync(up->port.irq);
wait_for_xmitr(up, UART_LSR_THRE);
@@ -2039,7 +2041,7 @@ static int serial8250_startup(struct uart_port *port)
iir = serial_in(up, UART_IIR);
serial_out(up, UART_IER, 0);
- if (up->port.flags & UPF_SHARE_IRQ)
+ if (up->port.irqflags & IRQF_SHARED)
enable_irq(up->port.irq);
spin_unlock_irqrestore(&up->port.lock, flags);
@@ -2108,7 +2110,7 @@ static int serial8250_startup(struct uart_port *port)
is variable. So, let's just don't test if we receive
TX irq. This way, we'll never enable UART_BUG_TXEN.
*/
- if (up->port.flags & UPF_NO_TXEN_TEST)
+ if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
goto dont_test_tx_en;
/*
@@ -2272,7 +2274,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ask the core to calculate the divisor for us.
*/
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0xffff,
+ port->uartclk / 16);
quot = serial8250_get_divisor(port, baud);
/*
@@ -2671,6 +2675,7 @@ static void __init serial8250_isa_init_ports(void)
i++, up++) {
up->port.iobase = old_serial_port[i].port;
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
+ up->port.irqflags = old_serial_port[i].irqflags;
up->port.uartclk = old_serial_port[i].baud_base * 16;
up->port.flags = old_serial_port[i].flags;
up->port.hub6 = old_serial_port[i].hub6;
@@ -2679,7 +2684,7 @@ static void __init serial8250_isa_init_ports(void)
up->port.regshift = old_serial_port[i].iomem_reg_shift;
set_io_from_upio(&up->port);
if (share_irqs)
- up->port.flags |= UPF_SHARE_IRQ;
+ up->port.irqflags |= IRQF_SHARED;
}
}
@@ -2869,6 +2874,7 @@ int __init early_serial_setup(struct uart_port *port)
p->iobase = port->iobase;
p->membase = port->membase;
p->irq = port->irq;
+ p->irqflags = port->irqflags;
p->uartclk = port->uartclk;
p->fifosize = port->fifosize;
p->regshift = port->regshift;
@@ -2942,6 +2948,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.iobase = p->iobase;
port.membase = p->membase;
port.irq = p->irq;
+ port.irqflags = p->irqflags;
port.uartclk = p->uartclk;
port.regshift = p->regshift;
port.iotype = p->iotype;
@@ -2954,7 +2961,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.serial_out = p->serial_out;
port.dev = &dev->dev;
if (share_irqs)
- port.flags |= UPF_SHARE_IRQ;
+ port.irqflags |= IRQF_SHARED;
ret = serial8250_register_port(&port);
if (ret < 0) {
dev_err(&dev->dev, "unable to register port at index %d "
@@ -3096,6 +3103,7 @@ int serial8250_register_port(struct uart_port *port)
uart->port.iobase = port->iobase;
uart->port.membase = port->membase;
uart->port.irq = port->irq;
+ uart->port.irqflags = port->irqflags;
uart->port.uartclk = port->uartclk;
uart->port.fifosize = port->fifosize;
uart->port.regshift = port->regshift;
@@ -3242,6 +3250,9 @@ MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
module_param(nr_uarts, uint, 0644);
MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+module_param(skip_txen_test, uint, 0644);
+MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
+
#ifdef CONFIG_SERIAL_8250_RSA
module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 520260326f3..6e19ea3e48d 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -25,6 +25,7 @@ struct old_serial_port {
unsigned char io_type;
unsigned char *iomem_base;
unsigned short iomem_reg_shift;
+ unsigned long irqflags;
};
/*
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 03422ce878c..e5225725727 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -862,7 +862,7 @@ config SERIAL_IMX_CONSOLE
config SERIAL_UARTLITE
tristate "Xilinx uartlite serial port support"
- depends on PPC32 || MICROBLAZE
+ depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE
select SERIAL_CORE
help
Say Y here if you want to use the Xilinx uartlite serial controller.
@@ -1458,4 +1458,23 @@ config SERIAL_TIMBERDALE
---help---
Add support for UART controller on timberdale.
+config SERIAL_BCM63XX
+ tristate "bcm63xx serial port support"
+ select SERIAL_CORE
+ depends on BCM63XX
+ help
+ If you have a bcm63xx CPU, you can enable its onboard
+ serial port by enabling this options.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bcm963xx_uart.
+
+config SERIAL_BCM63XX_CONSOLE
+ bool "Console on bcm63xx serial port"
+ depends on SERIAL_BCM63XX=y
+ select SERIAL_CORE_CONSOLE
+ help
+ If you have enabled the serial port on the bcm63xx CPU
+ you can make it the console by answering Y to this option.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 97f6fcc8b43..d21d5dd5d04 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
obj-$(CONFIG_SERIAL_PXA) += pxa.o
obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
+obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 58a4879c7e4..429a8ae8693 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -117,7 +117,7 @@ static void pl010_enable_ms(struct uart_port *port)
static void pl010_rx_chars(struct uart_amba_port *uap)
{
- struct tty_struct *tty = uap->port.info->port.tty;
+ struct tty_struct *tty = uap->port.state->port.tty;
unsigned int status, ch, flag, rsr, max_count = 256;
status = readb(uap->port.membase + UART01x_FR);
@@ -172,7 +172,7 @@ static void pl010_rx_chars(struct uart_amba_port *uap)
static void pl010_tx_chars(struct uart_amba_port *uap)
{
- struct circ_buf *xmit = &uap->port.info->xmit;
+ struct circ_buf *xmit = &uap->port.state->xmit;
int count;
if (uap->port.x_char) {
@@ -225,7 +225,7 @@ static void pl010_modem_status(struct uart_amba_port *uap)
if (delta & UART01x_FR_CTS)
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
- wake_up_interruptible(&uap->port.info->delta_msr_wait);
+ wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
}
static irqreturn_t pl010_int(int irq, void *dev_id)
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 72ba0c6d355..ef7adc8135d 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -124,7 +124,7 @@ static void pl011_enable_ms(struct uart_port *port)
static void pl011_rx_chars(struct uart_amba_port *uap)
{
- struct tty_struct *tty = uap->port.info->port.tty;
+ struct tty_struct *tty = uap->port.state->port.tty;
unsigned int status, ch, flag, max_count = 256;
status = readw(uap->port.membase + UART01x_FR);
@@ -175,7 +175,7 @@ static void pl011_rx_chars(struct uart_amba_port *uap)
static void pl011_tx_chars(struct uart_amba_port *uap)
{
- struct circ_buf *xmit = &uap->port.info->xmit;
+ struct circ_buf *xmit = &uap->port.state->xmit;
int count;
if (uap->port.x_char) {
@@ -226,7 +226,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
if (delta & UART01x_FR_CTS)
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
- wake_up_interruptible(&uap->port.info->delta_msr_wait);
+ wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
}
static irqreturn_t pl011_int(int irq, void *dev_id)
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 607d43a3104..3551c5cb709 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -427,7 +427,7 @@ static void atmel_rx_chars(struct uart_port *port)
*/
static void atmel_tx_chars(struct uart_port *port)
{
- struct circ_buf *xmit = &port->info->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) {
UART_PUT_CHAR(port, port->x_char);
@@ -560,7 +560,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
static void atmel_tx_dma(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct circ_buf *xmit = &port->info->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
int count;
@@ -663,14 +663,14 @@ static void atmel_rx_from_ring(struct uart_port *port)
* uart_start(), which takes the lock.
*/
spin_unlock(&port->lock);
- tty_flip_buffer_push(port->info->port.tty);
+ tty_flip_buffer_push(port->state->port.tty);
spin_lock(&port->lock);
}
static void atmel_rx_from_dma(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct tty_struct *tty = port->info->port.tty;
+ struct tty_struct *tty = port->state->port.tty;
struct atmel_dma_buffer *pdc;
int rx_idx = atmel_port->pdc_rx_idx;
unsigned int head;
@@ -776,7 +776,7 @@ static void atmel_tasklet_func(unsigned long data)
if (status_change & ATMEL_US_CTS)
uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
- wake_up_interruptible(&port->info->delta_msr_wait);
+ wake_up_interruptible(&port->state->port.delta_msr_wait);
atmel_port->irq_status_prev = status;
}
@@ -795,7 +795,7 @@ static void atmel_tasklet_func(unsigned long data)
static int atmel_startup(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct tty_struct *tty = port->info->port.tty;
+ struct tty_struct *tty = port->state->port.tty;
int retval;
/*
@@ -854,7 +854,7 @@ static int atmel_startup(struct uart_port *port)
}
if (atmel_use_dma_tx(port)) {
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
- struct circ_buf *xmit = &port->info->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
pdc->buf = xmit->buf;
pdc->dma_addr = dma_map_single(port->dev,
diff --git a/drivers/serial/bcm63xx_uart.c b/drivers/serial/bcm63xx_uart.c
new file mode 100644
index 00000000000..beddaa6e906
--- /dev/null
+++ b/drivers/serial/bcm63xx_uart.c
@@ -0,0 +1,890 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Derived from many drivers using generic_serial interface.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * Serial driver for BCM63xx integrated UART.
+ *
+ * Hardware flow control was _not_ tested since I only have RX/TX on
+ * my board.
+ */
+
+#if defined(CONFIG_SERIAL_BCM63XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/clk.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/sysrq.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <bcm63xx_clk.h>
+#include <bcm63xx_irq.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+
+#define BCM63XX_NR_UARTS 1
+
+static struct uart_port ports[BCM63XX_NR_UARTS];
+
+/*
+ * rx interrupt mask / stat
+ *
+ * mask:
+ * - rx fifo full
+ * - rx fifo above threshold
+ * - rx fifo not empty for too long
+ */
+#define UART_RX_INT_MASK (UART_IR_MASK(UART_IR_RXOVER) | \
+ UART_IR_MASK(UART_IR_RXTHRESH) | \
+ UART_IR_MASK(UART_IR_RXTIMEOUT))
+
+#define UART_RX_INT_STAT (UART_IR_STAT(UART_IR_RXOVER) | \
+ UART_IR_STAT(UART_IR_RXTHRESH) | \
+ UART_IR_STAT(UART_IR_RXTIMEOUT))
+
+/*
+ * tx interrupt mask / stat
+ *
+ * mask:
+ * - tx fifo empty
+ * - tx fifo below threshold
+ */
+#define UART_TX_INT_MASK (UART_IR_MASK(UART_IR_TXEMPTY) | \
+ UART_IR_MASK(UART_IR_TXTRESH))
+
+#define UART_TX_INT_STAT (UART_IR_STAT(UART_IR_TXEMPTY) | \
+ UART_IR_STAT(UART_IR_TXTRESH))
+
+/*
+ * external input interrupt
+ *
+ * mask: any edge on CTS, DCD
+ */
+#define UART_EXTINP_INT_MASK (UART_EXTINP_IRMASK(UART_EXTINP_IR_CTS) | \
+ UART_EXTINP_IRMASK(UART_EXTINP_IR_DCD))
+
+/*
+ * handy uart register accessor
+ */
+static inline unsigned int bcm_uart_readl(struct uart_port *port,
+ unsigned int offset)
+{
+ return bcm_readl(port->membase + offset);
+}
+
+static inline void bcm_uart_writel(struct uart_port *port,
+ unsigned int value, unsigned int offset)
+{
+ bcm_writel(value, port->membase + offset);
+}
+
+/*
+ * serial core request to check if uart tx fifo is empty
+ */
+static unsigned int bcm_uart_tx_empty(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ return (val & UART_IR_STAT(UART_IR_TXEMPTY)) ? 1 : 0;
+}
+
+/*
+ * serial core request to set RTS and DTR pin state and loopback mode
+ */
+static void bcm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_MCTL_REG);
+ val &= ~(UART_MCTL_DTR_MASK | UART_MCTL_RTS_MASK);
+ /* invert of written value is reflected on the pin */
+ if (!(mctrl & TIOCM_DTR))
+ val |= UART_MCTL_DTR_MASK;
+ if (!(mctrl & TIOCM_RTS))
+ val |= UART_MCTL_RTS_MASK;
+ bcm_uart_writel(port, val, UART_MCTL_REG);
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ if (mctrl & TIOCM_LOOP)
+ val |= UART_CTL_LOOPBACK_MASK;
+ else
+ val &= ~UART_CTL_LOOPBACK_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+}
+
+/*
+ * serial core request to return RI, CTS, DCD and DSR pin state
+ */
+static unsigned int bcm_uart_get_mctrl(struct uart_port *port)
+{
+ unsigned int val, mctrl;
+
+ mctrl = 0;
+ val = bcm_uart_readl(port, UART_EXTINP_REG);
+ if (val & UART_EXTINP_RI_MASK)
+ mctrl |= TIOCM_RI;
+ if (val & UART_EXTINP_CTS_MASK)
+ mctrl |= TIOCM_CTS;
+ if (val & UART_EXTINP_DCD_MASK)
+ mctrl |= TIOCM_CD;
+ if (val & UART_EXTINP_DSR_MASK)
+ mctrl |= TIOCM_DSR;
+ return mctrl;
+}
+
+/*
+ * serial core request to disable tx ASAP (used for flow control)
+ */
+static void bcm_uart_stop_tx(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val &= ~(UART_CTL_TXEN_MASK);
+ bcm_uart_writel(port, val, UART_CTL_REG);
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val &= ~UART_TX_INT_MASK;
+ bcm_uart_writel(port, val, UART_IR_REG);
+}
+
+/*
+ * serial core request to (re)enable tx
+ */
+static void bcm_uart_start_tx(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val |= UART_TX_INT_MASK;
+ bcm_uart_writel(port, val, UART_IR_REG);
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val |= UART_CTL_TXEN_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+}
+
+/*
+ * serial core request to stop rx, called before port shutdown
+ */
+static void bcm_uart_stop_rx(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val &= ~UART_RX_INT_MASK;
+ bcm_uart_writel(port, val, UART_IR_REG);
+}
+
+/*
+ * serial core request to enable modem status interrupt reporting
+ */
+static void bcm_uart_enable_ms(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val |= UART_IR_MASK(UART_IR_EXTIP);
+ bcm_uart_writel(port, val, UART_IR_REG);
+}
+
+/*
+ * serial core request to start/stop emitting break char
+ */
+static void bcm_uart_break_ctl(struct uart_port *port, int ctl)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ if (ctl)
+ val |= UART_CTL_XMITBRK_MASK;
+ else
+ val &= ~UART_CTL_XMITBRK_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*
+ * return port type in string format
+ */
+static const char *bcm_uart_type(struct uart_port *port)
+{
+ return (port->type == PORT_BCM63XX) ? "bcm63xx_uart" : NULL;
+}
+
+/*
+ * read all chars in rx fifo and send them to core
+ */
+static void bcm_uart_do_rx(struct uart_port *port)
+{
+ struct tty_struct *tty;
+ unsigned int max_count;
+
+ /* limit number of char read in interrupt, should not be
+ * higher than fifo size anyway since we're much faster than
+ * serial port */
+ max_count = 32;
+ tty = port->info->port.tty;
+ do {
+ unsigned int iestat, c, cstat;
+ char flag;
+
+ /* get overrun/fifo empty information from ier
+ * register */
+ iestat = bcm_uart_readl(port, UART_IR_REG);
+ if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY)))
+ break;
+
+ cstat = c = bcm_uart_readl(port, UART_FIFO_REG);
+ port->icount.rx++;
+ flag = TTY_NORMAL;
+ c &= 0xff;
+
+ if (unlikely((cstat & UART_FIFO_ANYERR_MASK))) {
+ /* do stats first */
+ if (cstat & UART_FIFO_BRKDET_MASK) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ }
+
+ if (cstat & UART_FIF