summaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-01-13 12:10:18 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2011-01-13 12:10:18 -0800
commitab4382d27412e7e3e7c936e8d50d8888dfac3df8 (patch)
tree51d96dea2431140358784b6b426715f37f74fd53 /drivers/serial
parent728674a7e466628df2aeec6d11a2ae1ef968fb67 (diff)
tty: move drivers/serial/ to drivers/tty/serial/
The serial drivers are really just tty drivers, so move them to drivers/tty/ to make things a bit neater overall. This is part of the tty/serial driver movement proceedure as proposed by Arnd Bergmann and approved by everyone involved a number of months ago. Cc: Arnd Bergmann <arnd@arndb.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Rogier Wolff <R.E.Wolff@bitwizard.nl> Cc: Michael H. Warfield <mhw@wittsend.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/21285.c513
-rw-r--r--drivers/serial/68328serial.c1472
-rw-r--r--drivers/serial/68328serial.h188
-rw-r--r--drivers/serial/68360serial.c2978
-rw-r--r--drivers/serial/8250.c3377
-rw-r--r--drivers/serial/8250.h80
-rw-r--r--drivers/serial/8250_accent.c47
-rw-r--r--drivers/serial/8250_acorn.c141
-rw-r--r--drivers/serial/8250_boca.c61
-rw-r--r--drivers/serial/8250_early.c287
-rw-r--r--drivers/serial/8250_exar_st16c554.c52
-rw-r--r--drivers/serial/8250_fourport.c53
-rw-r--r--drivers/serial/8250_gsc.c122
-rw-r--r--drivers/serial/8250_hp300.c327
-rw-r--r--drivers/serial/8250_hub6.c58
-rw-r--r--drivers/serial/8250_mca.c63
-rw-r--r--drivers/serial/8250_pci.c3850
-rw-r--r--drivers/serial/8250_pnp.c523
-rw-r--r--drivers/serial/Kconfig1598
-rw-r--r--drivers/serial/Makefile94
-rw-r--r--drivers/serial/altera_jtaguart.c504
-rw-r--r--drivers/serial/altera_uart.c608
-rw-r--r--drivers/serial/amba-pl010.c825
-rw-r--r--drivers/serial/amba-pl011.c1519
-rw-r--r--drivers/serial/apbuart.c709
-rw-r--r--drivers/serial/apbuart.h64
-rw-r--r--drivers/serial/atmel_serial.c1808
-rw-r--r--drivers/serial/bcm63xx_uart.c891
-rw-r--r--drivers/serial/bfin_5xx.c1600
-rw-r--r--drivers/serial/bfin_sport_uart.c935
-rw-r--r--drivers/serial/bfin_sport_uart.h86
-rw-r--r--drivers/serial/clps711x.c579
-rw-r--r--drivers/serial/cpm_uart/Makefile11
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h147
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c1443
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c138
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.h34
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c174
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.h34
-rw-r--r--drivers/serial/crisv10.c4573
-rw-r--r--drivers/serial/crisv10.h147
-rw-r--r--drivers/serial/dz.c955
-rw-r--r--drivers/serial/dz.h129
-rw-r--r--drivers/serial/icom.c1658
-rw-r--r--drivers/serial/icom.h287
-rw-r--r--drivers/serial/ifx6x60.c1406
-rw-r--r--drivers/serial/ifx6x60.h129
-rw-r--r--drivers/serial/imx.c1380
-rw-r--r--drivers/serial/ioc3_serial.c2199
-rw-r--r--drivers/serial/ioc4_serial.c2953
-rw-r--r--drivers/serial/ip22zilog.c1221
-rw-r--r--drivers/serial/ip22zilog.h281
-rw-r--r--drivers/serial/jsm/Makefile8
-rw-r--r--drivers/serial/jsm/jsm.h388
-rw-r--r--drivers/serial/jsm/jsm_driver.c297
-rw-r--r--drivers/serial/jsm/jsm_neo.c1412
-rw-r--r--drivers/serial/jsm/jsm_tty.c910
-rw-r--r--drivers/serial/kgdboc.c328
-rw-r--r--drivers/serial/m32r_sio.c1192
-rw-r--r--drivers/serial/m32r_sio.h48
-rw-r--r--drivers/serial/m32r_sio_reg.h152
-rw-r--r--drivers/serial/max3100.c926
-rw-r--r--drivers/serial/max3107-aava.c344
-rw-r--r--drivers/serial/max3107.c1213
-rw-r--r--drivers/serial/max3107.h441
-rw-r--r--drivers/serial/mcf.c662
-rw-r--r--drivers/serial/mfd.c1513
-rw-r--r--drivers/serial/mpc52xx_uart.c1527
-rw-r--r--drivers/serial/mpsc.c2159
-rw-r--r--drivers/serial/mrst_max3110.c919
-rw-r--r--drivers/serial/mrst_max3110.h60
-rw-r--r--drivers/serial/msm_serial.c758
-rw-r--r--drivers/serial/msm_serial.h173
-rw-r--r--drivers/serial/mux.c633
-rw-r--r--drivers/serial/netx-serial.c750
-rw-r--r--drivers/serial/nwpserial.c477
-rw-r--r--drivers/serial/of_serial.c201
-rw-r--r--drivers/serial/omap-serial.c1359
-rw-r--r--drivers/serial/pch_uart.c1451
-rw-r--r--drivers/serial/pmac_zilog.c2208
-rw-r--r--drivers/serial/pmac_zilog.h396
-rw-r--r--drivers/serial/pnx8xxx_uart.c854
-rw-r--r--drivers/serial/pxa.c879
-rw-r--r--drivers/serial/s3c2400.c106
-rw-r--r--drivers/serial/s3c2410.c118
-rw-r--r--drivers/serial/s3c2412.c152
-rw-r--r--drivers/serial/s3c2440.c181
-rw-r--r--drivers/serial/s3c24a0.c118
-rw-r--r--drivers/serial/s3c6400.c152
-rw-r--r--drivers/serial/s5pv210.c162
-rw-r--r--drivers/serial/sa1100.c918
-rw-r--r--drivers/serial/samsung.c1487
-rw-r--r--drivers/serial/samsung.h120
-rw-r--r--drivers/serial/sb1250-duart.c976
-rw-r--r--drivers/serial/sc26xx.c757
-rw-r--r--drivers/serial/serial_core.c2578
-rw-r--r--drivers/serial/serial_cs.c869
-rw-r--r--drivers/serial/serial_ks8695.c705
-rw-r--r--drivers/serial/serial_lh7a40x.c682
-rw-r--r--drivers/serial/serial_txx9.c1344
-rw-r--r--drivers/serial/sh-sci.c2027
-rw-r--r--drivers/serial/sh-sci.h660
-rw-r--r--drivers/serial/sn_console.c1085
-rw-r--r--drivers/serial/suncore.c247
-rw-r--r--drivers/serial/suncore.h33
-rw-r--r--drivers/serial/sunhv.c661
-rw-r--r--drivers/serial/sunsab.c1152
-rw-r--r--drivers/serial/sunsab.h322
-rw-r--r--drivers/serial/sunsu.c1608
-rw-r--r--drivers/serial/sunzilog.c1655
-rw-r--r--drivers/serial/sunzilog.h289
-rw-r--r--drivers/serial/timbuart.c531
-rw-r--r--drivers/serial/timbuart.h58
-rw-r--r--drivers/serial/uartlite.c709
-rw-r--r--drivers/serial/ucc_uart.c1537
-rw-r--r--drivers/serial/vr41xx_siu.c978
-rw-r--r--drivers/serial/vt8500_serial.c648
-rw-r--r--drivers/serial/zs.c1304
-rw-r--r--drivers/serial/zs.h284
119 files changed, 0 insertions, 97162 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
deleted file mode 100644
index d89aa38c5cf0..000000000000
--- a/drivers/serial/21285.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * linux/drivers/serial/21285.c
- *
- * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
- *
- * Based on drivers/char/serial.c
- */
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/device.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/hardware/dec21285.h>
-#include <mach/hardware.h>
-
-#define BAUD_BASE (mem_fclk_21285/64)
-
-#define SERIAL_21285_NAME "ttyFB"
-#define SERIAL_21285_MAJOR 204
-#define SERIAL_21285_MINOR 4
-
-#define RXSTAT_DUMMY_READ 0x80000000
-#define RXSTAT_FRAME (1 << 0)
-#define RXSTAT_PARITY (1 << 1)
-#define RXSTAT_OVERRUN (1 << 2)
-#define RXSTAT_ANYERR (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN)
-
-#define H_UBRLCR_BREAK (1 << 0)
-#define H_UBRLCR_PARENB (1 << 1)
-#define H_UBRLCR_PAREVN (1 << 2)
-#define H_UBRLCR_STOPB (1 << 3)
-#define H_UBRLCR_FIFO (1 << 4)
-
-static const char serial21285_name[] = "Footbridge UART";
-
-#define tx_enabled(port) ((port)->unused[0])
-#define rx_enabled(port) ((port)->unused[1])
-
-/*
- * The documented expression for selecting the divisor is:
- * BAUD_BASE / baud - 1
- * However, typically BAUD_BASE is not divisible by baud, so
- * we want to select the divisor that gives us the minimum
- * error. Therefore, we want:
- * int(BAUD_BASE / baud - 0.5) ->
- * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
- * int((BAUD_BASE - (baud >> 1)) / baud)
- */
-
-static void serial21285_stop_tx(struct uart_port *port)
-{
- if (tx_enabled(port)) {
- disable_irq_nosync(IRQ_CONTX);
- tx_enabled(port) = 0;
- }
-}
-
-static void serial21285_start_tx(struct uart_port *port)
-{
- if (!tx_enabled(port)) {
- enable_irq(IRQ_CONTX);
- tx_enabled(port) = 1;
- }
-}
-
-static void serial21285_stop_rx(struct uart_port *port)
-{
- if (rx_enabled(port)) {
- disable_irq_nosync(IRQ_CONRX);
- rx_enabled(port) = 0;
- }
-}
-
-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->state->port.tty;
- unsigned int status, ch, flag, rxs, max_count = 256;
-
- status = *CSR_UARTFLG;
- while (!(status & 0x10) && max_count--) {
- ch = *CSR_UARTDR;
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
- if (unlikely(rxs & RXSTAT_ANYERR)) {
- if (rxs & RXSTAT_PARITY)
- port->icount.parity++;
- else if (rxs & RXSTAT_FRAME)
- port->icount.frame++;
- if (rxs & RXSTAT_OVERRUN)
- port->icount.overrun++;
-
- rxs &= port->read_status_mask;
-
- if (rxs & RXSTAT_PARITY)
- flag = TTY_PARITY;
- else if (rxs & RXSTAT_FRAME)
- flag = TTY_FRAME;
- }
-
- uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
-
- status = *CSR_UARTFLG;
- }
- tty_flip_buffer_push(tty);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- struct circ_buf *xmit = &port->state->xmit;
- int count = 256;
-
- if (port->x_char) {
- *CSR_UARTDR = port->x_char;
- port->icount.tx++;
- port->x_char = 0;
- goto out;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- serial21285_stop_tx(port);
- goto out;
- }
-
- do {
- *CSR_UARTDR = xmit->buf[xmit->tail];
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0 && !(*CSR_UARTFLG & 0x20));
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- serial21285_stop_tx(port);
-
- out:
- return IRQ_HANDLED;
-}
-
-static unsigned int serial21285_tx_empty(struct uart_port *port)
-{
- return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT;
-}
-
-/* no modem control lines */
-static unsigned int serial21285_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-}
-
-static void serial21285_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-static void serial21285_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned long flags;
- unsigned int h_lcr;
-
- spin_lock_irqsave(&port->lock, flags);
- h_lcr = *CSR_H_UBRLCR;
- if (break_state)
- h_lcr |= H_UBRLCR_BREAK;
- else
- h_lcr &= ~H_UBRLCR_BREAK;
- *CSR_H_UBRLCR = h_lcr;
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int serial21285_startup(struct uart_port *port)
-{
- int ret;
-
- tx_enabled(port) = 1;
- rx_enabled(port) = 1;
-
- ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0,
- serial21285_name, port);
- if (ret == 0) {
- ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0,
- serial21285_name, port);
- if (ret)
- free_irq(IRQ_CONRX, port);
- }
-
- return ret;
-}
-
-static void serial21285_shutdown(struct uart_port *port)
-{
- free_irq(IRQ_CONTX, port);
- free_irq(IRQ_CONRX, port);
-}
-
-static void
-serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned long flags;
- unsigned int baud, quot, h_lcr, b;
-
- /*
- * We don't support modem control lines.
- */
- termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
- termios->c_cflag |= CLOCAL;
-
- /*
- * We don't support BREAK character recognition.
- */
- termios->c_iflag &= ~(IGNBRK | BRKINT);
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
- b = port->uartclk / (16 * quot);
- tty_termios_encode_baud_rate(termios, b, b);
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- h_lcr = 0x00;
- break;
- case CS6:
- h_lcr = 0x20;
- break;
- case CS7:
- h_lcr = 0x40;
- break;
- default: /* CS8 */
- h_lcr = 0x60;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- h_lcr |= H_UBRLCR_STOPB;
- if (termios->c_cflag & PARENB) {
- h_lcr |= H_UBRLCR_PARENB;
- if (!(termios->c_cflag & PARODD))
- h_lcr |= H_UBRLCR_PAREVN;
- }
-
- if (port->fifosize)
- h_lcr |= H_UBRLCR_FIFO;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /*
- * Which character status flags are we interested in?
- */
- port->read_status_mask = RXSTAT_OVERRUN;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
-
- /*
- * Which character status flags should we ignore?
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
- if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= RXSTAT_OVERRUN;
-
- /*
- * Ignore all characters if CREAD is not set.
- */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= RXSTAT_DUMMY_READ;
-
- quot -= 1;
-
- *CSR_UARTCON = 0;
- *CSR_L_UBRLCR = quot & 0xff;
- *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
- *CSR_H_UBRLCR = h_lcr;
- *CSR_UARTCON = 1;
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *serial21285_type(struct uart_port *port)
-{
- return port->type == PORT_21285 ? "DC21285" : NULL;
-}
-
-static void serial21285_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, 32);
-}
-
-static int serial21285_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, 32, serial21285_name)
- != NULL ? 0 : -EBUSY;
-}
-
-static void serial21285_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0)
- port->type = PORT_21285;
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
- ret = -EINVAL;
- if (ser->irq != NO_IRQ)
- ret = -EINVAL;
- if (ser->baud_base != port->uartclk / 16)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops serial21285_ops = {
- .tx_empty = serial21285_tx_empty,
- .get_mctrl = serial21285_get_mctrl,
- .set_mctrl = serial21285_set_mctrl,
- .stop_tx = serial21285_stop_tx,
- .start_tx = serial21285_start_tx,
- .stop_rx = serial21285_stop_rx,
- .enable_ms = serial21285_enable_ms,
- .break_ctl = serial21285_break_ctl,
- .startup = serial21285_startup,
- .shutdown = serial21285_shutdown,
- .set_termios = serial21285_set_termios,
- .type = serial21285_type,
- .release_port = serial21285_release_port,
- .request_port = serial21285_request_port,
- .config_port = serial21285_config_port,
- .verify_port = serial21285_verify_port,
-};
-
-static struct uart_port serial21285_port = {
- .mapbase = 0x42000160,
- .iotype = UPIO_MEM,
- .irq = NO_IRQ,
- .fifosize = 16,
- .ops = &serial21285_ops,
- .flags = UPF_BOOT_AUTOCONF,
-};
-
-static void serial21285_setup_ports(void)
-{
- serial21285_port.uartclk = mem_fclk_21285 / 4;
-}
-
-#ifdef CONFIG_SERIAL_21285_CONSOLE
-static void serial21285_console_putchar(struct uart_port *port, int ch)
-{
- while (*CSR_UARTFLG & 0x20)
- barrier();
- *CSR_UARTDR = ch;
-}
-
-static void
-serial21285_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
-}
-
-static void __init
-serial21285_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- if (*CSR_UARTCON == 1) {
- unsigned int tmp;
-
- tmp = *CSR_H_UBRLCR;
- switch (tmp & 0x60) {
- case 0x00:
- *bits = 5;
- break;
- case 0x20:
- *bits = 6;
- break;
- case 0x40:
- *bits = 7;
- break;
- default:
- case 0x60:
- *bits = 8;
- break;
- }
-
- if (tmp & H_UBRLCR_PARENB) {
- *parity = 'o';
- if (tmp & H_UBRLCR_PAREVN)
- *parity = 'e';
- }
-
- tmp = *CSR_L_UBRLCR | (*CSR_M_UBRLCR << 8);
-
- *baud = port->uartclk / (16 * (tmp + 1));
- }
-}
-
-static int __init serial21285_console_setup(struct console *co, char *options)
-{
- struct uart_port *port = &serial21285_port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (machine_is_personal_server())
- baud = 57600;
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- serial21285_get_options(port, &baud, &parity, &bits);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver serial21285_reg;
-
-static struct console serial21285_console =
-{
- .name = SERIAL_21285_NAME,
- .write = serial21285_console_write,
- .device = uart_console_device,
- .setup = serial21285_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &serial21285_reg,
-};
-
-static int __init rs285_console_init(void)
-{
- serial21285_setup_ports();
- register_console(&serial21285_console);
- return 0;
-}
-console_initcall(rs285_console_init);
-
-#define SERIAL_21285_CONSOLE &serial21285_console
-#else
-#define SERIAL_21285_CONSOLE NULL
-#endif
-
-static struct uart_driver serial21285_reg = {
- .owner = THIS_MODULE,
- .driver_name = "ttyFB",
- .dev_name = "ttyFB",
- .major = SERIAL_21285_MAJOR,
- .minor = SERIAL_21285_MINOR,
- .nr = 1,
- .cons = SERIAL_21285_CONSOLE,
-};
-
-static int __init serial21285_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: 21285 driver\n");
-
- serial21285_setup_ports();
-
- ret = uart_register_driver(&serial21285_reg);
- if (ret == 0)
- uart_add_one_port(&serial21285_reg, &serial21285_port);
-
- return ret;
-}
-
-static void __exit serial21285_exit(void)
-{
- uart_remove_one_port(&serial21285_reg, &serial21285_port);
- uart_unregister_driver(&serial21285_reg);
-}
-
-module_init(serial21285_init);
-module_exit(serial21285_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
-MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
deleted file mode 100644
index be0ebce36e54..000000000000
--- a/drivers/serial/68328serial.c
+++ /dev/null
@@ -1,1472 +0,0 @@
-/* 68328serial.c: Serial port driver for 68328 microcontroller
- *
- * Copyright (C) 1995 David S. Miller <davem@caip.rutgers.edu>
- * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
- * Copyright (C) 1998, 1999 D. Jeff Dionne <jeff@uclinux.org>
- * Copyright (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>
- * Copyright (C) 2002-2003 David McCullough <davidm@snapgear.com>
- * Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
- *
- * VZ Support/Fixes Evan Stawnyczy <e@lineo.ca>
- * Multiple UART support Daniel Potts <danielp@cse.unsw.edu.au>
- * Power management support Daniel Potts <danielp@cse.unsw.edu.au>
- * VZ Second Serial Port enable Phil Wilshire
- * 2.4/2.5 port David McCullough
- */
-
-#include <asm/dbg.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/console.h>
-#include <linux/reboot.h>
-#include <linux/keyboard.h>
-#include <linux/init.h>
-#include <linux/pm.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/delay.h>
-#include <asm/uaccess.h>
-
-/* (es) */
-/* note: perhaps we can murge these files, so that you can just
- * define 1 of them, and they can sort that out for themselves
- */
-#if defined(CONFIG_M68EZ328)
-#include <asm/MC68EZ328.h>
-#else
-#if defined(CONFIG_M68VZ328)
-#include <asm/MC68VZ328.h>
-#else
-#include <asm/MC68328.h>
-#endif /* CONFIG_M68VZ328 */
-#endif /* CONFIG_M68EZ328 */
-
-#include "68328serial.h"
-
-/* Turn off usage of real serial interrupt code, to "support" Copilot */
-#ifdef CONFIG_XCOPILOT_BUGS
-#undef USE_INTS
-#else
-#define USE_INTS
-#endif
-
-static struct m68k_serial m68k_soft[NR_PORTS];
-
-static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;
-
-/* multiple ports are contiguous in memory */
-m68328_uart *uart_addr = (m68328_uart *)USTCNT_ADDR;
-
-struct tty_struct m68k_ttys;
-struct m68k_serial *m68k_consinfo = 0;
-
-#define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */
-
-struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/* Debugging... DEBUG_INTR is bad to use when one of the zs
- * lines is your console ;(
- */
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-
-#define RS_ISR_PASS_LIMIT 256
-
-static void change_speed(struct m68k_serial *info);
-
-/*
- * Setup for console. Argument comes from the boot command line.
- */
-
-/* note: this is messy, but it works, again, perhaps defined somewhere else?*/
-#ifdef CONFIG_M68VZ328
-#define CONSOLE_BAUD_RATE 19200
-#define DEFAULT_CBAUD B19200
-#endif
-
-
-#ifndef CONSOLE_BAUD_RATE
-#define CONSOLE_BAUD_RATE 9600
-#define DEFAULT_CBAUD B9600
-#endif
-
-
-static int m68328_console_initted = 0;
-static int m68328_console_baud = CONSOLE_BAUD_RATE;
-static int m68328_console_cbaud = DEFAULT_CBAUD;
-
-
-static inline int serial_paranoia_check(struct m68k_serial *info,
- char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
- static const char *badmagic =
- "Warning: bad magic number for serial struct %s in %s\n";
- static const char *badinfo =
- "Warning: null m68k_serial for %s in %s\n";
-
- if (!info) {
- printk(badinfo, name, routine);
- return 1;
- }
- if (info->magic != SERIAL_MAGIC) {
- printk(badmagic, name, routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-/*
- * This is used to figure out the divisor speeds and the timeouts
- */
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 0 };
-
-/* Sets or clears DTR/RTS on the requested line */
-static inline void m68k_rtsdtr(struct m68k_serial *ss, int set)
-{
- if (set) {
- /* set the RTS/CTS line */
- } else {
- /* clear it */
- }
- return;
-}
-
-/* Utility routines */
-static inline int get_baud(struct m68k_serial *ss)
-{
- unsigned long result = 115200;
- unsigned short int baud = uart_addr[ss->line].ubaud;
- if (GET_FIELD(baud, UBAUD_PRESCALER) == 0x38) result = 38400;
- result >>= GET_FIELD(baud, UBAUD_DIVIDE);
-
- return result;
-}
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_stop(struct tty_struct *tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "rs_stop"))
- return;
-
- local_irq_save(flags);
- uart->ustcnt &= ~USTCNT_TXEN;
- local_irq_restore(flags);
-}
-
-static int rs_put_char(char ch)
-{
- int flags, loops = 0;
-
- local_irq_save(flags);
-
- while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) {
- loops++;
- udelay(5);
- }
-
- UTX_TXDATA = ch;
- udelay(5);
- local_irq_restore(flags);
- return 1;
-}
-
-static void rs_start(struct tty_struct *tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "rs_start"))
- return;
-
- local_irq_save(flags);
- if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) {
-#ifdef USE_INTS
- uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK;
-#else
- uart->ustcnt |= USTCNT_TXEN;
-#endif
- }
- local_irq_restore(flags);
-}
-
-/* Drop into either the boot monitor or kadb upon receiving a break
- * from keyboard/console input.
- */
-static void batten_down_hatches(void)
-{
- /* Drop into the debugger */
-}
-
-static void status_handle(struct m68k_serial *info, unsigned short status)
-{
-#if 0
- if(status & DCD) {
- if((info->port.tty->termios->c_cflag & CRTSCTS) &&
- ((info->curregs[3] & AUTO_ENAB)==0)) {
- info->curregs[3] |= AUTO_ENAB;
- info->pendregs[3] |= AUTO_ENAB;
- write_zsreg(info->m68k_channel, 3, info->curregs[3]);
- }
- } else {
- if((info->curregs[3] & AUTO_ENAB)) {
- info->curregs[3] &= ~AUTO_ENAB;
- info->pendregs[3] &= ~AUTO_ENAB;
- write_zsreg(info->m68k_channel, 3, info->curregs[3]);
- }
- }
-#endif
- /* If this is console input and this is a
- * 'break asserted' status change interrupt
- * see if we can drop into the debugger
- */
- if((status & URX_BREAK) && info->break_abort)
- batten_down_hatches();
- return;
-}
-
-static void receive_chars(struct m68k_serial *info, unsigned short rx)
-{
- struct tty_struct *tty = info->port.tty;
- m68328_uart *uart = &uart_addr[info->line];
- unsigned char ch, flag;
-
- /*
- * This do { } while() loop will get ALL chars out of Rx FIFO
- */
-#ifndef CONFIG_XCOPILOT_BUGS
- do {
-#endif
- ch = GET_FIELD(rx, URX_RXDATA);
-
- if(info->is_cons) {
- if(URX_BREAK & rx) { /* whee, break received */
- status_handle(info, rx);
- return;
-#ifdef CONFIG_MAGIC_SYSRQ
- } else if (ch == 0x10) { /* ^P */
- show_state();
- show_free_areas();
- show_buffers();
-/* show_net_buffers(); */
- return;
- } else if (ch == 0x12) { /* ^R */
- emergency_restart();
- return;
-#endif /* CONFIG_MAGIC_SYSRQ */
- }
- }
-
- if(!tty)
- goto clear_and_exit;
-
- flag = TTY_NORMAL;
-
- if(rx & URX_PARITY_ERROR) {
- flag = TTY_PARITY;
- status_handle(info, rx);
- } else if(rx & URX_OVRUN) {
- flag = TTY_OVERRUN;
- status_handle(info, rx);
- } else if(rx & URX_FRAME_ERROR) {
- flag = TTY_FRAME;
- status_handle(info, rx);
- }
- tty_insert_flip_char(tty, ch, flag);
-#ifndef CONFIG_XCOPILOT_BUGS
- } while((rx = uart->urx.w) & URX_DATA_READY);
-#endif
-
- tty_schedule_flip(tty);
-
-clear_and_exit:
- return;
-}
-
-static void transmit_chars(struct m68k_serial *info)
-{
- m68328_uart *uart = &uart_addr[info->line];
-
- if (info->x_char) {
- /* Send next char */
- uart->utx.b.txdata = info->x_char;
- info->x_char = 0;
- goto clear_and_return;
- }
-
- if((info->xmit_cnt <= 0) || info->port.tty->stopped) {
- /* That's peculiar... TX ints off */
- uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
- goto clear_and_return;
- }
-
- /* Send char */
- uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++];
- info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt--;
-
- if (info->xmit_cnt < WAKEUP_CHARS)
- schedule_work(&info->tqueue);
-
- if(info->xmit_cnt <= 0) {
- /* All done for now... TX ints off */
- uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
- goto clear_and_return;
- }
-
-clear_and_return:
- /* Clear interrupt (should be auto)*/
- return;
-}
-
-/*
- * This is the serial driver's generic interrupt routine
- */
-irqreturn_t rs_interrupt(int irq, void *dev_id)
-{
- struct m68k_serial *info = dev_id;
- m68328_uart *uart;
- unsigned short rx;
- unsigned short tx;
-
- uart = &uart_addr[info->line];
- rx = uart->urx.w;
-
-#ifdef USE_INTS
- tx = uart->utx.w;
-
- if (rx & URX_DATA_READY) receive_chars(info, rx);
- if (tx & UTX_TX_AVAIL) transmit_chars(info);
-#else
- receive_chars(info, rx);
-#endif
- return IRQ_HANDLED;
-}
-
-static void do_softint(struct work_struct *work)
-{
- struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue);
- struct tty_struct *tty;
-
- tty = info->port.tty;
- if (!tty)
- return;
-#if 0
- if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
- tty_wakeup(tty);
- }
-#endif
-}
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred. The path of
- * hangup processing is:
- *
- * serial interrupt routine -> (scheduler tqueue) ->
- * do_serial_hangup() -> tty->hangup() -> rs_hangup()
- *
- */
-static void do_serial_hangup(struct work_struct *work)
-{
- struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue_hangup);
- struct tty_struct *tty;
-
- tty = info->port.tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
-}
-
-
-static int startup(struct m68k_serial * info)
-{
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
-
- if (info->flags & S_INITIALIZED)
- return 0;
-
- if (!info->xmit_buf) {
- info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL);
- if (!info->xmit_buf)
- return -ENOMEM;
- }
-
- local_irq_save(flags);
-
- /*
- * Clear the FIFO buffers and disable them
- * (they will be reenabled in change_speed())
- */
-
- uart->ustcnt = USTCNT_UEN;
- info->xmit_fifo_size = 1;
- uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_TXEN;
- (void)uart->urx.w;
-
- /*
- * Finally, enable sequencing and interrupts
- */
-#ifdef USE_INTS
- uart->ustcnt = USTCNT_UEN | USTCNT_RXEN |
- USTCNT_RX_INTR_MASK | USTCNT_TX_INTR_MASK;
-#else
- uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK;
-#endif
-
- if (info->port.tty)
- clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
- /*
- * and set the speed of the serial port
- */
-
- change_speed(info);
-
- info->flags |= S_INITIALIZED;
- local_irq_restore(flags);
- return 0;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct m68k_serial * info)
-{
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
-
- uart->ustcnt = 0; /* All off! */
- if (!(info->flags & S_INITIALIZED))
- return;
-
- local_irq_save(flags);
-
- if (info->xmit_buf) {
- free_page((unsigned long) info->xmit_buf);
- info->xmit_buf = 0;
- }
-
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- info->flags &= ~S_INITIALIZED;
- local_irq_restore(flags);
-}
-
-struct {
- int divisor, prescale;
-}
-#ifndef CONFIG_M68VZ328
- hw_baud_table[18] = {
- {0,0}, /* 0 */
- {0,0}, /* 50 */
- {0,0}, /* 75 */
- {0,0}, /* 110 */
- {0,0}, /* 134 */
- {0,0}, /* 150 */
- {0,0}, /* 200 */
- {7,0x26}, /* 300 */
- {6,0x26}, /* 600 */
- {5,0x26}, /* 1200 */
- {0,0}, /* 1800 */
- {4,0x26}, /* 2400 */
- {3,0x26}, /* 4800 */
- {2,0x26}, /* 9600 */
- {1,0x26}, /* 19200 */
- {0,0x26}, /* 38400 */
- {1,0x38}, /* 57600 */
- {0,0x38}, /* 115200 */
-};
-#else
- hw_baud_table[18] = {
- {0,0}, /* 0 */
- {0,0}, /* 50 */
- {0,0}, /* 75 */
- {0,0}, /* 110 */
- {0,0}, /* 134 */
- {0,0}, /* 150 */
- {0,0}, /* 200 */
- {0,0}, /* 300 */
- {7,0x26}, /* 600 */
- {6,0x26}, /* 1200 */
- {0,0}, /* 1800 */
- {5,0x26}, /* 2400 */
- {4,0x26}, /* 4800 */
- {3,0x26}, /* 9600 */
- {2,0x26}, /* 19200 */
- {1,0x26}, /* 38400 */
- {0,0x26}, /* 57600 */
- {1,0x38}, /* 115200 */
-};
-#endif
-/* rate = 1036800 / ((65 - prescale) * (1<<divider)) */
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(struct m68k_serial *info)
-{
- m68328_uart *uart = &uart_addr[info->line];
- unsigned short port;
- unsigned short ustcnt;
- unsigned cflag;
- int i;
-
- if (!info->port.tty || !info->port.tty->termios)
- return;
- cflag = info->port.tty->termios->c_cflag;
- if (!(port = info->port))
- return;
-
- ustcnt = uart->ustcnt;
- uart->ustcnt = ustcnt & ~USTCNT_TXEN;
-
- i = cflag & CBAUD;
- if (i & CBAUDEX) {
- i = (i & ~CBAUDEX) + B38400;
- }
-
- info->baud = baud_table[i];
- uart->ubaud = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) |
- PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale);
-
- ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7);
-
- if ((cflag & CSIZE) == CS8)
- ustcnt |= USTCNT_8_7;
-
- if (cflag & CSTOPB)
- ustcnt |= USTCNT_STOP;
-
- if (cflag & PARENB)
- ustcnt |= USTCNT_PARITYEN;
- if (cflag & PARODD)
- ustcnt |= USTCNT_ODD_EVEN;
-
-#ifdef CONFIG_SERIAL_68328_RTS_CTS
- if (cflag & CRTSCTS) {
- uart->utx.w &= ~ UTX_NOCTS;
- } else {
- uart->utx.w |= UTX_NOCTS;
- }
-#endif
-
- ustcnt |= USTCNT_TXEN;
-
- uart->ustcnt = ustcnt;
- return;
-}
-
-/*
- * Fair output driver allows a process to speak.
- */
-static void rs_fair_output(void)
-{
- int left; /* Output no more than that */
- unsigned long flags;
- struct m68k_serial *info = &m68k_soft[0];
- char c;
-
- if (info == 0) return;
- if (info->xmit_buf == 0) return;
-
- local_irq_save(flags);
- left = info->xmit_cnt;
- while (left != 0) {
- c = info->xmit_buf[info->xmit_tail];
- info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt--;
- local_irq_restore(flags);
-
- rs_put_char(c);
-
- local_irq_save(flags);
- left = min(info->xmit_cnt, left-1);
- }
-
- /* Last character is being transmitted now (hopefully). */
- udelay(5);
-
- local_irq_restore(flags);
- return;
-}
-
-/*
- * m68k_console_print is registered for printk.
- */
-void console_print_68328(const char *p)
-{
- char c;
-
- while((c=*(p++)) != 0) {
- if(c == '\n')
- rs_put_char('\r');
- rs_put_char(c);
- }
-
- /* Comment this if you want to have a strict interrupt-driven output */
- rs_fair_output();
-
- return;
-}
-
-static void rs_set_ldisc(struct tty_struct *tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_set_ldisc"))
- return;
-
- info->is_cons = (tty->termios->c_line == N_TTY);
-
- printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off");
-}
-
-static void rs_flush_chars(struct tty_struct *tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
- return;
-#ifndef USE_INTS
- for(;;) {
-#endif
-
- /* Enable transmitter */
- local_irq_save(flags);
-
- if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
- !info->xmit_buf) {
- local_irq_restore(flags);
- return;
- }
-
-#ifdef USE_INTS
- uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK;
-#else
- uart->ustcnt |= USTCNT_TXEN;
-#endif
-
-#ifdef USE_INTS
- if (uart->utx.w & UTX_TX_AVAIL) {
-#else
- if (1) {
-#endif
- /* Send char */
- uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++];
- info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt--;
- }
-
-#ifndef USE_INTS
- while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5);
- }
-#endif
- local_irq_restore(flags);
-}
-
-extern void console_printn(const char * b, int count);
-
-static int rs_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- int c, total = 0;
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "rs_write"))
- return 0;
-
- if (!tty || !info->xmit_buf)
- return 0;
-
- local_save_flags(flags);
- while (1) {
- local_irq_disable();
- c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- local_irq_restore(flags);
-
- if (c <= 0)
- break;
-
- memcpy(info->xmit_buf + info->xmit_head, buf, c);
-
- local_irq_disable();
- info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt += c;
- local_irq_restore(flags);
- buf += c;
- count -= c;
- total += c;
- }
-
- if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
- /* Enable transmitter */
- local_irq_disable();
-#ifndef USE_INTS
- while(info->xmit_cnt) {
-#endif
-
- uart->ustcnt |= USTCNT_TXEN;
-#ifdef USE_INTS
- uart->ustcnt |= USTCNT_TX_INTR_MASK;
-#else
- while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5);
-#endif
- if (uart->utx.w & UTX_TX_AVAIL) {
- uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++];
- info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt--;
- }
-
-#ifndef USE_INTS
- }
-#endif
- local_irq_restore(flags);
- }
-
- return total;
-}
-
-static int rs_write_room(struct tty_struct *tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- int ret;
-
- if (serial_paranoia_check(info, tty->name, "rs_write_room"))
- return 0;
- ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
- if (ret < 0)
- ret = 0;
- return ret;
-}
-
-static int rs_chars_in_buffer(struct tty_struct *tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
- return 0;
- return info->xmit_cnt;
-}
-
-static void rs_flush_buffer(struct tty_struct *tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
- return;
- local_irq_save(flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- local_irq_restore(flags);
- tty_wakeup(tty);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_throttle(struct tty_struct * tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_throttle"))
- return;
-
- if (I_IXOFF(tty))
- info->x_char = STOP_CHAR(tty);
-
- /* Turn off RTS line (do this atomic) */
-}
-
-static void rs_unthrottle(struct tty_struct * tty)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
- return;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- info->x_char = START_CHAR(tty);
- }
-
- /* Assert RTS line (do this atomic) */
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int get_serial_info(struct m68k_serial * info,
- struct serial_struct * retinfo)
-{
- struct serial_struct tmp;
-
- if (!retinfo)
- return -EFAULT;
- memset(&tmp, 0, sizeof(tmp));
- tmp.type = info->type;
- tmp.line = info->line;
- tmp.port = info->port;
- tmp.irq = info->irq;
- tmp.flags = info->flags;
- tmp.baud_base = info->baud_base;
- tmp.close_delay = info->close_delay;
- tmp.closing_wait = info->closing_wait;
- tmp.custom_divisor = info->custom_divisor;
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
-
- return 0;
-}
-
-static int set_serial_info(struct m68k_serial * info,
- struct serial_struct * new_info)
-{
- struct serial_struct new_serial;
- struct m68k_serial old_info;
- int retval = 0;
-
- if (!new_info)
- return -EFAULT;
- if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
- return -EFAULT;
- old_info = *info;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((new_serial.baud_base != info->baud_base) ||
- (new_serial.type != info->type) ||
- (new_serial.close_delay != info->close_delay) ||
- ((new_serial.flags & ~S_USR_MASK) !=
- (info->flags & ~S_USR_MASK)))
- return -EPERM;
- info->flags = ((info->flags & ~S_USR_MASK) |
- (new_serial.flags & S_USR_MASK));
- info->custom_divisor = new_serial.custom_divisor;
- goto check_and_exit;
- }
-
- if (info->count > 1)
- return -EBUSY;
-
- /*
- * OK, past this point, all the error checking has been done.
- * At this point, we start making changes.....
- */
-
- info->baud_base = new_serial.baud_base;
- info->flags = ((info->flags & ~S_FLAGS) |
- (new_serial.flags & S_FLAGS));
- info->type = new_serial.type;
- info->close_delay = new_serial.close_delay;
- info->closing_wait = new_serial.closing_wait;
-
-check_and_exit:
- retval = startup(info);
- return retval;
-}
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct m68k_serial * info, unsigned int *value)
-{
-#ifdef CONFIG_SERIAL_68328_RTS_CTS
- m68328_uart *uart = &uart_addr[info->line];
-#endif
- unsigned char status;
- unsigned long flags;
-
- local_irq_save(flags);
-#ifdef CONFIG_SERIAL_68328_RTS_CTS
- status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0;
-#else
- status = 0;
-#endif
- local_irq_restore(flags);
- return put_user(status, value);
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void send_break(struct m68k_serial * info, unsigned int duration)
-{
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
- if (!info->port)
- return;
- local_irq_save(flags);
-#ifdef USE_INTS
- uart->utx.w |= UTX_SEND_BREAK;
- msleep_interruptible(duration);
- uart->utx.w &= ~UTX_SEND_BREAK;
-#endif
- local_irq_restore(flags);
-}
-
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- int error;
- struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
- int retval;
-
- if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
- return -ENODEV;
-
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
- (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- send_break(info, 250); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- send_break(info, arg ? arg*(100) : 250);
- return 0;
- case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
- case TIOCSERGSTRUCT:
- if (copy_to_user((struct m68k_serial *) arg,
- info, sizeof(struct m68k_serial)))
- return -EFAULT;
- return 0;
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
- struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
-
- change_speed(info);
-
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- rs_start(tty);
- }
-
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * S structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_close(struct tty_struct *tty, struct file * filp)
-{
- struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
- m68328_uart *uart = &uart_addr[info->line];
- unsigned long flags;
-
- if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
- return;
-
- local_irq_save(flags);
-
- if (tty_hung_up_p(filp)) {
- local_irq_restore(flags);
- return;
- }
-
- if ((tty->count == 1) && (info->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. Info->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk("rs_close: bad serial port count; tty->count is 1, "
- "info->count is %d\n", info->count);
- info->count = 1;
- }
- if (--info->count < 0) {
- printk("rs_close: bad serial port count for ttyS%d: %d\n",
- info->line, info->count);
- info->count = 0;
- }
- if (info->count) {
- local_irq_restore(flags);
- return;
- }
- info->flags |= S_CLOSING;
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->closing_wait != S_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
- /*
- * At this point we stop accepting input. To do this, we
- * disable the receive line status interrupts, and tell the
- * interrupt driver to stop checking the data ready bit in the
- * line status register.
- */
-
- uart->ustcnt &= ~USTCNT_RXEN;
- uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK);
-
- shutdown(info);
- rs_flush_buffer(tty);
-
- tty_ldisc_flush(tty);
- tty->closing = 0;
- info->event = 0;
- info->port.tty = NULL;
-#warning "This is not and has never been valid so fix it"
-#if 0
- if (tty->ldisc.num != ldiscs[N_TTY].num) {
- if (tty->ldisc.close)
- (tty->ldisc.close)(tty);
- tty->ldisc = ldiscs[N_TTY];
- tty->termios->c_line = N_TTY;
- if (tty->ldisc.open)
- (tty->ldisc.open)(tty);
- }
-#endif
- if (info->blocked_open) {
- if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
- }
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(S_NORMAL_ACTIVE|S_CLOSING);
- wake_up_interruptible(&info->close_wait);
- local_irq_restore(flags);
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-void rs_hangup(struct tty_struct *tty)
-{
- struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_hangup"))
- return;
-
- rs_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- info->count = 0;
- info->flags &= ~S_NORMAL_ACTIVE;
- info->port.tty = NULL;
- wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- struct m68k_serial *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (info->flags & S_CLOSING) {
- interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- if (info->flags & S_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- info->flags |= S_NORMAL_ACTIVE;
- return 0;
- }
-
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-
- info->count--;
- info->blocked_open++;
- while (1) {
- local_irq_disable();
- m68k_rtsdtr(info, 1);
- local_irq_enable();
- current->state = TASK_INTERRUPTIBLE;
- if (tty_hung_up_p(filp) ||
- !(info->flags & S_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & S_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & S_CLOSING) && do_clocal)
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- tty_unlock();
- schedule();
- tty_lock();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
- info->count++;
- info->blocked_open--;
-
- if (retval)
- return retval;
- info->flags |= S_NORMAL_ACTIVE;
- return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its S structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-int rs_open(struct tty_struct *tty, struct file * filp)
-{
- struct m68k_serial *info;
- int retval, line;
-
- line = tty->index;
-
- if (line >= NR_PORTS || line < 0) /* we have exactly one */
- return -ENODEV;
-
- info = &m68k_soft[line];
-
- if (serial_paranoia_check(info, tty->name, "rs_open"))
- return -ENODEV;
-
- info->count++;
- tty->driver_data = info;
- info->port.tty = tty;
-
- /*
- * Start up serial port
- */
- retval = startup(info);
- if (retval)
- return retval;
-
- return block_til_ready(tty, filp, info);
-}
-
-/* Finally, routines used to initialize the serial driver. */
-
-static void show_serial_version(void)
-{
- printk("MC68328 serial driver version 1.00\n");
-}
-
-static const struct tty_operations rs_ops = {
- .open = rs_open,
- .close = rs_close,
- .write = rs_write,
- .flush_chars = rs_flush_chars,
- .write_room = rs_write_room,
- .chars_in_buffer = rs_chars_in_buffer,
- .flush_buffer = rs_flush_buffer,
- .ioctl = rs_ioctl,
- .throttle = rs_throttle,
- .unthrottle = rs_unthrottle,
- .set_termios = rs_set_termios,
- .stop = rs_stop,
- .start = rs_start,
- .hangup = rs_hangup,
- .set_ldisc = rs_set_ldisc,
-};
-
-/* rs_init inits the driver */
-static int __init
-rs68328_init(void)
-{
- int flags, i;
- struct m68k_serial *info;
-
- serial_driver = alloc_tty_driver(NR_PORTS);
- if (!serial_driver)
- return -ENOMEM;
-
- show_serial_version();
-
- /* Initialize the tty_driver structure */
- /* SPARC: Not all of this is exactly right for us. */
-
- serial_driver->name = "ttyS";
- serial_driver->major = TTY_MAJOR;
- serial_driver->minor_start = 64;
- serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver->subtype = SERIAL_TYPE_NORMAL;
- serial_driver->init_termios = tty_std_termios;
- serial_driver->init_termios.c_cflag =
- m68328_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(serial_driver, &rs_ops);
-
- if (tty_register_driver(serial_driver)) {
- put_tty_driver(serial_driver);
- printk(KERN_ERR "Couldn't register serial driver\n");
- return -ENOMEM;
- }
-
- local_irq_save(flags);
-
- for(i=0;i<NR_PORTS;i++) {
-
- info = &m68k_soft[i];
- info->magic = SERIAL_MAGIC;
- info->port = (int) &uart_addr[i];
- info->port.tty = NULL;
- info->irq = uart_irqs[i];
- info->custom_divisor = 16;
- info->close_delay = 50;
- info->closing_wait = 3000;
- info->x_char = 0;
- info->event = 0;
- info->count = 0;
- info->blocked_open = 0;
- INIT_WORK(&info->tqueue, do_softint);
- INIT_WORK(&info->tqueue_hangup, do_serial_hangup);
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- info->line = i;
- info->is_cons = 1; /* Means shortcuts work */
-
- printk("%s%d at 0x%08x (irq = %d)", serial_driver->name, info->line,
- info->port, info->irq);
- printk(" is a builtin MC68328 UART\n");
-
-#ifdef CONFIG_M68VZ328
- if (i > 0 )
- PJSEL &= 0xCF; /* PSW enable second port output */
-#endif
-
- if (request_irq(uart_irqs[i],
- rs_interrupt,
- IRQF_DISABLED,
- "M68328_UART", info))
- panic("Unable to attach 68328 serial interrupt\n");
- }
- local_irq_restore(flags);
- return 0;
-}
-
-module_init(rs68328_init);
-
-
-
-static void m68328_set_baud(void)
-{
- unsigned short ustcnt;
- int i;
-
- ustcnt = USTCNT;
- USTCNT = ustcnt & ~USTCNT_TXEN;
-
-again:
- for (i = 0; i < ARRAY_SIZE(baud_table); i++)
- if (baud_table[i] == m68328_console_baud)
- break;
- if (i >= ARRAY_SIZE(baud_table)) {
- m68328_console_baud = 9600;
- goto again;
- }
-
- UBAUD = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) |
- PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale);
- ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7);
- ustcnt |= USTCNT_8_7;
- ustcnt |= USTCNT_TXEN;
- USTCNT = ustcnt;
- m68328_console_initted = 1;
- return;
-}
-
-
-int m68328_console_setup(struct console *cp, char *arg)
-{
- int i, n = CONSOLE_BAUD_RATE;
-
- if (!cp)
- return(-1);
-
- if (arg)
- n = simple_strtoul(arg,NULL,0);
-
- for (i = 0; i < ARRAY_SIZE(baud_table); i++)
- if (baud_table[i] == n)
- break;
- if (i < ARRAY_SIZE(baud_table)) {
- m68328_console_baud = n;
- m68328_console_cbaud = 0;
- if (i > 15) {
- m68328_console_cbaud |= CBAUDEX;
- i -= 15;
- }
- m68328_console_cbaud |= i;
- }
-
- m68328_set_baud(); /* make sure baud rate changes */
- return(0);
-}
-
-
-static struct tty_driver *m68328_console_device(struct console *c, int *index)
-{
- *index = c->index;
- return serial_driver;
-}
-
-
-void m68328_console_write (struct console *co, const char *str,
- unsigned int count)
-{
- if (!m68328_console_initted)
- m68328_set_baud();
- while (count--) {
- if (*str == '\n')
- rs_put_char('\r');
- rs_put_char( *str++ );
- }
-}
-
-
-static struct console m68328_driver = {
- .name = "ttyS",
- .write = m68328_console_write,
- .device = m68328_console_device,
- .setup = m68328_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-
-static int __init m68328_console_init(void)
-{
- register_console(&m68328_driver);
- return 0;
-}
-
-console_initcall(m68328_console_init);
diff --git a/drivers/serial/68328serial.h b/drivers/serial/68328serial.h
deleted file mode 100644
index 664ceb0a158c..000000000000
--- a/drivers/serial/68328serial.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/* 68328serial.h: Definitions for the mc68328 serial driver.
- *
- * Copyright (C) 1995 David S. Miller <davem@caip.rutgers.edu>
- * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
- * Copyright (C) 1998, 1999 D. Jeff Dionne <jeff@uclinux.org>
- * Copyright (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>
- *
- * VZ Support/Fixes Evan Stawnyczy <e@lineo.ca>
- */
-
-#ifndef _MC683XX_SERIAL_H
-#define _MC683XX_SERIAL_H
-
-
-struct serial_struct {
- int type;
- int line;
- int port;
- int irq;
- int flags;
- int xmit_fifo_size;
- int custom_divisor;
- int baud_base;
- unsigned short close_delay;
- char reserved_char[2];
- int hub6; /* FIXME: We don't have AT&T Hub6 boards! */
- unsigned short closing_wait; /* time to wait before closing */
- unsigned short closing_wait2; /* no longer used... */
- int reserved[4];
-};
-
-/*
- * For the close wait times, 0 means wait forever for serial port to
- * flush its output. 65535 means don't wait at all.
- */
-#define S_CLOSING_WAIT_INF 0
-#define S_CLOSING_WAIT_NONE 65535
-
-/*
- * Definitions for S_struct (and serial_struct) flags field
- */
-#define S_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
- on the callout port */
-#define S_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
-#define S_SAK 0x0004 /* Secure Attention Key (Orange book) */
-#define S_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
-
-#define S_SPD_MASK 0x0030
-#define S_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
-
-#define S_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
-#define S_SPD_CUST 0x0030 /* Use user-specified divisor */
-
-#define S_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
-#define S_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
-#define S_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
-#define S_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
-#define S_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
-
-#define S_FLAGS 0x0FFF /* Possible legal S flags */
-#define S_USR_MASK 0x0430 /* Legal flags that non-privileged
- * users can set or reset */
-
-/* Internal flags used only by kernel/chr_drv/serial.c */
-#define S_INITIALIZED 0x80000000 /* Serial port was initialized */
-#define S_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
-#define S_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
-#define S_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
-#define S_CLOSING 0x08000000 /* Serial port is closing */
-#define S_CTS_FLOW 0x04000000 /* Do CTS flow control */
-#define S_CHECK_CD 0x02000000 /* i.e., CLOCAL */
-
-/* Software state per channel */
-
-#ifdef __KERNEL__
-
-/*
- * I believe this is the optimal setting that reduces the number of interrupts.
- * At high speeds the output might become a little "bursted" (use USTCNT_TXHE
- * if that bothers you), but in most cases it will not, since we try to
- * transmit characters every time rs_interrupt is called. Thus, quite often
- * you'll see that a receive interrupt occures before the transmit one.
- * -- Vladimir Gurevich
- */
-#define USTCNT_TX_INTR_MASK (USTCNT_TXEE)
-
-/*
- * 68328 and 68EZ328 UARTS are a little bit different. EZ328 has special
- * "Old data interrupt" which occures whenever the data stay in the FIFO
- * longer than 30 bits time. This allows us to use FIFO without compromising
- * latency. '328 does not have this feature and without the real 328-based
- * board I would assume that RXRE is the safest setting.
- *
- * For EZ328 I use RXHE (Half empty) interrupt to reduce the number of
- * interrupts. RXFE (receive queue full) causes the system to lose data
- * at least at 115200 baud
- *
- * If your board is busy doing other stuff, you might consider to use
- * RXRE (data ready intrrupt) instead.
- *
- * The other option is to make these INTR masks run-time configurable, so
- * that people can dynamically adapt them according to the current usage.
- * -- Vladimir Gurevich
- */
-
-/* (es) */
-#if defined(CONFIG_M68EZ328) || defined(CONFIG_M68VZ328)
-#define USTCNT_RX_INTR_MASK (USTCNT_RXHE | USTCNT_ODEN)
-#elif defined(CONFIG_M68328)
-#define USTCNT_RX_INTR_MASK (USTCNT_RXRE)
-#else
-#error Please, define the Rx interrupt events for your CPU
-#endif
-/* (/es) */
-
-/*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-struct m68k_serial {
- char soft_carrier; /* Use soft carrier on this channel */
- char break_abort; /* Is serial console in, so process brk/abrt */
- char is_cons; /* Is this our console. */
-
- /* We need to know the current clock divisor
- * to read the bps rate the chip has currently
- * loaded.
- */
- unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
- int baud;
- int magic;
- int baud_base;
- int port;
- int irq;
- int flags; /* defined in tty.h */
- int type; /* UART type */
- struct tty_struct *tty;
- int read_status_mask;
- int ignore_status_mask;
- int timeout;
- int xmit_fifo_size;
- int custom_divisor;
- int x_char; /* xon/xoff character */
- int close_delay;
- unsigned short closing_wait;
- unsigned short closing_wait2;
- unsigned long event;
- unsigned long last_active;
- int line;
- int count; /* # of fd on device */
- int blocked_open; /* # of blocked opens */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- struct work_struct tqueue;
- struct work_struct tqueue_hangup;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-};
-
-
-#define SERIAL_MAGIC 0x5301
-
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#define SERIAL_XMIT_SIZE 4096
-
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at rs interrupt time.
- */
-#define RS_EVENT_WRITE_WAKEUP 0
-
-/*
- * Define the number of ports supported and their irqs.
- */
-#define NR_PORTS 1
-#define UART_IRQ_DEFNS {UART_IRQ_NUM}
-
-#endif /* __KERNEL__ */
-#endif /* !(_MC683XX_SERIAL_H) */
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
deleted file mode 100644
index 88b13356ec10..000000000000
--- a/drivers/serial/68360serial.c
+++ /dev/null
@@ -1,2978 +0,0 @@
-/*
- * UART driver for 68360 CPM SCC or SMC
- * Copyright (c) 2000 D. Jeff Dionne <jeff@uclinux.org>,
- * Copyright (c) 2000 Michael Leslie <mleslie@lineo.ca>
- * Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
- *
- * I used the serial.c driver as the framework for this driver.
- * Give credit to those guys.
- * The original code was written for the MBX860 board. I tried to make
- * it generic, but there may be some assumptions in the structures that
- * have to be fixed later.
- * To save porting time, I did not bother to change any object names
- * that are not accessed outside of this file.
- * It still needs lots of work........When it was easy, I included code
- * to support the SCCs, but this has never been tested, nor is it complete.
- * Only the SCCs support modem control, so that is not complete either.
- *
- * This module exports the following rs232 io functions:
- *
- * int rs_360_init(void);
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <asm/irq.h>
-#include <asm/m68360.h>
-#include <asm/commproc.h>
-
-
-#ifdef CONFIG_KGDB
-extern void breakpoint(void);
-extern void set_debug_traps(void);
-extern int kgdb_output_string (const char* s, unsigned int count);
-#endif
-
-
-/* #ifdef CONFIG_SERIAL_CONSOLE */ /* This seems to be a post 2.0 thing - mles */
-#include <linux/console.h>
-#include <linux/jiffies.h>
-
-/* this defines the index into rs_table for the port to use
- */
-#ifndef CONFIG_SERIAL_CONSOLE_PORT
-#define CONFIG_SERIAL_CONSOLE_PORT 1 /* ie SMC2 - note USE_SMC2 must be defined */
-#endif
-/* #endif */
-
-#if 0
-/* SCC2 for console
- */
-#undef CONFIG_SERIAL_CONSOLE_PORT
-#define CONFIG_SERIAL_CONSOLE_PORT 2
-#endif
-
-
-#define TX_WAKEUP ASYNC_SHARE_IRQ
-
-static char *serial_name = "CPM UART driver";
-static char *serial_version = "0.03";
-
-static struct tty_driver *serial_driver;
-int serial_console_setup(struct console *co, char *options);
-
-/*
- * Serial driver configuration section. Here are the various options:
- */
-#define SERIAL_PARANOIA_CHECK
-#define CONFIG_SERIAL_NOPAUSE_IO
-#define SERIAL_DO_RESTART
-
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-
-#define _INLINE_ inline
-
-#define DBG_CNT(s)
-
-/* We overload some of the items in the data structure to meet our
- * needs. For example, the port address is the CPM parameter ram
- * offset for the SCC or SMC. The maximum number of ports is 4 SCCs and
- * 2 SMCs. The "hub6" field is used to indicate the channel number, with
- * a flag indicating SCC or SMC, and the number is used as an index into
- * the CPM parameter area for this device.
- * The "type" field is currently set to 0, for PORT_UNKNOWN. It is
- * not currently used. I should probably use it to indicate the port
- * type of SMC or SCC.
- * The SMCs do not support any modem control signals.
- */
-#define smc_scc_num hub6
-#define NUM_IS_SCC ((int)0x00010000)
-#define PORT_NUM(P) ((P) & 0x0000ffff)
-
-
-#if defined (CONFIG_UCQUICC)
-
-volatile extern void *_periph_base;
-/* sipex transceiver
- * mode bits for are on pins
- *
- * SCC2 d16..19
- * SCC3 d20..23
- * SCC4 d24..27
- */
-#define SIPEX_MODE(n,m) ((m & 0x0f)<<(16+4*(n-1)))
-
-static uint sipex_mode_bits = 0x00000000;
-
-#endif
-
-/* There is no `serial_state' defined back here in 2.0.
- * Try to get by with serial_struct
- */
-/* #define serial_state serial_struct */
-
-/* 2.4 -> 2.0 portability problem: async_icount in 2.4 has a few
- * extras: */
-
-#if 0
-struct async_icount_24 {
- __u32 cts, dsr, rng, dcd, tx, rx;
- __u32 frame, parity, overrun, brk;
- __u32 buf_overrun;
-} icount;
-#endif
-
-#if 0
-
-struct serial_state {
- int magic;
- int baud_base;
- unsigned long port;
- int irq;
- int flags;
- int hub6;
- int type;
- int line;
- int revision; /* Chip revision (950) */
- int xmit_fifo_size;
- int custom_divisor;
- int count;
- u8 *iomem_base;
- u16 iomem_reg_shift;
- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
- struct async_icount_24 icount;
- int io_type;
- struct async_struct *info;
-};
-#endif
-
-#define SSTATE_MAGIC 0x5302
-
-
-
-/* SMC2 is sometimes used for low performance TDM interfaces. Define
- * this as 1 if you want SMC2 as a serial port UART managed by this driver.
- * Define this as 0 if you wish to use SMC2 for something else.
- */
-#define USE_SMC2 1
-
-#if 0
-/* Define SCC to ttySx mapping. */
-#define SCC_NUM_BASE (USE_SMC2 + 1) /* SCC base tty "number" */
-
-/* Define which SCC is the first one to use for a serial port. These
- * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
- * for Ethernet, and the first available SCC for serial UART is SCC2.
- * NOTE: IF YOU CHANGE THIS, you have to change the PROFF_xxx and
- * interrupt vectors in the table below to match.
- */
-#define SCC_IDX_BASE 1 /* table index */
-#endif
-
-
-/* Processors other than the 860 only get SMCs configured by default.
- * Either they don't have SCCs or they are allocated somewhere else.
- * Of course, there are now 860s without some SCCs, so we will need to
- * address that someday.
- * The Embedded Planet Multimedia I/O cards use TDM interfaces to the
- * stereo codec parts, and we use SMC2 to help support that.
- */
-static struct serial_state rs_table[] = {
-/* type line PORT IRQ FLAGS smc_scc_num (F.K.A. hub6) */
- { 0, 0, PRSLOT_SMC1, CPMVEC_SMC1, 0, 0 } /* SMC1 ttyS0 */
-#if USE_SMC2
- ,{ 0, 0, PRSLOT_SMC2, CPMVEC_SMC2, 0, 1 } /* SMC2 ttyS1 */
-#endif
-
-#if defined(CONFIG_SERIAL_68360_SCC)
- ,{ 0, 0, PRSLOT_SCC2, CPMVEC_SCC2, 0, (NUM_IS_SCC | 1) } /* SCC2 ttyS2 */
- ,{ 0, 0, PRSLOT_SCC3, CPMVEC_SCC3, 0, (NUM_IS_SCC | 2) } /* SCC3 ttyS3 */
- ,{ 0, 0, PRSLOT_SCC4, CPMVEC_SCC4, 0, (NUM_IS_SCC | 3) } /* SCC4 ttyS4 */
-#endif
-};
-
-#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
-
-/* The number of buffer descriptors and their sizes.
- */
-#define RX_NUM_FIFO 4
-#define RX_BUF_SIZE 32
-#define TX_NUM_FIFO 4
-#define TX_BUF_SIZE 32
-
-#define CONSOLE_NUM_FIFO 2
-#define CONSOLE_BUF_SIZE 4
-
-char *console_fifos[CONSOLE_NUM_FIFO * CONSOLE_BUF_SIZE];
-
-/* The async_struct in serial.h does not really give us what we
- * need, so define our own here.
- */
-typedef struct serial_info {
- int magic;
- int flags;
-
- struct serial_state *state;
- /* struct serial_struct *state; */
- /* struct async_struct *state; */
-
- struct tty_struct *tty;
- int read_status_mask;
- int ignore_status_mask;
- int timeout;
- int line;
- int x_char; /* xon/xoff character */
- int close_delay;
- unsigned short closing_wait;
- unsigned short closing_wait2;
- unsigned long event;
- unsigned long last_active;
- int blocked_open; /* # of blocked opens */
- struct work_struct tqueue;
- struct work_struct tqueue_hangup;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-
-
-/* CPM Buffer Descriptor pointers.
- */
- QUICC_BD *rx_bd_base;
- QUICC_BD *rx_cur;
- QUICC_BD *tx_bd_base;
- QUICC_BD *tx_cur;
-} ser_info_t;
-
-
-/* since kmalloc_init() does not get called until much after this initialization: */
-static ser_info_t quicc_ser_info[NR_PORTS];
-static char rx_buf_pool[NR_PORTS * RX_NUM_FIFO * RX_BUF_SIZE];
-static char tx_buf_pool[NR_PORTS * TX_NUM_FIFO * TX_BUF_SIZE];
-
-static void change_speed(ser_info_t *info);
-static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout);
-
-static inline int serial_paranoia_check(ser_info_t *info,
- char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
- static const char *badmagic =
- "Warning: bad magic number for serial struct (%s) in %s\n";
- static const char *badinfo =
- "Warning: null async_struct for (%s) in %s\n";
-
- if (!info) {
- printk(badinfo, name, routine);
- return 1;
- }
- if (info->magic != SERIAL_MAGIC) {
- printk(badmagic, name, routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-/*
- * This is used to figure out the divisor speeds and the timeouts,
- * indexed by the termio value. The generic CPM functions are responsible
- * for setting and assigning baud rate generators for us.
- */
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
-
-/* This sucks. There is a better way: */
-#if defined(CONFIG_CONSOLE_9600)
- #define CONSOLE_BAUDRATE 9600
-#elif defined(CONFIG_CONSOLE_19200)
- #define CONSOLE_BAUDRATE 19200
-#elif defined(CONFIG_CONSOLE_115200)
- #define CONSOLE_BAUDRATE 115200
-#else
- #warning "console baud rate undefined"
- #define CONSOLE_BAUDRATE 9600
-#endif
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_360_stop(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int idx;
- unsigned long flags;
- volatile struct scc_regs *sccp;
- volatile struct smc_regs *smcp;
-
- if (serial_paranoia_check(info, tty->name, "rs_stop"))
- return;
-
- local_irq_save(flags);
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_sccm &= ~UART_SCCM_TX;
- } else {
- /* smcp = &cpmp->cp_smc[idx]; */
- smcp = &pquicc->smc_regs[idx];
- smcp->smc_smcm &= ~SMCM_TX;
- }
- local_irq_restore(flags);
-}
-
-
-static void rs_360_start(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int idx;
- unsigned long flags;
- volatile struct scc_regs *sccp;
- volatile struct smc_regs *smcp;
-
- if (serial_paranoia_check(info, tty->name, "rs_stop"))
- return;
-
- local_irq_save(flags);
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_sccm |= UART_SCCM_TX;
- } else {
- smcp = &pquicc->smc_regs[idx];
- smcp->smc_smcm |= SMCM_TX;
- }
- local_irq_restore(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines. All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt(). They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off. People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible. After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-static _INLINE_ void receive_chars(ser_info_t *info)
-{
- struct tty_struct *tty = info->port.tty;
- unsigned char ch, flag, *cp;
- /*int ignored = 0;*/
- int i;
- ushort status;
- struct async_icount *icount;
- /* struct async_icount_24 *icount; */
- volatile QUICC_BD *bdp;
-
- icount = &info->state->icount;
-
- /* Just loop through the closed BDs and copy the characters into
- * the buffer.
- */
- bdp = info->rx_cur;
- for (;;) {
- if (bdp->status & BD_SC_EMPTY) /* If this one is empty */
- break; /* we are all done */
-
- /* The read status mask tell us what we should do with
- * incoming characters, especially if errors occur.
- * One special case is the use of BD_SC_EMPTY. If
- * this is not set, we are supposed to be ignoring
- * inputs. In this case, just mark the buffer empty and
- * continue.
- */
- if (!(info->read_status_mask & BD_SC_EMPTY)) {
- bdp->status |= BD_SC_EMPTY;
- bdp->status &=
- ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
- if (bdp->status & BD_SC_WRAP)
- bdp = info->rx_bd_base;
- else
- bdp++;
- continue;
- }
-
- /* Get the number of characters and the buffer pointer.
- */
- i = bdp->length;
- /* cp = (unsigned char *)__va(bdp->buf); */
- cp = (char *)bdp->buf;
- status = bdp->status;
-
- while (i-- > 0) {
- ch = *cp++;
- icount->rx++;
-
-#ifdef SERIAL_DEBUG_INTR
- printk("DR%02x:%02x...", ch, status);
-#endif
- flag = TTY_NORMAL;
-
- if (status & (BD_SC_BR | BD_SC_FR |
- BD_SC_PR | BD_SC_OV)) {
- /*
- * For statistics only
- */
- if (status & BD_SC_BR)
- icount->brk++;
- else if (status & BD_SC_PR)
- icount->parity++;
- else if (status & BD_SC_FR)
- icount->frame++;
- if (status & BD_SC_OV)
- icount->overrun++;
-
- /*
- * Now check to see if character should be
- * ignored, and mask off conditions which
- * should be ignored.
- if (status & info->ignore_status_mask) {
- if (++ignored > 100)
- break;
- continue;
- }
- */
- status &= info->read_status_mask;
-
- if (status & (BD_SC_BR)) {
-#ifdef SERIAL_DEBUG_INTR
- printk("handling break....");
-#endif
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- if (info->flags & ASYNC_SAK)
- do_SAK(tty);
- } else if (status & BD_SC_PR)
- flag = TTY_PARITY;
- else if (status & BD_SC_FR)
- flag = TTY_FRAME;
- }
- tty_insert_flip_char(tty, ch, flag);
- if (status & BD_SC_OV)
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
-
- /* This BD is ready to be used again. Clear status.
- * Get next BD.
- */
- bdp->status |= BD_SC_EMPTY;
- bdp->status &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
- if (bdp->status & BD_SC_WRAP)
- bdp = info->rx_bd_base;
- else
- bdp++;
- }
-
- info->rx_cur = (QUICC_BD *)bdp;
-
- tty_schedule_flip(tty);
-}
-
-static _INLINE_ void receive_break(ser_info_t *info)
-{
- struct tty_struct *tty = info->port.tty;
-
- info->state->icount.brk++;
- /* Check to see if there is room in the tty buffer for
- * the break. If not, we exit now, losing the break. FIXME
- */
- tty_insert_flip_char(tty, 0, TTY_BREAK);
- tty_schedule_flip(tty);
-}
-
-static _INLINE_ void transmit_chars(ser_info_t *info)
-{
-
- if ((info->flags & TX_WAKEUP) ||
- (info->port.tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) {
- schedule_work(&info->tqueue);
- }
-
-#ifdef SERIAL_DEBUG_INTR
- printk("THRE...");
-#endif
-}
-
-#ifdef notdef
- /* I need to do this for the SCCs, so it is left as a reminder.
- */
-static _INLINE_ void check_modem_status(struct async_struct *info)
-{
- int status;
- /* struct async_icount *icount; */
- struct async_icount_24 *icount;
-
- status = serial_in(info, UART_MSR);
-
- if (status & UART_MSR_ANY_DELTA) {
- icount = &info->state->icount;
- /* update input line counters */
- if (status & UART_MSR_TERI)
- icount->rng++;
- if (status & UART_MSR_DDSR)
- icount->dsr++;
- if (status & UART_MSR_DDCD) {
- icount->dcd++;
-#ifdef CONFIG_HARD_PPS
- if ((info->flags & ASYNC_HARDPPS_CD) &&
- (status & UART_MSR_DCD))
- hardpps();
-#endif
- }
- if (status & UART_MSR_DCTS)
- icount->cts++;
- wake_up_interruptible(&info->delta_msr_wait);
- }
-
- if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
- printk("ttys%d CD now %s...", info->line,
- (status & UART_MSR_DCD) ? "on" : "off");
-#endif
- if (status & UART_MSR_DCD)
- wake_up_interruptible(&info->open_wait);
- else {
-#ifdef SERIAL_DEBUG_OPEN
- printk("scheduling hangup...");
-#endif
- queue_task(&info->tqueue_hangup,
- &tq_scheduler);
- }
- }
- if (info->flags & ASYNC_CTS_FLOW) {
- if (info->port.tty->hw_stopped) {
- if (status & UART_MSR_CTS) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
- printk("CTS tx start...");
-#endif
- info->port.tty->hw_stopped = 0;
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
- rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
- return;
- }
- } else {
- if (!(status & UART_MSR_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
- printk("CTS tx stop...");
-#endif
- info->port.tty->hw_stopped = 1;
- info->IER &= ~UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
- }
- }
- }
-}
-#endif
-
-/*
- * This is the serial driver's interrupt routine for a single port
- */
-/* static void rs_360_interrupt(void *dev_id) */ /* until and if we start servicing irqs here */
-static void rs_360_interrupt(int vec, void *dev_id)
-{
- u_char events;
- int idx;
- ser_info_t *info;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- info = dev_id;
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- events = sccp->scc_scce;
- if (events & SCCM_RX)
- receive_chars(info);
- if (events & SCCM_TX)
- transmit_chars(info);
- sccp->scc_scce = events;
- } else {
- smcp = &pquicc->smc_regs[idx];
- events = smcp->smc_smce;
- if (events & SMCM_BRKE)
- receive_break(info);
- if (events & SMCM_RX)
- receive_chars(info);
- if (events & SMCM_TX)
- transmit_chars(info);
- smcp->smc_smce = events;
- }
-
-#ifdef SERIAL_DEBUG_INTR
- printk("rs_interrupt_single(%d, %x)...",
- info->state->smc_scc_num, events);
-#endif
-#ifdef modem_control
- check_modem_status(info);
-#endif
- info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
- printk("end.\n");
-#endif
-}
-
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-
-static void do_softint(void *private_)
-{
- ser_info_t *info = (ser_info_t *) private_;
- struct tty_struct *tty;
-
- tty = info->port.tty;
- if (!tty)
- return;
-
- if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
- tty_wakeup(tty);
-}
-
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred. The path of
- * hangup processing is:
- *
- * serial interrupt routine -> (scheduler tqueue) ->
- * do_serial_hangup() -> tty->hangup() -> rs_hangup()
- *
- */
-static void do_serial_hangup(void *private_)
-{
- struct async_struct *info = (struct async_struct *) private_;
- struct tty_struct *tty;
-
- tty = info->port.tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
-}
-
-
-static int startup(ser_info_t *info)
-{
- unsigned long flags;
- int retval=0;
- int idx;
- /*struct serial_state *state = info->state;*/
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
- volatile struct smc_uart_pram *up;
- volatile struct uart_pram *scup;
-
-
- local_irq_save(flags);
-
- if (info->flags & ASYNC_INITIALIZED) {
- goto errout;
- }
-
-#ifdef maybe
- if (!state->port || !state->type) {
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
- goto errout;
- }
-#endif
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("starting up ttys%d (irq %d)...", info->line, state->irq);
-#endif
-
-
-#ifdef modem_control
- info->MCR = 0;
- if (info->port.tty->termios->c_cflag & CBAUD)
- info->MCR = UART_MCR_DTR | UART_MCR_RTS;
-#endif
-
- if (info->port.tty)
- clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- /*
- * and set the speed of the serial port
- */
- change_speed(info);
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- scup = &pquicc->pram[info->state->port].scc.pscc.u;
-
- scup->mrblr = RX_BUF_SIZE;
- scup->max_idl = RX_BUF_SIZE;
-
- sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
- sccp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
- } else {
- smcp = &pquicc->smc_regs[idx];
-
- /* Enable interrupts and I/O.
- */
- smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
- smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
-
- /* We can tune the buffer length and idle characters
- * to take advantage of the entire incoming buffer size.
- * If mrblr is something other than 1, maxidl has to be
- * non-zero or we never get an interrupt. The maxidl
- * is the number of character times we wait after reception
- * of the last character before we decide no more characters
- * are coming.
- */
- /* up = (smc_uart_t *)&pquicc->cp_dparam[state->port]; */
- /* holy unionized structures, Batman: */
- up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
-
- up->mrblr = RX_BUF_SIZE;
- up->max_idl = RX_BUF_SIZE;
-
- up->brkcr = 1; /* number of break chars */
- }
-
- info->flags |= ASYNC_INITIALIZED;
- local_irq_restore(flags);
- return 0;
-
-errout:
- local_irq_restore(flags);
- return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(ser_info_t *info)
-{
- unsigned long flags;
- struct serial_state *state;
- int idx;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- if (!(info->flags & ASYNC_INITIALIZED))
- return;
-
- state = info->state;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("Shutting down serial port %d (irq %d)....", info->line,
- state->irq);
-#endif
-
- local_irq_save(flags);
-
- idx = PORT_NUM(state->smc_scc_num);
- if (state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_gsmr.w.low &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#ifdef CONFIG_SERIAL_CONSOLE
- /* We can't disable the transmitter if this is the
- * system console.
- */
- if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT)
-#endif
- sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
- } else {
- smcp = &pquicc->smc_regs[idx];
-
- /* Disable interrupts and I/O.
- */
- smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
-#ifdef CONFIG_SERIAL_CONSOLE
- /* We can't disable the transmitter if this is the
- * system console.
- */
- if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT)
-#endif
- smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
- }
-
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- info->flags &= ~ASYNC_INITIALIZED;
- local_irq_restore(flags);
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(ser_info_t *info)
-{
- int baud_rate;
- unsigned cflag, cval, scval, prev_mode;
- int i, bits, sbits, idx;
- unsigned long flags;
- struct serial_state *state;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- if (!info->port.tty || !info->port.tty->termios)
- return;
- cflag = info->port.tty->termios->c_cflag;
-
- state = info->state;
-
- /* Character length programmed into the mode register is the
- * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
- * 1 or 2 stop bits, minus 1.
- * The value 'bits' counts this for us.
- */
- cval = 0;
- scval = 0;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: bits = 5; break;
- case CS6: bits = 6; break;
- case CS7: bits = 7; break;
- case CS8: bits = 8; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: bits = 8; break;
- }
- sbits = bits - 5;
-
- if (cflag & CSTOPB) {
- cval |= SMCMR_SL; /* Two stops */
- scval |= SCU_PMSR_SL;
- bits++;
- }
- if (cflag & PARENB) {
- cval |= SMCMR_PEN;
- scval |= SCU_PMSR_PEN;
- bits++;
- }
- if (!(cflag & PARODD)) {
- cval |= SMCMR_PM_EVEN;
- scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
- }
-
- /* Determine divisor based on baud rate */
- i = cflag & CBAUD;
- if (i >= (sizeof(baud_table)/sizeof(int)))
- baud_rate = 9600;
- else
- baud_rate = baud_table[i];
-
- info->timeout = (TX_BUF_SIZE*HZ*bits);
- info->timeout += HZ/50; /* Add .02 seconds of slop */
-
-#ifdef modem_control
- /* CTS flow control flag and modem status interrupts */
- info->IER &= ~UART_IER_MSI;
- if (info->flags & ASYNC_HARDPPS_CD)
- info->IER |= UART_IER_MSI;
- if (cflag & CRTSCTS) {
- info->flags |= ASYNC_CTS_FLOW;
- info->IER |= UART_IER_MSI;
- } else
- info->flags &= ~ASYNC_CTS_FLOW;
- if (cflag & CLOCAL)
- info->flags &= ~ASYNC_CHECK_CD;
- else {
- info->flags |= ASYNC_CHECK_CD;
- info->IER |= UART_IER_MSI;
- }
- serial_out(info, UART_IER, info->IER);
-#endif
-
- /*
- * Set up parity check flag
- */
- info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
- if (I_INPCK(info->port.tty))
- info->read_status_mask |= BD_SC_FR | BD_SC_PR;
- if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- info->read_status_mask |= BD_SC_BR;
-
- /*
- * Characters to ignore
- */
- info->ignore_status_mask = 0;
- if (I_IGNPAR(info->port.tty))
- info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
- if (I_IGNBRK(info->port.tty)) {
- info->ignore_status_mask |= BD_SC_BR;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (I_IGNPAR(info->port.tty))
- info->ignore_status_mask |= BD_SC_OV;
- }
- /*
- * !!! ignore all characters if CREAD is not set
- */
- if ((cflag & CREAD) == 0)
- info->read_status_mask &= ~BD_SC_EMPTY;
- local_irq_save(flags);
-
- /* Start bit has not been added (so don't, because we would just
- * subtract it later), and we need to add one for the number of
- * stops bits (there is always at least one).
- */
- bits++;
- idx = PORT_NUM(state->smc_scc_num);
- if (state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_psmr = (sbits << 12) | scval;
- } else {
- smcp = &pquicc->smc_regs[idx];
-
- /* Set the mode register. We want to keep a copy of the
- * enables, because we want to put them back if they were
- * present.
- */
- prev_mode = smcp->smc_smcmr;
- smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
- smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
- }
-
- m360_cpm_setbrg((state - rs_table), baud_rate);
-
- local_irq_restore(flags);
-}
-
-static void rs_360_put_char(struct tty_struct *tty, unsigned char ch)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- volatile QUICC_BD *bdp;
-
- if (serial_paranoia_check(info, tty->name, "rs_put_char"))
- return 0;
-
- if (!tty)
- return 0;
-
- bdp = info->tx_cur;
- while (bdp->status & BD_SC_READY);
-
- /* *((char *)__va(bdp->buf)) = ch; */
- *((char *)bdp->buf) = ch;
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- /* Get next BD.
- */
- if (bdp->status & BD_SC_WRAP)
- bdp = info->tx_bd_base;
- else
- bdp++;
-
- info->tx_cur = (QUICC_BD *)bdp;
- return 1;
-
-}
-
-static int rs_360_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- int c, ret = 0;
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- volatile QUICC_BD *bdp;
-
-#ifdef CONFIG_KGDB
- /* Try to let stub handle output. Returns true if it did. */
- if (kgdb_output_string(buf, count))
- return ret;
-#endif
-
- if (serial_paranoia_check(info, tty->name, "rs_write"))
- return 0;
-
- if (!tty)
- return 0;
-
- bdp = info->tx_cur;
-
- while (1) {
- c = min(count, TX_BUF_SIZE);
-
- if (c <= 0)
- break;
-
- if (bdp->status & BD_SC_READY) {
- info->flags |= TX_WAKEUP;
- break;
- }
-
- /* memcpy(__va(bdp->buf), buf, c); */
- memcpy((void *)bdp->buf, buf, c);
-
- bdp->length = c;
- bdp->status |= BD_SC_READY;
-
- buf += c;
- count -= c;
- ret += c;
-
- /* Get next BD.
- */
- if (bdp->status & BD_SC_WRAP)
- bdp = info->tx_bd_base;
- else
- bdp++;
- info->tx_cur = (QUICC_BD *)bdp;
- }
- return ret;
-}
-
-static int rs_360_write_room(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int ret;
-
- if (serial_paranoia_check(info, tty->name, "rs_write_room"))
- return 0;
-
- if ((info->tx_cur->status & BD_SC_READY) == 0) {
- info->flags &= ~TX_WAKEUP;
- ret = TX_BUF_SIZE;
- }
- else {
- info->flags |= TX_WAKEUP;
- ret = 0;
- }
- return ret;
-}
-
-/* I could track this with transmit counters....maybe later.
-*/
-static int rs_360_chars_in_buffer(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
- return 0;
- return 0;
-}
-
-static void rs_360_flush_buffer(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
- return;
-
- /* There is nothing to "flush", whatever we gave the CPM
- * is on its way out.
- */
- tty_wakeup(tty);
- info->flags &= ~TX_WAKEUP;
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_360_send_xchar(struct tty_struct *tty, char ch)
-{
- volatile QUICC_BD *bdp;
-
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_send_char"))
- return;
-
- bdp = info->tx_cur;
- while (bdp->status & BD_SC_READY);
-
- /* *((char *)__va(bdp->buf)) = ch; */
- *((char *)bdp->buf) = ch;
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- /* Get next BD.
- */
- if (bdp->status & BD_SC_WRAP)
- bdp = info->tx_bd_base;
- else
- bdp++;
-
- info->tx_cur = (QUICC_BD *)bdp;
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_360_throttle(struct tty_struct * tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("throttle %s: %d....\n", _tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->name, "rs_throttle"))
- return;
-
- if (I_IXOFF(tty))
- rs_360_send_xchar(tty, STOP_CHAR(tty));
-
-#ifdef modem_control
- if (tty->termios->c_cflag & CRTSCTS)
- info->MCR &= ~UART_MCR_RTS;
-
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
-#endif
-}
-
-static void rs_360_unthrottle(struct tty_struct * tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
- return;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- rs_360_send_xchar(tty, START_CHAR(tty));
- }
-#ifdef modem_control
- if (tty->termios->c_cflag & CRTSCTS)
- info->MCR |= UART_MCR_RTS;
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-#ifdef maybe
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct async_struct * info, unsigned int *value)
-{
- unsigned char status;
- unsigned int result;
-
- local_irq_disable();
- status = serial_in(info, UART_LSR);
- local_irq_enable();
- result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
- return put_user(result,value);
-}
-#endif
-
-static int rs_360_tiocmget(struct tty_struct *tty, struct file *file)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- unsigned int result = 0;
-#ifdef modem_control
- unsigned char control, status;
-
- if (serial_paranoia_check(info, tty->name, __func__))
- return -ENODEV;
-
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
-
- control = info->MCR;
- local_irq_disable();
- status = serial_in(info, UART_MSR);
- local_irq_enable();
- result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
- | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-#ifdef TIOCM_OUT1
- | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
- | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
-#endif
- | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
- | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
- | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
- | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-#endif
- return result;
-}
-
-static int rs_360_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
-{
-#ifdef modem_control
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- unsigned int arg;
-
- if (serial_paranoia_check(info, tty->name, __func__))
- return -ENODEV;
-
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- /* FIXME: locking on info->mcr */
- if (set & TIOCM_RTS)
- info->mcr |= UART_MCR_RTS;
- if (set & TIOCM_DTR)
- info->mcr |= UART_MCR_DTR;
- if (clear & TIOCM_RTS)
- info->MCR &= ~UART_MCR_RTS;
- if (clear & TIOCM_DTR)
- info->MCR &= ~UART_MCR_DTR;
-
-#ifdef TIOCM_OUT1
- if (set & TIOCM_OUT1)
- info->MCR |= UART_MCR_OUT1;
- if (set & TIOCM_OUT2)
- info->MCR |= UART_MCR_OUT2;
- if (clear & TIOCM_OUT1)
- info->MCR &= ~UART_MCR_OUT1;
- if (clear & TIOCM_OUT2)
- info->MCR &= ~UART_MCR_OUT2;
-#endif
-
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
-#endif
- return 0;
-}
-
-/* Sending a break is a two step process on the SMC/SCC. It is accomplished
- * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
- * command. We take advantage of the begin/end functions to make this
- * happen.
- */
-static ushort smc_chan_map[] = {
- CPM_CR_CH_SMC1,
- CPM_CR_CH_SMC2
-};
-
-static ushort scc_chan_map[] = {
- CPM_CR_CH_SCC1,
- CPM_CR_CH_SCC2,
- CPM_CR_CH_SCC3,
- CPM_CR_CH_SCC4
-};
-
-static void begin_break(ser_info_t *info)
-{
- volatile QUICC *cp;
- ushort chan;
- int idx;
-
- cp = pquicc;
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC)
- chan = scc_chan_map[idx];
- else
- chan = smc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-}
-
-static void end_break(ser_info_t *info)
-{
- volatile QUICC *cp;
- ushort chan;
- int idx;
-
- cp = pquicc;
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC)
- chan = scc_chan_map[idx];
- else
- chan = smc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_RESTART_TX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void send_break(ser_info_t *info, unsigned int duration)
-{
-#ifdef SERIAL_DEBUG_SEND_BREAK
- printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
-#endif
- begin_break(info);
- msleep_interruptible(duration);
- end_break(info);
-#ifdef SERIAL_DEBUG_SEND_BREAK
- printk("done jiffies=%lu\n", jiffies);
-#endif
-}
-
-
-/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
-static int rs_360_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- struct async_icount cnow;
-
- local_irq_disable();
- cnow = info->state->icount;
- local_irq_enable();
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
-
- return 0;
-}
-
-static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- int error;
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int retval;
- struct async_icount cnow;
- /* struct async_icount_24 cnow;*/ /* kernel counter temps */
- struct serial_icounter_struct *p_cuser; /* user space */
-
- if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
- return -ENODEV;
-
- if (cmd != TIOCMIWAIT) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (signal_pending(current))
- return -EINTR;
- if (!arg) {
- send_break(info, 250); /* 1/4 second */
- if (signal_pending(current))
- return -EINTR;
- }
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (signal_pending(current))
- return -EINTR;
- send_break(info, arg ? arg*100 : 250);
- if (signal_pending(current))
- return -EINTR;
- return 0;
- case TIOCSBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- begin_break(info);
- return 0;
- case TIOCCBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- end_break(info);
- return 0;
-#ifdef maybe
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
-#endif
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
- case TIOCMIWAIT:
-#ifdef modem_control
- local_irq_disable();
- /* note the counters on entry */
- cprev = info->state->icount;
- local_irq_enable();
- while (1) {
- interruptible_sleep_on(&info->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- local_irq_disable();
- cnow = info->state->icount; /* atomic copy */
- local_irq_enable();
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
-#else
- return 0;
-#endif
-
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-/* FIX UP modem control here someday......
-*/
-static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- change_speed(info);
-
-#ifdef modem_control
- /* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) &&
- !(tty->termios->c_cflag & CBAUD)) {
- info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
- }
-
- /* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) &&
- (tty->termios->c_cflag & CBAUD)) {
- info->MCR |= UART_MCR_DTR;
- if (!tty->hw_stopped ||
- !(tty->termios->c_cflag & CRTSCTS)) {
- info->MCR |= UART_MCR_RTS;
- }
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
- }
-
- /* Handle turning off CRTSCTS */
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- rs_360_start(tty);
- }
-#endif
-
-#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(&info->open_wait);
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_360_close(struct tty_struct *tty, struct file * filp)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- /* struct async_state *state; */
- struct serial_state *state;
- unsigned long flags;
- int idx;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
- return;
-
- state = info->state;
-
- local_irq_save(flags);
-
- if (tty_hung_up_p(filp)) {
- DBG_CNT("before DEC-hung");
- local_irq_restore(flags);
- return;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_close ttys%d, count = %d\n", info->line, state->count);
-#endif
- if ((tty->count == 1) && (state->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk("rs_close: bad serial port count; tty->count is 1, "
- "state->count is %d\n", state->count);
- state->count = 1;
- }
- if (--state->count < 0) {
- printk("rs_close: bad serial port count for ttys%d: %d\n",
- info->line, state->count);
- state->count = 0;
- }
- if (state->count) {
- DBG_CNT("before DEC-2");
- local_irq_restore(flags);
- return;
- }
- info->flags |= ASYNC_CLOSING;
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
- /*
- * At this point we stop accepting input. To do this, we
- * disable the receive line status interrupts, and tell the
- * interrupt driver to stop checking the data ready bit in the
- * line status register.
- */
- info->read_status_mask &= ~BD_SC_EMPTY;
- if (info->flags & ASYNC_INITIALIZED) {
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_sccm &= ~UART_SCCM_RX;
- sccp->scc_gsmr.w.low &= ~SCC_GSMRL_ENR;
- } else {
- smcp = &pquicc->smc_regs[idx];
- smcp->smc_smcm &= ~SMCM_RX;
- smcp->smc_smcmr &= ~SMCMR_REN;
- }
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- rs_360_wait_until_sent(tty, info->timeout);
- }
- shutdown(info);
- rs_360_flush_buffer(tty);
- tty_ldisc_flush(tty);
- tty->closing = 0;
- info->event = 0;
- info->port.tty = NULL;
- if (info->blocked_open) {
- if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
- }
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
- local_irq_restore(flags);
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- unsigned long orig_jiffies, char_time;
- /*int lsr;*/
- volatile QUICC_BD *bdp;
-
- if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
- return;
-
-#ifdef maybe
- if (info->state->type == PORT_UNKNOWN)
- return;
-#endif
-
- orig_jiffies = jiffies;
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = 1;
- if (timeout)
- char_time = min(char_time, (unsigned long)timeout);
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
- printk("jiff=%lu...", jiffies);
-#endif
-
- /* We go through the loop at least once because we can't tell
- * exactly when the last character exits the shifter. There can
- * be at least two characters waiting to be sent after the buffers
- * are empty.
- */
- do {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-/* current->counter = 0; make us low-priority */
- msleep_interruptible(jiffies_to_msecs(char_time));
- if (signal_pending(current))
- break;
- if (timeout && (time_after(jiffies, orig_jiffies + timeout)))
- break;
- /* The 'tx_cur' is really the next buffer to send. We
- * have to back up to the previous BD and wait for it
- * to go. This isn't perfect, because all this indicates
- * is the buffer is available. There are still characters
- * in the CPM FIFO.
- */
- bdp = info->tx_cur;
- if (bdp == info->tx_bd_base)
- bdp += (TX_NUM_FIFO-1);
- else
- bdp--;
- } while (bdp->status & BD_SC_READY);
- current->state = TASK_RUNNING;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rs_360_hangup(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- struct serial_state *state = info->state;
-
- if (serial_paranoia_check(info, tty->name, "rs_hangup"))
- return;
-
- state = info->state;
-
- rs_360_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- state->count = 0;
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- info->port.tty = NULL;
- wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- ser_info_t *info)
-{
-#ifdef DO_THIS_LATER
- DECLARE_WAITQUEUE(wait, current);
-#endif
- struct serial_state *state = info->state;
- int retval;
- int do_clocal = 0;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- * If this is an SMC port, we don't have modem control to wait
- * for, so just get out here.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR)) ||
- !(info->state->smc_scc_num & NUM_IS_SCC)) {
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, state->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
-#ifdef DO_THIS_LATER
- add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready before block: ttys%d, count = %d\n",
- state->line, state->count);
-#endif
- local_irq_disable();
- if (!tty_hung_up_p(filp))
- state->count--;
- local_irq_enable();
- info->blocked_open++;
- while (1) {
- local_irq_disable();
- if (tty->termios->c_cflag & CBAUD)
- serial_out(info, UART_MCR,
- serial_inp(info, UART_MCR) |
- (UART_MCR_DTR | UART_MCR_RTS));
- local_irq_enable();
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & ASYNC_CLOSING) &&
- (do_clocal || (serial_in(info, UART_MSR) &
- UART_MSR_DCD)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready blocking: ttys%d, count = %d\n",
- info->line, state->count);
-#endif
- tty_unlock();
- schedule();
- tty_lock();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
- state->count++;
- info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready after blocking: ttys%d, count = %d\n",
- info->line, state->count);
-#endif
-#endif /* DO_THIS_LATER */
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-static int get_async_struct(int line, ser_info_t **ret_info)
-{
- struct serial_state *sstate;
-
- sstate = rs_table + line;
- if (sstate->info) {
- sstate->count++;
- *ret_info = (ser_info_t *)sstate->info;
- return 0;
- }
- else {
- return -ENOMEM;
- }
-}
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_360_open(struct tty_struct *tty, struct file * filp)
-{
- ser_info_t *info;
- int retval, line;
-
- line = tty->index;
- if ((line < 0) || (line >= NR_PORTS))
- return -ENODEV;
- retval = get_async_struct(line, &info);
- if (retval)
- return retval;
- if (serial_paranoia_check(info, tty->name, "rs_open"))
- return -ENODEV;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open %s, count = %d\n", tty->name, info->state->count);
-#endif
- tty->driver_data = info;
- info->port.tty = tty;
-
- /*
- * Start up serial port
- */
- retval = startup(info);
- if (retval)
- return retval;
-
- retval = block_til_ready(tty, filp, info);
- if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open returning after block_til_ready with %d\n",
- retval);
-#endif
- return retval;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open %s successful...", tty->name);
-#endif
- return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline int line_info(char *buf, struct serial_state *state)
-{
-#ifdef notdef
- struct async_struct *info = state->info, scr_info;
- char stat_buf[30], control, status;
-#endif
- int ret;
-
- ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
- state->line,
- (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC",
- (unsigned int)(state->port), state->irq);
-
- if (!state->port || (state->type == PORT_UNKNOWN)) {
- ret += sprintf(buf+ret, "\n");
- return ret;
- }
-
-#ifdef notdef
- /*
- * Figure out the current RS-232 lines
- */
- if (!info) {
- info = &scr_info; /* This is just for serial_{in,out} */
-
- info->magic = SERIAL_MAGIC;
- info->port = state->port;
- info->flags = state->flags;
- info->quot = 0;
- info->port.tty = NULL;
- }
- local_irq_disable();
- status = serial_in(info, UART_MSR);
- control = info ? info->MCR : serial_in(info, UART_MCR);
- local_irq_enable();
-
- stat_buf[0] = 0;
- stat_buf[1] = 0;
- if (control & UART_MCR_RTS)
- strcat(stat_buf, "|RTS");
- if (status & UART_MSR_CTS)
- strcat(stat_buf, "|CTS");
- if (control & UART_MCR_DTR)
- strcat(stat_buf, "|DTR");
- if (status & UART_MSR_DSR)
- strcat(stat_buf, "|DSR");
- if (status & UART_MSR_DCD)
- strcat(stat_buf, "|CD");
- if (status & UART_MSR_RI)
- strcat(stat_buf, "|RI");
-
- if (info->quot) {
- ret += sprintf(buf+ret, " baud:%d",
- state->baud_base / info->quot);
- }
-
- ret += sprintf(buf+ret, " tx:%d rx:%d",
- state->icount.tx, state->icount.rx);
-
- if (state->icount.frame)
- ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
-
- if (state->icount.parity)
- ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
-
- if (state->icount.brk)
- ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
-
- if (state->icount.overrun)
- ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
-
- /*
- * Last thing is the RS-232 status lines
- */
- ret += sprintf(buf+ret, " %s\n", stat_buf+1);
-#endif
- return ret;
-}
-
-int rs_360_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- int i, len = 0;
- off_t begin = 0;
-
- len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
- for (i = 0; i < NR_PORTS && len < 4000; i++) {
- len += line_info(page + len, &rs_table[i]);
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
- }
- *eof = 1;
-done:
- if (off >= len+begin)
- return 0;
- *start = page + (begin-off);
- return ((count < begin+len-off) ? count : begin+len-off);
-}
-
-/*
- * ---------------------------------------------------------------------
- * rs_init() and friends
- *
- * rs_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static _INLINE_ void show_serial_version(void)
-{
- printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-
-/*
- * The serial console driver used during boot. Note that these names
- * clash with those found in "serial.c", so we currently can't support
- * the 16xxx uarts and these at the same time. I will fix this to become
- * an indirect function call from tty_io.c (or something).
- */
-
-#ifdef CONFIG_SERIAL_CONSOLE
-
-/*
- * Print a string to the serial port trying not to disturb any possible
- * real use of the port...
- */
-static void my_console_write(int idx, const char *s,
- unsigned count)
-{
- struct serial_state *ser;
- ser_info_t *info;
- unsigned i;
- QUICC_BD *bdp, *bdbase;
- volatile struct smc_uart_pram *up;
- volatile u_char *cp;
-
- ser = rs_table + idx;
-
-
- /* If the port has been initialized for general use, we have
- * to use the buffer descriptors allocated there. Otherwise,
- * we simply use the single buffer allocated.
- */
- if ((info = (ser_info_t *)ser->info) != NULL) {
- bdp = info->tx_cur;
- bdbase = info->tx_bd_base;
- }
- else {
- /* Pointer to UART in parameter ram.
- */
- /* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */
- up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u;
-
- /* Get the address of the host memory buffer.
- */
- bdp = bdbase = (QUICC_BD *)((uint)pquicc + (uint)up->tbase);
- }
-
- /*
- * We need to gracefully shut down the transmitter, disable
- * interrupts, then send our bytes out.
- */
-
- /*
- * Now, do each character. This is not as bad as it looks
- * since this is a holding FIFO and not a transmitting FIFO.
- * We could add the complexity of filling the entire transmit
- * buffer, but we would just wait longer between accesses......
- */
- for (i = 0; i < count; i++, s++) {
- /* Wait for transmitter fifo to empty.
- * Ready indicates output is ready, and xmt is doing
- * that, not that it is ready for us to send.
- */
- while (bdp->status & BD_SC_READY);
-
- /* Send the character out.
- */
- cp = bdp->buf;
- *cp = *s;
-
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- if (bdp->status & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
-
- /* if a LF, also do CR... */
- if (*s == 10) {
- while (bdp->status & BD_SC_READY);
- /* cp = __va(bdp->buf); */
- cp = bdp->buf;
- *cp = 13;
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- if (bdp->status & BD_SC_WRAP) {
- bdp = bdbase;
- }
- else {
- bdp++;
- }
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- while (bdp->status & BD_SC_READY);
-
- if (info)
- info->tx_cur = (QUICC_BD *)bdp;
-}
-
-static void serial_console_write(struct console *c, const char *s,
- unsigned count)
-{
-#ifdef CONFIG_KGDB
- /* Try to let stub handle output. Returns true if it did. */
- if (kgdb_output_string(s, count))
- return;
-#endif
- my_console_write(c->index, s, count);
-}
-
-
-
-/*void console_print_68360(const char *p)
-{
- const char *cp = p;
- int i;
-
- for (i=0;cp[i]!=0;i++);
-
- serial_console_write (p, i);
-
- //Comment this if you want to have a strict interrupt-driven output
- //rs_fair_output();
-
- return;
-}*/
-
-
-
-
-
-
-#ifdef CONFIG_XMON
-int
-xmon_360_write(const char *s, unsigned count)
-{
- my_console_write(0, s, count);
- return(count);
-}
-#endif
-
-#ifdef CONFIG_KGDB
-void
-putDebugChar(char ch)
-{
- my_console_write(0, &ch, 1);
-}
-#endif
-
-/*
- * Receive character from the serial port. This only works well
- * before the port is initialized for real use.
- */
-static int my_console_wait_key(int idx, int xmon, char *obuf)
-{
- struct serial_state *ser;
- u_char c, *cp;
- ser_info_t *info;
- QUICC_BD *bdp;
- volatile struct smc_uart_pram *up;
- int i;
-
- ser = rs_table + idx;
-
- /* Get the address of the host memory buffer.
- * If the port has been initialized for general use, we must
- * use information from the port structure.
- */
- if ((info = (ser_info_t *)ser->info))
- bdp = info->rx_cur;
- else
- /* bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase]; */
- bdp = (QUICC_BD *)((uint)pquicc + (uint)up->tbase);
-
- /* Pointer to UART in parameter ram.
- */
- /* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */
- up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
-
- /*
- * We need to gracefully shut down the receiver, disable
- * interrupts, then read the input.
- * XMON just wants a poll. If no character, return -1, else
- * return the character.
- */
- if (!xmon) {
- while (bdp->status & BD_SC_EMPTY);
- }
- else {
- if (bdp->status & BD_SC_EMPTY)
- return -1;
- }
-
- cp = (char *)bdp->buf;
-
- if (obuf) {
- i = c = bdp->length;
- while (i-- > 0)
- *obuf++ = *cp++;
- }
- else {
- c = *cp;
- }
- bdp->status |= BD_SC_EMPTY;
-
- if (info) {
- if (bdp->status & BD_SC_WRAP) {
- bdp = info->rx_bd_base;
- }
- else {
- bdp++;
- }
- info->rx_cur = (QUICC_BD *)bdp;
- }
-
- return((int)c);
-}
-
-static int serial_console_wait_key(struct console *co)
-{
- return(my_console_wait_key(co->index, 0, NULL));
-}
-
-#ifdef CONFIG_XMON
-int
-xmon_360_read_poll(void)
-{
- return(my_console_wait_key(0, 1, NULL));
-}
-
-int
-xmon_360_read_char(void)
-{
- return(my_console_wait_key(0, 0, NULL));
-}
-#endif
-
-#ifdef CONFIG_KGDB
-static char kgdb_buf[RX_BUF_SIZE], *kgdp;
-static int kgdb_chars;
-
-unsigned char
-getDebugChar(void)
-{
- if (kgdb_chars <= 0) {
- kgdb_chars = my_console_wait_key(0, 0, kgdb_buf);
- kgdp = kgdb_buf;
- }
- kgdb_chars--;
-
- return(*kgdp++);
-}
-
-void kgdb_interruptible(int state)
-{
-}
-void kgdb_map_scc(void)
-{
- struct serial_state *ser;
- uint mem_addr;
- volatile QUICC_BD *bdp;
- volatile smc_uart_t *up;
-
- cpmp = (cpm360_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
-
- /* To avoid data cache CPM DMA coherency problems, allocate a
- * buffer in the CPM DPRAM. This will work until the CPM and
- * serial ports are initialized. At that time a memory buffer
- * will be allocated.
- * The port is already initialized from the boot procedure, all
- * we do here is give it a different buffer and make it a FIFO.
- */
-
- ser = rs_table;
-
- /* Right now, assume we are using SMCs.
- */
- up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
-
- /* Allocate space for an input FIFO, plus a few bytes for output.
- * Allocate bytes to maintain word alignment.
- */
- mem_addr = (uint)(&cpmp->cp_dpmem[0x1000]);
-
- /* Set the physical address of the host memory buffers in
- * the buffer descriptors.
- */
- bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase];
- bdp->buf = mem_addr;
-
- bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_tbase];
- bdp->buf = mem_addr+RX_BUF_SIZE;
-
- up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */
- up->smc_maxidl = RX_BUF_SIZE;
-}
-#endif
-
-static struct tty_struct *serial_console_device(struct console *c, int *index)
-{
- *index = c->index;
- return serial_driver;
-}
-
-
-struct console sercons = {
- .name = "ttyS",
- .write = serial_console_write,
- .device = serial_console_device,
- .wait_key = serial_console_wait_key,
- .setup = serial_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = CONFIG_SERIAL_CONSOLE_PORT,
-};
-
-
-
-/*
- * Register console.
- */
-long console_360_init(long kmem_start, long kmem_end)
-{
- register_console(&sercons);
- /*register_console (console_print_68360); - 2.0.38 only required a write
- function pointer. */
- return kmem_start;
-}
-
-#endif
-
-/* Index in baud rate table of the default console baud rate.
-*/
-static int baud_idx;
-
-static const struct tty_operations rs_360_ops = {
- .owner = THIS_MODULE,
- .open = rs_360_open,
- .close = rs_360_close,
- .write = rs_360_write,
- .put_char = rs_360_put_char,
- .write_room = rs_360_write_room,
- .chars_in_buffer = rs_360_chars_in_buffer,
- .flush_buffer = rs_360_flush_buffer,
- .ioctl = rs_360_ioctl,
- .throttle = rs_360_throttle,
- .unthrottle = rs_360_unthrottle,
- /* .send_xchar = rs_360_send_xchar, */
- .set_termios = rs_360_set_termios,
- .stop = rs_360_stop,
- .start = rs_360_start,
- .hangup = rs_360_hangup,
- /* .wait_until_sent = rs_360_wait_until_sent, */
- /* .read_proc = rs_360_read_proc, */
- .tiocmget = rs_360_tiocmget,
- .tiocmset = rs_360_tiocmset,
-};
-
-static int __init rs_360_init(void)
-{
- struct serial_state * state;
- ser_info_t *info;
- void *mem_addr;
- uint dp_addr, iobits;
- int i, j, idx;
- ushort chan;
- QUICC_BD *bdp;
- volatile QUICC *cp;
- volatile struct smc_regs *sp;
- volatile struct smc_uart_pram *up;
- volatile struct scc_regs *scp;
- volatile struct uart_pram *sup;
- /* volatile immap_t *immap; */
-
- serial_driver = alloc_tty_driver(NR_PORTS);
- if (!serial_driver)
- return -1;
-
- show_serial_version();
-
- serial_driver->name = "ttyS";
- serial_driver->major = TTY_MAJOR;
- serial_driver->minor_start = 64;
- serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver->subtype = SERIAL_TYPE_NORMAL;
- serial_driver->init_termios = tty_std_termios;
- serial_driver->init_termios.c_cflag =
- baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(serial_driver, &rs_360_ops);
-
- if (tty_register_driver(serial_driver))
- panic("Couldn't register serial driver\n");
-
- cp = pquicc; /* Get pointer to Communication Processor */
- /* immap = (immap_t *)IMAP_ADDR; */ /* and to internal registers */
-
-
- /* Configure SCC2, SCC3, and SCC4 instead of port A parallel I/O.
- */
- /* The "standard" configuration through the 860.
- */
-/* immap->im_ioport.iop_papar |= 0x00fc; */
-/* immap->im_ioport.iop_padir &= ~0x00fc; */
-/* immap->im_ioport.iop_paodr &= ~0x00fc; */
- cp->pio_papar |= 0x00fc;
- cp->pio_padir &= ~0x00fc;
- /* cp->pio_paodr &= ~0x00fc; */
-
-
- /* Since we don't yet do modem control, connect the port C pins
- * as general purpose I/O. This will assert CTS and CD for the
- * SCC ports.
- */
- /* FIXME: see 360um p.7-365 and 860um p.34-12
- * I can't make sense of these bits - mleslie*/
-/* immap->im_ioport.iop_pcdir |= 0x03c6; */
-/* immap->im_ioport.iop_pcpar &= ~0x03c6; */
-
-/* cp->pio_pcdir |= 0x03c6; */
-/* cp->pio_pcpar &= ~0x03c6; */
-
-
-
- /* Connect SCC2 and SCC3 to NMSI. Connect BRG3 to SCC2 and
- * BRG4 to SCC3.
- */
- cp->si_sicr &= ~0x00ffff00;
- cp->si_sicr |= 0x001b1200;
-
-#ifdef CONFIG_PP04
- /* Frequentis PP04 forced to RS-232 until we know better.
- * Port C 12 and 13 low enables RS-232 on SCC3 and SCC4.
- */
- immap->im_ioport.iop_pcdir |= 0x000c;
- immap->im_ioport.iop_pcpar &= ~0x000c;
- immap->im_ioport.iop_pcdat &= ~0x000c;
-
- /* This enables the TX driver.
- */
- cp->cp_pbpar &= ~0x6000;
- cp->cp_pbdat &= ~0x6000;
-#endif
-
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- state->magic = SSTATE_MAGIC;
- state->line = i;
- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
- state->icount.cts = state->icount.dsr =
- state->icount.rng = state->icount.dcd = 0;
- state->icount.rx = state->icount.tx = 0;
- state->icount.frame = state->icount.parity = 0;
- state->icount.overrun = state->icount.brk = 0;
- printk(KERN_INFO "ttyS%d at irq 0x%02x is an %s\n",
- i, (unsigned int)(state->irq),
- (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");
-
-#ifdef CONFIG_SERIAL_CONSOLE
- /* If we just printed the message on the console port, and
- * we are about to initialize it for general use, we have
- * to wait a couple of character times for the CR/NL to
- * make it out of the transmit buffer.
- */
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- mdelay(8);
-
-
-/* idx = PORT_NUM(info->state->smc_scc_num); */
-/* if (info->state->smc_scc_num & NUM_IS_SCC) */
-/* chan = scc_chan_map[idx]; */
-/* else */
-/* chan = smc_chan_map[idx]; */
-
-/* cp->cp_cr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG; */
-/* while (cp->cp_cr & CPM_CR_FLG); */
-
-#endif
- /* info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); */
- info = &quicc_ser_info[i];
- if (info) {
- memset (info, 0, sizeof(ser_info_t));
- info->magic = SERIAL_MAGIC;
- info->line = i;
- info->flags = state->flags;
- INIT_WORK(&info->tqueue, do_softint, info);
- INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- info->state = state;
- state->info = (struct async_struct *)info;
-
- /* We need to allocate a transmit and receive buffer
- * descriptors from dual port ram, and a character
- * buffer area from host mem.
- */
- dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * RX_NUM_FIFO);
-
- /* Allocate space for FIFOs in the host memory.
- * (for now this is from a static array of buffers :(
- */
- /* mem_addr = m360_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE); */
- /* mem_addr = kmalloc (RX_NUM_FIFO * RX_BUF_SIZE, GFP_BUFFER); */
- mem_addr = &rx_buf_pool[i * RX_NUM_FIFO * RX_BUF_SIZE];
-
- /* Set the physical address of the host memory
- * buffers in the buffer descriptors, and the
- * virtual address for us to work with.
- */
- bdp = (QUICC_BD *)((uint)pquicc + dp_addr);
- info->rx_cur = info->rx_bd_base = bdp;
-
- /* initialize rx buffer descriptors */
- for (j=0; j<(RX_NUM_FIFO-1); j++) {
- bdp->buf = &rx_buf_pool[(i * RX_NUM_FIFO + j ) * RX_BUF_SIZE];
- bdp->status = BD_SC_EMPTY | BD_SC_INTRPT;
- mem_addr += RX_BUF_SIZE;
- bdp++;
- }
- bdp->buf = &rx_buf_pool[(i * RX_NUM_FIFO + j ) * RX_BUF_SIZE];
- bdp->status = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
-
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
-
-#if defined (CONFIG_UCQUICC) && 1
- /* set the transceiver mode to RS232 */
- sipex_mode_bits &= ~(uint)SIPEX_MODE(idx,0x0f); /* clear current mode */
- sipex_mode_bits |= (uint)SIPEX_MODE(idx,0x02);
- *(uint *)_periph_base = sipex_mode_bits;
- /* printk ("sipex bits = 0x%08x\n", sipex_mode_bits); */
-#endif
- }
-
- dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * TX_NUM_FIFO);
-
- /* Allocate space for FIFOs in the host memory.
- */
- /* mem_addr = m360_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE); */
- /* mem_addr = kmalloc (TX_NUM_FIFO * TX_BUF_SIZE, GFP_BUFFER); */
- mem_addr = &tx_buf_pool[i * TX_NUM_FIFO * TX_BUF_SIZE];
-
- /* Set the physical address of the host memory
- * buffers in the buffer descriptors, and the
- * virtual address for us to work with.
- */
- /* bdp = (QUICC_BD *)&cp->cp_dpmem[dp_addr]; */
- bdp = (QUICC_BD *)((uint)pquicc + dp_addr);
- info->tx_cur = info->tx_bd_base = (QUICC_BD *)bdp;
-
- /* initialize tx buffer descriptors */
- for (j=0; j<(TX_NUM_FIFO-1); j++) {
- bdp->buf = &tx_buf_pool[(i * TX_NUM_FIFO + j ) * TX_BUF_SIZE];
- bdp->status = BD_SC_INTRPT;
- mem_addr += TX_BUF_SIZE;
- bdp++;
- }
- bdp->buf = &tx_buf_pool[(i * TX_NUM_FIFO + j ) * TX_BUF_SIZE];
- bdp->status = (BD_SC_WRAP | BD_SC_INTRPT);
-
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- scp = &pquicc->scc_regs[idx];
- sup = &pquicc->pram[info->state->port].scc.pscc.u;
- sup->rbase = dp_addr;
- sup->tbase = dp_addr;
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
- sup->rfcr = SMC_EB;
- sup->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle character
- * time requires some additional tuning.
- */
- sup->mrblr = 1;
- sup->max_idl = 0;
- sup->brkcr = 1;
- sup->parec = 0;
- sup->frmer = 0;
- sup->nosec = 0;
- sup->brkec = 0;
- sup->uaddr1 = 0;
- sup->uaddr2 = 0;
- sup->toseq = 0;
- {
- int i;
- for (i=0;i<8;i++)
- sup->cc[i] = 0x8000;
- }
- sup->rccm = 0xc0ff;
-
- /* Send the CPM an initialize command.
- */
- chan = scc_chan_map[idx];
-
- /* execute the INIT RX & TX PARAMS command for this channel. */
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- scp->scc_gsmr.w.high = 0;
- scp->scc_gsmr.w.low =
- (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
-
- /* Disable all interrupts and clear all pending
- * events.
- */
- scp->scc_sccm = 0;
- scp->scc_scce = 0xffff;
- scp->scc_dsr = 0x7e7e;
- scp->scc_psmr = 0x3000;
-
- /* If the port is the console, enable Rx and Tx.
- */
-#ifdef CONFIG_SERIAL_CONSOLE
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- scp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#endif
- }
- else {
- /* Configure SMCs Tx/Rx instead of port B
- * parallel I/O.
- */
- up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
- up->rbase = dp_addr;
-
- iobits = 0xc0 << (idx * 4);
- cp->pip_pbpar |= iobits;
- cp->pip_pbdir &= ~iobits;
- cp->pip_pbodr &= ~iobits;
-
-
- /* Connect the baud rate generator to the
- * SMC based upon index in rs_table. Also
- * make sure it is connected to NMSI.
- */
- cp->si_simode &= ~(0xffff << (idx * 16));
- cp->si_simode |= (i << ((idx * 16) + 12));
-
- up->tbase = dp_addr;
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
- up->rfcr = SMC_EB;
- up->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle character
- * time requires some additional tuning.
- */
- up->mrblr = 1;
- up->max_idl = 0;
- up->brkcr = 1;
-
- /* Send the CPM an initialize command.
- */
- chan = smc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan,
- CPM_CR_INIT_TRX) | CPM_CR_FLG;
-#ifdef CONFIG_SERIAL_CONSOLE
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- printk("");
-#endif
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- sp = &cp->smc_regs[idx];
- sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
-
- /* Disable all interrupts and clear all pending
- * events.
- */
- sp->smc_smcm = 0;
- sp->smc_smce = 0xff;
-
- /* If the port is the console, enable Rx and Tx.
- */
-#ifdef CONFIG_SERIAL_CONSOLE
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-#endif
- }
-
- /* Install interrupt handler.
- */
- /* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info); */
- /*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */
- request_irq(state->irq, rs_360_interrupt,
- IRQ_FLG_LOCK, "ttyS", (void *)info);
-
- /* Set up the baud rate generator.
- */
- m360_cpm_setbrg(i, baud_table[baud_idx]);
-
- }
- }
-
- return 0;
-}
-module_init(rs_360_init);
-
-/* This must always be called before the rs_360_init() function, otherwise
- * it blows away the port control information.
- */
-//static int __init serial_console_setup( struct console *co, char *options)
-int serial_console_setup( struct console *co, char *options)
-{
- struct serial_state *ser;
- uint mem_addr, dp_addr, bidx, idx, iobits;
- ushort chan;
- QUICC_BD *bdp;
- volatile QUICC *cp;
- volatile struct smc_regs *sp;
- volatile struct scc_regs *scp;
- volatile struct smc_uart_pram *up;
- volatile struct uart_pram *sup;
-
-/* mleslie TODO:
- * add something to the 68k bootloader to store a desired initial console baud rate */
-
-/* bd_t *bd; */ /* a board info struct used by EPPC-bug */
-/* bd = (bd_t *)__res; */
-
- for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
- /* if (bd->bi_baudrate == baud_table[bidx]) */
- if (CONSOLE_BAUDRATE == baud_table[bidx])
- break;
-
- /* co->cflag = CREAD|CLOCAL|bidx|CS8; */
- baud_idx = bidx;
-
- ser = rs_table + CONFIG_SERIAL_CONSOLE_PORT;
-
- cp = pquicc; /* Get pointer to Communication Processor */
-
- idx = PORT_NUM(ser->smc_scc_num);
- if (ser->smc_scc_num & NUM_IS_SCC) {
-
- /* TODO: need to set up SCC pin assignment etc. here */
-
- }
- else {
- iobits = 0xc0 << (idx * 4);
- cp->pip_pbpar |= iobits;
- cp->pip_pbdir &= ~iobits;
- cp->pip_pbodr &= ~iobits;
-
- /* Connect the baud rate generator to the
- * SMC based upon index in rs_table. Also
- * make sure it is connected to NMSI.
- */
- cp->si_simode &= ~(0xffff << (idx * 16));
- cp->si_simode |= (idx << ((idx * 16) + 12));
- }
-
- /* When we get here, the CPM has been reset, so we need
- * to configure the port.
- * We need to allocate a transmit and receive buffer descriptor
- * from dual port ram, and a character buffer area from host mem.
- */
-
- /* Allocate space for two buffer descriptors in the DP ram.
- */
- dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * CONSOLE_NUM_FIFO);
-
- /* Allocate space for two 2 byte FIFOs in the host memory.
- */
- /* mem_addr = m360_cpm_hostalloc(8); */
- mem_addr = (uint)console_fifos;
-
-
- /* Set the physical address of the host memory buffers in
- * the buffer descriptors.
- */
- /* bdp = (QUICC_BD *)&cp->cp_dpmem[dp_addr]; */
- bdp = (QUICC_BD *)((uint)pquicc + dp_addr);
- bdp->buf = (char *)mem_addr;
- (bdp+1)->buf = (char *)(mem_addr+4);
-
- /* For the receive, set empty and wrap.
- * For transmit, set wrap.
- */
- bdp->status = BD_SC_EMPTY | BD_SC_WRAP;
- (bdp+1)->status = BD_SC_WRAP;
-
- /* Set up the uart parameters in the parameter ram.
- */
- if (ser->smc_scc_num & NUM_IS_SCC) {
- scp = &cp->scc_regs[idx];
- /* sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; */
- sup = &pquicc->pram[ser->port].scc.pscc.u;
-
- sup->rbase = dp_addr;
- sup->tbase = dp_addr + sizeof(QUICC_BD);
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
- sup->rfcr = SMC_EB;
- sup->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle character
- * time requires some additional tuning.
- */
- sup->mrblr = 1;
- sup->max_idl = 0;
- sup->brkcr = 1;
- sup->parec = 0;
- sup->frmer = 0;
- sup->nosec = 0;
- sup->brkec = 0;
- sup->uaddr1 = 0;
- sup->uaddr2 = 0;
- sup->toseq = 0;
- {
- int i;
- for (i=0;i<8;i++)
- sup->cc[i] = 0x8000;
- }
- sup->rccm = 0xc0ff;
-
- /* Send the CPM an initialize command.
- */
- chan = scc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- scp->scc_gsmr.w.high = 0;
- scp->scc_gsmr.w.low =
- (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
-
- /* Disable all interrupts and clear all pending
- * events.
- */
- scp->scc_sccm = 0;
- scp->scc_scce = 0xffff;
- scp->scc_dsr = 0x7e7e;
- scp->scc_psmr = 0x3000;
-
- scp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
- }
- else {
- /* up = (smc_uart_t *)&cp->cp_dparam[ser->port]; */
- up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u;
-
- up->rbase = dp_addr; /* Base of receive buffer desc. */
- up->tbase = dp_addr+sizeof(QUICC_BD); /* Base of xmt buffer desc. */
- up->rfcr = SMC_EB;
- up->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single character interrupts.
- */
- up->mrblr = 1; /* receive buffer length */
- up->max_idl = 0; /* wait forever for next char */
-
- /* Send the CPM an initialize command.
- */
- chan = smc_chan_map[idx];
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- sp = &cp->smc_regs[idx];
- sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
-
- /* And finally, enable Rx and Tx.
- */
- sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
- }
-
- /* Set up the baud rate generator.
- */
- /* m360_cpm_setbrg((ser - rs_table), bd->bi_baudrate); */
- m360_cpm_setbrg((ser - rs_table), CONSOLE_BAUDRATE);
-
- return 0;
-}
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
deleted file mode 100644
index b25e6e490530..000000000000
--- a/drivers/serial/8250.c
+++ /dev/null
@@ -1,3377 +0,0 @@
-/*
- * linux/drivers/char/8250.c
- *
- * Driver for 8250/16550-type serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King.
- *
- * 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.
- *
- * A note about mapbase / membase
- *
- * mapbase is the physical address of the IO port.
- * membase is an 'ioremapped' cookie.
- */
-
-#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/ratelimit.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/nmi.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "8250.h"
-
-#ifdef CONFIG_SPARC
-#include "suncore.h"
-#endif
-
-/*
- * Configuration:
- * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
- * is unsafe when used on edge-triggered interrupts.
- */
-static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
-
-static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
-
-static struct uart_driver serial8250_reg;
-
-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.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...) printk(fmt)
-#else
-#define DEBUG_INTR(fmt...) do { } while (0)
-#endif
-
-#define PASS_LIMIT 256
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-
-/*
- * We default to IRQ0 for the "no irq" hack. Some
- * machine types want others as well - they're free
- * to redefine this in their header file.
- */
-#define is_real_interrupt(irq) ((irq) != 0)
-
-#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-#define CONFIG_SERIAL_DETECT_IRQ 1
-#endif
-#ifdef CONFIG_SERIAL_8250_MANY_PORTS
-#define CONFIG_SERIAL_MANY_PORTS 1
-#endif
-
-/*
- * HUB6 is always on. This will be removed once the header
- * files have been cleaned.
- */
-#define CONFIG_HUB6 1
-
-#include <asm/serial.h>
-/*
- * SERIAL_PORT_DFNS tells us about built-in ports that have no
- * standard enumeration mechanism. Platforms that can find all
- * serial ports via mechanisms like ACPI or PCI need not supply it.
- */
-#ifndef SERIAL_PORT_DFNS
-#define SERIAL_PORT_DFNS
-#endif
-
-static const struct old_serial_port old_serial_port[] = {
- SERIAL_PORT_DFNS /* defined in asm/serial.h */
-};
-
-#define UART_NR CONFIG_SERIAL_8250_NR_UARTS
-
-#ifdef CONFIG_SERIAL_8250_RSA
-
-#define PORT_RSA_MAX 4
-static unsigned long probe_rsa[PORT_RSA_MAX];
-static unsigned int probe_rsa_count;
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-struct uart_8250_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short capabilities; /* port capabilities */
- unsigned short bugs; /* port bugs */
- unsigned int tx_loadsz; /* transmit fifo load size */
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char cur_iotype; /* Running I/O type */
-
- /*
- * Some bits in registers are cleared on a read, so they must
- * be saved whenever the register is read but the bits will not
- * be immediately processed.
- */
-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
- unsigned char lsr_saved_flags;
-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
- unsigned char msr_saved_flags;
-};
-
-struct irq_info {
- struct hlist_node node;
- int irq;
- spinlock_t lock; /* Protects list not the hash */
- struct list_head *head;
-};
-
-#define NR_IRQ_HASH 32 /* Can be adjusted later */
-static struct hlist_head irq_lists[NR_IRQ_HASH];
-static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial8250_config uart_config[] = {
- [PORT_UNKNOWN] = {
- .name = "unknown",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_8250] = {
- .name = "8250",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16450] = {
- .name = "16450",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16550] = {
- .name = "16550",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16550A] = {
- .name = "16550A",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
- },
- [PORT_CIRRUS] = {
- .name = "Cirrus",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16650] = {
- .name = "ST16650",
- .fifo_size = 1,
- .tx_loadsz = 1,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16650V2] = {
- .name = "ST16650V2",
- .fifo_size = 32,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_00,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16750] = {
- .name = "TI16750",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
- UART_FCR7_64BYTE,
- .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
- },
- [PORT_STARTECH] = {
- .name = "Startech",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16C950] = {
- .name = "16C950/954",
- .fifo_size = 128,
- .tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16654] = {
- .name = "ST16654",
- .fifo_size = 64,
- .tx_loadsz = 32,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16850] = {
- .name = "XR16850",
- .fifo_size = 128,
- .tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_RSA] = {
- .name = "RSA",
- .fifo_size = 2048,
- .tx_loadsz = 2048,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
- .flags = UART_CAP_FIFO,
- },
- [PORT_NS16550A] = {
- .name = "NS16550A",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_NATSEMI,
- },
- [PORT_XSCALE] = {
- .name = "XScale",
- .fifo_size = 32,
- .tx_loadsz = 32,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_UUE,
- },
- [PORT_RM9000] = {
- .name = "RM9000",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
- },
- [PORT_OCTEON] = {
- .name = "OCTEON",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
- },
- [PORT_AR7] = {
- .name = "AR7",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
- [PORT_U6_16550A] = {
- .name = "U6_16550A",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
-};
-
-#if defined(CONFIG_MIPS_ALCHEMY)
-
-/* Au1x00 UART hardware has a weird register layout */
-static const u8 au_io_in_map[] = {
- [UART_RX] = 0,
- [UART_IER] = 2,
- [UART_IIR] = 3,
- [UART_LCR] = 5,
- [UART_MCR] = 6,
- [UART_LSR] = 7,
- [UART_MSR] = 8,
-};
-
-static const u8 au_io_out_map[] = {
- [UART_TX] = 1,
- [UART_IER] = 2,
- [UART_FCR] = 4,
- [UART_LCR] = 5,
- [UART_MCR] = 6,
-};
-
-/* sane hardware needs no mapping */
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_AU)
- return offset;
- return au_io_in_map[offset];
-}
-
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_AU)
- return offset;
- return au_io_out_map[offset];
-}
-
-#elif defined(CONFIG_SERIAL_8250_RM9K)
-
-static const u8
- regmap_in[8] = {
- [UART_RX] = 0x00,
- [UART_IER] = 0x0c,
- [UART_IIR] = 0x14,
- [UART_LCR] = 0x1c,
- [UART_MCR] = 0x20,
- [UART_LSR] = 0x24,
- [UART_MSR] = 0x28,
- [UART_SCR] = 0x2c
- },
- regmap_out[8] = {
- [UART_TX] = 0x04,
- [UART_IER] = 0x0c,
- [UART_FCR] = 0x18,
- [UART_LCR] = 0x1c,
- [UART_MCR] = 0x20,
- [UART_LSR] = 0x24,
- [UART_MSR] = 0x28,
- [UART_SCR] = 0x2c
- };
-
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_RM9000)
- return offset;
- return regmap_in[offset];
-}
-
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_RM9000)
- return offset;
- return regmap_out[offset];
-}
-
-#else
-
-/* sane hardware needs no mapping */
-#define map_8250_in_reg(up, offset) (offset)
-#define map_8250_out_reg(up, offset) (offset)
-
-#endif
-
-static unsigned int hub6_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- return inb(p->iobase + 1);
-}
-
-static void hub6_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- outb(value, p->iobase + 1);
-}
-
-static unsigned int mem_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return readb(p->membase + offset);
-}
-
-static void mem_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- writeb(value, p->membase + offset);
-}
-
-static void mem32_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- writel(value, p->membase + offset);
-}
-
-static unsigned int mem32_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return readl(p->membase + offset);
-}
-
-static unsigned int au_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return __raw_readl(p->membase + offset);
-}
-
-static void au_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- __raw_writel(value, p->membase + offset);
-}
-
-static unsigned int tsi_serial_in(struct uart_port *p, int offset)
-{
- unsigned int tmp;
- offset = map_8250_in_reg(p, offset) << p->regshift;
- if (offset == UART_IIR) {
- tmp = readl(p->membase + (UART_IIR & ~3));
- return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
- } else
- return readb(p->membase + offset);
-}
-
-static void tsi_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- if (!((offset == UART_IER) && (value & UART_IER_UUE)))
- writeb(value, p->membase + offset);
-}
-
-/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */
-static inline void dwapb_save_out_value(struct uart_port *p, int offset,
- int value)
-{
- struct uart_8250_port *up =
- container_of(p, struct uart_8250_port, port);
-
- if (offset == UART_LCR)
- up->lcr = value;
-}
-
-/* Read the IER to ensure any interrupt is cleared before returning from ISR. */
-static inline void dwapb_check_clear_ier(struct uart_port *p, int offset)
-{
- if (offset == UART_TX || offset == UART_IER)
- p->serial_in(p, UART_IER);
-}
-
-static void dwapb_serial_out(struct uart_port *p, int offset, int value)
-{
- int save_offset = offset;
- offset = map_8250_out_reg(p, offset) << p->regshift;
- dwapb_save_out_value(p, save_offset, value);
- writeb(value, p->membase + offset);
- dwapb_check_clear_ier(p, save_offset);
-}
-
-static void dwapb32_serial_out(struct uart_port *p, int offset, int value)
-{
- int save_offset = offset;
- offset = map_8250_out_reg(p, offset) << p->regshift;
- dwapb_save_out_value(p, save_offset, value);
- writel(value, p->membase + offset);
- dwapb_check_clear_ier(p, save_offset);
-}
-
-static unsigned int io_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return inb(p->iobase + offset);
-}
-
-static void io_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- outb(value, p->iobase + offset);
-}
-
-static void set_io_from_upio(struct uart_port *p)
-{
- struct uart_8250_port *up =
- container_of(p, struct uart_8250_port, port);
- switch (p->iotype) {
- case UPIO_HUB6:
- p->serial_in = hub6_serial_in;
- p->serial_out = hub6_serial_out;
- break;
-
- case UPIO_MEM:
- p->serial_in = mem_serial_in;
- p->serial_out = mem_serial_out;
- break;
-
- case UPIO_RM9000:
- case UPIO_MEM32:
- p->serial_in = mem32_serial_in;
- p->serial_out = mem32_serial_out;
- break;
-
- case UPIO_AU:
- p->serial_in = au_serial_in;
- p->serial_out = au_serial_out;
- break;
-
- case UPIO_TSI:
- p->serial_in = tsi_serial_in;
- p->serial_out = tsi_serial_out;
- break;
-
- case UPIO_DWAPB:
- p->serial_in = mem_serial_in;
- p->serial_out = dwapb_serial_out;
- break;
-
- case UPIO_DWAPB32:
- p->serial_in = mem32_serial_in;
- p->serial_out = dwapb32_serial_out;
- break;
-
- default:
- p->serial_in = io_serial_in;
- p->serial_out = io_serial_out;
- break;
- }
- /* Remember loaded iotype */
- up->cur_iotype = p->iotype;
-}
-
-static void
-serial_out_sync(struct uart_8250_port *up, int offset, int value)
-{
- struct uart_port *p = &up->port;
- switch (p->iotype) {
- case UPIO_MEM:
- case UPIO_MEM32:
- case UPIO_AU:
- case UPIO_DWAPB:
- case UPIO_DWAPB32:
- p->serial_out(p, offset, value);
- p->serial_in(p, UART_LCR); /* safe, no side-effects */
- break;
- default:
- p->serial_out(p, offset, value);
- }
-}
-
-#define serial_in(up, offset) \
- (up->port.serial_in(&(up)->port, (offset)))
-#define serial_out(up, offset, value) \
- (up->port.serial_out(&(up)->port, (offset), (value)))
-/*
- * We used to support using pause I/O for certain machines. We
- * haven't supported this for a while, but just in case it's badly
- * needed for certain old 386 machines, I've left these #define's
- * in....
- */
-#define serial_inp(up, offset) serial_in(up, offset)
-#define serial_outp(up, offset, value) serial_out(up, offset, value)
-
-/* Uart divisor latch read */
-static inline int _serial_dl_read(struct uart_8250_port *up)
-{
- return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
-}
-
-/* Uart divisor latch write */
-static inline void _serial_dl_write(struct uart_8250_port *up, int value)
-{
- serial_outp(up, UART_DLL, value & 0xff);
- serial_outp(up, UART_DLM, value >> 8 & 0xff);
-}
-
-#if defined(CONFIG_MIPS_ALCHEMY)
-/* Au1x00 haven't got a standard divisor latch */
-static int serial_dl_read(struct uart_8250_port *up)
-{
- if (up->port.iotype == UPIO_AU)
- return __raw_readl(up->port.membase + 0x28);
- else
- return _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
- if (up->port.iotype == UPIO_AU)
- __raw_writel(value, up->port.membase + 0x28);
- else
- _serial_dl_write(up, value);
-}
-#elif defined(CONFIG_SERIAL_8250_RM9K)
-static int serial_dl_read(struct uart_8250_port *up)
-{
- return (up->port.iotype == UPIO_RM9000) ?
- (((__raw_readl(up->port.membase + 0x10) << 8) |
- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
- _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
- if (up->port.iotype == UPIO_RM9000) {
- __raw_writel(value, up->port.membase + 0x08);
- __raw_writel(value >> 8, up->port.membase + 0x10);
- } else {
- _serial_dl_write(up, value);
- }
-}
-#else
-#define serial_dl_read(up) _serial_dl_read(up)
-#define serial_dl_write(up, value) _serial_dl_write(up, value)
-#endif
-
-/*
- * For the 16C950
- */
-static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-{
- serial_out(up, UART_SCR, offset);
- serial_out(up, UART_ICR, value);
-}
-
-static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
-{
- unsigned int value;
-
- serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
- serial_out(up, UART_SCR, offset);
- value = serial_in(up, UART_ICR);
- serial_icr_write(up, UART_ACR, up->acr);
-
- return value;
-}
-
-/*
- * FIFO support.
- */
-static void serial8250_clear_fifos(struct uart_8250_port *p)
-{
- if (p->capabilities & UART_CAP_FIFO) {
- serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_outp(p, UART_FCR, 0);
- }
-}
-
-/*
- * IER sleep support. UARTs which have EFRs need the "extended
- * capability" bit enabled. Note that on XR16C850s, we need to
- * reset LCR to write to IER.
- */
-static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
-{
- if (p->capabilities & UART_CAP_SLEEP) {
- if (p->capabilities & UART_CAP_EFR) {
- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(p, UART_EFR, UART_EFR_ECB);
- serial_outp(p, UART_LCR, 0);
- }
- serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
- if (p->capabilities & UART_CAP_EFR) {
- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(p, UART_EFR, 0);
- serial_outp(p, UART_LCR, 0);
- }
- }
-}
-
-#ifdef CONFIG_SERIAL_8250_RSA
-/*
- * Attempts to turn on the RSA FIFO. Returns zero on failure.
- * We set the port uart clock rate if we succeed.
- */
-static int __enable_rsa(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- mode = serial_inp(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
-
- if (!result) {
- serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
- mode = serial_inp(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-
- return result;
-}
-
-static void enable_rsa(struct uart_8250_port *up)
-{
- if (up->port.type == PORT_RSA) {
- if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
- __enable_rsa(up);
- spin_unlock_irq(&up->port.lock);
- }
- if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
- serial_outp(up, UART_RSA_FRR, 0);
- }
-}
-
-/*
- * Attempts to turn off the RSA FIFO. Returns zero on failure.
- * It is unknown why interrupts were disabled in here. However,
- * the caller is expected to preserve this behaviour by grabbing
- * the spinlock before calling this function.
- */
-static void disable_rsa(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- if (up->port.type == PORT_RSA &&
- up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
-
- mode = serial_inp(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
-
- if (!result) {
- serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
- mode = serial_inp(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
- spin_unlock_irq(&up->port.lock);
- }
-}
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-/*
- * This is a quickie test to see how big the FIFO is.
- * It doesn't work at all the time, more's the pity.
- */
-static int size_fifo(struct uart_8250_port *up)
-{
- unsigned char old_fcr, old_mcr, old_lcr;
- unsigned short old_dl;
- int count;
-
- old_lcr = serial_inp(up, UART_LCR);
- serial_outp(up, UART_LCR, 0);
- old_fcr = serial_inp(up, UART_FCR);
- old_mcr = serial_inp(up, UART_MCR);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_MCR, UART_MCR_LOOP);
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- old_dl = serial_dl_read(up);
- serial_dl_write(up, 0x0001);
- serial_outp(up, UART_LCR, 0x03);
- for (count = 0; count < 256; count++)
- serial_outp(up, UART_TX, count);
- mdelay(20);/* FIXME - schedule_timeout */
- for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
- (count < 256); count++)
- serial_inp(up, UART_RX);
- serial_outp(up, UART_FCR, old_fcr);
- serial_outp(up, UART_MCR, old_mcr);
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_dl_write(up, old_dl);
- serial_outp(up, UART_LCR, old_lcr);
-
- return count;
-}
-
-/*
- * Read UART ID using the divisor method - set DLL and DLM to zero
- * and the revision will be in DLL and device type in DLM. We
- * preserve the device state across this.
- */
-static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
-{
- unsigned char old_dll, old_dlm, old_lcr;
- unsigned int id;
-
- old_lcr = serial_inp(p, UART_LCR);
- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);
-
- old_dll = serial_inp(p, UART_DLL);
- old_dlm = serial_inp(p, UART_DLM);
-
- serial_outp(p, UART_DLL, 0);
- serial_outp(p, UART_DLM, 0);
-
- id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
-
- serial_outp(p, UART_DLL, old_dll);
- serial_outp(p, UART_DLM, old_dlm);
- serial_outp(p, UART_LCR, old_lcr);
-
- return id;
-}
-
-/*
- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
- * When this function is called we know it is at least a StarTech
- * 16650 V2, but it might be one of several StarTech UARTs, or one of
- * its clones. (We treat the broken original StarTech 16650 V1 as a
- * 16550, and why not? Startech doesn't seem to even acknowledge its
- * existence.)
- *
- * What evil have men's minds wrought...
- */
-static void autoconfig_has_efr(struct uart_8250_port *up)
-{
- unsigned int id1, id2, id3, rev;
-
- /*
- * Everything with an EFR has SLEEP
- */
- up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
-
- /*
- * First we check to see if it's an Oxford Semiconductor UART.
- *
- * If we have to do this here because some non-National
- * Semiconductor clone chips lock up if you try writing to the
- * LSR register (which serial_icr_read does)
- */
-
- /*
- * Check for Oxford Semiconductor 16C950.
- *
- * EFR [4] must be set else this test fails.
- *
- * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
- * claims that it's needed for 952 dual UART's (which are not
- * recommended for new designs).
- */
- up->acr = 0;
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, UART_EFR_ECB);
- serial_out(up, UART_LCR, 0x00);
- id1 = serial_icr_read(up, UART_ID1);
- id2 = serial_icr_read(up, UART_ID2);
- id3 = serial_icr_read(up, UART_ID3);
- rev = serial_icr_read(up, UART_REV);
-
- DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
-
- if (id1 == 0x16 && id2 == 0xC9 &&
- (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
- up->port.type = PORT_16C950;
-
- /*
- * Enable work around for the Oxford Semiconductor 952 rev B
- * chip which causes it to seriously miscalculate baud rates
- * when DLL is 0.
- */
- if (id3 == 0x52 && rev == 0x01)
- up->bugs |= UART_BUG_QUOT;
- return;
- }
-
- /*
- * We check for a XR16C850 by setting DLL and DLM to 0, and then
- * reading back DLL and DLM. The chip type depends on the DLM
- * value read back:
- * 0x10 - XR16C850 and the DLL contains the chip revision.
- * 0x12 - XR16C2850.
- * 0x14 - XR16C854.
- */
- id1 = autoconfig_read_divisor_id(up);
- DEBUG_AUTOCONF("850id=%04x ", id1);
-
- id2 = id1 >> 8;
- if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
- up->port.type = PORT_16850;
- return;
- }
-
- /*
- * It wasn't an XR16C850.
- *
- * We distinguish between the '654 and the '650 by counting
- * how many bytes are in the FIFO. I'm using this for now,
- * since that's the technique that was sent to me in the
- * serial driver update, but I'm not convinced this works.
- * I've had problems doing this in the past. -TYT
- */
- if (size_fifo(up) == 64)
- up->port.type = PORT_16654;
- else
- up->port.type = PORT_16650V2;
-}
-
-/*
- * We detected a chip without a FIFO. Only two fall into
- * this category - the original 8250 and the 16450. The
- * 16450 has a scratch register (accessible with LCR=0)
- */
-static void autoconfig_8250(struct uart_8250_port *up)
-{
- unsigned char scratch, status1, status2;
-
- up->port.type = PORT_8250;
-
- scratch = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, 0xa5);
- status1 = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, 0x5a);
- status2 = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, scratch);
-
- if (status1 == 0xa5 && status2 == 0x5a)
- up->port.type = PORT_16450;
-}
-
-static int broken_efr(struct uart_8250_port *up)
-{
- /*
- * Exar ST16C2550 "A2" devices incorrectly detect as
- * having an EFR, and report an ID of 0x0201. See
- * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
- */
- if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
- return 1;
-
- return 0;
-}
-
-/*
- * We know that the chip has FIFOs. Does it have an EFR? The
- * EFR is located in the same register position as the IIR and
- * we know the top two bits of the IIR are currently set. The
- * EFR should contain zero. Try to read the EFR.
- */
-static void autoconfig_16550a(struct uart_8250_port *up)
-{
- unsigned char status1, status2;
- unsigned int iersave;
-
- up->port.type = PORT_16550A;
- up->capabilities |= UART_CAP_FIFO;
-
- /*
- * Check for presence of the EFR when DLAB is set.
- * Only ST16C650V1 UARTs pass this test.
- */
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- if (serial_in(up, UART_EFR) == 0) {
- serial_outp(up, UART_EFR, 0xA8);
- if (serial_in(up, UART_EFR) != 0) {
- DEBUG_AUTOCONF("EFRv1 ");
- up->port.type = PORT_16650;
- up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
- } else {
- DEBUG_AUTOCONF("Motorola 8xxx DUART ");
- }
- serial_outp(up, UART_EFR, 0);
- return;
- }
-
- /*
- * Maybe it requires 0xbf to be written to the LCR.
- * (other ST16C650V2 UARTs, TI16C752A, etc)
- */
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
- DEBUG_AUTOCONF("EFRv2 ");
- autoconfig_has_efr(up);
- return;
- }
-
- /*
- * Check for a National Semiconductor SuperIO chip.
- * Attempt to switch to bank 2, read the value of the LOOP bit
- * from EXCR1. Switch back to bank 0, change it in MCR. Then
- * switch back to bank 2, read it from EXCR1 again and check
- * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
- */
- serial_outp(up, UART_LCR, 0);
- status1 = serial_in(up, UART_MCR);
- serial_outp(up, UART_LCR, 0xE0);
- status2 = serial_in(up, 0x02); /* EXCR1 */
-
- if (!((status2 ^ status1) & UART_MCR_LOOP)) {
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
- serial_outp(up, UART_LCR, 0xE0);
- status2 = serial_in(up, 0x02); /* EXCR1 */
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_MCR, status1);
-
- if ((status2 ^ status1) & UART_MCR_LOOP) {
- unsigned short quot;
-
- serial_outp(up, UART_LCR, 0xE0);
-
- quot = serial_dl_read(up);
- quot <<= 3;
-
- status1 = serial_in(up, 0x04); /* EXCR2 */
- status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
- status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
- serial_outp(up, 0x04, status1);
-
- serial_dl_write(up, quot);
-
- serial_outp(up, UART_LCR, 0);
-
- up->port.uartclk = 921600*16;
- up->port.type = PORT_NS16550A;
- up->capabilities |= UART_NATSEMI;
- return;
- }
- }
-
- /*
- * No EFR. Try to detect a TI16750, which only sets bit 5 of
- * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
- * Try setting it with and without DLAB set. Cheap clones
- * set bit 5 without DLAB set.
- */
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- status1 = serial_in(up, UART_IIR) >> 5;
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- status2 = serial_in(up, UART_IIR) >> 5;
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_LCR, 0);
-
- DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
-
- if (status1 == 6 && status2 == 7) {
- up->port.type = PORT_16750;
- up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
- return;
- }
-
- /*
- * Try writing and reading the UART_IER_UUE bit (b6).
- * If it works, this is probably one of the Xscale platform's
- * internal UARTs.
- * We're going to explicitly set the UUE bit to 0 before
- * trying to write and read a 1 just to make sure it's not
- * already a 1 and maybe locked there before we even start start.
- */
- iersave = serial_in(up, UART_IER);
- serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
- if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
- /*
- * OK it's in a known zero state, try writing and reading
- * without disturbing the current state of the other bits.
- */
- serial_outp(up, UART_IER, iersave | UART_IER_UUE);
- if (serial_in(up, UART_IER) & UART_IER_UUE) {
- /*
- * It's an Xscale.
- * We'll leave the UART_IER_UUE bit set to 1 (enabled).
- */
- DEBUG_AUTOCONF("Xscale ");
- up->port.type = PORT_XSCALE;
- up->capabilities |= UART_CAP_UUE;
- return;
- }
- } else {
- /*
- * If we got here we couldn't force the IER_UUE bit to 0.
- * Log it and continue.
- */
- DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
- }
- serial_outp(up, UART_IER, iersave);
-
- /*
- * We distinguish between 16550A and U6 16550A by counting
- * how many bytes are in the FIFO.
- */
- if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
- up->port.type = PORT_U6_16550A;
- up->capabilities |= UART_CAP_AFE;
- }
-}
-
-/*
- * This routine is called by rs_init() to initialize a specific serial
- * port. It determines what type of UART chip this serial port is
- * using: 8250, 16450, 16550, 16550A. The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
- */
-static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
-{
- unsigned char status1, scratch, scratch2, scratch3;
- unsigned char save_lcr, save_mcr;
- unsigned long flags;
-
- if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
- return;
-
- DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
- serial_index(&up->port), up->port.iobase, up->port.membase);
-
- /*
- * We really do need global IRQs disabled here - we're going to
- * be frobbing the chips IRQ enable register to see if it exists.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->capabilities = 0;
- up->bugs = 0;
-
- if (!(up->port.flags & UPF_BUGGY_UART)) {
- /*
- * Do a simple existence test first; if we fail this,
- * there's no point trying anything else.
- *
- * 0x80 is used as a nonsense port to prevent against
- * false positives due to ISA bus float. The
- * assumption is that 0x80 is a non-existent port;
- * which should be safe since include/asm/io.h also
- * makes this assumption.
- *
- * Note: this is safe as long as MCR bit 4 is clear
- * and the device is in "PC" mode.
- */
- scratch = serial_inp(up, UART_IER);
- serial_outp(up, UART_IER, 0);
-#ifdef __i386__
- outb(0xff, 0x080);
-#endif
- /*
- * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
- * 16C754B) allow only to modify them if an EFR bit is set.
- */
- scratch2 = serial_inp(up, UART_IER) & 0x0f;
- serial_outp(up, UART_IER, 0x0F);
-#ifdef __i386__
- outb(0, 0x080);
-#endif
- scratch3 = serial_inp(up, UART_IER) & 0x0f;
- serial_outp(up, UART_IER, scratch);
- if (scratch2 != 0 || scratch3 != 0x0F) {
- /*
- * We failed; there's nothing here
- */
- DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
- scratch2, scratch3);
- goto out;
- }
- }
-
- save_mcr = serial_in(up, UART_MCR);
- save_lcr = serial_in(up, UART_LCR);
-
- /*
- * Check to see if a UART is really there. Certain broken
- * internal modems based on the Rockwell chipset fail this
- * test, because they apparently don't implement the loopback
- * test mode. So this test is skipped on the COM 1 through
- * COM 4 ports. This *should* be safe, since no board
- * manufacturer would be stupid enough to design a board
- * that conflicts with COM 1-4 --- we hope!
- */
- if (!(up->port.flags & UPF_SKIP_TEST)) {
- serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
- status1 = serial_inp(up, UART_MSR) & 0xF0;
- serial_outp(up, UART_MCR, save_mcr);
- if (status1 != 0x90) {
- DEBUG_AUTOCONF("LOOP test failed (%02x) ",
- status1);
- goto out;
- }
- }
-
- /*
- * We're pretty sure there's a port here. Lets find out what
- * type of port it is. The IIR top two bits allows us to find
- * out if it's 8250 or 16450, 16550, 16550A or later. This
- * determines what we test for next.
- *
- * We also initialise the EFR (if any) to zero for later. The
- * EFR occupies the same register location as the FCR and IIR.
- */
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(up, UART_EFR, 0);
- serial_outp(up, UART_LCR, 0);
-
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- scratch = serial_in(up, UART_IIR) >> 6;
-
- DEBUG_AUTOCONF("iir=%d ", scratch);
-
- switch (scratch) {
- case 0:
- autoconfig_8250(up);
- break;
- case 1:
- up->port.type = PORT_UNKNOWN;
- break;
- case 2:
- up->port.type = PORT_16550;
- break;
- case 3:
- autoconfig_16550a(up);
- break;
- }
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * Only probe for RSA ports if we got the region.
- */
- if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
- int i;
-
- for (i = 0 ; i < probe_rsa_count; ++i) {
- if (probe_rsa[i] == up->port.iobase &&
- __enable_rsa(up)) {
- up->port.type = PORT_RSA;
- break;
- }
- }
- }
-#endif
-
- serial_outp(up, UART_LCR, save_lcr);
-
- if (up->capabilities != uart_config[up->port.type].flags) {
- printk(KERN_WARNING
- "ttyS%d: detected caps %08x should be %08x\n",
- serial_index(&up->port), up->capabilities,
- uart_config[up->port.type].flags);
- }
-
- up->port.fifosize = uart_config[up->port.type].fifo_size;
- up->capabilities = uart_config[up->port.type].flags;
- up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
-
- if (up->port.type == PORT_UNKNOWN)
- goto out;
-
- /*
- * Reset the UART.
- */
-#ifdef CONFIG_SERIAL_8250_RSA
- if (up->port.type == PORT_RSA)
- serial_outp(up, UART_RSA_FRR, 0);
-#endif
- serial_outp(up, UART_MCR, save_mcr);
- serial8250_clear_fifos(up);
- serial_in(up, UART_RX);
- if (up->capabilities & UART_CAP_UUE)
- serial_outp(up, UART_IER, UART_IER_UUE);
- else
- serial_outp(up, UART_IER, 0);
-
- out:
- spin_unlock_irqrestore(&up->port.lock, flags);
- DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
-}
-
-static void autoconfig_irq(struct uart_8250_port *up)
-{
- unsigned char save_mcr, save_ier;
- unsigned char save_ICP = 0;
- unsigned int ICP = 0;
- unsigned long irqs;
- int irq;
-
- if (up->port.flags & UPF_FOURPORT) {
- ICP = (up->port.iobase & 0xfe0) | 0x1f;
- save_ICP = inb_p(ICP);
- outb_p(0x80, ICP);
- (void) inb_p(ICP);
- }
-
- /* forget possible initially masked and pending IRQ */
- probe_irq_off(probe_irq_on());
- save_mcr = serial_inp(up, UART_MCR);
- save_ier = serial_inp(up, UART_IER);
- serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
- irqs = probe_irq_on();
- serial_outp(up, UART_MCR, 0);
- udelay(10);
- if (up->port.flags & UPF_FOURPORT) {
- serial_outp(up, UART_MCR,
- UART_MCR_DTR | UART_MCR_RTS);
- } else {
- serial_outp(up, UART_MCR,
- UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
- }
- serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
- (void)serial_inp(up, UART_LSR);
- (void)serial_inp(up, UART_RX);
- (void)serial_inp(up, UART_IIR);
- (void)serial_inp(up, UART_MSR);
- serial_outp(up, UART_TX, 0xFF);
- udelay(20);
- irq = probe_irq_off(irqs);
-
- serial_outp(up, UART_MCR, save_mcr);
- serial_outp(up, UART_IER, save_ier);
-
- if (up->port.flags & UPF_FOURPORT)
- outb_p(save_ICP, ICP);
-
- up->port.irq = (irq > 0) ? irq : 0;
-}
-
-static inline void __stop_tx(struct uart_8250_port *p)
-{
- if (p->ier & UART_IER_THRI) {
- p->ier &= ~UART_IER_THRI;
- serial_out(p, UART_IER, p->ier);
- }
-}
-
-static void serial8250_stop_tx(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- __stop_tx(up);
-
- /*
- * We really want to stop the transmitter from sending.
- */
- if (up->port.type == PORT_16C950) {
- up->acr |= UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
-}
-
-static void transmit_chars(struct uart_8250_port *up);
-
-static void serial8250_start_tx(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
-
- if (up->bugs & UART_BUG_TXEN) {
- unsigned char lsr;
- lsr = serial_in(up, UART_LSR);
- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- if ((up->port.type == PORT_RM9000) ?
- (lsr & UART_LSR_THRE) :
- (lsr & UART_LSR_TEMT))
- transmit_chars(up);
- }
- }
-
- /*
- * Re-enable the transmitter if we disabled it.
- */
- if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
- up->acr &= ~UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
-}
-
-static void serial8250_stop_rx(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void serial8250_enable_ms(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- /* no MSR capabilities */
- if (up->bugs & UART_BUG_NOMSR)
- return;
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void
-receive_chars(struct uart_8250_port *up, unsigned int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned char ch, lsr = *status;
- int max_count = 256;
- char flag;
-
- do {
- if (likely(lsr & UART_LSR_DR))
- ch = serial_inp(up, UART_RX);
- else
- /*
- * Intel 82571 has a Serial Over Lan device that will
- * set UART_LSR_BI without setting UART_LSR_DR when
- * it receives a break. To avoid reading from the
- * receive buffer without UART_LSR_DR bit set, we
- * just force the read character to be 0
- */
- ch = 0;
-
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- lsr |= up->lsr_saved_flags;
- up->lsr_saved_flags = 0;
-
- if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
- /*
- * For statistics only
- */
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (lsr & UART_LSR_PE)
- up->port.icount.parity++;
- else if (lsr & UART_LSR_FE)
- up->port.icount.frame++;
- if (lsr & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- lsr &= up->port.read_status_mask;
-
- if (lsr & UART_LSR_BI) {
- DEBUG_INTR("handling break....");
- flag = TTY_BREAK;
- } else if (lsr & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (lsr & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
-
- uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
-
-ignore_char:
- lsr = serial_inp(up, UART_LSR);
- } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
- *status = lsr;
-}
-
-static void transmit_chars(struct uart_8250_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_outp(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_tx_stopped(&up->port)) {
- serial8250_stop_tx(&up->port);
- return;
- }
- if (uart_circ_empty(xmit)) {
- __stop_tx(up);
- return;
- }
-
- count = up->tx_loadsz;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- DEBUG_INTR("THRE...");
-
- if (uart_circ_empty(xmit))
- __stop_tx(up);
-}
-
-static unsigned int check_modem_status(struct uart_8250_port *up)
-{
- unsigned int status = serial_in(up, UART_MSR);
-
- status |= up->msr_saved_flags;
- up->msr_saved_flags = 0;
- if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
- up->port.state != NULL) {
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
- }
-
- return status;
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static void serial8250_handle_port(struct uart_8250_port *up)
-{
- unsigned int status;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- status = serial_inp(up, UART_LSR);
-
- DEBUG_INTR("status = %x...", status);
-
- if (status & (UART_LSR_DR | UART_LSR_BI))
- receive_chars(up, &status);
- check_modem_status(up);
- if (status & UART_LSR_THRE)
- transmit_chars(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts. (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
-{
- struct irq_info *i = dev_id;
- struct list_head *l, *end = NULL;
- int pass_counter = 0, handled = 0;
-
- DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-
- spin_lock(&i->lock);
-
- l = i->head;
- do {
- struct uart_8250_port *up;
- unsigned int iir;
-
- up = list_entry(l, struct uart_8250_port, list);
-
- iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
- serial8250_handle_port(up);
-
- handled = 1;
-
- end = NULL;
- } else if ((up->port.iotype == UPIO_DWAPB ||
- up->port.iotype == UPIO_DWAPB32) &&
- (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
- /* The DesignWare APB UART has an Busy Detect (0x07)
- * interrupt meaning an LCR write attempt occured while the
- * UART was busy. The interrupt must be cleared by reading
- * the UART status register (USR) and the LCR re-written. */
- unsigned int status;
- status = *(volatile u32 *)up->port.private_data;
- serial_out(up, UART_LCR, up->lcr);
-
- handled = 1;
-
- end = NULL;
- } else if (end == NULL)
- end = l;
-
- l = l->next;
-
- if (l == i->head && pass_counter++ > PASS_LIMIT) {
- /* If we hit this, we're dead. */
- printk_ratelimited(KERN_ERR
- "serial8250: too much work for irq%d\n", irq);
- break;
- }
- } while (l != end);
-
- spin_unlock(&i->lock);
-
- DEBUG_INTR("end.\n");
-
- return IRQ_RETVAL(handled);
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning. Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-{
- spin_lock_irq(&i->lock);
-
- if (!list_empty(i->head)) {
- if (i->head == &up->list)
- i->head = i->head->next;
- list_del(&up->list);
- } else {
- BUG_ON(i->head != &up->list);
- i->head = NULL;
- }
- spin_unlock_irq(&i->lock);
- /* List empty so throw away the hash node */
- if (i->head == NULL) {
- hlist_del(&i->node);
- kfree(i);
- }
-}
-
-static int serial_link_irq_chain(struct uart_8250_port *up)
-{
- struct hlist_head *h;
- struct hlist_node *n;
- struct irq_info *i;
- int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
-
- mutex_lock(&hash_mutex);
-
- h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
- hlist_for_each(n, h) {
- i = hlist_entry(n, struct irq_info, node);
- if (i->irq == up->port.irq)
- break;
- }
-
- if (n == NULL) {
- i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
- if (i == NULL) {
- mutex_unlock(&hash_mutex);
- return -ENOMEM;
- }
- spin_lock_init(&i->lock);
- i->irq = up->port.irq;
- hlist_add_head(&i->node, h);
- }
- mutex_unlock(&hash_mutex);
-
- spin_lock_irq(&i->lock);
-
- if (i->head) {
- list_add(&up->list, i->head);
- spin_unlock_irq(&i->lock);
-
- ret = 0;
- } else {
- 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)
- serial_do_unlink(i, up);
- }
-
- return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_8250_port *up)
-{
- struct irq_info *i;
- struct hlist_node *n;
- struct hlist_head *h;
-
- mutex_lock(&hash_mutex);
-
- h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
- hlist_for_each(n, h) {
- i = hlist_entry(n, struct irq_info, node);
- if (i->irq == up->port.irq)
- break;
- }
-
- BUG_ON(n == NULL);
- BUG_ON(i->head == NULL);
-
- if (list_empty(i->head))
- free_irq(up->port.irq, i);
-
- serial_do_unlink(i, up);
- mutex_unlock(&hash_mutex);
-}
-
-/*
- * This function is used to handle ports that do not have an
- * interrupt. This doesn't work very well for 16450's, but gives
- * barely passable results for a 16550A. (Although at the expense
- * of much CPU overhead).
- */
-static void serial8250_timeout(unsigned long data)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)data;
- unsigned int iir;
-
- iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT))
- serial8250_handle_port(up);
- mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
-}
-
-static void serial8250_backup_timeout(unsigned long data)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)data;
- unsigned int iir, ier = 0, lsr;
- unsigned long flags;
-
- /*
- * Must disable interrupts or else we risk racing with the interrupt
- * based handler.
- */
- if (is_real_interrupt(up->port.irq)) {
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
- }
-
- iir = serial_in(up, UART_IIR);
-
- /*
- * This should be a safe test for anyone who doesn't trust the
- * IIR bits on their UART, but it's specifically designed for
- * the "Diva" UART used on the management processor on many HP
- * ia64 and parisc boxes.
- */
- spin_lock_irqsave(&up->port.lock, flags);
- lsr = serial_in(up, UART_LSR);
- 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.state->xmit) || up->port.x_char) &&
- (lsr & UART_LSR_THRE)) {
- iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
- iir |= UART_IIR_THRI;
- }
-
- if (!(iir & UART_IIR_NO_INT))
- serial8250_handle_port(up);
-
- if (is_real_interrupt(up->port.irq))
- serial_out(up, UART_IER, ier);
-
- /* Standard timer interval plus 0.2s to keep the port running */
- mod_timer(&up->timer,
- jiffies + uart_poll_timeout(&up->port) + HZ / 5);
-}
-
-static unsigned int serial8250_tx_empty(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
- unsigned int lsr;
-
- spin_lock_irqsave(&up->port.lock, flags);
- lsr = serial_in(up, UART_LSR);
- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int serial8250_get_mctrl(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned int status;
- unsigned int ret;
-
- status = check_modem_status(up);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-
- serial_out(up, UART_MCR, mcr);
-}
-
-static void serial8250_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- for (;;) {
- status = serial_in(up, UART_LSR);
-
- up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
-
- if ((status & bits) == bits)
- break;
- if (--tmout == 0)
- break;
- udelay(1);
- }
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- unsigned int tmout;
- for (tmout = 1000000; tmout; tmout--) {
- unsigned int msr = serial_in(up, UART_MSR);
- up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
- if (msr & UART_MSR_CTS)
- break;
- udelay(1);
- touch_nmi_watchdog();
- }
- }
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial8250_get_poll_char(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned char lsr = serial_inp(up, UART_LSR);
-
- if (!(lsr & UART_LSR_DR))
- return NO_POLL_CHAR;
-
- return serial_inp(up, UART_RX);
-}
-
-
-static void serial8250_put_poll_char(struct uart_port *port,
- unsigned char c)
-{
- unsigned int ier;
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
- if (up->capabilities & UART_CAP_UUE)
- serial_out(up, UART_IER, UART_IER_UUE);
- else
- serial_out(up, UART_IER, 0);
-
- wait_for_xmitr(up, BOTH_EMPTY);
- /*
- * Send the character out.
- * If a LF, also do CR...
- */
- serial_out(up, UART_TX, c);
- if (c == 10) {
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_out(up, UART_TX, 13);
- }
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int serial8250_startup(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
- unsigned char lsr, iir;
- int retval;
-
- up->port.fifosize = uart_config[up->port.type].fifo_size;
- up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
- up->capabilities = uart_config[up->port.type].flags;
- up->mcr = 0;
-
- if (up->port.iotype != up->cur_iotype)
- set_io_from_upio(port);
-
- if (up->port.type == PORT_16C950) {
- /* Wake up and initialize UART */
- up->acr = 0;
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(up, UART_EFR, UART_EFR_ECB);
- serial_outp(up, UART_IER, 0);
- serial_outp(up, UART_LCR, 0);
- serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
- serial_outp(up, UART_LCR, 0xBF);
- serial_outp(up, UART_EFR, UART_EFR_ECB);
- serial_outp(up, UART_LCR, 0);
- }
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * If this is an RSA port, see if we can kick it up to the
- * higher speed clock.
- */
- enable_rsa(up);
-#endif
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- serial8250_clear_fifos(up);
-
- /*
- * Clear the interrupt registers.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- /*
- * At this point, there's no way the LSR could still be 0xff;
- * if it is, then bail out, because there's likely no UART
- * here.
- */
- if (!(up->port.flags & UPF_BUGGY_UART) &&
- (serial_inp(up, UART_LSR) == 0xff)) {
- printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
- serial_index(&up->port));
- return -ENODEV;
- }
-
- /*
- * For a XR16C850, we need to set the trigger levels
- */
- if (up->port.type == PORT_16850) {
- unsigned char fctr;
-
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
- serial_outp(up, UART_TRG, UART_TRG_96);
- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
- serial_outp(up, UART_TRG, UART_TRG_96);
-
- serial_outp(up, UART_LCR, 0);
- }
-
- if (is_real_interrupt(up->port.irq)) {
- unsigned char iir1;
- /*
- * Test for UARTs that do not reassert THRE when the
- * transmitter is idle and the interrupt has already
- * been cleared. Real 16550s should always reassert
- * this interrupt whenever the transmitter is idle and
- * the interrupt is enabled. Delays are necessary to
- * allow register changes to become visible.
- */
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.irqflags & IRQF_SHARED)
- disable_irq_nosync(up->port.irq);
-
- wait_for_xmitr(up, UART_LSR_THRE);
- serial_out_sync(up, UART_IER, UART_IER_THRI);
- udelay(1); /* allow THRE to set */
- iir1 = serial_in(up, UART_IIR);
- serial_out(up, UART_IER, 0);
- serial_out_sync(up, UART_IER, UART_IER_THRI);
- udelay(1); /* allow a working UART time to re-assert THRE */
- iir = serial_in(up, UART_IIR);
- serial_out(up, UART_IER, 0);
-
- if (up->port.irqflags & IRQF_SHARED)
- enable_irq(up->port.irq);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * If the interrupt is not reasserted, setup a timer to
- * kick the UART on a regular basis.
- */
- if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
- up->bugs |= UART_BUG_THRE;
- pr_debug("ttyS%d - using backup timer\n",
- serial_index(port));
- }
- }
-
- /*
- * The above check will only give an accurate result the first time
- * the port is opened so this value needs to be preserved.
- */
- if (up->bugs & UART_BUG_THRE) {
- up->timer.function = serial8250_backup_timeout;
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies +
- uart_poll_timeout(port) + HZ / 5);
- }
-
- /*
- * If the "interrupt" for this port doesn't correspond with any
- * hardware interrupt, we use a timer-based system. The original
- * driver used to do this with IRQ0.
- */
- if (!is_real_interrupt(up->port.irq)) {
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
- } else {
- retval = serial_link_irq_chain(up);
- if (retval)
- return retval;
- }
-
- /*
- * Now, initialize the UART
- */
- serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- if (!is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT1;
- } else
- /*
- * Most PC uarts need OUT2 raised to enable interrupts.
- */
- if (is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
-
- /* Serial over Lan (SoL) hack:
- Intel 8257x Gigabit ethernet chips have a
- 16550 emulation, to be used for Serial Over Lan.
- Those chips take a longer time than a normal
- serial device to signalize that a transmission
- data was queued. Due to that, the above test generally
- fails. One solution would be to delay the reading of
- iir. However, this is not reliable, since the timeout
- is variable. So, let's just don't test if we receive
- TX irq. This way, we'll never enable UART_BUG_TXEN.
- */
- if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
- goto dont_test_tx_en;
-
- /*
- * Do a quick test to see if we receive an
- * interrupt when we enable the TX irq.
- */
- serial_outp(up, UART_IER, UART_IER_THRI);
- lsr = serial_in(up, UART_LSR);
- iir = serial_in(up, UART_IIR);
- serial_outp(up, UART_IER, 0);
-
- if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
- if (!(up->bugs & UART_BUG_TXEN)) {
- up->bugs |= UART_BUG_TXEN;
- pr_debug("ttyS%d - enabling bad tx status workarounds\n",
- serial_index(port));
- }
- } else {
- up->bugs &= ~UART_BUG_TXEN;
- }
-
-dont_test_tx_en:
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Clear the interrupt registers again for luck, and clear the
- * saved flags to avoid getting false values from polling
- * routines or the previous session.
- */
- serial_inp(up, UART_LSR);
- serial_inp(up, UART_RX);
- serial_inp(up, UART_IIR);
- serial_inp(up, UART_MSR);
- up->lsr_saved_flags = 0;
- up->msr_saved_flags = 0;
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI;
- serial_outp(up, UART_IER, up->ier);
-
- if (up->port.flags & UPF_FOURPORT) {
- unsigned int icp;
- /*
- * Enable interrupts on the AST Fourport board
- */
- icp = (up->port.iobase & 0xfe0) | 0x01f;
- outb_p(0x80, icp);
- (void) inb_p(icp);
- }
-
- return 0;
-}
-
-static void serial8250_shutdown(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_outp(up, UART_IER, 0);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- /* reset interrupts on the AST Fourport board */
- inb((up->port.iobase & 0xfe0) | 0x1f);
- up->port.mctrl |= TIOCM_OUT1;
- } else
- up->port.mctrl &= ~TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
- serial8250_clear_fifos(up);
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * Reset the RSA board back to 115kbps compat mode.
- */
- disable_rsa(up);
-#endif
-
- /*
- * Read data port to reset things, and then unlink from
- * the IRQ chain.
- */
- (void) serial_in(up, UART_RX);
-
- del_timer_sync(&up->timer);
- up->timer.function = serial8250_timeout;
- if (is_real_interrupt(up->port.irq))
- serial_unlink_irq_chain(up);
-}
-
-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
-{
- unsigned int quot;
-
- /*
- * Handle magic divisors for baud rates above baud_base on
- * SMSC SuperIO chips.
- */
- if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/4))
- quot = 0x8001;
- else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/8))
- quot = 0x8002;
- else
- quot = uart_get_divisor(port, baud);
-
- return quot;
-}
-
-void
-serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned char cval, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (termios->c_cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old,
- port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
- quot = serial8250_get_divisor(port, baud);
-
- /*
- * Oxford Semi 952 rev B workaround
- */
- if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
- quot++;
-
- if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
- if (baud < 2400)
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
- else
- fcr = uart_config[up->port.type].fcr;
- }
-
- /*
- * MCR-based auto flow control. When AFE is enabled, RTS will be
- * deasserted when the receive FIFO contains more characters than
- * the trigger, or the MCR RTS bit is cleared. In the case where
- * the remote UART is not using CTS auto flow control, we must
- * have sufficient FIFO entries for the latency of the remote
- * UART to respond. IOW, at least 32 bytes of FIFO.
- */
- if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) {
- up->mcr &= ~UART_MCR_AFE;
- if (termios->c_cflag & CRTSCTS)
- up->mcr |= UART_MCR_AFE;
- }
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (!(up->bugs & UART_BUG_NOMSR) &&
- 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;
-
- serial_out(up, UART_IER, up->ier);
-
- if (up->capabilities & UART_CAP_EFR) {
- unsigned char efr = 0;
- /*
- * TI16C752/Startech hardware flow control. FIXME:
- * - TI16C752 requires control thresholds to be set.
- * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
- */
- if (termios->c_cflag & CRTSCTS)
- efr |= UART_EFR_CTS;
-
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(up, UART_EFR, efr);
- }
-
-#ifdef CONFIG_ARCH_OMAP
- /* Workaround to enable 115200 baud on OMAP1510 internal ports */
- if (cpu_is_omap1510() && is_omap_port(up)) {
- if (baud == 115200) {
- quot = 1;
- serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
- } else
- serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
- }
-#endif
-
- if (up->capabilities & UART_NATSEMI) {
- /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
- serial_outp(up, UART_LCR, 0xe0);
- } else {
- serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
- }
-
- serial_dl_write(up, quot);
-
- /*
- * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
- * is written without DLAB set, this mode will be disabled.
- */
- if (up->port.type == PORT_16750)
- serial_outp(up, UART_FCR, fcr);
-
- serial_outp(up, UART_LCR, cval); /* reset DLAB */
- up->lcr = cval; /* Save LCR */
- if (up->port.type != PORT_16750) {
- if (fcr & UART_FCR_ENABLE_FIFO) {
- /* emulated UARTs (Lucent Venus 167x) need two steps */
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- }
- serial_outp(up, UART_FCR, fcr); /* set fcr */
- }
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
- /* Don't rewrite B0 */
- if (tty_termios_baud_rate(termios))
- tty_termios_encode_baud_rate(termios, baud, baud);
-}
-EXPORT_SYMBOL(serial8250_do_set_termios);
-
-static void
-serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- if (port->set_termios)
- port->set_termios(port, termios, old);
- else
- serial8250_do_set_termios(port, termios, old);
-}
-
-static void
-serial8250_set_ldisc(struct uart_port *port, int new)
-{
- if (new == N_PPS) {
- port->flags |= UPF_HARDPPS_CD;
- serial8250_enable_ms(port);
- } else
- port->flags &= ~UPF_HARDPPS_CD;
-}
-
-
-void serial8250_do_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_8250_port *p =
- container_of(port, struct uart_8250_port, port);
-
- serial8250_set_sleep(p, state != 0);
-}
-EXPORT_SYMBOL(serial8250_do_pm);
-
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- if (port->pm)
- port->pm(port, state, oldstate);
- else
- serial8250_do_pm(port, state, oldstate);
-}
-
-static unsigned int serial8250_port_size(struct uart_8250_port *pt)
-{
- if (pt->port.iotype == UPIO_AU)
- return 0x1000;
-#ifdef CONFIG_ARCH_OMAP
- if (is_omap_port(pt))
- return 0x16 << pt->port.regshift;
-#endif
- return 8 << pt->port.regshift;
-}
-
-/*
- * Resource handling.
- */
-static int serial8250_request_std_resource(struct uart_8250_port *up)
-{
- unsigned int size = serial8250_port_size(up);
- int ret = 0;
-
- switch (up->port.iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM:
- case UPIO_DWAPB:
- case UPIO_DWAPB32:
- if (!up->port.mapbase)
- break;
-
- if (!request_mem_region(up->port.mapbase, size, "serial")) {
- ret = -EBUSY;
- break;
- }
-
- if (up->port.flags & UPF_IOREMAP) {
- up->port.membase = ioremap_nocache(up->port.mapbase,
- size);
- if (!up->port.membase) {
- release_mem_region(up->port.mapbase, size);
- ret = -ENOMEM;
- }
- }
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- if (!request_region(up->port.iobase, size, "serial"))
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-static void serial8250_release_std_resource(struct uart_8250_port *up)
-{
- unsigned int size = serial8250_port_size(up);
-
- switch (up->port.iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM:
- case UPIO_DWAPB:
- case UPIO_DWAPB32:
- if (!up->port.mapbase)
- break;
-
- if (up->port.flags & UPF_IOREMAP) {
- iounmap(up->port.membase);
- up->port.membase = NULL;
- }
-
- release_mem_region(up->port.mapbase, size);
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- release_region(up->port.iobase, size);
- break;
- }
-}
-
-static int serial8250_request_rsa_resource(struct uart_8250_port *up)
-{
- unsigned long start = UART_RSA_BASE << up->port.regshift;
- unsigned int size = 8 << up->port.regshift;
- int ret = -EINVAL;
-
- switch (up->port.iotype) {
- case UPIO_HUB6:
- case UPIO_PORT:
- start += up->port.iobase;
- if (request_region(start, size, "serial-rsa"))
- ret = 0;
- else
- ret = -EBUSY;
- break;
- }
-
- return ret;
-}
-
-static void serial8250_release_rsa_resource(struct uart_8250_port *up)
-{
- unsigned long offset = UART_RSA_BASE << up->port.regshift;
- unsigned int size = 8 << up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_HUB6:
- case UPIO_PORT:
- release_region(up->port.iobase + offset, size);
- break;
- }
-}
-
-static void serial8250_release_port(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- serial8250_release_std_resource(up);
- if (up->port.type == PORT_RSA)
- serial8250_release_rsa_resource(up);
-}
-
-static int serial8250_request_port(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- int ret = 0;
-
- ret = serial8250_request_std_resource(up);
- if (ret == 0 && up->port.type == PORT_RSA) {
- ret = serial8250_request_rsa_resource(up);
- if (ret < 0)
- serial8250_release_std_resource(up);
- }
-
- return ret;
-}
-
-static void serial8250_config_port(struct uart_port *port, int flags)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- int probeflags = PROBE_ANY;
- int ret;
-
- /*
- * Find the region that we can probe for. This in turn
- * tells us whether we can probe for the type of port.
- */
- ret = serial8250_request_std_resource(up);
- if (ret < 0)
- return;
-
- ret = serial8250_request_rsa_resource(up);
- if (ret < 0)
- probeflags &= ~PROBE_RSA;
-
- if (up->port.iotype != up->cur_iotype)
- set_io_from_upio(port);
-
- if (flags & UART_CONFIG_TYPE)
- autoconfig(up, probeflags);
-
- /* if access method is AU, it is a 16550 with a quirk */
- if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
- up->bugs |= UART_BUG_NOMSR;
-
- if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
- autoconfig_irq(up);
-
- if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
- serial8250_release_rsa_resource(up);
- if (up->port.type == PORT_UNKNOWN)
- serial8250_release_std_resource(up);
-}
-
-static int
-serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->irq >= nr_irqs || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
- ser->type == PORT_STARTECH)
- return -EINVAL;
- return 0;
-}
-
-static const char *
-serial8250_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static struct uart_ops serial8250_pops = {
- .tx_empty = serial8250_tx_empty,
- .set_mctrl = serial8250_set_mctrl,
- .get_mctrl = serial8250_get_mctrl,
- .stop_tx = serial8250_stop_tx,
- .start_tx = serial8250_start_tx,
- .stop_rx = serial8250_stop_rx,
- .enable_ms = serial8250_enable_ms,
- .break_ctl = serial8250_break_ctl,
- .startup = serial8250_startup,
- .shutdown = serial8250_shutdown,
- .set_termios = serial8250_set_termios,
- .set_ldisc = serial8250_set_ldisc,
- .pm = serial8250_pm,
- .type = serial8250_type,
- .release_port = serial8250_release_port,
- .request_port = serial8250_request_port,
- .config_port = serial8250_config_port,
- .verify_port = serial8250_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = serial8250_get_poll_char,
- .poll_put_char = serial8250_put_poll_char,
-#endif
-};
-
-static struct uart_8250_port serial8250_ports[UART_NR];
-
-static void (*serial8250_isa_config)(int port, struct uart_port *up,
- unsigned short *capabilities);
-
-void serial8250_set_isa_configurator(
- void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
-{
- serial8250_isa_config = v;
-}
-EXPORT_SYMBOL(serial8250_set_isa_configurator);
-
-static void __init serial8250_isa_init_ports(void)
-{
- struct uart_8250_port *up;
- static int first = 1;
- int i, irqflag = 0;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- up->port.line = i;
- spin_lock_init(&up->port.lock);
-
- init_timer(&up->timer);
- up->timer.function = serial8250_timeout;
-
- /*
- * ALPHA_KLUDGE_MCR needs to be killed.
- */
- up->mcr_mask = ~ALPHA_KLUDGE_MCR;
- up->mcr_force = ALPHA_KLUDGE_MCR;
-
- up->port.ops = &serial8250_pops;
- }
-
- if (share_irqs)
- irqflag = IRQF_SHARED;
-
- for (i = 0, up = serial8250_ports;
- i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
- 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;
- up->port.membase = old_serial_port[i].iomem_base;
- up->port.iotype = old_serial_port[i].io_type;
- up->port.regshift = old_serial_port[i].iomem_reg_shift;
- set_io_from_upio(&up->port);
- up->port.irqflags |= irqflag;
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(i, &up->port, &up->capabilities);
-
- }
-}
-
-static void
-serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
-{
- up->port.type = type;
- up->port.fifosize = uart_config[type].fifo_size;
- up->capabilities = uart_config[type].flags;
- up->tx_loadsz = uart_config[type].tx_loadsz;
-}
-
-static void __init
-serial8250_register_ports(struct uart_driver *drv, struct device *dev)
-{
- int i;
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
- up->cur_iotype = 0xFF;
- }
-
- serial8250_isa_init_ports();
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- up->port.dev = dev;
-
- if (up->port.flags & UPF_FIXED_TYPE)
- serial8250_init_fixed_type_port(up, up->port.type);
-
- uart_add_one_port(drv, &up->port);
- }
-}
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-
-static void serial8250_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- wait_for_xmitr(up, UART_LSR_THRE);
- serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void
-serial8250_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_8250_port *up = &serial8250_ports[co->index];
- unsigned long flags;
- unsigned int ier;
- int locked = 1;
-
- touch_nmi_watchdog();
-
- local_irq_save(flags);
- if (up->port.sysrq) {
- /* serial8250_handle_port() already took the lock */
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&up->port.lock);
- } else
- spin_lock(&up->port.lock);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
-
- if (up->capabilities & UART_CAP_UUE)
- serial_out(up, UART_IER, UART_IER_UUE);
- else
- serial_out(up, UART_IER, 0);
-
- uart_console_write(&up->port, s, count, serial8250_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_out(up, UART_IER, ier);
-
- /*
- * The receive handling will happen properly because the
- * receive ready bit will still be set; it is not cleared
- * on read. However, modem control will not, we must
- * call it if we have saved something in the saved flags
- * while processing with interrupts off.
- */
- if (up->msr_saved_flags)
- check_modem_status(up);
-
- if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
-}
-
-static int __init serial8250_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= nr_uarts)
- co->index = 0;
- port = &serial8250_ports[co->index].port;
- if (!port->iobase && !port->membase)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static int serial8250_console_early_setup(void)
-{
- return serial8250_find_port_for_earlycon();
-}
-
-static struct console serial8250_console = {
- .name = "ttyS",
- .write = serial8250_console_write,
- .device = uart_console_device,
- .setup = serial8250_console_setup,
- .early_setup = serial8250_console_early_setup,
- .flags = CON_PRINTBUFFER | CON_ANYTIME,
- .index = -1,
- .data = &serial8250_reg,
-};
-
-static int __init serial8250_console_init(void)
-{
- if (nr_uarts > UART_NR)
- nr_uarts = UART_NR;
-
- serial8250_isa_init_ports();
- register_console(&serial8250_console);
- return 0;
-}
-console_initcall(serial8250_console_init);
-
-int serial8250_find_port(struct uart_port *p)
-{
- int line;
- struct uart_port *port;
-
- for (line = 0; line < nr_uarts; line++) {
- port = &serial8250_ports[line].port;
- if (uart_match_port(p, port))
- return line;
- }
- return -ENODEV;
-}
-
-#define SERIAL8250_CONSOLE &serial8250_console
-#else
-#define SERIAL8250_CONSOLE NULL
-#endif
-
-static struct uart_driver serial8250_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .cons = SERIAL8250_CONSOLE,
-};
-
-/*
- * early_serial_setup - early registration for 8250 ports
- *
- * Setup an 8250 port structure prior to console initialisation. Use
- * after console initialisation will cause undefined behaviour.
- */
-int __init early_serial_setup(struct uart_port *port)
-{
- struct uart_port *p;
-
- if (port->line >= ARRAY_SIZE(serial8250_ports))
- return -ENODEV;
-
- serial8250_isa_init_ports();
- p = &serial8250_ports[port->line].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;
- p->iotype = port->iotype;
- p->flags = port->flags;
- p->mapbase = port->mapbase;
- p->private_data = port->private_data;
- p->type = port->type;
- p->line = port->line;
-
- set_io_from_upio(p);
- if (port->serial_in)
- p->serial_in = port->serial_in;
- if (port->serial_out)
- p->serial_out = port->serial_out;
-
- return 0;
-}
-
-/**
- * serial8250_suspend_port - suspend one serial port
- * @line: serial line number
- *
- * Suspend one serial port.
- */
-void serial8250_suspend_port(int line)
-{
- uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
-}
-
-/**
- * serial8250_resume_port - resume one serial port
- * @line: serial line number
- *
- * Resume one serial port.
- */
-void serial8250_resume_port(int line)
-{
- struct uart_8250_port *up = &serial8250_ports[line];
-
- if (up->capabilities & UART_NATSEMI) {
- unsigned char tmp;
-
- /* Ensure it's still in high speed mode */
- serial_outp(up, UART_LCR, 0xE0);
-
- tmp = serial_in(up, 0x04); /* EXCR2 */
- tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
- tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
- serial_outp(up, 0x04, tmp);
-
- serial_outp(up, UART_LCR, 0);
- }
- uart_resume_port(&serial8250_reg, &up->port);
-}
-
-/*
- * Register a set of serial devices attached to a platform device. The
- * list is terminated with a zero flags entry, which means we expect
- * all entries to have at least UPF_BOOT_AUTOCONF set.
- */
-static int __devinit serial8250_probe(struct platform_device *dev)
-{
- struct plat_serial8250_port *p = dev->dev.platform_data;
- struct uart_port port;
- int ret, i, irqflag = 0;
-
- memset(&port, 0, sizeof(struct uart_port));
-
- if (share_irqs)
- irqflag = IRQF_SHARED;
-
- for (i = 0; p && p->flags != 0; p++, i++) {
- port.iobase = p->iobase;
- port.membase = p->membase;
- port.irq = p->irq;
- port.irqflags = p->irqflags;
- port.uartclk = p->uartclk;
- port.regshift = p->regshift;
- port.iotype = p->iotype;
- port.flags = p->flags;
- port.mapbase = p->mapbase;
- port.hub6 = p->hub6;
- port.private_data = p->private_data;
- port.type = p->type;
- port.serial_in = p->serial_in;
- port.serial_out = p->serial_out;
- port.set_termios = p->set_termios;
- port.pm = p->pm;
- port.dev = &dev->dev;
- port.irqflags |= irqflag;
- ret = serial8250_register_port(&port);
- if (ret < 0) {
- dev_err(&dev->dev, "unable to register port at index %d "
- "(IO%lx MEM%llx IRQ%d): %d\n", i,
- p->iobase, (unsigned long long)p->mapbase,
- p->irq, ret);
- }
- }
- return 0;
-}
-
-/*
- * Remove serial ports registered against a platform device.
- */
-static int __devexit serial8250_remove(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- if (up->port.dev == &dev->dev)
- serial8250_unregister_port(i);
- }
- return 0;
-}
-
-static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- uart_suspend_port(&serial8250_reg, &up->port);
- }
-
- return 0;
-}
-
-static int serial8250_resume(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- serial8250_resume_port(i);
- }
-
- return 0;
-}
-
-static struct platform_driver serial8250_isa_driver = {
- .probe = serial8250_probe,
- .remove = __devexit_p(serial8250_remove),
- .suspend = serial8250_suspend,
- .resume = serial8250_resume,
- .driver = {
- .name = "serial8250",
- .owner = THIS_MODULE,
- },
-};
-
-/*
- * This "device" covers _all_ ISA 8250-compatible serial devices listed
- * in the table in include/asm/serial.h
- */
-static struct platform_device *serial8250_isa_devs;
-
-/*
- * serial8250_register_port and serial8250_unregister_port allows for
- * 16x50 serial ports to be configured at run-time, to support PCMCIA
- * modems and PCI multiport cards.
- */
-static DEFINE_MUTEX(serial_mutex);
-
-static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
-{
- int i;
-
- /*
- * First, find a port entry which matches.
- */
- for (i = 0; i < nr_uarts; i++)
- if (uart_match_port(&serial8250_ports[i].port, port))
- return &serial8250_ports[i];
-
- /*
- * We didn't find a matching entry, so look for the first
- * free entry. We look for one which hasn't been previously
- * used (indicated by zero iobase).
- */
- for (i = 0; i < nr_uarts; i++)
- if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
- serial8250_ports[i].port.iobase == 0)
- return &serial8250_ports[i];
-
- /*
- * That also failed. Last resort is to find any entry which
- * doesn't have a real port associated with it.
- */
- for (i = 0; i < nr_uarts; i++)
- if (serial8250_ports[i].port.type == PORT_UNKNOWN)
- return &serial8250_ports[i];
-
- return NULL;
-}
-
-/**
- * serial8250_register_port - register a serial port
- * @port: serial port template
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use, it is hung up and unregistered
- * first.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- */
-int serial8250_register_port(struct uart_port *port)
-{
- struct uart_8250_port *uart;
- int ret = -ENOSPC;
-
- if (port->uartclk == 0)
- return -EINVAL;
-
- mutex_lock(&serial_mutex);
-
- uart = serial8250_find_match_or_unused(port);
- if (uart) {
- uart_remove_one_port(&serial8250_reg, &uart->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;
- uart->port.iotype = port->iotype;
- uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
- uart->port.mapbase = port->mapbase;
- uart->port.private_data = port->private_data;
- if (port->dev)
- uart->port.dev = port->dev;
-
- if (port->flags & UPF_FIXED_TYPE)
- serial8250_init_fixed_type_port(uart, port->type);
-
- set_io_from_upio(&uart->port);
- /* Possibly override default I/O functions. */
- if (port->serial_in)
- uart->port.serial_in = port->serial_in;
- if (port->serial_out)
- uart->port.serial_out = port->serial_out;
- /* Possibly override set_termios call */
- if (port->set_termios)
- uart->port.set_termios = port->set_termios;
- if (port->pm)
- uart->port.pm = port->pm;
-
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(0, &uart->port,
- &uart->capabilities);
-
- ret = uart_add_one_port(&serial8250_reg, &uart->port);
- if (ret == 0)
- ret = uart->port.line;
- }
- mutex_unlock(&serial_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(serial8250_register_port);
-
-/**
- * serial8250_unregister_port - remove a 16x50 serial port at runtime
- * @line: serial line number
- *
- * Remove one serial port. This may not be called from interrupt
- * context. We hand the port back to the our control.
- */
-void serial8250_unregister_port(int line)
-{
- struct uart_8250_port *uart = &serial8250_ports[line];
-
- mutex_lock(&serial_mutex);
- uart_remove_one_port(&serial8250_reg, &uart->port);
- if (serial8250_isa_devs) {
- uart->port.flags &= ~UPF_BOOT_AUTOCONF;
- uart->port.type = PORT_UNKNOWN;
- uart->port.dev = &serial8250_isa_devs->dev;
- uart_add_one_port(&serial8250_reg, &uart->port);
- } else {
- uart->port.dev = NULL;
- }
- mutex_unlock(&serial_mutex);
-}
-EXPORT_SYMBOL(serial8250_unregister_port);
-
-static int __init serial8250_init(void)
-{
- int ret;
-
- if (nr_uarts > UART_NR)
- nr_uarts = UART_NR;
-
- printk(KERN_INFO "Serial: 8250/16550 driver, "
- "%d ports, IRQ sharing %sabled\n", nr_uarts,
- share_irqs ? "en" : "dis");
-
-#ifdef CONFIG_SPARC
- ret = sunserial_register_minors(&serial8250_reg, UART_NR);
-#else
- serial8250_reg.nr = UART_NR;
- ret = uart_register_driver(&serial8250_reg);
-#endif
- if (ret)
- goto out;
-
- serial8250_isa_devs = platform_device_alloc("serial8250",
- PLAT8250_DEV_LEGACY);
- if (!serial8250_isa_devs) {
- ret = -ENOMEM;
- goto unreg_uart_drv;
- }
-
- ret = platform_device_add(serial8250_isa_devs);
- if (ret)
- goto put_dev;
-
- serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
-
- ret = platform_driver_register(&serial8250_isa_driver);
- if (ret == 0)
- goto out;
-
- platform_device_del(serial8250_isa_devs);
-put_dev:
- platform_device_put(serial8250_isa_devs);
-unreg_uart_drv:
-#ifdef CONFIG_SPARC
- sunserial_unregister_minors(&serial8250_reg, UART_NR);
-#else
- uart_unregister_driver(&serial8250_reg);
-#endif
-out:
- return ret;
-}
-
-static void __exit serial8250_exit(void)
-{
- struct platform_device *isa_dev = serial8250_isa_devs;
-
- /*
- * This tells serial8250_unregister_port() not to re-register
- * the ports (thereby making serial8250_isa_driver permanently
- * in use.)
- */
- serial8250_isa_devs = NULL;
-
- platform_driver_unregister(&serial8250_isa_driver);
- platform_device_unregister(isa_dev);
-
-#ifdef CONFIG_SPARC
- sunserial_unregister_minors(&serial8250_reg, UART_NR);
-#else
- uart_unregister_driver(&serial8250_reg);
-#endif
-}
-
-module_init(serial8250_init);
-module_exit(serial8250_exit);
-
-EXPORT_SYMBOL(serial8250_suspend_port);
-EXPORT_SYMBOL(serial8250_resume_port);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
-
-module_param(share_irqs, uint, 0644);
-MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
- " (unsafe)");
-
-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");
-#endif
-MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
deleted file mode 100644
index 6e19ea3e48d5..000000000000
--- a/drivers/serial/8250.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * linux/drivers/char/8250.h
- *
- * Driver for 8250/16550-type serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King.
- *
- * 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/serial_8250.h>
-
-struct old_serial_port {
- unsigned int uart;
- unsigned int baud_base;
- unsigned int port;
- unsigned int irq;
- unsigned int flags;
- unsigned char hub6;
- unsigned char io_type;
- unsigned char *iomem_base;
- unsigned short iomem_reg_shift;
- unsigned long irqflags;
-};
-
-/*
- * This replaces serial_uart_config in include/linux/serial.h
- */
-struct serial8250_config {
- const char *name;
- unsigned short fifo_size;
- unsigned short tx_loadsz;
- unsigned char fcr;
- unsigned int flags;
-};
-
-#define UART_CAP_FIFO (1 << 8) /* UART has FIFO */
-#define UART_CAP_EFR (1 << 9) /* UART has EFR */
-#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_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
-#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
-#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
-#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
-
-#define PROBE_RSA (1 << 0)
-#define PROBE_ANY (~0)
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
-#define SERIAL8250_SHARE_IRQS 1
-#else
-#define SERIAL8250_SHARE_IRQS 0
-#endif
-
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-/*
- * Digital did something really horribly wrong with the OUT1 and OUT2
- * lines on at least some ALPHA's. The failure mode is that if either
- * is cleared, the machine locks up with endless interrupts.
- */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
-#elif defined(CONFIG_SBC8560)
-/*
- * WindRiver did something similarly broken on their SBC8560 board. The
- * UART tristates its IRQ output while OUT2 is clear, but they pulled
- * the interrupt line _up_ instead of down, so if we register the IRQ
- * while the UART is in that state, we die in an IRQ storm. */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
-#else
-#define ALPHA_KLUDGE_MCR 0
-#endif
diff --git a/drivers/serial/8250_accent.c b/drivers/serial/8250_accent.c
deleted file mode 100644
index 9c10262f2469..000000000000
--- a/drivers/serial/8250_accent.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * linux/drivers/serial/8250_accent.c
- *
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF, \
- }
-
-static struct plat_serial8250_port accent_data[] = {
- PORT(0x330, 4),
- PORT(0x338, 4),
- { },
-};
-
-static struct platform_device accent_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_ACCENT,
- .dev = {
- .platform_data = accent_data,
- },
-};
-
-static int __init accent_init(void)
-{
- return platform_device_register(&accent_device);
-}
-
-module_init(accent_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Accent Async cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c
deleted file mode 100644
index b0ce8c56f1a4..000000000000
--- a/drivers/serial/8250_acorn.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * linux/drivers/serial/acorn.c
- *
- * Copyright (C) 1996-2003 Russell King.
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/ecard.h>
-#include <asm/string.h>
-
-#include "8250.h"
-
-#define MAX_PORTS 3
-
-struct serial_card_type {
- unsigned int num_ports;
- unsigned int uartclk;
- unsigned int type;
- unsigned int offset[MAX_PORTS];
-};
-
-struct serial_card_info {
- unsigned int num_ports;
- int ports[MAX_PORTS];
- void __iomem *vaddr;
-};
-
-static int __devinit
-serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
- struct serial_card_info *info;
- struct serial_card_type *type = id->data;
- struct uart_port port;
- unsigned long bus_addr;
- unsigned int i;
-
- info = kzalloc(sizeof(struct serial_card_info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- info->num_ports = type->num_ports;
-
- bus_addr = ecard_resource_start(ec, type->type);
- info->vaddr = ecardm_iomap(ec, type->type, 0, 0);
- if (!info->vaddr) {
- kfree(info);
- return -ENOMEM;
- }
-
- ecard_set_drvdata(ec, info);
-
- memset(&port, 0, sizeof(struct uart_port));
- port.irq = ec->irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- port.uartclk = type->uartclk;
- port.iotype = UPIO_MEM;
- port.regshift = 2;
- port.dev = &ec->dev;
-
- for (i = 0; i < info->num_ports; i ++) {
- port.membase = info->vaddr + type->offset[i];
- port.mapbase = bus_addr + type->offset[i];
-
- info->ports[i] = serial8250_register_port(&port);
- }
-
- return 0;
-}
-
-static void __devexit serial_card_remove(struct expansion_card *ec)
-{
- struct serial_card_info *info = ecard_get_drvdata(ec);
- int i;
-
- ecard_set_drvdata(ec, NULL);
-
- for (i = 0; i < info->num_ports; i++)
- if (info->ports[i] > 0)
- serial8250_unregister_port(info->ports[i]);
-
- kfree(info);
-}
-
-static struct serial_card_type atomwide_type = {
- .num_ports = 3,
- .uartclk = 7372800,
- .type = ECARD_RES_IOCSLOW,
- .offset = { 0x2800, 0x2400, 0x2000 },
-};
-
-static struct serial_card_type serport_type = {
- .num_ports = 2,
- .uartclk = 3686400,
- .type = ECARD_RES_IOCSLOW,
- .offset = { 0x2000, 0x2020 },
-};
-
-static const struct ecard_id serial_cids[] = {
- { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, &atomwide_type },
- { MANU_SERPORT, PROD_SERPORT_DSPORT, &serport_type },
- { 0xffff, 0xffff }
-};
-
-static struct ecard_driver serial_card_driver = {
- .probe = serial_card_probe,
- .remove = __devexit_p(serial_card_remove),
- .id_table = serial_cids,
- .drv = {
- .name = "8250_acorn",
- },
-};
-
-static int __init serial_card_init(void)
-{
- return ecard_register_driver(&serial_card_driver);
-}
-
-static void __exit serial_card_exit(void)
-{
- ecard_remove_driver(&serial_card_driver);
-}
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver");
-MODULE_LICENSE("GPL");
-
-module_init(serial_card_init);
-module_exit(serial_card_exit);
diff --git a/drivers/serial/8250_boca.c b/drivers/serial/8250_boca.c
deleted file mode 100644
index 3bfe0f7b26fb..000000000000
--- a/drivers/serial/8250_boca.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * linux/drivers/serial/8250_boca.c
- *
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF, \
- }
-
-static struct plat_serial8250_port boca_data[] = {
- PORT(0x100, 12),
- PORT(0x108, 12),
- PORT(0x110, 12),
- PORT(0x118, 12),
- PORT(0x120, 12),
- PORT(0x128, 12),
- PORT(0x130, 12),
- PORT(0x138, 12),
- PORT(0x140, 12),
- PORT(0x148, 12),
- PORT(0x150, 12),
- PORT(0x158, 12),
- PORT(0x160, 12),
- PORT(0x168, 12),
- PORT(0x170, 12),
- PORT(0x178, 12),
- { },
-};
-
-static struct platform_device boca_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_BOCA,
- .dev = {
- .platform_data = boca_data,
- },
-};
-
-static int __init boca_init(void)
-{
- return platform_device_register(&boca_device);
-}
-
-module_init(boca_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Boca cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
deleted file mode 100644
index eaafb98debed..000000000000
--- a/drivers/serial/8250_early.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Early serial console for 8250/16550 devices
- *
- * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * 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.
- *
- * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
- * and on early_printk.c by Andi Kleen.
- *
- * This is for use before the serial driver has initialized, in
- * particular, before the UARTs have been discovered and named.
- * Instead of specifying the console device as, e.g., "ttyS0",
- * we locate the device directly by its MMIO or I/O port address.
- *
- * The user can specify the device directly, e.g.,
- * earlycon=uart8250,io,0x3f8,9600n8
- * earlycon=uart8250,mmio,0xff5e0000,115200n8
- * earlycon=uart8250,mmio32,0xff5e0000,115200n8
- * or
- * console=uart8250,io,0x3f8,9600n8
- * console=uart8250,mmio,0xff5e0000,115200n8
- * console=uart8250,mmio32,0xff5e0000,115200n8
- */
-
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <asm/io.h>
-#include <asm/serial.h>
-#ifdef CONFIG_FIX_EARLYCON_MEM
-#include <asm/pgtable.h>
-#include <asm/fixmap.h>
-#endif
-
-struct early_serial8250_device {
- struct uart_port port;
- char options[16]; /* e.g., 115200n8 */
- unsigned int baud;
-};
-
-static struct early_serial8250_device early_device;
-
-static unsigned int __init serial_in(struct uart_port *port, int offset)
-{
- switch (port->iotype) {
- case UPIO_MEM:
- return readb(port->membase + offset);
- case UPIO_MEM32:
- return readl(port->membase + (offset << 2));
- case UPIO_PORT:
- return inb(port->iobase + offset);
- default:
- return 0;
- }
-}
-
-static void __init serial_out(struct uart_port *port, int offset, int value)
-{
- switch (port->iotype) {
- case UPIO_MEM:
- writeb(value, port->membase + offset);
- break;
- case UPIO_MEM32:
- writel(value, port->membase + (offset << 2));
- break;
- case UPIO_PORT:
- outb(value, port->iobase + offset);
- break;
- }
-}
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static void __init wait_for_xmitr(struct uart_port *port)
-{
- unsigned int status;
-
- for (;;) {
- status = serial_in(port, UART_LSR);
- if ((status & BOTH_EMPTY) == BOTH_EMPTY)
- return;
- cpu_relax();
- }
-}
-
-static void __init serial_putc(struct uart_port *port, int c)
-{
- wait_for_xmitr(port);
- serial_out(port, UART_TX, c);
-}
-
-static void __init early_serial8250_write(struct console *console,
- const char *s, unsigned int count)
-{
- struct uart_port *port = &early_device.port;
- unsigned int ier;
-
- /* Save the IER and disable interrupts */
- ier = serial_in(port, UART_IER);
- serial_out(port, UART_IER, 0);
-
- uart_console_write(port, s, count, serial_putc);
-
- /* Wait for transmitter to become empty and restore the IER */
- wait_for_xmitr(port);
- serial_out(port, UART_IER, ier);
-}
-
-static unsigned int __init probe_baud(struct uart_port *port)
-{
- unsigned char lcr, dll, dlm;
- unsigned int quot;
-
- lcr = serial_in(port, UART_LCR);
- serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
- dll = serial_in(port, UART_DLL);
- dlm = serial_in(port, UART_DLM);
- serial_out(port, UART_LCR, lcr);
-
- quot = (dlm << 8) | dll;
- return (port->uartclk / 16) / quot;
-}
-
-static void __init init_port(struct early_serial8250_device *device)
-{
- struct uart_port *port = &device->port;
- unsigned int divisor;
- unsigned char c;
-
- serial_out(port, UART_LCR, 0x3); /* 8n1 */
- serial_out(port, UART_IER, 0); /* no interrupt */
- serial_out(port, UART_FCR, 0); /* no fifo */
- serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
-
- divisor = port->uartclk / (16 * device->baud);
- c = serial_in(port, UART_LCR);
- serial_out(port, UART_LCR, c | UART_LCR_DLAB);
- serial_out(port, UART_DLL, divisor & 0xff);
- serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
- serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
-}
-
-static int __init parse_options(struct early_serial8250_device *device,
- char *options)
-{
- struct uart_port *port = &device->port;
- int mmio, mmio32, length;
-
- if (!options)
- return -ENODEV;
-
- port->uartclk = BASE_BAUD * 16;
-
- mmio = !strncmp(options, "mmio,", 5);
- mmio32 = !strncmp(options, "mmio32,", 7);
- if (mmio || mmio32) {
- port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
- port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
- &options, 0);
- if (mmio32)
- port->regshift = 2;
-#ifdef CONFIG_FIX_EARLYCON_MEM
- set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
- port->mapbase & PAGE_MASK);
- port->membase =
- (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
- port->membase += port->mapbase & ~PAGE_MASK;
-#else
- port->membase = ioremap_nocache(port->mapbase, 64);
- if (!port->membase) {
- printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
- __func__,
- (unsigned long long) port->mapbase);
- return -ENOMEM;
- }
-#endif
- } else if (!strncmp(options, "io,", 3)) {
- port->iotype = UPIO_PORT;
- port->iobase = simple_strtoul(options + 3, &options, 0);
- mmio = 0;
- } else
- return -EINVAL;
-
- options = strchr(options, ',');
- if (options) {
- options++;
- device->baud = simple_strtoul(options, NULL, 0);
- length = min(strcspn(options, " "), sizeof(device->options));
- strncpy(device->options, options, length);
- } else {
- device->baud = probe_baud(port);
- snprintf(device->options, sizeof(device->options), "%u",
- device->baud);
- }
-
- if (mmio || mmio32)
- printk(KERN_INFO
- "Early serial console at MMIO%s 0x%llx (options '%s')\n",
- mmio32 ? "32" : "",
- (unsigned long long)port->mapbase,
- device->options);
- else
- printk(KERN_INFO
- "Early serial console at I/O port 0x%lx (options '%s')\n",
- port->iobase,
- device->options);
-
- return 0;
-}
-
-static struct console early_serial8250_console __initdata = {
- .name = "uart",
- .write = early_serial8250_write,
- .flags = CON_PRINTBUFFER | CON_BOOT,
- .index = -1,
-};
-
-static int __init early_serial8250_setup(char *options)
-{
- struct early_serial8250_device *device = &early_device;
- int err;
-
- if (device->port.membase || device->port.iobase)
- return 0;
-
- err = parse_options(device, options);
- if (err < 0)
- return err;
-
- init_port(device);
- return 0;
-}
-
-int __init setup_early_serial8250_console(char *cmdline)
-{
- char *options;
- int err;
-
- options = strstr(cmdline, "uart8250,");
- if (!options) {
- options = strstr(cmdline, "uart,");
- if (!options)
- return 0;
- }
-
- options = strchr(cmdline, ',') + 1;
- err = early_serial8250_setup(options);
- if (err < 0)
- return err;
-
- register_console(&early_serial8250_console);
-
- return 0;
-}
-
-int serial8250_find_port_for_earlycon(void)
-{
- struct early_serial8250_device *device = &early_device;
- struct uart_port *port = &device->port;
- int line;
- int ret;
-
- if (!device->port.membase && !device->port.iobase)
- return -ENODEV;
-
- line = serial8250_find_port(port);
- if (line < 0)
- return -ENODEV;
-
- ret = update_console_cmdline("uart", 8250,
- "ttyS", line, device->options);
- if (ret < 0)
- ret = update_console_cmdline("uart", 0,
- "ttyS", line, device->options);
-
- return ret;
-}
-
-early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/8250_exar_st16c554.c b/drivers/serial/8250_exar_st16c554.c
deleted file mode 100644
index 567143ace159..000000000000
--- a/drivers/serial/8250_exar_st16c554.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * linux/drivers/serial/8250_exar.c
- *
- * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
- * Based on 8250_boca.
- *
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF, \
- }
-
-static struct plat_serial8250_port exar_data[] = {
- PORT(0x100, 5),
- PORT(0x108, 5),
- PORT(0x110, 5),
- PORT(0x118, 5),
- { },
-};
-
-static struct platform_device exar_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_EXAR_ST16C554,
- .dev = {
- .platform_data = exar_data,
- },
-};
-
-static int __init exar_init(void)
-{
- return platform_device_register(&exar_device);
-}
-
-module_init(exar_init);
-
-MODULE_AUTHOR("Paul B Schroeder");
-MODULE_DESCRIPTION("8250 serial probe module for Exar cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_fourport.c b/drivers/serial/8250_fourport.c
deleted file mode 100644
index 6375d68b7913..000000000000
--- a/drivers/serial/8250_fourport.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * linux/drivers/serial/8250_fourport.c
- *
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF | UPF_FOURPORT, \
- }
-
-static struct plat_serial8250_port fourport_data[] = {
- PORT(0x1a0, 9),
- PORT(0x1a8, 9),
- PORT(0x1b0, 9),
- PORT(0x1b8, 9),
- PORT(0x2a0, 5),
- PORT(0x2a8, 5),
- PORT(0x2b0, 5),
- PORT(0x2b8, 5),
- { },
-};
-
-static struct platform_device fourport_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_FOURPORT,
- .dev = {
- .platform_data = fourport_data,
- },
-};
-
-static int __init fourport_init(void)
-{
- return platform_device_register(&fourport_device);
-}
-
-module_init(fourport_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for AST Fourport cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
deleted file mode 100644
index d8c0ffbfa6e3..000000000000
--- a/drivers/serial/8250_gsc.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Serial Device Initialisation for Lasi/Asp/Wax/Dino
- *
- * (c) Copyright Matthew Wilcox <willy@debian.org> 2001-2002
- *
- * 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/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/serial_core.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-
-#include <asm/hardware.h>
-#include <asm/parisc-device.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-static int __init serial_init_chip(struct parisc_device *dev)
-{
- struct uart_port port;
- unsigned long address;
- int err;
-
- if (!dev->irq) {
- /* We find some unattached serial ports by walking native
- * busses. These should be silently ignored. Otherwise,
- * what we have here is a missing parent device, so tell
- * the user what they're missing.
- */
- if (parisc_parent(dev)->id.hw_type != HPHW_IOA)
- printk(KERN_INFO
- "Serial: device 0x%llx not configured.\n"
- "Enable support for Wax, Lasi, Asp or Dino.\n",
- (unsigned long long)dev->hpa.start);
- return -ENODEV;
- }
-
- address = dev->hpa.start;
- if (dev->id.sversion != 0x8d)
- address += 0x800;
-
- memset(&port, 0, sizeof(port));
- port.iotype = UPIO_MEM;
- /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
- port.uartclk = 7272727;
- port.mapbase = address;
- port.membase = ioremap_nocache(address, 16);
- port.irq = dev->irq;
- port.flags = UPF_BOOT_AUTOCONF;
- port.dev = &dev->dev;
-
- err = serial8250_register_port(&port);
- if (err < 0) {
- printk(KERN_WARNING
- "serial8250_register_port returned error %d\n", err);
- iounmap(port.membase);
- return err;
- }
-
- return 0;
-}
-
-static struct parisc_device_id serial_tbl[] = {
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 },
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c },
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d },
- { 0 }
-};
-
-/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1
- * attached to Dino. Unfortunately, Dino appears before Lasi in the device
- * tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one
- * which only knows about Lasi and then a second which will find all the
- * other serial ports. HPUX ignores this problem.
- */
-static struct parisc_device_id lasi_tbl[] = {
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */
- { 0 }
-};
-
-
-MODULE_DEVICE_TABLE(parisc, serial_tbl);
-
-static struct parisc_driver lasi_driver = {
- .name = "serial_1",
- .id_table = lasi_tbl,
- .probe = serial_init_chip,
-};
-
-static struct parisc_driver serial_driver = {
- .name = "serial",
- .id_table = serial_tbl,
- .probe = serial_init_chip,
-};
-
-static int __init probe_serial_gsc(void)
-{
- register_parisc_driver(&lasi_driver);
- register_parisc_driver(&serial_driver);
- return 0;
-}
-
-module_init(probe_serial_gsc);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_hp300.c b/drivers/serial/8250_hp300.c
deleted file mode 100644
index c13438c93012..000000000000
--- a/drivers/serial/8250_hp300.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Driver for the 98626/98644/internal serial interface on hp300/hp400
- * (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
- *
- * Ported from 2.2 and modified to use the normal 8250 driver
- * by Kars de Jong <jongk@linux-m68k.org>, May 2004.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-#include <linux/dio.h>
-#include <linux/console.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
-#warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
-#endif
-
-#ifdef CONFIG_HPAPCI
-struct hp300_port
-{
- struct hp300_port *next; /* next port */
- int line; /* line (tty) number */
-};
-
-static struct hp300_port *hp300_ports;
-#endif
-
-#ifdef CONFIG_HPDCA
-
-static int __devinit hpdca_init_one(struct dio_dev *d,
- const struct dio_device_id *ent);
-static void __devexit hpdca_remove_one(struct dio_dev *d);
-
-static struct dio_device_id hpdca_dio_tbl[] = {
- { DIO_ID_DCA0 },
- { DIO_ID_DCA0REM },
- { DIO_ID_DCA1 },
- { DIO_ID_DCA1REM },
- { 0 }
-};
-
-static struct dio_driver hpdca_driver = {
- .name = "hpdca",
- .id_table = hpdca_dio_tbl,
- .probe = hpdca_init_one,
- .remove = __devexit_p(hpdca_remove_one),
-};
-
-#endif
-
-static unsigned int num_ports;
-
-extern int hp300_uart_scode;
-
-/* Offset to UART registers from base of DCA */
-#define UART_OFFSET 17
-
-#define DCA_ID 0x01 /* ID (read), reset (write) */
-#define DCA_IC 0x03 /* Interrupt control */
-
-/* Interrupt control */
-#define DCA_IC_IE 0x80 /* Master interrupt enable */
-
-#define HPDCA_BAUD_BASE 153600
-
-/* Base address of the Frodo part */
-#define FRODO_BASE (0x41c000)
-
-/*
- * Where we find the 8250-like APCI ports, and how far apart they are.
- */
-#define FRODO_APCIBASE 0x0
-#define FRODO_APCISPACE 0x20
-#define FRODO_APCI_OFFSET(x) (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
-
-#define HPAPCI_BAUD_BASE 500400
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-/*
- * Parse the bootinfo to find descriptions for headless console and
- * debug serial ports and register them with the 8250 driver.
- * This function should be called before serial_console_init() is called
- * to make sure the serial console will be available for use. IA-64 kernel
- * calls this function from setup_arch() after the EFI and ACPI tables have
- * been parsed.
- */
-int __init hp300_setup_serial_console(void)
-{
- int scode;
- struct uart_port port;
-
- memset(&port, 0, sizeof(port));
-
- if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
- return 0;
-
- if (DIO_SCINHOLE(hp300_uart_scode))
- return 0;
-
- scode = hp300_uart_scode;
-
- /* Memory mapped I/O */
- port.iotype = UPIO_MEM;
- port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
- port.type = PORT_UNKNOWN;
-
- /* Check for APCI console */
- if (scode == 256) {
-#ifdef CONFIG_HPAPCI
- printk(KERN_INFO "Serial console is HP APCI 1\n");
-
- port.uartclk = HPAPCI_BAUD_BASE * 16;
- port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
- port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
- port.regshift = 2;
- add_preferred_console("ttyS", port.line, "9600n8");
-#else
- printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
- return 0;
-#endif
- } else {
-#ifdef CONFIG_HPDCA
- unsigned long pa = dio_scodetophysaddr(scode);
- if (!pa)
- return 0;
-
- printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode);
-
- port.uartclk = HPDCA_BAUD_BASE * 16;
- port.mapbase = (pa + UART_OFFSET);
- port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
- port.regshift = 1;
- port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
-
- /* Enable board-interrupts */
- out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
-
- if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80)
- add_preferred_console("ttyS", port.line, "9600n8");
-#else
- printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
- return 0;
-#endif
- }
-
- if (early_serial_setup(&port) < 0)
- printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n");
- return 0;
-}
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-
-#ifdef CONFIG_HPDCA
-static int __devinit hpdca_init_one(struct dio_dev *d,
- const struct dio_device_id *ent)
-{
- struct uart_port port;
- int line;
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (hp300_uart_scode == d->scode) {
- /* Already got it. */
- return 0;
- }
-#endif
- memset(&port, 0, sizeof(struct uart_port));
-
- /* Memory mapped I/O */
- port.iotype = UPIO_MEM;
- port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
- port.irq = d->ipl;
- port.uartclk = HPDCA_BAUD_BASE * 16;
- port.mapbase = (d->resource.start + UART_OFFSET);
- port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
- port.regshift = 1;
- port.dev = &d->dev;
- line = serial8250_register_port(&port);
-
- if (line < 0) {
- printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
- " irq %d failed\n", d->scode, port.irq);
- return -ENOMEM;
- }
-
- /* Enable board-interrupts */
- out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
- dio_set_drvdata(d, (void *)line);
-
- /* Reset the DCA */
- out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
- udelay(100);
-
- num_ports++;
-
- return 0;
-}
-#endif
-
-static int __init hp300_8250_init(void)
-{
- static int called;
-#ifdef CONFIG_HPAPCI
- int line;
- unsigned long base;
- struct uart_port uport;
- struct hp300_port *port;
- int i;
-#endif
- if (called)
- return -ENODEV;
- called = 1;
-
- if (!MACH_IS_HP300)
- return -ENODEV;
-
-#ifdef CONFIG_HPDCA
- dio_register_driver(&hpdca_driver);
-#endif
-#ifdef CONFIG_HPAPCI
- if (hp300_model < HP_400) {
- if (!num_ports)
- return -ENODEV;
- return 0;
- }
- /* These models have the Frodo chip.
- * Port 0 is reserved for the Apollo Domain keyboard.
- * Port 1 is either the console or the DCA.
- */
- for (i = 1; i < 4; i++) {
- /* Port 1 is the console on a 425e, on other machines it's
- * mapped to DCA.
- */
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (i == 1)
- continue;
-#endif
-
- /* Create new serial device */
- port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
- if (!port)
- return -ENOMEM;
-
- memset(&uport, 0, sizeof(struct uart_port));
-
- base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
-
- /* Memory mapped I/O */
- uport.iotype = UPIO_MEM;
- uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
- | UPF_BOOT_AUTOCONF;
- /* XXX - no interrupt support yet */
- uport.irq = 0;
- uport.uartclk = HPAPCI_BAUD_BASE * 16;
- uport.mapbase = base;
- uport.membase = (char *)(base + DIO_VIRADDRBASE);
- uport.regshift = 2;
-
- line = serial8250_register_port(&uport);
-
- if (line < 0) {
- printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
- " %d irq %d failed\n", i, uport.irq);
- kfree(port);
- continue;
- }
-
- port->line = line;
- port->next = hp300_ports;
- hp300_ports = port;
-
- num_ports++;
- }
-#endif
-
- /* Any boards found? */
- if (!num_ports)
- return -ENODEV;
-
- return 0;
-}
-
-#ifdef CONFIG_HPDCA
-static void __devexit hpdca_remove_one(struct dio_dev *d)
-{
- int line;
-
- line = (int) dio_get_drvdata(d);
- if (d->resource.start) {
- /* Disable board-interrupts */
- out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
- }
- serial8250_unregister_port(line);
-}
-#endif
-
-static void __exit hp300_8250_exit(void)
-{
-#ifdef CONFIG_HPAPCI
- struct hp300_port *port, *to_free;
-
- for (port = hp300_ports; port; ) {
- serial8250_unregister_port(port->line);
- to_free = port;
- port = port->next;
- kfree(to_free);
- }
-
- hp300_ports = NULL;
-#endif
-#ifdef CONFIG_HPDCA
- dio_unregister_driver(&hpdca_driver);
-#endif
-}
-
-module_init(hp300_8250_init);
-module_exit(hp300_8250_exit);
-MODULE_DESCRIPTION("HP DCA/APCI serial driver");
-MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_hub6.c b/drivers/serial/8250_hub6.c
deleted file mode 100644
index 7609150e7d5e..000000000000
--- a/drivers/serial/8250_hub6.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * linux/drivers/serial/8250_hub6.c
- *
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define HUB6(card,port) \
- { \
- .iobase = 0x302, \
- .irq = 3, \
- .uartclk = 1843200, \
- .iotype = UPIO_HUB6, \
- .flags = UPF_BOOT_AUTOCONF, \
- .hub6 = (card) << 6 | (port) << 3 | 1, \
- }
-
-static struct plat_serial8250_port hub6_data[] = {
- HUB6(0, 0),
- HUB6(0, 1),
- HUB6(0, 2),
- HUB6(0, 3),
- HUB6(0, 4),
- HUB6(0, 5),
- HUB6(1, 0),
- HUB6(1, 1),
- HUB6(1, 2),
- HUB6(1, 3),
- HUB6(1, 4),
- HUB6(1, 5),
- { },
-};
-
-static struct platform_device hub6_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_HUB6,
- .dev = {
- .platform_data = hub6_data,
- },
-};
-
-static int __init hub6_init(void)
-{
- return platform_device_register(&hub6_device);
-}
-
-module_init(hub6_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Hub6 cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_mca.c b/drivers/serial/8250_mca.c
deleted file mode 100644
index d10be944ad44..000000000000
--- a/drivers/serial/8250_mca.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * linux/drivers/serial/8250_mca.c
- *
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mca.h>
-#include <linux/serial_8250.h>
-
-/*
- * FIXME: Should we be doing AUTO_IRQ here?
- */
-#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-#define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ
-#else
-#define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
-#endif
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = MCA_FLAGS, \
- }
-
-static struct plat_serial8250_port mca_data[] = {
- PORT(0x3220, 3),
- PORT(0x3228, 3),
- PORT(0x4220, 3),
- PORT(0x4228, 3),
- PORT(0x5220, 3),
- PORT(0x5228, 3),
- { },
-};
-
-static struct platform_device mca_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_MCA,
- .dev = {
- .platform_data = mca_data,
- },
-};
-
-static int __init mca_init(void)
-{
- if (!MCA_bus)
- return -ENODEV;
- return platform_device_register(&mca_device);
-}
-
-module_init(mca_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for MCA ports");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
deleted file mode 100644
index 8b8930f700b5..000000000000
--- a/drivers/serial/8250_pci.c
+++ /dev/null
@@ -1,3850 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2001 Russell King, All Rights Reserved.
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/8250_pci.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-#undef SERIAL_DEBUG_PCI
-
-/*
- * init function returns:
- * > 0 - number of ports
- * = 0 - use board->num_ports
- * < 0 - error
- */
-struct pci_serial_quirk {
- u32 vendor;
- u32 device;
- u32 subvendor;
- u32 subdevice;
- int (*init)(struct pci_dev *dev);
- int (*setup)(struct serial_private *,
- const struct pciserial_board *,
- struct uart_port *, int);
- void (*exit)(struct pci_dev *dev);
-};
-
-#define PCI_NUM_BAR_RESOURCES 6
-
-struct serial_private {
- struct pci_dev *dev;
- unsigned int nr;
- void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES];
- struct pci_serial_quirk *quirk;
- int line[0];
-};
-
-static void moan_device(const char *str, struct pci_dev *dev)
-{
- printk(KERN_WARNING
- "%s: %s\n"
- "Please send the output of lspci -vv, this\n"
- "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
- "manufacturer and name of serial board or\n"
- "modem board to rmk+serial@arm.linux.org.uk.\n",
- pci_name(dev), str, dev->vendor, dev->device,
- dev->subsystem_vendor, dev->subsystem_device);
-}
-
-static int
-setup_port(struct serial_private *priv, struct uart_port *port,
- int bar, int offset, int regshift)
-{
- struct pci_dev *dev = priv->dev;
- unsigned long base, len;
-
- if (bar >= PCI_NUM_BAR_RESOURCES)
- return -EINVAL;
-
- base = pci_resource_start(dev, bar);
-
- if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
- len = pci_resource_len(dev, bar);
-
- if (!priv->remapped_bar[bar])
- priv->remapped_bar[bar] = ioremap_nocache(base, len);
- if (!priv->remapped_bar[bar])
- return -ENOMEM;
-
- port->iotype = UPIO_MEM;
- port->iobase = 0;
- port->mapbase = base + offset;
- port->membase = priv->remapped_bar[bar] + offset;
- port->regshift = regshift;
- } else {
- port->iotype = UPIO_PORT;
- port->iobase = base + offset;
- port->mapbase = 0;
- port->membase = NULL;
- port->regshift = 0;
- }
- return 0;
-}
-
-/*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
-static int addidata_apci7800_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar = 0, offset = board->first_offset;
- bar = FL_GET_BASE(board->flags);
-
- if (idx < 2) {
- offset += idx * board->uart_offset;
- } else if ((idx >= 2) && (idx < 4)) {
- bar += 1;
- offset += ((idx - 2) * board->uart_offset);
- } else if ((idx >= 4) && (idx < 6)) {
- bar += 2;
- offset += ((idx - 4) * board->uart_offset);
- } else if (idx >= 6) {
- bar += 3;
- offset += ((idx - 6) * board->uart_offset);
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * AFAVLAB uses a different mixture of BARs and offsets
- * Not that ugly ;) -- HW
- */
-static int
-afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset;
-
- bar = FL_GET_BASE(board->flags);
- if (idx < 4)
- bar += idx;
- else {
- bar = 4;
- offset += (idx - 4) * board->uart_offset;
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * HP's Remote Management Console. The Diva chip came in several
- * different versions. N-class, L2000 and A500 have two Diva chips, each
- * with 3 UARTs (the third UART on the second chip is unused). Superdome
- * and Keystone have one Diva chip with 3 UARTs. Some later machines have
- * one Diva chip, but it has been expanded to 5 UARTs.
- */
-static int pci_hp_diva_init(struct pci_dev *dev)
-{
- int rc = 0;
-
- switch (dev->subsystem_device) {
- case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
- case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
- case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
- case PCI_DEVICE_ID_HP_DIVA_EVEREST:
- rc = 3;
- break;
- case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
- rc = 2;
- break;
- case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
- rc = 4;
- break;
- case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
- case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
- rc = 1;
- break;
- }
-
- return rc;
-}
-
-/*
- * HP's Diva chip puts the 4th/5th serial port further out, and
- * some serial ports are supposed to be hidden on certain models.
- */
-static int
-pci_hp_diva_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int offset = board->first_offset;
- unsigned int bar = FL_GET_BASE(board->flags);
-
- switch (priv->dev->subsystem_device) {
- case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
- if (idx == 3)
- idx++;
- break;
- case PCI_DEVICE_ID_HP_DIVA_EVEREST:
- if (idx > 0)
- idx++;
- if (idx > 2)
- idx++;
- break;
- }
- if (idx > 2)
- offset = 0x18;
-
- offset += idx * board->uart_offset;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * Added for EKF Intel i960 serial boards
- */
-static int pci_inteli960ni_init(struct pci_dev *dev)
-{
- unsigned long oldval;
-
- if (!(dev->subsystem_device & 0x1000))
- return -ENODEV;
-
- /* is firmware started? */
- pci_read_config_dword(dev, 0x44, (void *)&oldval);
- if (oldval == 0x00001000L) { /* RESET value */
- printk(KERN_DEBUG "Local i960 firmware missing");
- return -ENODEV;
- }
- return 0;
-}
-
-/*
- * Some PCI serial cards using the PLX 9050 PCI interface chip require
- * that the card interrupt be explicitly enabled or disabled. This
- * seems to be mainly needed on card using the PLX which also use I/O
- * mapped memory.
- */
-static int pci_plx9050_init(struct pci_dev *dev)
-{
- u8 irq_config;
- void __iomem *p;
-
- if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar 0", dev);
- return 0;
- }
-
- irq_config = 0x41;
- if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
- dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS)
- irq_config = 0x43;
-
- if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
- (dev->device == PCI_DEVICE_ID_PLX_ROMULUS))
- /*
- * As the megawolf cards have the int pins active
- * high, and have 2 UART chips, both ints must be
- * enabled on the 9050. Also, the UARTS are set in
- * 16450 mode by default, so we have to enable the
- * 16C950 'enhanced' mode so that we can use the
- * deep FIFOs
- */
- irq_config = 0x5b;
- /*
- * enable/disable interrupts
- */
- p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
- if (p == NULL)
- return -ENOMEM;
- writel(irq_config, p + 0x4c);
-
- /*
- * Read the register back to ensure that it took effect.
- */
- readl(p + 0x4c);
- iounmap(p);
-
- return 0;
-}
-
-static void __devexit pci_plx9050_exit(struct pci_dev *dev)
-{
- u8 __iomem *p;
-
- if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0)
- return;
-
- /*
- * disable interrupts
- */
- p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
- if (p != NULL) {
- writel(0, p + 0x4c);
-
- /*
- * Read the register back to ensure that it took effect.
- */
- readl(p + 0x4c);
- iounmap(p);
- }
-}
-
-#define NI8420_INT_ENABLE_REG 0x38
-#define NI8420_INT_ENABLE_BIT 0x2000
-
-static void __devexit pci_ni8420_exit(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return;
-
- /* Disable the CPU Interrupt */
- writel(readl(p + NI8420_INT_ENABLE_REG) & ~(NI8420_INT_ENABLE_BIT),
- p + NI8420_INT_ENABLE_REG);
- iounmap(p);
-}
-
-
-/* MITE registers */
-#define MITE_IOWBSR1 0xc4
-#define MITE_IOWCR1 0xf4
-#define MITE_LCIMR1 0x08
-#define MITE_LCIMR2 0x10
-
-#define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
-
-static void __devexit pci_ni8430_exit(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return;
-
- /* Disable the CPU Interrupt */
- writel(MITE_LCIMR2_CLR_CPU_IE, p + MITE_LCIMR2);
- iounmap(p);
-}
-
-/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
-static int
-sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset;
-
- bar = 0;
-
- if (idx < 4) {
- /* first four channels map to 0, 0x100, 0x200, 0x300 */
- offset += idx * board->uart_offset;
- } else if (idx < 8) {
- /* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */
- offset += idx * board->uart_offset + 0xC00;
- } else /* we have only 8 ports on PMC-OCTALPRO */
- return 1;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
-* This does initialization for PMC OCTALPRO cards:
-* maps the device memory, resets the UARTs (needed, bc
-* if the module is removed and inserted again, the card
-* is in the sleep mode) and enables global interrupt.
-*/
-
-/* global control register offset for SBS PMC-OctalPro */
-#define OCT_REG_CR_OFF 0x500
-
-static int sbs_init(struct pci_dev *dev)
-{
- u8 __iomem *p;
-
- p = pci_ioremap_bar(dev, 0);
-
- if (p == NULL)
- return -ENOMEM;
- /* Set bit-4 Control Register (UART RESET) in to reset the uarts */
- writeb(0x10, p + OCT_REG_CR_OFF);
- udelay(50);
- writeb(0x0, p + OCT_REG_CR_OFF);
-
- /* Set bit-2 (INTENABLE) of Control Register */
- writeb(0x4, p + OCT_REG_CR_OFF);
- iounmap(p);
-
- return 0;
-}
-
-/*
- * Disables the global interrupt of PMC-OctalPro
- */
-
-static void __devexit sbs_exit(struct pci_dev *dev)
-{
- u8 __iomem *p;
-
- p = pci_ioremap_bar(dev, 0);
- /* FIXME: What if resource_len < OCT_REG_CR_OFF */
- if (p != NULL)
- writeb(0, p + OCT_REG_CR_OFF);
- iounmap(p);
-}
-
-/*
- * SIIG serial cards have an PCI interface chip which also controls
- * the UART clocking frequency. Each UART can be clocked independently
- * (except cards equiped with 4 UARTs) and initial clocking settings
- * are stored in the EEPROM chip. It can cause problems because this
- * version of serial driver doesn't support differently clocked UART's
- * on single PCI card. To prevent this, initialization functions set
- * high frequency clocking for all UART's on given card. It is safe (I
- * hope) because it doesn't touch EEPROM settings to prevent conflicts
- * with other OSes (like M$ DOS).
- *
- * SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
- *
- * There is two family of SIIG serial cards with different PCI
- * interface chip and different configuration methods:
- * - 10x cards have control registers in IO and/or memory space;
- * - 20x cards have control registers in standard PCI configuration space.
- *
- * Note: all 10x cards have PCI device ids 0x10..
- * all 20x cards have PCI device ids 0x20..
- *
- * There are also Quartet Serial cards which use Oxford Semiconductor
- * 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
- *
- * Note: some SIIG cards are probed by the parport_serial object.
- */
-
-#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
-#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
-
-static int pci_siig10x_init(struct pci_dev *dev)
-{
- u16 data;
- void __iomem *p;
-
- switch (dev->device & 0xfff8) {
- case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
- data = 0xffdf;
- break;
- case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
- data = 0xf7ff;
- break;
- default: /* 1S1P, 4S */
- data = 0xfffb;
- break;
- }
-
- p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
- if (p == NULL)
- return -ENOMEM;
-
- writew(readw(p + 0x28) & data, p + 0x28);
- readw(p + 0x28);
- iounmap(p);
- return 0;
-}
-
-#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
-#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
-
-static int pci_siig20x_init(struct pci_dev *dev)
-{
- u8 data;
-
- /* Change clock frequency for the first UART. */
- pci_read_config_byte(dev, 0x6f, &data);
- pci_write_config_byte(dev, 0x6f, data & 0xef);
-
- /* If this card has 2 UART, we have to do the same with second UART. */
- if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
- ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
- pci_read_config_byte(dev, 0x73, &data);
- pci_write_config_byte(dev, 0x73, data & 0xef);
- }
- return 0;
-}
-
-static int pci_siig_init(struct pci_dev *dev)
-{
- unsigned int type = dev->device & 0xff00;
-
- if (type == 0x1000)
- return pci_siig10x_init(dev);
- else if (type == 0x2000)
- return pci_siig20x_init(dev);
-
- moan_device("Unknown SIIG card", dev);
- return -ENODEV;
-}
-
-static int pci_siig_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
-
- if (idx > 3) {
- bar = 4;
- offset = (idx - 4) * 8;
- }
-
- return setup_port(priv, port, bar, offset, 0);
-}
-
-/*
- * Timedia has an explosion of boards, and to avoid the PCI table from
- * growing *huge*, we use this function to collapse some 70 entries
- * in the PCI table into one, for sanity's and compactness's sake.
- */
-static const unsigned short timedia_single_port[] = {
- 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
-};
-
-static const unsigned short timedia_dual_port[] = {
- 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
- 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
- 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
- 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
- 0xD079, 0
-};
-
-static const unsigned short timedia_quad_port[] = {
- 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
- 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
- 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
- 0xB157, 0
-};
-
-static const unsigned short timedia_eight_port[] = {
- 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
- 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
-};
-
-static const struct timedia_struct {
- int num;
- const unsigned short *ids;
-} timedia_data[] = {
- { 1, timedia_single_port },
- { 2, timedia_dual_port },
- { 4, timedia_quad_port },
- { 8, timedia_eight_port }
-};
-
-static int pci_timedia_init(struct pci_dev *dev)
-{
- const unsigned short *ids;
- int i, j;
-
- for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
- ids = timedia_data[i].ids;
- for (j = 0; ids[j]; j++)
- if (dev->subsystem_device == ids[j])
- return timedia_data[i].num;
- }
- return 0;
-}
-
-/*
- * Timedia/SUNIX uses a mixture of BARs and offsets
- * Ugh, this is ugly as all hell --- TYT
- */
-static int
-pci_timedia_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar = 0, offset = board->first_offset;
-
- switch (idx) {
- case 0:
- bar = 0;
- break;
- case 1:
- offset = board->uart_offset;
- bar = 0;
- break;
- case 2:
- bar = 1;
- break;
- case 3:
- offset = board->uart_offset;
- /* FALLTHROUGH */
- case 4: /* BAR 2 */
- case 5: /* BAR 3 */
- case 6: /* BAR 4 */
- case 7: /* BAR 5 */
- bar = idx - 2;
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * Some Titan cards are also a little weird
- */
-static int
-titan_400l_800l_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset;
-
- switch (idx) {
- case 0:
- bar = 1;
- break;
- case 1:
- bar = 2;
- break;
- default:
- bar = 4;
- offset = (idx - 2) * board->uart_offset;
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int pci_xircom_init(struct pci_dev *dev)
-{
- msleep(100);
- return 0;
-}
-
-static int pci_ni8420_init(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return 0;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return -ENOMEM;
-
- /* Enable CPU Interrupt */
- writel(readl(p + NI8420_INT_ENABLE_REG) | NI8420_INT_ENABLE_BIT,
- p + NI8420_INT_ENABLE_REG);
-
- iounmap(p);
- return 0;
-}
-
-#define MITE_IOWBSR1_WSIZE 0xa
-#define MITE_IOWBSR1_WIN_OFFSET 0x800
-#define MITE_IOWBSR1_WENAB (1 << 7)
-#define MITE_LCIMR1_IO_IE_0 (1 << 24)
-#define MITE_LCIMR2_SET_CPU_IE (1 << 31)
-#define MITE_IOWCR1_RAMSEL_MASK 0xfffffffe
-
-static int pci_ni8430_init(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- u32 device_window;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return 0;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return -ENOMEM;
-
- /* Set device window address and size in BAR0 */
- device_window = ((base + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00)
- | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE;
- writel(device_window, p + MITE_IOWBSR1);
-
- /* Set window access to go to RAMSEL IO address space */
- writel((readl(p + MITE_IOWCR1) & MITE_IOWCR1_RAMSEL_MASK),
- p + MITE_IOWCR1);
-
- /* Enable IO Bus Interrupt 0 */
- writel(MITE_LCIMR1_IO_IE_0, p + MITE_LCIMR1);
-
- /* Enable CPU Interrupt */
- writel(MITE_LCIMR2_SET_CPU_IE, p + MITE_LCIMR2);
-
- iounmap(p);
- return 0;
-}
-
-/* UART Port Control Register */
-#define NI8430_PORTCON 0x0f
-#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
-
-static int
-pci_ni8430_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar, offset = board->first_offset;
-
- if (idx >= board->num_ports)
- return 1;
-
- bar = FL_GET_BASE(board->flags);
- offset += idx * board->uart_offset;
-
- base = pci_resource_start(priv->dev, bar);
- len = pci_resource_len(priv->dev, bar);
- p = ioremap_nocache(base, len);
-
- /* enable the transciever */
- writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
- p + offset + NI8430_PORTCON);
-
- iounmap(p);
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-
-static int pci_netmos_init(struct pci_dev *dev)
-{
- /* subdevice 0x00PS means <P> parallel, <S> serial */
- unsigned int num_serial = dev->subsystem_device & 0xf;
-
- if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
- (dev->device == PCI_DEVICE_ID_NETMOS_9865))
- return 0;
- if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
- dev->subsystem_device == 0x0299)
- return 0;
-
- if (num_serial == 0)
- return -ENODEV;
- return num_serial;
-}
-
-/*
- * These chips are available with optionally one parallel port and up to
- * two serial ports. Unfortunately they all have the same product id.
- *
- * Basic configuration is done over a region of 32 I/O ports. The base
- * ioport is called INTA or INTC, depending on docs/other drivers.
- *
- * The region of the 32 I/O ports is configured in POSIO0R...
- */
-
-/* registers */
-#define ITE_887x_MISCR 0x9c
-#define ITE_887x_INTCBAR 0x78
-#define ITE_887x_UARTBAR 0x7c
-#define ITE_887x_PS0BAR 0x10
-#define ITE_887x_POSIO0 0x60
-
-/* I/O space size */
-#define ITE_887x_IOSIZE 32
-/* I/O space size (bits 26-24; 8 bytes = 011b) */
-#define ITE_887x_POSIO_IOSIZE_8 (3 << 24)
-/* I/O space size (bits 26-24; 32 bytes = 101b) */
-#define ITE_887x_POSIO_IOSIZE_32 (5 << 24)
-/* Decoding speed (1 = slow, 2 = medium, 3 = fast) */
-#define ITE_887x_POSIO_SPEED (3 << 29)
-/* enable IO_Space bit */
-#define ITE_887x_POSIO_ENABLE (1 << 31)
-
-static int pci_ite887x_init(struct pci_dev *dev)
-{
- /* inta_addr are the configuration addresses of the ITE */
- static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
- 0x200, 0x280, 0 };
- int ret, i, type;
- struct resource *iobase = NULL;
- u32 miscr, uartbar, ioport;
-
- /* search for the base-ioport */
- i = 0;
- while (inta_addr[i] && iobase == NULL) {
- iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
- "ite887x");
- if (iobase != NULL) {
- /* write POSIO0R - speed | size | ioport */
- pci_write_config_dword(dev, ITE_887x_POSIO0,
- ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
- ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]);
- /* write INTCBAR - ioport */
- pci_write_config_dword(dev, ITE_887x_INTCBAR,
- inta_addr[i]);
- ret = inb(inta_addr[i]);
- if (ret != 0xff) {
- /* ioport connected */
- break;
- }
- release_region(iobase->start, ITE_887x_IOSIZE);
- iobase = NULL;
- }
- i++;
- }
-
- if (!inta_addr[i]) {
- printk(KERN_ERR "ite887x: could not find iobase\n");
- return -ENODEV;
- }
-
- /* start of undocumented type checking (see parport_pc.c) */
- type = inb(iobase->start + 0x18) & 0x0f;
-
- switch (type) {
- case 0x2: /* ITE8871 (1P) */
- case 0xa: /* ITE8875 (1P) */
- ret = 0;
- break;
- case 0xe: /* ITE8872 (2S1P) */
- ret = 2;
- break;
- case 0x6: /* ITE8873 (1S) */
- ret = 1;
- break;
- case 0x8: /* ITE8874 (2S) */
- ret = 2;
- break;
- default:
- moan_device("Unknown ITE887x", dev);
- ret = -ENODEV;
- }
-
- /* configure all serial ports */
- for (i = 0; i < ret; i++) {
- /* read the I/O port from the device */
- pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)),
- &ioport);
- ioport &= 0x0000FF00; /* the actual base address */
- pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)),
- ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
- ITE_887x_POSIO_IOSIZE_8 | ioport);
-
- /* write the ioport to the UARTBAR */
- pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar);
- uartbar &= ~(0xffff << (16 * i)); /* clear half the reg */
- uartbar |= (ioport << (16 * i)); /* set the ioport */
- pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar);
-
- /* get current config */
- pci_read_config_dword(dev, ITE_887x_MISCR, &miscr);
- /* disable interrupts (UARTx_Routing[3:0]) */
- miscr &= ~(0xf << (12 - 4 * i));
- /* activate the UART (UARTx_En) */
- miscr |= 1 << (23 - i);
- /* write new config with activated UART */
- pci_write_config_dword(dev, ITE_887x_MISCR, miscr);
- }
-
- if (ret <= 0) {
- /* the device has no UARTs if we get here */
- release_region(iobase->start, ITE_887x_IOSIZE);
- }
-
- return ret;
-}
-
-static void __devexit pci_ite887x_exit(struct pci_dev *dev)
-{
- u32 ioport;
- /* the ioport is bit 0-15 in POSIO0R */
- pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);
- ioport &= 0xffff;
- release_region(ioport, ITE_887x_IOSIZE);
-}
-
-/*
- * Oxford Semiconductor Inc.
- * Check that device is part of the Tornado range of devices, then determine
- * the number of ports available on the device.
- */
-static int pci_oxsemi_tornado_init(struct pci_dev *dev)
-{
- u8 __iomem *p;
- unsigned long deviceID;
- unsigned int number_uarts = 0;
-
- /* OxSemi Tornado devices are all 0xCxxx */
- if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
- (dev->device & 0xF000) != 0xC000)
- return 0;
-
- p = pci_iomap(dev, 0, 5);
- if (p == NULL)
- return -ENOMEM;
-
- deviceID = ioread32(p);
- /* Tornado device */
- if (deviceID == 0x07000200) {
- number_uarts = ioread8(p + 4);
- printk(KERN_DEBUG
- "%d ports detected on Oxford PCI Express device\n",
- number_uarts);
- }
- pci_iounmap(dev, p);
- return number_uarts;
-}
-
-static int
-pci_default_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset, maxnr;
-
- bar = FL_GET_BASE(board->flags);
- if (board->flags & FL_BASE_BARS)
- bar += idx;
- else
- offset += idx * board->uart_offset;
-
- maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
- (board->reg_shift + 3);
-
- if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
- return 1;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int
-ce4100_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- int ret;
-
- ret = setup_port(priv, port, 0, 0, board->reg_shift);
- port->iotype = UPIO_MEM32;
- port->type = PORT_XSCALE;
- port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
- port->regshift = 2;
-
- return ret;
-}
-
-static int skip_tx_en_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- port->flags |= UPF_NO_TXEN_TEST;
- printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
- "[%04x:%04x] subsystem [%04x:%04x]\n",
- priv->dev->vendor,
- priv->dev->device,
- priv->dev->subsystem_vendor,
- priv->dev->subsystem_device);
-
- return pci_default_setup(priv, board, port, idx);
-}
-
-/* This should be in linux/pci_ids.h */
-#define PCI_VENDOR_ID_SBSMODULARIO 0x124B
-#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
-#define PCI_DEVICE_ID_OCTPRO 0x0001
-#define PCI_SUBDEVICE_ID_OCTPRO232 0x0108
-#define PCI_SUBDEVICE_ID_OCTPRO422 0x0208
-#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
-#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
-#define PCI_VENDOR_ID_ADVANTECH 0x13fe
-#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
-#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
-#define PCI_DEVICE_ID_TITAN_200I 0x8028
-#define PCI_DEVICE_ID_TITAN_400I 0x8048
-#define PCI_DEVICE_ID_TITAN_800I 0x8088
-#define PCI_DEVICE_ID_TITAN_800EH 0xA007
-#define PCI_DEVICE_ID_TITAN_800EHB 0xA008
-#define PCI_DEVICE_ID_TITAN_400EH 0xA009
-#define PCI_DEVICE_ID_TITAN_100E 0xA010
-#define PCI_DEVICE_ID_TITAN_200E 0xA012
-#define PCI_DEVICE_ID_TITAN_400E 0xA013
-#define PCI_DEVICE_ID_TITAN_800E 0xA014
-#define PCI_DEVICE_ID_TITAN_200EI 0xA016
-#define PCI_DEVICE_ID_TITAN_200EISI 0xA017
-#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538
-
-/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
-#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
-
-/*
- * Master list of serial port init/setup/exit quirks.
- * This does not describe the general nature of the port.
- * (ie, baud base, number and location of ports, etc)
- *
- * This list is ordered alphabetically by vendor then device.
- * Specific entries must come before more generic entries.
- */
-static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
- /*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
- {
- .vendor = PCI_VENDOR_ID_ADDIDATA_OLD,
- .device = PCI_DEVICE_ID_ADDIDATA_APCI7800,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = addidata_apci7800_setup,
- },
- /*
- * AFAVLAB cards - these may be called via parport_serial
- * It is not clear whether this applies to all products.
- */
- {
- .vendor = PCI_VENDOR_ID_AFAVLAB,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = afavlab_setup,
- },
- /*
- * HP Diva
- */
- {
- .vendor = PCI_VENDOR_ID_HP,
- .device = PCI_DEVICE_ID_HP_DIVA,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_hp_diva_init,
- .setup = pci_hp_diva_setup,
- },
- /*
- * Intel
- */
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_80960_RP,
- .subvendor = 0xe4bf,
- .subdevice = PCI_ANY_ID,
- .init = pci_inteli960ni_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_8257X_SOL,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = skip_tx_en_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82573L_SOL,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = skip_tx_en_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82573E_SOL,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = skip_tx_en_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_CE4100_UART,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = ce4100_serial_setup,
- },
- /*
- * ITE
- */
- {
- .vendor = PCI_VENDOR_ID_ITE,
- .device = PCI_DEVICE_ID_ITE_8872,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ite887x_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ite887x_exit),
- },
- /*
- * National Instruments
- */
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI23216,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2328,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2324,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2322,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2324I,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2322I,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_23216,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_2328,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_2324,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_2322,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8422_2324,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8422_2322,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8430_init,
- .setup = pci_ni8430_setup,
- .exit = __devexit_p(pci_ni8430_exit),
- },
- /*
- * Panacom
- */
- {
- .vendor = PCI_VENDOR_ID_PANACOM,
- .device = PCI_DEVICE_ID_PANACOM_QUADMODEM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PANACOM,
- .device = PCI_DEVICE_ID_PANACOM_DUALMODEM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- /*
- * PLX
- */
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9030,
- .subvendor = PCI_SUBVENDOR_ID_PERLE,
- .subdevice = PCI_ANY_ID,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9050,
- .subvendor = PCI_SUBVENDOR_ID_EXSYS,
- .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9050,
- .subvendor = PCI_SUBVENDOR_ID_KEYSPAN,
- .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9050,
- .subvendor = PCI_VENDOR_ID_PLX,
- .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_ROMULUS,
- .subvendor = PCI_VENDOR_ID_PLX,
- .subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- /*
- * SBS Technologies, Inc., PMC-OCTALPRO 232
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_OCTPRO232,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SBS Technologies, Inc., PMC-OCTALPRO 422
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_OCTPRO422,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SBS Technologies, Inc., P-Octal 232
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_POCTAL232,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SBS Technologies, Inc., P-Octal 422
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_POCTAL422,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SIIG cards - these may be called via parport_serial
- */
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig_init,
- .setup = pci_siig_setup,
- },
- /*
- * Titan cards
- */
- {
- .vendor = PCI_VENDOR_ID_TITAN,
- .device = PCI_DEVICE_ID_TITAN_400L,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = titan_400l_800l_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_TITAN,
- .device = PCI_DEVICE_ID_TITAN_800L,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = titan_400l_800l_setup,
- },
- /*
- * Timedia cards
- */
- {
- .vendor = PCI_VENDOR_ID_TIMEDIA,
- .device = PCI_DEVICE_ID_TIMEDIA_1889,
- .subvendor = PCI_VENDOR_ID_TIMEDIA,
- .subdevice = PCI_ANY_ID,
- .init = pci_timedia_init,
- .setup = pci_timedia_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_TIMEDIA,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_timedia_setup,
- },
- /*
- * Xircom cards
- */
- {
- .vendor = PCI_VENDOR_ID_XIRCOM,
- .device = PCI_DEVICE_ID_XIRCOM_X3201_MDM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_xircom_init,
- .setup = pci_default_setup,
- },
- /*
- * Netmos cards - these may be called via parport_serial
- */
- {
- .vendor = PCI_VENDOR_ID_NETMOS,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_netmos_init,
- .setup = pci_default_setup,
- },
- /*
- * For Oxford Semiconductor and Mainpine
- */
- {
- .vendor = PCI_VENDOR_ID_OXSEMI,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_MAINPINE,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
- },
- /*
- * Default "match everything" terminator entry
- */
- {
- .vendor = PCI_ANY_ID,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_default_setup,
- }
-};
-
-static inline int quirk_id_matches(u32 quirk_id, u32 dev_id)
-{
- return quirk_id == PCI_ANY_ID || quirk_id == dev_id;
-}
-
-static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
-{
- struct pci_serial_quirk *quirk;
-
- for (quirk = pci_serial_quirks; ; quirk++)
- if (quirk_id_matches(quirk->vendor, dev->vendor) &&
- quirk_id_matches(quirk->device, dev->device) &&
- quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
- quirk_id_matches(quirk->subdevice, dev->subsystem_device))
- break;
- return quirk;
-}
-
-static inline int get_pci_irq(struct pci_dev *dev,
- const struct pciserial_board *board)
-{
- if (board->flags & FL_NOIRQ)
- return 0;
- else
- return dev->irq;
-}
-
-/*
- * This is the configuration table for all of the PCI serial boards
- * which we support. It is directly indexed by the pci_board_num_t enum
- * value, which is encoded in the pci_device_id PCI probe table's
- * driver_data member.
- *
- * The makeup of these names are:
- * pbn_bn{_bt}_n_baud{_offsetinhex}
- *
- * bn = PCI BAR number
- * bt = Index using PCI BARs
- * n = number of serial ports
- * baud = baud rate
- * offsetinhex = offset for each sequential port (in hex)
- *
- * This table is sorted by (in order): bn, bt, baud, offsetindex, n.
- *
- * Please note: in theory if n = 1, _bt infix should make no difference.
- * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
- */
-enum pci_board_num_t {
- pbn_default = 0,
-
- pbn_b0_1_115200,
- pbn_b0_2_115200,
- pbn_b0_4_115200,
- pbn_b0_5_115200,
- pbn_b0_8_115200,
-
- pbn_b0_1_921600,
- pbn_b0_2_921600,
- pbn_b0_4_921600,
-
- pbn_b0_2_1130000,
-
- pbn_b0_4_1152000,
-
- pbn_b0_2_1843200,
- pbn_b0_4_1843200,
-
- pbn_b0_2_1843200_200,
- pbn_b0_4_1843200_200,
- pbn_b0_8_1843200_200,
-
- pbn_b0_1_4000000,
-
- pbn_b0_bt_1_115200,
- pbn_b0_bt_2_115200,
- pbn_b0_bt_4_115200,
- pbn_b0_bt_8_115200,
-
- pbn_b0_bt_1_460800,
- pbn_b0_bt_2_460800,
- pbn_b0_bt_4_460800,
-
- pbn_b0_bt_1_921600,
- pbn_b0_bt_2_921600,
- pbn_b0_bt_4_921600,
- pbn_b0_bt_8_921600,
-
- pbn_b1_1_115200,
- pbn_b1_2_115200,
- pbn_b1_4_115200,
- pbn_b1_8_115200,
- pbn_b1_16_115200,
-
- pbn_b1_1_921600,
- pbn_b1_2_921600,
- pbn_b1_4_921600,
- pbn_b1_8_921600,
-
- pbn_b1_2_1250000,
-
- pbn_b1_bt_1_115200,
- pbn_b1_bt_2_115200,
- pbn_b1_bt_4_115200,
-
- pbn_b1_bt_2_921600,
-
- pbn_b1_1_1382400,
- pbn_b1_2_1382400,
- pbn_b1_4_1382400,
- pbn_b1_8_1382400,
-
- pbn_b2_1_115200,
- pbn_b2_2_115200,
- pbn_b2_4_115200,
- pbn_b2_8_115200,
-
- pbn_b2_1_460800,
- pbn_b2_4_460800,
- pbn_b2_8_460800,
- pbn_b2_16_460800,
-
- pbn_b2_1_921600,
- pbn_b2_4_921600,
- pbn_b2_8_921600,
-
- pbn_b2_8_1152000,
-
- pbn_b2_bt_1_115200,
- pbn_b2_bt_2_115200,
- pbn_b2_bt_4_115200,
-
- pbn_b2_bt_2_921600,
- pbn_b2_bt_4_921600,
-
- pbn_b3_2_115200,
- pbn_b3_4_115200,
- pbn_b3_8_115200,
-
- pbn_b4_bt_2_921600,
- pbn_b4_bt_4_921600,
- pbn_b4_bt_8_921600,
-
- /*
- * Board-specific versions.
- */
- pbn_panacom,
- pbn_panacom2,
- pbn_panacom4,
- pbn_exsys_4055,
- pbn_plx_romulus,
- pbn_oxsemi,
- pbn_oxsemi_1_4000000,
- pbn_oxsemi_2_4000000,
- pbn_oxsemi_4_4000000,
- pbn_oxsemi_8_4000000,
- pbn_intel_i960,
- pbn_sgi_ioc3,
- pbn_computone_4,
- pbn_computone_6,
- pbn_computone_8,
- pbn_sbsxrsio,
- pbn_exar_XR17C152,
- pbn_exar_XR17C154,
- pbn_exar_XR17C158,
- pbn_exar_ibm_saturn,
- pbn_pasemi_1682M,
- pbn_ni8430_2,
- pbn_ni8430_4,
- pbn_ni8430_8,
- pbn_ni8430_16,
- pbn_ADDIDATA_PCIe_1_3906250,
- pbn_ADDIDATA_PCIe_2_3906250,
- pbn_ADDIDATA_PCIe_4_3906250,
- pbn_ADDIDATA_PCIe_8_3906250,
- pbn_ce4100_1_115200,
-};
-
-/*
- * uart_offset - the space between channels
- * reg_shift - describes how the UART registers are mapped
- * to PCI memory by the card.
- * For example IER register on SBS, Inc. PMC-OctPro is located at
- * offset 0x10 from the UART base, while UART_IER is defined as 1
- * in include/linux/serial_reg.h,
- * see first lines of serial_in() and serial_out() in 8250.c
-*/
-
-static struct pciserial_board pci_boards[] __devinitdata = {
- [pbn_default] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_1_115200] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_2_115200] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_4_115200] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_5_115200] = {
- .flags = FL_BASE0,
- .num_ports = 5,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_8_115200] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_1_921600] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_2_921600] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_4_921600] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b0_2_1130000] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 1130000,
- .uart_offset = 8,
- },
-
- [pbn_b0_4_1152000] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 1152000,
- .uart_offset = 8,
- },
-
- [pbn_b0_2_1843200] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 1843200,
- .uart_offset = 8,
- },
- [pbn_b0_4_1843200] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 1843200,
- .uart_offset = 8,
- },
-
- [pbn_b0_2_1843200_200] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 1843200,
- .uart_offset = 0x200,
- },
- [pbn_b0_4_1843200_200] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 1843200,
- .uart_offset = 0x200,
- },
- [pbn_b0_8_1843200_200] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 1843200,
- .uart_offset = 0x200,
- },
- [pbn_b0_1_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 4000000,
- .uart_offset = 8,
- },
-
- [pbn_b0_bt_1_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_bt_2_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_bt_4_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_bt_8_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b0_bt_1_460800] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b0_bt_2_460800] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b0_bt_4_460800] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 460800,
- .uart_offset = 8,
- },
-
- [pbn_b0_bt_1_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_bt_2_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_bt_4_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_bt_8_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b1_1_115200] = {
- .flags = FL_BASE1,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_2_115200] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_4_115200] = {
- .flags = FL_BASE1,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_8_115200] = {
- .flags = FL_BASE1,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_16_115200] = {
- .flags = FL_BASE1,
- .num_ports = 16,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b1_1_921600] = {
- .flags = FL_BASE1,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_2_921600] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_4_921600] = {
- .flags = FL_BASE1,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_8_921600] = {
- .flags = FL_BASE1,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_2_1250000] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 1250000,
- .uart_offset = 8,
- },
-
- [pbn_b1_bt_1_115200] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_bt_2_115200] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_bt_4_115200] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b1_bt_2_921600] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b1_1_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 1,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
- [pbn_b1_2_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
- [pbn_b1_4_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 4,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
- [pbn_b1_8_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 8,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
-
- [pbn_b2_1_115200] = {
- .flags = FL_BASE2,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_2_115200] = {
- .flags = FL_BASE2,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_4_115200] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_8_115200] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b2_1_460800] = {
- .flags = FL_BASE2,
- .num_ports = 1,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b2_4_460800] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b2_8_460800] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b2_16_460800] = {
- .flags = FL_BASE2,
- .num_ports = 16,
- .base_baud = 460800,
- .uart_offset = 8,
- },
-
- [pbn_b2_1_921600] = {
- .flags = FL_BASE2,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b2_4_921600] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b2_8_921600] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b2_8_1152000] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 1152000,
- .uart_offset = 8,
- },
-
- [pbn_b2_bt_1_115200] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_bt_2_115200] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_bt_4_115200] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b2_bt_2_921600] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b2_bt_4_921600] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b3_2_115200] = {
- .flags = FL_BASE3,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b3_4_115200] = {
- .flags = FL_BASE3,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b3_8_115200] = {
- .flags = FL_BASE3,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b4_bt_2_921600] = {
- .flags = FL_BASE4,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b4_bt_4_921600] = {
- .flags = FL_BASE4,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b4_bt_8_921600] = {
- .flags = FL_BASE4,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- /*
- * Entries following this are board-specific.
- */
-
- /*
- * Panacom - IOMEM
- */
- [pbn_panacom] = {
- .flags = FL_BASE2,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 0x400,
- .reg_shift = 7,
- },
- [pbn_panacom2] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 0x400,
- .reg_shift = 7,
- },
- [pbn_panacom4] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 0x400,
- .reg_shift = 7,
- },
-
- [pbn_exsys_4055] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- /* I think this entry is broken - the first_offset looks wrong --rmk */
- [pbn_plx_romulus] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8 << 2,
- .reg_shift = 2,
- .first_offset = 0x03,
- },
-
- /*
- * This board uses the size of PCI Base region 0 to
- * signal now many ports are available
- */
- [pbn_oxsemi] = {
- .flags = FL_BASE0|FL_REGION_SZ_CAP,
- .num_ports = 32,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_oxsemi_1_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_oxsemi_2_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_oxsemi_4_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_oxsemi_8_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
-
-
- /*
- * EKF addition for i960 Boards form EKF with serial port.
- * Max 256 ports.
- */
- [pbn_intel_i960] = {
- .flags = FL_BASE0,
- .num_ports = 32,
- .base_baud = 921600,
- .uart_offset = 8 << 2,
- .reg_shift = 2,
- .first_offset = 0x10000,
- },
- [pbn_sgi_ioc3] = {
- .flags = FL_BASE0|FL_NOIRQ,
- .num_ports = 1,
- .base_baud = 458333,
- .uart_offset = 8,
- .reg_shift = 0,
- .first_offset = 0x20178,
- },
-
- /*
- * Computone - uses IOMEM.
- */
- [pbn_computone_4] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 0x40,
- .reg_shift = 2,
- .first_offset = 0x200,
- },
- [pbn_computone_6] = {
- .flags = FL_BASE0,
- .num_ports = 6,
- .base_baud = 921600,
- .uart_offset = 0x40,
- .reg_shift = 2,
- .first_offset = 0x200,
- },
- [pbn_computone_8] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 0x40,
- .reg_shift = 2,
- .first_offset = 0x200,
- },
- [pbn_sbsxrsio] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 460800,
- .uart_offset = 256,
- .reg_shift = 4,
- },
- /*
- * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
- * Only basic 16550A support.
- * XR17C15[24] are not tested, but they should work.
- */
- [pbn_exar_XR17C152] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
- [pbn_exar_XR17C154] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
- [pbn_exar_XR17C158] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
- [pbn_exar_ibm_saturn] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
-
- /*
- * PA Semi PWRficient PA6T-1682M on-chip UART
- */
- [pbn_pasemi_1682M] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 8333333,
- },
- /*
- * National Instruments 843x
- */
- [pbn_ni8430_16] = {
- .flags = FL_BASE0,
- .num_ports = 16,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- [pbn_ni8430_8] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- [pbn_ni8430_4] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- [pbn_ni8430_2] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- /*
- * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
- */
- [pbn_ADDIDATA_PCIe_1_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ADDIDATA_PCIe_2_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ADDIDATA_PCIe_4_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ADDIDATA_PCIe_8_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ce4100_1_115200] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
- .reg_shift = 2,
- },
-};
-
-static const struct pci_device_id softmodem_blacklist[] = {
- { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
- { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
- { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
-};
-
-/*
- * Given a complete unknown PCI device, try to use some heuristics to
- * guess what the configuration might be, based on the pitiful PCI
- * serial specs. Returns 0 on success, 1 on failure.
- */
-static int __devinit
-serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
-{
- const struct pci_device_id *blacklist;
- int num_iomem, num_port, first_port = -1, i;
-
- /*
- * If it is not a communications device or the programming
- * interface is greater than 6, give up.
- *
- * (Should we try to make guesses for multiport serial devices
- * later?)
- */
- if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
- ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
- (dev->class & 0xff) > 6)
- return -ENODEV;
-
- /*
- * Do not access blacklisted devices that are known not to
- * feature serial ports.
- */
- for (blacklist = softmodem_blacklist;
- blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
- blacklist++) {
- if (dev->vendor == blacklist->vendor &&
- dev->device == blacklist->device)
- return -ENODEV;
- }
-
- num_iomem = num_port = 0;
- for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
- if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
- num_port++;
- if (first_port == -1)
- first_port = i;
- }
- if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
- num_iomem++;
- }
-
- /*
- * If there is 1 or 0 iomem regions, and exactly one port,
- * use it. We guess the number of ports based on the IO
- * region size.
- */
- if (num_iomem <= 1 && num_port == 1) {
- board->flags = first_port;
- board->num_ports = pci_resource_len(dev, first_port) / 8;
- return 0;
- }
-
- /*
- * Now guess if we've got a board which indexes by BARs.
- * Each IO BAR should be 8 bytes, and they should follow
- * consecutively.
- */
- first_port = -1;
- num_port = 0;
- for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
- if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
- pci_resource_len(dev, i) == 8 &&
- (first_port == -1 || (first_port + num_port) == i)) {
- num_port++;
- if (first_port == -1)
- first_port = i;
- }
- }
-
- if (num_port > 1) {
- board->flags = first_port | FL_BASE_BARS;
- board->num_ports = num_port;
- return 0;
- }
-
- return -ENODEV;
-}
-
-static inline int
-serial_pci_matches(const struct pciserial_board *board,
- const struct pciserial_board *guessed)
-{
- return
- board->num_ports == guessed->num_ports &&
- board->base_baud == guessed->base_baud &&
- board->uart_offset == guessed->uart_offset &&
- board->reg_shift == guessed->reg_shift &&
- board->first_offset == guessed->first_offset;
-}
-
-struct serial_private *
-pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
-{
- struct uart_port serial_port;
- struct serial_private *priv;
- struct pci_serial_quirk *quirk;
- int rc, nr_ports, i;
-
- nr_ports = board->num_ports;
-
- /*
- * Find an init and setup quirks.
- */
- quirk = find_quirk(dev);
-
- /*
- * Run the new-style initialization function.
- * The initialization function returns:
- * <0 - error
- * 0 - use board->num_ports
- * >0 - number of ports
- */
- if (quirk->init) {
- rc = quirk->init(dev);
- if (rc < 0) {
- priv = ERR_PTR(rc);
- goto err_out;
- }
- if (rc)
- nr_ports = rc;
- }
-
- priv = kzalloc(sizeof(struct serial_private) +
- sizeof(unsigned int) * nr_ports,
- GFP_KERNEL);
- if (!priv) {
- priv = ERR_PTR(-ENOMEM);
- goto err_deinit;
- }
-
- priv->dev = dev;
- priv->quirk = quirk;
-
- memset(&serial_port, 0, sizeof(struct uart_port));
- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- serial_port.uartclk = board->base_baud * 16;
- serial_port.irq = get_pci_irq(dev, board);
- serial_port.dev = &dev->dev;
-
- for (i = 0; i < nr_ports; i++) {
- if (quirk->setup(priv, board, &serial_port, i))
- break;
-
-#ifdef SERIAL_DEBUG_PCI
- printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
- serial_port.iobase, serial_port.irq, serial_port.iotype);
-#endif
-
- priv->line[i] = serial8250_register_port(&serial_port);
- if (priv->line[i] < 0) {
- printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
- break;
- }
- }
- priv->nr = i;
- return priv;
-
-err_deinit:
- if (quirk->exit)
- quirk->exit(dev);
-err_out:
- return priv;
-}
-EXPORT_SYMBOL_GPL(pciserial_init_ports);
-
-void pciserial_remove_ports(struct serial_private *priv)
-{
- struct pci_serial_quirk *quirk;
- int i;
-
- for (i = 0; i < priv->nr; i++)
- serial8250_unregister_port(priv->line[i]);
-
- for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
- if (priv->remapped_bar[i])
- iounmap(priv->remapped_bar[i]);
- priv->remapped_bar[i] = NULL;
- }
-
- /*
- * Find the exit quirks.
- */
- quirk = find_quirk(priv->dev);
- if (quirk->exit)
- quirk->exit(priv->dev);
-
- kfree(priv);
-}
-EXPORT_SYMBOL_GPL(pciserial_remove_ports);
-
-void pciserial_suspend_ports(struct serial_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->nr; i++)
- if (priv->line[i] >= 0)
- serial8250_suspend_port(priv->line[i]);
-}
-EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
-
-void pciserial_resume_ports(struct serial_private *priv)
-{
- int i;
-
- /*
- * Ensure that the board is correctly configured.
- */
- if (priv->quirk->init)
- priv->quirk->init(priv->dev);
-
- for (i = 0; i < priv->nr; i++)
- if (priv->line[i] >= 0)
- serial8250_resume_port(priv->line[i]);
-}
-EXPORT_SYMBOL_GPL(pciserial_resume_ports);
-
-/*
- * Probe one serial board. Unfortunately, there is no rhyme nor reason
- * to the arrangement of serial ports on a PCI card.
- */
-static int __devinit
-pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
-{
- struct serial_private *priv;
- const struct pciserial_board *board;
- struct pciserial_board tmp;
- int rc;
-
- if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
- printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
- ent->driver_data);
- return -EINVAL;
- }
-
- board = &pci_boards[ent->driver_data];
-
- rc = pci_enable_device(dev);
- if (rc)
- return rc;
-
- if (ent->driver_data == pbn_default) {
- /*
- * Use a copy of the pci_board entry for this;
- * avoid changing entries in the table.
- */
- memcpy(&tmp, board, sizeof(struct pciserial_board));
- board = &tmp;
-
- /*
- * We matched one of our class entries. Try to
- * determine the parameters of this board.
- */
- rc = serial_pci_guess_board(dev, &tmp);
- if (rc)
- goto disable;
- } else {
- /*
- * We matched an explicit entry. If we are able to
- * detect this boards settings with our heuristic,
- * then we no longer need this entry.
- */
- memcpy(&tmp, &pci_boards[pbn_default],
- sizeof(struct pciserial_board));
- rc = serial_pci_guess_board(dev, &tmp);
- if (rc == 0 && serial_pci_matches(board, &tmp))
- moan_device("Redundant entry in serial pci_table.",
- dev);
- }
-
- priv = pciserial_init_ports(dev, board);
- if (!IS_ERR(priv)) {
- pci_set_drvdata(dev, priv);
- return 0;
- }
-
- rc = PTR_ERR(priv);
-
- disable:
- pci_disable_device(dev);
- return rc;
-}
-
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
-{
- struct serial_private *priv = pci_get_drvdata(dev);
-
- pci_set_drvdata(dev, NULL);
-
- pciserial_remove_ports(priv);
-
- pci_disable_device(dev);
-}
-
-#ifdef CONFIG_PM
-static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
-{
- struct serial_private *priv = pci_get_drvdata(dev);
-
- if (priv)
- pciserial_suspend_ports(priv);
-
- pci_save_state(dev);
- pci_set_power_state(dev, pci_choose_state(dev, state));
- return 0;
-}
-
-static int pciserial_resume_one(struct pci_dev *dev)
-{
- int err;
- struct serial_private *priv = pci_get_drvdata(dev);
-
- pci_set_power_state(dev, PCI_D0);
- pci_restore_state(dev);
-
- if (priv) {
- /*
- * The device may have been disabled. Re-enable it.
- */
- err = pci_enable_device(dev);
- /* FIXME: We cannot simply error out here */
- if (err)
- printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
- pciserial_resume_ports(priv);
- }
- return 0;
-}
-#endif
-
-static struct pci_device_id serial_pci_tbl[] = {
- /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
- { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
- PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
- pbn_b2_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
- pbn_b1_8_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
- pbn_b1_4_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
- pbn_b1_2_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
- pbn_b1_8_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
- pbn_b1_4_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
- pbn_b1_2_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
- pbn_b1_4_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
- pbn_b1_4_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
- pbn_b1_2_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
- pbn_b1_4_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0,
- pbn_b1_2_1250000 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0,
- pbn_b0_2_1843200 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
- pbn_b0_4_1843200 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_VENDOR_ID_AFAVLAB,
- PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
- pbn_b0_4_1152000 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
- 0, 0, pbn_exar_ibm_saturn },
-
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_1_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_460800 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_115200 },
-
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- /*
- * VScom SPCOM800, from sl@s.pl
- */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_921600 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_4_921600 },
- /* Unknown card - subdevice 0x1584 */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_VENDOR_ID_PLX,
- PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
- pbn_b0_4_115200 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_KEYSPAN,
- PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
- pbn_panacom },
- { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_panacom4 },
- { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_panacom2 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
- PCI_VENDOR_ID_ESDGMBH,
- PCI_DEVICE_ID_ESDGMBH_CPCIASIO4, 0, 0,
- pbn_b2_4_115200 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
- pbn_b2_4_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
- pbn_b2_8_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
- pbn_b2_16_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
- pbn_b2_16_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIRAS,
- PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
- pbn_b2_4_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIRAS,
- PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
- pbn_b2_8_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_EXSYS,
- PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
- pbn_exsys_4055 },
- /*
- * Megawolf Romulus PCI Serial Card, from Mike Hudson
- * (Exoray@isys.ca)
- */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
- 0x10b5, 0x106a, 0, 0,
- pbn_plx_romulus },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_4_115200 },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_2_115200 },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
- 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL,
- 0, 0,
- pbn_b0_4_1152000 },
- { PCI_VENDOR_ID_OXSEMI, 0x9505,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
-
- /*
- * The below card is a little controversial since it is the
- * subject of a PCI vendor/device ID clash. (See
- * www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html).
- * For now just used the hex ID 0x950a.
- */
- { PCI_VENDOR_ID_OXSEMI, 0x950a,
- PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
- pbn_b0_2_115200 },
- { PCI_VENDOR_ID_OXSEMI, 0x950a,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_2_1130000 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_C950,
- PCI_VENDOR_ID_OXSEMI, PCI_SUBDEVICE_ID_OXSEMI_C950, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_115200 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958,
- PCI_ANY_ID , PCI_ANY_ID, 0, 0,
- pbn_b2_8_1152000 },
-
- /*
- * Oxford Semiconductor Inc. Tornado PCI express device range.
- */
- { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- /*
- * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
- */
- { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
- PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
- PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
- PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
- pbn_oxsemi_4_4000000 },
- { 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 },
- /*
- * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
- * from skokodyn@yahoo.com
- */
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO232, 0, 0,
- pbn_sbsxrsio },
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO422, 0, 0,
- pbn_sbsxrsio },
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL232, 0, 0,
- pbn_sbsxrsio },
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL422, 0, 0,
- pbn_sbsxrsio },
-
- /*
- * Digitan DS560-558, from jimd@esoft.com
- */
- { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_115200 },
-
- /*
- * Titan Electronic cards
- * The 400L and 800L have a custom setup quirk.
- */
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_2_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b4_bt_2_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b4_bt_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b4_bt_8_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
-
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_460800 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_460800 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_460800 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
-
- /*
- * Computone devices submitted by Doug McNash dmcnash@computone.com
- */
- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
- 0, 0, pbn_computone_4 },
- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
- 0, 0, pbn_computone_8 },
- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
- 0, 0, pbn_computone_6 },
-
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi },
- { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
- PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_1_921600 },
-
- /*
- * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org>
- */
- { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_115200 },
- { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P030,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_115200 },
-
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_1_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_1_460800 },
-
- /*
- * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
- * Cards are identified by their subsystem vendor IDs, which
- * (in hex) match the model number.
- *
- * Note that JC140x are RS422/485 cards which require ox950
- * ACR = 0x10, and as such are not currently fully supported.
- */
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1204, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
-/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1402, 0x0002, 0, 0,
- pbn_b0_2_921600 }, */
-/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1404, 0x0004, 0, 0,
- pbn_b0_4_921600 }, */
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
-
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
- 0x1204, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- /*
- * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
- */
- { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_1382400 },
-
- /*
- * Dell Remote Access Card III - Tim_T_Murphy@Dell.com
- */
- { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_1382400 },
-
- /*
- * RAStel 2 port modem, gerg@moreton.com.au
- */
- { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
-
- /*
- * EKF addition for i960 Boards form EKF with serial port
- */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP,
- 0xE4BF, PCI_ANY_ID, 0, 0,
- pbn_intel_i960 },
-
- /*
- * Xircom Cardbus/Ethernet combos
- */
- { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_115200 },
- /*
- * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry)
- */
- { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_115200 },
-
- /*
- * Untested PCI modems, sent in from various folks...
- */
-
- /*
- * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de>
- */
- { PCI_VENDOR_ID_ROCKWELL, 0x1004,
- 0x1048, 0x1500, 0, 0,
- pbn_b1_1_115200 },
-
- { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
- 0xFF00, 0, 0, 0,
- pbn_sgi_ioc3 },
-
- /*
- * HP Diva card
- */
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
- PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0,
- pbn_b1_1_115200 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_5_115200 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_115200 },
-
- { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b3_2_115200 },
- { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b3_4_115200 },
- { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b3_8_115200 },
-
- /*
- * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
- */
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_exar_XR17C152 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_exar_XR17C154 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_exar_XR17C158 },
-
- /*
- * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
- */
- { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_115200 },
- /*
- * ITE
- */
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
- PCI_ANY_ID, PCI_ANY_ID,
- 0, 0,
- pbn_b1_bt_1_115200 },
-
- /*
- * IntaShield IS-200
- */
- { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */
- pbn_b2_2_115200 },
- /*
- * IntaShield IS-400
- */
- { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
- pbn_b2_4_115200 },
- /*
- * Perle PCI-RAS cards
- */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
- PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4,
- 0, 0, pbn_b2_4_921600 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
- PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
- 0, 0, pbn_b2_8_921600 },
-
- /*
- * Mainpine series cards: Fairly standard layout but fools
- * parts of the autodetect in some cases and uses otherwise
- * unmatched communications subclasses in the PCI Express case
- */
-
- { /* RockForceDUO */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0200,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceQUATRO */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0300,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceDUO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0400,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceQUATRO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0500,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForce+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0600,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForce+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0700,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceOCTO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0800,
- 0, 0, pbn_b0_8_115200 },
- { /* RockForceDUO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0C00,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceQUARTRO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0D00,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceOCTO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x1D00,
- 0, 0, pbn_b0_8_115200 },
- { /* RockForceD1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2000,
- 0, 0, pbn_b0_1_115200 },
- { /* RockForceF1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2100,
- 0, 0, pbn_b0_1_115200 },
- { /* RockForceD2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2200,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceF2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2300,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceD4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2400,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceF4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2500,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceD8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2600,
- 0, 0, pbn_b0_8_115200 },
- { /* RockForceF8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2700,
- 0, 0, pbn_b0_8_115200 },
- { /* IQ Express D1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3000,
- 0, 0, pbn_b0_1_115200 },
- { /* IQ Express F1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3100,
- 0, 0, pbn_b0_1_115200 },
- { /* IQ Express D2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3200,
- 0, 0, pbn_b0_2_115200 },
- { /* IQ Express F2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3300,
- 0, 0, pbn_b0_2_115200 },
- { /* IQ Express D4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3400,
- 0, 0, pbn_b0_4_115200 },
- { /* IQ Express F4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3500,
- 0, 0, pbn_b0_4_115200 },
- { /* IQ Express D8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3C00,
- 0, 0, pbn_b0_8_115200 },
- { /* IQ Express F8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3D00,
- 0, 0, pbn_b0_8_115200 },
-
-
- /*
- * PA Semi PA6T-1682M on-chip UART
- */
- { PCI_VENDOR_ID_PASEMI, 0xa004,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pasemi_1682M },
-
- /*
- * National Instruments
- */
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_16_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_16_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_8 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_8 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_16 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_16 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
-
- /*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7500,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_4_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7420,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_2_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7300,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA_OLD,
- PCI_DEVICE_ID_ADDIDATA_APCI7800,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b1_8_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7500_2,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_4_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7420_2,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_2_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7300_2,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7500_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_4_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7420_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_2_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7300_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7800_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_8_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7500,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_4_3906250 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7420,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_2_3906250 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7300,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_1_3906250 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7800,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_8_3906250 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
- PCI_VENDOR_ID_IBM, 0x0299,
- 0, 0, pbn_b0_bt_2_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- /*
- * Best Connectivity PCI Multi I/O cards
- */
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
- 0xA000, 0x3004,
- 0, 0, pbn_b0_bt_4_115200 },
- /* Intel CE4100 */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ce4100_1_115200 },
-
-
- /*
- * These entries match devices with class COMMUNICATION_SERIAL,
- * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
- */
- { PCI_ANY_ID, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8,
- 0xffff00, pbn_default },
- { PCI_ANY_ID, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_MODEM << 8,
- 0xffff00, pbn_default },
- { PCI_ANY_ID, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_MULTISERIAL << 8,
- 0xffff00, pbn_default },
- { 0, }
-};
-
-static struct pci_driver serial_pci_driver = {
- .name = "serial",
- .probe = pciserial_init_one,
- .remove = __devexit_p(pciserial_remove_one),
-#ifdef CONFIG_PM
- .suspend = pciserial_suspend_one,
- .resume = pciserial_resume_one,
-#endif
- .id_table = serial_pci_tbl,
-};
-
-static int __init serial8250_pci_init(void)
-{
- return pci_register_driver(&serial_pci_driver);
-}
-
-static void __exit serial8250_pci_exit(void)
-{
- pci_unregister_driver(&serial_pci_driver);
-}
-
-module_init(serial8250_pci_init);
-module_exit(serial8250_pci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
-MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
deleted file mode 100644
index 4822cb50cd0f..000000000000
--- a/drivers/serial/8250_pnp.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2001 Russell King, All Rights Reserved.
- *
- * Ported to the Linux PnP Layer - (C) Adam Belay.
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pnp.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/serial_core.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-
-#include "8250.h"
-
-#define UNKNOWN_DEV 0x3000
-
-
-static const struct pnp_device_id pnp_dev_table[] = {
- /* Archtek America Corp. */
- /* Archtek SmartLink Modem 3334BT Plug & Play */
- { "AAC000F", 0 },
- /* Anchor Datacomm BV */
- /* SXPro 144 External Data Fax Modem Plug & Play */
- { "ADC0001", 0 },
- /* SXPro 288 External Data Fax Modem Plug & Play */
- { "ADC0002", 0 },
- /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
- { "AEI0250", 0 },
- /* Actiontec ISA PNP 56K X2 Fax Modem */
- { "AEI1240", 0 },
- /* Rockwell 56K ACF II Fax+Data+Voice Modem */
- { "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
- /* AZT3005 PnP SOUND DEVICE */
- { "AZT4001", 0 },
- /* Best Data Products Inc. Smart One 336F PnP Modem */
- { "BDP3336", 0 },
- /* Boca Research */
- /* Boca Complete Ofc Communicator 14.4 Data-FAX */
- { "BRI0A49", 0 },
- /* Boca Research 33,600 ACF Modem */
- { "BRI1400", 0 },
- /* Boca 33.6 Kbps Internal FD34FSVD */
- { "BRI3400", 0 },
- /* Boca 33.6 Kbps Internal FD34FSVD */
- { "BRI0A49", 0 },
- /* Best Data Products Inc. Smart One 336F PnP Modem */
- { "BDP3336", 0 },
- /* Computer Peripherals Inc */
- /* EuroViVa CommCenter-33.6 SP PnP */
- { "CPI4050", 0 },
- /* Creative Labs */
- /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
- { "CTL3001", 0 },
- /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
- { "CTL3011", 0 },
- /* Davicom ISA 33.6K Modem */
- { "DAV0336", 0 },
- /* Creative */
- /* Creative Modem Blaster Flash56 DI5601-1 */
- { "DMB1032", 0 },
- /* Creative Modem Blaster V.90 DI5660 */
- { "DMB2001", 0 },
- /* E-Tech */
- /* E-Tech CyberBULLET PC56RVP */
- { "ETT0002", 0 },
- /* FUJITSU */
- /* Fujitsu 33600 PnP-I2 R Plug & Play */
- { "FUJ0202", 0 },
- /* Fujitsu FMV-FX431 Plug & Play */
- { "FUJ0205", 0 },
- /* Fujitsu 33600 PnP-I4 R Plug & Play */
- { "FUJ0206", 0 },
- /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
- { "FUJ0209", 0 },
- /* Archtek America Corp. */
- /* Archtek SmartLink Modem 3334BT Plug & Play */
- { "GVC000F", 0 },
- /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
- { "GVC0303", 0 },
- /* Hayes */
- /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
- { "HAY0001", 0 },
- /* Hayes Optima 336 V.34 + FAX + Voice PnP */
- { "HAY000C", 0 },
- /* Hayes Optima 336B V.34 + FAX + Voice PnP */
- { "HAY000D", 0 },
- /* Hayes Accura 56K Ext Fax Modem PnP */
- { "HAY5670", 0 },
- /* Hayes Accura 56K Ext Fax Modem PnP */
- { "HAY5674", 0 },
- /* Hayes Accura 56K Fax Modem PnP */
- { "HAY5675", 0 },
- /* Hayes 288, V.34 + FAX */
- { "HAYF000", 0 },
- /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
- { "HAYF001", 0 },
- /* IBM */
- /* IBM Thinkpad 701 Internal Modem Voice */
- { "IBM0033", 0 },
- /* Intertex */
- /* Intertex 28k8 33k6 Voice EXT PnP */
- { "IXDC801", 0 },
- /* Intertex 33k6 56k Voice EXT PnP */
- { "IXDC901", 0 },
- /* Intertex 28k8 33k6 Voice SP EXT PnP */
- { "IXDD801", 0 },
- /* Intertex 33k6 56k Voice SP EXT PnP */
- { "IXDD901", 0 },
- /* Intertex 28k8 33k6 Voice SP INT PnP */
- { "IXDF401", 0 },
- /* Intertex 28k8 33k6 Voice SP EXT PnP */
- { "IXDF801", 0 },
- /* Intertex 33k6 56k Voice SP EXT PnP */
- { "IXDF901", 0 },
- /* Kortex International */
- /* KORTEX 28800 Externe PnP */
- { "KOR4522", 0 },
- /* KXPro 33.6 Vocal ASVD PnP */
- { "KORF661", 0 },
- /* Lasat */
- /* LASAT Internet 33600 PnP */
- { "LAS4040", 0 },
- /* Lasat Safire 560 PnP */
- { "LAS4540", 0 },
- /* Lasat Safire 336 PnP */
- { "LAS5440", 0 },
- /* Microcom, Inc. */
- /* Microcom TravelPorte FAST V.34 Plug & Play */
- { "MNP0281", 0 },
- /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
- { "MNP0336", 0 },
- /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
- { "MNP0339", 0 },
- /* Microcom DeskPorte 28.8P Plug & Play */
- { "MNP0342", 0 },
- /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
- { "MNP0500", 0 },
- /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
- { "MNP0501", 0 },
- /* Microcom DeskPorte 28.8S Internal Plug & Play */
- { "MNP0502", 0 },
- /* Motorola */
- /* Motorola BitSURFR Plug & Play */
- { "MOT1105", 0 },
- /* Motorola TA210 Plug & Play */
- { "MOT1111", 0 },
- /* Motorola HMTA 200 (ISDN) Plug & Play */
- { "MOT1114", 0 },
- /* Motorola BitSURFR Plug & Play */
- { "MOT1115", 0 },
- /* Motorola Lifestyle 28.8 Internal */
- { "MOT1190", 0 },
- /* Motorola V.3400 Plug & Play */
- { "MOT1501", 0 },
- /* Motorola Lifestyle 28.8 V.34 Plug & Play */
- { "MOT1502", 0 },
- /* Motorola Power 28.8 V.34 Plug & Play */
- { "MOT1505", 0 },
- /* Motorola ModemSURFR External 28.8 Plug & Play */
- { "MOT1509", 0 },
- /* Motorola Premier 33.6 Desktop Plug & Play */
- { "MOT150A", 0 },
- /* Motorola VoiceSURFR 56K External PnP */
- { "MOT150F", 0 },
- /* Motorola ModemSURFR 56K External PnP */
- { "MOT1510", 0 },
- /* Motorola ModemSURFR 56K Internal PnP */
- { "MOT1550", 0 },
- /* Motorola ModemSURFR Internal 28.8 Plug & Play */
- { "MOT1560", 0 },
- /* Motorola Premier 33.6 Internal Plug & Play */
- { "MOT1580", 0 },
- /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
- { "MOT15B0", 0 },
- /* Motorola VoiceSURFR 56K Internal PnP */
- { "MOT15F0", 0 },
- /* Com 1 */
- /* Deskline K56 Phone System PnP */
- { "MVX00A1", 0 },
- /* PC Rider K56 Phone System PnP */
- { "MVX00F2", 0 },
- /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
- { "nEC8241", 0 },
- /* Pace 56 Voice Internal Plug & Play Modem */
- { "PMC2430", 0 },
- /* Generic */
- /* Generic standard PC COM port */
- { "PNP0500", 0 },
- /* Generic 16550A-compatible COM port */
- { "PNP0501", 0 },
- /* Compaq 14400 Modem */
- { "PNPC000", 0 },
- /* Compaq 2400/9600 Modem */
- { "PNPC001", 0 },
- /* Dial-Up Networking Serial Cable between 2 PCs */
- { "PNPC031", 0 },
- /* Dial-Up Networking Parallel Cable between 2 PCs */
- { "PNPC032", 0 },
- /* Standard 9600 bps Modem */
- { "PNPC100", 0 },
- /* Standard 14400 bps Modem */
- { "PNPC101", 0 },
- /* Standard 28800 bps Modem*/
- { "PNPC102", 0 },
- /* Standard Modem*/
- { "PNPC103", 0 },
- /* Standard 9600 bps Modem*/
- { "PNPC104", 0 },
- /* Standard 14400 bps Modem*/
- { "PNPC105", 0 },
- /* Standard 28800 bps Modem*/
- { "PNPC106", 0 },
- /* Standard Modem */
- { "PNPC107", 0 },
- /* Standard 9600 bps Modem */
- { "PNPC108", 0 },
- /* Standard 14400 bps Modem */
- { "PNPC109", 0 },
- /* Standard 28800 bps Modem */
- { "PNPC10A", 0 },
- /* Standard Modem */
- { "PNPC10B", 0 },
- /* Standard 9600 bps Modem */
- { "PNPC10C", 0 },
- /* Standard 14400 bps Modem */
- { "PNPC10D", 0 },
- /* Standard 28800 bps Modem */
- { "PNPC10E", 0 },
- /* Standard Modem */
- { "PNPC10F", 0 },
- /* Standard PCMCIA Card Modem */
- { "PNP2000", 0 },
- /* Rockwell */
- /* Modular Technology */
- /* Rockwell 33.6 DPF Internal PnP */
- /* Modular Technology 33.6 Internal PnP */
- { "ROK0030", 0 },
- /* Kortex International */
- /* KORTEX 14400 Externe PnP */
- { "ROK0100", 0 },
- /* Rockwell 28.8 */
- { "ROK4120", 0 },
- /* Viking Components, Inc */
- /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
- { "ROK4920", 0 },
- /* Rockwell */
- /* British Telecom */
- /* Modular Technology */
- /* Rockwell 33.6 DPF External PnP */
- /* BT Prologue 33.6 External PnP */
- /* Modular Technology 33.6 External PnP */
- { "RSS00A0", 0 },
- /* Viking 56K FAX INT */
- { "RSS0262", 0 },
- /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
- { "RSS0250", 0 },
- /* SupraExpress 28.8 Data/Fax PnP modem */
- { "SUP1310", 0 },
- /* SupraExpress 336i PnP Voice Modem */
- { "SUP1381", 0 },
- /* SupraExpress 33.6 Data/Fax PnP modem */
- { "SUP1421", 0 },
- /* SupraExpress 33.6 Data/Fax PnP modem */
- { "SUP1590", 0 },
- /* SupraExpress 336i Sp ASVD */
- { "SUP1620", 0 },
- /* SupraExpress 33.6 Data/Fax PnP modem */
- { "SUP1760", 0 },
- /* SupraExpress 56i Sp Intl */
- { "SUP2171", 0 },
- /* Phoebe Micro */
- /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
- { "TEX0011", 0 },
- /* Archtek America Corp. */
- /* Archtek SmartLink Modem 3334BT Plug & Play */
- { "UAC000F", 0 },
- /* 3Com Corp. */
- /* Gateway Telepath IIvi 33.6 */
- { "USR0000", 0 },
- /* U.S. Robotics Sporster 33.6K Fax INT PnP */
- { "USR0002", 0 },
- /* Sportster Vi 14.4 PnP FAX Voicemail */
- { "USR0004", 0 },
- /* U.S. Robotics 33.6K Voice INT PnP */
- { "USR0006", 0 },
- /* U.S. Robotics 33.6K Voice EXT PnP */
- { "USR0007", 0 },
- /* U.S. Robotics Courier V.Everything INT PnP */
- { "USR0009", 0 },
- /* U.S. Robotics 33.6K Voice INT PnP */
- { "USR2002", 0 },
- /* U.S. Robotics 56K Voice INT PnP */
- { "USR2070", 0 },
- /* U.S. Robotics 56K Voice EXT PnP */
- { "USR2080", 0 },
- /* U.S. Robotics 56K FAX INT */
- { "USR3031", 0 },
- /* U.S. Robotics 56K FAX INT */
- { "USR3050", 0 },
- /* U.S. Robotics 56K Voice INT PnP */
- { "USR3070", 0 },
- /* U.S. Robotics 56K Voice EXT PnP */
- { "USR3080", 0 },
- /* U.S. Robotics 56K Voice INT PnP */
- { "USR3090", 0 },
- /* U.S. Robotics 56K Message */
- { "USR9100", 0 },
- /* U.S. Robotics 56K FAX EXT PnP*/
- { "USR9160", 0 },
- /* U.S. Robotics 56K FAX INT PnP*/
- { "USR9170", 0 },
- /* U.S. Robotics 56K Voice EXT PnP*/
- { "USR9180", 0 },
- /* U.S. Robotics 56K Voice INT PnP*/
- { "USR9190", 0 },
- /* Wacom tablets */
- { "WACFXXX", 0 },
- /* Compaq touchscreen */
- { "FPI2002", 0 },
- /* Fujitsu Stylistic touchscreens */
- { "FUJ02B2", 0 },
- { "FUJ02B3", 0 },
- /* Fujitsu Stylistic LT touchscreens */
- { "FUJ02B4", 0 },
- /* Passive Fujitsu Stylistic touchscreens */
- { "FUJ02B6", 0 },
- { "FUJ02B7", 0 },
- { "FUJ02B8", 0 },
- { "FUJ02B9", 0 },
- { "FUJ02BC", 0 },
- /* Fujitsu Wacom Tablet PC device */
- { "FUJ02E5", 0 },
- /* Fujitsu P-series tablet PC device */
- { "FUJ02E6", 0 },
- /* Fujitsu Wacom 2FGT Tablet PC device */
- { "FUJ02E7", 0 },
- /* Fujitsu Wacom 1FGT Tablet PC device */
- { "FUJ02E9", 0 },
- /*
- * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
- * disguise)
- */
- { "LTS0001", 0 },
- /* Rockwell's (PORALiNK) 33600 INT PNP */
- { "WCI0003", 0 },
- /* Unknown PnP modems */
- { "PNPCXXX", UNKNOWN_DEV },
- /* More unknown PnP modems */
- { "PNPDXXX", UNKNOWN_DEV },
- { "", 0 }
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-static char *modem_names[] __devinitdata = {
- "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
- "56K", "56k", "K56", "33.6", "28.8", "14.4",
- "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
- "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
-};
-
-static int __devinit check_name(char *name)
-{
- char **tmp;
-
- for (tmp = modem_names; *tmp; tmp++)
- if (strstr(name, *tmp))
- return 1;
-
- return 0;
-}
-
-static int __devinit check_resources(struct pnp_dev *dev)
-{
- resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
- int i;
-
- for (i = 0; i < ARRAY_SIZE(base); i++) {
- if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Given a complete unknown PnP device, try to use some heuristics to
- * detect modems. Currently use such heuristic set:
- * - dev->name or dev->bus->name must contain "modem" substring;
- * - device must have only one IO region (8 byte long) with base address
- * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
- *
- * Such detection looks very ugly, but can detect at least some of numerous
- * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
- * table.
- */
-static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
-{
- if (!(check_name(pnp_dev_name(dev)) ||
- (dev->card && check_name(dev->card->name))))
- return -ENODEV;
-
- if (check_resources(dev))
- return 0;
-
- return -ENODEV;
-}
-
-static int __devinit
-serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
- struct uart_port port;
- int ret, line, flags = dev_id->driver_data;
-
- if (flags & UNKNOWN_DEV) {
- ret = serial_pnp_guess_board(dev, &flags);
- if (ret < 0)
- return ret;
- }
-
- memset(&port, 0, sizeof(struct uart_port));
- if (pnp_irq_valid(dev, 0))
- port.irq = pnp_irq(dev, 0);
- if (pnp_port_valid(dev, 0)) {
- port.iobase = pnp_port_start(dev, 0);
- port.iotype = UPIO_PORT;
- } else if (pnp_mem_valid(dev, 0)) {
- port.mapbase = pnp_mem_start(dev, 0);
- port.iotype = UPIO_MEM;
- port.flags = UPF_IOREMAP;
- } else
- return -ENODEV;
-
-#ifdef SERIAL_DEBUG_PNP
- printk(KERN_DEBUG
- "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
- port.iobase, port.mapbase, port.irq, port.iotype);
-#endif
-
- port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
- if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
- port.flags |= UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &dev->dev;
-
- line = serial8250_register_port(&port);
- if (line < 0)
- return -ENODEV;
-
- pnp_set_drvdata(dev, (void *)((long)line + 1));
- return 0;
-}
-
-static void __devexit serial_pnp_remove(struct pnp_dev *dev)
-{
- long line = (long)pnp_get_drvdata(dev);
- if (line)
- serial8250_unregister_port(line - 1);
-}
-
-#ifdef CONFIG_PM
-static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
-{
- long line = (long)pnp_get_drvdata(dev);
-
- if (!line)
- return -ENODEV;
- serial8250_suspend_port(line - 1);
- return 0;
-}
-
-static int serial_pnp_resume(struct pnp_dev *dev)
-{
- long line = (long)pnp_get_drvdata(dev);
-
- if (!line)
- return -ENODEV;
- serial8250_resume_port(line - 1);
- return 0;
-}
-#else
-#define serial_pnp_suspend NULL
-#define serial_pnp_resume NULL
-#endif /* CONFIG_PM */
-
-static struct pnp_driver serial_pnp_driver = {
- .name = "serial",
- .probe = serial_pnp_probe,
- .remove = __devexit_p(serial_pnp_remove),
- .suspend = serial_pnp_suspend,
- .resume = serial_pnp_resume,
- .id_table = pnp_dev_table,
-};
-
-static int __init serial8250_pnp_init(void)
-{
- return pnp_register_driver(&serial_pnp_driver);
-}
-
-static void __exit serial8250_pnp_exit(void)
-{
- pnp_unregister_driver(&serial_pnp_driver);
-}
-
-module_init(serial8250_pnp_init);
-module_exit(serial8250_pnp_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver");
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
deleted file mode 100644
index c1df7676a73d..000000000000
--- a/drivers/serial/Kconfig
+++ /dev/null
@@ -1,1598 +0,0 @@
-#
-# Serial device configuration
-#
-
-menu "Serial drivers"
- depends on HAS_IOMEM
-
-#
-# The new 8250/16550 serial drivers
-config SERIAL_8250
- tristate "8250/16550 and compatible serial support"
- select SERIAL_CORE
- ---help---
- This selects whether you want to include the driver for the standard
- serial ports. The standard answer is Y. People who might say N
- here are those that are setting up dedicated Ethernet WWW/FTP
- servers, or users that have one of the various bus mice instead of a
- serial mouse and don't intend to use their machine's standard serial
- port for anything. (Note that the Cyclades and Stallion multi
- serial port drivers do not need this driver built in for them to
- work.)
-
- To compile this driver as a module, choose M here: the
- module will be called 8250.
- [WARNING: Do not compile this driver as a module if you are using
- non-standard serial ports, since the configuration information will
- be lost when the driver is unloaded. This limitation may be lifted
- in the future.]
-
- BTW1: If you have a mouseman serial mouse which is not recognized by
- the X window system, try running gpm first.
-
- BTW2: If you intend to use a software modem (also called Winmodem)
- under Linux, forget it. These modems are crippled and require
- proprietary drivers which are only available under Windows.
-
- Most people will say Y or M here, so that they can use serial mice,
- modems and similar devices connecting to the standard serial ports.
-
-config SERIAL_8250_CONSOLE
- bool "Console on 8250/16550 and compatible serial port"
- depends on SERIAL_8250=y
- select SERIAL_CORE_CONSOLE
- ---help---
- If you say Y here, it will be possible to use a serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode). This could be useful if some terminal or printer is connected
- to that serial port.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyS1". (Try "man bootparam" or see the documentation of
- your boot loader (grub or lilo or loadlin) about how to pass options
- to the kernel at boot time.)
-
- If you don't have a VGA card installed and you say Y here, the
- kernel will automatically use the first serial line, /dev/ttyS0, as
- system console.
-
- You can set that using a kernel command line option such as
- "console=uart8250,io,0x3f8,9600n8"
- "console=uart8250,mmio,0xff5e0000,115200n8".
- and it will switch to normal serial console when the corresponding
- port is ready.
- "earlycon=uart8250,io,0x3f8,9600n8"
- "earlycon=uart8250,mmio,0xff5e0000,115200n8".
- it will not only setup early console.
-
- If unsure, say N.
-
-config FIX_EARLYCON_MEM
- bool
- depends on X86
- default y
-
-config SERIAL_8250_GSC
- tristate
- depends on SERIAL_8250 && GSC
- default SERIAL_8250
-
-config SERIAL_8250_PCI
- tristate "8250/16550 PCI device support" if EMBEDDED
- depends on SERIAL_8250 && PCI
- default SERIAL_8250
- help
- This builds standard PCI serial support. You may be able to
- disable this feature if you only need legacy serial support.
- Saves about 9K.
-
-config SERIAL_8250_PNP
- tristate "8250/16550 PNP device support" if EMBEDDED
- depends on SERIAL_8250 && PNP
- default SERIAL_8250
- help
- This builds standard PNP serial support. You may be able to
- disable this feature if you only need legacy serial support.
-
-config SERIAL_8250_HP300
- tristate
- depends on SERIAL_8250 && HP300
- default SERIAL_8250
-
-config SERIAL_8250_CS
- tristate "8250/16550 PCMCIA device support"
- depends on PCMCIA && SERIAL_8250
- ---help---
- Say Y here to enable support for 16-bit PCMCIA serial devices,
- including serial port cards, modems, and the modem functions of
- multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
- credit-card size devices often used with laptops.)
-
- To compile this driver as a module, choose M here: the
- module will be called serial_cs.
-
- If unsure, say N.
-
-config SERIAL_8250_NR_UARTS
- int "Maximum number of 8250/16550 serial ports"
- depends on SERIAL_8250
- default "4"
- help
- Set this to the number of serial ports you want the driver
- to support. This includes any ports discovered via ACPI or
- PCI enumeration and any ports that may be added at run-time
- via hot-plug, or any ISA multi-port serial cards.
-
-config SERIAL_8250_RUNTIME_UARTS
- int "Number of 8250/16550 serial ports to register at runtime"
- depends on SERIAL_8250
- range 0 SERIAL_8250_NR_UARTS
- default "4"
- help
- Set this to the maximum number of serial ports you want
- the kernel to register at boot time. This can be overridden
- with the module parameter "nr_uarts", or boot-time parameter
- 8250.nr_uarts
-
-config SERIAL_8250_EXTENDED
- bool "Extended 8250/16550 serial driver options"
- depends on SERIAL_8250
- help
- If you wish to use any non-standard features of the standard "dumb"
- driver, say Y here. This includes HUB6 support, shared serial
- interrupts, special multiport support, support for more than the
- four COM 1/2/3/4 boards, etc.
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about serial driver options. If unsure, say N.
-
-config SERIAL_8250_MANY_PORTS
- bool "Support more than 4 legacy serial ports"
- depends on SERIAL_8250_EXTENDED && !IA64
- help
- Say Y here if you have dumb serial boards other than the four
- standard COM 1/2/3/4 ports. This may happen if you have an AST
- FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
- from <http://www.tldp.org/docs.html#howto>), or other custom
- serial port hardware which acts similar to standard serial port
- hardware. If you only use the standard COM 1/2/3/4 ports, you can
- say N here to save some memory. You can also say Y if you have an
- "intelligent" multiport card such as Cyclades, Digiboards, etc.
-
-#
-# Multi-port serial cards
-#
-
-config SERIAL_8250_FOURPORT
- tristate "Support Fourport cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have an AST FourPort serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_fourport.
-
-config SERIAL_8250_ACCENT
- tristate "Support Accent cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have an Accent Async serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_accent.
-
-config SERIAL_8250_BOCA
- tristate "Support Boca cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have a Boca serial board. Please read the Boca
- mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_boca.
-
-config SERIAL_8250_EXAR_ST16C554
- tristate "Support Exar ST16C554/554D Quad UART"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- The Uplogix Envoy TU301 uses this Exar Quad UART. If you are
- tinkering with your Envoy TU301, or have a machine with this UART,
- say Y here.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_exar_st16c554.
-
-config SERIAL_8250_HUB6
- tristate "Support Hub6 cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have a HUB6 serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_hub6.
-
-config SERIAL_8250_SHARE_IRQ
- bool "Support for sharing serial interrupts"
- depends on SERIAL_8250_EXTENDED
- help
- Some serial boards have hardware support which allows multiple dumb
- serial ports on the same board to share a single IRQ. To enable
- support for this in the serial driver, say Y here.
-
-config SERIAL_8250_DETECT_IRQ
- bool "Autodetect IRQ on standard ports (unsafe)"
- depends on SERIAL_8250_EXTENDED
- help
- Say Y here if you want the kernel to try to guess which IRQ
- to use for your serial port.
-
- This is considered unsafe; it is far better to configure the IRQ in
- a boot script using the setserial command.
-
- If unsure, say N.
-
-config SERIAL_8250_RSA
- bool "Support RSA serial ports"
- depends on SERIAL_8250_EXTENDED
- help
- ::: To be written :::
-
-config SERIAL_8250_MCA
- tristate "Support 8250-type ports on MCA buses"
- depends on SERIAL_8250 != n && MCA
- help
- Say Y here if you have a MCA serial ports.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_mca.
-
-config SERIAL_8250_ACORN
- tristate "Acorn expansion card serial port support"
- depends on ARCH_ACORN && SERIAL_8250
- help
- If you have an Atomwide Serial card or Serial Port card for an Acorn
- system, say Y to this option. The driver can handle 1, 2, or 3 port
- cards. If unsure, say N.
-
-config SERIAL_8250_RM9K
- bool "Support for MIPS RM9xxx integrated serial port"
- depends on SERIAL_8250 != n && SERIAL_RM9000
- select SERIAL_8250_SHARE_IRQ
- help
- Selecting this option will add support for the integrated serial
- port hardware found on MIPS RM9122 and similar processors.
- If unsure, say N.
-
-comment "Non-8250 serial port support"
-
-config SERIAL_AMBA_PL010
- tristate "ARM AMBA PL010 serial port support"
- depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
- select SERIAL_CORE
- help
- This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
- an Integrator/AP or Integrator/PP2 platform, or if you have a
- Cirrus Logic EP93xx CPU, say Y or M here.
-
- If unsure, say N.
-
-config SERIAL_AMBA_PL010_CONSOLE
- bool "Support for console on AMBA serial port"
- depends on SERIAL_AMBA_PL010=y
- select SERIAL_CORE_CONSOLE
- ---help---
- Say Y here if you wish to use an AMBA PrimeCell UART as the system
- console (the system console is the device which receives all kernel
- messages and warnings and which allows logins in single user mode).
-
- Even if you say Y here, the currently visible framebuffer console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyAM0". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_AMBA_PL011
- tristate "ARM AMBA PL011 serial port support"
- depends on ARM_AMBA
- select SERIAL_CORE
- help
- This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have
- an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
- here.
-
- If unsure, say N.
-
-config SERIAL_AMBA_PL011_CONSOLE
- bool "Support for console on AMBA serial port"
- depends on SERIAL_AMBA_PL011=y
- select SERIAL_CORE_CONSOLE
- ---help---
- Say Y here if you wish to use an AMBA PrimeCell UART as the system
- console (the system console is the device which receives all kernel
- messages and warnings and which allows logins in single user mode).
-
- Even if you say Y here, the currently visible framebuffer console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyAMA0". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_SB1250_DUART
- tristate "BCM1xxx on-chip DUART serial support"
- depends on SIBYTE_SB1xxx_SOC=y
- select SERIAL_CORE
- default y
- ---help---
- Support for the asynchronous serial interface (DUART) included in
- the BCM1250 and derived System-On-a-Chip (SOC) devices. Note that
- the letter D in DUART stands for "dual", which is how the device
- is implemented. Depending on the SOC configuration there may be
- one or more DUARTs available of which all are handled.
-
- If unsure, say Y. To compile this driver as a module, choose M here:
- the module will be called sb1250-duart.
-
-config SERIAL_SB1250_DUART_CONSOLE
- bool "Support for console on a BCM1xxx DUART serial port"
- depends on SERIAL_SB1250_DUART=y
- select SERIAL_CORE_CONSOLE
- default y
- ---help---
- If you say Y here, it will be possible to use a serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode).
-
- If unsure, say Y.
-
-config SERIAL_ATMEL
- bool "AT91 / AT32 on-chip serial port support"
- depends on (ARM && ARCH_AT91) || AVR32
- select SERIAL_CORE
- help
- This enables the driver for the on-chip UARTs of the Atmel
- AT91 and AT32 processors.
-
-config SERIAL_ATMEL_CONSOLE
- bool "Support for console on AT91 / AT32 serial port"
- depends on SERIAL_ATMEL=y
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you wish to use an on-chip UART on a Atmel
- AT91 or AT32 processor as the system console (the system
- console is the device which receives all kernel messages and
- warnings and which allows logins in single user mode).
-
-config SERIAL_ATMEL_PDC
- bool "Support DMA transfers on AT91 / AT32 serial port"
- depends on SERIAL_ATMEL
- default y
- help
- Say Y here if you wish to use the PDC to do DMA transfers to
- and from the Atmel AT91 / AT32 serial port. In order to
- actually use DMA transfers, make sure that the use_dma_tx
- and use_dma_rx members in the atmel_uart_data struct is set
- appropriately for each port.
-
- Note that break and error handling currently doesn't work
- properly when DMA is enabled. Make sure that ports where
- this matters don't use DMA.
-
-config SERIAL_ATMEL_TTYAT
- bool "Install as device ttyATn instead of ttySn"
- depends on SERIAL_ATMEL=y
- help
- Say Y here if you wish to have the internal AT91 / AT32 UARTs
- appear as /dev/ttyATn (major 204, minor starting at 154)
- instead of the normal /dev/ttySn (major 4, minor starting at
- 64). This is necessary if you also want other UARTs, such as
- external 8250/16C550 compatible UARTs.
- The ttySn nodes are legally reserved for the 8250 serial driver
- but are often misused by other serial drivers.
-
- To use this, you should create suitable ttyATn device nodes in
- /dev/, and pass "console=ttyATn" to the kernel.
-
- Say Y if you have an external 8250/16C550 UART. If unsure, say N.
-
-config SERIAL_KS8695
- bool "Micrel KS8695 (Centaur) serial port support"
- depends on ARCH_KS8695
- select SERIAL_CORE
- help
- This selects the Micrel Centaur KS8695 UART. Say Y here.
-
-config SERIAL_KS8695_CONSOLE
- bool "Support for console on KS8695 (Centaur) serial port"
- depends on SERIAL_KS8695=y
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you wish to use a KS8695 (Centaur) UART as the
- system console (the system console is the device which
- receives all kernel messages and warnings and which allows
- logins in single user mode).
-
-config SERIAL_CLPS711X
- tristate "CLPS711X serial port support"
- depends on ARM && ARCH_CLPS711X
- select SERIAL_CORE
- help
- ::: To be written :::
-
-config SERIAL_CLPS711X_CONSOLE
- bool "Support for console on CLPS711X serial port"
- depends on SERIAL_CLPS711X=y
- select SERIAL_CORE_CONSOLE
- help
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyCL1". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_SAMSUNG
- tristate "Samsung SoC serial support"
- depends on ARM && PLAT_SAMSUNG
- select SERIAL_CORE
- help
- Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
- providing /dev/ttySAC0, 1 and 2 (note, some machines may not
- provide all of these ports, depending on how the serial port
- pins are configured.
-
-config SERIAL_SAMSUNG_UARTS_4
- bool
- depends on ARM && PLAT_SAMSUNG
- default y if CPU_S3C2443
- help
- Internal node for the common case of 4 Samsung compatible UARTs
-
-config SERIAL_SAMSUNG_UARTS
- int
- depends on ARM && PLAT_SAMSUNG
- default 2 if ARCH_S3C2400
- default 6 if ARCH_S5P6450
- default 4 if SERIAL_SAMSUNG_UARTS_4
- default 3
- help
- Select the number of available UART ports for the Samsung S3C
- serial driver
-
-config SERIAL_SAMSUNG_DEBUG
- bool "Samsung SoC serial debug"
- depends on SERIAL_SAMSUNG && DEBUG_LL
- help
- Add support for debugging the serial driver. Since this is
- generally being used as a console, we use our own output
- routines that go via the low-level debug printascii()
- function.
-
-config SERIAL_SAMSUNG_CONSOLE
- bool "Support for console on Samsung SoC serial port"
- depends on SERIAL_SAMSUNG=y
- select SERIAL_CORE_CONSOLE
- help
- Allow selection of the S3C24XX on-board serial ports for use as
- an virtual console.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttySACx". (Try "man bootparam" or see the documentation of
- your boot loader about how to pass options to the kernel at
- boot time.)
-
-config SERIAL_S3C2400
- tristate "Samsung S3C2410 Serial port support"
- depends on ARM && SERIAL_SAMSUNG && CPU_S3C2400
- default y if CPU_S3C2400
- help
- Serial port support for the Samsung S3C2400 SoC
-
-config SERIAL_S3C2410
- tristate "Samsung S3C2410 Serial port support"
- depends on SERIAL_SAMSUNG && CPU_S3C2410
- default y if CPU_S3C2410
- help
- Serial port support for the Samsung S3C2410 SoC
-
-config SERIAL_S3C2412
- tristate "Samsung S3C2412/S3C2413 Serial port support"
- depends on SERIAL_SAMSUNG && CPU_S3C2412
- default y if CPU_S3C2412
- help
- Serial port support for the Samsung S3C2412 and S3C2413 SoC
-
-config SERIAL_S3C2440
- tristate "Samsung S3C2440/S3C2442/S3C2416 Serial port support"
- depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442 || CPU_S3C2416)
- default y if CPU_S3C2440
- default y if CPU_S3C2442
- select SERIAL_SAMSUNG_UARTS_4 if CPU_S3C2416
- help
- Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC
-
-config SERIAL_S3C24A0
- tristate "Samsung S3C24A0 Serial port support"
- depends on SERIAL_SAMSUNG && CPU_S3C24A0
- default y if CPU_S3C24A0
- help
- Serial port support for the Samsung S3C24A0 SoC
-
-config SERIAL_S3C6400
- tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support"
- depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100)
- select SERIAL_SAMSUNG_UARTS_4
- default y
- help
- Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450
- and S5PC100 SoCs
-
-config SERIAL_S5PV210
- tristate "Samsung S5PV210 Serial port support"
- depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_S5PV310)
- select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_S5PV310)
- default y
- help
- Serial port support for Samsung's S5P Family of SoC's
-
-
-config SERIAL_MAX3100
- tristate "MAX3100 support"
- depends on SPI
- select SERIAL_CORE
- help
- MAX3100 chip support
-
-config SERIAL_MAX3107
- tristate "MAX3107 support"
- depends on SPI
- select SERIAL_CORE
- help
- MAX3107 chip support
-
-config SERIAL_MAX3107_AAVA
- tristate "MAX3107 AAVA platform support"
- depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB
- select SERIAL_CORE
- help
- Support for the MAX3107 chip configuration found on the AAVA
- platform. Includes the extra initialisation and GPIO support
- neded for this device.
-
-config SERIAL_DZ
- bool "DECstation DZ serial driver"
- depends on MACH_DECSTATION && 32BIT
- select SERIAL_CORE
- default y
- ---help---
- DZ11-family serial controllers for DECstations and VAXstations,
- including the DC7085, M7814, and M7819.
-
-config SERIAL_DZ_CONSOLE
- bool "Support console on DECstation DZ serial driver"
- depends on SERIAL_DZ=y
- select SERIAL_CORE_CONSOLE
- default y
- ---help---
- If you say Y here, it will be possible to use a serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode).
-
- Note that the firmware uses ttyS3 as the serial console on
- DECstations that use this driver.
-
- If unsure, say Y.
-
-config SERIAL_ZS
- tristate "DECstation Z85C30 serial support"
- depends on MACH_DECSTATION
- select SERIAL_CORE
- default y
- ---help---
- Support for the Zilog 85C350 serial communications controller used
- for serial ports in newer DECstation systems. These include the
- DECsystem 5900 and all models of the DECstation and DECsystem 5000
- systems except from model 200.
-
- If unsure, say Y. To compile this driver as a module, choose M here:
- the module will be called zs.
-
-config SERIAL_ZS_CONSOLE
- bool "Support for console on a DECstation Z85C30 serial port"
- depends on SERIAL_ZS=y
- select SERIAL_CORE_CONSOLE
- default y
- ---help---
- If you say Y here, it will be possible to use a serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode).
-
- Note that the firmware uses ttyS1 as the serial console on the
- Maxine and ttyS3 on the others using this driver.
-
- If unsure, say Y.
-
-config SERIAL_21285
- tristate "DC21285 serial port support"
- depends on ARM && FOOTBRIDGE
- select SERIAL_CORE
- help
- If you have a machine based on a 21285 (Footbridge) StrongARM(R)/
- PCI bridge you can enable its onboard serial port by enabling this
- option.
-
-config SERIAL_21285_CONSOLE
- bool "Console on DC21285 serial port"
- depends on SERIAL_21285=y
- select SERIAL_CORE_CONSOLE
- help
- If you have enabled the serial port on the 21285 footbridge you can
- make it the console by answering Y to this option.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyFB". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_MPSC
- bool "Marvell MPSC serial port support"
- depends on PPC32 && MV64X60
- select SERIAL_CORE
- help
- Say Y here if you want to use the Marvell MPSC serial controller.
-
-config SERIAL_MPSC_CONSOLE
- bool "Support for console on Marvell MPSC serial port"
- depends on SERIAL_MPSC
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you want to support a serial console on a Marvell MPSC.
-
-config SERIAL_PXA
- bool "PXA serial port support"
- depends on ARCH_PXA || ARCH_MMP
- select SERIAL_CORE
- help
- If you have a machine based on an Intel XScale PXA2xx CPU you
- can enable its onboard serial ports by enabling this option.
-
-config SERIAL_PXA_CONSOLE
- bool "Console on PXA serial port"
- depends on SERIAL_PXA
- select SERIAL_CORE_CONSOLE
- help
- If you have enabled the serial port on the Intel XScale PXA
- CPU you can make it the console by answering Y to this option.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttySA0". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_SA1100
- bool "SA1100 serial port support"
- depends on ARM && ARCH_SA1100
- select SERIAL_CORE
- help
- If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
- can enable its onboard serial port by enabling this option.
- Please read <file:Documentation/arm/SA1100/serial_UART> for further
- info.
-
-config SERIAL_SA1100_CONSOLE
- bool "Console on SA1100 serial port"
- depends on SERIAL_SA1100
- select SERIAL_CORE_CONSOLE
- help
- If you have enabled the serial port on the SA1100/SA1110 StrongARM
- CPU you can make it the console by answering Y to this option.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttySA0". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_MRST_MAX3110
- tristate "SPI UART driver for Max3110"
- depends on SPI_DW_PCI
- select SERIAL_CORE
- select SERIAL_CORE_CONSOLE
- help
- This is the UART protocol driver for the MAX3110 device on
- the Intel Moorestown platform. On other systems use the max3100
- driver.
-
-config SERIAL_MFD_HSU
- tristate "Medfield High Speed UART support"
- depends on PCI
- select SERIAL_CORE
-
-config SERIAL_MFD_HSU_CONSOLE
- boolean "Medfile HSU serial console support"
- depends on SERIAL_MFD_HSU=y
- select SERIAL_CORE_CONSOLE
-
-config SERIAL_BFIN
- tristate "Blackfin serial port support"
- depends on BLACKFIN
- select SERIAL_CORE
- select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561)
- help
- Add support for the built-in UARTs on the Blackfin.
-
- To compile this driver as a module, choose M here: the
- module will be called bfin_5xx.
-
-config SERIAL_BFIN_CONSOLE
- bool "Console on Blackfin serial port"
- depends on SERIAL_BFIN=y
- select SERIAL_CORE_CONSOLE
-
-choice
- prompt "UART Mode"
- depends on SERIAL_BFIN
- default SERIAL_BFIN_DMA
- help
- This driver supports the built-in serial ports of the Blackfin family
- of CPUs
-
-config SERIAL_BFIN_DMA
- bool "DMA mode"
- depends on !DMA_UNCACHED_NONE && KGDB_SERIAL_CONSOLE=n
- help
- This driver works under DMA mode. If this option is selected, the
- blackfin simple dma driver is also enabled.
-
-config SERIAL_BFIN_PIO
- bool "PIO mode"
- help
- This driver works under PIO mode.
-
-endchoice
-
-config SERIAL_BFIN_UART0
- bool "Enable UART0"
- depends on SERIAL_BFIN
- help
- Enable UART0
-
-config BFIN_UART0_CTSRTS
- bool "Enable UART0 hardware flow control"
- depends on SERIAL_BFIN_UART0
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_BFIN_UART1
- bool "Enable UART1"
- depends on SERIAL_BFIN && (!BF531 && !BF532 && !BF533 && !BF561)
- help
- Enable UART1
-
-config BFIN_UART1_CTSRTS
- bool "Enable UART1 hardware flow control"
- depends on SERIAL_BFIN_UART1
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_BFIN_UART2
- bool "Enable UART2"
- depends on SERIAL_BFIN && (BF54x || BF538 || BF539)
- help
- Enable UART2
-
-config BFIN_UART2_CTSRTS
- bool "Enable UART2 hardware flow control"
- depends on SERIAL_BFIN_UART2
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_BFIN_UART3
- bool "Enable UART3"
- depends on SERIAL_BFIN && (BF54x)
- help
- Enable UART3
-
-config BFIN_UART3_CTSRTS
- bool "Enable UART3 hardware flow control"
- depends on SERIAL_BFIN_UART3
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_IMX
- bool "IMX serial port support"
- depends on ARM && (ARCH_IMX || ARCH_MXC)
- select SERIAL_CORE
- select RATIONAL
- help
- If you have a machine based on a Motorola IMX CPU you
- can enable its onboard serial port by enabling this option.
-
-config SERIAL_IMX_CONSOLE
- bool "Console on IMX serial port"
- depends on SERIAL_IMX
- select SERIAL_CORE_CONSOLE
- help
- If you have enabled the serial port on the Motorola IMX
- CPU you can make it the console by answering Y to this option.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttySA0". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_UARTLITE
- tristate "Xilinx uartlite serial port support"
- depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE
- select SERIAL_CORE
- help
- Say Y here if you want to use the Xilinx uartlite serial controller.
-
- To compile this driver as a module, choose M here: the
- module will be called uartlite.
-
-config SERIAL_UARTLITE_CONSOLE
- bool "Support for console on Xilinx uartlite serial port"
- depends on SERIAL_UARTLITE=y
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you wish to use a Xilinx uartlite as the system
- console (the system console is the device which receives all kernel
- messages and warnings and which allows logins in single user mode).
-
-config SERIAL_SUNCORE
- bool
- depends on SPARC
- select SERIAL_CORE
- select SERIAL_CORE_CONSOLE
- default y
-
-config SERIAL_SUNZILOG
- tristate "Sun Zilog8530 serial support"
- depends on SPARC
- help
- This driver supports the Zilog8530 serial ports found on many Sparc
- systems. Say Y or M if you want to be able to these serial ports.
-
-config SERIAL_SUNZILOG_CONSOLE
- bool "Console on Sun Zilog8530 serial port"
- depends on SERIAL_SUNZILOG=y
- help
- If you would like to be able to use the Zilog8530 serial port
- on your Sparc system as the console, you can do so by answering
- Y to this option.
-
-config SERIAL_SUNSU
- tristate "Sun SU serial support"
- depends on SPARC && PCI
- help
- This driver supports the 8250 serial ports that run the keyboard and
- mouse on (PCI) UltraSPARC systems. Say Y or M if you want to be able
- to these serial ports.
-
-config SERIAL_SUNSU_CONSOLE
- bool "Console on Sun SU serial port"
- depends on SERIAL_SUNSU=y
- help
- If you would like to be able to use the SU serial port
- on your Sparc system as the console, you can do so by answering
- Y to this option.
-
-config SERIAL_MUX
- tristate "Serial MUX support"
- depends on GSC
- select SERIAL_CORE
- default y
- ---help---
- Saying Y here will enable the hardware MUX serial driver for
- the Nova, K class systems and D class with a 'remote control card'.
- The hardware MUX is not 8250/16550 compatible therefore the
- /dev/ttyB0 device is shared between the Serial MUX and the PDC
- software console. The following steps need to be completed to use
- the Serial MUX:
-
- 1. create the device entry (mknod /dev/ttyB0 c 11 0)
- 2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
- 3. Add device ttyB0 to /etc/securetty (if you want to log on as
- root on this console.)
- 4. Change the kernel command console parameter to: console=ttyB0
-
-config SERIAL_MUX_CONSOLE
- bool "Support for console on serial MUX"
- depends on SERIAL_MUX=y
- select SERIAL_CORE_CONSOLE
- default y
-
-config PDC_CONSOLE
- bool "PDC software console support"
- depends on PARISC && !SERIAL_MUX && VT
- default n
- help
- Saying Y here will enable the software based PDC console to be
- used as the system console. This is useful for machines in
- which the hardware based console has not been written yet. The
- following steps must be competed to use the PDC console:
-
- 1. create the device entry (mknod /dev/ttyB0 c 11 0)
- 2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
- 3. Add device ttyB0 to /etc/securetty (if you want to log on as
- root on this console.)
- 4. Change the kernel command console parameter to: console=ttyB0
-
-config SERIAL_SUNSAB
- tristate "Sun Siemens SAB82532 serial support"
- depends on SPARC && PCI
- help
- This driver supports the Siemens SAB82532 DUSCC serial ports on newer
- (PCI) UltraSPARC systems. Say Y or M if you want to be able to these
- serial ports.
-
-config SERIAL_SUNSAB_CONSOLE
- bool "Console on Sun Siemens SAB82532 serial port"
- depends on SERIAL_SUNSAB=y
- help
- If you would like to be able to use the SAB82532 serial port
- on your Sparc system as the console, you can do so by answering
- Y to this option.
-
-config SERIAL_SUNHV
- bool "Sun4v Hypervisor Console support"
- depends on SPARC64
- help
- This driver supports the console device found on SUN4V Sparc
- systems. Say Y if you want to be able to use this device.
-
-config SERIAL_IP22_ZILOG
- tristate "SGI Zilog8530 serial support"
- depends on SGI_HAS_ZILOG
- select SERIAL_CORE
- help
- This driver supports the Zilog8530 serial ports found on SGI
- systems. Say Y or M if you want to be able to these serial ports.
-
-config SERIAL_IP22_ZILOG_CONSOLE
- bool "Console on SGI Zilog8530 serial port"
- depends on SERIAL_IP22_ZILOG=y
- select SERIAL_CORE_CONSOLE
-
-config SERIAL_SH_SCI
- tristate "SuperH SCI(F) serial port support"
- depends on HAVE_CLK && (SUPERH || H8300 || ARCH_SHMOBILE)
- select SERIAL_CORE
-
-config SERIAL_SH_SCI_NR_UARTS
- int "Maximum number of SCI(F) serial ports"
- depends on SERIAL_SH_SCI
- default "2"
-
-config SERIAL_SH_SCI_CONSOLE
- bool "Support for console on SuperH SCI(F)"
- depends on SERIAL_SH_SCI=y
- select SERIAL_CORE_CONSOLE
-
-config SERIAL_SH_SCI_DMA
- bool "DMA support"
- depends on SERIAL_SH_SCI && SH_DMAE && EXPERIMENTAL
-
-config SERIAL_PNX8XXX
- bool "Enable PNX8XXX SoCs' UART Support"
- depends on MIPS && (SOC_PNX8550 || SOC_PNX833X)
- select SERIAL_CORE
- help
- If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
- and you want to use serial ports, say Y. Otherwise, say N.
-
-config SERIAL_PNX8XXX_CONSOLE
- bool "Enable PNX8XX0 serial console"
- depends on SERIAL_PNX8XXX
- select SERIAL_CORE_CONSOLE
- help
- If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
- and you want to use serial console, say Y. Otherwise, say N.
-
-config SERIAL_CORE
- tristate
-
-config SERIAL_CORE_CONSOLE
- bool
-
-config CONSOLE_POLL
- bool
-
-config SERIAL_68328
- bool "68328 serial support"
- depends on M68328 || M68EZ328 || M68VZ328
- help
- This driver supports the built-in serial port of the Motorola 68328
- (standard, EZ and VZ varieties).
-
-config SERIAL_68328_RTS_CTS
- bool "Support RTS/CTS on 68328 serial port"
- depends on SERIAL_68328
-
-config SERIAL_MCF
- bool "Coldfire serial support"
- depends on COLDFIRE
- select SERIAL_CORE
- help
- This serial driver supports the Freescale Coldfire serial ports.
-
-config SERIAL_MCF_BAUDRATE
- int "Default baudrate for Coldfire serial ports"
- depends on SERIAL_MCF
- default 19200
- help
- This setting lets you define what the default baudrate is for the
- ColdFire serial ports. The usual default varies from board to board,
- and this setting is a way of catering for that.
-
-config SERIAL_MCF_CONSOLE
- bool "Coldfire serial console support"
- depends on SERIAL_MCF
- select SERIAL_CORE_CONSOLE
- help
- Enable a ColdFire internal serial port to be the system console.
-
-config SERIAL_68360_SMC
- bool "68360 SMC uart support"
- depends on M68360
- help
- This driver supports the SMC serial ports of the Motorola 68360 CPU.
-
-config SERIAL_68360_SCC
- bool "68360 SCC uart support"
- depends on M68360
- help
- This driver supports the SCC serial ports of the Motorola 68360 CPU.
-
-config SERIAL_68360
- bool
- depends on SERIAL_68360_SMC || SERIAL_68360_SCC
- default y
-
-config SERIAL_PMACZILOG
- tristate "Mac or PowerMac z85c30 ESCC support"
- depends on (M68K && MAC) || (PPC_OF && PPC_PMAC)
- select SERIAL_CORE
- help
- This driver supports the Zilog z85C30 serial ports found on
- (Power)Mac machines.
- Say Y or M if you want to be able to these serial ports.
-
-config SERIAL_PMACZILOG_TTYS
- bool "Use ttySn device nodes for Zilog z85c30"
- depends on SERIAL_PMACZILOG
- help
- The pmac_zilog driver for the z85C30 chip on many powermacs
- historically used the device numbers for /dev/ttySn. The
- 8250 serial port driver also uses these numbers, which means
- the two drivers being unable to coexist; you could not use
- both z85C30 and 8250 type ports at the same time.
-
- If this option is not selected, the pmac_zilog driver will
- use the device numbers allocated for /dev/ttyPZn. This allows
- the pmac_zilog and 8250 drivers to co-exist, but may cause
- existing userspace setups to break. Programs that need to
- access the built-in serial ports on powermacs will need to
- be reconfigured to use /dev/ttyPZn instead of /dev/ttySn.
-
- If you enable this option, any z85c30 ports in the system will
- be registered as ttyS0 onwards as in the past, and you will be
- unable to use the 8250 module for PCMCIA or other 16C550-style
- UARTs.
-
- Say N unless you need the z85c30 ports on your (Power)Mac
- to appear as /dev/ttySn.
-
-config SERIAL_PMACZILOG_CONSOLE
- bool "Console on Mac or PowerMac z85c30 serial port"
- depends on SERIAL_PMACZILOG=y
- select SERIAL_CORE_CONSOLE
- help
- If you would like to be able to use the z85c30 serial port
- on your (Power)Mac as the console, you can do so by answering
- Y to this option.
-
-config SERIAL_LH7A40X
- tristate "Sharp LH7A40X embedded UART support"
- depends on ARM && ARCH_LH7A40X
- select SERIAL_CORE
- help
- This enables support for the three on-board UARTs of the
- Sharp LH7A40X series CPUs. Choose Y or M.
-
-config SERIAL_LH7A40X_CONSOLE
- bool "Support for console on Sharp LH7A40X serial port"
- depends on SERIAL_LH7A40X=y
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you wish to use one of the serial ports as the
- system console--the system console is the device which
- receives all kernel messages and warnings and which allows
- logins in single user mode.
-
- Even if you say Y here, the currently visible framebuffer console
- (/dev/tty0) will still be used as the default system console, but
- you can alter that using a kernel command line, for example
- "console=ttyAM1".
-
-config SERIAL_CPM
- tristate "CPM SCC/SMC serial port support"
- depends on CPM2 || 8xx
- select SERIAL_CORE
- help
- This driver supports the SCC and SMC serial ports on Motorola
- embedded PowerPC that contain a CPM1 (8xx) or CPM2 (8xxx)
-
-config SERIAL_CPM_CONSOLE
- bool "Support for console on CPM SCC/SMC serial port"
- depends on SERIAL_CPM=y
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you wish to use a SCC or SMC CPM UART as the system
- console (the system console is the device which receives all kernel
- messages and warnings and which allows logins in single user mode).
-
- Even if you say Y here, the currently visible framebuffer console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyCPM0". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-config SERIAL_SGI_L1_CONSOLE
- bool "SGI Altix L1 serial console support"
- depends on IA64_GENERIC || IA64_SGI_SN2
- select SERIAL_CORE
- select SERIAL_CORE_CONSOLE
- help
- If you have an SGI Altix and you would like to use the system
- controller serial port as your console (you want this!),
- say Y. Otherwise, say N.
-
-config SERIAL_MPC52xx
- tristate "Freescale MPC52xx/MPC512x family PSC serial support"
- depends on PPC_MPC52xx || PPC_MPC512x
- select SERIAL_CORE
- help
- This driver supports MPC52xx and MPC512x PSC serial ports. If you would
- like to use them, you must answer Y or M to this option. Note that
- for use as console, it must be included in kernel and not as a
- module.
-
-config SERIAL_MPC52xx_CONSOLE
- bool "Console on a Freescale MPC52xx/MPC512x family PSC serial port"
- depends on SERIAL_MPC52xx=y
- select SERIAL_CORE_CONSOLE
- help
- Select this options if you'd like to use one of the PSC serial port
- of the Freescale MPC52xx family as a console.
-
-config SERIAL_MPC52xx_CONSOLE_BAUD
- int "Freescale MPC52xx/MPC512x family PSC serial port baud"
- depends on SERIAL_MPC52xx_CONSOLE=y
- default "9600"
- help
- Select the MPC52xx console baud rate.
- This value is only used if the bootloader doesn't pass in the
- console baudrate
-
-config SERIAL_ICOM
- tristate "IBM Multiport Serial Adapter"
- depends on PCI && (PPC_ISERIES || PPC_PSERIES)
- select SERIAL_CORE
- select FW_LOADER
- help
- This driver is for a family of multiport serial adapters
- including 2 port RVX, 2 port internal modem, 4 port internal
- modem and a split 1 port RVX and 1 port internal modem.
-
- This driver can also be built as a module. If so, the module
- will be called icom.
-
-config SERIAL_M32R_SIO
- bool "M32R SIO I/F"
- depends on M32R
- default y
- select SERIAL_CORE
- help
- Say Y here if you want to use the M32R serial controller.
-
-config SERIAL_M32R_SIO_CONSOLE
- bool "use SIO console"
- depends on SERIAL_M32R_SIO=y
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you want to support a serial console.
-
- If you use an M3T-M32700UT or an OPSPUT platform,
- please say also y for SERIAL_M32R_PLDSIO.
-
-config SERIAL_M32R_PLDSIO
- bool "M32R SIO I/F on a PLD"
- depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PLAT_USRV || PLAT_M32700UT)
- default n
- help
- Say Y here if you want to use the M32R serial controller
- on a PLD (Programmable Logic Device).
-
- If you use an M3T-M32700UT or an OPSPUT platform,
- please say Y.
-
-config SERIAL_TXX9
- bool "TMPTX39XX/49XX SIO support"
- depends on HAS_TXX9_SERIAL
- select SERIAL_CORE
- default y
-
-config HAS_TXX9_SERIAL
- bool
-
-config SERIAL_TXX9_NR_UARTS
- int "Maximum number of TMPTX39XX/49XX SIO ports"
- depends on SERIAL_TXX9
- default "6"
-
-config SERIAL_TXX9_CONSOLE
- bool "TMPTX39XX/49XX SIO Console support"
- depends on SERIAL_TXX9=y
- select SERIAL_CORE_CONSOLE
-
-config SERIAL_TXX9_STDSERIAL
- bool "TX39XX/49XX SIO act as standard serial"
- depends on !SERIAL_8250 && SERIAL_TXX9
-
-config SERIAL_VR41XX
- tristate "NEC VR4100 series Serial Interface Unit support"
- depends on CPU_VR41XX
- select SERIAL_CORE
- help
- If you have a NEC VR4100 series processor and you want to use
- Serial Interface Unit(SIU) or Debug Serial Interface Unit(DSIU)
- (not include VR4111/VR4121 DSIU), say Y. Otherwise, say N.
-
-config SERIAL_VR41XX_CONSOLE
- bool "Enable NEC VR4100 series Serial Interface Unit console"
- depends on SERIAL_VR41XX=y
- select SERIAL_CORE_CONSOLE
- help
- If you have a NEC VR4100 series processor and you want to use
- a console on a serial port, say Y. Otherwise, say N.
-
-config SERIAL_JSM
- tristate "Digi International NEO PCI Support"
- depends on PCI
- select SERIAL_CORE
- help
- This is a driver for Digi International's Neo series
- of cards which provide multiple serial ports. You would need
- something like this to connect more than two modems to your Linux
- box, for instance in order to become a dial-in server. This driver
- supports PCI boards only.
-
- If you have a card like this, say Y here, otherwise say N.
-
- To compile this driver as a module, choose M here: the
- module will be called jsm.
-
-config SERIAL_SGI_IOC4
- tristate "SGI IOC4 controller serial support"
- depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC4
- select SERIAL_CORE
- help
- If you have an SGI Altix with an IOC4 based Base IO card
- and wish to use the serial ports on this card, say Y.
- Otherwise, say N.
-
-config SERIAL_SGI_IOC3
- tristate "SGI Altix IOC3 serial support"
- depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3
- select SERIAL_CORE
- help
- If you have an SGI Altix with an IOC3 serial card,
- say Y or M. Otherwise, say N.
-
-config SERIAL_MSM
- bool "MSM on-chip serial port support"
- depends on ARM && ARCH_MSM
- select SERIAL_CORE
-
-config SERIAL_MSM_CONSOLE
- bool "MSM serial console support"
- depends on SERIAL_MSM=y
- select SERIAL_CORE_CONSOLE
-
-config SERIAL_VT8500
- bool "VIA VT8500 on-chip serial port support"
- depends on ARM && ARCH_VT8500
- select SERIAL_CORE
-
-config SERIAL_VT8500_CONSOLE
- bool "VIA VT8500 serial console support"
- depends on SERIAL_VT8500=y
- select SERIAL_CORE_CONSOLE
-
-config SERIAL_NETX
- tristate "NetX serial port support"
- depends on ARM && ARCH_NETX
- select SERIAL_CORE
- help
- If you have a machine based on a Hilscher NetX SoC you
- can enable its onboard serial port by enabling this option.
-
- To compile this driver as a module, choose M here: the
- module will be called netx-serial.
-
-config SERIAL_NETX_CONSOLE
- bool "Console on NetX serial port"
- depends on SERIAL_NETX=y
- select SERIAL_CORE_CONSOLE
- help
- If you have enabled the serial port on the Hilscher NetX SoC
- you can make it the console by answering Y to this option.
-
-config SERIAL_OF_PLATFORM
- tristate "Serial port on Open Firmware platform bus"
- depends on OF
- depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
- help
- If you have a PowerPC based system that has serial ports
- on a platform specific bus, you should enable this option.
- Currently, only 8250 compatible ports are supported, but
- others can easily be added.
-
-config SERIAL_OMAP
- tristate "OMAP serial port support"
- depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4
- select SERIAL_CORE
- help
- If you have a machine based on an Texas Instruments OMAP CPU you
- can enable its onboard serial ports by enabling this option.
-
- By enabling this option you take advantage of dma feature available
- with the omap-serial driver. DMA support can be enabled from platform
- data.
-
-config SERIAL_OMAP_CONSOLE
- bool "Console on OMAP serial port"
- depends on SERIAL_OMAP
- select SERIAL_CORE_CONSOLE
- help
- Select this option if you would like to use omap serial port as
- console.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyOx". (Try "man bootparam" or see the documentation of
- your boot loader about how to pass options to the kernel at
- boot time.)
-
-config SERIAL_OF_PLATFORM_NWPSERIAL
- tristate "NWP serial port driver"
- depends on PPC_OF && PPC_DCR
- select SERIAL_OF_PLATFORM
- select SERIAL_CORE_CONSOLE
- select SERIAL_CORE
- help
- This driver supports the cell network processor nwp serial
- device.
-
-config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
- bool "Console on NWP serial port"
- depends on SERIAL_OF_PLATFORM_NWPSERIAL=y
- select SERIAL_CORE_CONSOLE
- help
- Support for Console on the NWP serial ports.
-
-config SERIAL_QE
- tristate "Freescale QUICC Engine serial port support"
- depends on QUICC_ENGINE
- select SERIAL_CORE
- select FW_LOADER
- default n
- help
- This driver supports the QE serial ports on Freescale embedded
- PowerPC that contain a QUICC Engine.
-
-config SERIAL_SC26XX
- tristate "SC2681/SC2692 serial port support"
- depends on SNI_RM
- select SERIAL_CORE
- help
- This is a driver for the onboard serial ports of
- older RM400 machines.
-
-config SERIAL_SC26XX_CONSOLE
- bool "Console on SC2681/SC2692 serial port"
- depends on SERIAL_SC26XX
- select SERIAL_CORE_CONSOLE
- help
- Support for Console on SC2681/SC2692 serial ports.
-
-config SERIAL_BFIN_SPORT
- tristate "Blackfin SPORT emulate UART"
- depends on BLACKFIN
- select SERIAL_CORE
- help
- Enable SPORT emulate UART on Blackfin series.
-
- To compile this driver as a module, choose M here: the
- module will be called bfin_sport_uart.
-
-config SERIAL_BFIN_SPORT_CONSOLE
- bool "Console on Blackfin sport emulated uart"
- depends on SERIAL_BFIN_SPORT=y
- select SERIAL_CORE_CONSOLE
-
-config SERIAL_BFIN_SPORT0_UART
- bool "Enable UART over SPORT0"
- depends on SERIAL_BFIN_SPORT && !(BF542 || BF544)
- help
- Enable UART over SPORT0
-
-config SERIAL_BFIN_SPORT0_UART_CTSRTS
- bool "Enable UART over SPORT0 hardware flow control"
- depends on SERIAL_BFIN_SPORT0_UART
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_BFIN_SPORT1_UART
- bool "Enable UART over SPORT1"
- depends on SERIAL_BFIN_SPORT
- help
- Enable UART over SPORT1
-
-config SERIAL_BFIN_SPORT1_UART_CTSRTS
- bool "Enable UART over SPORT1 hardware flow control"
- depends on SERIAL_BFIN_SPORT1_UART
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_BFIN_SPORT2_UART
- bool "Enable UART over SPORT2"
- depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
- help
- Enable UART over SPORT2
-
-config SERIAL_BFIN_SPORT2_UART_CTSRTS
- bool "Enable UART over SPORT2 hardware flow control"
- depends on SERIAL_BFIN_SPORT2_UART
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_BFIN_SPORT3_UART
- bool "Enable UART over SPORT3"
- depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
- help
- Enable UART over SPORT3
-
-config SERIAL_BFIN_SPORT3_UART_CTSRTS
- bool "Enable UART over SPORT3 hardware flow control"
- depends on SERIAL_BFIN_SPORT3_UART
- help
- Enable hardware flow control in the driver.
-
-config SERIAL_TIMBERDALE
- tristate "Support for timberdale UART"
- select SERIAL_CORE
- ---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.
-
-config SERIAL_GRLIB_GAISLER_APBUART
- tristate "GRLIB APBUART serial support"
- depends on OF
- ---help---
- Add support for the GRLIB APBUART serial port.
-
-config SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
- bool "Console on GRLIB APBUART serial port"
- depends on SERIAL_GRLIB_GAISLER_APBUART=y
- select SERIAL_CORE_CONSOLE
- help
- Support for running a console on the GRLIB APBUART
-
-config SERIAL_ALTERA_JTAGUART
- tristate "Altera JTAG UART support"
- select SERIAL_CORE
- help
- This driver supports the Altera JTAG UART port.
-
-config SERIAL_ALTERA_JTAGUART_CONSOLE
- bool "Altera JTAG UART console support"
- depends on SERIAL_ALTERA_JTAGUART=y
- select SERIAL_CORE_CONSOLE
- help
- Enable a Altera JTAG UART port to be the system console.
-
-config SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS
- bool "Bypass output when no connection"
- depends on SERIAL_ALTERA_JTAGUART_CONSOLE
- select SERIAL_CORE_CONSOLE
- help
- Bypass console output and keep going even if there is no
- JTAG terminal connection with the host.
-
-config SERIAL_ALTERA_UART
- tristate "Altera UART support"
- select SERIAL_CORE
- help
- This driver supports the Altera softcore UART port.
-
-config SERIAL_ALTERA_UART_MAXPORTS
- int "Maximum number of Altera UART ports"
- depends on SERIAL_ALTERA_UART
- default 4
- help
- This setting lets you define the maximum number of the Altera
- UART ports. The usual default varies from board to board, and
- this setting is a way of catering for that.
-
-config SERIAL_ALTERA_UART_BAUDRATE
- int "Default baudrate for Altera UART ports"
- depends on SERIAL_ALTERA_UART
- default 115200
- help
- This setting lets you define what the default baudrate is for the
- Altera UART ports. The usual default varies from board to board,
- and this setting is a way of catering for that.
-
-config SERIAL_ALTERA_UART_CONSOLE
- bool "Altera UART console support"
- depends on SERIAL_ALTERA_UART=y
- select SERIAL_CORE_CONSOLE
- help
- Enable a Altera UART port to be the system console.
-
-config SERIAL_IFX6X60
- tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
- depends on GPIOLIB && SPI && EXPERIMENTAL
- help
- Support for the IFX6x60 modem devices on Intel MID platforms.
-
-config SERIAL_PCH_UART
- tristate "Intel EG20T PCH UART"
- depends on PCI && DMADEVICES
- select SERIAL_CORE
- select PCH_DMA
- help
- This driver is for PCH(Platform controller Hub) UART of Intel EG20T
- which is an IOH(Input/Output Hub) for x86 embedded processor.
- Enabling PCH_DMA, this PCH UART works as DMA mode.
-endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
deleted file mode 100644
index 8ea92e9c73b0..000000000000
--- a/drivers/serial/Makefile
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# Makefile for the kernel serial device drivers.
-#
-
-obj-$(CONFIG_SERIAL_CORE) += serial_core.o
-obj-$(CONFIG_SERIAL_21285) += 21285.o
-
-# These Sparc drivers have to appear before others such as 8250
-# which share ttySx minor node space. Otherwise console device
-# names change and other unplesantries.
-obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
-obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
-obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
-obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
-obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
-
-obj-$(CONFIG_SERIAL_8250) += 8250.o
-obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
-obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
-obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
-obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
-obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
-obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
-obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
-obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
-obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
-obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
-obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
-obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
-obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
-obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
-obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
-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
-obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o
-obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
-obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
-obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
-obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
-obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
-obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
-obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
-obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
-obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o
-obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
-obj-$(CONFIG_SERIAL_MUX) += mux.o
-obj-$(CONFIG_SERIAL_68328) += 68328serial.o
-obj-$(CONFIG_SERIAL_68360) += 68360serial.o
-obj-$(CONFIG_SERIAL_MCF) += mcf.o
-obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
-obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
-obj-$(CONFIG_SERIAL_DZ) += dz.o
-obj-$(CONFIG_SERIAL_ZS) += zs.o
-obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
-obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o
-obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
-obj-$(CONFIG_SERIAL_IMX) += imx.o
-obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
-obj-$(CONFIG_SERIAL_ICOM) += icom.o
-obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
-obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
-obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
-obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
-obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
-obj-$(CONFIG_SERIAL_JSM) += jsm/
-obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
-obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
-obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
-obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
-obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
-obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
-obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
-obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
-obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
-obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
-obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
-obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
-obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
-obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
-obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
-obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
-obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
-obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
-obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
-obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
-obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
-obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o
-obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
diff --git a/drivers/serial/altera_jtaguart.c b/drivers/serial/altera_jtaguart.c
deleted file mode 100644
index f9b49b5ff5e1..000000000000
--- a/drivers/serial/altera_jtaguart.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * altera_jtaguart.c -- Altera JTAG UART driver
- *
- * Based on mcf.c -- Freescale ColdFire UART driver
- *
- * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
- * (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
- * (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/altera_jtaguart.h>
-
-#define DRV_NAME "altera_jtaguart"
-
-/*
- * Altera JTAG UART register definitions according to the Altera JTAG UART
- * datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
- */
-
-#define ALTERA_JTAGUART_SIZE 8
-
-#define ALTERA_JTAGUART_DATA_REG 0
-
-#define ALTERA_JTAGUART_DATA_DATA_MSK 0x000000FF
-#define ALTERA_JTAGUART_DATA_RVALID_MSK 0x00008000
-#define ALTERA_JTAGUART_DATA_RAVAIL_MSK 0xFFFF0000
-#define ALTERA_JTAGUART_DATA_RAVAIL_OFF 16
-
-#define ALTERA_JTAGUART_CONTROL_REG 4
-
-#define ALTERA_JTAGUART_CONTROL_RE_MSK 0x00000001
-#define ALTERA_JTAGUART_CONTROL_WE_MSK 0x00000002
-#define ALTERA_JTAGUART_CONTROL_RI_MSK 0x00000100
-#define ALTERA_JTAGUART_CONTROL_RI_OFF 8
-#define ALTERA_JTAGUART_CONTROL_WI_MSK 0x00000200
-#define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400
-#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000
-#define ALTERA_JTAGUART_CONTROL_WSPACE_OFF 16
-
-/*
- * Local per-uart structure.
- */
-struct altera_jtaguart {
- struct uart_port port;
- unsigned int sigs; /* Local copy of line sigs */
- unsigned long imr; /* Local IMR mirror */
-};
-
-static unsigned int altera_jtaguart_tx_empty(struct uart_port *port)
-{
- return (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int altera_jtaguart_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-}
-
-static void altera_jtaguart_set_mctrl(struct uart_port *port, unsigned int sigs)
-{
-}
-
-static void altera_jtaguart_start_tx(struct uart_port *port)
-{
- struct altera_jtaguart *pp =
- container_of(port, struct altera_jtaguart, port);
-
- pp->imr |= ALTERA_JTAGUART_CONTROL_WE_MSK;
- writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
-}
-
-static void altera_jtaguart_stop_tx(struct uart_port *port)
-{
- struct altera_jtaguart *pp =
- container_of(port, struct altera_jtaguart, port);
-
- pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
- writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
-}
-
-static void altera_jtaguart_stop_rx(struct uart_port *port)
-{
- struct altera_jtaguart *pp =
- container_of(port, struct altera_jtaguart, port);
-
- pp->imr &= ~ALTERA_JTAGUART_CONTROL_RE_MSK;
- writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
-}
-
-static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
-{
-}
-
-static void altera_jtaguart_enable_ms(struct uart_port *port)
-{
-}
-
-static void altera_jtaguart_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- /* Just copy the old termios settings back */
- if (old)
- tty_termios_copy_hw(termios, old);
-}
-
-static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
-{
- struct uart_port *port = &pp->port;
- unsigned char ch, flag;
- unsigned long status;
-
- while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) &
- ALTERA_JTAGUART_DATA_RVALID_MSK) {
- ch = status & ALTERA_JTAGUART_DATA_DATA_MSK;
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- if (uart_handle_sysrq_char(port, ch))
- continue;
- uart_insert_char(port, 0, 0, ch, flag);
- }
-
- tty_flip_buffer_push(port->state->port.tty);
-}
-
-static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
-{
- struct uart_port *port = &pp->port;
- struct circ_buf *xmit = &port->state->xmit;
- unsigned int pending, count;
-
- if (port->x_char) {
- /* Send special char - probably flow control */
- writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG);
- port->x_char = 0;
- port->icount.tx++;
- return;
- }
-
- pending = uart_circ_chars_pending(xmit);
- if (pending > 0) {
- count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) >>
- ALTERA_JTAGUART_CONTROL_WSPACE_OFF;
- if (count > pending)
- count = pending;
- if (count > 0) {
- pending -= count;
- while (count--) {
- writel(xmit->buf[xmit->tail],
- port->membase + ALTERA_JTAGUART_DATA_REG);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
- if (pending < WAKEUP_CHARS)
- uart_write_wakeup(port);
- }
- }
-
- if (pending == 0) {
- pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
- writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
- }
-}
-
-static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
-{
- struct uart_port *port = data;
- struct altera_jtaguart *pp =
- container_of(port, struct altera_jtaguart, port);
- unsigned int isr;
-
- isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >>
- ALTERA_JTAGUART_CONTROL_RI_OFF) & pp->imr;
-
- spin_lock(&port->lock);
-
- if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK)
- altera_jtaguart_rx_chars(pp);
- if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK)
- altera_jtaguart_tx_chars(pp);
-
- spin_unlock(&port->lock);
-
- return IRQ_RETVAL(isr);
-}
-
-static void altera_jtaguart_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_ALTERA_JTAGUART;
-
- /* Clear mask, so no surprise interrupts. */
- writel(0, port->membase + ALTERA_JTAGUART_CONTROL_REG);
-}
-
-static int altera_jtaguart_startup(struct uart_port *port)
-{
- struct altera_jtaguart *pp =
- container_of(port, struct altera_jtaguart, port);
- unsigned long flags;
- int ret;
-
- ret = request_irq(port->irq, altera_jtaguart_interrupt, IRQF_DISABLED,
- DRV_NAME, port);
- if (ret) {
- pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
- "interrupt vector=%d\n", port->line, port->irq);
- return ret;
- }
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Enable RX interrupts now */
- pp->imr = ALTERA_JTAGUART_CONTROL_RE_MSK;
- writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- return 0;
-}
-
-static void altera_jtaguart_shutdown(struct uart_port *port)
-{
- struct altera_jtaguart *pp =
- container_of(port, struct altera_jtaguart, port);
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Disable all interrupts now */
- pp->imr = 0;
- writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- free_irq(port->irq, port);
-}
-
-static const char *altera_jtaguart_type(struct uart_port *port)
-{
- return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL;
-}
-
-static int altera_jtaguart_request_port(struct uart_port *port)
-{
- /* UARTs always present */
- return 0;
-}
-
-static void altera_jtaguart_release_port(struct uart_port *port)
-{
- /* Nothing to release... */
-}
-
-static int altera_jtaguart_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART)
- return -EINVAL;
- return 0;
-}
-
-/*
- * Define the basic serial functions we support.
- */
-static struct uart_ops altera_jtaguart_ops = {
- .tx_empty = altera_jtaguart_tx_empty,
- .get_mctrl = altera_jtaguart_get_mctrl,
- .set_mctrl = altera_jtaguart_set_mctrl,
- .start_tx = altera_jtaguart_start_tx,
- .stop_tx = altera_jtaguart_stop_tx,
- .stop_rx = altera_jtaguart_stop_rx,
- .enable_ms = altera_jtaguart_enable_ms,
- .break_ctl = altera_jtaguart_break_ctl,
- .startup = altera_jtaguart_startup,
- .shutdown = altera_jtaguart_shutdown,
- .set_termios = altera_jtaguart_set_termios,
- .type = altera_jtaguart_type,
- .request_port = altera_jtaguart_request_port,
- .release_port = altera_jtaguart_release_port,
- .config_port = altera_jtaguart_config_port,
- .verify_port = altera_jtaguart_verify_port,
-};
-
-#define ALTERA_JTAGUART_MAXPORTS 1
-static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
-
-#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
-
-int __init early_altera_jtaguart_setup(struct altera_jtaguart_platform_uart
- *platp)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
- port = &altera_jtaguart_ports[i].port;
-
- port->line = i;
- port->type = PORT_ALTERA_JTAGUART;
- port->mapbase = platp[i].mapbase;
- port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
- port->iotype = SERIAL_IO_MEM;
- port->irq = platp[i].irq;
- port->flags = ASYNC_BOOT_AUTOCONF;
- port->ops = &altera_jtaguart_ops;
- }
-
- return 0;
-}
-
-#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
-static void altera_jtaguart_console_putc(struct console *co, const char c)
-{
- struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
- unsigned long status;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
- if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
- spin_unlock_irqrestore(&port->lock, flags);
- return; /* no connection activity */
- }
- spin_unlock_irqrestore(&port->lock, flags);
- cpu_relax();
- spin_lock_irqsave(&port->lock, flags);
- }
- writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-#else
-static void altera_jtaguart_console_putc(struct console *co, const char c)
-{
- struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
- spin_unlock_irqrestore(&port->lock, flags);
- cpu_relax();
- spin_lock_irqsave(&port->lock, flags);
- }
- writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-#endif
-
-static void altera_jtaguart_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- for (; count; count--, s++) {
- altera_jtaguart_console_putc(co, *s);
- if (*s == '\n')
- altera_jtaguart_console_putc(co, '\r');
- }
-}
-
-static int __init altera_jtaguart_console_setup(struct console *co,
- char *options)
-{
- struct uart_port *port;
-
- if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS)
- return -EINVAL;
- port = &altera_jtaguart_ports[co->index].port;
- if (port->membase == 0)
- return -ENODEV;
- return 0;
-}
-
-static struct uart_driver altera_jtaguart_driver;
-
-static struct console altera_jtaguart_console = {
- .name = "ttyJ",
- .write = altera_jtaguart_console_write,
- .device = uart_console_device,
- .setup = altera_jtaguart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &altera_jtaguart_driver,
-};
-
-static int __init altera_jtaguart_console_init(void)
-{
- register_console(&altera_jtaguart_console);
- return 0;
-}
-
-console_initcall(altera_jtaguart_console_init);
-
-#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
-
-#else
-
-#define ALTERA_JTAGUART_CONSOLE NULL
-
-#endif /* CONFIG_ALTERA_JTAGUART_CONSOLE */
-
-static struct uart_driver altera_jtaguart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "altera_jtaguart",
- .dev_name = "ttyJ",
- .major = ALTERA_JTAGUART_MAJOR,
- .minor = ALTERA_JTAGUART_MINOR,
- .nr = ALTERA_JTAGUART_MAXPORTS,
- .cons = ALTERA_JTAGUART_CONSOLE,
-};
-
-static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
-{
- struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
- struct uart_port *port;
- int i;
-
- for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
- port = &altera_jtaguart_ports[i].port;
-
- port->line = i;
- port->type = PORT_ALTERA_JTAGUART;
- port->mapbase = platp[i].mapbase;
- port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
- port->iotype = SERIAL_IO_MEM;
- port->irq = platp[i].irq;
- port->ops = &altera_jtaguart_ops;
- port->flags = ASYNC_BOOT_AUTOCONF;
-
- uart_add_one_port(&altera_jtaguart_driver, port);
- }
-
- return 0;
-}
-
-static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; i < ALTERA_JTAGUART_MAXPORTS; i++) {
- port = &altera_jtaguart_ports[i].port;
- if (port)
- uart_remove_one_port(&altera_jtaguart_driver, port);
- }
-
- return 0;
-}
-
-static struct platform_driver altera_jtaguart_platform_driver = {
- .probe = altera_jtaguart_probe,
- .remove = __devexit_p(altera_jtaguart_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init altera_jtaguart_init(void)
-{
- int rc;
-
- rc = uart_register_driver(&altera_jtaguart_driver);
- if (rc)
- return rc;
- rc = platform_driver_register(&altera_jtaguart_platform_driver);
- if (rc) {
- uart_unregister_driver(&altera_jtaguart_driver);
- return rc;
- }
- return 0;
-}
-
-static void __exit altera_jtaguart_exit(void)
-{
- platform_driver_unregister(&altera_jtaguart_platform_driver);
- uart_unregister_driver(&altera_jtaguart_driver);
-}
-
-module_init(altera_jtaguart_init);
-module_exit(altera_jtaguart_exit);
-
-MODULE_DESCRIPTION("Altera JTAG UART driver");
-MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
deleted file mode 100644
index 721216292a50..000000000000
--- a/drivers/serial/altera_uart.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- * altera_uart.c -- Altera UART driver
- *
- * Based on mcf.c -- Freescale ColdFire UART driver
- *
- * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
- * (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
- * (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/altera_uart.h>
-
-#define DRV_NAME "altera_uart"
-#define SERIAL_ALTERA_MAJOR 204
-#define SERIAL_ALTERA_MINOR 213
-
-/*
- * Altera UART register definitions according to the Nios UART datasheet:
- * http://www.altera.com/literature/ds/ds_nios_uart.pdf
- */
-
-#define ALTERA_UART_SIZE 32
-
-#define ALTERA_UART_RXDATA_REG 0
-#define ALTERA_UART_TXDATA_REG 4
-#define ALTERA_UART_STATUS_REG 8
-#define ALTERA_UART_CONTROL_REG 12
-#define ALTERA_UART_DIVISOR_REG 16
-#define ALTERA_UART_EOP_REG 20
-
-#define ALTERA_UART_STATUS_PE_MSK 0x0001 /* parity error */
-#define ALTERA_UART_STATUS_FE_MSK 0x0002 /* framing error */
-#define ALTERA_UART_STATUS_BRK_MSK 0x0004 /* break */
-#define ALTERA_UART_STATUS_ROE_MSK 0x0008 /* RX overrun error */
-#define ALTERA_UART_STATUS_TOE_MSK 0x0010 /* TX overrun error */
-#define ALTERA_UART_STATUS_TMT_MSK 0x0020 /* TX shift register state */
-#define ALTERA_UART_STATUS_TRDY_MSK 0x0040 /* TX ready */
-#define ALTERA_UART_STATUS_RRDY_MSK 0x0080 /* RX ready */
-#define ALTERA_UART_STATUS_E_MSK 0x0100 /* exception condition */
-#define ALTERA_UART_STATUS_DCTS_MSK 0x0400 /* CTS logic-level change */
-#define ALTERA_UART_STATUS_CTS_MSK 0x0800 /* CTS logic state */
-#define ALTERA_UART_STATUS_EOP_MSK 0x1000 /* EOP written/read */
-
- /* Enable interrupt on... */
-#define ALTERA_UART_CONTROL_PE_MSK 0x0001 /* ...parity error */
-#define ALTERA_UART_CONTROL_FE_MSK 0x0002 /* ...framing error */
-#define ALTERA_UART_CONTROL_BRK_MSK 0x0004 /* ...break */
-#define ALTERA_UART_CONTROL_ROE_MSK 0x0008 /* ...RX overrun */
-#define ALTERA_UART_CONTROL_TOE_MSK 0x0010 /* ...TX overrun */
-#define ALTERA_UART_CONTROL_TMT_MSK 0x0020 /* ...TX shift register empty */
-#define ALTERA_UART_CONTROL_TRDY_MSK 0x0040 /* ...TX ready */
-#define ALTERA_UART_CONTROL_RRDY_MSK 0x0080 /* ...RX ready */
-#define ALTERA_UART_CONTROL_E_MSK 0x0100 /* ...exception*/
-
-#define ALTERA_UART_CONTROL_TRBK_MSK 0x0200 /* TX break */
-#define ALTERA_UART_CONTROL_DCTS_MSK 0x0400 /* Interrupt on CTS change */
-#define ALTERA_UART_CONTROL_RTS_MSK 0x0800 /* RTS signal */
-#define ALTERA_UART_CONTROL_EOP_MSK 0x1000 /* Interrupt on EOP */
-
-/*
- * Local per-uart structure.
- */
-struct altera_uart {
- struct uart_port port;
- struct timer_list tmr;
- unsigned int sigs; /* Local copy of line sigs */
- unsigned short imr; /* Local IMR mirror */
-};
-
-static u32 altera_uart_readl(struct uart_port *port, int reg)
-{
- struct altera_uart_platform_uart *platp = port->private_data;
-
- return readl(port->membase + (reg << platp->bus_shift));
-}
-
-static void altera_uart_writel(struct uart_port *port, u32 dat, int reg)
-{
- struct altera_uart_platform_uart *platp = port->private_data;
-
- writel(dat, port->membase + (reg << platp->bus_shift));
-}
-
-static unsigned int altera_uart_tx_empty(struct uart_port *port)
-{
- return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
- ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int altera_uart_get_mctrl(struct uart_port *port)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned int sigs;
-
- sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
- ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
- sigs |= (pp->sigs & TIOCM_RTS);
-
- return sigs;
-}
-
-static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
-
- pp->sigs = sigs;
- if (sigs & TIOCM_RTS)
- pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
- else
- pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
- altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
-}
-
-static void altera_uart_start_tx(struct uart_port *port)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
-
- pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
- altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
-}
-
-static void altera_uart_stop_tx(struct uart_port *port)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
-
- pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
- altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
-}
-
-static void altera_uart_stop_rx(struct uart_port *port)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
-
- pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
- altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
-}
-
-static void altera_uart_break_ctl(struct uart_port *port, int break_state)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- if (break_state == -1)
- pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
- else
- pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
- altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void altera_uart_enable_ms(struct uart_port *port)
-{
-}
-
-static void altera_uart_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned long flags;
- unsigned int baud, baudclk;
-
- baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
- baudclk = port->uartclk / baud;
-
- if (old)
- tty_termios_copy_hw(termios, old);
- tty_termios_encode_baud_rate(termios, baud, baud);
-
- spin_lock_irqsave(&port->lock, flags);
- uart_update_timeout(port, termios->c_cflag, baud);
- altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void altera_uart_rx_chars(struct altera_uart *pp)
-{
- struct uart_port *port = &pp->port;
- unsigned char ch, flag;
- unsigned short status;
-
- while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) &
- ALTERA_UART_STATUS_RRDY_MSK) {
- ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- if (status & ALTERA_UART_STATUS_E_MSK) {
- altera_uart_writel(port, status,
- ALTERA_UART_STATUS_REG);
-
- if (status & ALTERA_UART_STATUS_BRK_MSK) {
- port->icount.brk++;
- if (uart_handle_break(port))
- continue;
- } else if (status & ALTERA_UART_STATUS_PE_MSK) {
- port->icount.parity++;
- } else if (status & ALTERA_UART_STATUS_ROE_MSK) {
- port->icount.overrun++;
- } else if (status & ALTERA_UART_STATUS_FE_MSK) {
- port->icount.frame++;
- }
-
- status &= port->read_status_mask;
-
- if (status & ALTERA_UART_STATUS_BRK_MSK)
- flag = TTY_BREAK;
- else if (status & ALTERA_UART_STATUS_PE_MSK)
- flag = TTY_PARITY;
- else if (status & ALTERA_UART_STATUS_FE_MSK)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, ch))
- continue;
- uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch,
- flag);
- }
-
- tty_flip_buffer_push(port->state->port.tty);
-}
-
-static void altera_uart_tx_chars(struct altera_uart *pp)
-{
- struct uart_port *port = &pp->port;
- struct circ_buf *xmit = &port->state->xmit;
-
- if (port->x_char) {
- /* Send special char - probably flow control */
- altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG);
- port->x_char = 0;
- port->icount.tx++;
- return;
- }
-
- while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
- ALTERA_UART_STATUS_TRDY_MSK) {
- if (xmit->head == xmit->tail)
- break;
- altera_uart_writel(port, xmit->buf[xmit->tail],
- ALTERA_UART_TXDATA_REG);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (xmit->head == xmit->tail) {
- pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
- altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
- }
-}
-
-static irqreturn_t altera_uart_interrupt(int irq, void *data)
-{
- struct uart_port *port = data;
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned int isr;
-
- isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr;
-
- spin_lock(&port->lock);
- if (isr & ALTERA_UART_STATUS_RRDY_MSK)
- altera_uart_rx_chars(pp);
- if (isr & ALTERA_UART_STATUS_TRDY_MSK)
- altera_uart_tx_chars(pp);
- spin_unlock(&port->lock);
-
- return IRQ_RETVAL(isr);
-}
-
-static void altera_uart_timer(unsigned long data)
-{
- struct uart_port *port = (void *)data;
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
-
- altera_uart_interrupt(0, port);
- mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
-}
-
-static void altera_uart_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_ALTERA_UART;
-
- /* Clear mask, so no surprise interrupts. */
- altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG);
- /* Clear status register */
- altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG);
-}
-
-static int altera_uart_startup(struct uart_port *port)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
- int ret;
-
- if (!port->irq) {
- setup_timer(&pp->tmr, altera_uart_timer, (unsigned long)port);
- mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
- return 0;
- }
-
- ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
- DRV_NAME, port);
- if (ret) {
- pr_err(DRV_NAME ": unable to attach Altera UART %d "
- "interrupt vector=%d\n", port->line, port->irq);
- return ret;
- }
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Enable RX interrupts now */
- pp->imr = ALTERA_UART_CONTROL_RRDY_MSK;
- writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- return 0;
-}
-
-static void altera_uart_shutdown(struct uart_port *port)
-{
- struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Disable all interrupts now */
- pp->imr = 0;
- writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (port->irq)
- free_irq(port->irq, port);
- else
- del_timer_sync(&pp->tmr);
-}
-
-static const char *altera_uart_type(struct uart_port *port)
-{
- return (port->type == PORT_ALTERA_UART) ? "Altera UART" : NULL;
-}
-
-static int altera_uart_request_port(struct uart_port *port)
-{
- /* UARTs always present */
- return 0;
-}
-
-static void altera_uart_release_port(struct uart_port *port)
-{
- /* Nothing to release... */
-}
-
-static int altera_uart_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_ALTERA_UART))
- return -EINVAL;
- return 0;
-}
-
-/*
- * Define the basic serial functions we support.
- */
-static struct uart_ops altera_uart_ops = {
- .tx_empty = altera_uart_tx_empty,
- .get_mctrl = altera_uart_get_mctrl,
- .set_mctrl = altera_uart_set_mctrl,
- .start_tx = altera_uart_start_tx,
- .stop_tx = altera_uart_stop_tx,
- .stop_rx = altera_uart_stop_rx,
- .enable_ms = altera_uart_enable_ms,
- .break_ctl = altera_uart_break_ctl,
- .startup = altera_uart_startup,
- .shutdown = altera_uart_shutdown,
- .set_termios = altera_uart_set_termios,
- .type = altera_uart_type,
- .request_port = altera_uart_request_port,
- .release_port = altera_uart_release_port,
- .config_port = altera_uart_config_port,
- .verify_port = altera_uart_verify_port,
-};
-
-static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
-
-#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
-
-int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
- port = &altera_uart_ports[i].port;
-
- port->line = i;
- port->type = PORT_ALTERA_UART;
- port->mapbase = platp[i].mapbase;
- port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
- port->iotype = SERIAL_IO_MEM;
- port->irq = platp[i].irq;
- port->uartclk = platp[i].uartclk;
- port->flags = UPF_BOOT_AUTOCONF;
- port->ops = &altera_uart_ops;
- port->private_data = platp;
- }
-
- return 0;
-}
-
-static void altera_uart_console_putc(struct uart_port *port, const char c)
-{
- while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
- ALTERA_UART_STATUS_TRDY_MSK))
- cpu_relax();
-
- writel(c, port->membase + ALTERA_UART_TXDATA_REG);
-}
-
-static void altera_uart_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_port *port = &(altera_uart_ports + co->index)->port;
-
- for (; count; count--, s++) {
- altera_uart_console_putc(port, *s);
- if (*s == '\n')
- altera_uart_console_putc(port, '\r');
- }
-}
-
-static int __init altera_uart_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
- return -EINVAL;
- port = &altera_uart_ports[co->index].port;
- if (!port->membase)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver altera_uart_driver;
-
-static struct console altera_uart_console = {
- .name = "ttyAL",
- .write = altera_uart_console_write,
- .device = uart_console_device,
- .setup = altera_uart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &altera_uart_driver,
-};
-
-static int __init altera_uart_console_init(void)
-{
- register_console(&altera_uart_console);
- return 0;
-}
-
-console_initcall(altera_uart_console_init);
-
-#define ALTERA_UART_CONSOLE (&altera_uart_console)
-
-#else
-
-#define ALTERA_UART_CONSOLE NULL
-
-#endif /* CONFIG_ALTERA_UART_CONSOLE */
-
-/*
- * Define the altera_uart UART driver structure.
- */
-static struct uart_driver altera_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = DRV_NAME,
- .dev_name = "ttyAL",
- .major = SERIAL_ALTERA_MAJOR,
- .minor = SERIAL_ALTERA_MINOR,
- .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
- .cons = ALTERA_UART_CONSOLE,
-};
-
-static int __devinit altera_uart_probe(struct platform_device *pdev)
-{
- struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
- struct uart_port *port;
- struct resource *res_mem;
- struct resource *res_irq;
- int i = pdev->id;
-
- /* -1 emphasizes that the platform must have one port, no .N suffix */
- if (i == -1)
- i = 0;
-
- if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
- return -EINVAL;
-
- port = &altera_uart_ports[i].port;
-
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res_mem)
- port->mapbase = res_mem->start;
- else if (platp->mapbase)
- port->mapbase = platp->mapbase;
- else
- return -EINVAL;
-
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (res_irq)
- port->irq = res_irq->start;
- else if (platp->irq)
- port->irq = platp->irq;
-
- port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
- if (!port->membase)
- return -ENOMEM;
-
- port->line = i;
- port->type = PORT_ALTERA_UART;
- port->iotype = SERIAL_IO_MEM;
- port->uartclk = platp->uartclk;
- port->ops = &altera_uart_ops;
- port->flags = UPF_BOOT_AUTOCONF;
- port->private_data = platp;
-
- uart_add_one_port(&altera_uart_driver, port);
-
- return 0;
-}
-
-static int __devexit altera_uart_remove(struct platform_device *pdev)
-{
- struct uart_port *port = &altera_uart_ports[pdev->id].port;
-
- uart_remove_one_port(&altera_uart_driver, port);
- return 0;
-}
-
-static struct platform_driver altera_uart_platform_driver = {
- .probe = altera_uart_probe,
- .remove = __devexit_p(altera_uart_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- .pm = NULL,
- },
-};
-
-static int __init altera_uart_init(void)
-{
- int rc;
-
- rc = uart_register_driver(&altera_uart_driver);
- if (rc)
- return rc;
- rc = platform_driver_register(&altera_uart_platform_driver);
- if (rc) {
- uart_unregister_driver(&altera_uart_driver);
- return rc;
- }
- return 0;
-}
-
-static void __exit altera_uart_exit(void)
-{
- platform_driver_unregister(&altera_uart_platform_driver);
- uart_unregister_driver(&altera_uart_driver);
-}
-
-module_init(altera_uart_init);
-module_exit(altera_uart_exit);
-
-MODULE_DESCRIPTION("Altera UART driver");
-MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR);
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
deleted file mode 100644
index 2904aa044126..000000000000
--- a/drivers/serial/amba-pl010.c
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- * linux/drivers/char/amba.c
- *
- * Driver for AMBA serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This is a generic driver for ARM AMBA-type serial ports. They
- * have a lot of 16550-like features, but are not register compatible.
- * Note that although they do have CTS, DCD and DSR inputs, they do
- * not have an RI input, nor do they have DTR or RTS outputs. If
- * required, these have to be supplied via some other means (eg, GPIO)
- * and hooked into this driver.
- */
-
-#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/serial.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-
-#define UART_NR 8
-
-#define SERIAL_AMBA_MAJOR 204
-#define SERIAL_AMBA_MINOR 16
-#define SERIAL_AMBA_NR UART_NR
-
-#define AMBA_ISR_PASS_LIMIT 256
-
-#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0)
-#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0)
-
-#define UART_DUMMY_RSR_RX 256
-#define UART_PORT_SIZE 64
-
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct uart_amba_port {
- struct uart_port port;
- struct clk *clk;
- struct amba_device *dev;
- struct amba_pl010_data *data;
- unsigned int old_status;
-};
-
-static void pl010_stop_tx(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int cr;
-
- cr = readb(uap->port.membase + UART010_CR);
- cr &= ~UART010_CR_TIE;
- writel(cr, uap->port.membase + UART010_CR);
-}
-
-static void pl010_start_tx(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int cr;
-
- cr = readb(uap->port.membase + UART010_CR);
- cr |= UART010_CR_TIE;
- writel(cr, uap->port.membase + UART010_CR);
-}
-
-static void pl010_stop_rx(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int cr;
-
- cr = readb(uap->port.membase + UART010_CR);
- cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
- writel(cr, uap->port.membase + UART010_CR);
-}
-
-static void pl010_enable_ms(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int cr;
-
- cr = readb(uap->port.membase + UART010_CR);
- cr |= UART010_CR_MSIE;
- writel(cr, uap->port.membase + UART010_CR);
-}
-
-static void pl010_rx_chars(struct uart_amba_port *uap)
-{
- 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);
- while (UART_RX_DATA(status) && max_count--) {
- ch = readb(uap->port.membase + UART01x_DR);
- flag = TTY_NORMAL;
-
- uap->port.icount.rx++;
-
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
- if (unlikely(rsr & UART01x_RSR_ANY)) {
- writel(0, uap->port.membase + UART01x_ECR);
-
- if (rsr & UART01x_RSR_BE) {
- rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
- uap->port.icount.brk++;
- if (uart_handle_break(&uap->port))
- goto ignore_char;
- } else if (rsr & UART01x_RSR_PE)
- uap->port.icount.parity++;
- else if (rsr & UART01x_RSR_FE)
- uap->port.icount.frame++;
- if (rsr & UART01x_RSR_OE)
- uap->port.icount.overrun++;
-
- rsr &= uap->port.read_status_mask;
-
- if (rsr & UART01x_RSR_BE)
- flag = TTY_BREAK;
- else if (rsr & UART01x_RSR_PE)
- flag = TTY_PARITY;
- else if (rsr & UART01x_RSR_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&uap->port, ch))
- goto ignore_char;
-
- uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
-
- ignore_char:
- status = readb(uap->port.membase + UART01x_FR);
- }
- spin_unlock(&uap->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&uap->port.lock);
-}
-
-static void pl010_tx_chars(struct uart_amba_port *uap)
-{
- struct circ_buf *xmit = &uap->port.state->xmit;
- int count;
-
- if (uap->port.x_char) {
- writel(uap->port.x_char, uap->port.membase + UART01x_DR);
- uap->port.icount.tx++;
- uap->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
- pl010_stop_tx(&uap->port);
- return;
- }
-
- count = uap->port.fifosize >> 1;
- do {
- writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- uap->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uap->port);
-
- if (uart_circ_empty(xmit))
- pl010_stop_tx(&uap->port);
-}
-
-static void pl010_modem_status(struct uart_amba_port *uap)
-{
- unsigned int status, delta;
-
- writel(0, uap->port.membase + UART010_ICR);
-
- status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
-
- delta = status ^ uap->old_status;
- uap->old_status = status;
-
- if (!delta)
- return;
-
- if (delta & UART01x_FR_DCD)
- uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
-
- if (delta & UART01x_FR_DSR)
- uap->port.icount.dsr++;
-
- if (delta & UART01x_FR_CTS)
- uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
-
- wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
-}
-
-static irqreturn_t pl010_int(int irq, void *dev_id)
-{
- struct uart_amba_port *uap = dev_id;
- unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
- int handled = 0;
-
- spin_lock(&uap->port.lock);
-
- status = readb(uap->port.membase + UART010_IIR);
- if (status) {
- do {
- if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
- pl010_rx_chars(uap);
- if (status & UART010_IIR_MIS)
- pl010_modem_status(uap);
- if (status & UART010_IIR_TIS)
- pl010_tx_chars(uap);
-
- if (pass_counter-- == 0)
- break;
-
- status = readb(uap->port.membase + UART010_IIR);
- } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
- UART010_IIR_TIS));
- handled = 1;
- }
-
- spin_unlock(&uap->port.lock);
-
- return IRQ_RETVAL(handled);
-}
-
-static unsigned int pl010_tx_empty(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int status = readb(uap->port.membase + UART01x_FR);
- return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
-}
-
-static unsigned int pl010_get_mctrl(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int result = 0;
- unsigned int status;
-
- status = readb(uap->port.membase + UART01x_FR);
- if (status & UART01x_FR_DCD)
- result |= TIOCM_CAR;
- if (status & UART01x_FR_DSR)
- result |= TIOCM_DSR;
- if (status & UART01x_FR_CTS)
- result |= TIOCM_CTS;
-
- return result;
-}
-
-static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- if (uap->data)
- uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
-}
-
-static void pl010_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned long flags;
- unsigned int lcr_h;
-
- spin_lock_irqsave(&uap->port.lock, flags);
- lcr_h = readb(uap->port.membase + UART010_LCRH);
- if (break_state == -1)
- lcr_h |= UART01x_LCRH_BRK;
- else
- lcr_h &= ~UART01x_LCRH_BRK;
- writel(lcr_h, uap->port.membase + UART010_LCRH);
- spin_unlock_irqrestore(&uap->port.lock, flags);
-}
-
-static int pl010_startup(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- int retval;
-
- /*
- * Try to enable the clock producer.
- */
- retval = clk_enable(uap->clk);
- if (retval)
- goto out;
-
- uap->port.uartclk = clk_get_rate(uap->clk);
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
- if (retval)
- goto clk_dis;
-
- /*
- * initialise the old status of the modem signals
- */
- uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
-
- /*
- * Finally, enable interrupts
- */
- writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
- uap->port.membase + UART010_CR);
-
- return 0;
-
- clk_dis:
- clk_disable(uap->clk);
- out:
- return retval;
-}
-
-static void pl010_shutdown(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- /*
- * Free the interrupt
- */
- free_irq(uap->port.irq, uap);
-
- /*
- * disable all interrupts, disable the port
- */
- writel(0, uap->port.membase + UART010_CR);
-
- /* disable break condition and fifos */
- writel(readb(uap->port.membase + UART010_LCRH) &
- ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
- uap->port.membase + UART010_LCRH);
-
- /*
- * Shut down the clock producer
- */
- clk_disable(uap->clk);
-}
-
-static void
-pl010_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int lcr_h, old_cr;
- unsigned long flags;
- unsigned int baud, quot;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- lcr_h = UART01x_LCRH_WLEN_5;
- break;
- case CS6:
- lcr_h = UART01x_LCRH_WLEN_6;
- break;
- case CS7:
- lcr_h = UART01x_LCRH_WLEN_7;
- break;
- default: // CS8
- lcr_h = UART01x_LCRH_WLEN_8;
- break;
- }
- if (termios->c_cflag & CSTOPB)
- lcr_h |= UART01x_LCRH_STP2;
- if (termios->c_cflag & PARENB) {
- lcr_h |= UART01x_LCRH_PEN;
- if (!(termios->c_cflag & PARODD))
- lcr_h |= UART01x_LCRH_EPS;
- }
- if (uap->port.fifosize > 1)
- lcr_h |= UART01x_LCRH_FEN;
-
- spin_lock_irqsave(&uap->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- uap->port.read_status_mask = UART01x_RSR_OE;
- if (termios->c_iflag & INPCK)
- uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- uap->port.read_status_mask |= UART01x_RSR_BE;
-
- /*
- * Characters to ignore
- */
- uap->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
- if (termios->c_iflag & IGNBRK) {
- uap->port.ignore_status_mask |= UART01x_RSR_BE;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- uap->port.ignore_status_mask |= UART01x_RSR_OE;
- }
-
- /*
- * Ignore all characters if CREAD is not set.
- */
- if ((termios->c_cflag & CREAD) == 0)
- uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
-
- /* first, disable everything */
- old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
-
- if (UART_ENABLE_MS(port, termios->c_cflag))
- old_cr |= UART010_CR_MSIE;
-
- writel(0, uap->port.membase + UART010_CR);
-
- /* Set baud rate */
- quot -= 1;
- writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
- writel(quot & 0xff, uap->port.membase + UART010_LCRL);
-
- /*
- * ----------v----------v----------v----------v-----
- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
- * ----------^----------^----------^----------^-----
- */
- writel(lcr_h, uap->port.membase + UART010_LCRH);
- writel(old_cr, uap->port.membase + UART010_CR);
-
- spin_unlock_irqrestore(&uap->port.lock, flags);
-}
-
-static void pl010_set_ldisc(struct uart_port *port, int new)
-{
- if (new == N_PPS) {
- port->flags |= UPF_HARDPPS_CD;
- pl010_enable_ms(port);
- } else
- port->flags &= ~UPF_HARDPPS_CD;
-}
-
-static const char *pl010_type(struct uart_port *port)
-{
- return port->type == PORT_AMBA ? "AMBA" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'
- */
-static void pl010_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, UART_PORT_SIZE);
-}
-
-/*
- * Request the memory region(s) being used by 'port'
- */
-static int pl010_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, UART_PORT_SIZE, "uart-pl010")
- != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void pl010_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_AMBA;
- pl010_request_port(port);
- }
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
- ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
- ret = -EINVAL;
- if (ser->baud_base < 9600)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops amba_pl010_pops = {
- .tx_empty = pl010_tx_empty,
- .set_mctrl = pl010_set_mctrl,
- .get_mctrl = pl010_get_mctrl,
- .stop_tx = pl010_stop_tx,
- .start_tx = pl010_start_tx,
- .stop_rx = pl010_stop_rx,
- .enable_ms = pl010_enable_ms,
- .break_ctl = pl010_break_ctl,
- .startup = pl010_startup,
- .shutdown = pl010_shutdown,
- .set_termios = pl010_set_termios,
- .set_ldisc = pl010_set_ldisc,
- .type = pl010_type,
- .release_port = pl010_release_port,
- .request_port = pl010_request_port,
- .config_port = pl010_config_port,
- .verify_port = pl010_verify_port,
-};
-
-static struct uart_amba_port *amba_ports[UART_NR];
-
-#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
-
-static void pl010_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int status;
-
- do {
- status = readb(uap->port.membase + UART01x_FR);
- barrier();
- } while (!UART_TX_READY(status));
- writel(ch, uap->port.membase + UART01x_DR);
-}
-
-static void
-pl010_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_amba_port *uap = amba_ports[co->index];
- unsigned int status, old_cr;
-
- clk_enable(uap->clk);
-
- /*
- * First save the CR then disable the interrupts
- */
- old_cr = readb(uap->port.membase + UART010_CR);
- writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
-
- uart_console_write(&uap->port, s, count, pl010_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the TCR
- */
- do {
- status = readb(uap->port.membase + UART01x_FR);
- barrier();
- } while (status & UART01x_FR_BUSY);
- writel(old_cr, uap->port.membase + UART010_CR);
-
- clk_disable(uap->clk);
-}
-
-static void __init
-pl010_console_get_options(struct uart_amba_port *uap, int *baud,
- int *parity, int *bits)
-{
- if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
- unsigned int lcr_h, quot;
- lcr_h = readb(uap->port.membase + UART010_LCRH);
-
- *parity = 'n';
- if (lcr_h & UART01x_LCRH_PEN) {
- if (lcr_h & UART01x_LCRH_EPS)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7)
- *bits = 7;
- else
- *bits = 8;
-
- quot = readb(uap->port.membase + UART010_LCRL) |
- readb(uap->port.membase + UART010_LCRM) << 8;
- *baud = uap->port.uartclk / (16 * (quot + 1));
- }
-}
-
-static int __init pl010_console_setup(struct console *co, char *options)
-{
- struct uart_amba_port *uap;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- uap = amba_ports[co->index];
- if (!uap)
- return -ENODEV;
-
- uap->port.uartclk = clk_get_rate(uap->clk);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- pl010_console_get_options(uap, &baud, &parity, &bits);
-
- return uart_set_options(&uap->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver amba_reg;
-static struct console amba_console = {
- .name = "ttyAM",
- .write = pl010_console_write,
- .device = uart_console_device,
- .setup = pl010_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &amba_reg,
-};
-
-#define AMBA_CONSOLE &amba_console
-#else
-#define AMBA_CONSOLE NULL
-#endif
-
-static struct uart_driver amba_reg = {
- .owner = THIS_MODULE,
- .driver_name = "ttyAM",
- .dev_name = "ttyAM",
- .major = SERIAL_AMBA_MAJOR,
- .minor = SERIAL_AMBA_MINOR,
- .nr = UART_NR,
- .cons = AMBA_CONSOLE,
-};
-
-static int pl010_probe(struct amba_device *dev, struct amba_id *id)
-{
- struct uart_amba_port *uap;
- void __iomem *base;
- int i, ret;
-
- for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
- if (amba_ports[i] == NULL)
- break;
-
- if (i == ARRAY_SIZE(amba_ports)) {
- ret = -EBUSY;
- goto out;
- }
-
- uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
- if (!uap) {
- ret = -ENOMEM;
- goto out;
- }
-
- base = ioremap(dev->res.start, resource_size(&dev->res));
- if (!base) {
- ret = -ENOMEM;
- goto free;
- }
-
- uap->clk = clk_get(&dev->dev, NULL);
- if (IS_ERR(uap->clk)) {
- ret = PTR_ERR(uap->clk);
- goto unmap;
- }
-
- uap->port.dev = &dev->dev;
- uap->port.mapbase = dev->res.start;
- uap->port.membase = base;
- uap->port.iotype = UPIO_MEM;
- uap->port.irq = dev->irq[0];
- uap->port.fifosize = 16;
- uap->port.ops = &amba_pl010_pops;
- uap->port.flags = UPF_BOOT_AUTOCONF;
- uap->port.line = i;
- uap->dev = dev;
- uap->data = dev->dev.platform_data;
-
- amba_ports[i] = uap;
-
- amba_set_drvdata(dev, uap);
- ret = uart_add_one_port(&amba_reg, &uap->port);
- if (ret) {
- amba_set_drvdata(dev, NULL);
- amba_ports[i] = NULL;
- clk_put(uap->clk);
- unmap:
- iounmap(base);
- free:
- kfree(uap);
- }
- out:
- return ret;
-}
-
-static int pl010_remove(struct amba_device *dev)
-{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
- int i;
-
- amba_set_drvdata(dev, NULL);
-
- uart_remove_one_port(&amba_reg, &uap->port);
-
- for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
- if (amba_ports[i] == uap)
- amba_ports[i] = NULL;
-
- iounmap(uap->port.membase);
- clk_put(uap->clk);
- kfree(uap);
- return 0;
-}
-
-static int pl010_suspend(struct amba_device *dev, pm_message_t state)
-{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
-
- if (uap)
- uart_suspend_port(&amba_reg, &uap->port);
-
- return 0;
-}
-
-static int pl010_resume(struct amba_device *dev)
-{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
-
- if (uap)
- uart_resume_port(&amba_reg, &uap->port);
-
- return 0;
-}
-
-static struct amba_id pl010_ids[] = {
- {
- .id = 0x00041010,
- .mask = 0x000fffff,
- },
- { 0, 0 },
-};
-
-static struct amba_driver pl010_driver = {
- .drv = {
- .name = "uart-pl010",
- },
- .id_table = pl010_ids,
- .probe = pl010_probe,
- .remove = pl010_remove,
- .suspend = pl010_suspend,
- .resume = pl010_resume,
-};
-
-static int __init pl010_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: AMBA driver\n");
-
- ret = uart_register_driver(&amba_reg);
- if (ret == 0) {
- ret = amba_driver_register(&pl010_driver);
- if (ret)
- uart_unregister_driver(&amba_reg);
- }
- return ret;
-}
-
-static void __exit pl010_exit(void)
-{
- amba_driver_unregister(&pl010_driver);
- uart_unregister_driver(&amba_reg);
-}
-
-module_init(pl010_init);
-module_exit(pl010_exit);
-
-MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("ARM AMBA serial port driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
deleted file mode 100644
index e76d7d000128..000000000000
--- a/drivers/serial/amba-pl011.c
+++ /dev/null
@@ -1,1519 +0,0 @@
-/*
- * linux/drivers/char/amba.c
- *
- * Driver for AMBA serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- * Copyright (C) 2010 ST-Ericsson SA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This is a generic driver for ARM AMBA-type serial ports. They
- * have a lot of 16550-like features, but are not register compatible.
- * Note that although they do have CTS, DCD and DSR inputs, they do
- * not have an RI input, nor do they have DTR or RTS outputs. If
- * required, these have to be supplied via some other means (eg, GPIO)
- * and hooked into this driver.
- */
-
-#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/serial.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-#include <linux/scatterlist.h>
-
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-#define UART_NR 14
-
-#define SERIAL_AMBA_MAJOR 204
-#define SERIAL_AMBA_MINOR 64
-#define SERIAL_AMBA_NR UART_NR
-
-#define AMBA_ISR_PASS_LIMIT 256
-
-#define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
-#define UART_DUMMY_DR_RX (1 << 16)
-
-/* There is by now at least one vendor with differing details, so handle it */
-struct vendor_data {
- unsigned int ifls;
- unsigned int fifosize;
- unsigned int lcrh_tx;
- unsigned int lcrh_rx;
- bool oversampling;
- bool dma_threshold;
-};
-
-static struct vendor_data vendor_arm = {
- .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
- .fifosize = 16,
- .lcrh_tx = UART011_LCRH,
- .lcrh_rx = UART011_LCRH,
- .oversampling = false,
- .dma_threshold = false,
-};
-
-static struct vendor_data vendor_st = {
- .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
- .fifosize = 64,
- .lcrh_tx = ST_UART011_LCRH_TX,
- .lcrh_rx = ST_UART011_LCRH_RX,
- .oversampling = true,
- .dma_threshold = true,
-};
-
-/* Deals with DMA transactions */
-struct pl011_dmatx_data {
- struct dma_chan *chan;
- struct scatterlist sg;
- char *buf;
- bool queued;
-};
-
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct uart_amba_port {
- struct uart_port port;
- struct clk *clk;
- const struct vendor_data *vendor;
- unsigned int dmacr; /* dma control reg */
- unsigned int im; /* interrupt mask */
- unsigned int old_status;
- unsigned int fifosize; /* vendor-specific */
- unsigned int lcrh_tx; /* vendor-specific */
- unsigned int lcrh_rx; /* vendor-specific */
- bool autorts;
- char type[12];
-#ifdef CONFIG_DMA_ENGINE
- /* DMA stuff */
- bool using_dma;
- struct pl011_dmatx_data dmatx;
-#endif
-};
-
-/*
- * All the DMA operation mode stuff goes inside this ifdef.
- * This assumes that you have a generic DMA device interface,
- * no custom DMA interfaces are supported.
- */
-#ifdef CONFIG_DMA_ENGINE
-
-#define PL011_DMA_BUFFER_SIZE PAGE_SIZE
-
-static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
-{
- /* DMA is the sole user of the platform data right now */
- struct amba_pl011_data *plat = uap->port.dev->platform_data;
- struct dma_slave_config tx_conf = {
- .dst_addr = uap->port.mapbase + UART01x_DR,
- .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
- .direction = DMA_TO_DEVICE,
- .dst_maxburst = uap->fifosize >> 1,
- };
- struct dma_chan *chan;
- dma_cap_mask_t mask;
-
- /* We need platform data */
- if (!plat || !plat->dma_filter) {
- dev_info(uap->port.dev, "no DMA platform data\n");
- return;
- }
-
- /* Try to acquire a generic DMA engine slave channel */
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
- if (!chan) {
- dev_err(uap->port.dev, "no TX DMA channel!\n");
- return;
- }
-
- dmaengine_slave_config(chan, &tx_conf);
- uap->dmatx.chan = chan;
-
- dev_info(uap->port.dev, "DMA channel TX %s\n",
- dma_chan_name(uap->dmatx.chan));
-}
-
-#ifndef MODULE
-/*
- * Stack up the UARTs and let the above initcall be done at device
- * initcall time, because the serial driver is called as an arch
- * initcall, and at this time the DMA subsystem is not yet registered.
- * At this point the driver will switch over to using DMA where desired.
- */
-struct dma_uap {
- struct list_head node;
- struct uart_amba_port *uap;
-};
-
-static LIST_HEAD(pl011_dma_uarts);
-
-static int __init pl011_dma_initcall(void)
-{
- struct list_head *node, *tmp;
-
- list_for_each_safe(node, tmp, &pl011_dma_uarts) {
- struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
- pl011_dma_probe_initcall(dmau->uap);
- list_del(node);
- kfree(dmau);
- }
- return 0;
-}
-
-device_initcall(pl011_dma_initcall);
-
-static void pl011_dma_probe(struct uart_amba_port *uap)
-{
- struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
- if (dmau) {
- dmau->uap = uap;
- list_add_tail(&dmau->node, &pl011_dma_uarts);
- }
-}
-#else
-static void pl011_dma_probe(struct uart_amba_port *uap)
-{
- pl011_dma_probe_initcall(uap);
-}
-#endif
-
-static void pl011_dma_remove(struct uart_amba_port *uap)
-{
- /* TODO: remove the initcall if it has not yet executed */
- if (uap->dmatx.chan)
- dma_release_channel(uap->dmatx.chan);
-}
-
-
-/* Forward declare this for the refill routine */
-static int pl011_dma_tx_refill(struct uart_amba_port *uap);
-
-/*
- * The current DMA TX buffer has been sent.
- * Try to queue up another DMA buffer.
- */
-static void pl011_dma_tx_callback(void *data)
-{
- struct uart_amba_port *uap = data;
- struct pl011_dmatx_data *dmatx = &uap->dmatx;
- unsigned long flags;
- u16 dmacr;
-
- spin_lock_irqsave(&uap->port.lock, flags);
- if (uap->dmatx.queued)
- dma_unmap_sg(dmatx->chan->device->dev, &dmatx->sg, 1,
- DMA_TO_DEVICE);
-
- dmacr = uap->dmacr;
- uap->dmacr = dmacr & ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
-
- /*
- * If TX DMA was disabled, it means that we've stopped the DMA for
- * some reason (eg, XOFF received, or we want to send an X-char.)
- *
- * Note: we need to be careful here of a potential race between DMA
- * and the rest of the driver - if the driver disables TX DMA while
- * a TX buffer completing, we must update the tx queued status to
- * get further refills (hence we check dmacr).
- */
- if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) ||
- uart_circ_empty(&uap->port.state->xmit)) {
- uap->dmatx.queued = false;
- spin_unlock_irqrestore(&uap->port.lock, flags);
- return;
- }
-
- if (pl011_dma_tx_refill(uap) <= 0) {
- /*
- * We didn't queue a DMA buffer for some reason, but we
- * have data pending to be sent. Re-enable the TX IRQ.
- */
- uap->im |= UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- }
- spin_unlock_irqrestore(&uap->port.lock, flags);
-}
-
-/*
- * Try to refill the TX DMA buffer.
- * Locking: called with port lock held and IRQs disabled.
- * Returns:
- * 1 if we queued up a TX DMA buffer.
- * 0 if we didn't want to handle this by DMA
- * <0 on error
- */
-static int pl011_dma_tx_refill(struct uart_amba_port *uap)
-{
- struct pl011_dmatx_data *dmatx = &uap->dmatx;
- struct dma_chan *chan = dmatx->chan;
- struct dma_device *dma_dev = chan->device;
- struct dma_async_tx_descriptor *desc;
- struct circ_buf *xmit = &uap->port.state->xmit;
- unsigned int count;
-
- /*
- * Try to avoid the overhead involved in using DMA if the
- * transaction fits in the first half of the FIFO, by using
- * the standard interrupt handling. This ensures that we
- * issue a uart_write_wakeup() at the appropriate time.
- */
- count = uart_circ_chars_pending(xmit);
- if (count < (uap->fifosize >> 1)) {
- uap->dmatx.queued = false;
- return 0;
- }
-
- /*
- * Bodge: don't send the last character by DMA, as this
- * will prevent XON from notifying us to restart DMA.
- */
- count -= 1;
-
- /* Else proceed to copy the TX chars to the DMA buffer and fire DMA */
- if (count > PL011_DMA_BUFFER_SIZE)
- count = PL011_DMA_BUFFER_SIZE;
-
- if (xmit->tail < xmit->head)
- memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], count);
- else {
- size_t first = UART_XMIT_SIZE - xmit->tail;
- size_t second = xmit->head;
-
- memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], first);
- if (second)
- memcpy(&dmatx->buf[first], &xmit->buf[0], second);
- }
-
- dmatx->sg.length = count;
-
- if (dma_map_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE) != 1) {
- uap->dmatx.queued = false;
- dev_dbg(uap->port.dev, "unable to map TX DMA\n");
- return -EBUSY;
- }
-
- desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_TO_DEVICE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE);
- uap->dmatx.queued = false;
- /*
- * If DMA cannot be used right now, we complete this
- * transaction via IRQ and let the TTY layer retry.
- */
- dev_dbg(uap->port.dev, "TX DMA busy\n");
- return -EBUSY;
- }
-
- /* Some data to go along to the callback */
- desc->callback = pl011_dma_tx_callback;
- desc->callback_param = uap;
-
- /* All errors should happen at prepare time */
- dmaengine_submit(desc);
-
- /* Fire the DMA transaction */
- dma_dev->device_issue_pending(chan);
-
- uap->dmacr |= UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
- uap->dmatx.queued = true;
-
- /*
- * Now we know that DMA will fire, so advance the ring buffer
- * with the stuff we just dispatched.
- */
- xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
- uap->port.icount.tx += count;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uap->port);
-
- return 1;
-}
-
-/*
- * We received a transmit interrupt without a pending X-char but with
- * pending characters.
- * Locking: called with port lock held and IRQs disabled.
- * Returns:
- * false if we want to use PIO to transmit
- * true if we queued a DMA buffer
- */
-static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
-{
- if (!uap->using_dma)
- return false;
-
- /*
- * If we already have a TX buffer queued, but received a
- * TX interrupt, it will be because we've just sent an X-char.
- * Ensure the TX DMA is enabled and the TX IRQ is disabled.
- */
- if (uap->dmatx.queued) {
- uap->dmacr |= UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
- uap->im &= ~UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- return true;
- }
-
- /*
- * We don't have a TX buffer queued, so try to queue one.
- * If we succesfully queued a buffer, mask the TX IRQ.
- */
- if (pl011_dma_tx_refill(uap) > 0) {
- uap->im &= ~UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- return true;
- }
- return false;
-}
-
-/*
- * Stop the DMA transmit (eg, due to received XOFF).
- * Locking: called with port lock held and IRQs disabled.
- */
-static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
-{
- if (uap->dmatx.queued) {
- uap->dmacr &= ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
- }
-}
-
-/*
- * Try to start a DMA transmit, or in the case of an XON/OFF
- * character queued for send, try to get that character out ASAP.
- * Locking: called with port lock held and IRQs disabled.
- * Returns:
- * false if we want the TX IRQ to be enabled
- * true if we have a buffer queued
- */
-static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
-{
- u16 dmacr;
-
- if (!uap->using_dma)
- return false;
-
- if (!uap->port.x_char) {
- /* no X-char, try to push chars out in DMA mode */
- bool ret = true;
-
- if (!uap->dmatx.queued) {
- if (pl011_dma_tx_refill(uap) > 0) {
- uap->im &= ~UART011_TXIM;
- ret = true;
- } else {
- uap->im |= UART011_TXIM;
- ret = false;
- }
- writew(uap->im, uap->port.membase + UART011_IMSC);
- } else if (!(uap->dmacr & UART011_TXDMAE)) {
- uap->dmacr |= UART011_TXDMAE;
- writew(uap->dmacr,
- uap->port.membase + UART011_DMACR);
- }
- return ret;
- }
-
- /*
- * We have an X-char to send. Disable DMA to prevent it loading
- * the TX fifo, and then see if we can stuff it into the FIFO.
- */
- dmacr = uap->dmacr;
- uap->dmacr &= ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
-
- if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
- /*
- * No space in the FIFO, so enable the transmit interrupt
- * so we know when there is space. Note that once we've
- * loaded the character, we should just re-enable DMA.
- */
- return false;
- }
-
- writew(uap->port.x_char, uap->port.membase + UART01x_DR);
- uap->port.icount.tx++;
- uap->port.x_char = 0;
-
- /* Success - restore the DMA state */
- uap->dmacr = dmacr;
- writew(dmacr, uap->port.membase + UART011_DMACR);
-
- return true;
-}
-
-/*
- * Flush the transmit buffer.
- * Locking: called with port lock held and IRQs disabled.
- */
-static void pl011_dma_flush_buffer(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- if (!uap->using_dma)
- return;
-
- /* Avoid deadlock with the DMA engine callback */
- spin_unlock(&uap->port.lock);
- dmaengine_terminate_all(uap->dmatx.chan);
- spin_lock(&uap->port.lock);
- if (uap->dmatx.queued) {
- dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
- DMA_TO_DEVICE);
- uap->dmatx.queued = false;
- uap->dmacr &= ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
- }
-}
-
-
-static void pl011_dma_startup(struct uart_amba_port *uap)
-{
- if (!uap->dmatx.chan)
- return;
-
- uap->dmatx.buf = kmalloc(PL011_DMA_BUFFER_SIZE, GFP_KERNEL);
- if (!uap->dmatx.buf) {
- dev_err(uap->port.dev, "no memory for DMA TX buffer\n");
- uap->port.fifosize = uap->fifosize;
- return;
- }
-
- sg_init_one(&uap->dmatx.sg, uap->dmatx.buf, PL011_DMA_BUFFER_SIZE);
-
- /* The DMA buffer is now the FIFO the TTY subsystem can use */
- uap->port.fifosize = PL011_DMA_BUFFER_SIZE;
- uap->using_dma = true;
-
- /* Turn on DMA error (RX/TX will be enabled on demand) */
- uap->dmacr |= UART011_DMAONERR;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
-
- /*
- * ST Micro variants has some specific dma burst threshold
- * compensation. Set this to 16 bytes, so burst will only
- * be issued above/below 16 bytes.
- */
- if (uap->vendor->dma_threshold)
- writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
- uap->port.membase + ST_UART011_DMAWM);
-}
-
-static void pl011_dma_shutdown(struct uart_amba_port *uap)
-{
- if (!uap->using_dma)
- return;
-
- /* Disable RX and TX DMA */
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
- barrier();
-
- spin_lock_irq(&uap->port.lock);
- uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
- spin_unlock_irq(&uap->port.lock);
-
- /* In theory, this should already be done by pl011_dma_flush_buffer */
- dmaengine_terminate_all(uap->dmatx.chan);
- if (uap->dmatx.queued) {
- dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
- DMA_TO_DEVICE);
- uap->dmatx.queued = false;
- }
-
- kfree(uap->dmatx.buf);
-
- uap->using_dma = false;
-}
-
-#else
-/* Blank functions if the DMA engine is not available */
-static inline void pl011_dma_probe(struct uart_amba_port *uap)
-{
-}
-
-static inline void pl011_dma_remove(struct uart_amba_port *uap)
-{
-}
-
-static inline void pl011_dma_startup(struct uart_amba_port *uap)
-{
-}
-
-static inline void pl011_dma_shutdown(struct uart_amba_port *uap)
-{
-}
-
-static inline bool pl011_dma_tx_irq(struct uart_amba_port *uap)
-{
- return false;
-}
-
-static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
-{
-}
-
-static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
-{
- return false;
-}
-
-#define pl011_dma_flush_buffer NULL
-#endif
-
-
-static void pl011_stop_tx(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- uap->im &= ~UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- pl011_dma_tx_stop(uap);
-}
-
-static void pl011_start_tx(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- if (!pl011_dma_tx_start(uap)) {
- uap->im |= UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- }
-}
-
-static void pl011_stop_rx(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
- UART011_PEIM|UART011_BEIM|UART011_OEIM);
- writew(uap->im, uap->port.membase + UART011_IMSC);
-}
-
-static void pl011_enable_ms(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
-}
-
-static void pl011_rx_chars(struct uart_amba_port *uap)
-{
- struct tty_struct *tty = uap->port.state->port.tty;
- unsigned int status, ch, flag, max_count = 256;
-
- status = readw(uap->port.membase + UART01x_FR);
- while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
- ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX;
- flag = TTY_NORMAL;
- uap->port.icount.rx++;
-
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- if (unlikely(ch & UART_DR_ERROR)) {
- if (ch & UART011_DR_BE) {
- ch &= ~(UART011_DR_FE | UART011_DR_PE);
- uap->port.icount.brk++;
- if (uart_handle_break(&uap->port))
- goto ignore_char;
- } else if (ch & UART011_DR_PE)
- uap->port.icount.parity++;
- else if (ch & UART011_DR_FE)
- uap->port.icount.frame++;
- if (ch & UART011_DR_OE)
- uap->port.icount.overrun++;
-
- ch &= uap->port.read_status_mask;
-
- if (ch & UART011_DR_BE)
- flag = TTY_BREAK;
- else if (ch & UART011_DR_PE)
- flag = TTY_PARITY;
- else if (ch & UART011_DR_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&uap->port, ch & 255))
- goto ignore_char;
-
- uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
-
- ignore_char:
- status = readw(uap->port.membase + UART01x_FR);
- }
- spin_unlock(&uap->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&uap->port.lock);
-}
-
-static void pl011_tx_chars(struct uart_amba_port *uap)
-{
- struct circ_buf *xmit = &uap->port.state->xmit;
- int count;
-
- if (uap->port.x_char) {
- writew(uap->port.x_char, uap->port.membase + UART01x_DR);
- uap->port.icount.tx++;
- uap->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
- pl011_stop_tx(&uap->port);
- return;
- }
-
- /* If we are using DMA mode, try to send some characters. */
- if (pl011_dma_tx_irq(uap))
- return;
-
- count = uap->fifosize >> 1;
- do {
- writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- uap->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uap->port);
-
- if (uart_circ_empty(xmit))
- pl011_stop_tx(&uap->port);
-}
-
-static void pl011_modem_status(struct uart_amba_port *uap)
-{
- unsigned int status, delta;
-
- status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
-
- delta = status ^ uap->old_status;
- uap->old_status = status;
-
- if (!delta)
- return;
-
- if (delta & UART01x_FR_DCD)
- uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
-
- if (delta & UART01x_FR_DSR)
- uap->port.icount.dsr++;
-
- if (delta & UART01x_FR_CTS)
- uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
-
- wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
-}
-
-static irqreturn_t pl011_int(int irq, void *dev_id)
-{
- struct uart_amba_port *uap = dev_id;
- unsigned long flags;
- unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
- int handled = 0;
-
- spin_lock_irqsave(&uap->port.lock, flags);
-
- status = readw(uap->port.membase + UART011_MIS);
- if (status) {
- do {
- writew(status & ~(UART011_TXIS|UART011_RTIS|
- UART011_RXIS),
- uap->port.membase + UART011_ICR);
-
- if (status & (UART011_RTIS|UART011_RXIS))
- pl011_rx_chars(uap);
- if (status & (UART011_DSRMIS|UART011_DCDMIS|
- UART011_CTSMIS|UART011_RIMIS))
- pl011_modem_status(uap);
- if (status & UART011_TXIS)
- pl011_tx_chars(uap);
-
- if (pass_counter-- == 0)
- break;
-
- status = readw(uap->port.membase + UART011_MIS);
- } while (status != 0);
- handled = 1;
- }
-
- spin_unlock_irqrestore(&uap->port.lock, flags);
-
- return IRQ_RETVAL(handled);
-}
-
-static unsigned int pl01x_tx_empty(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int status = readw(uap->port.membase + UART01x_FR);
- return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
-}
-
-static unsigned int pl01x_get_mctrl(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int result = 0;
- unsigned int status = readw(uap->port.membase + UART01x_FR);
-
-#define TIOCMBIT(uartbit, tiocmbit) \
- if (status & uartbit) \
- result |= tiocmbit
-
- TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
- TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR);
- TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS);
- TIOCMBIT(UART011_FR_RI, TIOCM_RNG);
-#undef TIOCMBIT
- return result;
-}
-
-static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int cr;
-
- cr = readw(uap->port.membase + UART011_CR);
-
-#define TIOCMBIT(tiocmbit, uartbit) \
- if (mctrl & tiocmbit) \
- cr |= uartbit; \
- else \
- cr &= ~uartbit
-
- TIOCMBIT(TIOCM_RTS, UART011_CR_RTS);
- TIOCMBIT(TIOCM_DTR, UART011_CR_DTR);
- TIOCMBIT(TIOCM_OUT1, UART011_CR_OUT1);
- TIOCMBIT(TIOCM_OUT2, UART011_CR_OUT2);
- TIOCMBIT(TIOCM_LOOP, UART011_CR_LBE);
-
- if (uap->autorts) {
- /* We need to disable auto-RTS if we want to turn RTS off */
- TIOCMBIT(TIOCM_RTS, UART011_CR_RTSEN);
- }
-#undef TIOCMBIT
-
- writew(cr, uap->port.membase + UART011_CR);
-}
-
-static void pl011_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned long flags;
- unsigned int lcr_h;
-
- spin_lock_irqsave(&uap->port.lock, flags);
- lcr_h = readw(uap->port.membase + uap->lcrh_tx);
- if (break_state == -1)
- lcr_h |= UART01x_LCRH_BRK;
- else
- lcr_h &= ~UART01x_LCRH_BRK;
- writew(lcr_h, uap->port.membase + uap->lcrh_tx);
- spin_unlock_irqrestore(&uap->port.lock, flags);
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-static int pl010_get_poll_char(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int status;
-
- status = readw(uap->port.membase + UART01x_FR);
- if (status & UART01x_FR_RXFE)
- return NO_POLL_CHAR;
-
- return readw(uap->port.membase + UART01x_DR);
-}
-
-static void pl010_put_poll_char(struct uart_port *port,
- unsigned char ch)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
- barrier();
-
- writew(ch, uap->port.membase + UART01x_DR);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int pl011_startup(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int cr;
- int retval;
-
- /*
- * Try to enable the clock producer.
- */
- retval = clk_enable(uap->clk);
- if (retval)
- goto out;
-
- uap->port.uartclk = clk_get_rate(uap->clk);
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
- if (retval)
- goto clk_dis;
-
- writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
-
- /*
- * Provoke TX FIFO interrupt into asserting.
- */
- cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
- writew(cr, uap->port.membase + UART011_CR);
- writew(0, uap->port.membase + UART011_FBRD);
- writew(1, uap->port.membase + UART011_IBRD);
- writew(0, uap->port.membase + uap->lcrh_rx);
- if (uap->lcrh_tx != uap->lcrh_rx) {
- int i;
- /*
- * Wait 10 PCLKs before writing LCRH_TX register,
- * to get this delay write read only register 10 times
- */
- for (i = 0; i < 10; ++i)
- writew(0xff, uap->port.membase + UART011_MIS);
- writew(0, uap->port.membase + uap->lcrh_tx);
- }
- writew(0, uap->port.membase + UART01x_DR);
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
- barrier();
-
- cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
- writew(cr, uap->port.membase + UART011_CR);
-
- /* Clear pending error interrupts */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
- uap->port.membase + UART011_ICR);
-
- /*
- * initialise the old status of the modem signals
- */
- uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
-
- /* Startup DMA */
- pl011_dma_startup(uap);
-
- /*
- * Finally, enable interrupts
- */
- spin_lock_irq(&uap->port.lock);
- uap->im = UART011_RXIM | UART011_RTIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- spin_unlock_irq(&uap->port.lock);
-
- return 0;
-
- clk_dis:
- clk_disable(uap->clk);
- out:
- return retval;
-}
-
-static void pl011_shutdown_channel(struct uart_amba_port *uap,
- unsigned int lcrh)
-{
- unsigned long val;
-
- val = readw(uap->port.membase + lcrh);
- val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
- writew(val, uap->port.membase + lcrh);
-}
-
-static void pl011_shutdown(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- /*
- * disable all interrupts
- */
- spin_lock_irq(&uap->port.lock);
- uap->im = 0;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- writew(0xffff, uap->port.membase + UART011_ICR);
- spin_unlock_irq(&uap->port.lock);
-
- pl011_dma_shutdown(uap);
-
- /*
- * Free the interrupt
- */
- free_irq(uap->port.irq, uap);
-
- /*
- * disable the port
- */
- uap->autorts = false;
- writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);
-
- /*
- * disable break condition and fifos
- */
- pl011_shutdown_channel(uap, uap->lcrh_rx);
- if (uap->lcrh_rx != uap->lcrh_tx)
- pl011_shutdown_channel(uap, uap->lcrh_tx);
-
- /*
- * Shut down the clock producer
- */
- clk_disable(uap->clk);
-}
-
-static void
-pl011_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int lcr_h, old_cr;
- unsigned long flags;
- unsigned int baud, quot, clkdiv;
-
- if (uap->vendor->oversampling)
- clkdiv = 8;
- else
- clkdiv = 16;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0,
- port->uartclk / clkdiv);
-
- if (baud > port->uartclk/16)
- quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
- else
- quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud);
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- lcr_h = UART01x_LCRH_WLEN_5;
- break;
- case CS6:
- lcr_h = UART01x_LCRH_WLEN_6;
- break;
- case CS7:
- lcr_h = UART01x_LCRH_WLEN_7;
- break;
- default: // CS8
- lcr_h = UART01x_LCRH_WLEN_8;
- break;
- }
- if (termios->c_cflag & CSTOPB)
- lcr_h |= UART01x_LCRH_STP2;
- if (termios->c_cflag & PARENB) {
- lcr_h |= UART01x_LCRH_PEN;
- if (!(termios->c_cflag & PARODD))
- lcr_h |= UART01x_LCRH_EPS;
- }
- if (uap->fifosize > 1)
- lcr_h |= UART01x_LCRH_FEN;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- port->read_status_mask = UART011_DR_OE | 255;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= UART011_DR_FE | UART011_DR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= UART011_DR_BE;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART011_DR_FE | UART011_DR_PE;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= UART011_DR_BE;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART011_DR_OE;
- }
-
- /*
- * Ignore all characters if CREAD is not set.
- */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= UART_DUMMY_DR_RX;
-
- if (UART_ENABLE_MS(port, termios->c_cflag))
- pl011_enable_ms(port);
-
- /* first, disable everything */
- old_cr = readw(port->membase + UART011_CR);
- writew(0, port->membase + UART011_CR);
-
- if (termios->c_cflag & CRTSCTS) {
- if (old_cr & UART011_CR_RTS)
- old_cr |= UART011_CR_RTSEN;
-
- old_cr |= UART011_CR_CTSEN;
- uap->autorts = true;
- } else {
- old_cr &= ~(UART011_CR_CTSEN | UART011_CR_RTSEN);
- uap->autorts = false;
- }
-
- if (uap->vendor->oversampling) {
- if (baud > port->uartclk / 16)
- old_cr |= ST_UART011_CR_OVSFACT;
- else
- old_cr &= ~ST_UART011_CR_OVSFACT;
- }
-
- /* Set baud rate */
- writew(quot & 0x3f, port->membase + UART011_FBRD);
- writew(quot >> 6, port->membase + UART011_IBRD);
-
- /*
- * ----------v----------v----------v----------v-----
- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
- * ----------^----------^----------^----------^-----
- */
- writew(lcr_h, port->membase + uap->lcrh_rx);
- if (uap->lcrh_rx != uap->lcrh_tx) {
- int i;
- /*
- * Wait 10 PCLKs before writing LCRH_TX register,
- * to get this delay write read only register 10 times
- */
- for (i = 0; i < 10; ++i)
- writew(0xff, uap->port.membase + UART011_MIS);
- writew(lcr_h, port->membase + uap->lcrh_tx);
- }
- writew(old_cr, port->membase + UART011_CR);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *pl011_type(struct uart_port *port)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
- return uap->port.type == PORT_AMBA ? uap->type : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'
- */
-static void pl010_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, SZ_4K);
-}
-
-/*
- * Request the memory region(s) being used by 'port'
- */
-static int pl010_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")
- != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void pl010_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_AMBA;
- pl010_request_port(port);
- }
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
- ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
- ret = -EINVAL;
- if (ser->baud_base < 9600)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops amba_pl011_pops = {
- .tx_empty = pl01x_tx_empty,
- .set_mctrl = pl011_set_mctrl,
- .get_mctrl = pl01x_get_mctrl,
- .stop_tx = pl011_stop_tx,
- .start_tx = pl011_start_tx,
- .stop_rx = pl011_stop_rx,
- .enable_ms = pl011_enable_ms,
- .break_ctl = pl011_break_ctl,
- .startup = pl011_startup,
- .shutdown = pl011_shutdown,
- .flush_buffer = pl011_dma_flush_buffer,
- .set_termios = pl011_set_termios,
- .type = pl011_type,
- .release_port = pl010_release_port,
- .request_port = pl010_request_port,
- .config_port = pl010_config_port,
- .verify_port = pl010_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = pl010_get_poll_char,
- .poll_put_char = pl010_put_poll_char,
-#endif
-};
-
-static struct uart_amba_port *amba_ports[UART_NR];
-
-#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
-
-static void pl011_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_amba_port *uap = (struct uart_amba_port *)port;
-
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
- barrier();
- writew(ch, uap->port.membase + UART01x_DR);
-}
-
-static void
-pl011_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_amba_port *uap = amba_ports[co->index];
- unsigned int status, old_cr, new_cr;
-
- clk_enable(uap->clk);
-
- /*
- * First save the CR then disable the interrupts
- */
- old_cr = readw(uap->port.membase + UART011_CR);
- new_cr = old_cr & ~UART011_CR_CTSEN;
- new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
- writew(new_cr, uap->port.membase + UART011_CR);
-
- uart_console_write(&uap->port, s, count, pl011_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the TCR
- */
- do {
- status = readw(uap->port.membase + UART01x_FR);
- } while (status & UART01x_FR_BUSY);
- writew(old_cr, uap->port.membase + UART011_CR);
-
- clk_disable(uap->clk);
-}
-
-static void __init
-pl011_console_get_options(struct uart_amba_port *uap, int *baud,
- int *parity, int *bits)
-{
- if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
- unsigned int lcr_h, ibrd, fbrd;
-
- lcr_h = readw(uap->port.membase + uap->lcrh_tx);
-
- *parity = 'n';
- if (lcr_h & UART01x_LCRH_PEN) {
- if (lcr_h & UART01x_LCRH_EPS)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7)
- *bits = 7;
- else
- *bits = 8;
-
- ibrd = readw(uap->port.membase + UART011_IBRD);
- fbrd = readw(uap->port.membase + UART011_FBRD);
-
- *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
-
- if (uap->vendor->oversampling) {
- if (readw(uap->port.membase + UART011_CR)
- & ST_UART011_CR_OVSFACT)
- *baud *= 2;
- }
- }
-}
-
-static int __init pl011_console_setup(struct console *co, char *options)
-{
- struct uart_amba_port *uap;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- uap = amba_ports[co->index];
- if (!uap)
- return -ENODEV;
-
- uap->port.uartclk = clk_get_rate(uap->clk);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- pl011_console_get_options(uap, &baud, &parity, &bits);
-
- return uart_set_options(&uap->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver amba_reg;
-static struct console amba_console = {
- .name = "ttyAMA",
- .write = pl011_console_write,
- .device = uart_console_device,
- .setup = pl011_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &amba_reg,
-};
-
-#define AMBA_CONSOLE (&amba_console)
-#else
-#define AMBA_CONSOLE NULL
-#endif
-
-static struct uart_driver amba_reg = {
- .owner = THIS_MODULE,
- .driver_name = "ttyAMA",
- .dev_name = "ttyAMA",
- .major = SERIAL_AMBA_MAJOR,
- .minor = SERIAL_AMBA_MINOR,
- .nr = UART_NR,
- .cons = AMBA_CONSOLE,
-};
-
-static int pl011_probe(struct amba_device *dev, struct amba_id *id)
-{
- struct uart_amba_port *uap;
- struct vendor_data *vendor = id->data;
- void __iomem *base;
- int i, ret;
-
- for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
- if (amba_ports[i] == NULL)
- break;
-
- if (i == ARRAY_SIZE(amba_ports)) {
- ret = -EBUSY;
- goto out;
- }
-
- uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
- if (uap == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- base = ioremap(dev->res.start, resource_size(&dev->res));
- if (!base) {
- ret = -ENOMEM;
- goto free;
- }
-
- uap->clk = clk_get(&dev->dev, NULL);
- if (IS_ERR(uap->clk)) {
- ret = PTR_ERR(uap->clk);
- goto unmap;
- }
-
- uap->vendor = vendor;
- uap->lcrh_rx = vendor->lcrh_rx;
- uap->lcrh_tx = vendor->lcrh_tx;
- uap->fifosize = vendor->fifosize;
- uap->port.dev = &dev->dev;
- uap->port.mapbase = dev->res.start;
- uap->port.membase = base;
- uap->port.iotype = UPIO_MEM;
- uap->port.irq = dev->irq[0];
- uap->port.fifosize = uap->fifosize;
- uap->port.ops = &amba_pl011_pops;
- uap->port.flags = UPF_BOOT_AUTOCONF;
- uap->port.line = i;
- pl011_dma_probe(uap);
-
- snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
-
- amba_ports[i] = uap;
-
- amba_set_drvdata(dev, uap);
- ret = uart_add_one_port(&amba_reg, &uap->port);
- if (ret) {
- amba_set_drvdata(dev, NULL);
- amba_ports[i] = NULL;
- pl011_dma_remove(uap);
- clk_put(uap->clk);
- unmap:
- iounmap(base);
- free:
- kfree(uap);
- }
- out:
- return ret;
-}
-
-static int pl011_remove(struct amba_device *dev)
-{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
- int i;
-
- amba_set_drvdata(dev, NULL);
-
- uart_remove_one_port(&amba_reg, &uap->port);
-
- for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
- if (amba_ports[i] == uap)
- amba_ports[i] = NULL;
-
- pl011_dma_remove(uap);
- iounmap(uap->port.membase);
- clk_put(uap->clk);
- kfree(uap);
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int pl011_suspend(struct amba_device *dev, pm_message_t state)
-{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
-
- if (!uap)
- return -EINVAL;
-
- return uart_suspend_port(&amba_reg, &uap->port);
-}
-
-static int pl011_resume(struct amba_device *dev)
-{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
-
- if (!uap)
- return -EINVAL;
-
- return uart_resume_port(&amba_reg, &uap->port);
-}
-#endif
-
-static struct amba_id pl011_ids[] = {
- {
- .id = 0x00041011,
- .mask = 0x000fffff,
- .data = &vendor_arm,
- },
- {
- .id = 0x00380802,
- .mask = 0x00ffffff,
- .data = &vendor_st,
- },
- { 0, 0 },
-};
-
-static struct amba_driver pl011_driver = {
- .drv = {
- .name = "uart-pl011",
- },
- .id_table = pl011_ids,
- .probe = pl011_probe,
- .remove = pl011_remove,
-#ifdef CONFIG_PM
- .suspend = pl011_suspend,
- .resume = pl011_resume,
-#endif
-};
-
-static int __init pl011_init(void)
-{
- int ret;
- printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
-
- ret = uart_register_driver(&amba_reg);
- if (ret == 0) {
- ret = amba_driver_register(&pl011_driver);
- if (ret)
- uart_unregister_driver(&amba_reg);
- }
- return ret;
-}
-
-static void __exit pl011_exit(void)
-{
- amba_driver_unregister(&pl011_driver);
- uart_unregister_driver(&amba_reg);
-}
-
-/*
- * While this can be a module, if builtin it's most likely the console
- * So let's leave module_exit but move module_init to an earlier place
- */
-arch_initcall(pl011_init);
-module_exit(pl011_exit);
-
-MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("ARM AMBA serial port driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c
deleted file mode 100644
index 095a5d562618..000000000000
--- a/drivers/serial/apbuart.c
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * Driver for GRLIB serial ports (APBUART)
- *
- * Based on linux/drivers/serial/amba.c
- *
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- * Copyright (C) 2003 Konrad Eisele <eiselekd@web.de>
- * Copyright (C) 2006 Daniel Hellstrom <daniel@gaisler.com>, Aeroflex Gaisler AB
- * Copyright (C) 2008 Gilead Kutnick <kutnickg@zin-tech.com>
- * Copyright (C) 2009 Kristoffer Glembo <kristoffer@gaisler.com>, Aeroflex Gaisler AB
- */
-
-#if defined(CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/kthread.h>
-#include <linux/device.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/serial_core.h>
-#include <asm/irq.h>
-
-#include "apbuart.h"
-
-#define SERIAL_APBUART_MAJOR TTY_MAJOR
-#define SERIAL_APBUART_MINOR 64
-#define UART_DUMMY_RSR_RX 0x8000 /* for ignore all read */
-
-static void apbuart_tx_chars(struct uart_port *port);
-
-static void apbuart_stop_tx(struct uart_port *port)
-{
- unsigned int cr;
-
- cr = UART_GET_CTRL(port);
- cr &= ~UART_CTRL_TI;
- UART_PUT_CTRL(port, cr);
-}
-
-static void apbuart_start_tx(struct uart_port *port)
-{
- unsigned int cr;
-
- cr = UART_GET_CTRL(port);
- cr |= UART_CTRL_TI;
- UART_PUT_CTRL(port, cr);
-
- if (UART_GET_STATUS(port) & UART_STATUS_THE)
- apbuart_tx_chars(port);
-}
-
-static void apbuart_stop_rx(struct uart_port *port)
-{
- unsigned int cr;
-
- cr = UART_GET_CTRL(port);
- cr &= ~(UART_CTRL_RI);
- UART_PUT_CTRL(port, cr);
-}
-
-static void apbuart_enable_ms(struct uart_port *port)
-{
- /* No modem status change interrupts for APBUART */
-}
-
-static void apbuart_rx_chars(struct uart_port *port)
-{
- struct tty_struct *tty = port->state->port.tty;
- unsigned int status, ch, rsr, flag;
- unsigned int max_chars = port->fifosize;
-
- status = UART_GET_STATUS(port);
-
- while (UART_RX_DATA(status) && (max_chars--)) {
-
- ch = UART_GET_CHAR(port);
- flag = TTY_NORMAL;
-
- port->icount.rx++;
-
- rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX;
- UART_PUT_STATUS(port, 0);
- if (rsr & UART_STATUS_ERR) {
-
- if (rsr & UART_STATUS_BR) {
- rsr &= ~(UART_STATUS_FE | UART_STATUS_PE);
- port->icount.brk++;
- if (uart_handle_break(port))
- goto ignore_char;
- } else if (rsr & UART_STATUS_PE) {
- port->icount.parity++;
- } else if (rsr & UART_STATUS_FE) {
- port->icount.frame++;
- }
- if (rsr & UART_STATUS_OE)
- port->icount.overrun++;
-
- rsr &= port->read_status_mask;
-
- if (rsr & UART_STATUS_PE)
- flag = TTY_PARITY;
- else if (rsr & UART_STATUS_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
-
- uart_insert_char(port, rsr, UART_STATUS_OE, ch, flag);
-
-
- ignore_char:
- status = UART_GET_STATUS(port);
- }
-
- tty_flip_buffer_push(tty);
-}
-
-static void apbuart_tx_chars(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
- int count;
-
- if (port->x_char) {
- UART_PUT_CHAR(port, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- apbuart_stop_tx(port);
- return;
- }
-
- /* amba: fill FIFO */
- count = port->fifosize >> 1;
- do {
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- apbuart_stop_tx(port);
-}
-
-static irqreturn_t apbuart_int(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- unsigned int status;
-
- spin_lock(&port->lock);
-
- status = UART_GET_STATUS(port);
- if (status & UART_STATUS_DR)
- apbuart_rx_chars(port);
- if (status & UART_STATUS_THE)
- apbuart_tx_chars(port);
-
- spin_unlock(&port->lock);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int apbuart_tx_empty(struct uart_port *port)
-{
- unsigned int status = UART_GET_STATUS(port);
- return status & UART_STATUS_THE ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int apbuart_get_mctrl(struct uart_port *port)
-{
- /* The GRLIB APBUART handles flow control in hardware */
- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-}
-
-static void apbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- /* The GRLIB APBUART handles flow control in hardware */
-}
-
-static void apbuart_break_ctl(struct uart_port *port, int break_state)
-{
- /* We don't support sending break */
-}
-
-static int apbuart_startup(struct uart_port *port)
-{
- int retval;
- unsigned int cr;
-
- /* Allocate the IRQ */
- retval = request_irq(port->irq, apbuart_int, 0, "apbuart", port);
- if (retval)
- return retval;
-
- /* Finally, enable interrupts */
- cr = UART_GET_CTRL(port);
- UART_PUT_CTRL(port,
- cr | UART_CTRL_RE | UART_CTRL_TE |
- UART_CTRL_RI | UART_CTRL_TI);
-
- return 0;
-}
-
-static void apbuart_shutdown(struct uart_port *port)
-{
- unsigned int cr;
-
- /* disable all interrupts, disable the port */
- cr = UART_GET_CTRL(port);
- UART_PUT_CTRL(port,
- cr & ~(UART_CTRL_RE | UART_CTRL_TE |
- UART_CTRL_RI | UART_CTRL_TI));
-
- /* Free the interrupt */
- free_irq(port->irq, port);
-}
-
-static void apbuart_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- unsigned int cr;
- unsigned long flags;
- unsigned int baud, quot;
-
- /* Ask the core to calculate the divisor for us. */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
- if (baud == 0)
- panic("invalid baudrate %i\n", port->uartclk / 16);
-
- /* uart_get_divisor calc a *16 uart freq, apbuart is *8 */
- quot = (uart_get_divisor(port, baud)) * 2;
- cr = UART_GET_CTRL(port);
- cr &= ~(UART_CTRL_PE | UART_CTRL_PS);
-
- if (termios->c_cflag & PARENB) {
- cr |= UART_CTRL_PE;
- if ((termios->c_cflag & PARODD))
- cr |= UART_CTRL_PS;
- }
-
- /* Enable flow control. */
- if (termios->c_cflag & CRTSCTS)
- cr |= UART_CTRL_FL;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Update the per-port timeout. */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- port->read_status_mask = UART_STATUS_OE;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= UART_STATUS_FE | UART_STATUS_PE;
-
- /* Characters to ignore */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_STATUS_FE | UART_STATUS_PE;
-
- /* Ignore all characters if CREAD is not set. */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= UART_DUMMY_RSR_RX;
-
- /* Set baud rate */
- quot -= 1;
- UART_PUT_SCAL(port, quot);
- UART_PUT_CTRL(port, cr);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *apbuart_type(struct uart_port *port)
-{
- return port->type == PORT_APBUART ? "GRLIB/APBUART" : NULL;
-}
-
-static void apbuart_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, 0x100);
-}
-
-static int apbuart_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, 0x100, "grlib-apbuart")
- != NULL ? 0 : -EBUSY;
- return 0;
-}
-
-/* Configure/autoconfigure the port */
-static void apbuart_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_APBUART;
- apbuart_request_port(port);
- }
-}
-
-/* Verify the new serial_struct (for TIOCSSERIAL) */
-static int apbuart_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_APBUART)
- ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
- ret = -EINVAL;
- if (ser->baud_base < 9600)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops grlib_apbuart_ops = {
- .tx_empty = apbuart_tx_empty,
- .set_mctrl = apbuart_set_mctrl,
- .get_mctrl = apbuart_get_mctrl,
- .stop_tx = apbuart_stop_tx,
- .start_tx = apbuart_start_tx,
- .stop_rx = apbuart_stop_rx,
- .enable_ms = apbuart_enable_ms,
- .break_ctl = apbuart_break_ctl,
- .startup = apbuart_startup,
- .shutdown = apbuart_shutdown,
- .set_termios = apbuart_set_termios,
- .type = apbuart_type,
- .release_port = apbuart_release_port,
- .request_port = apbuart_request_port,
- .config_port = apbuart_config_port,
- .verify_port = apbuart_verify_port,
-};
-
-static struct uart_port grlib_apbuart_ports[UART_NR];
-static struct device_node *grlib_apbuart_nodes[UART_NR];
-
-static int apbuart_scan_fifo_size(struct uart_port *port, int portnumber)
-{
- int ctrl, loop = 0;
- int status;
- int fifosize;
- unsigned long flags;
-
- ctrl = UART_GET_CTRL(port);
-
- /*
- * Enable the transceiver and wait for it to be ready to send data.
- * Clear interrupts so that this process will not be externally
- * interrupted in the middle (which can cause the transceiver to
- * drain prematurely).
- */
-
- local_irq_save(flags);
-
- UART_PUT_CTRL(port, ctrl | UART_CTRL_TE);
-
- while (!UART_TX_READY(UART_GET_STATUS(port)))
- loop++;
-
- /*
- * Disable the transceiver so data isn't actually sent during the
- * actual test.
- */
-
- UART_PUT_CTRL(port, ctrl & ~(UART_CTRL_TE));
-
- fifosize = 1;
- UART_PUT_CHAR(port, 0);
-
- /*
- * So long as transmitting a character increments the tranceivier FIFO
- * length the FIFO must be at least that big. These bytes will
- * automatically drain off of the FIFO.
- */
-
- status = UART_GET_STATUS(port);
- while (((status >> 20) & 0x3F) == fifosize) {
- fifosize++;
- UART_PUT_CHAR(port, 0);
- status = UART_GET_STATUS(port);
- }
-
- fifosize--;
-
- UART_PUT_CTRL(port, ctrl);
- local_irq_restore(flags);
-
- if (fifosize == 0)
- fifosize = 1;
-
- return fifosize;
-}
-
-static void apbuart_flush_fifo(struct uart_port *port)
-{
- int i;
-
- for (i = 0; i < port->fifosize; i++)
- UART_GET_CHAR(port);
-}
-
-
-/* ======================================================================== */
-/* Console driver, if enabled */
-/* ======================================================================== */
-
-#ifdef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
-
-static void apbuart_console_putchar(struct uart_port *port, int ch)
-{
- unsigned int status;
- do {
- status = UART_GET_STATUS(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CHAR(port, ch);
-}
-
-static void
-apbuart_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_port *port = &grlib_apbuart_ports[co->index];
- unsigned int status, old_cr, new_cr;
-
- /* First save the CR then disable the interrupts */
- old_cr = UART_GET_CTRL(port);
- new_cr = old_cr & ~(UART_CTRL_RI | UART_CTRL_TI);
- UART_PUT_CTRL(port, new_cr);
-
- uart_console_write(port, s, count, apbuart_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the TCR
- */
- do {
- status = UART_GET_STATUS(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CTRL(port, old_cr);
-}
-
-static void __init
-apbuart_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- if (UART_GET_CTRL(port) & (UART_CTRL_RE | UART_CTRL_TE)) {
-
- unsigned int quot, status;
- status = UART_GET_STATUS(port);
-
- *parity = 'n';
- if (status & UART_CTRL_PE) {
- if ((status & UART_CTRL_PS) == 0)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- *bits = 8;
- quot = UART_GET_SCAL(port) / 8;
- *baud = port->uartclk / (16 * (quot + 1));
- }
-}
-
-static int __init apbuart_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- pr_debug("apbuart_console_setup co=%p, co->index=%i, options=%s\n",
- co, co->index, options);
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= grlib_apbuart_port_nr)
- co->index = 0;
-
- port = &grlib_apbuart_ports[co->index];
-
- spin_lock_init(&port->lock);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- apbuart_console_get_options(port, &baud, &parity, &bits);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver grlib_apbuart_driver;
-
-static struct console grlib_apbuart_console = {
- .name = "ttyS",
- .write = apbuart_console_write,
- .device = uart_console_device,
- .setup = apbuart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &grlib_apbuart_driver,
-};
-
-
-static int grlib_apbuart_configure(void);
-
-static int __init apbuart_console_init(void)
-{
- if (grlib_apbuart_configure())
- return -ENODEV;
- register_console(&grlib_apbuart_console);
- return 0;
-}
-
-console_initcall(apbuart_console_init);
-
-#define APBUART_CONSOLE (&grlib_apbuart_console)
-#else
-#define APBUART_CONSOLE NULL
-#endif
-
-static struct uart_driver grlib_apbuart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .dev_name = "ttyS",
- .major = SERIAL_APBUART_MAJOR,
- .minor = SERIAL_APBUART_MINOR,
- .nr = UART_NR,
- .cons = APBUART_CONSOLE,
-};
-
-
-/* ======================================================================== */
-/* OF Platform Driver */
-/* ======================================================================== */
-
-static int __devinit apbuart_probe(struct platform_device *op,
- const struct of_device_id *match)
-{
- int i = -1;
- struct uart_port *port = NULL;
-
- i = 0;
- for (i = 0; i < grlib_apbuart_port_nr; i++) {
- if (op->dev.of_node == grlib_apbuart_nodes[i])
- break;
- }
-
- port = &grlib_apbuart_ports[i];
- port->dev = &op->dev;
-
- uart_add_one_port(&grlib_apbuart_driver, (struct uart_port *) port);
-
- apbuart_flush_fifo((struct uart_port *) port);
-
- printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n",
- (unsigned long long) port->mapbase, port->irq);
- return 0;
-}
-
-static struct of_device_id __initdata apbuart_match[] = {
- {
- .name = "GAISLER_APBUART",
- },
- {
- .name = "01_00c",
- },
- {},
-};
-
-static struct of_platform_driver grlib_apbuart_of_driver = {
- .probe = apbuart_probe,
- .driver = {
- .owner = THIS_MODULE,
- .name = "grlib-apbuart",
- .of_match_table = apbuart_match,
- },
-};
-
-
-static int grlib_apbuart_configure(void)
-{
- struct device_node *np, *rp;
- const u32 *prop;
- int freq_khz, line = 0;
-
- /* Get bus frequency */
- rp = of_find_node_by_path("/");
- if (!rp)
- return -ENODEV;
- rp = of_get_next_child(rp, NULL);
- if (!rp)
- return -ENODEV;
- prop = of_get_property(rp, "clock-frequency", NULL);
- if (!prop)
- return -ENODEV;
- freq_khz = *prop;
-
- for_each_matching_node(np, apbuart_match) {
- const int *irqs, *ampopts;
- const struct amba_prom_registers *regs;
- struct uart_port *port;
- unsigned long addr;
-
- ampopts = of_get_property(np, "ampopts", NULL);
- if (ampopts && (*ampopts == 0))
- continue; /* Ignore if used by another OS instance */
-
- irqs = of_get_property(np, "interrupts", NULL);
- regs = of_get_property(np, "reg", NULL);
-
- if (!irqs || !regs)
- continue;
-
- grlib_apbuart_nodes[line] = np;
-
- addr = regs->phys_addr;
-
- port = &grlib_apbuart_ports[line];
-
- port->mapbase = addr;
- port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map));
- port->irq = *irqs;
- port->iotype = UPIO_MEM;
- port->ops = &grlib_apbuart_ops;
- port->flags = UPF_BOOT_AUTOCONF;
- port->line = line;
- port->uartclk = freq_khz * 1000;
- port->fifosize = apbuart_scan_fifo_size((struct uart_port *) port, line);
- line++;
-
- /* We support maximum UART_NR uarts ... */
- if (line == UART_NR)
- break;
- }
-
- grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line;
- return line ? 0 : -ENODEV;
-}
-
-static int __init grlib_apbuart_init(void)
-{
- int ret;
-
- /* Find all APBUARTS in device the tree and initialize their ports */
- ret = grlib_apbuart_configure();
- if (ret)
- return ret;
-
- printk(KERN_INFO "Serial: GRLIB APBUART driver\n");
-
- ret = uart_register_driver(&grlib_apbuart_driver);
-
- if (ret) {
- printk(KERN_ERR "%s: uart_register_driver failed (%i)\n",
- __FILE__, ret);
- return ret;
- }
-
- ret = of_register_platform_driver(&grlib_apbuart_of_driver);
- if (ret) {
- printk(KERN_ERR
- "%s: of_register_platform_driver failed (%i)\n",
- __FILE__, ret);
- uart_unregister_driver(&grlib_apbuart_driver);
- return ret;
- }
-
- return ret;
-}
-
-static void __exit grlib_apbuart_exit(void)
-{
- int i;
-
- for (i = 0; i < grlib_apbuart_port_nr; i++)
- uart_remove_one_port(&grlib_apbuart_driver,
- &grlib_apbuart_ports[i]);
-
- uart_unregister_driver(&grlib_apbuart_driver);
- of_unregister_platform_driver(&grlib_apbuart_of_driver);
-}
-
-module_init(grlib_apbuart_init);
-module_exit(grlib_apbuart_exit);
-
-MODULE_AUTHOR("Aeroflex Gaisler AB");
-MODULE_DESCRIPTION("GRLIB APBUART serial driver");
-MODULE_VERSION("2.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/apbuart.h b/drivers/serial/apbuart.h
deleted file mode 100644
index 5faf87c8d2bc..000000000000
--- a/drivers/serial/apbuart.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __GRLIB_APBUART_H__
-#define __GRLIB_APBUART_H__
-
-#include <asm/io.h>
-
-#define UART_NR 8
-static int grlib_apbuart_port_nr;
-
-struct grlib_apbuart_regs_map {
- u32 data;
- u32 status;
- u32 ctrl;
- u32 scaler;
-};
-
-struct amba_prom_registers {
- unsigned int phys_addr;
- unsigned int reg_size;
-};
-
-/*
- * The following defines the bits in the APBUART Status Registers.
- */
-#define UART_STATUS_DR 0x00000001 /* Data Ready */
-#define UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
-#define UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
-#define UART_STATUS_BR 0x00000008 /* Break Error */
-#define UART_STATUS_OE 0x00000010 /* RX Overrun Error */
-#define UART_STATUS_PE 0x00000020 /* RX Parity Error */
-#define UART_STATUS_FE 0x00000040 /* RX Framing Error */
-#define UART_STATUS_ERR 0x00000078 /* Error Mask */
-
-/*
- * The following defines the bits in the APBUART Ctrl Registers.
- */
-#define UART_CTRL_RE 0x00000001 /* Receiver enable */
-#define UART_CTRL_TE 0x00000002 /* Transmitter enable */
-#define UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
-#define UART_CTRL_TI 0x00000008 /* Transmitter irq */
-#define UART_CTRL_PS 0x00000010 /* Parity select */
-#define UART_CTRL_PE 0x00000020 /* Parity enable */
-#define UART_CTRL_FL 0x00000040 /* Flow control enable */
-#define UART_CTRL_LB 0x00000080 /* Loopback enable */
-
-#define APBBASE(port) ((struct grlib_apbuart_regs_map *)((port)->membase))
-
-#define APBBASE_DATA_P(port) (&(APBBASE(port)->data))
-#define APBBASE_STATUS_P(port) (&(APBBASE(port)->status))
-#define APBBASE_CTRL_P(port) (&(APBBASE(port)->ctrl))
-#define APBBASE_SCALAR_P(port) (&(APBBASE(port)->scaler))
-
-#define UART_GET_CHAR(port) (__raw_readl(APBBASE_DATA_P(port)))
-#define UART_PUT_CHAR(port, v) (__raw_writel(v, APBBASE_DATA_P(port)))
-#define UART_GET_STATUS(port) (__raw_readl(APBBASE_STATUS_P(port)))
-#define UART_PUT_STATUS(port, v)(__raw_writel(v, APBBASE_STATUS_P(port)))
-#define UART_GET_CTRL(port) (__raw_readl(APBBASE_CTRL_P(port)))
-#define UART_PUT_CTRL(port, v) (__raw_writel(v, APBBASE_CTRL_P(port)))
-#define UART_GET_SCAL(port) (__raw_readl(APBBASE_SCALAR_P(port)))
-#define UART_PUT_SCAL(port, v) (__raw_writel(v, APBBASE_SCALAR_P(port)))
-
-#define UART_RX_DATA(s) (((s) & UART_STATUS_DR) != 0)
-#define UART_TX_READY(s) (((s) & UART_STATUS_THE) != 0)
-
-#endif /* __GRLIB_APBUART_H__ */
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
deleted file mode 100644
index 3892666b5fbd..000000000000
--- a/drivers/serial/atmel_serial.c
+++ /dev/null
@@ -1,1808 +0,0 @@
-/*
- * linux/drivers/char/atmel_serial.c
- *
- * Driver for Atmel AT91 / AT32 Serial ports
- * Copyright (C) 2003 Rick Bronson
- *
- * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * DMA support added by Chip Coldwell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/clk.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/tty_flip.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-#include <linux/atmel_serial.h>
-#include <linux/uaccess.h>
-
-#include <asm/io.h>
-#include <asm/ioctls.h>
-
-#include <asm/mach/serial_at91.h>
-#include <mach/board.h>
-
-#ifdef CONFIG_ARM
-#include <mach/cpu.h>
-#include <mach/gpio.h>
-#endif
-
-#define PDC_BUFFER_SIZE 512
-/* Revisit: We should calculate this based on the actual port settings */
-#define PDC_RX_TIMEOUT (3 * 10) /* 3 bytes */
-
-#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-static void atmel_start_rx(struct uart_port *port);
-static void atmel_stop_rx(struct uart_port *port);
-
-#ifdef CONFIG_SERIAL_ATMEL_TTYAT
-
-/* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we
- * should coexist with the 8250 driver, such as if we have an external 16C550
- * UART. */
-#define SERIAL_ATMEL_MAJOR 204
-#define MINOR_START 154
-#define ATMEL_DEVICENAME "ttyAT"
-
-#else
-
-/* Use device name ttyS, major 4, minor 64-68. This is the usual serial port
- * name, but it is legally reserved for the 8250 driver. */
-#define SERIAL_ATMEL_MAJOR TTY_MAJOR
-#define MINOR_START 64
-#define ATMEL_DEVICENAME "ttyS"
-
-#endif
-
-#define ATMEL_ISR_PASS_LIMIT 256
-
-/* UART registers. CR is write-only, hence no GET macro */
-#define UART_PUT_CR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port) __raw_readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port) __raw_readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port) __raw_readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port) __raw_readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR)
-#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR)
-
- /* PDC registers */
-#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR)
-
-#define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port) __raw_readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
-
-#define UART_PUT_TPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
-#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
-
-static int (*atmel_open_hook)(struct uart_port *);
-static void (*atmel_close_hook)(struct uart_port *);
-
-struct atmel_dma_buffer {
- unsigned char *buf;
- dma_addr_t dma_addr;
- unsigned int dma_size;
- unsigned int ofs;
-};
-
-struct atmel_uart_char {
- u16 status;
- u16 ch;
-};
-
-#define ATMEL_SERIAL_RINGSIZE 1024
-
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct atmel_uart_port {
- struct uart_port uart; /* uart */
- struct clk *clk; /* uart clock */
- int may_wakeup; /* cached value of device_may_wakeup for times we need to disable it */
- u32 backup_imr; /* IMR saved during suspend */
- int break_active; /* break being received */
-
- short use_dma_rx; /* enable PDC receiver */
- short pdc_rx_idx; /* current PDC RX buffer */
- struct atmel_dma_buffer pdc_rx[2]; /* PDC receier */
-
- short use_dma_tx; /* enable PDC transmitter */
- struct atmel_dma_buffer pdc_tx; /* PDC transmitter */
-
- struct tasklet_struct tasklet;
- unsigned int irq_status;
- unsigned int irq_status_prev;
-
- struct circ_buf rx_ring;
-
- struct serial_rs485 rs485; /* rs485 settings */
- unsigned int tx_done_mask;
-};
-
-static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
-
-#ifdef SUPPORT_SYSRQ
-static struct console atmel_console;
-#endif
-
-static inline struct atmel_uart_port *
-to_atmel_uart_port(struct uart_port *uart)
-{
- return container_of(uart, struct atmel_uart_port, uart);
-}
-
-#ifdef CONFIG_SERIAL_ATMEL_PDC
-static bool atmel_use_dma_rx(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- return atmel_port->use_dma_rx;
-}
-
-static bool atmel_use_dma_tx(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- return atmel_port->use_dma_tx;
-}
-#else
-static bool atmel_use_dma_rx(struct uart_port *port)
-{
- return false;
-}
-
-static bool atmel_use_dma_tx(struct uart_port *port)
-{
- return false;
-}
-#endif
-
-/* Enable or disable the rs485 support */
-void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- unsigned int mode;
-
- spin_lock(&port->lock);
-
- /* Disable interrupts */
- UART_PUT_IDR(port, atmel_port->tx_done_mask);
-
- mode = UART_GET_MR(port);
-
- /* Resetting serial mode to RS232 (0x0) */
- mode &= ~ATMEL_US_USMODE;
-
- atmel_port->rs485 = *rs485conf;
-
- if (rs485conf->flags & SER_RS485_ENABLED) {
- dev_dbg(port->dev, "Setting UART to RS485\n");
- atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
- if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
- UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
- mode |= ATMEL_US_USMODE_RS485;
- } else {
- dev_dbg(port->dev, "Setting UART to RS232\n");
- if (atmel_use_dma_tx(port))
- atmel_port->tx_done_mask = ATMEL_US_ENDTX |
- ATMEL_US_TXBUFE;
- else
- atmel_port->tx_done_mask = ATMEL_US_TXRDY;
- }
- UART_PUT_MR(port, mode);
-
- /* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
-
- spin_unlock(&port->lock);
-
-}
-
-/*
- * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
- */
-static u_int atmel_tx_empty(struct uart_port *port)
-{
- return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
-}
-
-/*
- * Set state of the modem control output lines
- */
-static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
-{
- unsigned int control = 0;
- unsigned int mode;
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
-#ifdef CONFIG_ARCH_AT91RM9200
- if (cpu_is_at91rm9200()) {
- /*
- * AT91RM9200 Errata #39: RTS0 is not internally connected
- * to PA21. We need to drive the pin manually.
- */
- if (port->mapbase == AT91RM9200_BASE_US0) {
- if (mctrl & TIOCM_RTS)
- at91_set_gpio_value(AT91_PIN_PA21, 0);
- else
- at91_set_gpio_value(AT91_PIN_PA21, 1);
- }
- }
-#endif
-
- if (mctrl & TIOCM_RTS)
- control |= ATMEL_US_RTSEN;
- else
- control |= ATMEL_US_RTSDIS;
-
- if (mctrl & TIOCM_DTR)
- control |= ATMEL_US_DTREN;
- else
- control |= ATMEL_US_DTRDIS;
-
- UART_PUT_CR(port, control);
-
- /* Local loopback mode? */
- mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE;
- if (mctrl & TIOCM_LOOP)
- mode |= ATMEL_US_CHMODE_LOC_LOOP;
- else
- mode |= ATMEL_US_CHMODE_NORMAL;
-
- /* Resetting serial mode to RS232 (0x0) */
- mode &= ~ATMEL_US_USMODE;
-
- if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
- dev_dbg(port->dev, "Setting UART to RS485\n");
- if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
- UART_PUT_TTGR(port,
- atmel_port->rs485.delay_rts_after_send);
- mode |= ATMEL_US_USMODE_RS485;
- } else {
- dev_dbg(port->dev, "Setting UART to RS232\n");
- }
- UART_PUT_MR(port, mode);
-}
-
-/*
- * Get state of the modem control input lines
- */
-static u_int atmel_get_mctrl(struct uart_port *port)
-{
- unsigned int status, ret = 0;
-
- status = UART_GET_CSR(port);
-
- /*
- * The control signals are active low.
- */
- if (!(status & ATMEL_US_DCD))
- ret |= TIOCM_CD;
- if (!(status & ATMEL_US_CTS))
- ret |= TIOCM_CTS;
- if (!(status & ATMEL_US_DSR))
- ret |= TIOCM_DSR;
- if (!(status & ATMEL_US_RI))
- ret |= TIOCM_RI;
-
- return ret;
-}
-
-/*
- * Stop transmitting.
- */
-static void atmel_stop_tx(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (atmel_use_dma_tx(port)) {
- /* disable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
- }
- /* Disable interrupts */
- UART_PUT_IDR(port, atmel_port->tx_done_mask);
-
- if (atmel_port->rs485.flags & SER_RS485_ENABLED)
- atmel_start_rx(port);
-}
-
-/*
- * Start transmitting.
- */
-static void atmel_start_tx(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (atmel_use_dma_tx(port)) {
- if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
- /* The transmitter is already running. Yes, we
- really need this.*/
- return;
-
- if (atmel_port->rs485.flags & SER_RS485_ENABLED)
- atmel_stop_rx(port);
-
- /* re-enable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
- }
- /* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
-}
-
-/*
- * start receiving - port is in process of being opened.
- */
-static void atmel_start_rx(struct uart_port *port)
-{
- UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */
-
- if (atmel_use_dma_rx(port)) {
- /* enable PDC controller */
- UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
- port->read_status_mask);
- UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
- } else {
- UART_PUT_IER(port, ATMEL_US_RXRDY);
- }
-}
-
-/*
- * Stop receiving - port is in process of being closed.
- */
-static void atmel_stop_rx(struct uart_port *port)
-{
- if (atmel_use_dma_rx(port)) {
- /* disable PDC receive */
- UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
- UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
- port->read_status_mask);
- } else {
- UART_PUT_IDR(port, ATMEL_US_RXRDY);
- }
-}
-
-/*
- * Enable modem status interrupts
- */
-static void atmel_enable_ms(struct uart_port *port)
-{
- UART_PUT_IER(port, ATMEL_US_RIIC | ATMEL_US_DSRIC
- | ATMEL_US_DCDIC | ATMEL_US_CTSIC);
-}
-
-/*
- * Control the transmission of a break signal
- */
-static void atmel_break_ctl(struct uart_port *port, int break_state)
-{
- if (break_state != 0)
- UART_PUT_CR(port, ATMEL_US_STTBRK); /* start break */
- else
- UART_PUT_CR(port, ATMEL_US_STPBRK); /* stop break */
-}
-
-/*
- * Stores the incoming character in the ring buffer
- */
-static void
-atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
- unsigned int ch)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct circ_buf *ring = &atmel_port->rx_ring;
- struct atmel_uart_char *c;
-
- if (!CIRC_SPACE(ring->head, ring->tail, ATMEL_SERIAL_RINGSIZE))
- /* Buffer overflow, ignore char */
- return;
-
- c = &((struct atmel_uart_char *)ring->buf)[ring->head];
- c->status = status;
- c->ch = ch;
-
- /* Make sure the character is stored before we update head. */
- smp_wmb();
-
- ring->head = (ring->head + 1) & (ATMEL_SERIAL_RINGSIZE - 1);
-}
-
-/*
- * Deal with parity, framing and overrun errors.
- */
-static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
-{
- /* clear error */
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
-
- if (status & ATMEL_US_RXBRK) {
- /* ignore side-effect */
- status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);
- port->icount.brk++;
- }
- if (status & ATMEL_US_PARE)
- port->icount.parity++;
- if (status & ATMEL_US_FRAME)
- port->icount.frame++;
- if (status & ATMEL_US_OVRE)
- port->icount.overrun++;
-}
-
-/*
- * Characters received (called from interrupt handler)
- */
-static void atmel_rx_chars(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- unsigned int status, ch;
-
- status = UART_GET_CSR(port);
- while (status & ATMEL_US_RXRDY) {
- ch = UART_GET_CHAR(port);
-
- /*
- * note that the error handling code is
- * out of the main execution path
- */
- if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
- | ATMEL_US_OVRE | ATMEL_US_RXBRK)
- || atmel_port->break_active)) {
-
- /* clear error */
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
-
- if (status & ATMEL_US_RXBRK
- && !atmel_port->break_active) {
- atmel_port->break_active = 1;
- UART_PUT_IER(port, ATMEL_US_RXBRK);
- } else {
- /*
- * This is either the end-of-break
- * condition or we've received at
- * least one character without RXBRK
- * being set. In both cases, the next
- * RXBRK will indicate start-of-break.
- */
- UART_PUT_IDR(port, ATMEL_US_RXBRK);
- status &= ~ATMEL_US_RXBRK;
- atmel_port->break_active = 0;
- }
- }
-
- atmel_buffer_rx_char(port, status, ch);
- status = UART_GET_CSR(port);
- }
-
- tasklet_schedule(&atmel_port->tasklet);
-}
-
-/*
- * Transmit characters (called from tasklet with TXRDY interrupt
- * disabled)
- */
-static void atmel_tx_chars(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
- UART_PUT_CHAR(port, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(port))
- return;
-
- while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (!uart_circ_empty(xmit))
- /* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
-}
-
-/*
- * receive interrupt handler.
- */
-static void
-atmel_handle_receive(struct uart_port *port, unsigned int pending)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (atmel_use_dma_rx(port)) {
- /*
- * PDC receive. Just schedule the tasklet and let it
- * figure out the details.
- *
- * TODO: We're not handling error flags correctly at
- * the moment.
- */
- if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
- UART_PUT_IDR(port, (ATMEL_US_ENDRX
- | ATMEL_US_TIMEOUT));
- tasklet_schedule(&atmel_port->tasklet);
- }
-
- if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
- ATMEL_US_FRAME | ATMEL_US_PARE))
- atmel_pdc_rxerr(port, pending);
- }
-
- /* Interrupt receive */
- if (pending & ATMEL_US_RXRDY)
- atmel_rx_chars(port);
- else if (pending & ATMEL_US_RXBRK) {
- /*
- * End of break detected. If it came along with a
- * character, atmel_rx_chars will handle it.
- */
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
- UART_PUT_IDR(port, ATMEL_US_RXBRK);
- atmel_port->break_active = 0;
- }
-}
-
-/*
- * transmit interrupt handler. (Transmit is IRQF_NODELAY safe)
- */
-static void
-atmel_handle_transmit(struct uart_port *port, unsigned int pending)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (pending & atmel_port->tx_done_mask) {
- /* Either PDC or interrupt transmission */
- UART_PUT_IDR(port, atmel_port->tx_done_mask);
- tasklet_schedule(&atmel_port->tasklet);
- }
-}
-
-/*
- * status flags interrupt handler.
- */
-static void
-atmel_handle_status(struct uart_port *port, unsigned int pending,
- unsigned int status)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
- | ATMEL_US_CTSIC)) {
- atmel_port->irq_status = status;
- tasklet_schedule(&atmel_port->tasklet);
- }
-}
-
-/*
- * Interrupt handler
- */
-static irqreturn_t atmel_interrupt(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- unsigned int status, pending, pass_counter = 0;
-
- do {
- status = UART_GET_CSR(port);
- pending = status & UART_GET_IMR(port);
- if (!pending)
- break;
-
- atmel_handle_receive(port, pending);
- atmel_handle_status(port, pending, status);
- atmel_handle_transmit(port, pending);
- } while (pass_counter++ < ATMEL_ISR_PASS_LIMIT);
-
- return pass_counter ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/*
- * Called from tasklet with ENDTX and TXBUFE interrupts disabled.
- */
-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->state->xmit;
- struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
- int count;
-
- /* nothing left to transmit? */
- if (UART_GET_TCR(port))
- return;
-
- xmit->tail += pdc->ofs;
- xmit->tail &= UART_XMIT_SIZE - 1;
-
- port->icount.tx += pdc->ofs;
- pdc->ofs = 0;
-
- /* more to transmit - setup next transfer */
-
- /* disable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
-
- if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
- dma_sync_single_for_device(port->dev,
- pdc->dma_addr,
- pdc->dma_size,
- DMA_TO_DEVICE);
-
- count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- pdc->ofs = count;
-
- UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
- UART_PUT_TCR(port, count);
- /* re-enable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
- /* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
- } else {
- if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
- /* DMA done, stop TX, start RX for RS485 */
- atmel_start_rx(port);
- }
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-}
-
-static void atmel_rx_from_ring(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct circ_buf *ring = &atmel_port->rx_ring;
- unsigned int flg;
- unsigned int status;
-
- while (ring->head != ring->tail) {
- struct atmel_uart_char c;
-
- /* Make sure c is loaded after head. */
- smp_rmb();
-
- c = ((struct atmel_uart_char *)ring->buf)[ring->tail];
-
- ring->tail = (ring->tail + 1) & (ATMEL_SERIAL_RINGSIZE - 1);
-
- port->icount.rx++;
- status = c.status;
- flg = TTY_NORMAL;
-
- /*
- * note that the error handling code is
- * out of the main execution path
- */
- if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
- | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
- if (status & ATMEL_US_RXBRK) {
- /* ignore side-effect */
- status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);
-
- port->icount.brk++;
- if (uart_handle_break(port))
- continue;
- }
- if (status & ATMEL_US_PARE)
- port->icount.parity++;
- if (status & ATMEL_US_FRAME)
- port->icount.frame++;
- if (status & ATMEL_US_OVRE)
- port->icount.overrun++;
-
- status &= port->read_status_mask;
-
- if (status & ATMEL_US_RXBRK)
- flg = TTY_BREAK;
- else if (status & ATMEL_US_PARE)
- flg = TTY_PARITY;
- else if (status & ATMEL_US_FRAME)
- flg = TTY_FRAME;
- }
-
-
- if (uart_handle_sysrq_char(port, c.ch))
- continue;
-
- uart_insert_char(port, status, ATMEL_US_OVRE, c.ch, flg);
- }
-
- /*
- * Drop the lock here since it might end up calling
- * uart_start(), which takes the lock.
- */
- spin_unlock(&port->lock);
- 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->state->port.tty;
- struct atmel_dma_buffer *pdc;
- int rx_idx = atmel_port->pdc_rx_idx;
- unsigned int head;
- unsigned int tail;
- unsigned int count;
-
- do {
- /* Reset the UART timeout early so that we don't miss one */
- UART_PUT_CR(port, ATMEL_US_STTTO);
-
- pdc = &atmel_port->pdc_rx[rx_idx];
- head = UART_GET_RPR(port) - pdc->dma_addr;
- tail = pdc->ofs;
-
- /* If the PDC has switched buffers, RPR won't contain
- * any address within the current buffer. Since head
- * is unsigned, we just need a one-way comparison to
- * find out.
- *
- * In this case, we just need to consume the entire
- * buffer and resubmit it for DMA. This will clear the
- * ENDRX bit as well, so that we can safely re-enable
- * all interrupts below.
- */
- head = min(head, pdc->dma_size);
-
- if (likely(head != tail)) {
- dma_sync_single_for_cpu(port->dev, pdc->dma_addr,
- pdc->dma_size, DMA_FROM_DEVICE);
-
- /*
- * head will only wrap around when we recycle
- * the DMA buffer, and when that happens, we
- * explicitly set tail to 0. So head will
- * always be greater than tail.
- */
- count = head - tail;
-
- tty_insert_flip_string(tty, pdc->buf + pdc->ofs, count);
-
- dma_sync_single_for_device(port->dev, pdc->dma_addr,
- pdc->dma_size, DMA_FROM_DEVICE);
-
- port->icount.rx += count;
- pdc->ofs = head;
- }
-
- /*
- * If the current buffer is full, we need to check if
- * the next one contains any additional data.
- */
- if (head >= pdc->dma_size) {
- pdc->ofs = 0;
- UART_PUT_RNPR(port, pdc->dma_addr);
- UART_PUT_RNCR(port, pdc->dma_size);
-
- rx_idx = !rx_idx;
- atmel_port->pdc_rx_idx = rx_idx;
- }
- } while (head >= pdc->dma_size);
-
- /*
- * Drop the lock here since it might end up calling
- * uart_start(), which takes the lock.
- */
- spin_unlock(&port->lock);
- tty_flip_buffer_push(tty);
- spin_lock(&port->lock);
-
- UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
-}
-
-/*
- * tasklet handling tty stuff outside the interrupt handler.
- */
-static void atmel_tasklet_func(unsigned long data)
-{
- struct uart_port *port = (struct uart_port *)data;
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- unsigned int status;
- unsigned int status_change;
-
- /* The interrupt handler does not take the lock */
- spin_lock(&port->lock);
-
- if (atmel_use_dma_tx(port))
- atmel_tx_dma(port);
- else
- atmel_tx_chars(port);
-
- status = atmel_port->irq_status;
- status_change = status ^ atmel_port->irq_status_prev;
-
- if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
- | ATMEL_US_DCD | ATMEL_US_CTS)) {
- /* TODO: All reads to CSR will clear these interrupts! */
- if (status_change & ATMEL_US_RI)
- port->icount.rng++;
- if (status_change & ATMEL_US_DSR)
- port->icount.dsr++;
- if (status_change & ATMEL_US_DCD)
- uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
- if (status_change & ATMEL_US_CTS)
- uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
-
- wake_up_interruptible(&port->state->port.delta_msr_wait);
-
- atmel_port->irq_status_prev = status;
- }
-
- if (atmel_use_dma_rx(port))
- atmel_rx_from_dma(port);
- else
- atmel_rx_from_ring(port);
-
- spin_unlock(&port->lock);
-}
-
-/*
- * Perform initialization and enable port for reception
- */
-static int atmel_startup(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct tty_struct *tty = port->state->port.tty;
- int retval;
-
- /*
- * Ensure that no interrupts are enabled otherwise when
- * request_irq() is called we could get stuck trying to
- * handle an unexpected interrupt
- */
- UART_PUT_IDR(port, -1);
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
- tty ? tty->name : "atmel_serial", port);
- if (retval) {
- printk("atmel_serial: atmel_startup - Can't get irq\n");
- return retval;
- }
-
- /*
- * Initialize DMA (if necessary)
- */
- if (atmel_use_dma_rx(port)) {
- int i;
-
- for (i = 0; i < 2; i++) {
- struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
-
- pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL);
- if (pdc->buf == NULL) {
- if (i != 0) {
- dma_unmap_single(port->dev,
- atmel_port->pdc_rx[0].dma_addr,
- PDC_BUFFER_SIZE,
- DMA_FROM_DEVICE);
- kfree(atmel_port->pdc_rx[0].buf);
- }
- free_irq(port->irq, port);
- return -ENOMEM;
- }
- pdc->dma_addr = dma_map_single(port->dev,
- pdc->buf,
- PDC_BUFFER_SIZE,
- DMA_FROM_DEVICE);
- pdc->dma_size = PDC_BUFFER_SIZE;
- pdc->ofs = 0;
- }
-
- atmel_port->pdc_rx_idx = 0;
-
- UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
- UART_PUT_RCR(port, PDC_BUFFER_SIZE);
-
- UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
- UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
- }
- if (atmel_use_dma_tx(port)) {
- struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
- struct circ_buf *xmit = &port->state->xmit;
-
- pdc->buf = xmit->buf;
- pdc->dma_addr = dma_map_single(port->dev,
- pdc->buf,
- UART_XMIT_SIZE,
- DMA_TO_DEVICE);
- pdc->dma_size = UART_XMIT_SIZE;
- pdc->ofs = 0;
- }
-
- /*
- * If there is a specific "open" function (to register
- * control line interrupts)
- */
- if (atmel_open_hook) {
- retval = atmel_open_hook(port);
- if (retval) {
- free_irq(port->irq, port);
- return retval;
- }
- }
-
- /* Save current CSR for comparison in atmel_tasklet_func() */
- atmel_port->irq_status_prev = UART_GET_CSR(port);
- atmel_port->irq_status = atmel_port->irq_status_prev;
-
- /*
- * Finally, enable the serial port
- */
- UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
- /* enable xmit & rcvr */
- UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
-
- if (atmel_use_dma_rx(port)) {
- /* set UART timeout */
- UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
- UART_PUT_CR(port, ATMEL_US_STTTO);
-
- UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
- /* enable PDC controller */
- UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
- } else {
- /* enable receive only */
- UART_PUT_IER(port, ATMEL_US_RXRDY);
- }
-
- return 0;
-}
-
-/*
- * Disable the port
- */
-static void atmel_shutdown(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- /*
- * Ensure everything is stopped.
- */
- atmel_stop_rx(port);
- atmel_stop_tx(port);
-
- /*
- * Shut-down the DMA.
- */
- if (atmel_use_dma_rx(port)) {
- int i;
-
- for (i = 0; i < 2; i++) {
- struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
-
- dma_unmap_single(port->dev,
- pdc->dma_addr,
- pdc->dma_size,
- DMA_FROM_DEVICE);
- kfree(pdc->buf);
- }
- }
- if (atmel_use_dma_tx(port)) {
- struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
-
- dma_unmap_single(port->dev,
- pdc->dma_addr,
- pdc->dma_size,
- DMA_TO_DEVICE);
- }
-
- /*
- * Disable all interrupts, port and break condition.
- */
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
- UART_PUT_IDR(port, -1);
-
- /*
- * Free the interrupt
- */
- free_irq(port->irq, port);
-
- /*
- * If there is a specific "close" function (to unregister
- * control line interrupts)
- */
- if (atmel_close_hook)
- atmel_close_hook(port);
-}
-
-/*
- * Flush any TX data submitted for DMA. Called when the TX circular
- * buffer is reset.
- */
-static void atmel_flush_buffer(struct uart_port *port)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (atmel_use_dma_tx(port)) {
- UART_PUT_TCR(port, 0);
- atmel_port->pdc_tx.ofs = 0;
- }
-}
-
-/*
- * Power / Clock management.
- */
-static void atmel_serial_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- switch (state) {
- case 0:
- /*
- * Enable the peripheral clock for this serial port.
- * This is called on uart_open() or a resume event.
- */
- clk_enable(atmel_port->clk);
-
- /* re-enable interrupts if we disabled some on suspend */
- UART_PUT_IER(port, atmel_port->backup_imr);
- break;
- case 3:
- /* Back up the interrupt mask and disable all interrupts */
- atmel_port->backup_imr = UART_GET_IMR(port);
- UART_PUT_IDR(port, -1);
-
- /*
- * Disable the peripheral clock for this serial port.
- * This is called on uart_close() or a suspend event.
- */
- clk_disable(atmel_port->clk);
- break;
- default:
- printk(KERN_ERR "atmel_serial: unknown pm %d\n", state);
- }
-}
-
-/*
- * Change the port parameters
- */
-static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned long flags;
- unsigned int mode, imr, quot, baud;
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- /* Get current mode register */
- mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
- | ATMEL_US_NBSTOP | ATMEL_US_PAR
- | ATMEL_US_USMODE);
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
- quot = uart_get_divisor(port, baud);
-
- if (quot > 65535) { /* BRGR is 16-bit, so switch to slower clock */
- quot /= 8;
- mode |= ATMEL_US_USCLKS_MCK_DIV8;
- }
-
- /* byte size */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- mode |= ATMEL_US_CHRL_5;
- break;
- case CS6:
- mode |= ATMEL_US_CHRL_6;
- break;
- case CS7:
- mode |= ATMEL_US_CHRL_7;
- break;
- default:
- mode |= ATMEL_US_CHRL_8;
- break;
- }
-
- /* stop bits */
- if (termios->c_cflag & CSTOPB)
- mode |= ATMEL_US_NBSTOP_2;
-
- /* parity */
- if (termios->c_cflag & PARENB) {
- /* Mark or Space parity */
- if (termios->c_cflag & CMSPAR) {
- if (termios->c_cflag & PARODD)
- mode |= ATMEL_US_PAR_MARK;
- else
- mode |= ATMEL_US_PAR_SPACE;
- } else if (termios->c_cflag & PARODD)
- mode |= ATMEL_US_PAR_ODD;
- else
- mode |= ATMEL_US_PAR_EVEN;
- } else
- mode |= ATMEL_US_PAR_NONE;
-
- /* hardware handshake (RTS/CTS) */
- if (termios->c_cflag & CRTSCTS)
- mode |= ATMEL_US_USMODE_HWHS;
- else
- mode |= ATMEL_US_USMODE_NORMAL;
-
- spin_lock_irqsave(&port->lock, flags);
-
- port->read_status_mask = ATMEL_US_OVRE;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= ATMEL_US_RXBRK;
-
- if (atmel_use_dma_rx(port))
- /* need to enable error interrupts */
- UART_PUT_IER(port, port->read_status_mask);
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE);
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= ATMEL_US_RXBRK;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= ATMEL_US_OVRE;
- }
- /* TODO: Ignore all characters if CREAD is set.*/
-
- /* update the per-port timeout */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /*
- * save/disable interrupts. The tty layer will ensure that the
- * transmitter is empty if requested by the caller, so there's
- * no need to wait for it here.
- */
- imr = UART_GET_IMR(port);
- UART_PUT_IDR(port, -1);
-
- /* disable receiver and transmitter */
- UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
-
- /* Resetting serial mode to RS232 (0x0) */
- mode &= ~ATMEL_US_USMODE;
-
- if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
- dev_dbg(port->dev, "Setting UART to RS485\n");
- if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
- UART_PUT_TTGR(port,
- atmel_port->rs485.delay_rts_after_send);
- mode |= ATMEL_US_USMODE_RS485;
- } else {
- dev_dbg(port->dev, "Setting UART to RS232\n");
- }
-
- /* set the parity, stop bits and data size */
- UART_PUT_MR(port, mode);
-
- /* set the baud rate */
- UART_PUT_BRGR(port, quot);
- UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
- UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
-
- /* restore interrupts */
- UART_PUT_IER(port, imr);
-
- /* CTS flow-control and modem-status interrupts */
- if (UART_ENABLE_MS(port, termios->c_cflag))
- port->ops->enable_ms(port);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/*
- * Return string describing the specified port
- */
-static const char *atmel_type(struct uart_port *port)
-{
- return (port->type == PORT_ATMEL) ? "ATMEL_SERIAL" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'.
- */
-static void atmel_release_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- int size = pdev->resource[0].end - pdev->resource[0].start + 1;
-
- release_mem_region(port->mapbase, size);
-
- if (port->flags & UPF_IOREMAP) {
- iounmap(port->membase);
- port->membase = NULL;
- }
-}
-
-/*
- * Request the memory region(s) being used by 'port'.
- */
-static int atmel_request_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- int size = pdev->resource[0].end - pdev->resource[0].start + 1;
-
- if (!request_mem_region(port->mapbase, size, "atmel_serial"))
- return -EBUSY;
-
- if (port->flags & UPF_IOREMAP) {
- port->membase = ioremap(port->mapbase, size);
- if (port->membase == NULL) {
- release_mem_region(port->mapbase, size);
- return -ENOMEM;
- }
- }
-
- return 0;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void atmel_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_ATMEL;
- atmel_request_port(port);
- }
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- */
-static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_ATMEL)
- ret = -EINVAL;
- if (port->irq != ser->irq)
- ret = -EINVAL;
- if (ser->io_type != SERIAL_IO_MEM)
- ret = -EINVAL;
- if (port->uartclk / 16 != ser->baud_base)
- ret = -EINVAL;
- if ((void *)port->mapbase != ser->iomem_base)
- ret = -EINVAL;
- if (port->iobase != ser->port)
- ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
- return ret;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-static int atmel_poll_get_char(struct uart_port *port)
-{
- while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
- cpu_relax();
-
- return UART_GET_CHAR(port);
-}
-
-static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
-{
- while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
- cpu_relax();
-
- UART_PUT_CHAR(port, ch);
-}
-#endif
-
-static int
-atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
-{
- struct serial_rs485 rs485conf;
-
- switch (cmd) {
- case TIOCSRS485:
- if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
- sizeof(rs485conf)))
- return -EFAULT;
-
- atmel_config_rs485(port, &rs485conf);
- break;
-
- case TIOCGRS485:
- if (copy_to_user((struct serial_rs485 *) arg,
- &(to_atmel_uart_port(port)->rs485),
- sizeof(rs485conf)))
- return -EFAULT;
- break;
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-
-
-static struct uart_ops atmel_pops = {
- .tx_empty = atmel_tx_empty,
- .set_mctrl = atmel_set_mctrl,
- .get_mctrl = atmel_get_mctrl,
- .stop_tx = atmel_stop_tx,
- .start_tx = atmel_start_tx,
- .stop_rx = atmel_stop_rx,
- .enable_ms = atmel_enable_ms,
- .break_ctl = atmel_break_ctl,
- .startup = atmel_startup,
- .shutdown = atmel_shutdown,
- .flush_buffer = atmel_flush_buffer,
- .set_termios = atmel_set_termios,
- .type = atmel_type,
- .release_port = atmel_release_port,
- .request_port = atmel_request_port,
- .config_port = atmel_config_port,
- .verify_port = atmel_verify_port,
- .pm = atmel_serial_pm,
- .ioctl = atmel_ioctl,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = atmel_poll_get_char,
- .poll_put_char = atmel_poll_put_char,
-#endif
-};
-
-/*
- * Configure the port from the platform device resource info.
- */
-static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
- struct platform_device *pdev)
-{
- struct uart_port *port = &atmel_port->uart;
- struct atmel_uart_data *data = pdev->dev.platform_data;
-
- port->iotype = UPIO_MEM;
- port->flags = UPF_BOOT_AUTOCONF;
- port->ops = &atmel_pops;
- port->fifosize = 1;
- port->line = pdev->id;
- port->dev = &pdev->dev;
- port->mapbase = pdev->resource[0].start;
- port->irq = pdev->resource[1].start;
-
- tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
- (unsigned long)port);
-
- memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
-
- if (data->regs)
- /* Already mapped by setup code */
- port->membase = data->regs;
- else {
- port->flags |= UPF_IOREMAP;
- port->membase = NULL;
- }
-
- /* for console, the clock could already be configured */
- if (!atmel_port->clk) {
- atmel_port->clk = clk_get(&pdev->dev, "usart");
- clk_enable(atmel_port->clk);
- port->uartclk = clk_get_rate(atmel_port->clk);
- clk_disable(atmel_port->clk);
- /* only enable clock when USART is in use */
- }
-
- atmel_port->use_dma_rx = data->use_dma_rx;
- atmel_port->use_dma_tx = data->use_dma_tx;
- atmel_port->rs485 = data->rs485;
- /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
- if (atmel_port->rs485.flags & SER_RS485_ENABLED)
- atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
- else if (atmel_use_dma_tx(port)) {
- port->fifosize = PDC_BUFFER_SIZE;
- atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;
- } else {
- atmel_port->tx_done_mask = ATMEL_US_TXRDY;
- }
-}
-
-/*
- * Register board-specific modem-control line handlers.
- */
-void __init atmel_register_uart_fns(struct atmel_port_fns *fns)
-{
- if (fns->enable_ms)
- atmel_pops.enable_ms = fns->enable_ms;
- if (fns->get_mctrl)
- atmel_pops.get_mctrl = fns->get_mctrl;
- if (fns->set_mctrl)
- atmel_pops.set_mctrl = fns->set_mctrl;
- atmel_open_hook = fns->open;
- atmel_close_hook = fns->close;
- atmel_pops.pm = fns->pm;
- atmel_pops.set_wake = fns->set_wake;
-}
-
-#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
-static void atmel_console_putchar(struct uart_port *port, int ch)
-{
- while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
- cpu_relax();
- UART_PUT_CHAR(port, ch);
-}
-
-/*
- * Interrupts are disabled on entering
- */
-static void atmel_console_write(struct console *co, const char *s, u_int count)
-{
- struct uart_port *port = &atmel_ports[co->index].uart;
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- unsigned int status, imr;
- unsigned int pdc_tx;
-
- /*
- * First, save IMR and then disable interrupts
- */
- imr = UART_GET_IMR(port);
- UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
-
- /* Store PDC transmit status and disable it */
- pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
-
- uart_console_write(port, s, count, atmel_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore IMR
- */
- do {
- status = UART_GET_CSR(port);
- } while (!(status & ATMEL_US_TXRDY));
-
- /* Restore PDC transmit status */
- if (pdc_tx)
- UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
-
- /* set interrupts back the way they were */
- UART_PUT_IER(port, imr);
-}
-
-/*
- * If the port was already initialised (eg, by a boot loader),
- * try to determine the current setup.
- */
-static void __init atmel_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- unsigned int mr, quot;
-
- /*
- * If the baud rate generator isn't running, the port wasn't
- * initialized by the boot loader.
- */
- quot = UART_GET_BRGR(port) & ATMEL_US_CD;
- if (!quot)
- return;
-
- mr = UART_GET_MR(port) & ATMEL_US_CHRL;
- if (mr == ATMEL_US_CHRL_8)
- *bits = 8;
- else
- *bits = 7;
-
- mr = UART_GET_MR(port) & ATMEL_US_PAR;
- if (mr == ATMEL_US_PAR_EVEN)
- *parity = 'e';
- else if (mr == ATMEL_US_PAR_ODD)
- *parity = 'o';
-
- /*
- * The serial core only rounds down when matching this to a
- * supported baud rate. Make sure we don't end up slightly
- * lower than one of those, as it would make us fall through
- * to a much lower baud rate than we really want.
- */
- *baud = port->uartclk / (16 * (quot - 1));
-}
-
-static int __init atmel_console_setup(struct console *co, char *options)
-{
- struct uart_port *port = &atmel_ports[co->index].uart;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (port->membase == NULL) {
- /* Port not initialized yet - delay setup */
- return -ENODEV;
- }
-
- clk_enable(atmel_ports[co->index].clk);
-
- UART_PUT_IDR(port, -1);
- UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
- UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- atmel_console_get_options(port, &baud, &parity, &bits);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver atmel_uart;
-
-static struct console atmel_console = {
- .name = ATMEL_DEVICENAME,
- .write = atmel_console_write,
- .device = uart_console_device,
- .setup = atmel_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &atmel_uart,
-};
-
-#define ATMEL_CONSOLE_DEVICE (&atmel_console)
-
-/*
- * Early console initialization (before VM subsystem initialized).
- */
-static int __init atmel_console_init(void)
-{
- if (atmel_default_console_device) {
- add_preferred_console(ATMEL_DEVICENAME,
- atmel_default_console_device->id, NULL);
- atmel_init_port(&atmel_ports[atmel_default_console_device->id],
- atmel_default_console_device);
- register_console(&atmel_console);
- }
-
- return 0;
-}
-
-console_initcall(atmel_console_init);
-
-/*
- * Late console initialization.
- */
-static int __init atmel_late_console_init(void)
-{
- if (atmel_default_console_device
- && !(atmel_console.flags & CON_ENABLED))
- register_console(&atmel_console);
-
- return 0;
-}
-
-core_initcall(atmel_late_console_init);
-
-static inline bool atmel_is_console_port(struct uart_port *port)
-{
- return port->cons && port->cons->index == port->line;
-}
-
-#else
-#define ATMEL_CONSOLE_DEVICE NULL
-
-static inline bool atmel_is_console_port(struct uart_port *port)
-{
- return false;
-}
-#endif
-
-static struct uart_driver atmel_uart = {
- .owner = THIS_MODULE,
- .driver_name = "atmel_serial",
- .dev_name = ATMEL_DEVICENAME,
- .major = SERIAL_ATMEL_MAJOR,
- .minor = MINOR_START,
- .nr = ATMEL_MAX_UART,
- .cons = ATMEL_CONSOLE_DEVICE,
-};
-
-#ifdef CONFIG_PM
-static bool atmel_serial_clk_will_stop(void)
-{
-#ifdef CONFIG_ARCH_AT91
- return at91_suspend_entering_slow_clock();
-#else
- return false;
-#endif
-}
-
-static int atmel_serial_suspend(struct platform_device *pdev,
- pm_message_t state)
-{
- struct uart_port *port = platform_get_drvdata(pdev);
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- if (atmel_is_console_port(port) && console_suspend_enabled) {
- /* Drain the TX shifter */
- while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
- cpu_relax();
- }
-
- /* we can not wake up if we're running on slow clock */
- atmel_port->may_wakeup = device_may_wakeup(&pdev->dev);
- if (atmel_serial_clk_will_stop())
- device_set_wakeup_enable(&pdev->dev, 0);
-
- uart_suspend_port(&atmel_uart, port);
-
- return 0;
-}
-
-static int atmel_serial_resume(struct platform_device *pdev)
-{
- struct uart_port *port = platform_get_drvdata(pdev);
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-
- uart_resume_port(&atmel_uart, port);
- device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup);
-
- return 0;
-}
-#else
-#define atmel_serial_suspend NULL
-#define atmel_serial_resume NULL
-#endif
-
-static int __devinit atmel_serial_probe(struct platform_device *pdev)
-{
- struct atmel_uart_port *port;
- void *data;
- int ret;
-
- BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
-
- port = &atmel_ports[pdev->id];
- port->backup_imr = 0;
-
- atmel_init_port(port, pdev);
-
- if (!atmel_use_dma_rx(&port->uart)) {
- ret = -ENOMEM;
- data = kmalloc(sizeof(struct atmel_uart_char)
- * ATMEL_SERIAL_RINGSIZE, GFP_KERNEL);
- if (!data)
- goto err_alloc_ring;
- port->rx_ring.buf = data;
- }
-
- ret = uart_add_one_port(&atmel_uart, &port->uart);
- if (ret)
- goto err_add_port;
-
-#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
- if (atmel_is_console_port(&port->uart)
- && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
- /*
- * The serial core enabled the clock for us, so undo
- * the clk_enable() in atmel_console_setup()
- */
- clk_disable(port->clk);
- }
-#endif
-
- device_init_wakeup(&pdev->dev, 1);
- platform_set_drvdata(pdev, port);
-
- return 0;
-
-err_add_port:
- kfree(port->rx_ring.buf);
- port->rx_ring.buf = NULL;
-err_alloc_ring:
- if (!atmel_is_console_port(&port->uart)) {
- clk_put(port->clk);
- port->clk = NULL;
- }
-
- return ret;
-}
-
-static int __devexit atmel_serial_remove(struct platform_device *pdev)
-{
- struct uart_port *port = platform_get_drvdata(pdev);
- struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- int ret = 0;
-
- device_init_wakeup(&pdev->dev, 0);
- platform_set_drvdata(pdev, NULL);
-
- ret = uart_remove_one_port(&atmel_uart, port);
-
- tasklet_kill(&atmel_port->tasklet);
- kfree(atmel_port->rx_ring.buf);
-
- /* "port" is allocated statically, so we shouldn't free it */
-
- clk_put(atmel_port->clk);
-
- return ret;
-}
-
-static struct platform_driver atmel_serial_driver = {
- .probe = atmel_serial_probe,
- .remove = __devexit_p(atmel_serial_remove),
- .suspend = atmel_serial_suspend,
- .resume = atmel_serial_resume,
- .driver = {
- .name = "atmel_usart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init atmel_serial_init(void)
-{
- int ret;
-
- ret = uart_register_driver(&atmel_uart);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&atmel_serial_driver);
- if (ret)
- uart_unregister_driver(&atmel_uart);
-
- return ret;
-}
-
-static void __exit atmel_serial_exit(void)
-{
- platform_driver_unregister(&atmel_serial_driver);
- uart_unregister_driver(&atmel_uart);
-}
-
-module_init(atmel_serial_init);
-module_exit(atmel_serial_exit);
-
-MODULE_AUTHOR("Rick Bronson");
-MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:atmel_usart");
diff --git a/drivers/serial/bcm63xx_uart.c b/drivers/serial/bcm63xx_uart.c
deleted file mode 100644
index a1a0e55d0807..000000000000
--- a/drivers/serial/bcm63xx_uart.c
+++ /dev/null
@@ -1,891 +0,0 @@
-/*
- * 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 2
-
-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->state->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_FIFO_PARERR_MASK)
- port->icount.parity++;
- if (cstat & UART_FIFO_FRAMEERR_MASK)
- port->icount.frame++;
-
- /* update flag wrt read_status_mask */
- cstat &= port->read_status_mask;
- if (cstat & UART_FIFO_BRKDET_MASK)
- flag = TTY_BREAK;
- if (cstat & UART_FIFO_FRAMEERR_MASK)
- flag = TTY_FRAME;
- if (cstat & UART_FIFO_PARERR_MASK)
- flag = TTY_PARITY;
- }
-
- if (uart_handle_sysrq_char(port, c))
- continue;
-
- if (unlikely(iestat & UART_IR_STAT(UART_IR_RXOVER))) {
- port->icount.overrun++;
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
-
- if ((cstat & port->ignore_status_mask) == 0)
- tty_insert_flip_char(tty, c, flag);
-
- } while (--max_count);
-
- tty_flip_buffer_push(tty);
-}
-
-/*
- * fill tx fifo with chars to send, stop when fifo is about to be full
- * or when all chars have been sent.
- */
-static void bcm_uart_do_tx(struct uart_port *port)
-{
- struct circ_buf *xmit;
- unsigned int val, max_count;
-
- if (port->x_char) {
- bcm_uart_writel(port, port->x_char, UART_FIFO_REG);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
-
- if (uart_tx_stopped(port)) {
- bcm_uart_stop_tx(port);
- return;
- }
-
- xmit = &port->state->xmit;
- if (uart_circ_empty(xmit))
- goto txq_empty;
-
- val = bcm_uart_readl(port, UART_MCTL_REG);
- val = (val & UART_MCTL_TXFIFOFILL_MASK) >> UART_MCTL_TXFIFOFILL_SHIFT;
- max_count = port->fifosize - val;
-
- while (max_count--) {
- unsigned int c;
-
- c = xmit->buf[xmit->tail];
- bcm_uart_writel(port, c, UART_FIFO_REG);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- goto txq_empty;
- return;
-
-txq_empty:
- /* nothing to send, disable transmit interrupt */
- val = bcm_uart_readl(port, UART_IR_REG);
- val &= ~UART_TX_INT_MASK;
- bcm_uart_writel(port, val, UART_IR_REG);
- return;
-}
-
-/*
- * process uart interrupt
- */
-static irqreturn_t bcm_uart_interrupt(int irq, void *dev_id)
-{
- struct uart_port *port;
- unsigned int irqstat;
-
- port = dev_id;
- spin_lock(&port->lock);
-
- irqstat = bcm_uart_readl(port, UART_IR_REG);
- if (irqstat & UART_RX_INT_STAT)
- bcm_uart_do_rx(port);
-
- if (irqstat & UART_TX_INT_STAT)
- bcm_uart_do_tx(port);
-
- if (irqstat & UART_IR_MASK(UART_IR_EXTIP)) {
- unsigned int estat;
-
- estat = bcm_uart_readl(port, UART_EXTINP_REG);
- if (estat & UART_EXTINP_IRSTAT(UART_EXTINP_IR_CTS))
- uart_handle_cts_change(port,
- estat & UART_EXTINP_CTS_MASK);
- if (estat & UART_EXTINP_IRSTAT(UART_EXTINP_IR_DCD))
- uart_handle_dcd_change(port,
- estat & UART_EXTINP_DCD_MASK);
- }
-
- spin_unlock(&port->lock);
- return IRQ_HANDLED;
-}
-
-/*
- * enable rx & tx operation on uart
- */
-static void bcm_uart_enable(struct uart_port *port)
-{
- unsigned int val;
-
- val = bcm_uart_readl(port, UART_CTL_REG);
- val |= (UART_CTL_BRGEN_MASK | UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK);
- bcm_uart_writel(port, val, UART_CTL_REG);
-}
-
-/*
- * disable rx & tx operation on uart
- */
-static void bcm_uart_disable(struct uart_port *port)
-{
- unsigned int val;
-
- val = bcm_uart_readl(port, UART_CTL_REG);
- val &= ~(UART_CTL_BRGEN_MASK | UART_CTL_TXEN_MASK |
- UART_CTL_RXEN_MASK);
- bcm_uart_writel(port, val, UART_CTL_REG);
-}
-
-/*
- * clear all unread data in rx fifo and unsent data in tx fifo
- */
-static void bcm_uart_flush(struct uart_port *port)
-{
- unsigned int val;
-
- /* empty rx and tx fifo */
- val = bcm_uart_readl(port, UART_CTL_REG);
- val |= UART_CTL_RSTRXFIFO_MASK | UART_CTL_RSTTXFIFO_MASK;
- bcm_uart_writel(port, val, UART_CTL_REG);
-
- /* read any pending char to make sure all irq status are
- * cleared */
- (void)bcm_uart_readl(port, UART_FIFO_REG);
-}
-
-/*
- * serial core request to initialize uart and start rx operation
- */
-static int bcm_uart_startup(struct uart_port *port)
-{
- unsigned int val;
- int ret;
-
- /* mask all irq and flush port */
- bcm_uart_disable(port);
- bcm_uart_writel(port, 0, UART_IR_REG);
- bcm_uart_flush(port);
-
- /* clear any pending external input interrupt */
- (void)bcm_uart_readl(port, UART_EXTINP_REG);
-
- /* set rx/tx fifo thresh to fifo half size */
- val = bcm_uart_readl(port, UART_MCTL_REG);
- val &= ~(UART_MCTL_RXFIFOTHRESH_MASK | UART_MCTL_TXFIFOTHRESH_MASK);
- val |= (port->fifosize / 2) << UART_MCTL_RXFIFOTHRESH_SHIFT;
- val |= (port->fifosize / 2) << UART_MCTL_TXFIFOTHRESH_SHIFT;
- bcm_uart_writel(port, val, UART_MCTL_REG);
-
- /* set rx fifo timeout to 1 char time */
- val = bcm_uart_readl(port, UART_CTL_REG);
- val &= ~UART_CTL_RXTMOUTCNT_MASK;
- val |= 1 << UART_CTL_RXTMOUTCNT_SHIFT;
- bcm_uart_writel(port, val, UART_CTL_REG);
-
- /* report any edge on dcd and cts */
- val = UART_EXTINP_INT_MASK;
- val |= UART_EXTINP_DCD_NOSENSE_MASK;
- val |= UART_EXTINP_CTS_NOSENSE_MASK;
- bcm_uart_writel(port, val, UART_EXTINP_REG);
-
- /* register irq and enable rx interrupts */
- ret = request_irq(port->irq, bcm_uart_interrupt, 0,
- bcm_uart_type(port), port);
- if (ret)
- return ret;
- bcm_uart_writel(port, UART_RX_INT_MASK, UART_IR_REG);
- bcm_uart_enable(port);
- return 0;
-}
-
-/*
- * serial core request to flush & disable uart
- */
-static void bcm_uart_shutdown(struct uart_port *port)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- bcm_uart_writel(port, 0, UART_IR_REG);
- spin_unlock_irqrestore(&port->lock, flags);
-
- bcm_uart_disable(port);
- bcm_uart_flush(port);
- free_irq(port->irq, port);
-}
-
-/*
- * serial core request to change current uart setting
- */
-static void bcm_uart_set_termios(struct uart_port *port,
- struct ktermios *new,
- struct ktermios *old)
-{
- unsigned int ctl, baud, quot, ier;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* disable uart while changing speed */
- bcm_uart_disable(port);
- bcm_uart_flush(port);
-
- /* update Control register */
- ctl = bcm_uart_readl(port, UART_CTL_REG);
- ctl &= ~UART_CTL_BITSPERSYM_MASK;
-
- switch (new->c_cflag & CSIZE) {
- case CS5:
- ctl |= (0 << UART_CTL_BITSPERSYM_SHIFT);
- break;
- case CS6:
- ctl |= (1 << UART_CTL_BITSPERSYM_SHIFT);
- break;
- case CS7:
- ctl |= (2 << UART_CTL_BITSPERSYM_SHIFT);
- break;
- default:
- ctl |= (3 << UART_CTL_BITSPERSYM_SHIFT);
- break;
- }
-
- ctl &= ~UART_CTL_STOPBITS_MASK;
- if (new->c_cflag & CSTOPB)
- ctl |= UART_CTL_STOPBITS_2;
- else
- ctl |= UART_CTL_STOPBITS_1;
-
- ctl &= ~(UART_CTL_RXPAREN_MASK | UART_CTL_TXPAREN_MASK);
- if (new->c_cflag & PARENB)
- ctl |= (UART_CTL_RXPAREN_MASK | UART_CTL_TXPAREN_MASK);
- ctl &= ~(UART_CTL_RXPAREVEN_MASK | UART_CTL_TXPAREVEN_MASK);
- if (new->c_cflag & PARODD)
- ctl |= (UART_CTL_RXPAREVEN_MASK | UART_CTL_TXPAREVEN_MASK);
- bcm_uart_writel(port, ctl, UART_CTL_REG);
-
- /* update Baudword register */
- baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
- quot = uart_get_divisor(port, baud) - 1;
- bcm_uart_writel(port, quot, UART_BAUD_REG);
-
- /* update Interrupt register */
- ier = bcm_uart_readl(port, UART_IR_REG);
-
- ier &= ~UART_IR_MASK(UART_IR_EXTIP);
- if (UART_ENABLE_MS(port, new->c_cflag))
- ier |= UART_IR_MASK(UART_IR_EXTIP);
-
- bcm_uart_writel(port, ier, UART_IR_REG);
-
- /* update read/ignore mask */
- port->read_status_mask = UART_FIFO_VALID_MASK;
- if (new->c_iflag & INPCK) {
- port->read_status_mask |= UART_FIFO_FRAMEERR_MASK;
- port->read_status_mask |= UART_FIFO_PARERR_MASK;
- }
- if (new->c_iflag & (BRKINT))
- port->read_status_mask |= UART_FIFO_BRKDET_MASK;
-
- port->ignore_status_mask = 0;
- if (new->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_FIFO_PARERR_MASK;
- if (new->c_iflag & IGNBRK)
- port->ignore_status_mask |= UART_FIFO_BRKDET_MASK;
- if (!(new->c_cflag & CREAD))
- port->ignore_status_mask |= UART_FIFO_VALID_MASK;
-
- uart_update_timeout(port, new->c_cflag, baud);
- bcm_uart_enable(port);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/*
- * serial core request to claim uart iomem
- */
-static int bcm_uart_request_port(struct uart_port *port)
-{
- unsigned int size;
-
- size = RSET_UART_SIZE;
- if (!request_mem_region(port->mapbase, size, "bcm63xx")) {
- dev_err(port->dev, "Memory region busy\n");
- return -EBUSY;
- }
-
- port->membase = ioremap(port->mapbase, size);
- if (!port->membase) {
- dev_err(port->dev, "Unable to map registers\n");
- release_mem_region(port->mapbase, size);
- return -EBUSY;
- }
- return 0;
-}
-
-/*
- * serial core request to release uart iomem
- */
-static void bcm_uart_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, RSET_UART_SIZE);
- iounmap(port->membase);
-}
-
-/*
- * serial core request to do any port required autoconfiguration
- */
-static void bcm_uart_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- if (bcm_uart_request_port(port))
- return;
- port->type = PORT_BCM63XX;
- }
-}
-
-/*
- * serial core request to check that port information in serinfo are
- * suitable
- */
-static int bcm_uart_verify_port(struct uart_port *port,
- struct serial_struct *serinfo)
-{
- if (port->type != PORT_BCM63XX)
- return -EINVAL;
- if (port->irq != serinfo->irq)
- return -EINVAL;
- if (port->iotype != serinfo->io_type)
- return -EINVAL;
- if (port->mapbase != (unsigned long)serinfo->iomem_base)
- return -EINVAL;
- return 0;
-}
-
-/* serial core callbacks */
-static struct uart_ops bcm_uart_ops = {
- .tx_empty = bcm_uart_tx_empty,
- .get_mctrl = bcm_uart_get_mctrl,
- .set_mctrl = bcm_uart_set_mctrl,
- .start_tx = bcm_uart_start_tx,
- .stop_tx = bcm_uart_stop_tx,
- .stop_rx = bcm_uart_stop_rx,
- .enable_ms = bcm_uart_enable_ms,
- .break_ctl = bcm_uart_break_ctl,
- .startup = bcm_uart_startup,
- .shutdown = bcm_uart_shutdown,
- .set_termios = bcm_uart_set_termios,
- .type = bcm_uart_type,
- .release_port = bcm_uart_release_port,
- .request_port = bcm_uart_request_port,
- .config_port = bcm_uart_config_port,
- .verify_port = bcm_uart_verify_port,
-};
-
-
-
-#ifdef CONFIG_SERIAL_BCM63XX_CONSOLE
-static inline void wait_for_xmitr(struct uart_port *port)
-{
- unsigned int tmout;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- tmout = 10000;
- while (--tmout) {
- unsigned int val;
-
- val = bcm_uart_readl(port, UART_IR_REG);
- if (val & UART_IR_STAT(UART_IR_TXEMPTY))
- break;
- udelay(1);
- }
-
- /* Wait up to 1s for flow control if necessary */
- if (port->flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout) {
- unsigned int val;
-
- val = bcm_uart_readl(port, UART_EXTINP_REG);
- if (val & UART_EXTINP_CTS_MASK)
- break;
- udelay(1);
- }
- }
-}
-
-/*
- * output given char
- */
-static void bcm_console_putchar(struct uart_port *port, int ch)
-{
- wait_for_xmitr(port);
- bcm_uart_writel(port, ch, UART_FIFO_REG);
-}
-
-/*
- * console core request to output given string
- */
-static void bcm_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_port *port;
- unsigned long flags;
- int locked;
-
- port = &ports[co->index];
-
- local_irq_save(flags);
- if (port->sysrq) {
- /* bcm_uart_interrupt() already took the lock */
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&port->lock);
- } else {
- spin_lock(&port->lock);
- locked = 1;
- }
-
- /* call helper to deal with \r\n */
- uart_console_write(port, s, count, bcm_console_putchar);
-
- /* and wait for char to be transmitted */
- wait_for_xmitr(port);
-
- if (locked)
- spin_unlock(&port->lock);
- local_irq_restore(flags);
-}
-
-/*
- * console core request to setup given console, find matching uart
- * port and setup it.
- */
-static int bcm_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (co->index < 0 || co->index >= BCM63XX_NR_UARTS)
- return -EINVAL;
- port = &ports[co->index];
- if (!port->membase)
- return -ENODEV;
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver bcm_uart_driver;
-
-static struct console bcm63xx_console = {
- .name = "ttyS",
- .write = bcm_console_write,
- .device = uart_console_device,
- .setup = bcm_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &bcm_uart_driver,
-};
-
-static int __init bcm63xx_console_init(void)
-{
- register_console(&bcm63xx_console);
- return 0;
-}
-
-console_initcall(bcm63xx_console_init);
-
-#define BCM63XX_CONSOLE (&bcm63xx_console)
-#else
-#define BCM63XX_CONSOLE NULL
-#endif /* CONFIG_SERIAL_BCM63XX_CONSOLE */
-
-static struct uart_driver bcm_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "bcm63xx_uart",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = BCM63XX_NR_UARTS,
- .cons = BCM63XX_CONSOLE,
-};
-
-/*
- * platform driver probe/remove callback
- */
-static int __devinit bcm_uart_probe(struct platform_device *pdev)
-{
- struct resource *res_mem, *res_irq;
- struct uart_port *port;
- struct clk *clk;
- int ret;
-
- if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
- return -EINVAL;
-
- if (ports[pdev->id].membase)
- return -EBUSY;
-
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res_mem)
- return -ENODEV;
-
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
- return -ENODEV;
-
- clk = clk_get(&pdev->dev, "periph");
- if (IS_ERR(clk))
- return -ENODEV;
-
- port = &ports[pdev->id];
- memset(port, 0, sizeof(*port));
- port->iotype = UPIO_MEM;
- port->mapbase = res_mem->start;
- port->irq = res_irq->start;
- port->ops = &bcm_uart_ops;
- port->flags = UPF_BOOT_AUTOCONF;
- port->dev = &pdev->dev;
- port->fifosize = 16;
- port->uartclk = clk_get_rate(clk) / 2;
- port->line = pdev->id;
- clk_put(clk);
-
- ret = uart_add_one_port(&bcm_uart_driver, port);
- if (ret) {
- ports[pdev->id].membase = 0;
- return ret;
- }
- platform_set_drvdata(pdev, port);
- return 0;
-}
-
-static int __devexit bcm_uart_remove(struct platform_device *pdev)
-{
- struct uart_port *port;
-
- port = platform_get_drvdata(pdev);
- uart_remove_one_port(&bcm_uart_driver, port);
- platform_set_drvdata(pdev, NULL);
- /* mark port as free */
- ports[pdev->id].membase = 0;
- return 0;
-}
-
-/*
- * platform driver stuff
- */
-static struct platform_driver bcm_uart_platform_driver = {
- .probe = bcm_uart_probe,
- .remove = __devexit_p(bcm_uart_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "bcm63xx_uart",
- },
-};
-
-static int __init bcm_uart_init(void)
-{
- int ret;
-
- ret = uart_register_driver(&bcm_uart_driver);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&bcm_uart_platform_driver);
- if (ret)
- uart_unregister_driver(&bcm_uart_driver);
-
- return ret;
-}
-
-static void __exit bcm_uart_exit(void)
-{
- platform_driver_unregister(&bcm_uart_platform_driver);
- uart_unregister_driver(&bcm_uart_driver);
-}
-
-module_init(bcm_uart_init);
-module_exit(bcm_uart_exit);
-
-MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
-MODULE_DESCRIPTION("Broadcom 63<xx integrated uart driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
deleted file mode 100644
index e381b895b04d..000000000000
--- a/drivers/serial/bfin_5xx.c
+++ /dev/null
@@ -1,1600 +0,0 @@
-/*
- * Blackfin On-Chip Serial Driver
- *
- * Copyright 2006-2010 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-#if defined(CONFIG_SERIAL_BFIN_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#define DRIVER_NAME "bfin-uart"
-#define pr_fmt(fmt) DRIVER_NAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/gfp.h>
-#include <linux/io.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/kgdb.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/portmux.h>
-#include <asm/cacheflush.h>
-#include <asm/dma.h>
-
-#define port_membase(uart) (((struct bfin_serial_port *)(uart))->port.membase)
-#define get_lsr_cache(uart) (((struct bfin_serial_port *)(uart))->lsr)
-#define put_lsr_cache(uart, v) (((struct bfin_serial_port *)(uart))->lsr = (v))
-#include <asm/bfin_serial.h>
-
-#ifdef CONFIG_SERIAL_BFIN_MODULE
-# undef CONFIG_EARLY_PRINTK
-#endif
-
-#ifdef CONFIG_SERIAL_BFIN_MODULE
-# undef CONFIG_EARLY_PRINTK
-#endif
-
-/* UART name and device definitions */
-#define BFIN_SERIAL_DEV_NAME "ttyBF"
-#define BFIN_SERIAL_MAJOR 204
-#define BFIN_SERIAL_MINOR 64
-
-static struct bfin_serial_port *bfin_serial_ports[BFIN_UART_NR_PORTS];
-
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
- defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
-
-# ifndef CONFIG_SERIAL_BFIN_PIO
-# error KGDB only support UART in PIO mode.
-# endif
-
-static int kgdboc_port_line;
-static int kgdboc_break_enabled;
-#endif
-/*
- * Setup for console. Argument comes from the menuconfig
- */
-#define DMA_RX_XCOUNT 512
-#define DMA_RX_YCOUNT (PAGE_SIZE / DMA_RX_XCOUNT)
-
-#define DMA_RX_FLUSH_JIFFIES (HZ / 50)
-
-#ifdef CONFIG_SERIAL_BFIN_DMA
-static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart);
-#else
-static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
-#endif
-
-static void bfin_serial_reset_irda(struct uart_port *port);
-
-#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
- defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
-static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- if (uart->cts_pin < 0)
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-
- /* CTS PIN is negative assertive. */
- if (UART_GET_CTS(uart))
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
- else
- return TIOCM_DSR | TIOCM_CAR;
-}
-
-static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- if (uart->rts_pin < 0)
- return;
-
- /* RTS PIN is negative assertive. */
- if (mctrl & TIOCM_RTS)
- UART_ENABLE_RTS(uart);
- else
- UART_DISABLE_RTS(uart);
-}
-
-/*
- * Handle any change of modem status signal.
- */
-static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)
-{
- struct bfin_serial_port *uart = dev_id;
- unsigned int status;
-
- status = bfin_serial_get_mctrl(&uart->port);
- uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- uart->scts = 1;
- UART_CLEAR_SCTS(uart);
- UART_CLEAR_IER(uart, EDSSI);
-#endif
-
- return IRQ_HANDLED;
-}
-#else
-static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-}
-
-static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-#endif
-
-/*
- * interrupts are disabled on entry
- */
-static void bfin_serial_stop_tx(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-#ifdef CONFIG_SERIAL_BFIN_DMA
- struct circ_buf *xmit = &uart->port.state->xmit;
-#endif
-
- while (!(UART_GET_LSR(uart) & TEMT))
- cpu_relax();
-
-#ifdef CONFIG_SERIAL_BFIN_DMA
- disable_dma(uart->tx_dma_channel);
- xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
- uart->port.icount.tx += uart->tx_count;
- uart->tx_count = 0;
- uart->tx_done = 1;
-#else
-#ifdef CONFIG_BF54x
- /* Clear TFI bit */
- UART_PUT_LSR(uart, TFI);
-#endif
- UART_CLEAR_IER(uart, ETBEI);
-#endif
-}
-
-/*
- * port is locked and interrupts are disabled
- */
-static void bfin_serial_start_tx(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- struct tty_struct *tty = uart->port.state->port.tty;
-
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
- uart->scts = 0;
- uart_handle_cts_change(&uart->port, uart->scts);
- }
-#endif
-
- /*
- * To avoid losting RX interrupt, we reset IR function
- * before sending data.
- */
- if (tty->termios->c_line == N_IRDA)
- bfin_serial_reset_irda(port);
-
-#ifdef CONFIG_SERIAL_BFIN_DMA
- if (uart->tx_done)
- bfin_serial_dma_tx_chars(uart);
-#else
- UART_SET_IER(uart, ETBEI);
- bfin_serial_tx_chars(uart);
-#endif
-}
-
-/*
- * Interrupts are enabled
- */
-static void bfin_serial_stop_rx(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-
- UART_CLEAR_IER(uart, ERBFI);
-}
-
-/*
- * Set the modem control timer to fire immediately.
- */
-static void bfin_serial_enable_ms(struct uart_port *port)
-{
-}
-
-
-#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
-# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
-# define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
-#else
-# define UART_GET_ANOMALY_THRESHOLD(uart) 0
-# define UART_SET_ANOMALY_THRESHOLD(uart, v)
-#endif
-
-#ifdef CONFIG_SERIAL_BFIN_PIO
-static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
-{
- struct tty_struct *tty = NULL;
- unsigned int status, ch, flg;
- static struct timeval anomaly_start = { .tv_sec = 0 };
-
- status = UART_GET_LSR(uart);
- UART_CLEAR_LSR(uart);
-
- ch = UART_GET_CHAR(uart);
- uart->port.icount.rx++;
-
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
- defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
- if (kgdb_connected && kgdboc_port_line == uart->port.line
- && kgdboc_break_enabled)
- if (ch == 0x3) {/* Ctrl + C */
- kgdb_breakpoint();
- return;
- }
-
- if (!uart->port.state || !uart->port.state->port.tty)
- return;
-#endif
- tty = uart->port.state->port.tty;
-
- if (ANOMALY_05000363) {
- /* The BF533 (and BF561) family of processors have a nice anomaly
- * where they continuously generate characters for a "single" break.
- * We have to basically ignore this flood until the "next" valid
- * character comes across. Due to the nature of the flood, it is
- * not possible to reliably catch bytes that are sent too quickly
- * after this break. So application code talking to the Blackfin
- * which sends a break signal must allow at least 1.5 character
- * times after the end of the break for things to stabilize. This
- * timeout was picked as it must absolutely be larger than 1
- * character time +/- some percent. So 1.5 sounds good. All other
- * Blackfin families operate properly. Woo.
- */
- if (anomaly_start.tv_sec) {
- struct timeval curr;
- suseconds_t usecs;
-
- if ((~ch & (~ch + 1)) & 0xff)
- goto known_good_char;
-
- do_gettimeofday(&curr);
- if (curr.tv_sec - anomaly_start.tv_sec > 1)
- goto known_good_char;
-
- usecs = 0;
- if (curr.tv_sec != anomaly_start.tv_sec)
- usecs += USEC_PER_SEC;
- usecs += curr.tv_usec - anomaly_start.tv_usec;
-
- if (usecs > UART_GET_ANOMALY_THRESHOLD(uart))
- goto known_good_char;
-
- if (ch)
- anomaly_start.tv_sec = 0;
- else
- anomaly_start = curr;
-
- return;
-
- known_good_char:
- status &= ~BI;
- anomaly_start.tv_sec = 0;
- }
- }
-
- if (status & BI) {
- if (ANOMALY_05000363)
- if (bfin_revid() < 5)
- do_gettimeofday(&anomaly_start);
- uart->port.icount.brk++;
- if (uart_handle_break(&uart->port))
- goto ignore_char;
- status &= ~(PE | FE);
- }
- if (status & PE)
- uart->port.icount.parity++;
- if (status & OE)
- uart->port.icount.overrun++;
- if (status & FE)
- uart->port.icount.frame++;
-
- status &= uart->port.read_status_mask;
-
- if (status & BI)
- flg = TTY_BREAK;
- else if (status & PE)
- flg = TTY_PARITY;
- else if (status & FE)
- flg = TTY_FRAME;
- else
- flg = TTY_NORMAL;
-
- if (uart_handle_sysrq_char(&uart->port, ch))
- goto ignore_char;
-
- uart_insert_char(&uart->port, status, OE, ch, flg);
-
- ignore_char:
- tty_flip_buffer_push(tty);
-}
-
-static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
-{
- struct circ_buf *xmit = &uart->port.state->xmit;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
-#ifdef CONFIG_BF54x
- /* Clear TFI bit */
- UART_PUT_LSR(uart, TFI);
-#endif
- /* Anomaly notes:
- * 05000215 - we always clear ETBEI within last UART TX
- * interrupt to end a string. It is always set
- * when start a new tx.
- */
- UART_CLEAR_IER(uart, ETBEI);
- return;
- }
-
- if (uart->port.x_char) {
- UART_PUT_CHAR(uart, uart->port.x_char);
- uart->port.icount.tx++;
- uart->port.x_char = 0;
- }
-
- while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
- UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- uart->port.icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uart->port);
-}
-
-static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
-{
- struct bfin_serial_port *uart = dev_id;
-
- spin_lock(&uart->port.lock);
- while (UART_GET_LSR(uart) & DR)
- bfin_serial_rx_chars(uart);
- spin_unlock(&uart->port.lock);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
-{
- struct bfin_serial_port *uart = dev_id;
-
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
- uart->scts = 0;
- uart_handle_cts_change(&uart->port, uart->scts);
- }
-#endif
- spin_lock(&uart->port.lock);
- if (UART_GET_LSR(uart) & THRE)
- bfin_serial_tx_chars(uart);
- spin_unlock(&uart->port.lock);
-
- return IRQ_HANDLED;
-}
-#endif
-
-#ifdef CONFIG_SERIAL_BFIN_DMA
-static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
-{
- struct circ_buf *xmit = &uart->port.state->xmit;
-
- uart->tx_done = 0;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
- uart->tx_count = 0;
- uart->tx_done = 1;
- return;
- }
-
- if (uart->port.x_char) {
- UART_PUT_CHAR(uart, uart->port.x_char);
- uart->port.icount.tx++;
- uart->port.x_char = 0;
- }
-
- uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
- if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail))
- uart->tx_count = UART_XMIT_SIZE - xmit->tail;
- blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail),
- (unsigned long)(xmit->buf+xmit->tail+uart->tx_count));
- set_dma_config(uart->tx_dma_channel,
- set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP,
- INTR_ON_BUF,
- DIMENSION_LINEAR,
- DATA_SIZE_8,
- DMA_SYNC_RESTART));
- set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
- set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
- set_dma_x_modify(uart->tx_dma_channel, 1);
- SSYNC();
- enable_dma(uart->tx_dma_channel);
-
- UART_SET_IER(uart, ETBEI);
-}
-
-static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
-{
- struct tty_struct *tty = uart->port.state->port.tty;
- int i, flg, status;
-
- status = UART_GET_LSR(uart);
- UART_CLEAR_LSR(uart);
-
- uart->port.icount.rx +=
- CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail,
- UART_XMIT_SIZE);
-
- if (status & BI) {
- uart->port.icount.brk++;
- if (uart_handle_break(&uart->port))
- goto dma_ignore_char;
- status &= ~(PE | FE);
- }
- if (status & PE)
- uart->port.icount.parity++;
- if (status & OE)
- uart->port.icount.overrun++;
- if (status & FE)
- uart->port.icount.frame++;
-
- status &= uart->port.read_status_mask;
-
- if (status & BI)
- flg = TTY_BREAK;
- else if (status & PE)
- flg = TTY_PARITY;
- else if (status & FE)
- flg = TTY_FRAME;
- else
- flg = TTY_NORMAL;
-
- for (i = uart->rx_dma_buf.tail; ; i++) {
- if (i >= UART_XMIT_SIZE)
- i = 0;
- if (i == uart->rx_dma_buf.head)
- break;
- if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
- uart_insert_char(&uart->port, status, OE,
- uart->rx_dma_buf.buf[i], flg);
- }
-
- dma_ignore_char:
- tty_flip_buffer_push(tty);
-}
-
-void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
-{
- int x_pos, pos;
-
- dma_disable_irq(uart->tx_dma_channel);
- dma_disable_irq(uart->rx_dma_channel);
- spin_lock_bh(&uart->port.lock);
-
- /* 2D DMA RX buffer ring is used. Because curr_y_count and
- * curr_x_count can't be read as an atomic operation,
- * curr_y_count should be read before curr_x_count. When
- * curr_x_count is read, curr_y_count may already indicate
- * next buffer line. But, the position calculated here is
- * still indicate the old line. The wrong position data may
- * be smaller than current buffer tail, which cause garbages
- * are received if it is not prohibit.
- */
- uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
- x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
- uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
- if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
- uart->rx_dma_nrows = 0;
- x_pos = DMA_RX_XCOUNT - x_pos;
- if (x_pos == DMA_RX_XCOUNT)
- x_pos = 0;
-
- pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
- /* Ignore receiving data if new position is in the same line of
- * current buffer tail and small.
- */
- if (pos > uart->rx_dma_buf.tail ||
- uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
- uart->rx_dma_buf.head = pos;
- bfin_serial_dma_rx_chars(uart);
- uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
- }
-
- spin_unlock_bh(&uart->port.lock);
- dma_enable_irq(uart->tx_dma_channel);
- dma_enable_irq(uart->rx_dma_channel);
-
- mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
-}
-
-static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
-{
- struct bfin_serial_port *uart = dev_id;
- struct circ_buf *xmit = &uart->port.state->xmit;
-
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->scts && !(bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
- uart->scts = 0;
- uart_handle_cts_change(&uart->port, uart->scts);
- }
-#endif
-
- spin_lock(&uart->port.lock);
- if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
- disable_dma(uart->tx_dma_channel);
- clear_dma_irqstat(uart->tx_dma_channel);
- /* Anomaly notes:
- * 05000215 - we always clear ETBEI within last UART TX
- * interrupt to end a string. It is always set
- * when start a new tx.
- */
- UART_CLEAR_IER(uart, ETBEI);
- xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
- uart->port.icount.tx += uart->tx_count;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uart->port);
-
- bfin_serial_dma_tx_chars(uart);
- }
-
- spin_unlock(&uart->port.lock);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
-{
- struct bfin_serial_port *uart = dev_id;
- unsigned short irqstat;
- int x_pos, pos;
-
- spin_lock(&uart->port.lock);
- irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
- clear_dma_irqstat(uart->rx_dma_channel);
-
- uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
- x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
- uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
- if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
- uart->rx_dma_nrows = 0;
-
- pos = uart->rx_dma_nrows * DMA_RX_XCOUNT;
- if (pos > uart->rx_dma_buf.tail ||
- uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
- uart->rx_dma_buf.head = pos;
- bfin_serial_dma_rx_chars(uart);
- uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
- }
-
- spin_unlock(&uart->port.lock);
-
- return IRQ_HANDLED;
-}
-#endif
-
-/*
- * Return TIOCSER_TEMT when transmitter is not busy.
- */
-static unsigned int bfin_serial_tx_empty(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned short lsr;
-
- lsr = UART_GET_LSR(uart);
- if (lsr & TEMT)
- return TIOCSER_TEMT;
- else
- return 0;
-}
-
-static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- u16 lcr = UART_GET_LCR(uart);
- if (break_state)
- lcr |= SB;
- else
- lcr &= ~SB;
- UART_PUT_LCR(uart, lcr);
- SSYNC();
-}
-
-static int bfin_serial_startup(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-
-#ifdef CONFIG_SERIAL_BFIN_DMA
- dma_addr_t dma_handle;
-
- if (request_dma(uart->rx_dma_channel, "BFIN_UART_RX") < 0) {
- printk(KERN_NOTICE "Unable to attach Blackfin UART RX DMA channel\n");
- return -EBUSY;
- }
-
- if (request_dma(uart->tx_dma_channel, "BFIN_UART_TX") < 0) {
- printk(KERN_NOTICE "Unable to attach Blackfin UART TX DMA channel\n");
- free_dma(uart->rx_dma_channel);
- return -EBUSY;
- }
-
- set_dma_callback(uart->rx_dma_channel, bfin_serial_dma_rx_int, uart);
- set_dma_callback(uart->tx_dma_channel, bfin_serial_dma_tx_int, uart);
-
- uart->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA);
- uart->rx_dma_buf.head = 0;
- uart->rx_dma_buf.tail = 0;
- uart->rx_dma_nrows = 0;
-
- set_dma_config(uart->rx_dma_channel,
- set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO,
- INTR_ON_ROW, DIMENSION_2D,
- DATA_SIZE_8,
- DMA_SYNC_RESTART));
- set_dma_x_count(uart->rx_dma_channel, DMA_RX_XCOUNT);
- set_dma_x_modify(uart->rx_dma_channel, 1);
- set_dma_y_count(uart->rx_dma_channel, DMA_RX_YCOUNT);
- set_dma_y_modify(uart->rx_dma_channel, 1);
- set_dma_start_addr(uart->rx_dma_channel, (unsigned long)uart->rx_dma_buf.buf);
- enable_dma(uart->rx_dma_channel);
-
- uart->rx_dma_timer.data = (unsigned long)(uart);
- uart->rx_dma_timer.function = (void *)bfin_serial_rx_dma_timeout;
- uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
- add_timer(&(uart->rx_dma_timer));
-#else
-# if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
- defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
- if (kgdboc_port_line == uart->port.line && kgdboc_break_enabled)
- kgdboc_break_enabled = 0;
- else {
-# endif
- if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
- "BFIN_UART_RX", uart)) {
- printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
- return -EBUSY;
- }
-
- if (request_irq
- (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED,
- "BFIN_UART_TX", uart)) {
- printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n");
- free_irq(uart->port.irq, uart);
- return -EBUSY;
- }
-
-# ifdef CONFIG_BF54x
- {
- /*
- * UART2 and UART3 on BF548 share interrupt PINs and DMA
- * controllers with SPORT2 and SPORT3. UART rx and tx
- * interrupts are generated in PIO mode only when configure
- * their peripheral mapping registers properly, which means
- * request corresponding DMA channels in PIO mode as well.
- */
- unsigned uart_dma_ch_rx, uart_dma_ch_tx;
-
- switch (uart->port.irq) {
- case IRQ_UART3_RX:
- uart_dma_ch_rx = CH_UART3_RX;
- uart_dma_ch_tx = CH_UART3_TX;
- break;
- case IRQ_UART2_RX:
- uart_dma_ch_rx = CH_UART2_RX;
- uart_dma_ch_tx = CH_UART2_TX;
- break;
- default:
- uart_dma_ch_rx = uart_dma_ch_tx = 0;
- break;
- };
-
- if (uart_dma_ch_rx &&
- request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) {
- printk(KERN_NOTICE"Fail to attach UART interrupt\n");
- free_irq(uart->port.irq, uart);
- free_irq(uart->port.irq + 1, uart);
- return -EBUSY;
- }
- if (uart_dma_ch_tx &&
- request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) {
- printk(KERN_NOTICE "Fail to attach UART interrupt\n");
- free_dma(uart_dma_ch_rx);
- free_irq(uart->port.irq, uart);
- free_irq(uart->port.irq + 1, uart);
- return -EBUSY;
- }
- }
-# endif
-# if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
- defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
- }
-# endif
-#endif
-
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
- if (uart->cts_pin >= 0) {
- if (request_irq(gpio_to_irq(uart->cts_pin),
- bfin_serial_mctrl_cts_int,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
- IRQF_DISABLED, "BFIN_UART_CTS", uart)) {
- uart->cts_pin = -1;
- pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n");
- }
- }
- if (uart->rts_pin >= 0) {
- gpio_direction_output(uart->rts_pin, 0);
- }
-#endif
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->cts_pin >= 0 && request_irq(uart->status_irq,
- bfin_serial_mctrl_cts_int,
- IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
- uart->cts_pin = -1;
- pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n");
- }
-
- /* CTS RTS PINs are negative assertive. */
- UART_PUT_MCR(uart, ACTS);
- UART_SET_IER(uart, EDSSI);
-#endif
-
- UART_SET_IER(uart, ERBFI);
- return 0;
-}
-
-static void bfin_serial_shutdown(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-
-#ifdef CONFIG_SERIAL_BFIN_DMA
- disable_dma(uart->tx_dma_channel);
- free_dma(uart->tx_dma_channel);
- disable_dma(uart->rx_dma_channel);
- free_dma(uart->rx_dma_channel);
- del_timer(&(uart->rx_dma_timer));
- dma_free_coherent(NULL, PAGE_SIZE, uart->rx_dma_buf.buf, 0);
-#else
-#ifdef CONFIG_BF54x
- switch (uart->port.irq) {
- case IRQ_UART3_RX:
- free_dma(CH_UART3_RX);
- free_dma(CH_UART3_TX);
- break;
- case IRQ_UART2_RX:
- free_dma(CH_UART2_RX);
- free_dma(CH_UART2_TX);
- break;
- default:
- break;
- };
-#endif
- free_irq(uart->port.irq, uart);
- free_irq(uart->port.irq+1, uart);
-#endif
-
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
- if (uart->cts_pin >= 0)
- free_irq(gpio_to_irq(uart->cts_pin), uart);
-#endif
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->cts_pin >= 0)
- free_irq(uart->status_irq, uart);
-#endif
-}
-
-static void
-bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned long flags;
- unsigned int baud, quot;
- unsigned short val, ier, lcr = 0;
-
- switch (termios->c_cflag & CSIZE) {
- case CS8:
- lcr = WLS(8);
- break;
- case CS7:
- lcr = WLS(7);
- break;
- case CS6:
- lcr = WLS(6);
- break;
- case CS5:
- lcr = WLS(5);
- break;
- default:
- printk(KERN_ERR "%s: word lengh not supported\n",
- __func__);
- }
-
- /* Anomaly notes:
- * 05000231 - STOP bit is always set to 1 whatever the user is set.
- */
- if (termios->c_cflag & CSTOPB) {
- if (ANOMALY_05000231)
- printk(KERN_WARNING "STOP bits other than 1 is not "
- "supported in case of anomaly 05000231.\n");
- else
- lcr |= STB;
- }
- if (termios->c_cflag & PARENB)
- lcr |= PEN;
- if (!(termios->c_cflag & PARODD))
- lcr |= EPS;
- if (termios->c_cflag & CMSPAR)
- lcr |= STP;
-
- spin_lock_irqsave(&uart->port.lock, flags);
-
- port->read_status_mask = OE;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= (FE | PE);
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= BI;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= FE | PE;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= OE;
- }
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- /* If discipline is not IRDA, apply ANOMALY_05000230 */
- if (termios->c_line != N_IRDA)
- quot -= ANOMALY_05000230;
-
- UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
-
- /* Disable UART */
- ier = UART_GET_IER(uart);
- UART_DISABLE_INTS(uart);
-
- /* Set DLAB in LCR to Access DLL and DLH */
- UART_SET_DLAB(uart);
-
- UART_PUT_DLL(uart, quot & 0xFF);
- UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
- SSYNC();
-
- /* Clear DLAB in LCR to Access THR RBR IER */
- UART_CLEAR_DLAB(uart);
-
- UART_PUT_LCR(uart, lcr);
-
- /* Enable UART */
- UART_ENABLE_INTS(uart, ier);
-
- val = UART_GET_GCTL(uart);
- val |= UCEN;
- UART_PUT_GCTL(uart, val);
-
- /* Port speed changed, update the per-port timeout. */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_unlock_irqrestore(&uart->port.lock, flags);
-}
-
-static const char *bfin_serial_type(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-
- return uart->port.type == PORT_BFIN ? "BFIN-UART" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'.
- */
-static void bfin_serial_release_port(struct uart_port *port)
-{
-}
-
-/*
- * Request the memory region(s) being used by 'port'.
- */
-static int bfin_serial_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void bfin_serial_config_port(struct uart_port *port, int flags)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-
- if (flags & UART_CONFIG_TYPE &&
- bfin_serial_request_port(&uart->port) == 0)
- uart->port.type = PORT_BFIN;
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- * The only change we allow are to the flags and type, and
- * even then only between PORT_BFIN and PORT_UNKNOWN
- */
-static int
-bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return 0;
-}
-
-/*
- * Enable the IrDA function if tty->ldisc.num is N_IRDA.
- * In other cases, disable IrDA function.
- */
-static void bfin_serial_set_ldisc(struct uart_port *port, int ld)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned short val;
-
- switch (ld) {
- case N_IRDA:
- val = UART_GET_GCTL(uart);
- val |= (IREN | RPOLC);
- UART_PUT_GCTL(uart, val);
- break;
- default:
- val = UART_GET_GCTL(uart);
- val &= ~(IREN | RPOLC);
- UART_PUT_GCTL(uart, val);
- }
-}
-
-static void bfin_serial_reset_irda(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned short val;
-
- val = UART_GET_GCTL(uart);
- val &= ~(IREN | RPOLC);
- UART_PUT_GCTL(uart, val);
- SSYNC();
- val |= (IREN | RPOLC);
- UART_PUT_GCTL(uart, val);
- SSYNC();
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/* Anomaly notes:
- * 05000099 - Because we only use THRE in poll_put and DR in poll_get,
- * losing other bits of UART_LSR is not a problem here.
- */
-static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-
- while (!(UART_GET_LSR(uart) & THRE))
- cpu_relax();
-
- UART_CLEAR_DLAB(uart);
- UART_PUT_CHAR(uart, (unsigned char)chr);
-}
-
-static int bfin_serial_poll_get_char(struct uart_port *port)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned char chr;
-
- while (!(UART_GET_LSR(uart) & DR))
- cpu_relax();
-
- UART_CLEAR_DLAB(uart);
- chr = UART_GET_CHAR(uart);
-
- return chr;
-}
-#endif
-
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
- defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
-static void bfin_kgdboc_port_shutdown(struct uart_port *port)
-{
- if (kgdboc_break_enabled) {
- kgdboc_break_enabled = 0;
- bfin_serial_shutdown(port);
- }
-}
-
-static int bfin_kgdboc_port_startup(struct uart_port *port)
-{
- kgdboc_port_line = port->line;
- kgdboc_break_enabled = !bfin_serial_startup(port);
- return 0;
-}
-#endif
-
-static struct uart_ops bfin_serial_pops = {
- .tx_empty = bfin_serial_tx_empty,
- .set_mctrl = bfin_serial_set_mctrl,
- .get_mctrl = bfin_serial_get_mctrl,
- .stop_tx = bfin_serial_stop_tx,
- .start_tx = bfin_serial_start_tx,
- .stop_rx = bfin_serial_stop_rx,
- .enable_ms = bfin_serial_enable_ms,
- .break_ctl = bfin_serial_break_ctl,
- .startup = bfin_serial_startup,
- .shutdown = bfin_serial_shutdown,
- .set_termios = bfin_serial_set_termios,
- .set_ldisc = bfin_serial_set_ldisc,
- .type = bfin_serial_type,
- .release_port = bfin_serial_release_port,
- .request_port = bfin_serial_request_port,
- .config_port = bfin_serial_config_port,
- .verify_port = bfin_serial_verify_port,
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
- defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
- .kgdboc_port_startup = bfin_kgdboc_port_startup,
- .kgdboc_port_shutdown = bfin_kgdboc_port_shutdown,
-#endif
-#ifdef CONFIG_CONSOLE_POLL
- .poll_put_char = bfin_serial_poll_put_char,
- .poll_get_char = bfin_serial_poll_get_char,
-#endif
-};
-
-#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
-/*
- * If the port was already initialised (eg, by a boot loader),
- * try to determine the current setup.
- */
-static void __init
-bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
- int *parity, int *bits)
-{
- unsigned short status;
-
- status = UART_GET_IER(uart) & (ERBFI | ETBEI);
- if (status == (ERBFI | ETBEI)) {
- /* ok, the port was enabled */
- u16 lcr, dlh, dll;
-
- lcr = UART_GET_LCR(uart);
-
- *parity = 'n';
- if (lcr & PEN) {
- if (lcr & EPS)
- *parity = 'e';
- else
- *parity = 'o';
- }
- switch (lcr & 0x03) {
- case 0: *bits = 5; break;
- case 1: *bits = 6; break;
- case 2: *bits = 7; break;
- case 3: *bits = 8; break;
- }
- /* Set DLAB in LCR to Access DLL and DLH */
- UART_SET_DLAB(uart);
-
- dll = UART_GET_DLL(uart);
- dlh = UART_GET_DLH(uart);
-
- /* Clear DLAB in LCR to Access THR RBR IER */
- UART_CLEAR_DLAB(uart);
-
- *baud = get_sclk() / (16*(dll | dlh << 8));
- }
- pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits);
-}
-
-static struct uart_driver bfin_serial_reg;
-
-static void bfin_serial_console_putchar(struct uart_port *port, int ch)
-{
- struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- while (!(UART_GET_LSR(uart) & THRE))
- barrier();
- UART_PUT_CHAR(uart, ch);
-}
-
-#endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) ||
- defined (CONFIG_EARLY_PRINTK) */
-
-#ifdef CONFIG_SERIAL_BFIN_CONSOLE
-#define CLASS_BFIN_CONSOLE "bfin-console"
-/*
- * Interrupts are disabled on entering
- */
-static void
-bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct bfin_serial_port *uart = bfin_serial_ports[co->index];
- unsigned long flags;
-
- spin_lock_irqsave(&uart->port.lock, flags);
- uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);
- spin_unlock_irqrestore(&uart->port.lock, flags);
-
-}
-
-static int __init
-bfin_serial_console_setup(struct console *co, char *options)
-{
- struct bfin_serial_port *uart;
- int baud = 57600;
- int bits = 8;
- int parity = 'n';
-# if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
- defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
- int flow = 'r';
-# else
- int flow = 'n';
-# endif
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index < 0 || co->index >= BFIN_UART_NR_PORTS)
- return -ENODEV;
-
- uart = bfin_serial_ports[co->index];
- if (!uart)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- bfin_serial_console_get_options(uart, &baud, &parity, &bits);
-
- return uart_set_options(&uart->port, co, baud, parity, bits, flow);
-}
-
-static struct console bfin_serial_console = {
- .name = BFIN_SERIAL_DEV_NAME,
- .write = bfin_serial_console_write,
- .device = uart_console_device,
- .setup = bfin_serial_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &bfin_serial_reg,
-};
-#define BFIN_SERIAL_CONSOLE &bfin_serial_console
-#else
-#define BFIN_SERIAL_CONSOLE NULL
-#endif /* CONFIG_SERIAL_BFIN_CONSOLE */
-
-#ifdef CONFIG_EARLY_PRINTK
-static struct bfin_serial_port bfin_earlyprintk_port;
-#define CLASS_BFIN_EARLYPRINTK "bfin-earlyprintk"
-
-/*
- * Interrupts are disabled on entering
- */
-static void
-bfin_earlyprintk_console_write(struct console *co, const char *s, unsigned int count)
-{
- unsigned long flags;
-
- if (bfin_earlyprintk_port.port.line != co->index)
- return;
-
- spin_lock_irqsave(&bfin_earlyprintk_port.port.lock, flags);
- uart_console_write(&bfin_earlyprintk_port.port, s, count,
- bfin_serial_console_putchar);
- spin_unlock_irqrestore(&bfin_earlyprintk_port.port.lock, flags);
-}
-
-/*
- * This should have a .setup or .early_setup in it, but then things get called
- * without the command line options, and the baud rate gets messed up - so
- * don't let the common infrastructure play with things. (see calls to setup
- * & earlysetup in ./kernel/printk.c:register_console()
- */
-static struct __initdata console bfin_early_serial_console = {
- .name = "early_BFuart",
- .write = bfin_earlyprintk_console_write,
- .device = uart_console_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &bfin_serial_reg,
-};
-#endif
-
-static struct uart_driver bfin_serial_reg = {
- .owner = THIS_MODULE,
- .driver_name = DRIVER_NAME,
- .dev_name = BFIN_SERIAL_DEV_NAME,
- .major = BFIN_SERIAL_MAJOR,
- .minor = BFIN_SERIAL_MINOR,
- .nr = BFIN_UART_NR_PORTS,
- .cons = BFIN_SERIAL_CONSOLE,
-};
-
-static int bfin_serial_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct bfin_serial_port *uart = platform_get_drvdata(pdev);
-
- return uart_suspend_port(&bfin_serial_reg, &uart->port);
-}
-
-static int bfin_serial_resume(struct platform_device *pdev)
-{
- struct bfin_serial_port *uart = platform_get_drvdata(pdev);
-
- return uart_resume_port(&bfin_serial_reg, &uart->port);
-}
-
-static int bfin_serial_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct bfin_serial_port *uart = NULL;
- int ret = 0;
-
- if (pdev->id < 0 || pdev->id >= BFIN_UART_NR_PORTS) {
- dev_err(&pdev->dev, "Wrong bfin uart platform device id.\n");
- return -ENOENT;
- }
-
- if (bfin_serial_ports[pdev->id] == NULL) {
-
- uart = kzalloc(sizeof(*uart), GFP_KERNEL);
- if (!uart) {
- dev_err(&pdev->dev,
- "fail to malloc bfin_serial_port\n");
- return -ENOMEM;
- }
- bfin_serial_ports[pdev->id] = uart;
-
-#ifdef CONFIG_EARLY_PRINTK
- if (!(bfin_earlyprintk_port.port.membase
- && bfin_earlyprintk_port.port.line == pdev->id)) {
- /*
- * If the peripheral PINs of current port is allocated
- * in earlyprintk probe stage, don't do it again.
- */
-#endif
- ret = peripheral_request_list(
- (unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
- if (ret) {
- dev_err(&pdev->dev,
- "fail to request bfin serial peripherals\n");
- goto out_error_free_mem;
- }
-#ifdef CONFIG_EARLY_PRINTK
- }
-#endif
-
- spin_lock_init(&uart->port.lock);
- uart->port.uartclk = get_sclk();
- uart->port.fifosize = BFIN_UART_TX_FIFO_SIZE;
- uart->port.ops = &bfin_serial_pops;
- uart->port.line = pdev->id;
- uart->port.iotype = UPIO_MEM;
- uart->port.flags = UPF_BOOT_AUTOCONF;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
- ret = -ENOENT;
- goto out_error_free_peripherals;
- }
-
- uart->port.membase = ioremap(res->start,
- res->end - res->start);
- if (!uart->port.membase) {
- dev_err(&pdev->dev, "Cannot map uart IO\n");
- ret = -ENXIO;
- goto out_error_free_peripherals;
- }
- uart->port.mapbase = res->start;
-
- uart->port.irq = platform_get_irq(pdev, 0);
- if (uart->port.irq < 0) {
- dev_err(&pdev->dev, "No uart RX/TX IRQ specified\n");
- ret = -ENOENT;
- goto out_error_unmap;
- }
-
- uart->status_irq = platform_get_irq(pdev, 1);
- if (uart->status_irq < 0) {
- dev_err(&pdev->dev, "No uart status IRQ specified\n");
- ret = -ENOENT;
- goto out_error_unmap;
- }
-
-#ifdef CONFIG_SERIAL_BFIN_DMA
- uart->tx_done = 1;
- uart->tx_count = 0;
-
- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "No uart TX DMA channel specified\n");
- ret = -ENOENT;
- goto out_error_unmap;
- }
- uart->tx_dma_channel = res->start;
-
- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (res == NULL) {
- dev_err(&pdev->dev, "No uart RX DMA channel specified\n");
- ret = -ENOENT;
- goto out_error_unmap;
- }
- uart->rx_dma_channel = res->start;
-
- init_timer(&(uart->rx_dma_timer));
-#endif
-
-#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
- defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (res == NULL)
- uart->cts_pin = -1;
- else
- uart->cts_pin = res->start;
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 1);
- if (res == NULL)
- uart->rts_pin = -1;
- else
- uart->rts_pin = res->start;
-# if defined(CONFIG_SERIAL_BFIN_CTSRTS)
- if (uart->rts_pin >= 0)
- gpio_request(uart->rts_pin, DRIVER_NAME);
-# endif
-#endif
- }
-
-#ifdef CONFIG_SERIAL_BFIN_CONSOLE
- if (!is_early_platform_device(pdev)) {
-#endif
- uart = bfin_serial_ports[pdev->id];
- uart->port.dev = &pdev->dev;
- dev_set_drvdata(&pdev->dev, uart);
- ret = uart_add_one_port(&bfin_serial_reg, &uart->port);
-#ifdef CONFIG_SERIAL_BFIN_CONSOLE
- }
-#endif
-
- if (!ret)
- return 0;
-
- if (uart) {
-out_error_unmap:
- iounmap(uart->port.membase);
-out_error_free_peripherals:
- peripheral_free_list(
- (unsigned short *)pdev->dev.platform_data);
-out_error_free_mem:
- kfree(uart);
- bfin_serial_ports[pdev->id] = NULL;
- }
-
- return ret;
-}
-
-static int __devexit bfin_serial_remove(struct platform_device *pdev)
-{
- struct bfin_serial_port *uart = platform_get_drvdata(pdev);
-
- dev_set_drvdata(&pdev->dev, NULL);
-
- if (uart) {
- uart_remove_one_port(&bfin_serial_reg, &uart->port);
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
- if (uart->rts_pin >= 0)
- gpio_free(uart->rts_pin);
-#endif
- iounmap(uart->port.membase);
- peripheral_free_list(
- (unsigned short *)pdev->dev.platform_data);
- kfree(uart);
- bfin_serial_ports[pdev->id] = NULL;
- }
-
- return 0;
-}
-
-static struct platform_driver bfin_serial_driver = {
- .probe = bfin_serial_probe,
- .remove = __devexit_p(bfin_serial_remove),
- .suspend = bfin_serial_suspend,
- .resume = bfin_serial_resume,
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-#if defined(CONFIG_SERIAL_BFIN_CONSOLE)
-static __initdata struct early_platform_driver early_bfin_serial_driver = {
- .class_str = CLASS_BFIN_CONSOLE,
- .pdrv = &bfin_serial_driver,
- .requested_id = EARLY_PLATFORM_ID_UNSET,
-};
-
-static int __init bfin_serial_rs_console_init(void)
-{
- early_platform_driver_register(&early_bfin_serial_driver, DRIVER_NAME);
-
- early_platform_driver_probe(CLASS_BFIN_CONSOLE, BFIN_UART_NR_PORTS, 0);
-
- register_console(&bfin_serial_console);
-
- return 0;
-}
-console_initcall(bfin_serial_rs_console_init);
-#endif
-
-#ifdef CONFIG_EARLY_PRINTK
-/*
- * Memory can't be allocated dynamically during earlyprink init stage.
- * So, do individual probe for earlyprink with a static uart port variable.
- */
-static int bfin_earlyprintk_probe(struct platform_device *pdev)
-{
- struct resource *res;
- int ret;
-
- if (pdev->id < 0 || pdev->id >= BFIN_UART_NR_PORTS) {
- dev_err(&pdev->dev, "Wrong earlyprintk platform device id.\n");
- return -ENOENT;
- }
-
- ret = peripheral_request_list(
- (unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
- if (ret) {
- dev_err(&pdev->dev,
- "fail to request bfin serial peripherals\n");
- return ret;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
- ret = -ENOENT;
- goto out_error_free_peripherals;
- }
-
- bfin_earlyprintk_port.port.membase = ioremap(res->start,
- res->end - res->start);
- if (!bfin_earlyprintk_port.port.membase) {
- dev_err(&pdev->dev, "Cannot map uart IO\n");
- ret = -ENXIO;
- goto out_error_free_peripherals;
- }
- bfin_earlyprintk_port.port.mapbase = res->start;
- bfin_earlyprintk_port.port.line = pdev->id;
- bfin_earlyprintk_port.port.uartclk = get_sclk();
- bfin_earlyprintk_port.port.fifosize = BFIN_UART_TX_FIFO_SIZE;
- spin_lock_init(&bfin_earlyprintk_port.port.lock);
-
- return 0;
-
-out_error_free_peripherals:
- peripheral_free_list(
- (unsigned short *)pdev->dev.platform_data);
-
- return ret;
-}
-
-static struct platform_driver bfin_earlyprintk_driver = {
- .probe = bfin_earlyprintk_probe,
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static __initdata struct early_platform_driver early_bfin_earlyprintk_driver = {
- .class_str = CLASS_BFIN_EARLYPRINTK,
- .pdrv = &bfin_earlyprintk_driver,
- .requested_id = EARLY_PLATFORM_ID_UNSET,
-};
-
-struct console __init *bfin_earlyserial_init(unsigned int port,
- unsigned int cflag)
-{
- struct ktermios t;
- char port_name[20];
-
- if (port < 0 || port >= BFIN_UART_NR_PORTS)
- return NULL;
-
- /*
- * Only probe resource of the given port in earlyprintk boot arg.
- * The expected port id should be indicated in port name string.
- */
- snprintf(port_name, 20, DRIVER_NAME ".%d", port);
- early_platform_driver_register(&early_bfin_earlyprintk_driver,
- port_name);
- early_platform_driver_probe(CLASS_BFIN_EARLYPRINTK, 1, 0);
-
- if (!bfin_earlyprintk_port.port.membase)
- return NULL;
-
-#ifdef CONFIG_SERIAL_BFIN_CONSOLE
- /*
- * If we are using early serial, don't let the normal console rewind
- * log buffer, since that causes things to be printed multiple times
- */
- bfin_serial_console.flags &= ~CON_PRINTBUFFER;
-#endif
-
- bfin_early_serial_console.index = port;
- t.c_cflag = cflag;
- t.c_iflag = 0;
- t.c_oflag = 0;
- t.c_lflag = ICANON;
- t.c_line = port;
- bfin_serial_set_termios(&bfin_earlyprintk_port.port, &t, &t);
-
- return &bfin_early_serial_console;
-}
-#endif /* CONFIG_EARLY_PRINTK */
-
-static int __init bfin_serial_init(void)
-{
- int ret;
-
- pr_info("Blackfin serial driver\n");
-
- ret = uart_register_driver(&bfin_serial_reg);
- if (ret) {
- pr_err("failed to register %s:%d\n",
- bfin_serial_reg.driver_name, ret);
- }
-
- ret = platform_driver_register(&bfin_serial_driver);
- if (ret) {
- pr_err("fail to register bfin uart\n");
- uart_unregister_driver(&bfin_serial_reg);
- }
-
- return ret;
-}
-
-static void __exit bfin_serial_exit(void)
-{
- platform_driver_unregister(&bfin_serial_driver);
- uart_unregister_driver(&bfin_serial_reg);
-}
-
-
-module_init(bfin_serial_init);
-module_exit(bfin_serial_exit);
-
-MODULE_AUTHOR("Sonic Zhang, Aubrey Li");
-MODULE_DESCRIPTION("Blackfin generic serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(BFIN_SERIAL_MAJOR);
-MODULE_ALIAS("platform:bfin-uart");
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
deleted file mode 100644
index e95c524d9d18..000000000000
--- a/drivers/serial/bfin_sport_uart.c
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- * Blackfin On-Chip Sport Emulated UART Driver
- *
- * Copyright 2006-2009 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-/*
- * This driver and the hardware supported are in term of EE-191 of ADI.
- * http://www.analog.com/static/imported-files/application_notes/EE191.pdf
- * This application note describe how to implement a UART on a Sharc DSP,
- * but this driver is implemented on Blackfin Processor.
- * Transmit Frame Sync is not used by this driver to transfer data out.
- */
-
-/* #define DEBUG */
-
-#define DRV_NAME "bfin-sport-uart"
-#define DEVICE_NAME "ttySS"
-#define pr_fmt(fmt) DRV_NAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-
-#include <asm/bfin_sport.h>
-#include <asm/delay.h>
-#include <asm/portmux.h>
-
-#include "bfin_sport_uart.h"
-
-struct sport_uart_port {
- struct uart_port port;
- int err_irq;
- unsigned short csize;
- unsigned short rxmask;
- unsigned short txmask1;
- unsigned short txmask2;
- unsigned char stopb;
-/* unsigned char parib; */
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
- int cts_pin;
- int rts_pin;
-#endif
-};
-
-static int sport_uart_tx_chars(struct sport_uart_port *up);
-static void sport_stop_tx(struct uart_port *port);
-
-static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
-{
- pr_debug("%s value:%x, mask1=0x%x, mask2=0x%x\n", __func__, value,
- up->txmask1, up->txmask2);
-
- /* Place Start and Stop bits */
- __asm__ __volatile__ (
- "%[val] <<= 1;"
- "%[val] = %[val] & %[mask1];"
- "%[val] = %[val] | %[mask2];"
- : [val]"+d"(value)
- : [mask1]"d"(up->txmask1), [mask2]"d"(up->txmask2)
- : "ASTAT"
- );
- pr_debug("%s value:%x\n", __func__, value);
-
- SPORT_PUT_TX(up, value);
-}
-
-static inline unsigned char rx_one_byte(struct sport_uart_port *up)
-{
- unsigned int value;
- unsigned char extract;
- u32 tmp_mask1, tmp_mask2, tmp_shift, tmp;
-
- if ((up->csize + up->stopb) > 7)
- value = SPORT_GET_RX32(up);
- else
- value = SPORT_GET_RX(up);
-
- pr_debug("%s value:%x, cs=%d, mask=0x%x\n", __func__, value,
- up->csize, up->rxmask);
-
- /* Extract data */
- __asm__ __volatile__ (
- "%[extr] = 0;"
- "%[mask1] = %[rxmask];"
- "%[mask2] = 0x0200(Z);"
- "%[shift] = 0;"
- "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];"
- ".Lloop_s:"
- "%[tmp] = extract(%[val], %[mask1].L)(Z);"
- "%[tmp] <<= %[shift];"
- "%[extr] = %[extr] | %[tmp];"
- "%[mask1] = %[mask1] - %[mask2];"
- ".Lloop_e:"
- "%[shift] += 1;"
- : [extr]"=&d"(extract), [shift]"=&d"(tmp_shift), [tmp]"=&d"(tmp),
- [mask1]"=&d"(tmp_mask1), [mask2]"=&d"(tmp_mask2)
- : [val]"d"(value), [rxmask]"d"(up->rxmask), [lc]"a"(up->csize)
- : "ASTAT", "LB0", "LC0", "LT0"
- );
-
- pr_debug(" extract:%x\n", extract);
- return extract;
-}
-
-static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate)
-{
- int tclkdiv, rclkdiv;
- unsigned int sclk = get_sclk();
-
- /* Set TCR1 and TCR2, TFSR is not enabled for uart */
- SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK));
- SPORT_PUT_TCR2(up, size + 1);
- pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
-
- /* Set RCR1 and RCR2 */
- SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK));
- SPORT_PUT_RCR2(up, (size + 1) * 2 - 1);
- pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
-
- tclkdiv = sclk / (2 * baud_rate) - 1;
- /* The actual uart baud rate of devices vary between +/-2%. The sport
- * RX sample rate should be faster than the double of the worst case,
- * otherwise, wrong data are received. So, set sport RX clock to be
- * 3% faster.
- */
- rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1;
- SPORT_PUT_TCLKDIV(up, tclkdiv);
- SPORT_PUT_RCLKDIV(up, rclkdiv);
- SSYNC();
- pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, rclkdiv:%d\n",
- __func__, sclk, baud_rate, tclkdiv, rclkdiv);
-
- return 0;
-}
-
-static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id)
-{
- struct sport_uart_port *up = dev_id;
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned int ch;
-
- spin_lock(&up->port.lock);
-
- while (SPORT_GET_STAT(up) & RXNE) {
- ch = rx_one_byte(up);
- up->port.icount.rx++;
-
- if (!uart_handle_sysrq_char(&up->port, ch))
- tty_insert_flip_char(tty, ch, TTY_NORMAL);
- }
- tty_flip_buffer_push(tty);
-
- spin_unlock(&up->port.lock);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id)
-{
- struct sport_uart_port *up = dev_id;
-
- spin_lock(&up->port.lock);
- sport_uart_tx_chars(up);
- spin_unlock(&up->port.lock);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sport_uart_err_irq(int irq, void *dev_id)
-{
- struct sport_uart_port *up = dev_id;
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned int stat = SPORT_GET_STAT(up);
-
- spin_lock(&up->port.lock);
-
- /* Overflow in RX FIFO */
- if (stat & ROVF) {
- up->port.icount.overrun++;
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- SPORT_PUT_STAT(up, ROVF); /* Clear ROVF bit */
- }
- /* These should not happen */
- if (stat & (TOVF | TUVF | RUVF)) {
- pr_err("SPORT Error:%s %s %s\n",
- (stat & TOVF) ? "TX overflow" : "",
- (stat & TUVF) ? "TX underflow" : "",
- (stat & RUVF) ? "RX underflow" : "");
- SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
- SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
- }
- SSYNC();
-
- spin_unlock(&up->port.lock);
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
-static unsigned int sport_get_mctrl(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
- if (up->cts_pin < 0)
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-
- /* CTS PIN is negative assertive. */
- if (SPORT_UART_GET_CTS(up))
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
- else
- return TIOCM_DSR | TIOCM_CAR;
-}
-
-static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
- if (up->rts_pin < 0)
- return;
-
- /* RTS PIN is negative assertive. */
- if (mctrl & TIOCM_RTS)
- SPORT_UART_ENABLE_RTS(up);
- else
- SPORT_UART_DISABLE_RTS(up);
-}
-
-/*
- * Handle any change of modem status signal.
- */
-static irqreturn_t sport_mctrl_cts_int(int irq, void *dev_id)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)dev_id;
- unsigned int status;
-
- status = sport_get_mctrl(&up->port);
- uart_handle_cts_change(&up->port, status & TIOCM_CTS);
-
- return IRQ_HANDLED;
-}
-#else
-static unsigned int sport_get_mctrl(struct uart_port *port)
-{
- pr_debug("%s enter\n", __func__);
- return TIOCM_CTS | TIOCM_CD | TIOCM_DSR;
-}
-
-static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- pr_debug("%s enter\n", __func__);
-}
-#endif
-
-/* Reqeust IRQ, Setup clock */
-static int sport_startup(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
- int ret;
-
- pr_debug("%s enter\n", __func__);
- ret = request_irq(up->port.irq, sport_uart_rx_irq, 0,
- "SPORT_UART_RX", up);
- if (ret) {
- dev_err(port->dev, "unable to request SPORT RX interrupt\n");
- return ret;
- }
-
- ret = request_irq(up->port.irq+1, sport_uart_tx_irq, 0,
- "SPORT_UART_TX", up);
- if (ret) {
- dev_err(port->dev, "unable to request SPORT TX interrupt\n");
- goto fail1;
- }
-
- ret = request_irq(up->err_irq, sport_uart_err_irq, 0,
- "SPORT_UART_STATUS", up);
- if (ret) {
- dev_err(port->dev, "unable to request SPORT status interrupt\n");
- goto fail2;
- }
-
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
- if (up->cts_pin >= 0) {
- if (request_irq(gpio_to_irq(up->cts_pin),
- sport_mctrl_cts_int,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
- IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) {
- up->cts_pin = -1;
- dev_info(port->dev, "Unable to attach BlackFin UART \
- over SPORT CTS interrupt. So, disable it.\n");
- }
- }
- if (up->rts_pin >= 0)
- gpio_direction_output(up->rts_pin, 0);
-#endif
-
- return 0;
- fail2:
- free_irq(up->port.irq+1, up);
- fail1:
- free_irq(up->port.irq, up);
-
- return ret;
-}
-
-/*
- * sport_uart_tx_chars
- *
- * ret 1 means need to enable sport.
- * ret 0 means do nothing.
- */
-static int sport_uart_tx_chars(struct sport_uart_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
-
- if (SPORT_GET_STAT(up) & TXF)
- return 0;
-
- if (up->port.x_char) {
- tx_one_byte(up, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return 1;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- /* The waiting loop to stop SPORT TX from TX interrupt is
- * too long. This may block SPORT RX interrupts and cause
- * RX FIFO overflow. So, do stop sport TX only after the last
- * char in TX FIFO is moved into the shift register.
- */
- if (SPORT_GET_STAT(up) & TXHRE)
- sport_stop_tx(&up->port);
- return 0;
- }
-
- while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) {
- tx_one_byte(up, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
- up->port.icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- return 1;
-}
-
-static unsigned int sport_tx_empty(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
- unsigned int stat;
-
- stat = SPORT_GET_STAT(up);
- pr_debug("%s stat:%04x\n", __func__, stat);
- if (stat & TXHRE) {
- return TIOCSER_TEMT;
- } else
- return 0;
-}
-
-static void sport_stop_tx(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
-
- pr_debug("%s enter\n", __func__);
-
- if (!(SPORT_GET_TCR1(up) & TSPEN))
- return;
-
- /* Although the hold register is empty, last byte is still in shift
- * register and not sent out yet. So, put a dummy data into TX FIFO.
- * Then, sport tx stops when last byte is shift out and the dummy
- * data is moved into the shift register.
- */
- SPORT_PUT_TX(up, 0xffff);
- while (!(SPORT_GET_STAT(up) & TXHRE))
- cpu_relax();
-
- SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
- SSYNC();
-
- return;
-}
-
-static void sport_start_tx(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
-
- pr_debug("%s enter\n", __func__);
-
- /* Write data into SPORT FIFO before enable SPROT to transmit */
- if (sport_uart_tx_chars(up)) {
- /* Enable transmit, then an interrupt will generated */
- SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
- SSYNC();
- }
-
- pr_debug("%s exit\n", __func__);
-}
-
-static void sport_stop_rx(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
-
- pr_debug("%s enter\n", __func__);
- /* Disable sport to stop rx */
- SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
- SSYNC();
-}
-
-static void sport_enable_ms(struct uart_port *port)
-{
- pr_debug("%s enter\n", __func__);
-}
-
-static void sport_break_ctl(struct uart_port *port, int break_state)
-{
- pr_debug("%s enter\n", __func__);
-}
-
-static void sport_shutdown(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
-
- dev_dbg(port->dev, "%s enter\n", __func__);
-
- /* Disable sport */
- SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
- SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
- SSYNC();
-
- free_irq(up->port.irq, up);
- free_irq(up->port.irq+1, up);
- free_irq(up->err_irq, up);
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
- if (up->cts_pin >= 0)
- free_irq(gpio_to_irq(up->cts_pin), up);
-#endif
-}
-
-static const char *sport_type(struct uart_port *port)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
-
- pr_debug("%s enter\n", __func__);
- return up->port.type == PORT_BFIN_SPORT ? "BFIN-SPORT-UART" : NULL;
-}
-
-static void sport_release_port(struct uart_port *port)
-{
- pr_debug("%s enter\n", __func__);
-}
-
-static int sport_request_port(struct uart_port *port)
-{
- pr_debug("%s enter\n", __func__);
- return 0;
-}
-
-static void sport_config_port(struct uart_port *port, int flags)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
-
- pr_debug("%s enter\n", __func__);
- up->port.type = PORT_BFIN_SPORT;
-}
-
-static int sport_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- pr_debug("%s enter\n", __func__);
- return 0;
-}
-
-static void sport_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
- unsigned long flags;
- int i;
-
- pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
-
- switch (termios->c_cflag & CSIZE) {
- case CS8:
- up->csize = 8;
- break;
- case CS7:
- up->csize = 7;
- break;
- case CS6:
- up->csize = 6;
- break;
- case CS5:
- up->csize = 5;
- break;
- default:
- pr_warning("requested word length not supported\n");
- }
-
- if (termios->c_cflag & CSTOPB) {
- up->stopb = 1;
- }
- if (termios->c_cflag & PARENB) {
- pr_warning("PAREN bits is not supported yet\n");
- /* up->parib = 1; */
- }
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- port->read_status_mask = 0;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
-
- /* RX extract mask */
- up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8);
- /* TX masks, 8 bit data and 1 bit stop for example:
- * mask1 = b#0111111110
- * mask2 = b#1000000000
- */
- for (i = 0, up->txmask1 = 0; i < up->csize; i++)
- up->txmask1 |= (1<<i);
- up->txmask2 = (1<<i);
- if (up->stopb) {
- ++i;
- up->txmask2 |= (1<<i);
- }
- up->txmask1 <<= 1;
- up->txmask2 <<= 1;
- /* uart baud rate */
- port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16);
-
- /* Disable UART */
- SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
- SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
-
- sport_uart_setup(up, up->csize + up->stopb, port->uartclk);
-
- /* driver TX line high after config, one dummy data is
- * necessary to stop sport after shift one byte
- */
- SPORT_PUT_TX(up, 0xffff);
- SPORT_PUT_TX(up, 0xffff);
- SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
- SSYNC();
- while (!(SPORT_GET_STAT(up) & TXHRE))
- cpu_relax();
- SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
- SSYNC();
-
- /* Port speed changed, update the per-port timeout. */
- uart_update_timeout(port, termios->c_cflag, port->uartclk);
-
- /* Enable sport rx */
- SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) | RSPEN);
- SSYNC();
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-struct uart_ops sport_uart_ops = {
- .tx_empty = sport_tx_empty,
- .set_mctrl = sport_set_mctrl,
- .get_mctrl = sport_get_mctrl,
- .stop_tx = sport_stop_tx,
- .start_tx = sport_start_tx,
- .stop_rx = sport_stop_rx,
- .enable_ms = sport_enable_ms,
- .break_ctl = sport_break_ctl,
- .startup = sport_startup,
- .shutdown = sport_shutdown,
- .set_termios = sport_set_termios,
- .type = sport_type,
- .release_port = sport_release_port,
- .request_port = sport_request_port,
- .config_port = sport_config_port,
- .verify_port = sport_verify_port,
-};
-
-#define BFIN_SPORT_UART_MAX_PORTS 4
-
-static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS];
-
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
-#define CLASS_BFIN_SPORT_CONSOLE "bfin-sport-console"
-
-static int __init
-sport_uart_console_setup(struct console *co, char *options)
-{
- struct sport_uart_port *up;
- int baud = 57600;
- int bits = 8;
- int parity = 'n';
-# ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
- int flow = 'r';
-# else
- int flow = 'n';
-# endif
-
- /* Check whether an invalid uart number has been specified */
- if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS)
- return -ENODEV;
-
- up = bfin_sport_uart_ports[co->index];
- if (!up)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static void sport_uart_console_putchar(struct uart_port *port, int ch)
-{
- struct sport_uart_port *up = (struct sport_uart_port *)port;
-
- while (SPORT_GET_STAT(up) & TXF)
- barrier();
-
- tx_one_byte(up, ch);
-}
-
-/*
- * Interrupts are disabled on entering
- */
-static void
-sport_uart_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct sport_uart_port *up = bfin_sport_uart_ports[co->index];
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- if (SPORT_GET_TCR1(up) & TSPEN)
- uart_console_write(&up->port, s, count, sport_uart_console_putchar);
- else {
- /* dummy data to start sport */
- while (SPORT_GET_STAT(up) & TXF)
- barrier();
- SPORT_PUT_TX(up, 0xffff);
- /* Enable transmit, then an interrupt will generated */
- SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
- SSYNC();
-
- uart_console_write(&up->port, s, count, sport_uart_console_putchar);
-
- /* Although the hold register is empty, last byte is still in shift
- * register and not sent out yet. So, put a dummy data into TX FIFO.
- * Then, sport tx stops when last byte is shift out and the dummy
- * data is moved into the shift register.
- */
- while (SPORT_GET_STAT(up) & TXF)
- barrier();
- SPORT_PUT_TX(up, 0xffff);
- while (!(SPORT_GET_STAT(up) & TXHRE))
- barrier();
-
- /* Stop sport tx transfer */
- SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
- SSYNC();
- }
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static struct uart_driver sport_uart_reg;
-
-static struct console sport_uart_console = {
- .name = DEVICE_NAME,
- .write = sport_uart_console_write,
- .device = uart_console_device,
- .setup = sport_uart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sport_uart_reg,
-};
-
-#define SPORT_UART_CONSOLE (&sport_uart_console)
-#else
-#define SPORT_UART_CONSOLE NULL
-#endif /* CONFIG_SERIAL_BFIN_SPORT_CONSOLE */
-
-
-static struct uart_driver sport_uart_reg = {
- .owner = THIS_MODULE,
- .driver_name = DRV_NAME,
- .dev_name = DEVICE_NAME,
- .major = 204,
- .minor = 84,
- .nr = BFIN_SPORT_UART_MAX_PORTS,
- .cons = SPORT_UART_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int sport_uart_suspend(struct device *dev)
-{
- struct sport_uart_port *sport = dev_get_drvdata(dev);
-
- dev_dbg(dev, "%s enter\n", __func__);
- if (sport)
- uart_suspend_port(&sport_uart_reg, &sport->port);
-
- return 0;
-}
-
-static int sport_uart_resume(struct device *dev)
-{
- struct sport_uart_port *sport = dev_get_drvdata(dev);
-
- dev_dbg(dev, "%s enter\n", __func__);
- if (sport)
- uart_resume_port(&sport_uart_reg, &sport->port);
-
- return 0;
-}
-
-static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
- .suspend = sport_uart_suspend,
- .resume = sport_uart_resume,
-};
-#endif
-
-static int __devinit sport_uart_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct sport_uart_port *sport;
- int ret = 0;
-
- dev_dbg(&pdev->dev, "%s enter\n", __func__);
-
- if (pdev->id < 0 || pdev->id >= BFIN_SPORT_UART_MAX_PORTS) {
- dev_err(&pdev->dev, "Wrong sport uart platform device id.\n");
- return -ENOENT;
- }
-
- if (bfin_sport_uart_ports[pdev->id] == NULL) {
- bfin_sport_uart_ports[pdev->id] =
- kzalloc(sizeof(struct sport_uart_port), GFP_KERNEL);
- sport = bfin_sport_uart_ports[pdev->id];
- if (!sport) {
- dev_err(&pdev->dev,
- "Fail to malloc sport_uart_port\n");
- return -ENOMEM;
- }
-
- ret = peripheral_request_list(
- (unsigned short *)pdev->dev.platform_data, DRV_NAME);
- if (ret) {
- dev_err(&pdev->dev,
- "Fail to request SPORT peripherals\n");
- goto out_error_free_mem;
- }
-
- spin_lock_init(&sport->port.lock);
- sport->port.fifosize = SPORT_TX_FIFO_SIZE,
- sport->port.ops = &sport_uart_ops;
- sport->port.line = pdev->id;
- sport->port.iotype = UPIO_MEM;
- sport->port.flags = UPF_BOOT_AUTOCONF;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
- ret = -ENOENT;
- goto out_error_free_peripherals;
- }
-
- sport->port.membase = ioremap(res->start, resource_size(res));
- if (!sport->port.membase) {
- dev_err(&pdev->dev, "Cannot map sport IO\n");
- ret = -ENXIO;
- goto out_error_free_peripherals;
- }
- sport->port.mapbase = res->start;
-
- sport->port.irq = platform_get_irq(pdev, 0);
- if (sport->port.irq < 0) {
- dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n");
- ret = -ENOENT;
- goto out_error_unmap;
- }
-
- sport->err_irq = platform_get_irq(pdev, 1);
- if (sport->err_irq < 0) {
- dev_err(&pdev->dev, "No sport status IRQ specified\n");
- ret = -ENOENT;
- goto out_error_unmap;
- }
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (res == NULL)
- sport->cts_pin = -1;
- else
- sport->cts_pin = res->start;
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 1);
- if (res == NULL)
- sport->rts_pin = -1;
- else
- sport->rts_pin = res->start;
-
- if (sport->rts_pin >= 0)
- gpio_request(sport->rts_pin, DRV_NAME);
-#endif
- }
-
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
- if (!is_early_platform_device(pdev)) {
-#endif
- sport = bfin_sport_uart_ports[pdev->id];
- sport->port.dev = &pdev->dev;
- dev_set_drvdata(&pdev->dev, sport);
- ret = uart_add_one_port(&sport_uart_reg, &sport->port);
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
- }
-#endif
- if (!ret)
- return 0;
-
- if (sport) {
-out_error_unmap:
- iounmap(sport->port.membase);
-out_error_free_peripherals:
- peripheral_free_list(
- (unsigned short *)pdev->dev.platform_data);
-out_error_free_mem:
- kfree(sport);
- bfin_sport_uart_ports[pdev->id] = NULL;
- }
-
- return ret;
-}
-
-static int __devexit sport_uart_remove(struct platform_device *pdev)
-{
- struct sport_uart_port *sport = platform_get_drvdata(pdev);
-
- dev_dbg(&pdev->dev, "%s enter\n", __func__);
- dev_set_drvdata(&pdev->dev, NULL);
-
- if (sport) {
- uart_remove_one_port(&sport_uart_reg, &sport->port);
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
- if (sport->rts_pin >= 0)
- gpio_free(sport->rts_pin);
-#endif
- iounmap(sport->port.membase);
- peripheral_free_list(
- (unsigned short *)pdev->dev.platform_data);
- kfree(sport);
- bfin_sport_uart_ports[pdev->id] = NULL;
- }
-
- return 0;
-}
-
-static struct platform_driver sport_uart_driver = {
- .probe = sport_uart_probe,
- .remove = __devexit_p(sport_uart_remove),
- .driver = {
- .name = DRV_NAME,
-#ifdef CONFIG_PM
- .pm = &bfin_sport_uart_dev_pm_ops,
-#endif
- },
-};
-
-#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
-static __initdata struct early_platform_driver early_sport_uart_driver = {
- .class_str = CLASS_BFIN_SPORT_CONSOLE,
- .pdrv = &sport_uart_driver,
- .requested_id = EARLY_PLATFORM_ID_UNSET,
-};
-
-static int __init sport_uart_rs_console_init(void)
-{
- early_platform_driver_register(&early_sport_uart_driver, DRV_NAME);
-
- early_platform_driver_probe(CLASS_BFIN_SPORT_CONSOLE,
- BFIN_SPORT_UART_MAX_PORTS, 0);
-
- register_console(&sport_uart_console);
-
- return 0;
-}
-console_initcall(sport_uart_rs_console_init);
-#endif
-
-static int __init sport_uart_init(void)
-{
- int ret;
-
- pr_info("Blackfin uart over sport driver\n");
-
- ret = uart_register_driver(&sport_uart_reg);
- if (ret) {
- pr_err("failed to register %s:%d\n",
- sport_uart_reg.driver_name, ret);
- return ret;
- }
-
- ret = platform_driver_register(&sport_uart_driver);
- if (ret) {
- pr_err("failed to register sport uart driver:%d\n", ret);
- uart_unregister_driver(&sport_uart_reg);
- }
-
- return ret;
-}
-module_init(sport_uart_init);
-
-static void __exit sport_uart_exit(void)
-{
- platform_driver_unregister(&sport_uart_driver);
- uart_unregister_driver(&sport_uart_reg);
-}
-module_exit(sport_uart_exit);
-
-MODULE_AUTHOR("Sonic Zhang, Roy Huang");
-MODULE_DESCRIPTION("Blackfin serial over SPORT driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/bfin_sport_uart.h b/drivers/serial/bfin_sport_uart.h
deleted file mode 100644
index 6d06ce1d5675..000000000000
--- a/drivers/serial/bfin_sport_uart.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Blackfin On-Chip Sport Emulated UART Driver
- *
- * Copyright 2006-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-/*
- * This driver and the hardware supported are in term of EE-191 of ADI.
- * http://www.analog.com/static/imported-files/application_notes/EE191.pdf
- * This application note describe how to implement a UART on a Sharc DSP,
- * but this driver is implemented on Blackfin Processor.
- * Transmit Frame Sync is not used by this driver to transfer data out.
- */
-
-#ifndef _BFIN_SPORT_UART_H
-#define _BFIN_SPORT_UART_H
-
-#define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */
-#define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */
-#define OFFSET_TCLKDIV 0x08 /* Transmit Serial Clock Divider Register */
-#define OFFSET_TFSDIV 0x0C /* Transmit Frame Sync Divider Register */
-#define OFFSET_TX 0x10 /* Transmit Data Register */
-#define OFFSET_RX 0x18 /* Receive Data Register */
-#define OFFSET_RCR1 0x20 /* Receive Configuration 1 Register */
-#define OFFSET_RCR2 0x24 /* Receive Configuration 2 Register */
-#define OFFSET_RCLKDIV 0x28 /* Receive Serial Clock Divider Register */
-#define OFFSET_RFSDIV 0x2c /* Receive Frame Sync Divider Register */
-#define OFFSET_STAT 0x30 /* Status Register */
-
-#define SPORT_GET_TCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_TCR1))
-#define SPORT_GET_TCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_TCR2))
-#define SPORT_GET_TCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TCLKDIV))
-#define SPORT_GET_TFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TFSDIV))
-#define SPORT_GET_TX(sport) bfin_read16(((sport)->port.membase + OFFSET_TX))
-#define SPORT_GET_RX(sport) bfin_read16(((sport)->port.membase + OFFSET_RX))
-/*
- * If another interrupt fires while doing a 32-bit read from RX FIFO,
- * a fake RX underflow error will be generated. So disable interrupts
- * to prevent interruption while reading the FIFO.
- */
-#define SPORT_GET_RX32(sport) \
-({ \
- unsigned int __ret; \
- if (ANOMALY_05000473) \
- local_irq_disable(); \
- __ret = bfin_read32((sport)->port.membase + OFFSET_RX); \
- if (ANOMALY_05000473) \
- local_irq_enable(); \
- __ret; \
-})
-#define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1))
-#define SPORT_GET_RCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR2))
-#define SPORT_GET_RCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RCLKDIV))
-#define SPORT_GET_RFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RFSDIV))
-#define SPORT_GET_STAT(sport) bfin_read16(((sport)->port.membase + OFFSET_STAT))
-
-#define SPORT_PUT_TCR1(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCR1), v)
-#define SPORT_PUT_TCR2(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCR2), v)
-#define SPORT_PUT_TCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCLKDIV), v)
-#define SPORT_PUT_TFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TFSDIV), v)
-#define SPORT_PUT_TX(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TX), v)
-#define SPORT_PUT_RX(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RX), v)
-#define SPORT_PUT_RCR1(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCR1), v)
-#define SPORT_PUT_RCR2(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCR2), v)
-#define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v)
-#define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v)
-#define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v)
-
-#define SPORT_TX_FIFO_SIZE 8
-
-#define SPORT_UART_GET_CTS(x) gpio_get_value(x->cts_pin)
-#define SPORT_UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
-#define SPORT_UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
-
-#if defined(CONFIG_SERIAL_BFIN_SPORT0_UART_CTSRTS) \
- || defined(CONFIG_SERIAL_BFIN_SPORT1_UART_CTSRTS) \
- || defined(CONFIG_SERIAL_BFIN_SPORT2_UART_CTSRTS) \
- || defined(CONFIG_SERIAL_BFIN_SPORT3_UART_CTSRTS)
-# define CONFIG_SERIAL_BFIN_SPORT_CTSRTS
-#endif
-
-#endif /* _BFIN_SPORT_UART_H */
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
deleted file mode 100644
index b6acd19b458e..000000000000
--- a/drivers/serial/clps711x.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * linux/drivers/char/clps711x.c
- *
- * Driver for CLPS711x serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/spinlock.h>
-#include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/hardware/clps7111.h>
-
-#define UART_NR 2
-
-#define SERIAL_CLPS711X_MAJOR 204
-#define SERIAL_CLPS711X_MINOR 40
-#define SERIAL_CLPS711X_NR UART_NR
-
-/*
- * We use the relevant SYSCON register as a base address for these ports.
- */
-#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
-#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
-#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
-#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
-
-#define TX_IRQ(port) ((port)->irq)
-#define RX_IRQ(port) ((port)->irq + 1)
-
-#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
-
-#define tx_enabled(port) ((port)->unused[0])
-
-static void clps711xuart_stop_tx(struct uart_port *port)
-{
- if (tx_enabled(port)) {
- disable_irq(TX_IRQ(port));
- tx_enabled(port) = 0;
- }
-}
-
-static void clps711xuart_start_tx(struct uart_port *port)
-{
- if (!tx_enabled(port)) {
- enable_irq(TX_IRQ(port));
- tx_enabled(port) = 1;
- }
-}
-
-static void clps711xuart_stop_rx(struct uart_port *port)
-{
- disable_irq(RX_IRQ(port));
-}
-
-static void clps711xuart_enable_ms(struct uart_port *port)
-{
-}
-
-static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- struct tty_struct *tty = port->state->port.tty;
- unsigned int status, ch, flg;
-
- status = clps_readl(SYSFLG(port));
- while (!(status & SYSFLG_URXFE)) {
- ch = clps_readl(UARTDR(port));
-
- port->icount.rx++;
-
- flg = TTY_NORMAL;
-
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- if (unlikely(ch & UART_ANY_ERR)) {
- if (ch & UARTDR_PARERR)
- port->icount.parity++;
- else if (ch & UARTDR_FRMERR)
- port->icount.frame++;
- if (ch & UARTDR_OVERR)
- port->icount.overrun++;
-
- ch &= port->read_status_mask;
-
- if (ch & UARTDR_PARERR)
- flg = TTY_PARITY;
- else if (ch & UARTDR_FRMERR)
- flg = TTY_FRAME;
-
-#ifdef SUPPORT_SYSRQ
- port->sysrq = 0;
-#endif
- }
-
- if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
-
- /*
- * CHECK: does overrun affect the current character?
- * ASSUMPTION: it does not.
- */
- uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
-
- ignore_char:
- status = clps_readl(SYSFLG(port));
- }
- tty_flip_buffer_push(tty);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- struct circ_buf *xmit = &port->state->xmit;
- int count;
-
- if (port->x_char) {
- clps_writel(port->x_char, UARTDR(port));
- port->icount.tx++;
- port->x_char = 0;
- return IRQ_HANDLED;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- clps711xuart_stop_tx(port);
- return IRQ_HANDLED;
- }
-
- count = port->fifosize >> 1;
- do {
- clps_writel(xmit->buf[xmit->tail], UARTDR(port));
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- clps711xuart_stop_tx(port);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int clps711xuart_tx_empty(struct uart_port *port)
-{
- unsigned int status = clps_readl(SYSFLG(port));
- return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
-}
-
-static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
-{
- unsigned int port_addr;
- unsigned int result = 0;
- unsigned int status;
-
- port_addr = SYSFLG(port);
- if (port_addr == SYSFLG1) {
- status = clps_readl(SYSFLG1);
- if (status & SYSFLG1_DCD)
- result |= TIOCM_CAR;
- if (status & SYSFLG1_DSR)
- result |= TIOCM_DSR;
- if (status & SYSFLG1_CTS)
- result |= TIOCM_CTS;
- }
-
- return result;
-}
-
-static void
-clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned long flags;
- unsigned int ubrlcr;
-
- spin_lock_irqsave(&port->lock, flags);
- ubrlcr = clps_readl(UBRLCR(port));
- if (break_state == -1)
- ubrlcr |= UBRLCR_BREAK;
- else
- ubrlcr &= ~UBRLCR_BREAK;
- clps_writel(ubrlcr, UBRLCR(port));
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int clps711xuart_startup(struct uart_port *port)
-{
- unsigned int syscon;
- int retval;
-
- tx_enabled(port) = 1;
-
- /*
- * Allocate the IRQs
- */
- retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
- "clps711xuart_tx", port);
- if (retval)
- return retval;
-
- retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
- "clps711xuart_rx", port);
- if (retval) {
- free_irq(TX_IRQ(port), port);
- return retval;
- }
-
- /*
- * enable the port
- */
- syscon = clps_readl(SYSCON(port));
- syscon |= SYSCON_UARTEN;
- clps_writel(syscon, SYSCON(port));
-
- return 0;
-}
-
-static void clps711xuart_shutdown(struct uart_port *port)
-{
- unsigned int ubrlcr, syscon;
-
- /*
- * Free the interrupt
- */
- free_irq(TX_IRQ(port), port); /* TX interrupt */
- free_irq(RX_IRQ(port), port); /* RX interrupt */
-
- /*
- * disable the port
- */
- syscon = clps_readl(SYSCON(port));
- syscon &= ~SYSCON_UARTEN;
- clps_writel(syscon, SYSCON(port));
-
- /*
- * disable break condition and fifos
- */
- ubrlcr = clps_readl(UBRLCR(port));
- ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
- clps_writel(ubrlcr, UBRLCR(port));
-}
-
-static void
-clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int ubrlcr, baud, quot;
- unsigned long flags;
-
- /*
- * We don't implement CREAD.
- */
- termios->c_cflag |= CREAD;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- ubrlcr = UBRLCR_WRDLEN5;
- break;
- case CS6:
- ubrlcr = UBRLCR_WRDLEN6;
- break;
- case CS7:
- ubrlcr = UBRLCR_WRDLEN7;
- break;
- default: // CS8
- ubrlcr = UBRLCR_WRDLEN8;
- break;
- }
- if (termios->c_cflag & CSTOPB)
- ubrlcr |= UBRLCR_XSTOP;
- if (termios->c_cflag & PARENB) {
- ubrlcr |= UBRLCR_PRTEN;
- if (!(termios->c_cflag & PARODD))
- ubrlcr |= UBRLCR_EVENPRT;
- }
- if (port->fifosize > 1)
- ubrlcr |= UBRLCR_FIFOEN;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- port->read_status_mask = UARTDR_OVERR;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
- if (termios->c_iflag & IGNBRK) {
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns to (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UARTDR_OVERR;
- }
-
- quot -= 1;
-
- clps_writel(ubrlcr | quot, UBRLCR(port));
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *clps711xuart_type(struct uart_port *port)
-{
- return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void clps711xuart_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE)
- port->type = PORT_CLPS711X;
-}
-
-static void clps711xuart_release_port(struct uart_port *port)
-{
-}
-
-static int clps711xuart_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static struct uart_ops clps711x_pops = {
- .tx_empty = clps711xuart_tx_empty,
- .set_mctrl = clps711xuart_set_mctrl_null,
- .get_mctrl = clps711xuart_get_mctrl,
- .stop_tx = clps711xuart_stop_tx,
- .start_tx = clps711xuart_start_tx,
- .stop_rx = clps711xuart_stop_rx,
- .enable_ms = clps711xuart_enable_ms,
- .break_ctl = clps711xuart_break_ctl,
- .startup = clps711xuart_startup,
- .shutdown = clps711xuart_shutdown,
- .set_termios = clps711xuart_set_termios,
- .type = clps711xuart_type,
- .config_port = clps711xuart_config_port,
- .release_port = clps711xuart_release_port,
- .request_port = clps711xuart_request_port,
-};
-
-static struct uart_port clps711x_ports[UART_NR] = {
- {
- .iobase = SYSCON1,
- .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
- .uartclk = 3686400,
- .fifosize = 16,
- .ops = &clps711x_pops,
- .line = 0,
- .flags = UPF_BOOT_AUTOCONF,
- },
- {
- .iobase = SYSCON2,
- .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
- .uartclk = 3686400,
- .fifosize = 16,
- .ops = &clps711x_pops,
- .line = 1,
- .flags = UPF_BOOT_AUTOCONF,
- }
-};
-
-#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-static void clps711xuart_console_putchar(struct uart_port *port, int ch)
-{
- while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
- barrier();
- clps_writel(ch, UARTDR(port));
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- *
- * Note that this is called with interrupts already disabled
- */
-static void
-clps711xuart_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_port *port = clps711x_ports + co->index;
- unsigned int status, syscon;
-
- /*
- * Ensure that the port is enabled.
- */
- syscon = clps_readl(SYSCON(port));
- clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
-
- uart_console_write(port, s, count, clps711xuart_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the uart state.
- */
- do {
- status = clps_readl(SYSFLG(port));
- } while (status & SYSFLG_UBUSY);
-
- clps_writel(syscon, SYSCON(port));
-}
-
-static void __init
-clps711xuart_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
- unsigned int ubrlcr, quot;
-
- ubrlcr = clps_readl(UBRLCR(port));
-
- *parity = 'n';
- if (ubrlcr & UBRLCR_PRTEN) {
- if (ubrlcr & UBRLCR_EVENPRT)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
- *bits = 7;
- else
- *bits = 8;
-
- quot = ubrlcr & UBRLCR_BAUD_MASK;
- *baud = port->uartclk / (16 * (quot + 1));
- }
-}
-
-static int __init clps711xuart_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- port = uart_get_console(clps711x_ports, UART_NR, co);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- clps711xuart_console_get_options(port, &baud, &parity, &bits);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver clps711x_reg;
-static struct console clps711x_console = {
- .name = "ttyCL",
- .write = clps711xuart_console_write,
- .device = uart_console_device,
- .setup = clps711xuart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &clps711x_reg,
-};
-
-static int __init clps711xuart_console_init(void)
-{
- register_console(&clps711x_console);
- return 0;
-}
-console_initcall(clps711xuart_console_init);
-
-#define CLPS711X_CONSOLE &clps711x_console
-#else
-#define CLPS711X_CONSOLE NULL
-#endif
-
-static struct uart_driver clps711x_reg = {
- .driver_name = "ttyCL",
- .dev_name = "ttyCL",
- .major = SERIAL_CLPS711X_MAJOR,
- .minor = SERIAL_CLPS711X_MINOR,
- .nr = UART_NR,
-
- .cons = CLPS711X_CONSOLE,
-};
-
-static int __init clps711xuart_init(void)
-{
- int ret, i;
-
- printk(KERN_INFO "Serial: CLPS711x driver\n");
-
- ret = uart_register_driver(&clps711x_reg);
- if (ret)
- return ret;
-
- for (i = 0; i < UART_NR; i++)
- uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
-
- return 0;
-}
-
-static void __exit clps711xuart_exit(void)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++)
- uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
-
- uart_unregister_driver(&clps711x_reg);
-}
-
-module_init(clps711xuart_init);
-module_exit(clps711xuart_exit);
-
-MODULE_AUTHOR("Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("CLPS-711x generic serial driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);
diff --git a/drivers/serial/cpm_uart/Makefile b/drivers/serial/cpm_uart/Makefile
deleted file mode 100644
index e072724ea754..000000000000
--- a/drivers/serial/cpm_uart/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the Motorola 8xx FEC ethernet controller
-#
-
-obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o
-
-# Select the correct platform objects.
-cpm_uart-objs-$(CONFIG_CPM2) += cpm_uart_cpm2.o
-cpm_uart-objs-$(CONFIG_8xx) += cpm_uart_cpm1.o
-
-cpm_uart-objs := cpm_uart_core.o $(cpm_uart-objs-y)
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
deleted file mode 100644
index b754dcf0fda5..000000000000
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * linux/drivers/serial/cpm_uart.h
- *
- * Driver for CPM (SCC/SMC) serial ports
- *
- * Copyright (C) 2004 Freescale Semiconductor, Inc.
- *
- * 2006 (c) MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- */
-#ifndef CPM_UART_H
-#define CPM_UART_H
-
-#include <linux/platform_device.h>
-#include <linux/fs_uart_pd.h>
-
-#if defined(CONFIG_CPM2)
-#include "cpm_uart_cpm2.h"
-#elif defined(CONFIG_8xx)
-#include "cpm_uart_cpm1.h"
-#endif
-
-#define SERIAL_CPM_MAJOR 204
-#define SERIAL_CPM_MINOR 46
-
-#define IS_SMC(pinfo) (pinfo->flags & FLAG_SMC)
-#define IS_DISCARDING(pinfo) (pinfo->flags & FLAG_DISCARDING)
-#define FLAG_DISCARDING 0x00000004 /* when set, don't discard */
-#define FLAG_SMC 0x00000002
-#define FLAG_CONSOLE 0x00000001
-
-#define UART_SMC1 fsid_smc1_uart
-#define UART_SMC2 fsid_smc2_uart
-#define UART_SCC1 fsid_scc1_uart
-#define UART_SCC2 fsid_scc2_uart
-#define UART_SCC3 fsid_scc3_uart
-#define UART_SCC4 fsid_scc4_uart
-
-#define UART_NR fs_uart_nr
-
-#define RX_NUM_FIFO 4
-#define RX_BUF_SIZE 32
-#define TX_NUM_FIFO 4
-#define TX_BUF_SIZE 32
-
-#define SCC_WAIT_CLOSING 100
-
-#define GPIO_CTS 0
-#define GPIO_RTS 1
-#define GPIO_DCD 2
-#define GPIO_DSR 3
-#define GPIO_DTR 4
-#define GPIO_RI 5
-
-#define NUM_GPIOS (GPIO_RI+1)
-
-struct uart_cpm_port {
- struct uart_port port;
- u16 rx_nrfifos;
- u16 rx_fifosize;
- u16 tx_nrfifos;
- u16 tx_fifosize;
- smc_t __iomem *smcp;
- smc_uart_t __iomem *smcup;
- scc_t __iomem *sccp;
- scc_uart_t __iomem *sccup;
- cbd_t __iomem *rx_bd_base;
- cbd_t __iomem *rx_cur;
- cbd_t __iomem *tx_bd_base;
- cbd_t __iomem *tx_cur;
- unsigned char *tx_buf;
- unsigned char *rx_buf;
- u32 flags;
- struct clk *clk;
- u8 brg;
- uint dp_addr;
- void *mem_addr;
- dma_addr_t dma_addr;
- u32 mem_size;
- /* wait on close if needed */
- int wait_closing;
- /* value to combine with opcode to form cpm command */
- u32 command;
- int gpios[NUM_GPIOS];
-};
-
-extern int cpm_uart_nr;
-extern struct uart_cpm_port cpm_uart_ports[UART_NR];
-
-/* these are located in their respective files */
-void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd);
-void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
- struct device_node *np);
-void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram);
-int cpm_uart_init_portdesc(void);
-int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
-void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
-
-void smc1_lineif(struct uart_cpm_port *pinfo);
-void smc2_lineif(struct uart_cpm_port *pinfo);
-void scc1_lineif(struct uart_cpm_port *pinfo);
-void scc2_lineif(struct uart_cpm_port *pinfo);
-void scc3_lineif(struct uart_cpm_port *pinfo);
-void scc4_lineif(struct uart_cpm_port *pinfo);
-
-/*
- virtual to phys transtalion
-*/
-static inline unsigned long cpu2cpm_addr(void *addr,
- struct uart_cpm_port *pinfo)
-{
- int offset;
- u32 val = (u32)addr;
- u32 mem = (u32)pinfo->mem_addr;
- /* sane check */
- if (likely(val >= mem && val < mem + pinfo->mem_size)) {
- offset = val - mem;
- return pinfo->dma_addr + offset;
- }
- /* something nasty happened */
- BUG();
- return 0;
-}
-
-static inline void *cpm2cpu_addr(unsigned long addr,
- struct uart_cpm_port *pinfo)
-{
- int offset;
- u32 val = addr;
- u32 dma = (u32)pinfo->dma_addr;
- /* sane check */
- if (likely(val >= dma && val < dma + pinfo->mem_size)) {
- offset = val - dma;
- return pinfo->mem_addr + offset;
- }
- /* something nasty happened */
- BUG();
- return NULL;
-}
-
-
-#endif /* CPM_UART_H */
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
deleted file mode 100644
index 8692ff98fc07..000000000000
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ /dev/null
@@ -1,1443 +0,0 @@
-/*
- * 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
- * Based on ppc8xx.c by Thomas Gleixner
- * Based on drivers/serial/amba.c by Russell King
- *
- * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
- * Pantelis Antoniou (panto@intracom.gr) (CPM1)
- *
- * Copyright (C) 2004, 2007 Freescale Semiconductor, Inc.
- * (C) 2004 Intracom, S.A.
- * (C) 2005-2006 MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-#include <linux/bootmem.h>
-#include <linux/dma-mapping.h>
-#include <linux/fs_uart_pd.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/clk.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-#include <asm/fs_pd.h>
-#include <asm/udbg.h>
-
-#if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-#include <linux/kernel.h>
-
-#include "cpm_uart.h"
-
-
-/**************************************************************/
-
-static int cpm_uart_tx_pump(struct uart_port *port);
-static void cpm_uart_init_smc(struct uart_cpm_port *pinfo);
-static void cpm_uart_init_scc(struct uart_cpm_port *pinfo);
-static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
-
-/**************************************************************/
-
-#define HW_BUF_SPD_THRESHOLD 9600
-
-/*
- * Check, if transmit buffers are processed
-*/
-static unsigned int cpm_uart_tx_empty(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- cbd_t __iomem *bdp = pinfo->tx_bd_base;
- int ret = 0;
-
- while (1) {
- if (in_be16(&bdp->cbd_sc) & BD_SC_READY)
- break;
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) {
- ret = TIOCSER_TEMT;
- break;
- }
- bdp++;
- }
-
- pr_debug("CPM uart[%d]:tx_empty: %d\n", port->line, ret);
-
- return ret;
-}
-
-static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-
- if (pinfo->gpios[GPIO_RTS] >= 0)
- gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS));
-
- if (pinfo->gpios[GPIO_DTR] >= 0)
- gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));
-}
-
-static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-
- if (pinfo->gpios[GPIO_CTS] >= 0) {
- if (gpio_get_value(pinfo->gpios[GPIO_CTS]))
- mctrl &= ~TIOCM_CTS;
- }
-
- if (pinfo->gpios[GPIO_DSR] >= 0) {
- if (gpio_get_value(pinfo->gpios[GPIO_DSR]))
- mctrl &= ~TIOCM_DSR;
- }
-
- if (pinfo->gpios[GPIO_DCD] >= 0) {
- if (gpio_get_value(pinfo->gpios[GPIO_DCD]))
- mctrl &= ~TIOCM_CAR;
- }
-
- if (pinfo->gpios[GPIO_RI] >= 0) {
- if (!gpio_get_value(pinfo->gpios[GPIO_RI]))
- mctrl |= TIOCM_RNG;
- }
-
- return mctrl;
-}
-
-/*
- * Stop transmitter
- */
-static void cpm_uart_stop_tx(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- smc_t __iomem *smcp = pinfo->smcp;
- scc_t __iomem *sccp = pinfo->sccp;
-
- pr_debug("CPM uart[%d]:stop tx\n", port->line);
-
- if (IS_SMC(pinfo))
- clrbits8(&smcp->smc_smcm, SMCM_TX);
- else
- clrbits16(&sccp->scc_sccm, UART_SCCM_TX);
-}
-
-/*
- * Start transmitter
- */
-static void cpm_uart_start_tx(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- smc_t __iomem *smcp = pinfo->smcp;
- scc_t __iomem *sccp = pinfo->sccp;
-
- pr_debug("CPM uart[%d]:start tx\n", port->line);
-
- if (IS_SMC(pinfo)) {
- if (in_8(&smcp->smc_smcm) & SMCM_TX)
- return;
- } else {
- if (in_be16(&sccp->scc_sccm) & UART_SCCM_TX)
- return;
- }
-
- if (cpm_uart_tx_pump(port) != 0) {
- if (IS_SMC(pinfo)) {
- setbits8(&smcp->smc_smcm, SMCM_TX);
- } else {
- setbits16(&sccp->scc_sccm, UART_SCCM_TX);
- }
- }
-}
-
-/*
- * Stop receiver
- */
-static void cpm_uart_stop_rx(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- smc_t __iomem *smcp = pinfo->smcp;
- scc_t __iomem *sccp = pinfo->sccp;
-
- pr_debug("CPM uart[%d]:stop rx\n", port->line);
-
- if (IS_SMC(pinfo))
- clrbits8(&smcp->smc_smcm, SMCM_RX);
- else
- clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
-}
-
-/*
- * Enable Modem status interrupts
- */
-static void cpm_uart_enable_ms(struct uart_port *port)
-{
- pr_debug("CPM uart[%d]:enable ms\n", port->line);
-}
-
-/*
- * Generate a break.
- */
-static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-
- pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line,
- break_state);
-
- if (break_state)
- cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
- else
- cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
-}
-
-/*
- * Transmit characters, refill buffer descriptor, if possible
- */
-static void cpm_uart_int_tx(struct uart_port *port)
-{
- pr_debug("CPM uart[%d]:TX INT\n", port->line);
-
- cpm_uart_tx_pump(port);
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-static int serial_polled;
-#endif
-
-/*
- * Receive characters
- */
-static void cpm_uart_int_rx(struct uart_port *port)
-{
- int i;
- unsigned char ch;
- u8 *cp;
- struct tty_struct *tty = port->state->port.tty;
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- cbd_t __iomem *bdp;
- u16 status;
- unsigned int flg;
-
- pr_debug("CPM uart[%d]:RX INT\n", port->line);
-
- /* Just loop through the closed BDs and copy the characters into
- * the buffer.
- */
- bdp = pinfo->rx_cur;
- for (;;) {
-#ifdef CONFIG_CONSOLE_POLL
- if (unlikely(serial_polled)) {
- serial_polled = 0;
- return;
- }
-#endif
- /* get status */
- status = in_be16(&bdp->cbd_sc);
- /* If this one is empty, return happy */
- if (status & BD_SC_EMPTY)
- break;
-
- /* get number of characters, and check spce in flip-buffer */
- i = in_be16(&bdp->cbd_datlen);
-
- /* If we have not enough room in tty flip buffer, then we try
- * later, which will be the next rx-interrupt or a timeout
- */
- if(tty_buffer_request_room(tty, i) < i) {
- printk(KERN_WARNING "No room in flip buffer\n");
- return;
- }
-
- /* get pointer */
- cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-
- /* loop through the buffer */
- while (i-- > 0) {
- ch = *cp++;
- port->icount.rx++;
- flg = TTY_NORMAL;
-
- if (status &
- (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
- goto handle_error;
- if (uart_handle_sysrq_char(port, ch))
- continue;
-#ifdef CONFIG_CONSOLE_POLL
- if (unlikely(serial_polled)) {
- serial_polled = 0;
- return;
- }
-#endif
- error_return:
- tty_insert_flip_char(tty, ch, flg);
-
- } /* End while (i--) */
-
- /* This BD is ready to be used again. Clear status. get next */
- clrbits16(&bdp->cbd_sc, BD_SC_BR | BD_SC_FR | BD_SC_PR |
- BD_SC_OV | BD_SC_ID);
- setbits16(&bdp->cbd_sc, BD_SC_EMPTY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = pinfo->rx_bd_base;
- else
- bdp++;
-
- } /* End for (;;) */
-
- /* Write back buffer pointer */
- pinfo->rx_cur = bdp;
-
- /* activate BH processing */
- tty_flip_buffer_push(tty);
-
- return;
-
- /* Error processing */
-
- handle_error:
- /* Statistics */
- if (status & BD_SC_BR)
- port->icount.brk++;
- if (status & BD_SC_PR)
- port->icount.parity++;
- if (status & BD_SC_FR)
- port->icount.frame++;
- if (status & BD_SC_OV)
- port->icount.overrun++;
-
- /* Mask out ignored conditions */
- status &= port->read_status_mask;
-
- /* Handle the remaining ones */
- if (status & BD_SC_BR)
- flg = TTY_BREAK;
- else if (status & BD_SC_PR)
- flg = TTY_PARITY;
- else if (status & BD_SC_FR)
- flg = TTY_FRAME;
-
- /* overrun does not affect the current character ! */
- if (status & BD_SC_OV) {
- ch = 0;
- flg = TTY_OVERRUN;
- /* We skip this buffer */
- /* CHECK: Is really nothing senseful there */
- /* ASSUMPTION: it contains nothing valid */
- i = 0;
- }
-#ifdef SUPPORT_SYSRQ
- port->sysrq = 0;
-#endif
- goto error_return;
-}
-
-/*
- * Asynchron mode interrupt handler
- */
-static irqreturn_t cpm_uart_int(int irq, void *data)
-{
- u8 events;
- struct uart_port *port = data;
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- smc_t __iomem *smcp = pinfo->smcp;
- scc_t __iomem *sccp = pinfo->sccp;
-
- pr_debug("CPM uart[%d]:IRQ\n", port->line);
-
- if (IS_SMC(pinfo)) {
- events = in_8(&smcp->smc_smce);
- out_8(&smcp->smc_smce, events);
- if (events & SMCM_BRKE)
- uart_handle_break(port);
- if (events & SMCM_RX)
- cpm_uart_int_rx(port);
- if (events & SMCM_TX)
- cpm_uart_int_tx(port);
- } else {
- events = in_be16(&sccp->scc_scce);
- out_be16(&sccp->scc_scce, events);
- if (events & UART_SCCM_BRKE)
- uart_handle_break(port);
- if (events & UART_SCCM_RX)
- cpm_uart_int_rx(port);
- if (events & UART_SCCM_TX)
- cpm_uart_int_tx(port);
- }
- return (events) ? IRQ_HANDLED : IRQ_NONE;
-}
-
-static int cpm_uart_startup(struct uart_port *port)
-{
- int retval;
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-
- pr_debug("CPM uart[%d]:startup\n", port->line);
-
- /* If the port is not the console, make sure rx is disabled. */
- if (!(pinfo->flags & FLAG_CONSOLE)) {
- /* Disable UART rx */
- if (IS_SMC(pinfo)) {
- clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN);
- clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX);
- } else {
- clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR);
- clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
- }
- cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
- }
- /* Install interrupt handler. */
- retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port);
- if (retval)
- return retval;
-
- /* Startup rx-int */
- if (IS_SMC(pinfo)) {
- setbits8(&pinfo->smcp->smc_smcm, SMCM_RX);
- setbits16(&pinfo->smcp->smc_smcmr, (SMCMR_REN | SMCMR_TEN));
- } else {
- setbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
- setbits32(&pinfo->sccp->scc_gsmrl, (SCC_GSMRL_ENR | SCC_GSMRL_ENT));
- }
-
- return 0;
-}
-
-inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
-{
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(pinfo->wait_closing);
-}
-
-/*
- * Shutdown the uart
- */
-static void cpm_uart_shutdown(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-
- pr_debug("CPM uart[%d]:shutdown\n", port->line);
-
- /* free interrupt handler */
- free_irq(port->irq, port);
-
- /* If the port is not the console, disable Rx and Tx. */
- if (!(pinfo->flags & FLAG_CONSOLE)) {
- /* Wait for all the BDs marked sent */
- while(!cpm_uart_tx_empty(port)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(2);
- }
-
- if (pinfo->wait_closing)
- cpm_uart_wait_until_send(pinfo);
-
- /* Stop uarts */
- if (IS_SMC(pinfo)) {
- smc_t __iomem *smcp = pinfo->smcp;
- clrbits16(&smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
- clrbits8(&smcp->smc_smcm, SMCM_RX | SMCM_TX);
- } else {
- scc_t __iomem *sccp = pinfo->sccp;
- clrbits32(&sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
- clrbits16(&sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
- }
-
- /* Shut them really down and reinit buffer descriptors */
- if (IS_SMC(pinfo)) {
- out_be16(&pinfo->smcup->smc_brkcr, 0);
- cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
- } else {
- out_be16(&pinfo->sccup->scc_brkcr, 0);
- cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
- }
-
- cpm_uart_initbd(pinfo);
- }
-}
-
-static void cpm_uart_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- int baud;
- unsigned long flags;
- u16 cval, scval, prev_mode;
- int bits, sbits;
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- smc_t __iomem *smcp = pinfo->smcp;
- scc_t __iomem *sccp = pinfo->sccp;
-
- pr_debug("CPM uart[%d]:set_termios\n", port->line);
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
- if (baud <= HW_BUF_SPD_THRESHOLD ||
- (pinfo->port.state && pinfo->port.state->port.tty->low_latency))
- pinfo->rx_fifosize = 1;
- else
- pinfo->rx_fifosize = RX_BUF_SIZE;
-
- /* Character length programmed into the mode register is the
- * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
- * 1 or 2 stop bits, minus 1.
- * The value 'bits' counts this for us.
- */
- cval = 0;
- scval = 0;
-
- /* byte size */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- bits = 5;
- break;
- case CS6:
- bits = 6;
- break;
- case CS7:
- bits = 7;
- break;
- case CS8:
- bits = 8;
- break;
- /* Never happens, but GCC is too dumb to figure it out */
- default:
- bits = 8;
- break;
- }
- sbits = bits - 5;
-
- if (termios->c_cflag & CSTOPB) {
- cval |= SMCMR_SL; /* Two stops */
- scval |= SCU_PSMR_SL;
- bits++;
- }
-
- if (termios->c_cflag & PARENB) {
- cval |= SMCMR_PEN;
- scval |= SCU_PSMR_PEN;
- bits++;
- if (!(termios->c_cflag & PARODD)) {
- cval |= SMCMR_PM_EVEN;
- scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP);
- }
- }
-
- /*
- * Update the timeout
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /*
- * Set up parity check flag
- */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
- port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= BD_SC_FR | BD_SC_PR;
- if ((termios->c_iflag & BRKINT) || (termios->c_iflag & PARMRK))
- port->read_status_mask |= BD_SC_BR;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= BD_SC_BR;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= BD_SC_OV;
- }
- /*
- * !!! ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- port->read_status_mask &= ~BD_SC_EMPTY;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Start bit has not been added (so don't, because we would just
- * subtract it later), and we need to add one for the number of
- * stops bits (there is always at least one).
- */
- bits++;
- if (IS_SMC(pinfo)) {
- /*
- * MRBLR can be changed while an SMC/SCC is operating only
- * if it is done in a single bus cycle with one 16-bit move
- * (not two 8-bit bus cycles back-to-back). This occurs when
- * the cp shifts control to the next RxBD, so the change does
- * not take effect immediately. To guarantee the exact RxBD
- * on which the change occurs, change MRBLR only while the
- * SMC/SCC receiver is disabled.
- */
- out_be16(&pinfo->smcup->smc_mrblr, pinfo->rx_fifosize);
-
- /* Set the mode register. We want to keep a copy of the
- * enables, because we want to put them back if they were
- * present.
- */
- prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN);
- /* Output in *one* operation, so we don't interrupt RX/TX if they
- * were already enabled. */
- out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval |
- SMCMR_SM_UART | prev_mode);
- } else {
- out_be16(&pinfo->sccup->scc_genscc.scc_mrblr, pinfo->rx_fifosize);
- out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
- }
-
- if (pinfo->clk)
- clk_set_rate(pinfo->clk, baud);
- else
- cpm_set_brg(pinfo->brg - 1, baud);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *cpm_uart_type(struct uart_port *port)
-{
- pr_debug("CPM uart[%d]:uart_type\n", port->line);
-
- return port->type == PORT_CPM ? "CPM UART" : NULL;
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int cpm_uart_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- int ret = 0;
-
- pr_debug("CPM uart[%d]:verify_port\n", port->line);
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
- ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
- ret = -EINVAL;
- if (ser->baud_base < 9600)
- ret = -EINVAL;
- return ret;
-}
-
-/*
- * Transmit characters, refill buffer descriptor, if possible
- */
-static int cpm_uart_tx_pump(struct uart_port *port)
-{
- cbd_t __iomem *bdp;
- u8 *p;
- int count;
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- struct circ_buf *xmit = &port->state->xmit;
-
- /* Handle xon/xoff */
- if (port->x_char) {
- /* Pick next descriptor and fill from buffer */
- bdp = pinfo->tx_cur;
-
- p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-
- *p++ = port->x_char;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
- /* Get next BD. */
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = pinfo->tx_bd_base;
- else
- bdp++;
- pinfo->tx_cur = bdp;
-
- port->icount.tx++;
- port->x_char = 0;
- return 1;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- cpm_uart_stop_tx(port);
- return 0;
- }
-
- /* Pick next descriptor and fill from buffer */
- bdp = pinfo->tx_cur;
-
- while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
- xmit->tail != xmit->head) {
- count = 0;
- p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
- while (count < pinfo->tx_fifosize) {
- *p++ = xmit->buf[xmit->tail];
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- count++;
- if (xmit->head == xmit->tail)
- break;
- }
- out_be16(&bdp->cbd_datlen, count);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
- /* Get next BD. */
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = pinfo->tx_bd_base;
- else
- bdp++;
- }
- pinfo->tx_cur = bdp;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit)) {
- cpm_uart_stop_tx(port);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * init buffer descriptors
- */
-static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
-{
- int i;
- u8 *mem_addr;
- cbd_t __iomem *bdp;
-
- pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);
-
- /* Set the physical address of the host memory
- * buffers in the buffer descriptors, and the
- * virtual address for us to work with.
- */
- mem_addr = pinfo->mem_addr;
- bdp = pinfo->rx_cur = pinfo->rx_bd_base;
- for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
- out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
- out_be16(&bdp->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT);
- mem_addr += pinfo->rx_fifosize;
- }
-
- out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
- out_be16(&bdp->cbd_sc, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT);
-
- /* Set the physical address of the host memory
- * buffers in the buffer descriptors, and the
- * virtual address for us to work with.
- */
- mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
- bdp = pinfo->tx_cur = pinfo->tx_bd_base;
- for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
- out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
- out_be16(&bdp->cbd_sc, BD_SC_INTRPT);
- mem_addr += pinfo->tx_fifosize;
- }
-
- out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
- out_be16(&bdp->cbd_sc, BD_SC_WRAP | BD_SC_INTRPT);
-}
-
-static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
-{
- scc_t __iomem *scp;
- scc_uart_t __iomem *sup;
-
- pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line);
-
- scp = pinfo->sccp;
- sup = pinfo->sccup;
-
- /* Store address */
- out_be16(&pinfo->sccup->scc_genscc.scc_rbase,
- (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
- out_be16(&pinfo->sccup->scc_genscc.scc_tbase,
- (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
-
- cpm_set_scc_fcr(sup);
-
- out_be16(&sup->scc_genscc.scc_mrblr, pinfo->rx_fifosize);
- out_be16(&sup->scc_maxidl, pinfo->rx_fifosize);
- out_be16(&sup->scc_brkcr, 1);
- out_be16(&sup->scc_parec, 0);
- out_be16(&sup->scc_frmec, 0);
- out_be16(&sup->scc_nosec, 0);
- out_be16(&sup->scc_brkec, 0);
- out_be16(&sup->scc_uaddr1, 0);
- out_be16(&sup->scc_uaddr2, 0);
- out_be16(&sup->scc_toseq, 0);
- out_be16(&sup->scc_char1, 0x8000);
- out_be16(&sup->scc_char2, 0x8000);
- out_be16(&sup->scc_char3, 0x8000);
- out_be16(&sup->scc_char4, 0x8000);
- out_be16(&sup->scc_char5, 0x8000);
- out_be16(&sup->scc_char6, 0x8000);
- out_be16(&sup->scc_char7, 0x8000);
- out_be16(&sup->scc_char8, 0x8000);
- out_be16(&sup->scc_rccm, 0xc0ff);
-
- /* Send the CPM an initialize command.
- */
- cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- out_be32(&scp->scc_gsmrh, 0);
- out_be32(&scp->scc_gsmrl,
- SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
-
- /* Enable rx interrupts and clear all pending events. */
- out_be16(&scp->scc_sccm, 0);
- out_be16(&scp->scc_scce, 0xffff);
- out_be16(&scp->scc_dsr, 0x7e7e);
- out_be16(&scp->scc_psmr, 0x3000);
-
- setbits32(&scp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-}
-
-static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
-{
- smc_t __iomem *sp;
- smc_uart_t __iomem *up;
-
- pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line);
-
- sp = pinfo->smcp;
- up = pinfo->smcup;
-
- /* Store address */
- out_be16(&pinfo->smcup->smc_rbase,
- (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
- out_be16(&pinfo->smcup->smc_tbase,
- (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
-
-/*
- * In case SMC1 is being relocated...
- */
-#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
- out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase));
- out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase));
- out_be32(&up->smc_rstate, 0);
- out_be32(&up->smc_tstate, 0);
- out_be16(&up->smc_brkcr, 1); /* number of break chars */
- out_be16(&up->smc_brkec, 0);
-#endif
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
- cpm_set_smc_fcr(up);
-
- /* Using idle character time requires some additional tuning. */
- out_be16(&up->smc_mrblr, pinfo->rx_fifosize);
- out_be16(&up->smc_maxidl, pinfo->rx_fifosize);
- out_be16(&up->smc_brklen, 0);
- out_be16(&up->smc_brkec, 0);
- out_be16(&up->smc_brkcr, 1);
-
- cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- out_be16(&sp->smc_smcmr, smcr_mk_clen(9) | SMCMR_SM_UART);
-
- /* Enable only rx interrupts clear all pending events. */
- out_8(&sp->smc_smcm, 0);
- out_8(&sp->smc_smce, 0xff);
-
- setbits16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
-}
-
-/*
- * Initialize port. This is called from early_console stuff
- * so we have to be careful here !
- */
-static int cpm_uart_request_port(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- int ret;
-
- pr_debug("CPM uart[%d]:request port\n", port->line);
-
- if (pinfo->flags & FLAG_CONSOLE)
- return 0;
-
- if (IS_SMC(pinfo)) {
- clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
- clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
- } else {
- clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
- clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
- }
-
- ret = cpm_uart_allocbuf(pinfo, 0);
-
- if (ret)
- return ret;
-
- cpm_uart_initbd(pinfo);
- if (IS_SMC(pinfo))
- cpm_uart_init_smc(pinfo);
- else
- cpm_uart_init_scc(pinfo);
-
- return 0;
-}
-
-static void cpm_uart_release_port(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-
- if (!(pinfo->flags & FLAG_CONSOLE))
- cpm_uart_freebuf(pinfo);
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void cpm_uart_config_port(struct uart_port *port, int flags)
-{
- pr_debug("CPM uart[%d]:config_port\n", port->line);
-
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_CPM;
- cpm_uart_request_port(port);
- }
-}
-
-#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
-/*
- * Write a string to the serial port
- * Note that this is called with interrupts already disabled
- */
-static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
- const char *string, u_int count)
-{
- unsigned int i;
- cbd_t __iomem *bdp, *bdbase;
- unsigned char *cpm_outp_addr;
-
- /* Get the address of the host memory buffer.
- */
- bdp = pinfo->tx_cur;
- bdbase = pinfo->tx_bd_base;
-
- /*
- * Now, do each character. This is not as bad as it looks
- * since this is a holding FIFO and not a transmitting FIFO.
- * We could add the complexity of filling the entire transmit
- * buffer, but we would just wait longer between accesses......
- */
- for (i = 0; i < count; i++, string++) {
- /* Wait for transmitter fifo to empty.
- * Ready indicates output is ready, and xmt is doing
- * that, not that it is ready for us to send.
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- /* Send the character out.
- * If the buffer address is in the CPM DPRAM, don't
- * convert it.
- */
- cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
- pinfo);
- *cpm_outp_addr = *string;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
-
- /* if a LF, also do CR... */
- if (*string == 10) {
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
- pinfo);
- *cpm_outp_addr = 13;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- pinfo->tx_cur = bdp;
-}
-#endif
-
-#ifdef CONFIG_CONSOLE_POLL
-/* Serial polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-#define GDB_BUF_SIZE 512 /* power of 2, please */
-
-static char poll_buf[GDB_BUF_SIZE];
-static char *pollp;
-static int poll_chars;
-
-static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
-{
- u_char c, *cp;
- volatile cbd_t *bdp;
- int i;
-
- /* Get the address of the host memory buffer.
- */
- bdp = pinfo->rx_cur;
- while (bdp->cbd_sc & BD_SC_EMPTY)
- ;
-
- /* If the buffer address is in the CPM DPRAM, don't
- * convert it.
- */
- cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
-
- if (obuf) {
- i = c = bdp->cbd_datlen;
- while (i-- > 0)
- *obuf++ = *cp++;
- } else
- c = *cp;
- bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
- bdp->cbd_sc |= BD_SC_EMPTY;
-
- if (bdp->cbd_sc & BD_SC_WRAP)
- bdp = pinfo->rx_bd_base;
- else
- bdp++;
- pinfo->rx_cur = (cbd_t *)bdp;
-
- return (int)c;
-}
-
-static int cpm_get_poll_char(struct uart_port *port)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-
- if (!serial_polled) {
- serial_polled = 1;
- poll_chars = 0;
- }
- if (poll_chars <= 0) {
- poll_chars = poll_wait_key(poll_buf, pinfo);
- pollp = poll_buf;
- }
- poll_chars--;
- return *pollp++;
-}
-
-static void cpm_put_poll_char(struct uart_port *port,
- unsigned char c)
-{
- struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- static char ch[2];
-
- ch[0] = (char)c;
- cpm_uart_early_write(pinfo, ch, 1);
-}
-#endif /* CONFIG_CONSOLE_POLL */
-
-static struct uart_ops cpm_uart_pops = {
- .tx_empty = cpm_uart_tx_empty,
- .set_mctrl = cpm_uart_set_mctrl,
- .get_mctrl = cpm_uart_get_mctrl,
- .stop_tx = cpm_uart_stop_tx,
- .start_tx = cpm_uart_start_tx,
- .stop_rx = cpm_uart_stop_rx,
- .enable_ms = cpm_uart_enable_ms,
- .break_ctl = cpm_uart_break_ctl,
- .startup = cpm_uart_startup,
- .shutdown = cpm_uart_shutdown,
- .set_termios = cpm_uart_set_termios,
- .type = cpm_uart_type,
- .release_port = cpm_uart_release_port,
- .request_port = cpm_uart_request_port,
- .config_port = cpm_uart_config_port,
- .verify_port = cpm_uart_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = cpm_get_poll_char,
- .poll_put_char = cpm_put_poll_char,
-#endif
-};
-
-struct uart_cpm_port cpm_uart_ports[UART_NR];
-
-static int cpm_uart_init_port(struct device_node *np,
- struct uart_cpm_port *pinfo)
-{
- const u32 *data;
- void __iomem *mem, *pram;
- int len;
- int ret;
- int i;
-
- data = of_get_property(np, "clock", NULL);
- if (data) {
- struct clk *clk = clk_get(NULL, (const char*)data);
- if (!IS_ERR(clk))
- pinfo->clk = clk;
- }
- if (!pinfo->clk) {
- data = of_get_property(np, "fsl,cpm-brg", &len);
- if (!data || len != 4) {
- printk(KERN_ERR "CPM UART %s has no/invalid "
- "fsl,cpm-brg property.\n", np->name);
- return -EINVAL;
- }
- pinfo->brg = *data;
- }
-
- data = of_get_property(np, "fsl,cpm-command", &len);
- if (!data || len != 4) {
- printk(KERN_ERR "CPM UART %s has no/invalid "
- "fsl,cpm-command property.\n", np->name);
- return -EINVAL;
- }
- pinfo->command = *data;
-
- mem = of_iomap(np, 0);
- if (!mem)
- return -ENOMEM;
-
- if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
- of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
- pinfo->sccp = mem;
- pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np);
- } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
- of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
- pinfo->flags |= FLAG_SMC;
- pinfo->smcp = mem;
- pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np);
- } else {
- ret = -ENODEV;
- goto out_mem;
- }
-
- if (!pram) {
- ret = -ENOMEM;
- goto out_mem;
- }
-
- pinfo->tx_nrfifos = TX_NUM_FIFO;
- pinfo->tx_fifosize = TX_BUF_SIZE;
- pinfo->rx_nrfifos = RX_NUM_FIFO;
- pinfo->rx_fifosize = RX_BUF_SIZE;
-
- pinfo->port.uartclk = ppc_proc_freq;
- pinfo->port.mapbase = (unsigned long)mem;
- pinfo->port.type = PORT_CPM;
- pinfo->port.ops = &cpm_uart_pops,
- pinfo->port.iotype = UPIO_MEM;
- pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize;
- spin_lock_init(&pinfo->port.lock);
-
- pinfo->port.irq = of_irq_to_resource(np, 0, NULL);
- if (pinfo->port.irq == NO_IRQ) {
- ret = -EINVAL;
- goto out_pram;
- }
-
- for (i = 0; i < NUM_GPIOS; i++)
- pinfo->gpios[i] = of_get_gpio(np, i);
-
-#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
- udbg_putc = NULL;
-#endif
-
- return cpm_uart_request_port(&pinfo->port);
-
-out_pram:
- cpm_uart_unmap_pram(pinfo, pram);
-out_mem:
- iounmap(mem);
- return ret;
-}
-
-#ifdef CONFIG_SERIAL_CPM_CONSOLE
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * Note that this is called with interrupts already disabled
- */
-static void cpm_uart_console_write(struct console *co, const char *s,
- u_int count)
-{
- struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
- unsigned long flags;
- int nolock = oops_in_progress;
-
- if (unlikely(nolock)) {
- local_irq_save(flags);
- } else {
- spin_lock_irqsave(&pinfo->port.lock, flags);
- }
-
- cpm_uart_early_write(pinfo, s, count);
-
- if (unlikely(nolock)) {
- local_irq_restore(flags);
- } else {
- spin_unlock_irqrestore(&pinfo->port.lock, flags);
- }
-}
-
-
-static int __init cpm_uart_console_setup(struct console *co, char *options)
-{
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- int ret;
- struct uart_cpm_port *pinfo;
- struct uart_port *port;
-
- struct device_node *np = NULL;
- int i = 0;
-
- if (co->index >= UART_NR) {
- printk(KERN_ERR "cpm_uart: console index %d too high\n",
- co->index);
- return -ENODEV;
- }
-
- do {
- np = of_find_node_by_type(np, "serial");
- if (!np)
- return -ENODEV;
-
- if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") &&
- !of_device_is_compatible(np, "fsl,cpm1-scc-uart") &&
- !of_device_is_compatible(np, "fsl,cpm2-smc-uart") &&
- !of_device_is_compatible(np, "fsl,cpm2-scc-uart"))
- i--;
- } while (i++ != co->index);
-
- pinfo = &cpm_uart_ports[co->index];
-
- pinfo->flags |= FLAG_CONSOLE;
- port = &pinfo->port;
-
- ret = cpm_uart_init_port(np, pinfo);
- of_node_put(np);
- if (ret)
- return ret;
-
- if (options) {
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- } else {
- if ((baud = uart_baudrate()) == -1)
- baud = 9600;
- }
-
- if (IS_SMC(pinfo)) {
- out_be16(&pinfo->smcup->smc_brkcr, 0);
- cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
- clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
- clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
- } else {
- out_be16(&pinfo->sccup->scc_brkcr, 0);
- cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
- clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
- clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
- }
-
- ret = cpm_uart_allocbuf(pinfo, 1);
-
- if (ret)
- return ret;
-
- cpm_uart_initbd(pinfo);
-
- if (IS_SMC(pinfo))
- cpm_uart_init_smc(pinfo);
- else
- cpm_uart_init_scc(pinfo);
-
- uart_set_options(port, co, baud, parity, bits, flow);
- cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
-
- return 0;
-}
-
-static struct uart_driver cpm_reg;
-static struct console cpm_scc_uart_console = {
- .name = "ttyCPM",
- .write = cpm_uart_console_write,
- .device = uart_console_device,
- .setup = cpm_uart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &cpm_reg,
-};
-
-static int __init cpm_uart_console_init(void)
-{
- register_console(&cpm_scc_uart_console);
- return 0;
-}
-
-console_initcall(cpm_uart_console_init);
-
-#define CPM_UART_CONSOLE &cpm_scc_uart_console
-#else
-#define CPM_UART_CONSOLE NULL
-#endif
-
-static struct uart_driver cpm_reg = {
- .owner = THIS_MODULE,
- .driver_name = "ttyCPM",
- .dev_name = "ttyCPM",
- .major = SERIAL_CPM_MAJOR,
- .minor = SERIAL_CPM_MINOR,
- .cons = CPM_UART_CONSOLE,
- .nr = UART_NR,
-};
-
-static int probe_index;
-
-static int __devinit cpm_uart_probe(struct platform_device *ofdev,
- const struct of_device_id *match)
-{
- int index = probe_index++;
- struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
- int ret;
-
- pinfo->port.line = index;
-
- if (index >= UART_NR)
- return -ENODEV;
-
- dev_set_drvdata(&ofdev->dev, pinfo);
-
- /* initialize the device pointer for the port */
- pinfo->port.dev = &ofdev->dev;
-
- ret = cpm_uart_init_port(ofdev->dev.of_node, pinfo);
- if (ret)
- return ret;
-
- return uart_add_one_port(&cpm_reg, &pinfo->port);
-}
-
-static int __devexit cpm_uart_remove(struct platform_device *ofdev)
-{
- struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
- return uart_remove_one_port(&cpm_reg, &pinfo->port);
-}
-
-static struct of_device_id cpm_uart_match[] = {
- {
- .compatible = "fsl,cpm1-smc-uart",
- },
- {
- .compatible = "fsl,cpm1-scc-uart",
- },
- {
- .compatible = "fsl,cpm2-smc-uart",
- },
- {
- .compatible = "fsl,cpm2-scc-uart",
- },
- {}
-};
-
-static struct of_platform_driver cpm_uart_driver = {
- .driver = {
- .name = "cpm_uart",
- .owner = THIS_MODULE,
- .of_match_table = cpm_uart_match,
- },
- .probe = cpm_uart_probe,
- .remove = cpm_uart_remove,
- };
-
-static int __init cpm_uart_init(void)
-{
- int ret = uart_register_driver(&cpm_reg);
- if (ret)
- return ret;
-
- ret = of_register_platform_driver(&cpm_uart_driver);
- if (ret)
- uart_unregister_driver(&cpm_reg);
-
- return ret;
-}
-
-static void __exit cpm_uart_exit(void)
-{
- of_unregister_platform_driver(&cpm_uart_driver);
- uart_unregister_driver(&cpm_reg);
-}
-
-module_init(cpm_uart_init);
-module_exit(cpm_uart_exit);
-
-MODULE_AUTHOR("Kumar Gala/Antoniou Pantelis");
-MODULE_DESCRIPTION("CPM SCC/SMC port driver $Revision: 0.01 $");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(SERIAL_CPM_MAJOR, SERIAL_CPM_MINOR);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
deleted file mode 100644
index 3fc1d66e32c6..000000000000
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * linux/drivers/serial/cpm_uart.c
- *
- * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions
- *
- * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
- * Pantelis Antoniou (panto@intracom.gr) (CPM1)
- *
- * Copyright (C) 2004 Freescale Semiconductor, Inc.
- * (C) 2004 Intracom, S.A.
- * (C) 2006 MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/gfp.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-#include <linux/bootmem.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/fs_pd.h>
-
-#include <linux/serial_core.h>
-#include <linux/kernel.h>
-
-#include <linux/of.h>
-
-#include "cpm_uart.h"
-
-/**************************************************************/
-
-void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
-{
- cpm_command(port->command, cmd);
-}
-
-void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
- struct device_node *np)
-{
- return of_iomap(np, 1);
-}
-
-void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
-{
- iounmap(pram);
-}
-
-/*
- * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
- * receive buffer descriptors from dual port ram, and a character
- * buffer area from host mem. If we are allocating for the console we need
- * to do it from bootmem
- */
-int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
-{
- int dpmemsz, memsz;
- u8 *dp_mem;
- unsigned long dp_offset;
- u8 *mem_addr;
- dma_addr_t dma_addr = 0;
-
- pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
-
- dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
- dp_offset = cpm_dpalloc(dpmemsz, 8);
- if (IS_ERR_VALUE(dp_offset)) {
- printk(KERN_ERR
- "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
- return -ENOMEM;
- }
- dp_mem = cpm_dpram_addr(dp_offset);
-
- memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
- L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
- if (is_con) {
- /* was hostalloc but changed cause it blows away the */
- /* large tlb mapping when pinning the kernel area */
- mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
- dma_addr = (u32)cpm_dpram_phys(mem_addr);
- } else
- mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
- GFP_KERNEL);
-
- if (mem_addr == NULL) {
- cpm_dpfree(dp_offset);
- printk(KERN_ERR
- "cpm_uart_cpm1.c: could not allocate coherent memory\n");
- return -ENOMEM;
- }
-
- pinfo->dp_addr = dp_offset;
- pinfo->mem_addr = mem_addr; /* virtual address*/
- pinfo->dma_addr = dma_addr; /* physical address*/
- pinfo->mem_size = memsz;
-
- pinfo->rx_buf = mem_addr;
- pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
- * pinfo->rx_fifosize);
-
- pinfo->rx_bd_base = (cbd_t __iomem __force *)dp_mem;
- pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
-
- return 0;
-}
-
-void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
-{
- dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
- pinfo->rx_fifosize) +
- L1_CACHE_ALIGN(pinfo->tx_nrfifos *
- pinfo->tx_fifosize), pinfo->mem_addr,
- pinfo->dma_addr);
-
- cpm_dpfree(pinfo->dp_addr);
-}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/serial/cpm_uart/cpm_uart_cpm1.h
deleted file mode 100644
index 10eecd6af6d4..000000000000
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * linux/drivers/serial/cpm_uart/cpm_uart_cpm1.h
- *
- * Driver for CPM (SCC/SMC) serial ports
- *
- * definitions for cpm1
- *
- */
-
-#ifndef CPM_UART_CPM1_H
-#define CPM_UART_CPM1_H
-
-#include <asm/cpm1.h>
-
-static inline void cpm_set_brg(int brg, int baud)
-{
- cpm_setbrg(brg, baud);
-}
-
-static inline void cpm_set_scc_fcr(scc_uart_t __iomem * sup)
-{
- out_8(&sup->scc_genscc.scc_rfcr, SMC_EB);
- out_8(&sup->scc_genscc.scc_tfcr, SMC_EB);
-}
-
-static inline void cpm_set_smc_fcr(smc_uart_t __iomem * up)
-{
- out_8(&up->smc_rfcr, SMC_EB);
- out_8(&up->smc_tfcr, SMC_EB);
-}
-
-#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0))
-
-#endif
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
deleted file mode 100644
index 814ac006393f..000000000000
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * linux/drivers/serial/cpm_uart_cpm2.c
- *
- * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions
- *
- * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
- * Pantelis Antoniou (panto@intracom.gr) (CPM1)
- *
- * Copyright (C) 2004 Freescale Semiconductor, Inc.
- * (C) 2004 Intracom, S.A.
- * (C) 2006 MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-#include <linux/bootmem.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/fs_pd.h>
-#include <asm/prom.h>
-
-#include <linux/serial_core.h>
-#include <linux/kernel.h>
-
-#include "cpm_uart.h"
-
-/**************************************************************/
-
-void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
-{
- cpm_command(port->command, cmd);
-}
-
-void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
- struct device_node *np)
-{
- void __iomem *pram;
- unsigned long offset;
- struct resource res;
- resource_size_t len;
-
- /* Don't remap parameter RAM if it has already been initialized
- * during console setup.
- */
- if (IS_SMC(port) && port->smcup)
- return port->smcup;
- else if (!IS_SMC(port) && port->sccup)
- return port->sccup;
-
- if (of_address_to_resource(np, 1, &res))
- return NULL;
-
- len = resource_size(&res);
- pram = ioremap(res.start, len);
- if (!pram)
- return NULL;
-
- if (!IS_SMC(port))
- return pram;
-
- if (len != 2) {
- printk(KERN_WARNING "cpm_uart[%d]: device tree references "
- "SMC pram, using boot loader/wrapper pram mapping. "
- "Please fix your device tree to reference the pram "
- "base register instead.\n",
- port->port.line);
- return pram;
- }
-
- offset = cpm_dpalloc(PROFF_SMC_SIZE, 64);
- out_be16(pram, offset);
- iounmap(pram);
- return cpm_muram_addr(offset);
-}
-
-void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
-{
- if (!IS_SMC(port))
- iounmap(pram);
-}
-
-/*
- * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
- * receive buffer descriptors from dual port ram, and a character
- * buffer area from host mem. If we are allocating for the console we need
- * to do it from bootmem
- */
-int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
-{
- int dpmemsz, memsz;
- u8 __iomem *dp_mem;
- unsigned long dp_offset;
- u8 *mem_addr;
- dma_addr_t dma_addr = 0;
-
- pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
-
- dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
- dp_offset = cpm_dpalloc(dpmemsz, 8);
- if (IS_ERR_VALUE(dp_offset)) {
- printk(KERN_ERR
- "cpm_uart_cpm.c: could not allocate buffer descriptors\n");
- return -ENOMEM;
- }
-
- dp_mem = cpm_dpram_addr(dp_offset);
-
- memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
- L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
- if (is_con) {
- mem_addr = kzalloc(memsz, GFP_NOWAIT);
- dma_addr = virt_to_bus(mem_addr);
- }
- else
- mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
- GFP_KERNEL);
-
- if (mem_addr == NULL) {
- cpm_dpfree(dp_offset);
- printk(KERN_ERR
- "cpm_uart_cpm.c: could not allocate coherent memory\n");
- return -ENOMEM;
- }
-
- pinfo->dp_addr = dp_offset;
- pinfo->mem_addr = mem_addr;
- pinfo->dma_addr = dma_addr;
- pinfo->mem_size = memsz;
-
- pinfo->rx_buf = mem_addr;
- pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
- * pinfo->rx_fifosize);
-
- pinfo->rx_bd_base = (cbd_t __iomem *)dp_mem;
- pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
-
- return 0;
-}
-
-void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
-{
- dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
- pinfo->rx_fifosize) +
- L1_CACHE_ALIGN(pinfo->tx_nrfifos *
- pinfo->tx_fifosize), (void __force *)pinfo->mem_addr,
- pinfo->dma_addr);
-
- cpm_dpfree(pinfo->dp_addr);
-}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
deleted file mode 100644
index 7194c63dcf5f..000000000000
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * linux/drivers/serial/cpm_uart/cpm_uart_cpm2.h
- *
- * Driver for CPM (SCC/SMC) serial ports
- *
- * definitions for cpm2
- *
- */
-
-#ifndef CPM_UART_CPM2_H
-#define CPM_UART_CPM2_H
-
-#include <asm/cpm2.h>
-
-static inline void cpm_set_brg(int brg, int baud)
-{
- cpm_setbrg(brg, baud);
-}
-
-static inline void cpm_set_scc_fcr(scc_uart_t __iomem *sup)
-{
- out_8(&sup->scc_genscc.scc_rfcr, CPMFCR_GBL | CPMFCR_EB);
- out_8(&sup->scc_genscc.scc_tfcr, CPMFCR_GBL | CPMFCR_EB);
-}
-
-static inline void cpm_set_smc_fcr(smc_uart_t __iomem *up)
-{
- out_8(&up->smc_rfcr, CPMFCR_GBL | CPMFCR_EB);
- out_8(&up->smc_tfcr, CPMFCR_GBL | CPMFCR_EB);
-}
-
-#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0))
-
-#endif
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
deleted file mode 100644
index bcc31f2140ac..000000000000
--- a/drivers/serial/crisv10.c
+++ /dev/null
@@ -1,4573 +0,0 @@
-/*
- * Serial port driver for the ETRAX 100LX chip
- *
- * Copyright (C) 1998-2007 Axis Communications AB
- *
- * Many, many authors. Based once upon a time on serial.c for 16x50.
- *
- */
-
-static char *serial_version = "$Revision: 1.25 $";
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/system.h>
-
-#include <arch/svinto.h>
-
-/* non-arch dependent serial structures are in linux/serial.h */
-#include <linux/serial.h>
-/* while we keep our own stuff (struct e100_serial) in a local .h file */
-#include "crisv10.h"
-#include <asm/fasttimer.h>
-#include <arch/io_interface_mux.h>
-
-#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
-#ifndef CONFIG_ETRAX_FAST_TIMER
-#error "Enable FAST_TIMER to use SERIAL_FAST_TIMER"
-#endif
-#endif
-
-#if defined(CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS) && \
- (CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS == 0)
-#error "RX_TIMEOUT_TICKS == 0 not allowed, use 1"
-#endif
-
-#if defined(CONFIG_ETRAX_RS485_ON_PA) && defined(CONFIG_ETRAX_RS485_ON_PORT_G)
-#error "Disable either CONFIG_ETRAX_RS485_ON_PA or CONFIG_ETRAX_RS485_ON_PORT_G"
-#endif
-
-/*
- * All of the compatibilty code so we can compile serial.c against
- * older kernels is hidden in serial_compat.h
- */
-#if defined(LOCAL_HEADERS)
-#include "serial_compat.h"
-#endif
-
-struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-//#define SERIAL_DEBUG_INTR
-//#define SERIAL_DEBUG_OPEN
-//#define SERIAL_DEBUG_FLOW
-//#define SERIAL_DEBUG_DATA
-//#define SERIAL_DEBUG_THROTTLE
-//#define SERIAL_DEBUG_IO /* Debug for Extra control and status pins */
-//#define SERIAL_DEBUG_LINE 0 /* What serport we want to debug */
-
-/* Enable this to use serial interrupts to handle when you
- expect the first received event on the serial port to
- be an error, break or similar. Used to be able to flash IRMA
- from eLinux */
-#define SERIAL_HANDLE_EARLY_ERRORS
-
-/* Currently 16 descriptors x 128 bytes = 2048 bytes */
-#define SERIAL_DESCR_BUF_SIZE 256
-
-#define SERIAL_PRESCALE_BASE 3125000 /* 3.125MHz */
-#define DEF_BAUD_BASE SERIAL_PRESCALE_BASE
-
-/* We don't want to load the system with massive fast timer interrupt
- * on high baudrates so limit it to 250 us (4kHz) */
-#define MIN_FLUSH_TIME_USEC 250
-
-/* Add an x here to log a lot of timer stuff */
-#define TIMERD(x)
-/* Debug details of interrupt handling */
-#define DINTR1(x) /* irq on/off, errors */
-#define DINTR2(x) /* tx and rx */
-/* Debug flip buffer stuff */
-#define DFLIP(x)
-/* Debug flow control and overview of data flow */
-#define DFLOW(x)
-#define DBAUD(x)
-#define DLOG_INT_TRIG(x)
-
-//#define DEBUG_LOG_INCLUDED
-#ifndef DEBUG_LOG_INCLUDED
-#define DEBUG_LOG(line, string, value)
-#else
-struct debug_log_info
-{
- unsigned long time;
- unsigned long timer_data;
-// int line;
- const char *string;
- int value;
-};
-#define DEBUG_LOG_SIZE 4096
-
-struct debug_log_info debug_log[DEBUG_LOG_SIZE];
-int debug_log_pos = 0;
-
-#define DEBUG_LOG(_line, _string, _value) do { \
- if ((_line) == SERIAL_DEBUG_LINE) {\
- debug_log_func(_line, _string, _value); \
- }\
-}while(0)
-
-void debug_log_func(int line, const char *string, int value)
-{
- if (debug_log_pos < DEBUG_LOG_SIZE) {
- debug_log[debug_log_pos].time = jiffies;
- debug_log[debug_log_pos].timer_data = *R_TIMER_DATA;
-// debug_log[debug_log_pos].line = line;
- debug_log[debug_log_pos].string = string;
- debug_log[debug_log_pos].value = value;
- debug_log_pos++;
- }
- /*printk(string, value);*/
-}
-#endif
-
-#ifndef CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS
-/* Default number of timer ticks before flushing rx fifo
- * When using "little data, low latency applications: use 0
- * When using "much data applications (PPP)" use ~5
- */
-#define CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5
-#endif
-
-unsigned long timer_data_to_ns(unsigned long timer_data);
-
-static void change_speed(struct e100_serial *info);
-static void rs_throttle(struct tty_struct * tty);
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-static int rs_write(struct tty_struct *tty,
- const unsigned char *buf, int count);
-#ifdef CONFIG_ETRAX_RS485
-static int e100_write_rs485(struct tty_struct *tty,
- const unsigned char *buf, int count);
-#endif
-static int get_lsr_info(struct e100_serial *info, unsigned int *value);
-
-
-#define DEF_BAUD 115200 /* 115.2 kbit/s */
-#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */
-/* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */
-#define DEF_TX 0x80 /* or SERIAL_CTRL_B */
-
-/* offsets from R_SERIALx_CTRL */
-
-#define REG_DATA 0
-#define REG_DATA_STATUS32 0 /* this is the 32 bit register R_SERIALx_READ */
-#define REG_TR_DATA 0
-#define REG_STATUS 1
-#define REG_TR_CTRL 1
-#define REG_REC_CTRL 2
-#define REG_BAUD 3
-#define REG_XOFF 4 /* this is a 32 bit register */
-
-/* The bitfields are the same for all serial ports */
-#define SER_RXD_MASK IO_MASK(R_SERIAL0_STATUS, rxd)
-#define SER_DATA_AVAIL_MASK IO_MASK(R_SERIAL0_STATUS, data_avail)
-#define SER_FRAMING_ERR_MASK IO_MASK(R_SERIAL0_STATUS, framing_err)
-#define SER_PAR_ERR_MASK IO_MASK(R_SERIAL0_STATUS, par_err)
-#define SER_OVERRUN_MASK IO_MASK(R_SERIAL0_STATUS, overrun)
-
-#define SER_ERROR_MASK (SER_OVERRUN_MASK | SER_PAR_ERR_MASK | SER_FRAMING_ERR_MASK)
-
-/* Values for info->errorcode */
-#define ERRCODE_SET_BREAK (TTY_BREAK)
-#define ERRCODE_INSERT 0x100
-#define ERRCODE_INSERT_BREAK (ERRCODE_INSERT | TTY_BREAK)
-
-#define FORCE_EOP(info) *R_SET_EOP = 1U << info->iseteop;
-
-/*
- * General note regarding the use of IO_* macros in this file:
- *
- * We will use the bits defined for DMA channel 6 when using various
- * IO_* macros (e.g. IO_STATE, IO_MASK, IO_EXTRACT) and _assume_ they are
- * the same for all channels (which of course they are).
- *
- * We will also use the bits defined for serial port 0 when writing commands
- * to the different ports, as these bits too are the same for all ports.
- */
-
-
-/* Mask for the irqs possibly enabled in R_IRQ_MASK1_RD etc. */
-static const unsigned long e100_ser_int_mask = 0
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
-| IO_MASK(R_IRQ_MASK1_RD, ser0_data) | IO_MASK(R_IRQ_MASK1_RD, ser0_ready)
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
-| IO_MASK(R_IRQ_MASK1_RD, ser1_data) | IO_MASK(R_IRQ_MASK1_RD, ser1_ready)
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
-| IO_MASK(R_IRQ_MASK1_RD, ser2_data) | IO_MASK(R_IRQ_MASK1_RD, ser2_ready)
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
-| IO_MASK(R_IRQ_MASK1_RD, ser3_data) | IO_MASK(R_IRQ_MASK1_RD, ser3_ready)
-#endif
-;
-unsigned long r_alt_ser_baudrate_shadow = 0;
-
-/* this is the data for the four serial ports in the etrax100 */
-/* DMA2(ser2), DMA4(ser3), DMA6(ser0) or DMA8(ser1) */
-/* R_DMA_CHx_CLR_INTR, R_DMA_CHx_FIRST, R_DMA_CHx_CMD */
-
-static struct e100_serial rs_table[] = {
- { .baud = DEF_BAUD,
- .ioport = (unsigned char *)R_SERIAL0_CTRL,
- .irq = 1U << 12, /* uses DMA 6 and 7 */
- .oclrintradr = R_DMA_CH6_CLR_INTR,
- .ofirstadr = R_DMA_CH6_FIRST,
- .ocmdadr = R_DMA_CH6_CMD,
- .ostatusadr = R_DMA_CH6_STATUS,
- .iclrintradr = R_DMA_CH7_CLR_INTR,
- .ifirstadr = R_DMA_CH7_FIRST,
- .icmdadr = R_DMA_CH7_CMD,
- .idescradr = R_DMA_CH7_DESCR,
- .flags = STD_FLAGS,
- .rx_ctrl = DEF_RX,
- .tx_ctrl = DEF_TX,
- .iseteop = 2,
- .dma_owner = dma_ser0,
- .io_if = if_serial_0,
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
- .enabled = 1,
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
- .dma_out_enabled = 1,
- .dma_out_nbr = SER0_TX_DMA_NBR,
- .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR,
- .dma_out_irq_flags = IRQF_DISABLED,
- .dma_out_irq_description = "serial 0 dma tr",
-#else
- .dma_out_enabled = 0,
- .dma_out_nbr = UINT_MAX,
- .dma_out_irq_nbr = 0,
- .dma_out_irq_flags = 0,
- .dma_out_irq_description = NULL,
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
- .dma_in_enabled = 1,
- .dma_in_nbr = SER0_RX_DMA_NBR,
- .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR,
- .dma_in_irq_flags = IRQF_DISABLED,
- .dma_in_irq_description = "serial 0 dma rec",
-#else
- .dma_in_enabled = 0,
- .dma_in_nbr = UINT_MAX,
- .dma_in_irq_nbr = 0,
- .dma_in_irq_flags = 0,
- .dma_in_irq_description = NULL,
-#endif
-#else
- .enabled = 0,
- .io_if_description = NULL,
- .dma_out_enabled = 0,
- .dma_in_enabled = 0
-#endif
-
-}, /* ttyS0 */
-#ifndef CONFIG_SVINTO_SIM
- { .baud = DEF_BAUD,
- .ioport = (unsigned char *)R_SERIAL1_CTRL,
- .irq = 1U << 16, /* uses DMA 8 and 9 */
- .oclrintradr = R_DMA_CH8_CLR_INTR,
- .ofirstadr = R_DMA_CH8_FIRST,
- .ocmdadr = R_DMA_CH8_CMD,
- .ostatusadr = R_DMA_CH8_STATUS,
- .iclrintradr = R_DMA_CH9_CLR_INTR,
- .ifirstadr = R_DMA_CH9_FIRST,
- .icmdadr = R_DMA_CH9_CMD,
- .idescradr = R_DMA_CH9_DESCR,
- .flags = STD_FLAGS,
- .rx_ctrl = DEF_RX,
- .tx_ctrl = DEF_TX,
- .iseteop = 3,
- .dma_owner = dma_ser1,
- .io_if = if_serial_1,
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
- .enabled = 1,
- .io_if_description = "ser1",
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
- .dma_out_enabled = 1,
- .dma_out_nbr = SER1_TX_DMA_NBR,
- .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR,
- .dma_out_irq_flags = IRQF_DISABLED,
- .dma_out_irq_description = "serial 1 dma tr",
-#else
- .dma_out_enabled = 0,
- .dma_out_nbr = UINT_MAX,
- .dma_out_irq_nbr = 0,
- .dma_out_irq_flags = 0,
- .dma_out_irq_description = NULL,
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
- .dma_in_enabled = 1,
- .dma_in_nbr = SER1_RX_DMA_NBR,
- .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR,
- .dma_in_irq_flags = IRQF_DISABLED,
- .dma_in_irq_description = "serial 1 dma rec",
-#else
- .dma_in_enabled = 0,
- .dma_in_enabled = 0,
- .dma_in_nbr = UINT_MAX,
- .dma_in_irq_nbr = 0,
- .dma_in_irq_flags = 0,
- .dma_in_irq_description = NULL,
-#endif
-#else
- .enabled = 0,
- .io_if_description = NULL,
- .dma_in_irq_nbr = 0,
- .dma_out_enabled = 0,
- .dma_in_enabled = 0
-#endif
-}, /* ttyS1 */
-
- { .baud = DEF_BAUD,
- .ioport = (unsigned char *)R_SERIAL2_CTRL,
- .irq = 1U << 4, /* uses DMA 2 and 3 */
- .oclrintradr = R_DMA_CH2_CLR_INTR,
- .ofirstadr = R_DMA_CH2_FIRST,
- .ocmdadr = R_DMA_CH2_CMD,
- .ostatusadr = R_DMA_CH2_STATUS,
- .iclrintradr = R_DMA_CH3_CLR_INTR,
- .ifirstadr = R_DMA_CH3_FIRST,
- .icmdadr = R_DMA_CH3_CMD,
- .idescradr = R_DMA_CH3_DESCR,
- .flags = STD_FLAGS,
- .rx_ctrl = DEF_RX,
- .tx_ctrl = DEF_TX,
- .iseteop = 0,
- .dma_owner = dma_ser2,
- .io_if = if_serial_2,
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
- .enabled = 1,
- .io_if_description = "ser2",
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
- .dma_out_enabled = 1,
- .dma_out_nbr = SER2_TX_DMA_NBR,
- .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR,
- .dma_out_irq_flags = IRQF_DISABLED,
- .dma_out_irq_description = "serial 2 dma tr",
-#else
- .dma_out_enabled = 0,
- .dma_out_nbr = UINT_MAX,
- .dma_out_irq_nbr = 0,
- .dma_out_irq_flags = 0,
- .dma_out_irq_description = NULL,
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
- .dma_in_enabled = 1,
- .dma_in_nbr = SER2_RX_DMA_NBR,
- .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR,
- .dma_in_irq_flags = IRQF_DISABLED,
- .dma_in_irq_description = "serial 2 dma rec",
-#else
- .dma_in_enabled = 0,
- .dma_in_nbr = UINT_MAX,
- .dma_in_irq_nbr = 0,
- .dma_in_irq_flags = 0,
- .dma_in_irq_description = NULL,
-#endif
-#else
- .enabled = 0,
- .io_if_description = NULL,
- .dma_out_enabled = 0,
- .dma_in_enabled = 0
-#endif
- }, /* ttyS2 */
-
- { .baud = DEF_BAUD,
- .ioport = (unsigned char *)R_SERIAL3_CTRL,
- .irq = 1U << 8, /* uses DMA 4 and 5 */
- .oclrintradr = R_DMA_CH4_CLR_INTR,
- .ofirstadr = R_DMA_CH4_FIRST,
- .ocmdadr = R_DMA_CH4_CMD,
- .ostatusadr = R_DMA_CH4_STATUS,
- .iclrintradr = R_DMA_CH5_CLR_INTR,
- .ifirstadr = R_DMA_CH5_FIRST,
- .icmdadr = R_DMA_CH5_CMD,
- .idescradr = R_DMA_CH5_DESCR,
- .flags = STD_FLAGS,
- .rx_ctrl = DEF_RX,
- .tx_ctrl = DEF_TX,
- .iseteop = 1,
- .dma_owner = dma_ser3,
- .io_if = if_serial_3,
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
- .enabled = 1,
- .io_if_description = "ser3",
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
- .dma_out_enabled = 1,
- .dma_out_nbr = SER3_TX_DMA_NBR,
- .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR,
- .dma_out_irq_flags = IRQF_DISABLED,
- .dma_out_irq_description = "serial 3 dma tr",
-#else
- .dma_out_enabled = 0,
- .dma_out_nbr = UINT_MAX,
- .dma_out_irq_nbr = 0,
- .dma_out_irq_flags = 0,
- .dma_out_irq_description = NULL,
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
- .dma_in_enabled = 1,
- .dma_in_nbr = SER3_RX_DMA_NBR,
- .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR,
- .dma_in_irq_flags = IRQF_DISABLED,
- .dma_in_irq_description = "serial 3 dma rec",
-#else
- .dma_in_enabled = 0,
- .dma_in_nbr = UINT_MAX,
- .dma_in_irq_nbr = 0,
- .dma_in_irq_flags = 0,
- .dma_in_irq_description = NULL
-#endif
-#else
- .enabled = 0,
- .io_if_description = NULL,
- .dma_out_enabled = 0,
- .dma_in_enabled = 0
-#endif
- } /* ttyS3 */
-#endif
-};
-
-
-#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
-
-#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
-static struct fast_timer fast_timers[NR_PORTS];
-#endif
-
-#ifdef CONFIG_ETRAX_SERIAL_PROC_ENTRY
-#define PROCSTAT(x) x
-struct ser_statistics_type {
- int overrun_cnt;
- int early_errors_cnt;
- int ser_ints_ok_cnt;
- int errors_cnt;
- unsigned long int processing_flip;
- unsigned long processing_flip_still_room;
- unsigned long int timeout_flush_cnt;
- int rx_dma_ints;
- int tx_dma_ints;
- int rx_tot;
- int tx_tot;
-};
-
-static struct ser_statistics_type ser_stat[NR_PORTS];
-
-#else
-
-#define PROCSTAT(x)
-
-#endif /* CONFIG_ETRAX_SERIAL_PROC_ENTRY */
-
-/* RS-485 */
-#if defined(CONFIG_ETRAX_RS485)
-#ifdef CONFIG_ETRAX_FAST_TIMER
-static struct fast_timer fast_timers_rs485[NR_PORTS];
-#endif
-#if defined(CONFIG_ETRAX_RS485_ON_PA)
-static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT;
-#endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
-static int rs485_port_g_bit = CONFIG_ETRAX_RS485_ON_PORT_G_BIT;
-#endif
-#endif
-
-/* Info and macros needed for each ports extra control/status signals. */
-#define E100_STRUCT_PORT(line, pinname) \
- ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \
- (R_PORT_PA_DATA): ( \
- (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \
- (R_PORT_PB_DATA):&dummy_ser[line]))
-
-#define E100_STRUCT_SHADOW(line, pinname) \
- ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \
- (&port_pa_data_shadow): ( \
- (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \
- (&port_pb_data_shadow):&dummy_ser[line]))
-#define E100_STRUCT_MASK(line, pinname) \
- ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \
- (1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT): ( \
- (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \
- (1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT):DUMMY_##pinname##_MASK))
-
-#define DUMMY_DTR_MASK 1
-#define DUMMY_RI_MASK 2
-#define DUMMY_DSR_MASK 4
-#define DUMMY_CD_MASK 8
-static unsigned char dummy_ser[NR_PORTS] = {0xFF, 0xFF, 0xFF,0xFF};
-
-/* If not all status pins are used or disabled, use mixed mode */
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
-
-#define SER0_PA_BITSUM (CONFIG_ETRAX_SER0_DTR_ON_PA_BIT+CONFIG_ETRAX_SER0_RI_ON_PA_BIT+CONFIG_ETRAX_SER0_DSR_ON_PA_BIT+CONFIG_ETRAX_SER0_CD_ON_PA_BIT)
-
-#if SER0_PA_BITSUM != -4
-# if CONFIG_ETRAX_SER0_DTR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER0_RI_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER0_DSR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER0_CD_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#define SER0_PB_BITSUM (CONFIG_ETRAX_SER0_DTR_ON_PB_BIT+CONFIG_ETRAX_SER0_RI_ON_PB_BIT+CONFIG_ETRAX_SER0_DSR_ON_PB_BIT+CONFIG_ETRAX_SER0_CD_ON_PB_BIT)
-
-#if SER0_PB_BITSUM != -4
-# if CONFIG_ETRAX_SER0_DTR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER0_RI_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER0_DSR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER0_CD_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#endif /* PORT0 */
-
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
-
-#define SER1_PA_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PA_BIT+CONFIG_ETRAX_SER1_RI_ON_PA_BIT+CONFIG_ETRAX_SER1_DSR_ON_PA_BIT+CONFIG_ETRAX_SER1_CD_ON_PA_BIT)
-
-#if SER1_PA_BITSUM != -4
-# if CONFIG_ETRAX_SER1_DTR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER1_RI_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER1_DSR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER1_CD_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#define SER1_PB_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PB_BIT+CONFIG_ETRAX_SER1_RI_ON_PB_BIT+CONFIG_ETRAX_SER1_DSR_ON_PB_BIT+CONFIG_ETRAX_SER1_CD_ON_PB_BIT)
-
-#if SER1_PB_BITSUM != -4
-# if CONFIG_ETRAX_SER1_DTR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER1_RI_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER1_DSR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER1_CD_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#endif /* PORT1 */
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
-
-#define SER2_PA_BITSUM (CONFIG_ETRAX_SER2_DTR_ON_PA_BIT+CONFIG_ETRAX_SER2_RI_ON_PA_BIT+CONFIG_ETRAX_SER2_DSR_ON_PA_BIT+CONFIG_ETRAX_SER2_CD_ON_PA_BIT)
-
-#if SER2_PA_BITSUM != -4
-# if CONFIG_ETRAX_SER2_DTR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER2_RI_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER2_DSR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER2_CD_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#define SER2_PB_BITSUM (CONFIG_ETRAX_SER2_DTR_ON_PB_BIT+CONFIG_ETRAX_SER2_RI_ON_PB_BIT+CONFIG_ETRAX_SER2_DSR_ON_PB_BIT+CONFIG_ETRAX_SER2_CD_ON_PB_BIT)
-
-#if SER2_PB_BITSUM != -4
-# if CONFIG_ETRAX_SER2_DTR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER2_RI_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER2_DSR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER2_CD_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#endif /* PORT2 */
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
-
-#define SER3_PA_BITSUM (CONFIG_ETRAX_SER3_DTR_ON_PA_BIT+CONFIG_ETRAX_SER3_RI_ON_PA_BIT+CONFIG_ETRAX_SER3_DSR_ON_PA_BIT+CONFIG_ETRAX_SER3_CD_ON_PA_BIT)
-
-#if SER3_PA_BITSUM != -4
-# if CONFIG_ETRAX_SER3_DTR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER3_RI_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER3_DSR_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER3_CD_ON_PA_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#define SER3_PB_BITSUM (CONFIG_ETRAX_SER3_DTR_ON_PB_BIT+CONFIG_ETRAX_SER3_RI_ON_PB_BIT+CONFIG_ETRAX_SER3_DSR_ON_PB_BIT+CONFIG_ETRAX_SER3_CD_ON_PB_BIT)
-
-#if SER3_PB_BITSUM != -4
-# if CONFIG_ETRAX_SER3_DTR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER3_RI_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER3_DSR_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-# if CONFIG_ETRAX_SER3_CD_ON_PB_BIT == -1
-# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
-# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
-# endif
-# endif
-#endif
-
-#endif /* PORT3 */
-
-
-#if defined(CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED) || \
- defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED) || \
- defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED) || \
- defined(CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED)
-#define CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED
-#endif
-
-#ifdef CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED
-/* The pins can be mixed on PA and PB */
-#define CONTROL_PINS_PORT_NOT_USED(line) \
- &dummy_ser[line], &dummy_ser[line], \
- &dummy_ser[line], &dummy_ser[line], \
- &dummy_ser[line], &dummy_ser[line], \
- &dummy_ser[line], &dummy_ser[line], \
- DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK
-
-
-struct control_pins
-{
- volatile unsigned char *dtr_port;
- unsigned char *dtr_shadow;
- volatile unsigned char *ri_port;
- unsigned char *ri_shadow;
- volatile unsigned char *dsr_port;
- unsigned char *dsr_shadow;
- volatile unsigned char *cd_port;
- unsigned char *cd_shadow;
-
- unsigned char dtr_mask;
- unsigned char ri_mask;
- unsigned char dsr_mask;
- unsigned char cd_mask;
-};
-
-static const struct control_pins e100_modem_pins[NR_PORTS] =
-{
- /* Ser 0 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
- E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR),
- E100_STRUCT_PORT(0,RI), E100_STRUCT_SHADOW(0,RI),
- E100_STRUCT_PORT(0,DSR), E100_STRUCT_SHADOW(0,DSR),
- E100_STRUCT_PORT(0,CD), E100_STRUCT_SHADOW(0,CD),
- E100_STRUCT_MASK(0,DTR),
- E100_STRUCT_MASK(0,RI),
- E100_STRUCT_MASK(0,DSR),
- E100_STRUCT_MASK(0,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(0)
-#endif
- },
-
- /* Ser 1 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
- E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR),
- E100_STRUCT_PORT(1,RI), E100_STRUCT_SHADOW(1,RI),
- E100_STRUCT_PORT(1,DSR), E100_STRUCT_SHADOW(1,DSR),
- E100_STRUCT_PORT(1,CD), E100_STRUCT_SHADOW(1,CD),
- E100_STRUCT_MASK(1,DTR),
- E100_STRUCT_MASK(1,RI),
- E100_STRUCT_MASK(1,DSR),
- E100_STRUCT_MASK(1,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(1)
-#endif
- },
-
- /* Ser 2 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
- E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR),
- E100_STRUCT_PORT(2,RI), E100_STRUCT_SHADOW(2,RI),
- E100_STRUCT_PORT(2,DSR), E100_STRUCT_SHADOW(2,DSR),
- E100_STRUCT_PORT(2,CD), E100_STRUCT_SHADOW(2,CD),
- E100_STRUCT_MASK(2,DTR),
- E100_STRUCT_MASK(2,RI),
- E100_STRUCT_MASK(2,DSR),
- E100_STRUCT_MASK(2,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(2)
-#endif
- },
-
- /* Ser 3 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
- E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR),
- E100_STRUCT_PORT(3,RI), E100_STRUCT_SHADOW(3,RI),
- E100_STRUCT_PORT(3,DSR), E100_STRUCT_SHADOW(3,DSR),
- E100_STRUCT_PORT(3,CD), E100_STRUCT_SHADOW(3,CD),
- E100_STRUCT_MASK(3,DTR),
- E100_STRUCT_MASK(3,RI),
- E100_STRUCT_MASK(3,DSR),
- E100_STRUCT_MASK(3,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(3)
-#endif
- }
-};
-#else /* CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
-
-/* All pins are on either PA or PB for each serial port */
-#define CONTROL_PINS_PORT_NOT_USED(line) \
- &dummy_ser[line], &dummy_ser[line], \
- DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK
-
-
-struct control_pins
-{
- volatile unsigned char *port;
- unsigned char *shadow;
-
- unsigned char dtr_mask;
- unsigned char ri_mask;
- unsigned char dsr_mask;
- unsigned char cd_mask;
-};
-
-#define dtr_port port
-#define dtr_shadow shadow
-#define ri_port port
-#define ri_shadow shadow
-#define dsr_port port
-#define dsr_shadow shadow
-#define cd_port port
-#define cd_shadow shadow
-
-static const struct control_pins e100_modem_pins[NR_PORTS] =
-{
- /* Ser 0 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
- E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR),
- E100_STRUCT_MASK(0,DTR),
- E100_STRUCT_MASK(0,RI),
- E100_STRUCT_MASK(0,DSR),
- E100_STRUCT_MASK(0,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(0)
-#endif
- },
-
- /* Ser 1 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
- E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR),
- E100_STRUCT_MASK(1,DTR),
- E100_STRUCT_MASK(1,RI),
- E100_STRUCT_MASK(1,DSR),
- E100_STRUCT_MASK(1,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(1)
-#endif
- },
-
- /* Ser 2 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
- E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR),
- E100_STRUCT_MASK(2,DTR),
- E100_STRUCT_MASK(2,RI),
- E100_STRUCT_MASK(2,DSR),
- E100_STRUCT_MASK(2,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(2)
-#endif
- },
-
- /* Ser 3 */
- {
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
- E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR),
- E100_STRUCT_MASK(3,DTR),
- E100_STRUCT_MASK(3,RI),
- E100_STRUCT_MASK(3,DSR),
- E100_STRUCT_MASK(3,CD)
-#else
- CONTROL_PINS_PORT_NOT_USED(3)
-#endif
- }
-};
-#endif /* !CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
-
-#define E100_RTS_MASK 0x20
-#define E100_CTS_MASK 0x40
-
-/* All serial port signals are active low:
- * active = 0 -> 3.3V to RS-232 driver -> -12V on RS-232 level
- * inactive = 1 -> 0V to RS-232 driver -> +12V on RS-232 level
- *
- * These macros returns the pin value: 0=0V, >=1 = 3.3V on ETRAX chip
- */
-
-/* Output */
-#define E100_RTS_GET(info) ((info)->rx_ctrl & E100_RTS_MASK)
-/* Input */
-#define E100_CTS_GET(info) ((info)->ioport[REG_STATUS] & E100_CTS_MASK)
-
-/* These are typically PA or PB and 0 means 0V, 1 means 3.3V */
-/* Is an output */
-#define E100_DTR_GET(info) ((*e100_modem_pins[(info)->line].dtr_shadow) & e100_modem_pins[(info)->line].dtr_mask)
-
-/* Normally inputs */
-#define E100_RI_GET(info) ((*e100_modem_pins[(info)->line].ri_port) & e100_modem_pins[(info)->line].ri_mask)
-#define E100_CD_GET(info) ((*e100_modem_pins[(info)->line].cd_port) & e100_modem_pins[(info)->line].cd_mask)
-
-/* Input */
-#define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].dsr_port) & e100_modem_pins[(info)->line].dsr_mask)
-
-
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-static DEFINE_MUTEX(tmp_buf_mutex);
-
-/* Calculate the chartime depending on baudrate, numbor of bits etc. */
-static void update_char_time(struct e100_serial * info)
-{
- tcflag_t cflags = info->port.tty->termios->c_cflag;
- int bits;
-
- /* calc. number of bits / data byte */
- /* databits + startbit and 1 stopbit */
- if ((cflags & CSIZE) == CS7)
- bits = 9;
- else
- bits = 10;
-
- if (cflags & CSTOPB) /* 2 stopbits ? */
- bits++;
-
- if (cflags & PARENB) /* parity bit ? */
- bits++;
-
- /* calc timeout */
- info->char_time_usec = ((bits * 1000000) / info->baud) + 1;
- info->flush_time_usec = 4*info->char_time_usec;
- if (info->flush_time_usec < MIN_FLUSH_TIME_USEC)
- info->flush_time_usec = MIN_FLUSH_TIME_USEC;
-
-}
-
-/*
- * This function maps from the Bxxxx defines in asm/termbits.h into real
- * baud rates.
- */
-
-static int
-cflag_to_baud(unsigned int cflag)
-{
- static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 };
-
- static int ext_baud_table[] = {
- 0, 57600, 115200, 230400, 460800, 921600, 1843200, 6250000,
- 0, 0, 0, 0, 0, 0, 0, 0 };
-
- if (cflag & CBAUDEX)
- return ext_baud_table[(cflag & CBAUD) & ~CBAUDEX];
- else
- return baud_table[cflag & CBAUD];
-}
-
-/* and this maps to an etrax100 hardware baud constant */
-
-static unsigned char
-cflag_to_etrax_baud(unsigned int cflag)
-{
- char retval;
-
- static char baud_table[] = {
- -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, 3, 4, 5, 6, 7 };
-
- static char ext_baud_table[] = {
- -1, 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1 };
-
- if (cflag & CBAUDEX)
- retval = ext_baud_table[(cflag & CBAUD) & ~CBAUDEX];
- else
- retval = baud_table[cflag & CBAUD];
-
- if (retval < 0) {
- printk(KERN_WARNING "serdriver tried setting invalid baud rate, flags %x.\n", cflag);
- retval = 5; /* choose default 9600 instead */
- }
-
- return retval | (retval << 4); /* choose same for both TX and RX */
-}
-
-
-/* Various static support functions */
-
-/* Functions to set or clear DTR/RTS on the requested line */
-/* It is complicated by the fact that RTS is a serial port register, while
- * DTR might not be implemented in the HW at all, and if it is, it can be on
- * any general port.
- */
-
-
-static inline void
-e100_dtr(struct e100_serial *info, int set)
-{
-#ifndef CONFIG_SVINTO_SIM
- unsigned char mask = e100_modem_pins[info->line].dtr_mask;
-
-#ifdef SERIAL_DEBUG_IO
- printk("ser%i dtr %i mask: 0x%02X\n", info->line, set, mask);
- printk("ser%i shadow before 0x%02X get: %i\n",
- info->line, *e100_modem_pins[info->line].dtr_shadow,
- E100_DTR_GET(info));
-#endif
- /* DTR is active low */
- {
- unsigned long flags;
-
- local_irq_save(flags);
- *e100_modem_pins[info->line].dtr_shadow &= ~mask;
- *e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask);
- *e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow;
- local_irq_restore(flags);
- }
-
-#ifdef SERIAL_DEBUG_IO
- printk("ser%i shadow after 0x%02X get: %i\n",
- info->line, *e100_modem_pins[info->line].dtr_shadow,
- E100_DTR_GET(info));
-#endif
-#endif
-}
-
-/* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive
- * 0=0V , 1=3.3V
- */
-static inline void
-e100_rts(struct e100_serial *info, int set)
-{
-#ifndef CONFIG_SVINTO_SIM
- unsigned long flags;
- local_irq_save(flags);
- info->rx_ctrl &= ~E100_RTS_MASK;
- info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */
- info->ioport[REG_REC_CTRL] = info->rx_ctrl;
- local_irq_restore(flags);
-#ifdef SERIAL_DEBUG_IO
- printk("ser%i rts %i\n", info->line, set);
-#endif
-#endif
-}
-
-
-/* If this behaves as a modem, RI and CD is an output */
-static inline void
-e100_ri_out(struct e100_serial *info, int set)
-{
-#ifndef CONFIG_SVINTO_SIM
- /* RI is active low */
- {
- unsigned char mask = e100_modem_pins[info->line].ri_mask;
- unsigned long flags;
-
- local_irq_save(flags);
- *e100_modem_pins[info->line].ri_shadow &= ~mask;
- *e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask);
- *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
- local_irq_restore(flags);
- }
-#endif
-}
-static inline void
-e100_cd_out(struct e100_serial *info, int set)
-{
-#ifndef CONFIG_SVINTO_SIM
- /* CD is active low */
- {
- unsigned char mask = e100_modem_pins[info->line].cd_mask;
- unsigned long flags;
-
- local_irq_save(flags);
- *e100_modem_pins[info->line].cd_shadow &= ~mask;
- *e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask);
- *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
- local_irq_restore(flags);
- }
-#endif
-}
-
-static inline void
-e100_disable_rx(struct e100_serial *info)
-{
-#ifndef CONFIG_SVINTO_SIM
- /* disable the receiver */
- info->ioport[REG_REC_CTRL] =
- (info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
-#endif
-}
-
-static inline void
-e100_enable_rx(struct e100_serial *info)
-{
-#ifndef CONFIG_SVINTO_SIM
- /* enable the receiver */
- info->ioport[REG_REC_CTRL] =
- (info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
-#endif
-}
-
-/* the rx DMA uses both the dma_descr and the dma_eop interrupts */
-
-static inline void
-e100_disable_rxdma_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("rxdma_irq(%d): 0\n",info->line);
-#endif
- DINTR1(DEBUG_LOG(info->line,"IRQ disable_rxdma_irq %i\n", info->line));
- *R_IRQ_MASK2_CLR = (info->irq << 2) | (info->irq << 3);
-}
-
-static inline void
-e100_enable_rxdma_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("rxdma_irq(%d): 1\n",info->line);
-#endif
- DINTR1(DEBUG_LOG(info->line,"IRQ enable_rxdma_irq %i\n", info->line));
- *R_IRQ_MASK2_SET = (info->irq << 2) | (info->irq << 3);
-}
-
-/* the tx DMA uses only dma_descr interrupt */
-
-static void e100_disable_txdma_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("txdma_irq(%d): 0\n",info->line);
-#endif
- DINTR1(DEBUG_LOG(info->line,"IRQ disable_txdma_irq %i\n", info->line));
- *R_IRQ_MASK2_CLR = info->irq;
-}
-
-static void e100_enable_txdma_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("txdma_irq(%d): 1\n",info->line);
-#endif
- DINTR1(DEBUG_LOG(info->line,"IRQ enable_txdma_irq %i\n", info->line));
- *R_IRQ_MASK2_SET = info->irq;
-}
-
-static void e100_disable_txdma_channel(struct e100_serial *info)
-{
- unsigned long flags;
-
- /* Disable output DMA channel for the serial port in question
- * ( set to something other than serialX)
- */
- local_irq_save(flags);
- DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line));
- if (info->line == 0) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) ==
- IO_STATE(R_GEN_CONFIG, dma6, serial0)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused);
- }
- } else if (info->line == 1) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma8)) ==
- IO_STATE(R_GEN_CONFIG, dma8, serial1)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb);
- }
- } else if (info->line == 2) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma2)) ==
- IO_STATE(R_GEN_CONFIG, dma2, serial2)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0);
- }
- } else if (info->line == 3) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma4)) ==
- IO_STATE(R_GEN_CONFIG, dma4, serial3)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1);
- }
- }
- *R_GEN_CONFIG = genconfig_shadow;
- local_irq_restore(flags);
-}
-
-
-static void e100_enable_txdma_channel(struct e100_serial *info)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line));
- /* Enable output DMA channel for the serial port in question */
- if (info->line == 0) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, serial0);
- } else if (info->line == 1) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, serial1);
- } else if (info->line == 2) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, serial2);
- } else if (info->line == 3) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3);
- }
- *R_GEN_CONFIG = genconfig_shadow;
- local_irq_restore(flags);
-}
-
-static void e100_disable_rxdma_channel(struct e100_serial *info)
-{
- unsigned long flags;
-
- /* Disable input DMA channel for the serial port in question
- * ( set to something other than serialX)
- */
- local_irq_save(flags);
- if (info->line == 0) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) ==
- IO_STATE(R_GEN_CONFIG, dma7, serial0)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, unused);
- }
- } else if (info->line == 1) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma9)) ==
- IO_STATE(R_GEN_CONFIG, dma9, serial1)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma9);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, usb);
- }
- } else if (info->line == 2) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma3)) ==
- IO_STATE(R_GEN_CONFIG, dma3, serial2)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, par0);
- }
- } else if (info->line == 3) {
- if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma5)) ==
- IO_STATE(R_GEN_CONFIG, dma5, serial3)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, par1);
- }
- }
- *R_GEN_CONFIG = genconfig_shadow;
- local_irq_restore(flags);
-}
-
-
-static void e100_enable_rxdma_channel(struct e100_serial *info)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- /* Enable input DMA channel for the serial port in question */
- if (info->line == 0) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, serial0);
- } else if (info->line == 1) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma9);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, serial1);
- } else if (info->line == 2) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, serial2);
- } else if (info->line == 3) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5);
- genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3);
- }
- *R_GEN_CONFIG = genconfig_shadow;
- local_irq_restore(flags);
-}
-
-#ifdef SERIAL_HANDLE_EARLY_ERRORS
-/* in order to detect and fix errors on the first byte
- we have to use the serial interrupts as well. */
-
-static inline void
-e100_disable_serial_data_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("ser_irq(%d): 0\n",info->line);
-#endif
- DINTR1(DEBUG_LOG(info->line,"IRQ disable data_irq %i\n", info->line));
- *R_IRQ_MASK1_CLR = (1U << (8+2*info->line));
-}
-
-static inline void
-e100_enable_serial_data_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("ser_irq(%d): 1\n",info->line);
- printk("**** %d = %d\n",
- (8+2*info->line),
- (1U << (8+2*info->line)));
-#endif
- DINTR1(DEBUG_LOG(info->line,"IRQ enable data_irq %i\n", info->line));
- *R_IRQ_MASK1_SET = (1U << (8+2*info->line));
-}
-#endif
-
-static inline void
-e100_disable_serial_tx_ready_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("ser_tx_irq(%d): 0\n",info->line);
-#endif
- DINTR1(DEBUG_LOG(info->line,"IRQ disable ready_irq %i\n", info->line));
- *R_IRQ_MASK1_CLR = (1U << (8+1+2*info->line));
-}
-
-static inline void
-e100_enable_serial_tx_ready_irq(struct e100_serial *info)
-{
-#ifdef SERIAL_DEBUG_INTR
- printk("ser_tx_irq(%d): 1\n",info->line);
- printk("**** %d = %d\n",
- (8+1+2*info->line),
- (1U << (8+1+2*info->line)));
-#endif
- DINTR2(DEBUG_LOG(info->line,"IRQ enable ready_irq %i\n", info->line));
- *R_IRQ_MASK1_SET = (1U << (8+1+2*info->line));
-}
-
-static inline void e100_enable_rx_irq(struct e100_serial *info)
-{
- if (info->uses_dma_in)
- e100_enable_rxdma_irq(info);
- else
- e100_enable_serial_data_irq(info);
-}
-static inline void e100_disable_rx_irq(struct e100_serial *info)
-{
- if (info->uses_dma_in)
- e100_disable_rxdma_irq(info);
- else
- e100_disable_serial_data_irq(info);
-}
-
-#if defined(CONFIG_ETRAX_RS485)
-/* Enable RS-485 mode on selected port. This is UGLY. */
-static int
-e100_enable_rs485(struct tty_struct *tty, struct serial_rs485 *r)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
-
-#if defined(CONFIG_ETRAX_RS485_ON_PA)
- *R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit);
-#endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
- REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
- rs485_port_g_bit, 1);
-#endif
-#if defined(CONFIG_ETRAX_RS485_LTC1387)
- REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
- CONFIG_ETRAX_RS485_LTC1387_DXEN_PORT_G_BIT, 1);
- REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
- CONFIG_ETRAX_RS485_LTC1387_RXEN_PORT_G_BIT, 1);
-#endif
-
- info->rs485 = *r;
-
- /* Maximum delay before RTS equal to 1000 */
- if (info->rs485.delay_rts_before_send >= 1000)
- info->rs485.delay_rts_before_send = 1000;
-
-/* printk("rts: on send = %i, after = %i, enabled = %i",
- info->rs485.rts_on_send,
- info->rs485.rts_after_sent,
- info->rs485.enabled
- );
-*/
- return 0;
-}
-
-static int
-e100_write_rs485(struct tty_struct *tty,
- const unsigned char *buf, int count)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
- int old_value = (info->rs485.flags) & SER_RS485_ENABLED;
-
- /* rs485 is always implicitly enabled if we're using the ioctl()
- * but it doesn't have to be set in the serial_rs485
- * (to be backward compatible with old apps)
- * So we store, set and restore it.
- */
- info->rs485.flags |= SER_RS485_ENABLED;
- /* rs_write now deals with RS485 if enabled */
- count = rs_write(tty, buf, count);
- if (!old_value)
- info->rs485.flags &= ~(SER_RS485_ENABLED);
- return count;
-}
-
-#ifdef CONFIG_ETRAX_FAST_TIMER
-/* Timer function to toggle RTS when using FAST_TIMER */
-static void rs485_toggle_rts_timer_function(unsigned long data)
-{
- struct e100_serial *info = (struct e100_serial *)data;
-
- fast_timers_rs485[info->line].function = NULL;
- e100_rts(info, (info->rs485.flags & SER_RS485_RTS_AFTER_SEND));
-#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
- e100_enable_rx(info);
- e100_enable_rx_irq(info);
-#endif
-}
-#endif
-#endif /* CONFIG_ETRAX_RS485 */
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter using the XOFF registers, as necessary.
- * ------------------------------------------------------------
- */
-
-static void
-rs_stop(struct tty_struct *tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- if (info) {
- unsigned long flags;
- unsigned long xoff;
-
- local_irq_save(flags);
- DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n",
- CIRC_CNT(info->xmit.head,
- info->xmit.tail,SERIAL_XMIT_SIZE)));
-
- xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char,
- STOP_CHAR(info->port.tty));
- xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop);
- if (tty->termios->c_iflag & IXON ) {
- xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
- }
-
- *((unsigned long *)&info->ioport[REG_XOFF]) = xoff;
- local_irq_restore(flags);
- }
-}
-
-static void
-rs_start(struct tty_struct *tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- if (info) {
- unsigned long flags;
- unsigned long xoff;
-
- local_irq_save(flags);
- DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n",
- CIRC_CNT(info->xmit.head,
- info->xmit.tail,SERIAL_XMIT_SIZE)));
- xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty));
- xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
- if (tty->termios->c_iflag & IXON ) {
- xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
- }
-
- *((unsigned long *)&info->ioport[REG_XOFF]) = xoff;
- if (!info->uses_dma_out &&
- info->xmit.head != info->xmit.tail && info->xmit.buf)
- e100_enable_serial_tx_ready_irq(info);
-
- local_irq_restore(flags);
- }
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines. All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt(). They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off. People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible. After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static void rs_sched_event(struct e100_serial *info, int event)
-{
- if (info->event & (1 << event))
- return;
- info->event |= 1 << event;
- schedule_work(&info->work);
-}
-
-/* The output DMA channel is free - use it to send as many chars as possible
- * NOTES:
- * We don't pay attention to info->x_char, which means if the TTY wants to
- * use XON/XOFF it will set info->x_char but we won't send any X char!
- *
- * To implement this, we'd just start a DMA send of 1 byte pointing at a
- * buffer containing the X char, and skip updating xmit. We'd also have to
- * check if the last sent char was the X char when we enter this function
- * the next time, to avoid updating xmit with the sent X value.
- */
-
-static void
-transmit_chars_dma(struct e100_serial *info)
-{
- unsigned int c, sentl;
- struct etrax_dma_descr *descr;
-
-#ifdef CONFIG_SVINTO_SIM
- /* This will output too little if tail is not 0 always since
- * we don't reloop to send the other part. Anyway this SHOULD be a
- * no-op - transmit_chars_dma would never really be called during sim
- * since rs_write does not write into the xmit buffer then.
- */
- if (info->xmit.tail)
- printk("Error in serial.c:transmit_chars-dma(), tail!=0\n");
- if (info->xmit.head != info->xmit.tail) {
- SIMCOUT(info->xmit.buf + info->xmit.tail,
- CIRC_CNT(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE));
- info->xmit.head = info->xmit.tail; /* move back head */
- info->tr_running = 0;
- }
- return;
-#endif
- /* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
- *info->oclrintradr =
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
-
-#ifdef SERIAL_DEBUG_INTR
- if (info->line == SERIAL_DEBUG_LINE)
- printk("tc\n");
-#endif
- if (!info->tr_running) {
- /* weirdo... we shouldn't get here! */
- printk(KERN_WARNING "Achtung: transmit_chars_dma with !tr_running\n");
- return;
- }
-
- descr = &info->tr_descr;
-
- /* first get the amount of bytes sent during the last DMA transfer,
- and update xmit accordingly */
-
- /* if the stop bit was not set, all data has been sent */
- if (!(descr->status & d_stop)) {
- sentl = descr->sw_len;
- } else
- /* otherwise we find the amount of data sent here */
- sentl = descr->hw_len;
-
- DFLOW(DEBUG_LOG(info->line, "TX %i done\n", sentl));
-
- /* update stats */
- info->icount.tx += sentl;
-
- /* update xmit buffer */
- info->xmit.tail = (info->xmit.tail + sentl) & (SERIAL_XMIT_SIZE - 1);
-
- /* if there is only a few chars left in the buf, wake up the blocked
- write if any */
- if (CIRC_CNT(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
- rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-
- /* find out the largest amount of consecutive bytes we want to send now */
-
- c = CIRC_CNT_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-
- /* Don't send all in one DMA transfer - divide it so we wake up
- * application before all is sent
- */
-
- if (c >= 4*WAKEUP_CHARS)
- c = c/2;
-
- if (c <= 0) {
- /* our job here is done, don't schedule any new DMA transfer */
- info->tr_running = 0;
-
-#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_FAST_TIMER)
- if (info->rs485.flags & SER_RS485_ENABLED) {
- /* Set a short timer to toggle RTS */
- start_one_shot_timer(&fast_timers_rs485[info->line],
- rs485_toggle_rts_timer_function,
- (unsigned long)info,
- info->char_time_usec*2,
- "RS-485");
- }
-#endif /* RS485 */
- return;
- }
-
- /* ok we can schedule a dma send of c chars starting at info->xmit.tail */
- /* set up the descriptor correctly for output */
- DFLOW(DEBUG_LOG(info->line, "TX %i\n", c));
- descr->ctrl = d_int | d_eol | d_wait; /* Wait needed for tty_wait_until_sent() */
- descr->sw_len = c;
- descr->buf = virt_to_phys(info->xmit.buf + info->xmit.tail);
- descr->status = 0;
-
- *info->ofirstadr = virt_to_phys(descr); /* write to R_DMAx_FIRST */
- *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
-
- /* DMA is now running (hopefully) */
-} /* transmit_chars_dma */
-
-static void
-start_transmit(struct e100_serial *info)
-{
-#if 0
- if (info->line == SERIAL_DEBUG_LINE)
- printk("x\n");
-#endif
-
- info->tr_descr.sw_len = 0;
- info->tr_descr.hw_len = 0;
- info->tr_descr.status = 0;
- info->tr_running = 1;
- if (info->uses_dma_out)
- transmit_chars_dma(info);
- else
- e100_enable_serial_tx_ready_irq(info);
-} /* start_transmit */
-
-#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
-static int serial_fast_timer_started = 0;
-static int serial_fast_timer_expired = 0;
-static void flush_timeout_function(unsigned long data);
-#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\
- unsigned long timer_flags; \
- local_irq_save(timer_flags); \
- if (fast_timers[info->line].function == NULL) { \
- serial_fast_timer_started++; \
- TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \
- TIMERD(DEBUG_LOG(info->line, "num started: %i\n", serial_fast_timer_started)); \
- start_one_shot_timer(&fast_timers[info->line], \
- flush_timeout_function, \
- (unsigned long)info, \
- (usec), \
- string); \
- } \
- else { \
- TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \
- } \
- local_irq_restore(timer_flags); \
-}
-#define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec)
-
-#else
-#define START_FLUSH_FAST_TIMER_TIME(info, string, usec)
-#define START_FLUSH_FAST_TIMER(info, string)
-#endif
-
-static struct etrax_recv_buffer *
-alloc_recv_buffer(unsigned int size)
-{
- struct etrax_recv_buffer *buffer;
-
- if (!(buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC)))
- return NULL;
-
- buffer->next = NULL;
- buffer->length = 0;
- buffer->error = TTY_NORMAL;
-
- return buffer;
-}
-
-static void
-append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer)
-{
- unsigned long flags;
-
- local_irq_save(flags);
-
- if (!info->first_recv_buffer)
- info->first_recv_buffer = buffer;
- else
- info->last_recv_buffer->next = buffer;
-
- info->last_recv_buffer = buffer;
-
- info->recv_cnt += buffer->length;
- if (info->recv_cnt > info->max_recv_cnt)
- info->max_recv_cnt = info->recv_cnt;
-
- local_irq_restore(flags);
-}
-
-static int
-add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char flag)
-{
- struct etrax_recv_buffer *buffer;
- if (info->uses_dma_in) {
- if (!(buffer = alloc_recv_buffer(4)))
- return 0;
-
- buffer->length = 1;
- buffer->error = flag;
- buffer->buffer[0] = data;
-
- append_recv_buffer(info, buffer);
-
- info->icount.rx++;
- } else {
- struct tty_struct *tty = info->port.tty;
- tty_insert_flip_char(tty, data, flag);
- info->icount.rx++;
- }
-
- return 1;
-}
-
-static unsigned int handle_descr_data(struct e100_serial *info,
- struct etrax_dma_descr *descr,
- unsigned int recvl)
-{
- struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer;
-
- if (info->recv_cnt + recvl > 65536) {
- printk(KERN_CRIT
- "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __func__, recvl);
- return 0;
- }
-
- buffer->length = recvl;
-
- if (info->errorcode == ERRCODE_SET_BREAK)
- buffer->error = TTY_BREAK;
- info->errorcode = 0;
-
- append_recv_buffer(info, buffer);
-
- if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
- panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
-
- descr->buf = virt_to_phys(buffer->buffer);
-
- return recvl;
-}
-
-static unsigned int handle_all_descr_data(struct e100_serial *info)
-{
- struct etrax_dma_descr *descr;
- unsigned int recvl;
- unsigned int ret = 0;
-
- while (1)
- {
- descr = &info->rec_descr[info->cur_rec_descr];
-
- if (descr == phys_to_virt(*info->idescradr))
- break;
-
- if (++info->cur_rec_descr == SERIAL_RECV_DESCRIPTORS)
- info->cur_rec_descr = 0;
-
- /* find out how many bytes were read */
-
- /* if the eop bit was not set, all data has been received */
- if (!(descr->status & d_eop)) {
- recvl = descr->sw_len;
- } else {
- /* otherwise we find the amount of data received here */
- recvl = descr->hw_len;
- }
-
- /* Reset the status information */
- descr->status = 0;
-
- DFLOW( DEBUG_LOG(info->line, "RX %lu\n", recvl);
- if (info->port.tty->stopped) {
- unsigned char *buf = phys_to_virt(descr->buf);
- DEBUG_LOG(info->line, "rx 0x%02X\n", buf[0]);
- DEBUG_LOG(info->line, "rx 0x%02X\n", buf[1]);
- DEBUG_LOG(info->line, "rx 0x%02X\n", buf[2]);
- }
- );
-
- /* update stats */
- info->icount.rx += recvl;
-
- ret += handle_descr_data(info, descr, recvl);
- }
-
- return ret;
-}
-
-static void receive_chars_dma(struct e100_serial *info)
-{
- struct tty_struct *tty;
- unsigned char rstat;
-
-#ifdef CONFIG_SVINTO_SIM
- /* No receive in the simulator. Will probably be when the rest of
- * the serial interface works, and this piece will just be removed.
- */
- return;
-#endif
-
- /* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
- *info->iclrintradr =
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
-
- tty = info->port.tty;
- if (!tty) /* Something wrong... */
- return;
-
-#ifdef SERIAL_HANDLE_EARLY_ERRORS
- if (info->uses_dma_in)
- e100_enable_serial_data_irq(info);
-#endif
-
- if (info->errorcode == ERRCODE_INSERT_BREAK)
- add_char_and_flag(info, '\0', TTY_BREAK);
-
- handle_all_descr_data(info);
-
- /* Read the status register to detect errors */
- rstat = info->ioport[REG_STATUS];
- if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) {
- DFLOW(DEBUG_LOG(info->line, "XOFF detect stat %x\n", rstat));
- }
-
- if (rstat & SER_ERROR_MASK) {
- /* If we got an error, we must reset it by reading the
- * data_in field
- */
- unsigned char data = info->ioport[REG_DATA];
-
- PROCSTAT(ser_stat[info->line].errors_cnt++);
- DEBUG_LOG(info->line, "#dERR: s d 0x%04X\n",
- ((rstat & SER_ERROR_MASK) << 8) | data);
-
- if (rstat & SER_PAR_ERR_MASK)
- add_char_and_flag(info, data, TTY_PARITY);
- else if (rstat & SER_OVERRUN_MASK)
- add_char_and_flag(info, data, TTY_OVERRUN);
- else if (rstat & SER_FRAMING_ERR_MASK)
- add_char_and_flag(info, data, TTY_FRAME);
- }
-
- START_FLUSH_FAST_TIMER(info, "receive_chars");
-
- /* Restart the receiving DMA */
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
-}
-
-static int start_recv_dma(struct e100_serial *info)
-{
- struct etrax_dma_descr *descr = info->rec_descr;
- struct etrax_recv_buffer *buffer;
- int i;
-
- /* Set up the receiving descriptors */
- for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
- if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
- panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
-
- descr[i].ctrl = d_int;
- descr[i].buf = virt_to_phys(buffer->buffer);
- descr[i].sw_len = SERIAL_DESCR_BUF_SIZE;
- descr[i].hw_len = 0;
- descr[i].status = 0;
- descr[i].next = virt_to_phys(&descr[i+1]);
- }
-
- /* Link the last descriptor to the first */
- descr[i-1].next = virt_to_phys(&descr[0]);
-
- /* Start with the first descriptor in the list */
- info->cur_rec_descr = 0;
-
- /* Start the DMA */
- *info->ifirstadr = virt_to_phys(&descr[info->cur_rec_descr]);
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
-
- /* Input DMA should be running now */
- return 1;
-}
-
-static void
-start_receive(struct e100_serial *info)
-{
-#ifdef CONFIG_SVINTO_SIM
- /* No receive in the simulator. Will probably be when the rest of
- * the serial interface works, and this piece will just be removed.
- */
- return;
-#endif
- if (info->uses_dma_in) {
- /* reset the input dma channel to be sure it works */
-
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
- while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
-
- start_recv_dma(info);
- }
-}
-
-
-/* the bits in the MASK2 register are laid out like this:
- DMAI_EOP DMAI_DESCR DMAO_EOP DMAO_DESCR
- where I is the input channel and O is the output channel for the port.
- info->irq is the bit number for the DMAO_DESCR so to check the others we
- shift info->irq to the left.
-*/
-
-/* dma output channel interrupt handler
- this interrupt is called from DMA2(ser2), DMA4(ser3), DMA6(ser0) or
- DMA8(ser1) when they have finished a descriptor with the intr flag set.
-*/
-
-static irqreturn_t
-tr_interrupt(int irq, void *dev_id)
-{
- struct e100_serial *info;
- unsigned long ireg;
- int i;
- int handled = 0;
-
-#ifdef CONFIG_SVINTO_SIM
- /* No receive in the simulator. Will probably be when the rest of
- * the serial interface works, and this piece will just be removed.
- */
- {
- const char *s = "What? tr_interrupt in simulator??\n";
- SIMCOUT(s,strlen(s));
- }
- return IRQ_HANDLED;
-#endif
-
- /* find out the line that caused this irq and get it from rs_table */
-
- ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
-
- for (i = 0; i < NR_PORTS; i++) {
- info = rs_table + i;
- if (!info->enabled || !info->uses_dma_out)
- continue;
- /* check for dma_descr (don't need to check for dma_eop in output dma for serial */
- if (ireg & info->irq) {
- handled = 1;
- /* we can send a new dma bunch. make it so. */
- DINTR2(DEBUG_LOG(info->line, "tr_interrupt %i\n", i));
- /* Read jiffies_usec first,
- * we want this time to be as late as possible
- */
- PROCSTAT(ser_stat[info->line].tx_dma_ints++);
- info->last_tx_active_usec = GET_JIFFIES_USEC();
- info->last_tx_active = jiffies;
- transmit_chars_dma(info);
- }
-
- /* FIXME: here we should really check for a change in the
- status lines and if so call status_handle(info) */
- }
- return IRQ_RETVAL(handled);
-} /* tr_interrupt */
-
-/* dma input channel interrupt handler */
-
-static irqreturn_t
-rec_interrupt(int irq, void *dev_id)
-{
- struct e100_serial *info;
- unsigned long ireg;
- int i;
- int handled = 0;
-
-#ifdef CONFIG_SVINTO_SIM
- /* No receive in the simulator. Will probably be when the rest of
- * the serial interface works, and this piece will just be removed.
- */
- {
- const char *s = "What? rec_interrupt in simulator??\n";
- SIMCOUT(s,strlen(s));
- }
- return IRQ_HANDLED;
-#endif
-
- /* find out the line that caused this irq and get it from rs_table */
-
- ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
-
- for (i = 0; i < NR_PORTS; i++) {
- info = rs_table + i;
- if (!info->enabled || !info->uses_dma_in)
- continue;
- /* check for both dma_eop and dma_descr for the input dma channel */
- if (ireg & ((info->irq << 2) | (info->irq << 3))) {
- handled = 1;
- /* we have received something */
- receive_chars_dma(info);
- }
-
- /* FIXME: here we should really check for a change in the
- status lines and if so call status_handle(info) */
- }
- return IRQ_RETVAL(handled);
-} /* rec_interrupt */
-
-static int force_eop_if_needed(struct e100_serial *info)
-{
- /* We check data_avail bit to determine if data has
- * arrived since last time
- */
- unsigned char rstat = info->ioport[REG_STATUS];
-
- /* error or datavail? */
- if (rstat & SER_ERROR_MASK) {
- /* Some error has occurred. If there has been valid data, an
- * EOP interrupt will be made automatically. If no data, the
- * normal ser_interrupt should be enabled and handle it.
- * So do nothing!
- */
- DEBUG_LOG(info->line, "timeout err: rstat 0x%03X\n",
- rstat | (info->line << 8));
- return 0;
- }
-
- if (rstat & SER_DATA_AVAIL_MASK) {
- /* Ok data, no error, count it */
- TIMERD(DEBUG_LOG(info->line, "timeout: rstat 0x%03X\n",
- rstat | (info->line << 8)));
- /* Read data to clear status flags */
- (void)info->ioport[REG_DATA];
-
- info->forced_eop = 0;
- START_FLUSH_FAST_TIMER(info, "magic");
- return 0;
- }
-
- /* hit the timeout, force an EOP for the input
- * dma channel if we haven't already
- */
- if (!info->forced_eop) {
- info->forced_eop = 1;
- PROCSTAT(ser_stat[info->line].timeout_flush_cnt++);
- TIMERD(DEBUG_LOG(info->line, "timeout EOP %i\n", info->line));
- FORCE_EOP(info);
- }
-
- return 1;
-}
-
-static void flush_to_flip_buffer(struct e100_serial *info)
-{
- struct tty_struct *tty;
- struct etrax_recv_buffer *buffer;
- unsigned long flags;
-
- local_irq_save(flags);
- tty = info->port.tty;
-
- if (!tty) {
- local_irq_restore(flags);
- return;
- }
-
- while ((buffer = info->first_recv_buffer) != NULL) {
- unsigned int count = buffer->length;
-
- tty_insert_flip_string(tty, buffer->buffer, count);
- info->recv_cnt -= count;
-
- if (count == buffer->length) {
- info->first_recv_buffer = buffer->next;
- kfree(buffer);
- } else {
- buffer->length -= count;
- memmove(buffer->buffer, buffer->buffer + count, buffer->length);
- buffer->error = TTY_NORMAL;
- }
- }
-
- if (!info->first_recv_buffer)
- info->last_recv_buffer = NULL;
-
- local_irq_restore(flags);
-
- /* This includes a check for low-latency */
- tty_flip_buffer_push(tty);
-}
-
-static void check_flush_timeout(struct e100_serial *info)
-{
- /* Flip what we've got (if we can) */
- flush_to_flip_buffer(info);
-
- /* We might need to flip later, but not to fast
- * since the system is busy processing input... */
- if (info->first_recv_buffer)
- START_FLUSH_FAST_TIMER_TIME(info, "flip", 2000);
-
- /* Force eop last, since data might have come while we're processing
- * and if we started the slow timer above, we won't start a fast
- * below.
- */
- force_eop_if_needed(info);
-}
-
-#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
-static void flush_timeout_function(unsigned long data)
-{
- struct e100_serial *info = (struct e100_serial *)data;
-
- fast_timers[info->line].function = NULL;
- serial_fast_timer_expired++;
- TIMERD(DEBUG_LOG(info->line, "flush_timout %i ", info->line));
- TIMERD(DEBUG_LOG(info->line, "num expired: %i\n", serial_fast_timer_expired));
- check_flush_timeout(info);
-}
-
-#else
-
-/* dma fifo/buffer timeout handler
- forces an end-of-packet for the dma input channel if no chars
- have been received for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS/100 s.
-*/
-
-static struct timer_list flush_timer;
-
-static void
-timed_flush_handler(unsigned long ptr)
-{
- struct e100_serial *info;
- int i;
-
-#ifdef CONFIG_SVINTO_SIM
- return;
-#endif
-
- for (i = 0; i < NR_PORTS; i++) {
- info = rs_table + i;
- if (info->uses_dma_in)
- check_flush_timeout(info);
- }
-
- /* restart flush timer */
- mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
-}
-#endif
-
-#ifdef SERIAL_HANDLE_EARLY_ERRORS
-
-/* If there is an error (ie break) when the DMA is running and
- * there are no bytes in the fifo the DMA is stopped and we get no
- * eop interrupt. Thus we have to monitor the first bytes on a DMA
- * transfer, and if it is without error we can turn the serial
- * interrupts off.
- */
-
-/*
-BREAK handling on ETRAX 100:
-ETRAX will generate interrupt although there is no stop bit between the
-characters.
-
-Depending on how long the break sequence is, the end of the breaksequence
-will look differently:
-| indicates start/end of a character.
-
-B= Break character (0x00) with framing error.
-E= Error byte with parity error received after B characters.
-F= "Faked" valid byte received immediately after B characters.
-V= Valid byte
-
-1.
- B BL ___________________________ V
-.._|__________|__________| |valid data |
-
-Multiple frame errors with data == 0x00 (B),
-the timing matches up "perfectly" so no extra ending char is detected.
-The RXD pin is 1 in the last interrupt, in that case
-we set info->errorcode = ERRCODE_INSERT_BREAK, but we can't really
-know if another byte will come and this really is case 2. below
-(e.g F=0xFF or 0xFE)
-If RXD pin is 0 we can expect another character (see 2. below).
-
-
-2.
-
- B B E or F__________________..__ V
-.._|__________|__________|______ | |valid data
- "valid" or
- parity error
-
-Multiple frame errors with data == 0x00 (B),
-but the part of the break trigs is interpreted as a start bit (and possibly
-some 0 bits followed by a number of 1 bits and a stop bit).
-Depending on parity settings etc. this last character can be either
-a fake "valid" char (F) or have a parity error (E).
-
-If the character is valid it will be put in the buffer,
-we set info->errorcode = ERRCODE_SET_BREAK so the receive interrupt
-will set the flags so the tty will handle it,
-if it's an error byte it will not be put in the buffer
-and we set info->errorcode = ERRCODE_INSERT_BREAK.
-
-To distinguish a V byte in 1. from an F byte in 2. we keep a timestamp
-of the last faulty char (B) and compares it with the current time:
-If the time elapsed time is less then 2*char_time_usec we will assume
-it's a faked F char and not a Valid char and set
-info->errorcode = ERRCODE_SET_BREAK.
-
-Flaws in the above solution:
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We use the timer to distinguish a F character from a V character,
-if a V character is to close after the break we might make the wrong decision.
-
-TODO: The break will be delayed until an F or V character is received.
-
-*/
-
-static
-struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
-{
- unsigned long data_read;
- struct tty_struct *tty = info->port.tty;
-
- if (!tty) {
- printk("!NO TTY!\n");
- return info;
- }
-
- /* Read data and status at the same time */
- data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]);
-more_data:
- if (data_read & IO_MASK(R_SERIAL0_READ, xoff_detect) ) {
- DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0));
- }
- DINTR2(DEBUG_LOG(info->line, "ser_rx %c\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read)));
-
- if (data_read & ( IO_MASK(R_SERIAL0_READ, framing_err) |
- IO_MASK(R_SERIAL0_READ, par_err) |
- IO_MASK(R_SERIAL0_READ, overrun) )) {
- /* An error */
- info->last_rx_active_usec = GET_JIFFIES_USEC();
- info->last_rx_active = jiffies;
- DINTR1(DEBUG_LOG(info->line, "ser_rx err stat_data %04X\n", data_read));
- DLOG_INT_TRIG(
- if (!log_int_trig1_pos) {
- log_int_trig1_pos = log_int_pos;
- log_int(rdpc(), 0, 0);
- }
- );
-
-
- if ( ((data_read & IO_MASK(R_SERIAL0_READ, data_in)) == 0) &&
- (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) ) {
- /* Most likely a break, but we get interrupts over and
- * over again.
- */
-
- if (!info->break_detected_cnt) {
- DEBUG_LOG(info->line, "#BRK start\n", 0);
- }
- if (data_read & IO_MASK(R_SERIAL0_READ, rxd)) {
- /* The RX pin is high now, so the break
- * must be over, but....
- * we can't really know if we will get another
- * last byte ending the break or not.
- * And we don't know if the byte (if any) will
- * have an error or look valid.
- */
- DEBUG_LOG(info->line, "# BL BRK\n", 0);
- info->errorcode = ERRCODE_INSERT_BREAK;
- }
- info->break_detected_cnt++;
- } else {
- /* The error does not look like a break, but could be
- * the end of one
- */
- if (info->break_detected_cnt) {
- DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt);
- info->errorcode = ERRCODE_INSERT_BREAK;
- } else {
- unsigned char data = IO_EXTRACT(R_SERIAL0_READ,
- data_in, data_read);
- char flag = TTY_NORMAL;
- if (info->errorcode == ERRCODE_INSERT_BREAK) {
- struct tty_struct *tty = info->port.tty;
- tty_insert_flip_char(tty, 0, flag);
- info->icount.rx++;
- }
-
- if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) {
- info->icount.parity++;
- flag = TTY_PARITY;
- } else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) {
- info->icount.overrun++;
- flag = TTY_OVERRUN;
- } else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) {
- info->icount.frame++;
- flag = TTY_FRAME;
- }
- tty_insert_flip_char(tty, data, flag);
- info->errorcode = 0;
- }
- info->break_detected_cnt = 0;
- }
- } else if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) {
- /* No error */
- DLOG_INT_TRIG(
- if (!log_int_trig1_pos) {
- if (log_int_pos >= log_int_size) {
- log_int_pos = 0;
- }
- log_int_trig0_pos = log_int_pos;
- log_int(rdpc(), 0, 0);
- }
- );
- tty_insert_flip_char(tty,
- IO_EXTRACT(R_SERIAL0_READ, data_in, data_read),
- TTY_NORMAL);
- } else {
- DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read);
- }
-
-
- info->icount.rx++;
- data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]);
- if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) {
- DEBUG_LOG(info->line, "ser_rx %c in loop\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read));
- goto more_data;
- }
-
- tty_flip_buffer_push(info->port.tty);
- return info;
-}
-
-static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
-{
- unsigned char rstat;
-
-#ifdef SERIAL_DEBUG_INTR
- printk("Interrupt from serport %d\n", i);
-#endif
-/* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */
- if (!info->uses_dma_in) {
- return handle_ser_rx_interrupt_no_dma(info);
- }
- /* DMA is used */
- rstat = info->ioport[REG_STATUS];
- if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) {
- DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0));
- }
-
- if (rstat & SER_ERROR_MASK) {
- unsigned char data;
-
- info->last_rx_active_usec = GET_JIFFIES_USEC();
- info->last_rx_active = jiffies;
- /* If we got an error, we must reset it by reading the
- * data_in field
- */
- data = info->ioport[REG_DATA];
- DINTR1(DEBUG_LOG(info->line, "ser_rx! %c\n", data));
- DINTR1(DEBUG_LOG(info->line, "ser_rx err stat %02X\n", rstat));
- if (!data && (rstat & SER_FRAMING_ERR_MASK)) {
- /* Most likely a break, but we get interrupts over and
- * over again.
- */
-
- if (!info->break_detected_cnt) {
- DEBUG_LOG(info->line, "#BRK start\n", 0);
- }
- if (rstat & SER_RXD_MASK) {
- /* The RX pin is high now, so the break
- * must be over, but....
- * we can't really know if we will get another
- * last byte ending the break or not.
- * And we don't know if the byte (if any) will
- * have an error or look valid.
- */
- DEBUG_LOG(info->line, "# BL BRK\n", 0);
- info->errorcode = ERRCODE_INSERT_BREAK;
- }
- info->break_detected_cnt++;
- } else {
- /* The error does not look like a break, but could be
- * the end of one
- */
- if (info->break_detected_cnt) {
- DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt);
- info->errorcode = ERRCODE_INSERT_BREAK;
- } else {
- if (info->errorcode == ERRCODE_INSERT_BREAK) {
- info->icount.brk++;
- add_char_and_flag(info, '\0', TTY_BREAK);
- }
-
- if (rstat & SER_PAR_ERR_MASK) {
- info->icount.parity++;
- add_char_and_flag(info, data, TTY_PARITY);
- } else if (rstat & SER_OVERRUN_MASK) {
- info->icount.overrun++;
- add_char_and_flag(info, data, TTY_OVERRUN);
- } else if (rstat & SER_FRAMING_ERR_MASK) {
- info->icount.frame++;
- add_char_and_flag(info, data, TTY_FRAME);
- }
-
- info->errorcode = 0;
- }
- info->break_detected_cnt = 0;
- DEBUG_LOG(info->line, "#iERR s d %04X\n",
- ((rstat & SER_ERROR_MASK) << 8) | data);
- }
- PROCSTAT(ser_stat[info->line].early_errors_cnt++);
- } else { /* It was a valid byte, now let the DMA do the rest */
- unsigned long curr_time_u = GET_JIFFIES_USEC();
- unsigned long curr_time = jiffies;
-
- if (info->break_detected_cnt) {
- /* Detect if this character is a new valid char or the
- * last char in a break sequence: If LSBits are 0 and
- * MSBits are high AND the time is close to the
- * previous interrupt we should discard it.
- */
- long elapsed_usec =
- (curr_time - info->last_rx_active) * (1000000/HZ) +
- curr_time_u - info->last_rx_active_usec;
- if (elapsed_usec < 2*info->char_time_usec) {
- DEBUG_LOG(info->line, "FBRK %i\n", info->line);
- /* Report as BREAK (error) and let
- * receive_chars_dma() handle it
- */
- info->errorcode = ERRCODE_SET_BREAK;
- } else {
- DEBUG_LOG(info->line, "Not end of BRK (V)%i\n", info->line);
- }
- DEBUG_LOG(info->line, "num brk %i\n", info->break_detected_cnt);
- }
-
-#ifdef SERIAL_DEBUG_INTR
- printk("** OK, disabling ser_interrupts\n");
-#endif
- e100_disable_serial_data_irq(info);
- DINTR2(DEBUG_LOG(info->line, "ser_rx OK %d\n", info->line));
- info->break_detected_cnt = 0;
-
- PROCSTAT(ser_stat[info->line].ser_ints_ok_cnt++);
- }
- /* Restarting the DMA never hurts */
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
- START_FLUSH_FAST_TIMER(info, "ser_int");
- return info;
-} /* handle_ser_rx_interrupt */
-
-static void handle_ser_tx_interrupt(struct e100_serial *info)
-{
- unsigned long flags;
-
- if (info->x_char) {
- unsigned char rstat;
- DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char));
- local_irq_save(flags);
- rstat = info->ioport[REG_STATUS];
- DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
-
- info->ioport[REG_TR_DATA] = info->x_char;
- info->icount.tx++;
- info->x_char = 0;
- /* We must enable since it is disabled in ser_interrupt */
- e100_enable_serial_tx_ready_irq(info);
- local_irq_restore(flags);
- return;
- }
- if (info->uses_dma_out) {
- unsigned char rstat;
- int i;
- /* We only use normal tx interrupt when sending x_char */
- DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0));
- local_irq_save(flags);
- rstat = info->ioport[REG_STATUS];
- DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
- e100_disable_serial_tx_ready_irq(info);
- if (info->port.tty->stopped)
- rs_stop(info->port.tty);
- /* Enable the DMA channel and tell it to continue */
- e100_enable_txdma_channel(info);
- /* Wait 12 cycles before doing the DMA command */
- for(i = 6; i > 0; i--)
- nop();
-
- *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue);
- local_irq_restore(flags);
- return;
- }
- /* Normal char-by-char interrupt */
- if (info->xmit.head == info->xmit.tail
- || info->port.tty->stopped
- || info->port.tty->hw_stopped) {
- DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n",
- info->port.tty->stopped));
- e100_disable_serial_tx_ready_irq(info);
- info->tr_running = 0;
- return;
- }
- DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail]));
- /* Send a byte, rs485 timing is critical so turn of ints */
- local_irq_save(flags);
- info->ioport[REG_TR_DATA] = info->xmit.buf[info->xmit.tail];
- info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1);
- info->icount.tx++;
- if (info->xmit.head == info->xmit.tail) {
-#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_FAST_TIMER)
- if (info->rs485.flags & SER_RS485_ENABLED) {
- /* Set a short timer to toggle RTS */
- start_one_shot_timer(&fast_timers_rs485[info->line],
- rs485_toggle_rts_timer_function,
- (unsigned long)info,
- info->char_time_usec*2,
- "RS-485");
- }
-#endif /* RS485 */
- info->last_tx_active_usec = GET_JIFFIES_USEC();
- info->last_tx_active = jiffies;
- e100_disable_serial_tx_ready_irq(info);
- info->tr_running = 0;
- DFLOW(DEBUG_LOG(info->line, "tx_int: stop2\n", 0));
- } else {
- /* We must enable since it is disabled in ser_interrupt */
- e100_enable_serial_tx_ready_irq(info);
- }
- local_irq_restore(flags);
-
- if (CIRC_CNT(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
- rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-
-} /* handle_ser_tx_interrupt */
-
-/* result of time measurements:
- * RX duration 54-60 us when doing something, otherwise 6-9 us
- * ser_int duration: just sending: 8-15 us normally, up to 73 us
- */
-static irqreturn_t
-ser_interrupt(int irq, void *dev_id)
-{
- static volatile int tx_started = 0;
- struct e100_serial *info;
- int i;
- unsigned long flags;
- unsigned long irq_mask1_rd;
- unsigned long data_mask = (1 << (8+2*0)); /* ser0 data_avail */
- int handled = 0;
- static volatile unsigned long reentered_ready_mask = 0;
-
- local_irq_save(flags);
- irq_mask1_rd = *R_IRQ_MASK1_RD;
- /* First handle all rx interrupts with ints disabled */
- info = rs_table;
- irq_mask1_rd &= e100_ser_int_mask;
- for (i = 0; i < NR_PORTS; i++) {
- /* Which line caused the data irq? */
- if (irq_mask1_rd & data_mask) {
- handled = 1;
- handle_ser_rx_interrupt(info);
- }
- info += 1;
- data_mask <<= 2;
- }
- /* Handle tx interrupts with interrupts enabled so we
- * can take care of new data interrupts while transmitting
- * We protect the tx part with the tx_started flag.
- * We disable the tr_ready interrupts we are about to handle and
- * unblock the serial interrupt so new serial interrupts may come.
- *
- * If we get a new interrupt:
- * - it migth be due to synchronous serial ports.
- * - serial irq will be blocked by general irq handler.
- * - async data will be handled above (sync will be ignored).
- * - tx_started flag will prevent us from trying to send again and
- * we will exit fast - no need to unblock serial irq.
- * - Next (sync) serial interrupt handler will be runned with
- * disabled interrupt due to restore_flags() at end of function,
- * so sync handler will not be preempted or reentered.
- */
- if (!tx_started) {
- unsigned long ready_mask;
- unsigned long
- tx_started = 1;
- /* Only the tr_ready interrupts left */
- irq_mask1_rd &= (IO_MASK(R_IRQ_MASK1_RD, ser0_ready) |
- IO_MASK(R_IRQ_MASK1_RD, ser1_ready) |
- IO_MASK(R_IRQ_MASK1_RD, ser2_ready) |
- IO_MASK(R_IRQ_MASK1_RD, ser3_ready));
- while (irq_mask1_rd) {
- /* Disable those we are about to handle */
- *R_IRQ_MASK1_CLR = irq_mask1_rd;
- /* Unblock the serial interrupt */
- *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set);
-
- local_irq_enable();
- ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */
- info = rs_table;
- for (i = 0; i < NR_PORTS; i++) {
- /* Which line caused the ready irq? */
- if (irq_mask1_rd & ready_mask) {
- handled = 1;
- handle_ser_tx_interrupt(info);
- }
- info += 1;
- ready_mask <<= 2;
- }
- /* handle_ser_tx_interrupt enables tr_ready interrupts */
- local_irq_disable();
- /* Handle reentered TX interrupt */
- irq_mask1_rd = reentered_ready_mask;
- }
- local_irq_disable();
- tx_started = 0;
- } else {
- unsigned long ready_mask;
- ready_mask = irq_mask1_rd & (IO_MASK(R_IRQ_MASK1_RD, ser0_ready) |
- IO_MASK(R_IRQ_MASK1_RD, ser1_ready) |
- IO_MASK(R_IRQ_MASK1_RD, ser2_ready) |
- IO_MASK(R_IRQ_MASK1_RD, ser3_ready));
- if (ready_mask) {
- reentered_ready_mask |= ready_mask;
- /* Disable those we are about to handle */
- *R_IRQ_MASK1_CLR = ready_mask;
- DFLOW(DEBUG_LOG(SERIAL_DEBUG_LINE, "ser_int reentered with TX %X\n", ready_mask));
- }
- }
-
- local_irq_restore(flags);
- return IRQ_RETVAL(handled);
-} /* ser_interrupt */
-#endif
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using rs_sched_event(), and they get done here.
- */
-static void
-do_softint(struct work_struct *work)
-{
- struct e100_serial *info;
- struct tty_struct *tty;
-
- info = container_of(work, struct e100_serial, work);
-
- tty = info->port.tty;
- if (!tty)
- return;
-
- if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
- tty_wakeup(tty);
-}
-
-static int
-startup(struct e100_serial * info)
-{
- unsigned long flags;
- unsigned long xmit_page;
- int i;
-
- xmit_page = get_zeroed_page(GFP_KERNEL);
- if (!xmit_page)
- return -ENOMEM;
-
- local_irq_save(flags);
-
- /* if it was already initialized, skip this */
-
- if (info->flags & ASYNC_INITIALIZED) {
- local_irq_restore(flags);
- free_page(xmit_page);
- return 0;
- }
-
- if (info->xmit.buf)
- free_page(xmit_page);
- else
- info->xmit.buf = (unsigned char *) xmit_page;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf);
-#endif
-
-#ifdef CONFIG_SVINTO_SIM
- /* Bits and pieces collected from below. Better to have them
- in one ifdef:ed clause than to mix in a lot of ifdefs,
- right? */
- if (info->port.tty)
- clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- info->xmit.head = info->xmit.tail = 0;
- info->first_recv_buffer = info->last_recv_buffer = NULL;
- info->recv_cnt = info->max_recv_cnt = 0;
-
- for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
- info->rec_descr[i].buf = NULL;
-
- /* No real action in the simulator, but may set info important
- to ioctl. */
- change_speed(info);
-#else
-
- /*
- * Clear the FIFO buffers and disable them
- * (they will be reenabled in change_speed())
- */
-
- /*
- * Reset the DMA channels and make sure their interrupts are cleared
- */
-
- if (info->dma_in_enabled) {
- info->uses_dma_in = 1;
- e100_enable_rxdma_channel(info);
-
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
-
- /* Wait until reset cycle is complete */
- while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
-
- /* Make sure the irqs are cleared */
- *info->iclrintradr =
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
- } else {
- e100_disable_rxdma_channel(info);
- }
-
- if (info->dma_out_enabled) {
- info->uses_dma_out = 1;
- e100_enable_txdma_channel(info);
- *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
-
- while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
-
- /* Make sure the irqs are cleared */
- *info->oclrintradr =
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
- IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
- } else {
- e100_disable_txdma_channel(info);
- }
-
- if (info->port.tty)
- clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- info->xmit.head = info->xmit.tail = 0;
- info->first_recv_buffer = info->last_recv_buffer = NULL;
- info->recv_cnt = info->max_recv_cnt = 0;
-
- for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
- info->rec_descr[i].buf = 0;
-
- /*
- * and set the speed and other flags of the serial port
- * this will start the rx/tx as well
- */
-#ifdef SERIAL_HANDLE_EARLY_ERRORS
- e100_enable_serial_data_irq(info);
-#endif
- change_speed(info);
-
- /* dummy read to reset any serial errors */
-
- (void)info->ioport[REG_DATA];
-
- /* enable the interrupts */
- if (info->uses_dma_out)
- e100_enable_txdma_irq(info);
-
- e100_enable_rx_irq(info);
-
- info->tr_running = 0; /* to be sure we don't lock up the transmitter */
-
- /* setup the dma input descriptor and start dma */
-
- start_receive(info);
-
- /* for safety, make sure the descriptors last result is 0 bytes written */
-
- info->tr_descr.sw_len = 0;
- info->tr_descr.hw_len = 0;
- info->tr_descr.status = 0;
-
- /* enable RTS/DTR last */
-
- e100_rts(info, 1);
- e100_dtr(info, 1);
-
-#endif /* CONFIG_SVINTO_SIM */
-
- info->flags |= ASYNC_INITIALIZED;
-
- local_irq_restore(flags);
- return 0;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void
-shutdown(struct e100_serial * info)
-{
- unsigned long flags;
- struct etrax_dma_descr *descr = info->rec_descr;
- struct etrax_recv_buffer *buffer;
- int i;
-
-#ifndef CONFIG_SVINTO_SIM
- /* shut down the transmitter and receiver */
- DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line));
- e100_disable_rx(info);
- info->ioport[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40);
-
- /* disable interrupts, reset dma channels */
- if (info->uses_dma_in) {
- e100_disable_rxdma_irq(info);
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
- info->uses_dma_in = 0;
- } else {
- e100_disable_serial_data_irq(info);
- }
-
- if (info->uses_dma_out) {
- e100_disable_txdma_irq(info);
- info->tr_running = 0;
- *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
- info->uses_dma_out = 0;
- } else {
- e100_disable_serial_tx_ready_irq(info);
- info->tr_running = 0;
- }
-
-#endif /* CONFIG_SVINTO_SIM */
-
- if (!(info->flags & ASYNC_INITIALIZED))
- return;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("Shutting down serial port %d (irq %d)....\n", info->line,
- info->irq);
-#endif
-
- local_irq_save(flags);
-
- if (info->xmit.buf) {
- free_page((unsigned long)info->xmit.buf);
- info->xmit.buf = NULL;
- }
-
- for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
- if (descr[i].buf) {
- buffer = phys_to_virt(descr[i].buf) - sizeof *buffer;
- kfree(buffer);
- descr[i].buf = 0;
- }
-
- if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
- /* hang up DTR and RTS if HUPCL is enabled */
- e100_dtr(info, 0);
- e100_rts(info, 0); /* could check CRTSCTS before doing this */
- }
-
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- info->flags &= ~ASYNC_INITIALIZED;
- local_irq_restore(flags);
-}
-
-
-/* change baud rate and other assorted parameters */
-
-static void
-change_speed(struct e100_serial *info)
-{
- unsigned int cflag;
- unsigned long xoff;
- unsigned long flags;
- /* first some safety checks */
-
- if (!info->port.tty || !info->port.tty->termios)
- return;
- if (!info->ioport)
- return;
-
- cflag = info->port.tty->termios->c_cflag;
-
- /* possibly, the tx/rx should be disabled first to do this safely */
-
- /* change baud-rate and write it to the hardware */
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
- /* Special baudrate */
- u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */
- unsigned long alt_source =
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, normal) |
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal);
- /* R_ALT_SER_BAUDRATE selects the source */
- DBAUD(printk("Custom baudrate: baud_base/divisor %lu/%i\n",
- (unsigned long)info->baud_base, info->custom_divisor));
- if (info->baud_base == SERIAL_PRESCALE_BASE) {
- /* 0, 2-65535 (0=65536) */
- u16 divisor = info->custom_divisor;
- /* R_SERIAL_PRESCALE (upper 16 bits of R_CLOCK_PRESCALE) */
- /* baudrate is 3.125MHz/custom_divisor */
- alt_source =
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, prescale) |
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, prescale);
- alt_source = 0x11;
- DBAUD(printk("Writing SERIAL_PRESCALE: divisor %i\n", divisor));
- *R_SERIAL_PRESCALE = divisor;
- info->baud = SERIAL_PRESCALE_BASE/divisor;
- }
-#ifdef CONFIG_ETRAX_EXTERN_PB6CLK_ENABLED
- else if ((info->baud_base==CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8 &&
- info->custom_divisor == 1) ||
- (info->baud_base==CONFIG_ETRAX_EXTERN_PB6CLK_FREQ &&
- info->custom_divisor == 8)) {
- /* ext_clk selected */
- alt_source =
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, extern) |
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, extern);
- DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8));
- info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8;
- }
-#endif
- else
- {
- /* Bad baudbase, we don't support using timer0
- * for baudrate.
- */
- printk(KERN_WARNING "Bad baud_base/custom_divisor: %lu/%i\n",
- (unsigned long)info->baud_base, info->custom_divisor);
- }
- r_alt_ser_baudrate_shadow &= ~mask;
- r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8));
- *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow;
- } else {
- /* Normal baudrate */
- /* Make sure we use normal baudrate */
- u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */
- unsigned long alt_source =
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, normal) |
- IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal);
- r_alt_ser_baudrate_shadow &= ~mask;
- r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8));
-#ifndef CONFIG_SVINTO_SIM
- *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow;
-#endif /* CONFIG_SVINTO_SIM */
-
- info->baud = cflag_to_baud(cflag);
-#ifndef CONFIG_SVINTO_SIM
- info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag);
-#endif /* CONFIG_SVINTO_SIM */
- }
-
-#ifndef CONFIG_SVINTO_SIM
- /* start with default settings and then fill in changes */
- local_irq_save(flags);
- /* 8 bit, no/even parity */
- info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) |
- IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) |
- IO_MASK(R_SERIAL0_REC_CTRL, rec_par));
-
- /* 8 bit, no/even parity, 1 stop bit, no cts */
- info->tx_ctrl &= ~(IO_MASK(R_SERIAL0_TR_CTRL, tr_bitnr) |
- IO_MASK(R_SERIAL0_TR_CTRL, tr_par_en) |
- IO_MASK(R_SERIAL0_TR_CTRL, tr_par) |
- IO_MASK(R_SERIAL0_TR_CTRL, stop_bits) |
- IO_MASK(R_SERIAL0_TR_CTRL, auto_cts));
-
- if ((cflag & CSIZE) == CS7) {
- /* set 7 bit mode */
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit);
- info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit);
- }
-
- if (cflag & CSTOPB) {
- /* set 2 stop bit mode */
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, stop_bits, two_bits);
- }
-
- if (cflag & PARENB) {
- /* enable parity */
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable);
- info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
- }
-
- if (cflag & CMSPAR) {
- /* enable stick parity, PARODD mean Mark which matches ETRAX */
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, stick);
- info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, stick);
- }
- if (cflag & PARODD) {
- /* set odd parity (or Mark if CMSPAR) */
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
- info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
- }
-
- if (cflag & CRTSCTS) {
- /* enable automatic CTS handling */
- DFLOW(DEBUG_LOG(info->line, "FLOW auto_cts enabled\n", 0));
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, active);
- }
-
- /* make sure the tx and rx are enabled */
-
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable);
- info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
-
- /* actually write the control regs to the hardware */
-
- info->ioport[REG_TR_CTRL] = info->tx_ctrl;
- info->ioport[REG_REC_CTRL] = info->rx_ctrl;
- xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty));
- xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
- if (info->port.tty->termios->c_iflag & IXON ) {
- DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n",
- STOP_CHAR(info->port.tty)));
- xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
- }
-
- *((unsigned long *)&info->ioport[REG_XOFF]) = xoff;
- local_irq_restore(flags);
-#endif /* !CONFIG_SVINTO_SIM */
-
- update_char_time(info);
-
-} /* change_speed */
-
-/* start transmitting chars NOW */
-
-static void
-rs_flush_chars(struct tty_struct *tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- if (info->tr_running ||
- info->xmit.head == info->xmit.tail ||
- tty->stopped ||
- tty->hw_stopped ||
- !info->xmit.buf)
- return;
-
-#ifdef SERIAL_DEBUG_FLOW
- printk("rs_flush_chars\n");
-#endif
-
- /* this protection might not exactly be necessary here */
-
- local_irq_save(flags);
- start_transmit(info);
- local_irq_restore(flags);
-}
-
-static int rs_raw_write(struct tty_struct *tty,
- const unsigned char *buf, int count)
-{
- int c, ret = 0;
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- /* first some sanity checks */
-
- if (!tty || !info->xmit.buf || !tmp_buf)
- return 0;
-
-#ifdef SERIAL_DEBUG_DATA
- if (info->line == SERIAL_DEBUG_LINE)
- printk("rs_raw_write (%d), status %d\n",
- count, info->ioport[REG_STATUS]);
-#endif
-
-#ifdef CONFIG_SVINTO_SIM
- /* Really simple. The output is here and now. */
- SIMCOUT(buf, count);
- return count;
-#endif
- local_save_flags(flags);
- DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
- DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
-
-
- /* The local_irq_disable/restore_flags pairs below are needed
- * because the DMA interrupt handler moves the info->xmit values.
- * the memcpy needs to be in the critical region unfortunately,
- * because we need to read xmit values, memcpy, write xmit values
- * in one atomic operation... this could perhaps be avoided by
- * more clever design.
- */
- local_irq_disable();
- while (count) {
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
-
- if (count < c)
- c = count;
- if (c <= 0)
- break;
-
- memcpy(info->xmit.buf + info->xmit.head, buf, c);
- info->xmit.head = (info->xmit.head + c) &
- (SERIAL_XMIT_SIZE-1);
- buf += c;
- count -= c;
- ret += c;
- }
- local_irq_restore(flags);
-
- /* enable transmitter if not running, unless the tty is stopped
- * this does not need IRQ protection since if tr_running == 0
- * the IRQ's are not running anyway for this port.
- */
- DFLOW(DEBUG_LOG(info->line, "write ret %i\n", ret));
-
- if (info->xmit.head != info->xmit.tail &&
- !tty->stopped &&
- !tty->hw_stopped &&
- !info->tr_running) {
- start_transmit(info);
- }
-
- return ret;
-} /* raw_raw_write() */
-
-static int
-rs_write(struct tty_struct *tty,
- const unsigned char *buf, int count)
-{
-#if defined(CONFIG_ETRAX_RS485)
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
-
- if (info->rs485.flags & SER_RS485_ENABLED)
- {
- /* If we are in RS-485 mode, we need to toggle RTS and disable
- * the receiver before initiating a DMA transfer
- */
-#ifdef CONFIG_ETRAX_FAST_TIMER
- /* Abort any started timer */
- fast_timers_rs485[info->line].function = NULL;
- del_fast_timer(&fast_timers_rs485[info->line]);
-#endif
- e100_rts(info, (info->rs485.flags & SER_RS485_RTS_ON_SEND));
-#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
- e100_disable_rx(info);
- e100_enable_rx_irq(info);
-#endif
- if ((info->rs485.flags & SER_RS485_RTS_BEFORE_SEND) &&
- (info->rs485.delay_rts_before_send > 0))
- msleep(info->rs485.delay_rts_before_send);
- }
-#endif /* CONFIG_ETRAX_RS485 */
-
- count = rs_raw_write(tty, buf, count);
-
-#if defined(CONFIG_ETRAX_RS485)
- if (info->rs485.flags & SER_RS485_ENABLED)
- {
- unsigned int val;
- /* If we are in RS-485 mode the following has to be done:
- * wait until DMA is ready
- * wait on transmit shift register
- * toggle RTS
- * enable the receiver
- */
-
- /* Sleep until all sent */
- tty_wait_until_sent(tty, 0);
-#ifdef CONFIG_ETRAX_FAST_TIMER
- /* Now sleep a little more so that shift register is empty */
- schedule_usleep(info->char_time_usec * 2);
-#endif
- /* wait on transmit shift register */
- do{
- get_lsr_info(info, &val);
- }while (!(val & TIOCSER_TEMT));
-
- e100_rts(info, (info->rs485.flags & SER_RS485_RTS_AFTER_SEND));
-
-#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
- e100_enable_rx(info);
- e100_enable_rxdma_irq(info);
-#endif
- }
-#endif /* CONFIG_ETRAX_RS485 */
-
- return count;
-} /* rs_write */
-
-
-/* how much space is available in the xmit buffer? */
-
-static int
-rs_write_room(struct tty_struct *tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
-
- return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-/* How many chars are in the xmit buffer?
- * This does not include any chars in the transmitter FIFO.
- * Use wait_until_sent for waiting for FIFO drain.
- */
-
-static int
-rs_chars_in_buffer(struct tty_struct *tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
-
- return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-/* discard everything in the xmit buffer */
-
-static void
-rs_flush_buffer(struct tty_struct *tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- local_irq_save(flags);
- info->xmit.head = info->xmit.tail = 0;
- local_irq_restore(flags);
-
- tty_wakeup(tty);
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- *
- * Since we use DMA we don't check for info->x_char in transmit_chars_dma(),
- * but we do it in handle_ser_tx_interrupt().
- * We disable DMA channel and enable tx ready interrupt and write the
- * character when possible.
- */
-static void rs_send_xchar(struct tty_struct *tty, char ch)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
- local_irq_save(flags);
- if (info->uses_dma_out) {
- /* Put the DMA on hold and disable the channel */
- *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold);
- while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) !=
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, hold));
- e100_disable_txdma_channel(info);
- }
-
- /* Must make sure transmitter is not stopped before we can transmit */
- if (tty->stopped)
- rs_start(tty);
-
- /* Enable manual transmit interrupt and send from there */
- DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch));
- info->x_char = ch;
- e100_enable_serial_tx_ready_irq(info);
- local_irq_restore(flags);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void
-rs_throttle(struct tty_struct * tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("throttle %s: %lu....\n", tty_name(tty, buf),
- (unsigned long)tty->ldisc.chars_in_buffer(tty));
-#endif
- DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty)));
-
- /* Do RTS before XOFF since XOFF might take some time */
- if (tty->termios->c_cflag & CRTSCTS) {
- /* Turn off RTS line */
- e100_rts(info, 0);
- }
- if (I_IXOFF(tty))
- rs_send_xchar(tty, STOP_CHAR(tty));
-
-}
-
-static void
-rs_unthrottle(struct tty_struct * tty)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("unthrottle %s: %lu....\n", tty_name(tty, buf),
- (unsigned long)tty->ldisc.chars_in_buffer(tty));
-#endif
- DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty)));
- DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count));
- /* Do RTS before XOFF since XOFF might take some time */
- if (tty->termios->c_cflag & CRTSCTS) {
- /* Assert RTS line */
- e100_rts(info, 1);
- }
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- rs_send_xchar(tty, START_CHAR(tty));
- }
-
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int
-get_serial_info(struct e100_serial * info,
- struct serial_struct * retinfo)
-{
- struct serial_struct tmp;
-
- /* this is all probably wrong, there are a lot of fields
- * here that we don't have in e100_serial and maybe we
- * should set them to something else than 0.
- */
-
- if (!retinfo)
- return -EFAULT;
- memset(&tmp, 0, sizeof(tmp));
- tmp.type = info->type;
- tmp.line = info->line;
- tmp.port = (int)info->ioport;
- tmp.irq = info->irq;
- tmp.flags = info->flags;
- tmp.baud_base = info->baud_base;
- tmp.close_delay = info->close_delay;
- tmp.closing_wait = info->closing_wait;
- tmp.custom_divisor = info->custom_divisor;
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
- return 0;
-}
-
-static int
-set_serial_info(struct e100_serial *info,
- struct serial_struct *new_info)
-{
- struct serial_struct new_serial;
- struct e100_serial old_info;
- int retval = 0;
-
- if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
- return -EFAULT;
-
- old_info = *info;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((new_serial.type != info->type) ||
- (new_serial.close_delay != info->close_delay) ||
- ((new_serial.flags & ~ASYNC_USR_MASK) !=
- (info->flags & ~ASYNC_USR_MASK)))
- return -EPERM;
- info->flags = ((info->flags & ~ASYNC_USR_MASK) |
- (new_serial.flags & ASYNC_USR_MASK));
- goto check_and_exit;
- }
-
- if (info->count > 1)
- return -EBUSY;
-
- /*
- * OK, past this point, all the error checking has been done.
- * At this point, we start making changes.....
- */
-
- info->baud_base = new_serial.baud_base;
- info->flags = ((info->flags & ~ASYNC_FLAGS) |
- (new_serial.flags & ASYNC_FLAGS));
- info->custom_divisor = new_serial.custom_divisor;
- info->type = new_serial.type;
- info->close_delay = new_serial.close_delay;
- info->closing_wait = new_serial.closing_wait;
- info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- check_and_exit:
- if (info->flags & ASYNC_INITIALIZED) {
- change_speed(info);
- } else
- retval = startup(info);
- return retval;
-}
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static int
-get_lsr_info(struct e100_serial * info, unsigned int *value)
-{
- unsigned int result = TIOCSER_TEMT;
-#ifndef CONFIG_SVINTO_SIM
- unsigned long curr_time = jiffies;
- unsigned long curr_time_usec = GET_JIFFIES_USEC();
- unsigned long elapsed_usec =
- (curr_time - info->last_tx_active) * 1000000/HZ +
- curr_time_usec - info->last_tx_active_usec;
-
- if (info->xmit.head != info->xmit.tail ||
- elapsed_usec < 2*info->char_time_usec) {
- result = 0;
- }
-#endif
-
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
- return 0;
-}
-
-#ifdef SERIAL_DEBUG_IO
-struct state_str
-{
- int state;
- const char *str;
-};
-
-const struct state_str control_state_str[] = {
- {TIOCM_DTR, "DTR" },
- {TIOCM_RTS, "RTS"},
- {TIOCM_ST, "ST?" },
- {TIOCM_SR, "SR?" },
- {TIOCM_CTS, "CTS" },
- {TIOCM_CD, "CD" },
- {TIOCM_RI, "RI" },
- {TIOCM_DSR, "DSR" },
- {0, NULL }
-};
-
-char *get_control_state_str(int MLines, char *s)
-{
- int i = 0;
-
- s[0]='\0';
- while (control_state_str[i].str != NULL) {
- if (MLines & control_state_str[i].state) {
- if (s[0] != '\0') {
- strcat(s, ", ");
- }
- strcat(s, control_state_str[i].str);
- }
- i++;
- }
- return s;
-}
-#endif
-
-static int
-rs_break(struct tty_struct *tty, int break_state)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- if (!info->ioport)
- return -EIO;
-
- local_irq_save(flags);
- if (break_state == -1) {
- /* Go to manual mode and set the txd pin to 0 */
- /* Clear bit 7 (txd) and 6 (tr_enable) */
- info->tx_ctrl &= 0x3F;
- } else {
- /* Set bit 7 (txd) and 6 (tr_enable) */
- info->tx_ctrl |= (0x80 | 0x40);
- }
- info->ioport[REG_TR_CTRL] = info->tx_ctrl;
- local_irq_restore(flags);
- return 0;
-}
-
-static int
-rs_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- local_irq_save(flags);
-
- if (clear & TIOCM_RTS)
- e100_rts(info, 0);
- if (clear & TIOCM_DTR)
- e100_dtr(info, 0);
- /* Handle FEMALE behaviour */
- if (clear & TIOCM_RI)
- e100_ri_out(info, 0);
- if (clear & TIOCM_CD)
- e100_cd_out(info, 0);
-
- if (set & TIOCM_RTS)
- e100_rts(info, 1);
- if (set & TIOCM_DTR)
- e100_dtr(info, 1);
- /* Handle FEMALE behaviour */
- if (set & TIOCM_RI)
- e100_ri_out(info, 1);
- if (set & TIOCM_CD)
- e100_cd_out(info, 1);
-
- local_irq_restore(flags);
- return 0;
-}
-
-static int
-rs_tiocmget(struct tty_struct *tty, struct file *file)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned int result;
- unsigned long flags;
-
- local_irq_save(flags);
-
- result =
- (!E100_RTS_GET(info) ? TIOCM_RTS : 0)
- | (!E100_DTR_GET(info) ? TIOCM_DTR : 0)
- | (!E100_RI_GET(info) ? TIOCM_RNG : 0)
- | (!E100_DSR_GET(info) ? TIOCM_DSR : 0)
- | (!E100_CD_GET(info) ? TIOCM_CAR : 0)
- | (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
-
- local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_IO
- printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n",
- info->line, result, result);
- {
- char s[100];
-
- get_control_state_str(result, s);
- printk(KERN_DEBUG "state: %s\n", s);
- }
-#endif
- return result;
-
-}
-
-
-static int
-rs_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
-
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
- (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
-
- case TIOCSERGSTRUCT:
- if (copy_to_user((struct e100_serial *) arg,
- info, sizeof(struct e100_serial)))
- return -EFAULT;
- return 0;
-
-#if defined(CONFIG_ETRAX_RS485)
- case TIOCSERSETRS485:
- {
- /* In this ioctl we still use the old structure
- * rs485_control for backward compatibility
- * (if we use serial_rs485, then old user-level code
- * wouldn't work anymore...).
- * The use of this ioctl is deprecated: use TIOCSRS485
- * instead.*/
- struct rs485_control rs485ctrl;
- struct serial_rs485 rs485data;
- printk(KERN_DEBUG "The use of this ioctl is deprecated. Use TIOCSRS485 instead\n");
- if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg,
- sizeof(rs485ctrl)))
- return -EFAULT;
-
- rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send;
- rs485data.flags = 0;
- if (rs485data.delay_rts_before_send != 0)
- rs485data.flags |= SER_RS485_RTS_BEFORE_SEND;
- else
- rs485data.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
-
- if (rs485ctrl.enabled)
- rs485data.flags |= SER_RS485_ENABLED;
- else
- rs485data.flags &= ~(SER_RS485_ENABLED);
-
- if (rs485ctrl.rts_on_send)
- rs485data.flags |= SER_RS485_RTS_ON_SEND;
- else
- rs485data.flags &= ~(SER_RS485_RTS_ON_SEND);
-
- if (rs485ctrl.rts_after_sent)
- rs485data.flags |= SER_RS485_RTS_AFTER_SEND;
- else
- rs485data.flags &= ~(SER_RS485_RTS_AFTER_SEND);
-
- return e100_enable_rs485(tty, &rs485data);
- }
-
- case TIOCSRS485:
- {
- /* This is the new version of TIOCSRS485, with new
- * data structure serial_rs485 */
- struct serial_rs485 rs485data;
- if (copy_from_user(&rs485data, (struct rs485_control *)arg,
- sizeof(rs485data)))
- return -EFAULT;
-
- return e100_enable_rs485(tty, &rs485data);
- }
-
- case TIOCGRS485:
- {
- struct serial_rs485 *rs485data =
- &(((struct e100_serial *)tty->driver_data)->rs485);
- /* This is the ioctl to get RS485 data from user-space */
- if (copy_to_user((struct serial_rs485 *) arg,
- rs485data,
- sizeof(struct serial_rs485)))
- return -EFAULT;
- break;
- }
-
- case TIOCSERWRRS485:
- {
- struct rs485_write rs485wr;
- if (copy_from_user(&rs485wr, (struct rs485_write *)arg,
- sizeof(rs485wr)))
- return -EFAULT;
-
- return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size);
- }
-#endif
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static void
-rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
-
- change_speed(info);
-
- /* Handle turning off CRTSCTS */
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- rs_start(tty);
- }
-
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * S structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void
-rs_close(struct tty_struct *tty, struct file * filp)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- if (!info)
- return;
-
- /* interrupts are disabled for this entire function */
-
- local_irq_save(flags);
-
- if (tty_hung_up_p(filp)) {
- local_irq_restore(flags);
- return;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("[%d] rs_close ttyS%d, count = %d\n", current->pid,
- info->line, info->count);
-#endif
- if ((tty->count == 1) && (info->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. Info->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk(KERN_CRIT
- "rs_close: bad serial port count; tty->count is 1, "
- "info->count is %d\n", info->count);
- info->count = 1;
- }
- if (--info->count < 0) {
- printk(KERN_CRIT "rs_close: bad serial port count for ttyS%d: %d\n",
- info->line, info->count);
- info->count = 0;
- }
- if (info->count) {
- local_irq_restore(flags);
- return;
- }
- info->flags |= ASYNC_CLOSING;
- /*
- * Save the termios structure, since this port may have
- * separate termios for callout and dialin.
- */
- if (info->flags & ASYNC_NORMAL_ACTIVE)
- info->normal_termios = *tty->termios;
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
- /*
- * At this point we stop accepting input. To do this, we
- * disable the serial receiver and the DMA receive interrupt.
- */
-#ifdef SERIAL_HANDLE_EARLY_ERRORS
- e100_disable_serial_data_irq(info);
-#endif
-
-#ifndef CONFIG_SVINTO_SIM
- e100_disable_rx(info);
- e100_disable_rx_irq(info);
-
- if (info->flags & ASYNC_INITIALIZED) {
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important as we have a transmit FIFO!
- */
- rs_wait_until_sent(tty, HZ);
- }
-#endif
-
- shutdown(info);
- rs_flush_buffer(tty);
- tty_ldisc_flush(tty);
- tty->closing = 0;
- info->event = 0;
- info->port.tty = NULL;
- if (info->blocked_open) {
- if (info->close_delay)
- schedule_timeout_interruptible(info->close_delay);
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
- local_irq_restore(flags);
-
- /* port closed */
-
-#if defined(CONFIG_ETRAX_RS485)
- if (info->rs485.flags & SER_RS485_ENABLED) {
- info->rs485.flags &= ~(SER_RS485_ENABLED);
-#if defined(CONFIG_ETRAX_RS485_ON_PA)
- *R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit);
-#endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
- REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
- rs485_port_g_bit, 0);
-#endif
-#if defined(CONFIG_ETRAX_RS485_LTC1387)
- REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
- CONFIG_ETRAX_RS485_LTC1387_DXEN_PORT_G_BIT, 0);
- REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow,
- CONFIG_ETRAX_RS485_LTC1387_RXEN_PORT_G_BIT, 0);
-#endif
- }
-#endif
-
- /*
- * Release any allocated DMA irq's.
- */
- if (info->dma_in_enabled) {
- free_irq(info->dma_in_irq_nbr, info);
- cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
- info->uses_dma_in = 0;
-#ifdef SERIAL_DEBUG_OPEN
- printk(KERN_DEBUG "DMA irq '%s' freed\n",
- info->dma_in_irq_description);
-#endif
- }
- if (info->dma_out_enabled) {
- free_irq(info->dma_out_irq_nbr, info);
- cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
- info->uses_dma_out = 0;
-#ifdef SERIAL_DEBUG_OPEN
- printk(KERN_DEBUG "DMA irq '%s' freed\n",
- info->dma_out_irq_description);
-#endif
- }
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- unsigned long orig_jiffies;
- struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- unsigned long curr_time = jiffies;
- unsigned long curr_time_usec = GET_JIFFIES_USEC();
- long elapsed_usec =
- (curr_time - info->last_tx_active) * (1000000/HZ) +
- curr_time_usec - info->last_tx_active_usec;
-
- /*
- * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
- * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
- */
- orig_jiffies = jiffies;
- while (info->xmit.head != info->xmit.tail || /* More in send queue */
- (*info->ostatusadr & 0x007f) || /* more in FIFO */
- (elapsed_usec < 2*info->char_time_usec)) {
- schedule_timeout_interruptible(1);
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
- curr_time = jiffies;
- curr_time_usec = GET_JIFFIES_USEC();
- elapsed_usec =
- (curr_time - info->last_tx_active) * (1000000/HZ) +
- curr_time_usec - info->last_tx_active_usec;
- }
- set_current_state(TASK_RUNNING);
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-void
-rs_hangup(struct tty_struct *tty)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
-
- rs_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- info->count = 0;
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- info->port.tty = NULL;
- wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int
-block_til_ready(struct tty_struct *tty, struct file * filp,
- struct e100_serial *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- int retval;
- int do_clocal = 0, extra_count = 0;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
- !(info->flags & ASYNC_CLOSING));
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (tty->termios->c_cflag & CLOCAL) {
- do_clocal = 1;
- }
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready before block: ttyS%d, count = %d\n",
- info->line, info->count);
-#endif
- local_irq_save(flags);
- if (!tty_hung_up_p(filp)) {
- extra_count++;
- info->count--;
- }
- local_irq_restore(flags);
- info->blocked_open++;
- while (1) {
- local_irq_save(flags);
- /* assert RTS and DTR */
- e100_rts(info, 1);
- e100_dtr(info, 1);
- local_irq_restore(flags);
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & ASYNC_CLOSING) && do_clocal)
- /* && (do_clocal || DCD_IS_ASSERTED) */
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready blocking: ttyS%d, count = %d\n",
- info->line, info->count);
-#endif
- tty_unlock();
- schedule();
- tty_lock();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->open_wait, &wait);
- if (extra_count)
- info->count++;
- info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready after blocking: ttyS%d, count = %d\n",
- info->line, info->count);
-#endif
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-static void
-deinit_port(struct e100_serial *info)
-{
- if (info->dma_out_enabled) {
- cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
- free_irq(info->dma_out_irq_nbr, info);
- }
- if (info->dma_in_enabled) {
- cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
- free_irq(info->dma_in_irq_nbr, info);
- }
-}
-
-/*
- * This routine is called whenever a serial port is opened.
- * It performs the serial-specific initialization for the tty structure.
- */
-static int
-rs_open(struct tty_struct *tty, struct file * filp)
-{
- struct e100_serial *info;
- int retval, line;
- unsigned long page;
- int allocated_resources = 0;
-
- /* find which port we want to open */
- line = tty->index;
-
- if (line < 0 || line >= NR_PORTS)
- return -ENODEV;
-
- /* find the corresponding e100_serial struct in the table */
- info = rs_table + line;
-
- /* don't allow the opening of ports that are not enabled in the HW config */
- if (!info->enabled)
- return -ENODEV;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name,
- info->count);
-#endif
-
- info->count++;
- tty->driver_data = info;
- info->port.tty = tty;
-
- info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
- return -ENOMEM;
- }
- if (tmp_buf)
- free_page(page);
- else
- tmp_buf = (unsigned char *) page;
- }
-
- /*
- * If the port is in the middle of closing, bail out now
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
- !(info->flags & ASYNC_CLOSING));
-#ifdef SERIAL_DO_RESTART
- return ((info->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If DMA is enabled try to allocate the irq's.
- */
- if (info->count == 1) {
- allocated_resources = 1;
- if (info->dma_in_enabled) {
- if (request_irq(info->dma_in_irq_nbr,
- rec_interrupt,
- info->dma_in_irq_flags,
- info->dma_in_irq_description,
- info)) {
- printk(KERN_WARNING "DMA irq '%s' busy; "
- "falling back to non-DMA mode\n",
- info->dma_in_irq_description);
- /* Make sure we never try to use DMA in */
- /* for the port again. */
- info->dma_in_enabled = 0;
- } else if (cris_request_dma(info->dma_in_nbr,
- info->dma_in_irq_description,
- DMA_VERBOSE_ON_ERROR,
- info->dma_owner)) {
- free_irq(info->dma_in_irq_nbr, info);
- printk(KERN_WARNING "DMA '%s' busy; "
- "falling back to non-DMA mode\n",
- info->dma_in_irq_description);
- /* Make sure we never try to use DMA in */
- /* for the port again. */
- info->dma_in_enabled = 0;
- }
-#ifdef SERIAL_DEBUG_OPEN
- else
- printk(KERN_DEBUG "DMA irq '%s' allocated\n",
- info->dma_in_irq_description);
-#endif
- }
- if (info->dma_out_enabled) {
- if (request_irq(info->dma_out_irq_nbr,
- tr_interrupt,
- info->dma_out_irq_flags,
- info->dma_out_irq_description,
- info)) {
- printk(KERN_WARNING "DMA irq '%s' busy; "
- "falling back to non-DMA mode\n",
- info->dma_out_irq_description);
- /* Make sure we never try to use DMA out */
- /* for the port again. */
- info->dma_out_enabled = 0;
- } else if (cris_request_dma(info->dma_out_nbr,
- info->dma_out_irq_description,
- DMA_VERBOSE_ON_ERROR,
- info->dma_owner)) {
- free_irq(info->dma_out_irq_nbr, info);
- printk(KERN_WARNING "DMA '%s' busy; "
- "falling back to non-DMA mode\n",
- info->dma_out_irq_description);
- /* Make sure we never try to use DMA out */
- /* for the port again. */
- info->dma_out_enabled = 0;
- }
-#ifdef SERIAL_DEBUG_OPEN
- else
- printk(KERN_DEBUG "DMA irq '%s' allocated\n",
- info->dma_out_irq_description);
-#endif
- }
- }
-
- /*
- * Start up the serial port
- */
-
- retval = startup(info);
- if (retval) {
- if (allocated_resources)
- deinit_port(info);
-
- /* FIXME Decrease count info->count here too? */
- return retval;
- }
-
-
- retval = block_til_ready(tty, filp, info);
- if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open returning after block_til_ready with %d\n",
- retval);
-#endif
- if (allocated_resources)
- deinit_port(info);
-
- return retval;
- }
-
- if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
- *tty->termios = info->normal_termios;
- change_speed(info);
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open ttyS%d successful...\n", info->line);
-#endif
- DLOG_INT_TRIG( log_int_pos = 0);
-
- DFLIP( if (info->line == SERIAL_DEBUG_LINE) {
- info->icount.rx = 0;
- } );
-
- return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- * /proc fs routines....
- */
-
-static void seq_line_info(struct seq_file *m, struct e100_serial *info)
-{
- unsigned long tmp;
-
- seq_printf(m, "%d: uart:E100 port:%lX irq:%d",
- info->line, (unsigned long)info->ioport, info->irq);
-
- if (!info->ioport || (info->type == PORT_UNKNOWN)) {
- seq_printf(m, "\n");
- return;
- }
-
- seq_printf(m, " baud:%d", info->baud);
- seq_printf(m, " tx:%lu rx:%lu",
- (unsigned long)info->icount.tx,
- (unsigned long)info->icount.rx);
- tmp = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
- if (tmp)
- seq_printf(m, " tx_pend:%lu/%lu",
- (unsigned long)tmp,
- (unsigned long)SERIAL_XMIT_SIZE);
-
- seq_printf(m, " rx_pend:%lu/%lu",
- (unsigned long)info->recv_cnt,
- (unsigned long)info->max_recv_cnt);
-
-#if 1
- if (info->port.tty) {
- if (info->port.tty->stopped)
- seq_printf(m, " stopped:%i",
- (int)info->port.tty->stopped);
- if (info->port.tty->hw_stopped)
- seq_printf(m, " hw_stopped:%i",
- (int)info->port.tty->hw_stopped);
- }
-
- {
- unsigned char rstat = info->ioport[REG_STATUS];
- if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect))
- seq_printf(m, " xoff_detect:1");
- }
-
-#endif
-
- if (info->icount.frame)
- seq_printf(m, " fe:%lu", (unsigned long)info->icount.frame);
-
- if (info->icount.parity)
- seq_printf(m, " pe:%lu", (unsigned long)info->icount.parity);
-
- if (info->icount.brk)
- seq_printf(m, " brk:%lu", (unsigned long)info->icount.brk);
-
- if (info->icount.overrun)
- seq_printf(m, " oe:%lu", (unsigned long)info->icount.overrun);
-
- /*
- * Last thing is the RS-232 status lines
- */
- if (!E100_RTS_GET(info))
- seq_puts(m, "|RTS");
- if (!E100_CTS_GET(info))
- seq_puts(m, "|CTS");
- if (!E100_DTR_GET(info))
- seq_puts(m, "|DTR");
- if (!E100_DSR_GET(info))
- seq_puts(m, "|DSR");
- if (!E100_CD_GET(info))
- seq_puts(m, "|CD");
- if (!E100_RI_GET(info))
- seq_puts(m, "|RI");
- seq_puts(m, "\n");
-}
-
-
-static int crisv10_proc_show(struct seq_file *m, void *v)
-{
- int i;
-
- seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
-
- for (i = 0; i < NR_PORTS; i++) {
- if (!rs_table[i].enabled)
- continue;
- seq_line_info(m, &rs_table[i]);
- }
-#ifdef DEBUG_LOG_INCLUDED
- for (i = 0; i < debug_log_pos; i++) {
- seq_printf(m, "%-4i %lu.%lu ",
- i, debug_log[i].time,
- timer_data_to_ns(debug_log[i].timer_data));
- seq_printf(m, debug_log[i].string, debug_log[i].value);
- }
- seq_printf(m, "debug_log %i/%i\n", i, DEBUG_LOG_SIZE);
- debug_log_pos = 0;
-#endif
- return 0;
-}
-
-static int crisv10_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, crisv10_proc_show, NULL);
-}
-
-static const struct file_operations crisv10_proc_fops = {
- .owner = THIS_MODULE,
- .open = crisv10_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-
-/* Finally, routines used to initialize the serial driver. */
-
-static void show_serial_version(void)
-{
- printk(KERN_INFO
- "ETRAX 100LX serial-driver %s, "
- "(c) 2000-2004 Axis Communications AB\r\n",
- &serial_version[11]); /* "$Revision: x.yy" */
-}
-
-/* rs_init inits the driver at boot (using the module_init chain) */
-
-static const struct tty_operations rs_ops = {
- .open = rs_open,
- .close = rs_close,
- .write = rs_write,
- .flush_chars = rs_flush_chars,
- .write_room = rs_write_room,
- .chars_in_buffer = rs_chars_in_buffer,
- .flush_buffer = rs_flush_buffer,
- .ioctl = rs_ioctl,
- .throttle = rs_throttle,
- .unthrottle = rs_unthrottle,
- .set_termios = rs_set_termios,
- .stop = rs_stop,
- .start = rs_start,
- .hangup = rs_hangup,
- .break_ctl = rs_break,
- .send_xchar = rs_send_xchar,
- .wait_until_sent = rs_wait_until_sent,
- .tiocmget = rs_tiocmget,
- .tiocmset = rs_tiocmset,
-#ifdef CONFIG_PROC_FS
- .proc_fops = &crisv10_proc_fops,
-#endif
-};
-
-static int __init rs_init(void)
-{
- int i;
- struct e100_serial *info;
- struct tty_driver *driver = alloc_tty_driver(NR_PORTS);
-
- if (!driver)
- return -ENOMEM;
-
- show_serial_version();
-
- /* Setup the timed flush handler system */
-
-#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER)
- setup_timer(&flush_timer, timed_flush_handler, 0);
- mod_timer(&flush_timer, jiffies + 5);
-#endif
-
-#if defined(CONFIG_ETRAX_RS485)
-#if defined(CONFIG_ETRAX_RS485_ON_PA)
- if (cris_io_interface_allocate_pins(if_ser0, 'a', rs485_pa_bit,
- rs485_pa_bit)) {
- printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
- "RS485 pin\n");
- put_tty_driver(driver);
- return -EBUSY;
- }
-#endif
-#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
- if (cris_io_interface_allocate_pins(if_ser0, 'g', rs485_pa_bit,
- rs485_port_g_bit)) {
- printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
- "RS485 pin\n");
- put_tty_driver(driver);
- return -EBUSY;
- }
-#endif
-#endif
-
- /* Initialize the tty_driver structure */
-
- driver->driver_name = "serial";
- driver->name = "ttyS";
- driver->major = TTY_MAJOR;
- driver->minor_start = 64;
- driver->type = TTY_DRIVER_TYPE_SERIAL;
- driver->subtype = SERIAL_TYPE_NORMAL;
- driver->init_termios = tty_std_termios;
- driver->init_termios.c_cflag =
- B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
- driver->init_termios.c_ispeed = 115200;
- driver->init_termios.c_ospeed = 115200;
- driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-
- tty_set_operations(driver, &rs_ops);
- serial_driver = driver;
- if (tty_register_driver(driver))
- panic("Couldn't register serial driver\n");
- /* do some initializing for the separate ports */
-
- for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
- if (info->enabled) {
- if (cris_request_io_interface(info->io_if,
- info->io_if_description)) {
- printk(KERN_CRIT "ETRAX100LX async serial: "
- "Could not allocate IO pins for "
- "%s, port %d\n",
- info->io_if_description, i);
- info->enabled = 0;
- }
- }
- info->uses_dma_in = 0;
- info->uses_dma_out = 0;
- info->line = i;
- info->port.tty = NULL;
- info->type = PORT_ETRAX;
- info->tr_running = 0;
- info->forced_eop = 0;
- info->baud_base = DEF_BAUD_BASE;
- info->custom_divisor = 0;
- info->flags = 0;
- info->close_delay = 5*HZ/10;
- info->closing_wait = 30*HZ;
- info->x_char = 0;
- info->event = 0;
- info->count = 0;
- info->blocked_open = 0;
- info->normal_termios = driver->init_termios;
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- info->xmit.buf = NULL;
- info->xmit.tail = info->xmit.head = 0;
- info->first_recv_buffer = info->last_recv_buffer = NULL;
- info->recv_cnt = info->max_recv_cnt = 0;
- info->last_tx_active_usec = 0;
- info->last_tx_active = 0;
-
-#if defined(CONFIG_ETRAX_RS485)
- /* Set sane defaults */
- info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND);
- info->rs485.flags |= SER_RS485_RTS_AFTER_SEND;
- info->rs485.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
- info->rs485.delay_rts_before_send = 0;
- info->rs485.flags &= ~(SER_RS485_ENABLED);
-#endif
- INIT_WORK(&info->work, do_softint);
-
- if (info->enabled) {
- printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n",
- serial_driver->name, info->line, info->ioport);
- }
- }
-#ifdef CONFIG_ETRAX_FAST_TIMER
-#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
- memset(fast_timers, 0, sizeof(fast_timers));
-#endif
-#ifdef CONFIG_ETRAX_RS485
- memset(fast_timers_rs485, 0, sizeof(fast_timers_rs485));
-#endif
- fast_timer_init();
-#endif
-
-#ifndef CONFIG_SVINTO_SIM
-#ifndef CONFIG_ETRAX_KGDB
- /* Not needed in simulator. May only complicate stuff. */
- /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
-
- if (request_irq(SERIAL_IRQ_NBR, ser_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "serial ", driver))
- panic("%s: Failed to request irq8", __func__);
-
-#endif
-#endif /* CONFIG_SVINTO_SIM */
-
- return 0;
-}
-
-/* this makes sure that rs_init is called during kernel boot */
-
-module_init(rs_init);
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h
deleted file mode 100644
index ea0beb46a10d..000000000000
--- a/drivers/serial/crisv10.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * serial.h: Arch-dep definitions for the Etrax100 serial driver.
- *
- * Copyright (C) 1998-2007 Axis Communications AB
- */
-
-#ifndef _ETRAX_SERIAL_H
-#define _ETRAX_SERIAL_H
-
-#include <linux/circ_buf.h>
-#include <asm/termios.h>
-#include <asm/dma.h>
-#include <arch/io_interface_mux.h>
-
-/* Software state per channel */
-
-#ifdef __KERNEL__
-/*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-#define SERIAL_RECV_DESCRIPTORS 8
-
-struct etrax_recv_buffer {
- struct etrax_recv_buffer *next;
- unsigned short length;
- unsigned char error;
- unsigned char pad;
-
- unsigned char buffer[0];
-};
-
-struct e100_serial {
- struct tty_port port;
- int baud;
- volatile u8 *ioport; /* R_SERIALx_CTRL */
- u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */
-
- /* Output registers */
- volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
- volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */
- volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */
- const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */
-
- /* Input registers */
- volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
- volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */
- volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */
- volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */
-
- int flags; /* defined in tty.h */
-
- u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
- u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
- u8 iseteop; /* bit number for R_SET_EOP for the input dma */
- int enabled; /* Set to 1 if the port is enabled in HW config */
-
- u8 dma_out_enabled; /* Set to 1 if DMA should be used */
- u8 dma_in_enabled; /* Set to 1 if DMA should be used */
-
- /* end of fields defined in rs_table[] in .c-file */
- int dma_owner;
- unsigned int dma_in_nbr;
- unsigned int dma_out_nbr;
- unsigned int dma_in_irq_nbr;
- unsigned int dma_out_irq_nbr;
- unsigned long dma_in_irq_flags;
- unsigned long dma_out_irq_flags;
- char *dma_in_irq_description;
- char *dma_out_irq_description;
-
- enum cris_io_interface io_if;
- char *io_if_description;
-
- u8 uses_dma_in; /* Set to 1 if DMA is used */
- u8 uses_dma_out; /* Set to 1 if DMA is used */
- u8 forced_eop; /* a fifo eop has been forced */
- int baud_base; /* For special baudrates */
- int custom_divisor; /* For special baudrates */
- struct etrax_dma_descr tr_descr;
- struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS];
- int cur_rec_descr;
-
- volatile int tr_running; /* 1 if output is running */
-
- struct tty_struct *tty;
- int read_status_mask;
- int ignore_status_mask;
- int x_char; /* xon/xoff character */
- int close_delay;
- unsigned short closing_wait;
- unsigned short closing_wait2;
- unsigned long event;
- unsigned long last_active;
- int line;
- int type; /* PORT_ETRAX */
- int count; /* # of fd on device */
- int blocked_open; /* # of blocked opens */
- struct circ_buf xmit;
- struct etrax_recv_buffer *first_recv_buffer;
- struct etrax_recv_buffer *last_recv_buffer;
- unsigned int recv_cnt;
- unsigned int max_recv_cnt;
-
- struct work_struct work;
- struct async_icount icount; /* error-statistics etc.*/
- struct ktermios normal_termios;
- struct ktermios callout_termios;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-
- unsigned long char_time_usec; /* The time for 1 char, in usecs */
- unsigned long flush_time_usec; /* How often we should flush */
- unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */
- unsigned long last_tx_active; /* Last tx time in jiffies */
- unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */
- unsigned long last_rx_active; /* Last rx time in jiffies */
-
- int break_detected_cnt;
- int errorcode;
-
-#ifdef CONFIG_ETRAX_RS485
- struct serial_rs485 rs485; /* RS-485 support */
-#endif
-};
-
-/* this PORT is not in the standard serial.h. it's not actually used for
- * anything since we only have one type of async serial-port anyway in this
- * system.
- */
-
-#define PORT_ETRAX 1
-
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at rs interrupt time.
- */
-#define RS_EVENT_WRITE_WAKEUP 0
-
-#endif /* __KERNEL__ */
-
-#endif /* !_ETRAX_SERIAL_H */
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
deleted file mode 100644
index 57421d776329..000000000000
--- a/drivers/serial/dz.c
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
- * dz.c: Serial port driver for DECstations equipped
- * with the DZ chipset.
- *
- * Copyright (C) 1998 Olivier A. D. Lebaillif
- *
- * Email: olivier.lebaillif@ifrsys.com
- *
- * Copyright (C) 2004, 2006, 2007 Maciej W. Rozycki
- *
- * [31-AUG-98] triemer
- * Changed IRQ to use Harald's dec internals interrupts.h
- * removed base_addr code - moving address assignment to setup.c
- * Changed name of dz_init to rs_init to be consistent with tc code
- * [13-NOV-98] triemer fixed code to receive characters
- * after patches by harald to irq code.
- * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
- * field from "current" - somewhere between 2.1.121 and 2.1.131
- Qua Jun 27 15:02:26 BRT 2001
- * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
- *
- * Parts (C) 1999 David Airlie, airlied@linux.ie
- * [07-SEP-99] Bugfixes
- *
- * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>
- * Converted to new serial core
- */
-
-#undef DEBUG_DZ
-
-#if defined(CONFIG_SERIAL_DZ_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-
-#include <asm/atomic.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include <asm/dec/interrupts.h>
-#include <asm/dec/kn01.h>
-#include <asm/dec/kn02.h>
-#include <asm/dec/machtype.h>
-#include <asm/dec/prom.h>
-#include <asm/dec/system.h>
-
-#include "dz.h"
-
-
-MODULE_DESCRIPTION("DECstation DZ serial driver");
-MODULE_LICENSE("GPL");
-
-
-static char dz_name[] __initdata = "DECstation DZ serial driver version ";
-static char dz_version[] __initdata = "1.04";
-
-struct dz_port {
- struct dz_mux *mux;
- struct uart_port port;
- unsigned int cflag;
-};
-
-struct dz_mux {
- struct dz_port dport[DZ_NB_PORT];
- atomic_t map_guard;
- atomic_t irq_guard;
- int initialised;
-};
-
-static struct dz_mux dz_mux;
-
-static inline struct dz_port *to_dport(struct uart_port *uport)
-{
- return container_of(uport, struct dz_port, port);
-}
-
-/*
- * ------------------------------------------------------------
- * dz_in () and dz_out ()
- *
- * These routines are used to access the registers of the DZ
- * chip, hiding relocation differences between implementation.
- * ------------------------------------------------------------
- */
-
-static u16 dz_in(struct dz_port *dport, unsigned offset)
-{
- void __iomem *addr = dport->port.membase + offset;
-
- return readw(addr);
-}
-
-static void dz_out(struct dz_port *dport, unsigned offset, u16 value)
-{
- void __iomem *addr = dport->port.membase + offset;
-
- writew(value, addr);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_stop () and rs_start ()
- *
- * These routines are called before setting or resetting
- * tty->stopped. They enable or disable transmitter interrupts,
- * as necessary.
- * ------------------------------------------------------------
- */
-
-static void dz_stop_tx(struct uart_port *uport)
-{
- struct dz_port *dport = to_dport(uport);
- u16 tmp, mask = 1 << dport->port.line;
-
- tmp = dz_in(dport, DZ_TCR); /* read the TX flag */
- tmp &= ~mask; /* clear the TX flag */
- dz_out(dport, DZ_TCR, tmp);
-}
-
-static void dz_start_tx(struct uart_port *uport)
-{
- struct dz_port *dport = to_dport(uport);
- u16 tmp, mask = 1 << dport->port.line;
-
- tmp = dz_in(dport, DZ_TCR); /* read the TX flag */
- tmp |= mask; /* set the TX flag */
- dz_out(dport, DZ_TCR, tmp);
-}
-
-static void dz_stop_rx(struct uart_port *uport)
-{
- struct dz_port *dport = to_dport(uport);
-
- dport->cflag &= ~DZ_RXENAB;
- dz_out(dport, DZ_LPR, dport->cflag);
-}
-
-static void dz_enable_ms(struct uart_port *uport)
-{
- /* nothing to do */
-}
-
-/*
- * ------------------------------------------------------------
- *
- * Here start the interrupt handling routines. All of the following
- * subroutines are declared as inline and are folded into
- * dz_interrupt. They were separated out for readability's sake.
- *
- * Note: dz_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off. People who may want to modify
- * dz_interrupt() should try to keep the interrupt handler as fast as
- * possible. After you are done making modifications, it is not a bad
- * idea to do:
- *
- * make drivers/serial/dz.s
- *
- * and look at the resulting assemble code in dz.s.
- *
- * ------------------------------------------------------------
- */
-
-/*
- * ------------------------------------------------------------
- * receive_char ()
- *
- * This routine deals with inputs from any lines.
- * ------------------------------------------------------------
- */
-static inline void dz_receive_chars(struct dz_mux *mux)
-{
- struct uart_port *uport;
- struct dz_port *dport = &mux->dport[0];
- struct tty_struct *tty = NULL;
- struct uart_icount *icount;
- int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 };
- unsigned char ch, flag;
- u16 status;
- int i;
-
- while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) {
- dport = &mux->dport[LINE(status)];
- uport = &dport->port;
- tty = uport->state->port.tty; /* point to the proper dev */
-
- ch = UCHAR(status); /* grab the char */
- flag = TTY_NORMAL;
-
- icount = &uport->icount;
- icount->rx++;
-
- if (unlikely(status & (DZ_OERR | DZ_FERR | DZ_PERR))) {
-
- /*
- * There is no separate BREAK status bit, so treat
- * null characters with framing errors as BREAKs;
- * normally, otherwise. For this move the Framing
- * Error bit to a simulated BREAK bit.
- */
- if (!ch) {
- status |= (status & DZ_FERR) >>
- (ffs(DZ_FERR) - ffs(DZ_BREAK));
- status &= ~DZ_FERR;
- }
-
- /* Handle SysRq/SAK & keep track of the statistics. */
- if (status & DZ_BREAK) {
- icount->brk++;
- if (uart_handle_break(uport))
- continue;
- } else if (status & DZ_FERR)
- icount->frame++;
- else if (status & DZ_PERR)
- icount->parity++;
- if (status & DZ_OERR)
- icount->overrun++;
-
- status &= uport->read_status_mask;
- if (status & DZ_BREAK)
- flag = TTY_BREAK;
- else if (status & DZ_FERR)
- flag = TTY_FRAME;
- else if (status & DZ_PERR)
- flag = TTY_PARITY;
-
- }
-
- if (uart_handle_sysrq_char(uport, ch))
- continue;
-
- uart_insert_char(uport, status, DZ_OERR, ch, flag);
- lines_rx[LINE(status)] = 1;
- }
- for (i = 0; i < DZ_NB_PORT; i++)
- if (lines_rx[i])
- tty_flip_buffer_push(mux->dport[i].port.state->port.tty);
-}
-
-/*
- * ------------------------------------------------------------
- * transmit_char ()
- *
- * This routine deals with outputs to any lines.
- * ------------------------------------------------------------
- */
-static inline void dz_transmit_chars(struct dz_mux *mux)
-{
- struct dz_port *dport = &mux->dport[0];
- struct circ_buf *xmit;
- unsigned char tmp;
- u16 status;
-
- status = dz_in(dport, DZ_CSR);
- dport = &mux->dport[LINE(status)];
- xmit = &dport->port.state->xmit;
-
- if (dport->port.x_char) { /* XON/XOFF chars */
- dz_out(dport, DZ_TDR, dport->port.x_char);
- dport->port.icount.tx++;
- dport->port.x_char = 0;
- return;
- }
- /* If nothing to do or stopped or hardware stopped. */
- if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
- spin_lock(&dport->port.lock);
- dz_stop_tx(&dport->port);
- spin_unlock(&dport->port.lock);
- return;
- }
-
- /*
- * If something to do... (remember the dz has no output fifo,
- * so we go one char at a time) :-<
- */
- tmp = xmit->buf[xmit->tail];
- xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
- dz_out(dport, DZ_TDR, tmp);
- dport->port.icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
- uart_write_wakeup(&dport->port);
-
- /* Are we are done. */
- if (uart_circ_empty(xmit)) {
- spin_lock(&dport->port.lock);
- dz_stop_tx(&dport->port);
- spin_unlock(&dport->port.lock);
- }
-}
-
-/*
- * ------------------------------------------------------------
- * check_modem_status()
- *
- * DS 3100 & 5100: Only valid for the MODEM line, duh!
- * DS 5000/200: Valid for the MODEM and PRINTER line.
- * ------------------------------------------------------------
- */
-static inline void check_modem_status(struct dz_port *dport)
-{
- /*
- * FIXME:
- * 1. No status change interrupt; use a timer.
- * 2. Handle the 3100/5000 as appropriate. --macro
- */
- u16 status;
-
- /* If not the modem line just return. */
- if (dport->port.line != DZ_MODEM)
- return;
-
- status = dz_in(dport, DZ_MSR);
-
- /* it's easy, since DSR2 is the only bit in the register */
- if (status)
- dport->port.icount.dsr++;
-}
-
-/*
- * ------------------------------------------------------------
- * dz_interrupt ()
- *
- * this is the main interrupt routine for the DZ chip.
- * It deals with the multiple ports.
- * ------------------------------------------------------------
- */
-static irqreturn_t dz_interrupt(int irq, void *dev_id)
-{
- struct dz_mux *mux = dev_id;
- struct dz_port *dport = &mux->dport[0];
- u16 status;
-
- /* get the reason why we just got an irq */
- status = dz_in(dport, DZ_CSR);
-
- if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE))
- dz_receive_chars(mux);
-
- if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE))
- dz_transmit_chars(mux);
-
- return IRQ_HANDLED;
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the DZ interrupt routines.
- * -------------------------------------------------------------------
- */
-
-static unsigned int dz_get_mctrl(struct uart_port *uport)
-{
- /*
- * FIXME: Handle the 3100/5000 as appropriate. --macro
- */
- struct dz_port *dport = to_dport(uport);
- unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-
- if (dport->port.line == DZ_MODEM) {
- if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)
- mctrl &= ~TIOCM_DSR;
- }
-
- return mctrl;
-}
-
-static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)
-{
- /*
- * FIXME: Handle the 3100/5000 as appropriate. --macro
- */
- struct dz_port *dport = to_dport(uport);
- u16 tmp;
-
- if (dport->port.line == DZ_MODEM) {
- tmp = dz_in(dport, DZ_TCR);
- if (mctrl & TIOCM_DTR)
- tmp &= ~DZ_MODEM_DTR;
- else
- tmp |= DZ_MODEM_DTR;
- dz_out(dport, DZ_TCR, tmp);
- }
-}
-
-/*
- * -------------------------------------------------------------------
- * startup ()
- *
- * various initialization tasks
- * -------------------------------------------------------------------
- */
-static int dz_startup(struct uart_port *uport)
-{
- struct dz_port *dport = to_dport(uport);
- struct dz_mux *mux = dport->mux;
- unsigned long flags;
- int irq_guard;
- int ret;
- u16 tmp;
-
- irq_guard = atomic_add_return(1, &mux->irq_guard);
- if (irq_guard != 1)
- return 0;
-
- ret = request_irq(dport->port.irq, dz_interrupt,
- IRQF_SHARED, "dz", mux);
- if (ret) {
- atomic_add(-1, &mux->irq_guard);
- printk(KERN_ERR "dz: Cannot get IRQ %d!\n", dport->port.irq);
- return ret;
- }
-
- spin_lock_irqsave(&dport->port.lock, flags);
-
- /* Enable interrupts. */
- tmp = dz_in(dport, DZ_CSR);
- tmp |= DZ_RIE | DZ_TIE;
- dz_out(dport, DZ_CSR, tmp);
-
- spin_unlock_irqrestore(&dport->port.lock, flags);
-
- return 0;
-}
-
-/*
- * -------------------------------------------------------------------
- * shutdown ()
- *
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- * -------------------------------------------------------------------
- */
-static void dz_shutdown(struct uart_port *uport)
-{
- struct dz_port *dport = to_dport(uport);
- struct dz_mux *mux = dport->mux;
- unsigned long flags;
- int irq_guard;
- u16 tmp;
-
- spin_lock_irqsave(&dport->port.lock, flags);
- dz_stop_tx(&dport->port);
- spin_unlock_irqrestore(&dport->port.lock, flags);
-
- irq_guard = atomic_add_return(-1, &mux->irq_guard);
- if (!irq_guard) {
- /* Disable interrupts. */
- tmp = dz_in(dport, DZ_CSR);
- tmp &= ~(DZ_RIE | DZ_TIE);
- dz_out(dport, DZ_CSR, tmp);
-
- free_irq(dport->port.irq, mux);
- }
-}
-
-/*
- * -------------------------------------------------------------------
- * dz_tx_empty() -- get the transmitter empty status
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- * -------------------------------------------------------------------
- */
-static unsigned int dz_tx_empty(struct uart_port *uport)
-{
- struct dz_port *dport = to_dport(uport);
- unsigned short tmp, mask = 1 << dport->port.line;
-
- tmp = dz_in(dport, DZ_TCR);
- tmp &= mask;
-
- return tmp ? 0 : TIOCSER_TEMT;
-}
-
-static void dz_break_ctl(struct uart_port *uport, int break_state)
-{
- /*
- * FIXME: Can't access BREAK bits in TDR easily;
- * reuse the code for polled TX. --macro
- */
- struct dz_port *dport = to_dport(uport);
- unsigned long flags;
- unsigned short tmp, mask = 1 << dport->port.line;
-
- spin_lock_irqsave(&uport->lock, flags);
- tmp = dz_in(dport, DZ_TCR);
- if (break_state)
- tmp |= mask;
- else
- tmp &= ~mask;
- dz_out(dport, DZ_TCR, tmp);
- spin_unlock_irqrestore(&uport->lock, flags);
-}
-
-static int dz_encode_baud_rate(unsigned int baud)
-{
- switch (baud) {
- case 50:
- return DZ_B50;
- case 75:
- return DZ_B75;
- case 110:
- return DZ_B110;
- case 134:
- return DZ_B134;
- case 150:
- return DZ_B150;
- case 300:
- return DZ_B300;
- case 600:
- return DZ_B600;
- case 1200:
- return DZ_B1200;
- case 1800:
- return DZ_B1800;
- case 2000:
- return DZ_B2000;
- case 2400:
- return DZ_B2400;
- case 3600:
- return DZ_B3600;
- case 4800:
- return DZ_B4800;
- case 7200:
- return DZ_B7200;
- case 9600:
- return DZ_B9600;
- default:
- return -1;
- }
-}
-
-
-static void dz_reset(struct dz_port *dport)
-{
- struct dz_mux *mux = dport->mux;
-
- if (mux->initialised)
- return;
-
- dz_out(dport, DZ_CSR, DZ_CLR);
- while (dz_in(dport, DZ_CSR) & DZ_CLR);
- iob();
-
- /* Enable scanning. */
- dz_out(dport, DZ_CSR, DZ_MSE);
-
- mux->initialised = 1;
-}
-
-static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
- struct ktermios *old_termios)
-{
- struct dz_port *dport = to_dport(uport);
- unsigned long flags;
- unsigned int cflag, baud;
- int bflag;
-
- cflag = dport->port.line;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cflag |= DZ_CS5;
- break;
- case CS6:
- cflag |= DZ_CS6;
- break;
- case CS7:
- cflag |= DZ_CS7;
- break;
- case CS8:
- default:
- cflag |= DZ_CS8;
- }
-
- if (termios->c_cflag & CSTOPB)
- cflag |= DZ_CSTOPB;
- if (termios->c_cflag & PARENB)
- cflag |= DZ_PARENB;
- if (termios->c_cflag & PARODD)
- cflag |= DZ_PARODD;
-
- baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);
- bflag = dz_encode_baud_rate(baud);
- if (bflag < 0) { /* Try to keep unchanged. */
- baud = uart_get_baud_rate(uport, old_termios, NULL, 50, 9600);
- bflag = dz_encode_baud_rate(baud);
- if (bflag < 0) { /* Resort to 9600. */
- baud = 9600;
- bflag = DZ_B9600;
- }
- tty_termios_encode_baud_rate(termios, baud, baud);
- }
- cflag |= bflag;
-
- if (termios->c_cflag & CREAD)
- cflag |= DZ_RXENAB;
-
- spin_lock_irqsave(&dport->port.lock, flags);
-
- uart_update_timeout(uport, termios->c_cflag, baud);
-
- dz_out(dport, DZ_LPR, cflag);
- dport->cflag = cflag;
-
- /* setup accept flag */
- dport->port.read_status_mask = DZ_OERR;
- if (termios->c_iflag & INPCK)
- dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
- if (termios->c_iflag & (BRKINT | PARMRK))
- dport->port.read_status_mask |= DZ_BREAK;
-
- /* characters to ignore */
- uport->ignore_status_mask = 0;
- if ((termios->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
- dport->port.ignore_status_mask |= DZ_OERR;
- if (termios->c_iflag & IGNPAR)
- dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
- if (termios->c_iflag & IGNBRK)
- dport->port.ignore_status_mask |= DZ_BREAK;
-
- spin_unlock_irqrestore(&dport->port.lock, flags);
-}
-
-/*
- * Hack alert!
- * Required solely so that the initial PROM-based console
- * works undisturbed in parallel with this one.
- */
-static void dz_pm(struct uart_port *uport, unsigned int state,
- unsigned int oldstate)
-{
- struct dz_port *dport = to_dport(uport);
- unsigned long flags;
-
- spin_lock_irqsave(&dport->port.lock, flags);
- if (state < 3)
- dz_start_tx(&dport->port);
- else
- dz_stop_tx(&dport->port);
- spin_unlock_irqrestore(&dport->port.lock, flags);
-}
-
-
-static const char *dz_type(struct uart_port *uport)
-{
- return "DZ";
-}
-
-static void dz_release_port(struct uart_port *uport)
-{
- struct dz_mux *mux = to_dport(uport)->mux;
- int map_guard;
-
- iounmap(uport->membase);
- uport->membase = NULL;
-
- map_guard = atomic_add_return(-1, &mux->map_guard);
- if (!map_guard)
- release_mem_region(uport->mapbase, dec_kn_slot_size);
-}
-
-static int dz_map_port(struct uart_port *uport)
-{
- if (!uport->membase)
- uport->membase = ioremap_nocache(uport->mapbase,
- dec_kn_slot_size);
- if (!uport->membase) {
- printk(KERN_ERR "dz: Cannot map MMIO\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-static int dz_request_port(struct uart_port *uport)
-{
- struct dz_mux *mux = to_dport(uport)->mux;
- int map_guard;
- int ret;
-
- map_guard = atomic_add_return(1, &mux->map_guard);
- if (map_guard == 1) {
- if (!request_mem_region(uport->mapbase, dec_kn_slot_size,
- "dz")) {
- atomic_add(-1, &mux->map_guard);
- printk(KERN_ERR
- "dz: Unable to reserve MMIO resource\n");
- return -EBUSY;
- }
- }
- ret = dz_map_port(uport);
- if (ret) {
- map_guard = atomic_add_return(-1, &mux->map_guard);
- if (!map_guard)
- release_mem_region(uport->mapbase, dec_kn_slot_size);
- return ret;
- }
- return 0;
-}
-
-static void dz_config_port(struct uart_port *uport, int flags)
-{
- struct dz_port *dport = to_dport(uport);
-
- if (flags & UART_CONFIG_TYPE) {
- if (dz_request_port(uport))
- return;
-
- uport->type = PORT_DZ;
-
- dz_reset(dport);
- }
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- */
-static int dz_verify_port(struct uart_port *uport, struct serial_struct *ser)
-{
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)
- ret = -EINVAL;
- if (ser->irq != uport->irq)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops dz_ops = {
- .tx_empty = dz_tx_empty,
- .get_mctrl = dz_get_mctrl,
- .set_mctrl = dz_set_mctrl,
- .stop_tx = dz_stop_tx,
- .start_tx = dz_start_tx,
- .stop_rx = dz_stop_rx,
- .enable_ms = dz_enable_ms,
- .break_ctl = dz_break_ctl,
- .startup = dz_startup,
- .shutdown = dz_shutdown,
- .set_termios = dz_set_termios,
- .pm = dz_pm,
- .type = dz_type,
- .release_port = dz_release_port,
- .request_port = dz_request_port,
- .config_port = dz_config_port,
- .verify_port = dz_verify_port,
-};
-
-static void __init dz_init_ports(void)
-{
- static int first = 1;
- unsigned long base;
- int line;
-
- if (!first)
- return;
- first = 0;
-
- if (mips_machtype == MACH_DS23100 || mips_machtype == MACH_DS5100)
- base = dec_kn_slot_base + KN01_DZ11;
- else
- base = dec_kn_slot_base + KN02_DZ11;
-
- for (line = 0; line < DZ_NB_PORT; line++) {
- struct dz_port *dport = &dz_mux.dport[line];
- struct uart_port *uport = &dport->port;
-
- dport->mux = &dz_mux;
-
- uport->irq = dec_interrupt[DEC_IRQ_DZ11];
- uport->fifosize = 1;
- uport->iotype = UPIO_MEM;
- uport->flags = UPF_BOOT_AUTOCONF;
- uport->ops = &dz_ops;
- uport->line = line;
- uport->mapbase = base;
- }
-}
-
-#ifdef CONFIG_SERIAL_DZ_CONSOLE
-/*
- * -------------------------------------------------------------------
- * dz_console_putchar() -- transmit a character
- *
- * Polled transmission. This is tricky. We need to mask transmit
- * interrupts so that they do not interfere, enable the transmitter
- * for the line requested and then wait till the transmit scanner
- * requests data for this line. But it may request data for another
- * line first, in which case we have to disable its transmitter and
- * repeat waiting till our line pops up. Only then the character may
- * be transmitted. Finally, the state of the transmitter mask is
- * restored. Welcome to the world of PDP-11!
- * -------------------------------------------------------------------
- */
-static void dz_console_putchar(struct uart_port *uport, int ch)
-{
- struct dz_port *dport = to_dport(uport);
- unsigned long flags;
- unsigned short csr, tcr, trdy, mask;
- int loops = 10000;
-
- spin_lock_irqsave(&dport->port.lock, flags);
- csr = dz_in(dport, DZ_CSR);
- dz_out(dport, DZ_CSR, csr & ~DZ_TIE);
- tcr = dz_in(dport, DZ_TCR);
- tcr |= 1 << dport->port.line;
- mask = tcr;
- dz_out(dport, DZ_TCR, mask);
- iob();
- spin_unlock_irqrestore(&dport->port.lock, flags);
-
- do {
- trdy = dz_in(dport, DZ_CSR);
- if (!(trdy & DZ_TRDY))
- continue;
- trdy = (trdy & DZ_TLINE) >> 8;
- if (trdy == dport->port.line)
- break;
- mask &= ~(1 << trdy);
- dz_out(dport, DZ_TCR, mask);
- iob();
- udelay(2);
- } while (--loops);
-
- if (loops) /* Cannot send otherwise. */
- dz_out(dport, DZ_TDR, ch);
-
- dz_out(dport, DZ_TCR, tcr);
- dz_out(dport, DZ_CSR, csr);
-}
-
-/*
- * -------------------------------------------------------------------
- * dz_console_print ()
- *
- * dz_console_print is registered for printk.
- * The console must be locked when we get here.
- * -------------------------------------------------------------------
- */
-static void dz_console_print(struct console *co,
- const char *str,
- unsigned int count)
-{
- struct dz_port *dport = &dz_mux.dport[co->index];
-#ifdef DEBUG_DZ
- prom_printf((char *) str);
-#endif
- uart_console_write(&dport->port, str, count, dz_console_putchar);
-}
-
-static int __init dz_console_setup(struct console *co, char *options)
-{
- struct dz_port *dport = &dz_mux.dport[co->index];
- struct uart_port *uport = &dport->port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- int ret;
-
- ret = dz_map_port(uport);
- if (ret)
- return ret;
-
- spin_lock_init(&dport->port.lock); /* For dz_pm(). */
-
- dz_reset(dport);
- dz_pm(uport, 0, -1);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&dport->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver dz_reg;
-static struct console dz_console = {
- .name = "ttyS",
- .write = dz_console_print,
- .device = uart_console_device,
- .setup = dz_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &dz_reg,
-};
-
-static int __init dz_serial_console_init(void)
-{
- if (!IOASIC) {
- dz_init_ports();
- register_console(&dz_console);
- return 0;
- } else
- return -ENXIO;
-}
-
-console_initcall(dz_serial_console_init);
-
-#define SERIAL_DZ_CONSOLE &dz_console
-#else
-#define SERIAL_DZ_CONSOLE NULL
-#endif /* CONFIG_SERIAL_DZ_CONSOLE */
-
-static struct uart_driver dz_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = DZ_NB_PORT,
- .cons = SERIAL_DZ_CONSOLE,
-};
-
-static int __init dz_init(void)
-{
- int ret, i;
-
- if (IOASIC)
- return -ENXIO;
-
- printk("%s%s\n", dz_name, dz_version);
-
- dz_init_ports();
-
- ret = uart_register_driver(&dz_reg);
- if (ret)
- return ret;
-
- for (i = 0; i < DZ_NB_PORT; i++)
- uart_add_one_port(&dz_reg, &dz_mux.dport[i].port);
-
- return 0;
-}
-
-module_init(dz_init);
diff --git a/drivers/serial/dz.h b/drivers/serial/dz.h
deleted file mode 100644
index faf169ed27b3..000000000000
--- a/drivers/serial/dz.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * dz.h: Serial port driver for DECstations equipped
- * with the DZ chipset.
- *
- * Copyright (C) 1998 Olivier A. D. Lebaillif
- *
- * Email: olivier.lebaillif@ifrsys.com
- *
- * Copyright (C) 2004, 2006 Maciej W. Rozycki
- */
-#ifndef DZ_SERIAL_H
-#define DZ_SERIAL_H
-
-/*
- * Definitions for the Control and Status Register.
- */
-#define DZ_TRDY 0x8000 /* Transmitter empty */
-#define DZ_TIE 0x4000 /* Transmitter Interrupt Enbl */
-#define DZ_TLINE 0x0300 /* Transmitter Line Number */
-#define DZ_RDONE 0x0080 /* Receiver data ready */
-#define DZ_RIE 0x0040 /* Receive Interrupt Enable */
-#define DZ_MSE 0x0020 /* Master Scan Enable */
-#define DZ_CLR 0x0010 /* Master reset */
-#define DZ_MAINT 0x0008 /* Loop Back Mode */
-
-/*
- * Definitions for the Receiver Buffer Register.
- */
-#define DZ_RBUF_MASK 0x00FF /* Data Mask */
-#define DZ_LINE_MASK 0x0300 /* Line Mask */
-#define DZ_DVAL 0x8000 /* Valid Data indicator */
-#define DZ_OERR 0x4000 /* Overrun error indicator */
-#define DZ_FERR 0x2000 /* Frame error indicator */
-#define DZ_PERR 0x1000 /* Parity error indicator */
-
-#define DZ_BREAK 0x0800 /* BREAK event software flag */
-
-#define LINE(x) ((x & DZ_LINE_MASK) >> 8) /* Get the line number
- from the input buffer */
-#define UCHAR(x) ((unsigned char)(x & DZ_RBUF_MASK))
-
-/*
- * Definitions for the Transmit Control Register.
- */
-#define DZ_LINE_KEYBOARD 0x0001
-#define DZ_LINE_MOUSE 0x0002
-#define DZ_LINE_MODEM 0x0004
-#define DZ_LINE_PRINTER 0x0008
-
-#define DZ_MODEM_RTS 0x0800 /* RTS for the modem line (2) */
-#define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */
-#define DZ_PRINT_RTS 0x0200 /* RTS for the prntr line (3) */
-#define DZ_PRINT_DTR 0x0100 /* DTR for the prntr line (3) */
-#define DZ_LNENB 0x000f /* Transmitter Line Enable */
-
-/*
- * Definitions for the Modem Status Register.
- */
-#define DZ_MODEM_RI 0x0800 /* RI for the modem line (2) */
-#define DZ_MODEM_CD 0x0400 /* CD for the modem line (2) */
-#define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */
-#define DZ_MODEM_CTS 0x0100 /* CTS for the modem line (2) */
-#define DZ_PRINT_RI 0x0008 /* RI for the printer line (3) */
-#define DZ_PRINT_CD 0x0004 /* CD for the printer line (3) */
-#define DZ_PRINT_DSR 0x0002 /* DSR for the prntr line (3) */
-#define DZ_PRINT_CTS 0x0001 /* CTS for the prntr line (3) */
-
-/*
- * Definitions for the Transmit Data Register.
- */
-#define DZ_BRK0 0x0100 /* Break assertion for line 0 */
-#define DZ_BRK1 0x0200 /* Break assertion for line 1 */
-#define DZ_BRK2 0x0400 /* Break assertion for line 2 */
-#define DZ_BRK3 0x0800 /* Break assertion for line 3 */
-
-/*
- * Definitions for the Line Parameter Register.
- */
-#define DZ_KEYBOARD 0x0000 /* line 0 = keyboard */
-#define DZ_MOUSE 0x0001 /* line 1 = mouse */
-#define DZ_MODEM 0x0002 /* line 2 = modem */
-#define DZ_PRINTER 0x0003 /* line 3 = printer */
-
-#define DZ_CSIZE 0x0018 /* Number of bits per byte (mask) */
-#define DZ_CS5 0x0000 /* 5 bits per byte */
-#define DZ_CS6 0x0008 /* 6 bits per byte */
-#define DZ_CS7 0x0010 /* 7 bits per byte */
-#define DZ_CS8 0x0018 /* 8 bits per byte */
-
-#define DZ_CSTOPB 0x0020 /* 2 stop bits instead of one */
-
-#define DZ_PARENB 0x0040 /* Parity enable */
-#define DZ_PARODD 0x0080 /* Odd parity instead of even */
-
-#define DZ_CBAUD 0x0E00 /* Baud Rate (mask) */
-#define DZ_B50 0x0000
-#define DZ_B75 0x0100
-#define DZ_B110 0x0200
-#define DZ_B134 0x0300
-#define DZ_B150 0x0400
-#define DZ_B300 0x0500
-#define DZ_B600 0x0600
-#define DZ_B1200 0x0700
-#define DZ_B1800 0x0800
-#define DZ_B2000 0x0900
-#define DZ_B2400 0x0A00
-#define DZ_B3600 0x0B00
-#define DZ_B4800 0x0C00
-#define DZ_B7200 0x0D00
-#define DZ_B9600 0x0E00
-
-#define DZ_RXENAB 0x1000 /* Receiver Enable */
-
-/*
- * Addresses for the DZ registers
- */
-#define DZ_CSR 0x00 /* Control and Status Register */
-#define DZ_RBUF 0x08 /* Receive Buffer */
-#define DZ_LPR 0x08 /* Line Parameters Register */
-#define DZ_TCR 0x10 /* Transmitter Control Register */
-#define DZ_MSR 0x18 /* Modem Status Register */
-#define DZ_TDR 0x18 /* Transmit Data Register */
-
-#define DZ_NB_PORT 4
-
-#define DZ_XMIT_SIZE 4096 /* buffer size */
-#define DZ_WAKEUP_CHARS DZ_XMIT_SIZE/4
-
-#endif /* DZ_SERIAL_H */
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
deleted file mode 100644
index 53a468227056..000000000000
--- a/drivers/serial/icom.c
+++ /dev/null
@@ -1,1658 +0,0 @@
-/*
- * icom.c
- *
- * Copyright (C) 2001 IBM Corporation. All rights reserved.
- *
- * Serial device driver.
- *
- * Based on code from serial.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#define SERIAL_DO_RESTART
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/termios.h>
-#include <linux/fs.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/kref.h>
-#include <linux/firmware.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "icom.h"
-
-/*#define ICOM_TRACE enable port trace capabilities */
-
-#define ICOM_DRIVER_NAME "icom"
-#define ICOM_VERSION_STR "1.3.1"
-#define NR_PORTS 128
-#define ICOM_PORT ((struct icom_port *)port)
-#define to_icom_adapter(d) container_of(d, struct icom_adapter, kref)
-
-static const struct pci_device_id icom_pci_table[] = {
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = ADAPTER_V1,
- },
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
- .subvendor = PCI_VENDOR_ID_IBM,
- .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX,
- .driver_data = ADAPTER_V2,
- },
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
- .subvendor = PCI_VENDOR_ID_IBM,
- .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM,
- .driver_data = ADAPTER_V2,
- },
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
- .subvendor = PCI_VENDOR_ID_IBM,
- .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL,
- .driver_data = ADAPTER_V2,
- },
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
- .subvendor = PCI_VENDOR_ID_IBM,
- .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE,
- .driver_data = ADAPTER_V2,
- },
- {}
-};
-
-struct lookup_proc_table start_proc[4] = {
- {NULL, ICOM_CONTROL_START_A},
- {NULL, ICOM_CONTROL_START_B},
- {NULL, ICOM_CONTROL_START_C},
- {NULL, ICOM_CONTROL_START_D}
-};
-
-
-struct lookup_proc_table stop_proc[4] = {
- {NULL, ICOM_CONTROL_STOP_A},
- {NULL, ICOM_CONTROL_STOP_B},
- {NULL, ICOM_CONTROL_STOP_C},
- {NULL, ICOM_CONTROL_STOP_D}
-};
-
-struct lookup_int_table int_mask_tbl[4] = {
- {NULL, ICOM_INT_MASK_PRC_A},
- {NULL, ICOM_INT_MASK_PRC_B},
- {NULL, ICOM_INT_MASK_PRC_C},
- {NULL, ICOM_INT_MASK_PRC_D},
-};
-
-
-MODULE_DEVICE_TABLE(pci, icom_pci_table);
-
-static LIST_HEAD(icom_adapter_head);
-
-/* spinlock for adapter initialization and changing adapter operations */
-static spinlock_t icom_lock;
-
-#ifdef ICOM_TRACE
-static inline void trace(struct icom_port *icom_port, char *trace_pt,
- unsigned long trace_data)
-{
- dev_info(&icom_port->adapter->pci_dev->dev, ":%d:%s - %lx\n",
- icom_port->port, trace_pt, trace_data);
-}
-#else
-static inline void trace(struct icom_port *icom_port, char *trace_pt, unsigned long trace_data) {};
-#endif
-static void icom_kref_release(struct kref *kref);
-
-static void free_port_memory(struct icom_port *icom_port)
-{
- struct pci_dev *dev = icom_port->adapter->pci_dev;
-
- trace(icom_port, "RET_PORT_MEM", 0);
- if (icom_port->recv_buf) {
- pci_free_consistent(dev, 4096, icom_port->recv_buf,
- icom_port->recv_buf_pci);
- icom_port->recv_buf = NULL;
- }
- if (icom_port->xmit_buf) {
- pci_free_consistent(dev, 4096, icom_port->xmit_buf,
- icom_port->xmit_buf_pci);
- icom_port->xmit_buf = NULL;
- }
- if (icom_port->statStg) {
- pci_free_consistent(dev, 4096, icom_port->statStg,
- icom_port->statStg_pci);
- icom_port->statStg = NULL;
- }
-
- if (icom_port->xmitRestart) {
- pci_free_consistent(dev, 4096, icom_port->xmitRestart,
- icom_port->xmitRestart_pci);
- icom_port->xmitRestart = NULL;
- }
-}
-
-static int __devinit get_port_memory(struct icom_port *icom_port)
-{
- int index;
- unsigned long stgAddr;
- unsigned long startStgAddr;
- unsigned long offset;
- struct pci_dev *dev = icom_port->adapter->pci_dev;
-
- icom_port->xmit_buf =
- pci_alloc_consistent(dev, 4096, &icom_port->xmit_buf_pci);
- if (!icom_port->xmit_buf) {
- dev_err(&dev->dev, "Can not allocate Transmit buffer\n");
- return -ENOMEM;
- }
-
- trace(icom_port, "GET_PORT_MEM",
- (unsigned long) icom_port->xmit_buf);
-
- icom_port->recv_buf =
- pci_alloc_consistent(dev, 4096, &icom_port->recv_buf_pci);
- if (!icom_port->recv_buf) {
- dev_err(&dev->dev, "Can not allocate Receive buffer\n");
- free_port_memory(icom_port);
- return -ENOMEM;
- }
- trace(icom_port, "GET_PORT_MEM",
- (unsigned long) icom_port->recv_buf);
-
- icom_port->statStg =
- pci_alloc_consistent(dev, 4096, &icom_port->statStg_pci);
- if (!icom_port->statStg) {
- dev_err(&dev->dev, "Can not allocate Status buffer\n");
- free_port_memory(icom_port);
- return -ENOMEM;
- }
- trace(icom_port, "GET_PORT_MEM",
- (unsigned long) icom_port->statStg);
-
- icom_port->xmitRestart =
- pci_alloc_consistent(dev, 4096, &icom_port->xmitRestart_pci);
- if (!icom_port->xmitRestart) {
- dev_err(&dev->dev,
- "Can not allocate xmit Restart buffer\n");
- free_port_memory(icom_port);
- return -ENOMEM;
- }
-
- memset(icom_port->statStg, 0, 4096);
-
- /* FODs: Frame Out Descriptor Queue, this is a FIFO queue that
- indicates that frames are to be transmitted
- */
-
- stgAddr = (unsigned long) icom_port->statStg;
- for (index = 0; index < NUM_XBUFFS; index++) {
- trace(icom_port, "FOD_ADDR", stgAddr);
- stgAddr = stgAddr + sizeof(icom_port->statStg->xmit[0]);
- if (index < (NUM_XBUFFS - 1)) {
- memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
- icom_port->statStg->xmit[index].leLengthASD =
- (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
- trace(icom_port, "FOD_ADDR", stgAddr);
- trace(icom_port, "FOD_XBUFF",
- (unsigned long) icom_port->xmit_buf);
- icom_port->statStg->xmit[index].leBuffer =
- cpu_to_le32(icom_port->xmit_buf_pci);
- } else if (index == (NUM_XBUFFS - 1)) {
- memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
- icom_port->statStg->xmit[index].leLengthASD =
- (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
- trace(icom_port, "FOD_XBUFF",
- (unsigned long) icom_port->xmit_buf);
- icom_port->statStg->xmit[index].leBuffer =
- cpu_to_le32(icom_port->xmit_buf_pci);
- } else {
- memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
- }
- }
- /* FIDs */
- startStgAddr = stgAddr;
-
- /* fill in every entry, even if no buffer */
- for (index = 0; index < NUM_RBUFFS; index++) {
- trace(icom_port, "FID_ADDR", stgAddr);
- stgAddr = stgAddr + sizeof(icom_port->statStg->rcv[0]);
- icom_port->statStg->rcv[index].leLength = 0;
- icom_port->statStg->rcv[index].WorkingLength =
- (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
- if (index < (NUM_RBUFFS - 1) ) {
- offset = stgAddr - (unsigned long) icom_port->statStg;
- icom_port->statStg->rcv[index].leNext =
- cpu_to_le32(icom_port-> statStg_pci + offset);
- trace(icom_port, "FID_RBUFF",
- (unsigned long) icom_port->recv_buf);
- icom_port->statStg->rcv[index].leBuffer =
- cpu_to_le32(icom_port->recv_buf_pci);
- } else if (index == (NUM_RBUFFS -1) ) {
- offset = startStgAddr - (unsigned long) icom_port->statStg;
- icom_port->statStg->rcv[index].leNext =
- cpu_to_le32(icom_port-> statStg_pci + offset);
- trace(icom_port, "FID_RBUFF",
- (unsigned long) icom_port->recv_buf + 2048);
- icom_port->statStg->rcv[index].leBuffer =
- cpu_to_le32(icom_port->recv_buf_pci + 2048);
- } else {
- icom_port->statStg->rcv[index].leNext = 0;
- icom_port->statStg->rcv[index].leBuffer = 0;
- }
- }
-
- return 0;
-}
-
-static void stop_processor(struct icom_port *icom_port)
-{
- unsigned long temp;
- unsigned long flags;
- int port;
-
- spin_lock_irqsave(&icom_lock, flags);
-
- port = icom_port->port;
- if (port == 0 || port == 1)
- stop_proc[port].global_control_reg = &icom_port->global_reg->control;
- else
- stop_proc[port].global_control_reg = &icom_port->global_reg->control_2;
-
-
- if (port < 4) {
- temp = readl(stop_proc[port].global_control_reg);
- temp =
- (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
- writel(temp, stop_proc[port].global_control_reg);
-
- /* write flush */
- readl(stop_proc[port].global_control_reg);
- } else {
- dev_err(&icom_port->adapter->pci_dev->dev,
- "Invalid port assignment\n");
- }
-
- spin_unlock_irqrestore(&icom_lock, flags);
-}
-
-static void start_processor(struct icom_port *icom_port)
-{
- unsigned long temp;
- unsigned long flags;
- int port;
-
- spin_lock_irqsave(&icom_lock, flags);
-
- port = icom_port->port;
- if (port == 0 || port == 1)
- start_proc[port].global_control_reg = &icom_port->global_reg->control;
- else
- start_proc[port].global_control_reg = &icom_port->global_reg->control_2;
- if (port < 4) {
- temp = readl(start_proc[port].global_control_reg);
- temp =
- (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
- writel(temp, start_proc[port].global_control_reg);
-
- /* write flush */
- readl(start_proc[port].global_control_reg);
- } else {
- dev_err(&icom_port->adapter->pci_dev->dev,
- "Invalid port assignment\n");
- }
-
- spin_unlock_irqrestore(&icom_lock, flags);
-}
-
-static void load_code(struct icom_port *icom_port)
-{
- const struct firmware *fw;
- char __iomem *iram_ptr;
- int index;
- int status = 0;
- void __iomem *dram_ptr = icom_port->dram;
- dma_addr_t temp_pci;
- unsigned char *new_page = NULL;
- unsigned char cable_id = NO_CABLE;
- struct pci_dev *dev = icom_port->adapter->pci_dev;
-
- /* Clear out any pending interrupts */
- writew(0x3FFF, icom_port->int_reg);
-
- trace(icom_port, "CLEAR_INTERRUPTS", 0);
-
- /* Stop processor */
- stop_processor(icom_port);
-
- /* Zero out DRAM */
- memset_io(dram_ptr, 0, 512);
-
- /* Load Call Setup into Adapter */
- if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) {
- dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n");
- status = -1;
- goto load_code_exit;
- }
-
- if (fw->size > ICOM_DCE_IRAM_OFFSET) {
- dev_err(&dev->dev, "Invalid firmware image for icom_call_setup.bin found.\n");
- release_firmware(fw);
- status = -1;
- goto load_code_exit;
- }
-
- iram_ptr = (char __iomem *)icom_port->dram + ICOM_IRAM_OFFSET;
- for (index = 0; index < fw->size; index++)
- writeb(fw->data[index], &iram_ptr[index]);
-
- release_firmware(fw);
-
- /* Load Resident DCE portion of Adapter */
- if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) {
- dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n");
- status = -1;
- goto load_code_exit;
- }
-
- if (fw->size > ICOM_IRAM_SIZE) {
- dev_err(&dev->dev, "Invalid firmware image for icom_res_dce.bin found.\n");
- release_firmware(fw);
- status = -1;
- goto load_code_exit;
- }
-
- iram_ptr = (char __iomem *) icom_port->dram + ICOM_IRAM_OFFSET;
- for (index = ICOM_DCE_IRAM_OFFSET; index < fw->size; index++)
- writeb(fw->data[index], &iram_ptr[index]);
-
- release_firmware(fw);
-
- /* Set Hardware level */
- if (icom_port->adapter->version == ADAPTER_V2)
- writeb(V2_HARDWARE, &(icom_port->dram->misc_flags));
-
- /* Start the processor in Adapter */
- start_processor(icom_port);
-
- writeb((HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL),
- &(icom_port->dram->HDLCConfigReg));
- writeb(0x04, &(icom_port->dram->FlagFillIdleTimer)); /* 0.5 seconds */
- writeb(0x00, &(icom_port->dram->CmdReg));
- writeb(0x10, &(icom_port->dram->async_config3));
- writeb((ICOM_ACFG_DRIVE1 | ICOM_ACFG_NO_PARITY | ICOM_ACFG_8BPC |
- ICOM_ACFG_1STOP_BIT), &(icom_port->dram->async_config2));
-
- /*Set up data in icom DRAM to indicate where personality
- *code is located and its length.
- */
- new_page = pci_alloc_consistent(dev, 4096, &temp_pci);
-
- if (!new_page) {
- dev_err(&dev->dev, "Can not allocate DMA buffer\n");
- status = -1;
- goto load_code_exit;
- }
-
- if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) {
- dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n");
- status = -1;
- goto load_code_exit;
- }
-
- if (fw->size > ICOM_DCE_IRAM_OFFSET) {
- dev_err(&dev->dev, "Invalid firmware image for icom_asc.bin found.\n");
- release_firmware(fw);
- status = -1;
- goto load_code_exit;
- }
-
- for (index = 0; index < fw->size; index++)
- new_page[index] = fw->data[index];
-
- release_firmware(fw);
-
- writeb((char) ((fw->size + 16)/16), &icom_port->dram->mac_length);
- writel(temp_pci, &icom_port->dram->mac_load_addr);
-
- /*Setting the syncReg to 0x80 causes adapter to start downloading
- the personality code into adapter instruction RAM.
- Once code is loaded, it will begin executing and, based on
- information provided above, will start DMAing data from
- shared memory to adapter DRAM.
- */
- /* the wait loop below verifies this write operation has been done
- and processed
- */
- writeb(START_DOWNLOAD, &icom_port->dram->sync);
-
- /* Wait max 1 Sec for data download and processor to start */
- for (index = 0; index < 10; index++) {
- msleep(100);
- if (readb(&icom_port->dram->misc_flags) & ICOM_HDW_ACTIVE)
- break;
- }
-
- if (index == 10)
- status = -1;
-
- /*
- * check Cable ID
- */
- cable_id = readb(&icom_port->dram->cable_id);
-
- if (cable_id & ICOM_CABLE_ID_VALID) {
- /* Get cable ID into the lower 4 bits (standard form) */
- cable_id = (cable_id & ICOM_CABLE_ID_MASK) >> 4;
- icom_port->cable_id = cable_id;
- } else {
- dev_err(&dev->dev,"Invalid or no cable attached\n");
- icom_port->cable_id = NO_CABLE;
- }
-
- load_code_exit:
-
- if (status != 0) {
- /* Clear out any pending interrupts */
- writew(0x3FFF, icom_port->int_reg);
-
- /* Turn off port */
- writeb(ICOM_DISABLE, &(icom_port->dram->disable));
-
- /* Stop processor */
- stop_processor(icom_port);
-
- dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
- }
-
- if (new_page != NULL)
- pci_free_consistent(dev, 4096, new_page, temp_pci);
-}
-
-static int startup(struct icom_port *icom_port)
-{
- unsigned long temp;
- unsigned char cable_id, raw_cable_id;
- unsigned long flags;
- int port;
-
- trace(icom_port, "STARTUP", 0);
-
- if (!icom_port->dram) {
- /* should NEVER be NULL */
- dev_err(&icom_port->adapter->pci_dev->dev,
- "Unusable Port, port configuration missing\n");
- return -ENODEV;
- }
-
- /*
- * check Cable ID
- */
- raw_cable_id = readb(&icom_port->dram->cable_id);
- trace(icom_port, "CABLE_ID", raw_cable_id);
-
- /* Get cable ID into the lower 4 bits (standard form) */
- cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
-
- /* Check for valid Cable ID */
- if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
- (cable_id != icom_port->cable_id)) {
-
- /* reload adapter code, pick up any potential changes in cable id */
- load_code(icom_port);
-
- /* still no sign of cable, error out */
- raw_cable_id = readb(&icom_port->dram->cable_id);
- cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
- if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
- (icom_port->cable_id == NO_CABLE))
- return -EIO;
- }
-
- /*
- * Finally, clear and enable interrupts
- */
- spin_lock_irqsave(&icom_lock, flags);
- port = icom_port->port;
- if (port == 0 || port == 1)
- int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
- else
- int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
-
- if (port == 0 || port == 2)
- writew(0x00FF, icom_port->int_reg);
- else
- writew(0x3F00, icom_port->int_reg);
- if (port < 4) {
- temp = readl(int_mask_tbl[port].global_int_mask);
- writel(temp & ~int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
-
- /* write flush */
- readl(int_mask_tbl[port].global_int_mask);
- } else {
- dev_err(&icom_port->adapter->pci_dev->dev,
- "Invalid port assignment\n");
- }
-
- spin_unlock_irqrestore(&icom_lock, flags);
- return 0;
-}
-
-static void shutdown(struct icom_port *icom_port)
-{
- unsigned long temp;
- unsigned char cmdReg;
- unsigned long flags;
- int port;
-
- spin_lock_irqsave(&icom_lock, flags);
- trace(icom_port, "SHUTDOWN", 0);
-
- /*
- * disable all interrupts
- */
- port = icom_port->port;
- if (port == 0 || port == 1)
- int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
- else
- int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
-
- if (port < 4) {
- temp = readl(int_mask_tbl[port].global_int_mask);
- writel(temp | int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
-
- /* write flush */
- readl(int_mask_tbl[port].global_int_mask);
- } else {
- dev_err(&icom_port->adapter->pci_dev->dev,
- "Invalid port assignment\n");
- }
- spin_unlock_irqrestore(&icom_lock, flags);
-
- /*
- * disable break condition
- */
- cmdReg = readb(&icom_port->dram->CmdReg);
- if (cmdReg & CMD_SND_BREAK) {
- writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg);
- }
-}
-
-static int icom_write(struct uart_port *port)
-{
- unsigned long data_count;
- unsigned char cmdReg;
- unsigned long offset;
- int temp_tail = port->state->xmit.tail;
-
- trace(ICOM_PORT, "WRITE", 0);
-
- if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
- SA_FLAGS_READY_TO_XMIT) {
- trace(ICOM_PORT, "WRITE_FULL", 0);
- return 0;
- }
-
- data_count = 0;
- while ((port->state->xmit.head != temp_tail) &&
- (data_count <= XMIT_BUFF_SZ)) {
-
- ICOM_PORT->xmit_buf[data_count++] =
- port->state->xmit.buf[temp_tail];
-
- temp_tail++;
- temp_tail &= (UART_XMIT_SIZE - 1);
- }
-
- if (data_count) {
- ICOM_PORT->statStg->xmit[0].flags =
- cpu_to_le16(SA_FLAGS_READY_TO_XMIT);
- ICOM_PORT->statStg->xmit[0].leLength =
- cpu_to_le16(data_count);
- offset =
- (unsigned long) &ICOM_PORT->statStg->xmit[0] -
- (unsigned long) ICOM_PORT->statStg;
- *ICOM_PORT->xmitRestart =
- cpu_to_le32(ICOM_PORT->statStg_pci + offset);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
- &ICOM_PORT->dram->CmdReg);
- writeb(START_XMIT, &ICOM_PORT->dram->StartXmitCmd);
- trace(ICOM_PORT, "WRITE_START", data_count);
- /* write flush */
- readb(&ICOM_PORT->dram->StartXmitCmd);
- }
-
- return data_count;
-}
-
-static inline void check_modem_status(struct icom_port *icom_port)
-{
- static char old_status = 0;
- char delta_status;
- unsigned char status;
-
- spin_lock(&icom_port->uart_port.lock);
-
- /*modem input register */
- status = readb(&icom_port->dram->isr);
- trace(icom_port, "CHECK_MODEM", status);
- delta_status = status ^ old_status;
- if (delta_status) {
- if (delta_status & ICOM_RI)
- icom_port->uart_port.icount.rng++;
- if (delta_status & ICOM_DSR)
- icom_port->uart_port.icount.dsr++;
- if (delta_status & ICOM_DCD)
- uart_handle_dcd_change(&icom_port->uart_port,
- delta_status & ICOM_DCD);
- if (delta_status & ICOM_CTS)
- uart_handle_cts_change(&icom_port->uart_port,
- delta_status & ICOM_CTS);
-
- wake_up_interruptible(&icom_port->uart_port.state->
- port.delta_msr_wait);
- old_status = status;
- }
- spin_unlock(&icom_port->uart_port.lock);
-}
-
-static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
-{
- unsigned short int count;
- int i;
-
- if (port_int_reg & (INT_XMIT_COMPLETED)) {
- trace(icom_port, "XMIT_COMPLETE", 0);
-
- /* clear buffer in use bit */
- icom_port->statStg->xmit[0].flags &=
- cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
-
- count = (unsigned short int)
- cpu_to_le16(icom_port->statStg->xmit[0].leLength);
- icom_port->uart_port.icount.tx += count;
-
- for (i=0; i<count &&
- !uart_circ_empty(&icom_port->uart_port.state->xmit); i++) {
-
- icom_port->uart_port.state->xmit.tail++;
- icom_port->uart_port.state->xmit.tail &=
- (UART_XMIT_SIZE - 1);
- }
-
- if (!icom_write(&icom_port->uart_port))
- /* activate write queue */
- uart_write_wakeup(&icom_port->uart_port);
- } else
- trace(icom_port, "XMIT_DISABLED", 0);
-}
-
-static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
-{
- short int count, rcv_buff;
- struct tty_struct *tty = icom_port->uart_port.state->port.tty;
- unsigned short int status;
- struct uart_icount *icount;
- unsigned long offset;
- unsigned char flag;
-
- trace(icom_port, "RCV_COMPLETE", 0);
- rcv_buff = icom_port->next_rcv;
-
- status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
- while (status & SA_FL_RCV_DONE) {
- int first = -1;
-
- trace(icom_port, "FID_STATUS", status);
- count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
-
- trace(icom_port, "RCV_COUNT", count);
-
- trace(icom_port, "REAL_COUNT", count);
-
- offset =
- cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
- icom_port->recv_buf_pci;
-
- /* Block copy all but the last byte as this may have status */
- if (count > 0) {
- first = icom_port->recv_buf[offset];
- tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1);
- }
-
- icount = &icom_port->uart_port.icount;
- icount->rx += count;
-
- /* Break detect logic */
- if ((status & SA_FLAGS_FRAME_ERROR)
- && first == 0) {
- status &= ~SA_FLAGS_FRAME_ERROR;
- status |= SA_FLAGS_BREAK_DET;
- trace(icom_port, "BREAK_DET", 0);
- }
-
- flag = TTY_NORMAL;
-
- if (status &
- (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
- SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
-
- if (status & SA_FLAGS_BREAK_DET)
- icount->brk++;
- if (status & SA_FLAGS_PARITY_ERROR)
- icount->parity++;
- if (status & SA_FLAGS_FRAME_ERROR)
- icount->frame++;
- if (status & SA_FLAGS_OVERRUN)
- icount->overrun++;
-
- /*
- * Now check to see if character should be
- * ignored, and mask off conditions which
- * should be ignored.
- */
- if (status & icom_port->ignore_status_mask) {
- trace(icom_port, "IGNORE_CHAR", 0);
- goto ignore_char;
- }
-
- status &= icom_port->read_status_mask;
-
- if (status & SA_FLAGS_BREAK_DET) {
- flag = TTY_BREAK;
- } else if (status & SA_FLAGS_PARITY_ERROR) {
- trace(icom_port, "PARITY_ERROR", 0);
- flag = TTY_PARITY;
- } else if (status & SA_FLAGS_FRAME_ERROR)
- flag = TTY_FRAME;
-
- }
-
- tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag);
-
- if (status & SA_FLAGS_OVERRUN)
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-ignore_char:
- icom_port->statStg->rcv[rcv_buff].flags = 0;
- icom_port->statStg->rcv[rcv_buff].leLength = 0;
- icom_port->statStg->rcv[rcv_buff].WorkingLength =
- (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
-
- rcv_buff++;
- if (rcv_buff == NUM_RBUFFS)
- rcv_buff = 0;
-
- status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
- }
- icom_port->next_rcv = rcv_buff;
- tty_flip_buffer_push(tty);
-}
-
-static void process_interrupt(u16 port_int_reg,
- struct icom_port *icom_port)
-{
-
- spin_lock(&icom_port->uart_port.lock);
- trace(icom_port, "INTERRUPT", port_int_reg);
-
- if (port_int_reg & (INT_XMIT_COMPLETED | INT_XMIT_DISABLED))
- xmit_interrupt(port_int_reg, icom_port);
-
- if (port_int_reg & INT_RCV_COMPLETED)
- recv_interrupt(port_int_reg, icom_port);
-
- spin_unlock(&icom_port->uart_port.lock);
-}
-
-static irqreturn_t icom_interrupt(int irq, void *dev_id)
-{
- void __iomem * int_reg;
- u32 adapter_interrupts;
- u16 port_int_reg;
- struct icom_adapter *icom_adapter;
- struct icom_port *icom_port;
-
- /* find icom_port for this interrupt */
- icom_adapter = (struct icom_adapter *) dev_id;
-
- if (icom_adapter->version == ADAPTER_V2) {
- int_reg = icom_adapter->base_addr + 0x8024;
-
- adapter_interrupts = readl(int_reg);
-
- if (adapter_interrupts & 0x00003FFF) {
- /* port 2 interrupt, NOTE: for all ADAPTER_V2, port 2 will be active */
- icom_port = &icom_adapter->port_info[2];
- port_int_reg = (u16) adapter_interrupts;
- process_interrupt(port_int_reg, icom_port);
- check_modem_status(icom_port);
- }
- if (adapter_interrupts & 0x3FFF0000) {
- /* port 3 interrupt */
- icom_port = &icom_adapter->port_info[3];
- if (icom_port->status == ICOM_PORT_ACTIVE) {
- port_int_reg =
- (u16) (adapter_interrupts >> 16);
- process_interrupt(port_int_reg, icom_port);
- check_modem_status(icom_port);
- }
- }
-
- /* Clear out any pending interrupts */
- writel(adapter_interrupts, int_reg);
-
- int_reg = icom_adapter->base_addr + 0x8004;
- } else {
- int_reg = icom_adapter->base_addr + 0x4004;
- }
-
- adapter_interrupts = readl(int_reg);
-
- if (adapter_interrupts & 0x00003FFF) {
- /* port 0 interrupt, NOTE: for all adapters, port 0 will be active */
- icom_port = &icom_adapter->port_info[0];
- port_int_reg = (u16) adapter_interrupts;
- process_interrupt(port_int_reg, icom_port);
- check_modem_status(icom_port);
- }
- if (adapter_interrupts & 0x3FFF0000) {
- /* port 1 interrupt */
- icom_port = &icom_adapter->port_info[1];
- if (icom_port->status == ICOM_PORT_ACTIVE) {
- port_int_reg = (u16) (adapter_interrupts >> 16);
- process_interrupt(port_int_reg, icom_port);
- check_modem_status(icom_port);
- }
- }
-
- /* Clear out any pending interrupts */
- writel(adapter_interrupts, int_reg);
-
- /* flush the write */
- adapter_interrupts = readl(int_reg);
-
- return IRQ_HANDLED;
-}
-
-/*
- * ------------------------------------------------------------------
- * Begin serial-core API
- * ------------------------------------------------------------------
- */
-static unsigned int icom_tx_empty(struct uart_port *port)
-{
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
- SA_FLAGS_READY_TO_XMIT)
- ret = TIOCSER_TEMT;
- else
- ret = 0;
-
- spin_unlock_irqrestore(&port->lock, flags);
- return ret;
-}
-
-static void icom_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- unsigned char local_osr;
-
- trace(ICOM_PORT, "SET_MODEM", 0);
- local_osr = readb(&ICOM_PORT->dram->osr);
-
- if (mctrl & TIOCM_RTS) {
- trace(ICOM_PORT, "RAISE_RTS", 0);
- local_osr |= ICOM_RTS;
- } else {
- trace(ICOM_PORT, "LOWER_RTS", 0);
- local_osr &= ~ICOM_RTS;
- }
-
- if (mctrl & TIOCM_DTR) {
- trace(ICOM_PORT, "RAISE_DTR", 0);
- local_osr |= ICOM_DTR;
- } else {
- trace(ICOM_PORT, "LOWER_DTR", 0);
- local_osr &= ~ICOM_DTR;
- }
-
- writeb(local_osr, &ICOM_PORT->dram->osr);
-}
-
-static unsigned int icom_get_mctrl(struct uart_port *port)
-{
- unsigned char status;
- unsigned int result;
-
- trace(ICOM_PORT, "GET_MODEM", 0);
-
- status = readb(&ICOM_PORT->dram->isr);
-
- result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
- | ((status & ICOM_RI) ? TIOCM_RNG : 0)
- | ((status & ICOM_DSR) ? TIOCM_DSR : 0)
- | ((status & ICOM_CTS) ? TIOCM_CTS : 0);
- return result;
-}
-
-static void icom_stop_tx(struct uart_port *port)
-{
- unsigned char cmdReg;
-
- trace(ICOM_PORT, "STOP", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
-}
-
-static void icom_start_tx(struct uart_port *port)
-{
- unsigned char cmdReg;
-
- trace(ICOM_PORT, "START", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
- writeb(cmdReg & ~CMD_HOLD_XMIT,
- &ICOM_PORT->dram->CmdReg);
-
- icom_write(port);
-}
-
-static void icom_send_xchar(struct uart_port *port, char ch)
-{
- unsigned char xdata;
- int index;
- unsigned long flags;
-
- trace(ICOM_PORT, "SEND_XCHAR", ch);
-
- /* wait .1 sec to send char */
- for (index = 0; index < 10; index++) {
- spin_lock_irqsave(&port->lock, flags);
- xdata = readb(&ICOM_PORT->dram->xchar);
- if (xdata == 0x00) {
- trace(ICOM_PORT, "QUICK_WRITE", 0);
- writeb(ch, &ICOM_PORT->dram->xchar);
-
- /* flush write operation */
- xdata = readb(&ICOM_PORT->dram->xchar);
- spin_unlock_irqrestore(&port->lock, flags);
- break;
- }
- spin_unlock_irqrestore(&port->lock, flags);
- msleep(10);
- }
-}
-
-static void icom_stop_rx(struct uart_port *port)
-{
- unsigned char cmdReg;
-
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
-}
-
-static void icom_enable_ms(struct uart_port *port)
-{
- /* no-op */
-}
-
-static void icom_break(struct uart_port *port, int break_state)
-{
- unsigned char cmdReg;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- trace(ICOM_PORT, "BREAK", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- if (break_state == -1) {
- writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
- } else {
- writeb(cmdReg & ~CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
- }
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int icom_open(struct uart_port *port)
-{
- int retval;
-
- kref_get(&ICOM_PORT->adapter->kref);
- retval = startup(ICOM_PORT);
-
- if (retval) {
- kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
- trace(ICOM_PORT, "STARTUP_ERROR", 0);
- return retval;
- }
-
- return 0;
-}
-
-static void icom_close(struct uart_port *port)
-{
- unsigned char cmdReg;
-
- trace(ICOM_PORT, "CLOSE", 0);
-
- /* stop receiver */
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg & (unsigned char) ~CMD_RCV_ENABLE,
- &ICOM_PORT->dram->CmdReg);
-
- shutdown(ICOM_PORT);
-
- kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
-}
-
-static void icom_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old_termios)
-{
- int baud;
- unsigned cflag, iflag;
- char new_config2;
- char new_config3 = 0;
- char tmp_byte;
- int index;
- int rcv_buff, xmit_buff;
- unsigned long offset;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- trace(ICOM_PORT, "CHANGE_SPEED", 0);
-
- cflag = termios->c_cflag;
- iflag = termios->c_iflag;
-
- new_config2 = ICOM_ACFG_DRIVE1;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: /* 5 bits/char */
- new_config2 |= ICOM_ACFG_5BPC;
- break;
- case CS6: /* 6 bits/char */
- new_config2 |= ICOM_ACFG_6BPC;
- break;
- case CS7: /* 7 bits/char */
- new_config2 |= ICOM_ACFG_7BPC;
- break;
- case CS8: /* 8 bits/char */
- new_config2 |= ICOM_ACFG_8BPC;
- break;
- default:
- break;
- }
- if (cflag & CSTOPB) {
- /* 2 stop bits */
- new_config2 |= ICOM_ACFG_2STOP_BIT;
- }
- if (cflag & PARENB) {
- /* parity bit enabled */
- new_config2 |= ICOM_ACFG_PARITY_ENAB;
- trace(ICOM_PORT, "PARENB", 0);
- }
- if (cflag & PARODD) {
- /* odd parity */
- new_config2 |= ICOM_ACFG_PARITY_ODD;
- trace(ICOM_PORT, "PARODD", 0);
- }
-
- /* Determine divisor based on baud rate */
- baud = uart_get_baud_rate(port, termios, old_termios,
- icom_acfg_baud[0],
- icom_acfg_baud[BAUD_TABLE_LIMIT]);
- if (!baud)
- baud = 9600; /* B0 transition handled in rs_set_termios */
-
- for (index = 0; index < BAUD_TABLE_LIMIT; index++) {
- if (icom_acfg_baud[index] == baud) {
- new_config3 = index;
- break;
- }
- }
-
- uart_update_timeout(port, cflag, baud);
-
- /* CTS flow control flag and modem status interrupts */
- tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
- if (cflag & CRTSCTS)
- tmp_byte |= HDLC_HDW_FLOW;
- else
- tmp_byte &= ~HDLC_HDW_FLOW;
- writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
-
- /*
- * Set up parity check flag
- */
- ICOM_PORT->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
- if (iflag & INPCK)
- ICOM_PORT->read_status_mask |=
- SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
-
- if ((iflag & BRKINT) || (iflag & PARMRK))
- ICOM_PORT->read_status_mask |= SA_FLAGS_BREAK_DET;
-
- /*
- * Characters to ignore
- */
- ICOM_PORT->ignore_status_mask = 0;
- if (iflag & IGNPAR)
- ICOM_PORT->ignore_status_mask |=
- SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
- if (iflag & IGNBRK) {
- ICOM_PORT->ignore_status_mask |= SA_FLAGS_BREAK_DET;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (iflag & IGNPAR)
- ICOM_PORT->ignore_status_mask |= SA_FLAGS_OVERRUN;
- }
-
- /*
- * !!! ignore all characters if CREAD is not set
- */
- if ((cflag & CREAD) == 0)
- ICOM_PORT->ignore_status_mask |= SA_FL_RCV_DONE;
-
- /* Turn off Receiver to prepare for reset */
- writeb(CMD_RCV_DISABLE, &ICOM_PORT->dram->CmdReg);
-
- for (index = 0; index < 10; index++) {
- if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
- break;
- }
- }
-
- /* clear all current buffers of data */
- for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
- ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
- ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
- ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
- (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
- }
-
- for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
- ICOM_PORT->statStg->xmit[xmit_buff].flags = 0;
- }
-
- /* activate changes and start xmit and receiver here */
- /* Enable the receiver */
- writeb(new_config3, &(ICOM_PORT->dram->async_config3));
- writeb(new_config2, &(ICOM_PORT->dram->async_config2));
- tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
- tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
- writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
- writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer)); /* 0.5 seconds */
- writeb(0xFF, &(ICOM_PORT->dram->ier)); /* enable modem signal interrupts */
-
- /* reset processor */
- writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
-
- for (index = 0; index < 10; index++) {
- if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
- break;
- }
- }
-
- /* Enable Transmitter and Reciever */
- offset =
- (unsigned long) &ICOM_PORT->statStg->rcv[0] -
- (unsigned long) ICOM_PORT->statStg;
- writel(ICOM_PORT->statStg_pci + offset,
- &ICOM_PORT->dram->RcvStatusAddr);
- ICOM_PORT->next_rcv = 0;
- ICOM_PORT->put_length = 0;
- *ICOM_PORT->xmitRestart = 0;
- writel(ICOM_PORT->xmitRestart_pci,
- &ICOM_PORT->dram->XmitStatusAddr);
- trace(ICOM_PORT, "XR_ENAB", 0);
- writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *icom_type(struct uart_port *port)
-{
- return "icom";
-}
-
-static void icom_release_port(struct uart_port *port)
-{
-}
-
-static int icom_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void icom_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_ICOM;
-}
-
-static struct uart_ops icom_ops = {
- .tx_empty = icom_tx_empty,
- .set_mctrl = icom_set_mctrl,
- .get_mctrl = icom_get_mctrl,
- .stop_tx = icom_stop_tx,
- .start_tx = icom_start_tx,
- .send_xchar = icom_send_xchar,
- .stop_rx = icom_stop_rx,
- .enable_ms = icom_enable_ms,
- .break_ctl = icom_break,
- .startup = icom_open,
- .shutdown = icom_close,
- .set_termios = icom_set_termios,
- .type = icom_type,
- .release_port = icom_release_port,
- .request_port = icom_request_port,
- .config_port = icom_config_port,
-};
-
-#define ICOM_CONSOLE NULL
-
-static struct uart_driver icom_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = ICOM_DRIVER_NAME,
- .dev_name = "ttyA",
- .major = ICOM_MAJOR,
- .minor = ICOM_MINOR_START,
- .nr = NR_PORTS,
- .cons = ICOM_CONSOLE,
-};
-
-static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
-{
- u32 subsystem_id = icom_adapter->subsystem_id;
- int i;
- struct icom_port *icom_port;
-
- if (icom_adapter->version == ADAPTER_V1) {
- icom_adapter->numb_ports = 2;
-
- for (i = 0; i < 2; i++) {
- icom_port = &icom_adapter->port_info[i];
- icom_port->port = i;
- icom_port->status = ICOM_PORT_ACTIVE;
- icom_port->imbed_modem = ICOM_UNKNOWN;
- }
- } else {
- if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
- icom_adapter->numb_ports = 4;
-
- for (i = 0; i < 4; i++) {
- icom_port = &icom_adapter->port_info[i];
-
- icom_port->port = i;
- icom_port->status = ICOM_PORT_ACTIVE;
- icom_port->imbed_modem = ICOM_IMBED_MODEM;
- }
- } else {
- icom_adapter->numb_ports = 4;
-
- icom_adapter->port_info[0].port = 0;
- icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
-
- if (subsystem_id ==
- PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM) {
- icom_adapter->port_info[0].imbed_modem = ICOM_IMBED_MODEM;
- } else {
- icom_adapter->port_info[0].imbed_modem = ICOM_RVX;
- }
-
- icom_adapter->port_info[1].status = ICOM_PORT_OFF;
-
- icom_adapter->port_info[2].port = 2;
- icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
- icom_adapter->port_info[2].imbed_modem = ICOM_RVX;
- icom_adapter->port_info[3].status = ICOM_PORT_OFF;
- }
- }
-
- return 0;
-}
-
-static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *icom_adapter, int port_num)
-{
- if (icom_adapter->version == ADAPTER_V1) {
- icom_port->global_reg = icom_adapter->base_addr + 0x4000;
- icom_port->int_reg = icom_adapter->base_addr +
- 0x4004 + 2 - 2 * port_num;
- } else {
- icom_port->global_reg = icom_adapter->base_addr + 0x8000;
- if (icom_port->port < 2)
- icom_port->int_reg = icom_adapter->base_addr +
- 0x8004 + 2 - 2 * icom_port->port;
- else
- icom_port->int_reg = icom_adapter->base_addr +
- 0x8024 + 2 - 2 * (icom_port->port - 2);
- }
-}
-static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
-{
- struct icom_port *icom_port;
- int port_num;
-
- for (port_num = 0; port_num < icom_adapter->numb_ports; port_num++) {
-
- icom_port = &icom_adapter->port_info[port_num];
-
- if (icom_port->status == ICOM_PORT_ACTIVE) {
- icom_port_active(icom_port, icom_adapter, port_num);
- icom_port->dram = icom_adapter->base_addr +
- 0x2000 * icom_port->port;
-
- icom_port->adapter = icom_adapter;
-
- /* get port memory */
- if (get_port_memory(icom_port) != 0) {
- dev_err(&icom_port->adapter->pci_dev->dev,
- "Memory allocation for port FAILED\n");
- }
- }
- }
- return 0;
-}
-
-static int __devinit icom_alloc_adapter(struct icom_adapter
- **icom_adapter_ref)
-{
- int adapter_count = 0;
- struct icom_adapter *icom_adapter;
- struct icom_adapter *cur_adapter_entry;
- struct list_head *tmp;
-
- icom_adapter = (struct icom_adapter *)
- kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
-
- if (!icom_adapter) {
- return -ENOMEM;
- }
-
- list_for_each(tmp, &icom_adapter_head) {
- cur_adapter_entry =
- list_entry(tmp, struct icom_adapter,
- icom_adapter_entry);
- if (cur_adapter_entry->index != adapter_count) {
- break;
- }
- adapter_count++;
- }
-
- icom_adapter->index = adapter_count;
- list_add_tail(&icom_adapter->icom_adapter_entry, tmp);
-
- *icom_adapter_ref = icom_adapter;
- return 0;
-}
-
-static void icom_free_adapter(struct icom_adapter *icom_adapter)
-{
- list_del(&icom_adapter->icom_adapter_entry);
- kfree(icom_adapter);
-}
-
-static void icom_remove_adapter(struct icom_adapter *icom_adapter)
-{
- struct icom_port *icom_port;
- int index;
-
- for (index = 0; index < icom_adapter->numb_ports; index++) {
- icom_port = &icom_adapter->port_info[index];
-
- if (icom_port->status == ICOM_PORT_ACTIVE) {
- dev_info(&icom_adapter->pci_dev->dev,
- "Device removed\n");
-
- uart_remove_one_port(&icom_uart_driver,
- &icom_port->uart_port);
-
- /* be sure that DTR and RTS are dropped */
- writeb(0x00, &icom_port->dram->osr);
-
- /* Wait 0.1 Sec for simple Init to complete */
- msleep(100);
-
- /* Stop proccessor */
- stop_processor(icom_port);
-
- free_port_memory(icom_port);
- }
- }
-
- free_irq(icom_adapter->pci_dev->irq, (void *) icom_adapter);
- iounmap(icom_adapter->base_addr);
- pci_release_regions(icom_adapter->pci_dev);
- icom_free_adapter(icom_adapter);
-}
-
-static void icom_kref_release(struct kref *kref)
-{
- struct icom_adapter *icom_adapter;
-
- icom_adapter = to_icom_adapter(kref);
- icom_remove_adapter(icom_adapter);
-}
-
-static int __devinit icom_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- int index;
- unsigned int command_reg;
- int retval;
- struct icom_adapter *icom_adapter;
- struct icom_port *icom_port;
-
- retval = pci_enable_device(dev);
- if (retval) {
- dev_err(&dev->dev, "Device enable FAILED\n");
- return retval;
- }
-
- if ( (retval = pci_request_regions(dev, "icom"))) {
- dev_err(&dev->dev, "pci_request_regions FAILED\n");
- pci_disable_device(dev);
- return retval;
- }
-
- pci_set_master(dev);
-
- if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
- dev_err(&dev->dev, "PCI Config read FAILED\n");
- return retval;
- }
-
- pci_write_config_dword(dev, PCI_COMMAND,
- command_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
- | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
-
- if (ent->driver_data == ADAPTER_V1) {
- pci_write_config_dword(dev, 0x44, 0x8300830A);
- } else {
- pci_write_config_dword(dev, 0x44, 0x42004200);
- pci_write_config_dword(dev, 0x48, 0x42004200);
- }
-
-
- retval = icom_alloc_adapter(&icom_adapter);
- if (retval) {
- dev_err(&dev->dev, "icom_alloc_adapter FAILED\n");
- retval = -EIO;
- goto probe_exit0;
- }
-
- icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
- icom_adapter->pci_dev = dev;
- icom_adapter->version = ent->driver_data;
- icom_adapter->subsystem_id = ent->subdevice;
-
-
- retval = icom_init_ports(icom_adapter);
- if (retval) {
- dev_err(&dev->dev, "Port configuration failed\n");
- goto probe_exit1;
- }
-
- icom_adapter->base_addr = pci_ioremap_bar(dev, 0);
-
- if (!icom_adapter->base_addr)
- goto probe_exit1;
-
- /* save off irq and request irq line */
- if ( (retval = request_irq(dev->irq, icom_interrupt,
- IRQF_DISABLED | IRQF_SHARED, ICOM_DRIVER_NAME,
- (void *) icom_adapter))) {
- goto probe_exit2;
- }
-
- retval = icom_load_ports(icom_adapter);
-
- for (index = 0; index < icom_adapter->numb_ports; index++) {
- icom_port = &icom_adapter->port_info[index];
-
- if (icom_port->status == ICOM_PORT_ACTIVE) {
- icom_port->uart_port.irq = icom_port->adapter->pci_dev->irq;
- icom_port->uart_port.type = PORT_ICOM;
- icom_port->uart_port.iotype = UPIO_MEM;
- icom_port->uart_port.membase =
- (char *) icom_adapter->base_addr_pci;
- icom_port->uart_port.fifosize = 16;
- icom_port->uart_port.ops = &icom_ops;
- icom_port->uart_port.line =
- icom_port->port + icom_adapter->index * 4;
- if (uart_add_one_port (&icom_uart_driver, &icom_port->uart_port)) {
- icom_port->status = ICOM_PORT_OFF;
- dev_err(&dev->dev, "Device add failed\n");
- } else
- dev_info(&dev->dev, "Device added\n");
- }
- }
-
- kref_init(&icom_adapter->kref);
- return 0;
-
-probe_exit2:
- iounmap(icom_adapter->base_addr);
-probe_exit1:
- icom_free_adapter(icom_adapter);
-
-probe_exit0:
- pci_release_regions(dev);
- pci_disable_device(dev);
-
- return retval;
-}
-
-static void __devexit icom_remove(struct pci_dev *dev)
-{
- struct icom_adapter *icom_adapter;
- struct list_head *tmp;
-
- list_for_each(tmp, &icom_adapter_head) {
- icom_adapter = list_entry(tmp, struct icom_adapter,
- icom_adapter_entry);
- if (icom_adapter->pci_dev == dev) {
- kref_put(&icom_adapter->kref, icom_kref_release);
- return;
- }
- }
-
- dev_err(&dev->dev, "Unable to find device to remove\n");
-}
-
-static struct pci_driver icom_pci_driver = {
- .name = ICOM_DRIVER_NAME,
- .id_table = icom_pci_table,
- .probe = icom_probe,
- .remove = __devexit_p(icom_remove),
-};
-
-static int __init icom_init(void)
-{
- int ret;
-
- spin_lock_init(&icom_lock);
-
- ret = uart_register_driver(&icom_uart_driver);
- if (ret)
- return ret;
-
- ret = pci_register_driver(&icom_pci_driver);
-
- if (ret < 0)
- uart_unregister_driver(&icom_uart_driver);
-
- return ret;
-}
-
-static void __exit icom_exit(void)
-{
- pci_unregister_driver(&icom_pci_driver);
- uart_unregister_driver(&icom_uart_driver);
-}
-
-module_init(icom_init);
-module_exit(icom_exit);
-
-MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>");
-MODULE_DESCRIPTION("IBM iSeries Serial IOA driver");
-MODULE_SUPPORTED_DEVICE
- ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("icom_call_setup.bin");
-MODULE_FIRMWARE("icom_res_dce.bin");
-MODULE_FIRMWARE("icom_asc.bin");
diff --git a/drivers/serial/icom.h b/drivers/serial/icom.h
deleted file mode 100644
index c8029e0025c9..000000000000
--- a/drivers/serial/icom.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * icom.h
- *
- * Copyright (C) 2001 Michael Anderson, IBM Corporation
- *
- * Serial device driver include file.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/serial_core.h>
-
-#define BAUD_TABLE_LIMIT ((sizeof(icom_acfg_baud)/sizeof(int)) - 1)
-static int icom_acfg_baud[] = {
- 300,
- 600,
- 900,
- 1200,
- 1800,
- 2400,
- 3600,
- 4800,
- 7200,
- 9600,
- 14400,
- 19200,
- 28800,
- 38400,
- 57600,
- 76800,
- 115200,
- 153600,
- 230400,
- 307200,
- 460800,
-};
-
-struct icom_regs {
- u32 control; /* Adapter Control Register */
- u32 interrupt; /* Adapter Interrupt Register */
- u32 int_mask; /* Adapter Interrupt Mask Reg */
- u32 int_pri; /* Adapter Interrupt Priority r */
- u32 int_reg_b; /* Adapter non-masked Interrupt */
- u32 resvd01;
- u32 resvd02;
- u32 resvd03;
- u32 control_2; /* Adapter Control Register 2 */
- u32 interrupt_2; /* Adapter Interrupt Register 2 */
- u32 int_mask_2; /* Adapter Interrupt Mask 2 */
- u32 int_pri_2; /* Adapter Interrupt Prior 2 */
- u32 int_reg_2b; /* Adapter non-masked 2 */
-};
-
-struct func_dram {
- u32 reserved[108]; /* 0-1B0 reserved by personality code */
- u32 RcvStatusAddr; /* 1B0-1B3 Status Address for Next rcv */
- u8 RcvStnAddr; /* 1B4 Receive Station Addr */
- u8 IdleState; /* 1B5 Idle State */
- u8 IdleMonitor; /* 1B6 Idle Monitor */
- u8 FlagFillIdleTimer; /* 1B7 Flag Fill Idle Timer */
- u32 XmitStatusAddr; /* 1B8-1BB Transmit Status Address */
- u8 StartXmitCmd; /* 1BC Start Xmit Command */
- u8 HDLCConfigReg; /* 1BD Reserved */
- u8 CauseCode; /* 1BE Cause code for fatal error */
- u8 xchar; /* 1BF High priority send */
- u32 reserved3; /* 1C0-1C3 Reserved */
- u8 PrevCmdReg; /* 1C4 Reserved */
- u8 CmdReg; /* 1C5 Command Register */
- u8 async_config2; /* 1C6 Async Config Byte 2 */
- u8 async_config3; /* 1C7 Async Config Byte 3 */
- u8 dce_resvd[20]; /* 1C8-1DB DCE Rsvd */
- u8 dce_resvd21; /* 1DC DCE Rsvd (21st byte */
- u8 misc_flags; /* 1DD misc flags */
-#define V2_HARDWARE 0x40
-#define ICOM_HDW_ACTIVE 0x01
- u8 call_length; /* 1DE Phone #/CFI buff ln */
- u8 call_length2; /* 1DF Upper byte (unused) */
- u32 call_addr; /* 1E0-1E3 Phn #/CFI buff addr */
- u16 timer_value; /* 1E4-1E5 general timer value */
- u8 timer_command; /* 1E6 general timer cmd */
- u8 dce_command; /* 1E7 dce command reg */
- u8 dce_cmd_status; /* 1E8 dce command stat */
- u8 x21_r1_ioff; /* 1E9 dce ready counter */
- u8 x21_r0_ioff; /* 1EA dce not ready ctr */
- u8 x21_ralt_ioff; /* 1EB dce CNR counter */
- u8 x21_r1_ion; /* 1EC dce ready I on ctr */
- u8 rsvd_ier; /* 1ED Rsvd for IER (if ne */
- u8 ier; /* 1EE Interrupt Enable */
- u8 isr; /* 1EF Input Signal Reg */
- u8 osr; /* 1F0 Output Signal Reg */
- u8 reset; /* 1F1 Reset/Reload Reg */
- u8 disable; /* 1F2 Disable Reg */
- u8 sync; /* 1F3 Sync Reg */
- u8 error_stat; /* 1F4 Error Status */
- u8 cable_id; /* 1F5 Cable ID */
- u8 cs_length; /* 1F6 CS Load Length */
- u8 mac_length; /* 1F7 Mac Load Length */
- u32 cs_load_addr; /* 1F8-1FB Call Load PCI Addr */
- u32 mac_load_addr; /* 1FC-1FF Mac Load PCI Addr */
-};
-
-/*
- * adapter defines and structures
- */
-#define ICOM_CONTROL_START_A 0x00000008
-#define ICOM_CONTROL_STOP_A 0x00000004
-#define ICOM_CONTROL_START_B 0x00000002
-#define ICOM_CONTROL_STOP_B 0x00000001
-#define ICOM_CONTROL_START_C 0x00000008
-#define ICOM_CONTROL_STOP_C 0x00000004
-#define ICOM_CONTROL_START_D 0x00000002
-#define ICOM_CONTROL_STOP_D 0x00000001
-#define ICOM_IRAM_OFFSET 0x1000
-#define ICOM_IRAM_SIZE 0x0C00
-#define ICOM_DCE_IRAM_OFFSET 0x0A00
-#define ICOM_CABLE_ID_VALID 0x01
-#define ICOM_CABLE_ID_MASK 0xF0
-#define ICOM_DISABLE 0x80
-#define CMD_XMIT_RCV_ENABLE 0xC0
-#define CMD_XMIT_ENABLE 0x40
-#define CMD_RCV_DISABLE 0x00
-#define CMD_RCV_ENABLE 0x80
-#define CMD_RESTART 0x01
-#define CMD_HOLD_XMIT 0x02
-#define CMD_SND_BREAK 0x04
-#define RS232_CABLE 0x06
-#define V24_CABLE 0x0E
-#define V35_CABLE 0x0C
-#define V36_CABLE 0x02
-#define NO_CABLE 0x00
-#define START_DOWNLOAD 0x80
-#define ICOM_INT_MASK_PRC_A 0x00003FFF
-#define ICOM_INT_MASK_PRC_B 0x3FFF0000
-#define ICOM_INT_MASK_PRC_C 0x00003FFF
-#define ICOM_INT_MASK_PRC_D 0x3FFF0000
-#define INT_RCV_COMPLETED 0x1000
-#define INT_XMIT_COMPLETED 0x2000
-#define INT_IDLE_DETECT 0x0800
-#define INT_RCV_DISABLED 0x0400
-#define INT_XMIT_DISABLED 0x0200
-#define INT_RCV_XMIT_SHUTDOWN 0x0100
-#define INT_FATAL_ERROR 0x0080
-#define INT_CABLE_PULL 0x0020
-#define INT_SIGNAL_CHANGE 0x0010
-#define HDLC_PPP_PURE_ASYNC 0x02
-#define HDLC_FF_FILL 0x00
-#define HDLC_HDW_FLOW 0x01
-#define START_XMIT 0x80
-#define ICOM_ACFG_DRIVE1 0x20
-#define ICOM_ACFG_NO_PARITY 0x00
-#define ICOM_ACFG_PARITY_ENAB 0x02
-#define ICOM_ACFG_PARITY_ODD 0x01
-#define ICOM_ACFG_8BPC 0x00
-#define ICOM_ACFG_7BPC 0x04
-#define ICOM_ACFG_6BPC 0x08
-#define ICOM_ACFG_5BPC 0x0C
-#define ICOM_ACFG_1STOP_BIT 0x00
-#define ICOM_ACFG_2STOP_BIT 0x10
-#define ICOM_DTR 0x80
-#define ICOM_RTS 0x40
-#define ICOM_RI 0x08
-#define ICOM_DSR 0x80
-#define ICOM_DCD 0x20
-#define ICOM_CTS 0x40
-
-#define NUM_XBUFFS 1
-#define NUM_RBUFFS 2
-#define RCV_BUFF_SZ 0x0200
-#define XMIT_BUFF_SZ 0x1000
-struct statusArea {
- /**********************************************/
- /* Transmit Status Area */
- /**********************************************/
- struct xmit_status_area{
- u32 leNext; /* Next entry in Little Endian on Adapter */
- u32 leNextASD;
- u32 leBuffer; /* Buffer for entry in LE for Adapter */
- u16 leLengthASD;
- u16 leOffsetASD;
- u16 leLength; /* Length of data in segment */
- u16 flags;
-#define SA_FLAGS_DONE 0x0080 /* Done with Segment */
-#define SA_FLAGS_CONTINUED 0x8000 /* More Segments */
-#define SA_FLAGS_IDLE 0x4000 /* Mark IDLE after frm */
-#define SA_FLAGS_READY_TO_XMIT 0x0800
-#define SA_FLAGS_STAT_MASK 0x007F
- } xmit[NUM_XBUFFS];
-
- /**********************************************/
- /* Receive Status Area */
- /**********************************************/
- struct {
- u32 leNext; /* Next entry in Little Endian on Adapter */
- u32 leNextASD;
- u32 leBuffer; /* Buffer for entry in LE for Adapter */
- u16 WorkingLength; /* size of segment */
- u16 reserv01;
- u16 leLength; /* Length of data in segment */
- u16 flags;
-#define SA_FL_RCV_DONE 0x0010 /* Data ready */
-#define SA_FLAGS_OVERRUN 0x0040
-#define SA_FLAGS_PARITY_ERROR 0x0080
-#define SA_FLAGS_FRAME_ERROR 0x0001
-#define SA_FLAGS_FRAME_TRUNC 0x0002
-#define SA_FLAGS_BREAK_DET 0x0004 /* set conditionally by device driver, not hardware */
-#define SA_FLAGS_RCV_MASK 0xFFE6
- } rcv[NUM_RBUFFS];
-};
-
-struct icom_adapter;
-
-
-#define ICOM_MAJOR 243
-#define ICOM_MINOR_START 0
-
-struct icom_port {
- struct uart_port uart_port;
- u8 imbed_modem;
-#define ICOM_UNKNOWN 1
-#define ICOM_RVX 2
-#define ICOM_IMBED_MODEM 3
- unsigned char cable_id;
- unsigned char read_status_mask;
- unsigned char ignore_status_mask;
- void __iomem * int_reg;
- struct icom_regs __iomem *global_reg;
- struct func_dram __iomem *dram;
- int port;
- struct statusArea *statStg;
- dma_addr_t statStg_pci;
- u32 *xmitRestart;
- dma_addr_t xmitRestart_pci;
- unsigned char *xmit_buf;
- dma_addr_t xmit_buf_pci;
- unsigned char *recv_buf;
- dma_addr_t recv_buf_pci;
- int next_rcv;
- int put_length;
- int status;
-#define ICOM_PORT_ACTIVE 1 /* Port exists. */
-#define ICOM_PORT_OFF 0 /* Port does not exist. */
- int load_in_progress;
- struct icom_adapter *adapter;
-};
-
-struct icom_adapter {
- void __iomem * base_addr;
- unsigned long base_addr_pci;
- struct pci_dev *pci_dev;
- struct icom_port port_info[4];
- int index;
- int version;
-#define ADAPTER_V1 0x0001
-#define ADAPTER_V2 0x0002
- u32 subsystem_id;
-#define FOUR_PORT_MODEL 0x0252
-#define V2_TWO_PORTS_RVX 0x021A
-#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM 0x0251
- int numb_ports;
- struct list_head icom_adapter_entry;
- struct kref kref;
-};
-
-/* prototype */
-extern void iCom_sercons_init(void);
-
-struct lookup_proc_table {
- u32 __iomem *global_control_reg;
- unsigned long processor_id;
-};
-
-struct lookup_int_table {
- u32 __iomem *global_int_mask;
- unsigned long processor_id;
-};
diff --git a/drivers/serial/ifx6x60.c b/drivers/serial/ifx6x60.c
deleted file mode 100644
index ab93763862d5..000000000000
--- a/drivers/serial/ifx6x60.c
+++ /dev/null
@@ -1,1406 +0,0 @@
-/****************************************************************************
- *
- * Driver for the IFX 6x60 spi modem.
- *
- * Copyright (C) 2008 Option International
- * Copyright (C) 2008 Filip Aben <f.aben@option.com>
- * Denis Joseph Barrow <d.barow@option.com>
- * Jan Dumon <j.dumon@option.com>
- *
- * Copyright (C) 2009, 2010 Intel Corp
- * Russ Gorby <richardx.r.gorby@intel.com>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA
- *
- * Driver modified by Intel from Option gtm501l_spi.c
- *
- * Notes
- * o The driver currently assumes a single device only. If you need to
- * change this then look for saved_ifx_dev and add a device lookup
- * o The driver is intended to be big-endian safe but has never been
- * tested that way (no suitable hardware). There are a couple of FIXME
- * notes by areas that may need addressing
- * o Some of the GPIO naming/setup assumptions may need revisiting if
- * you need to use this driver for another platform.
- *
- *****************************************************************************/
-#include <linux/module.h>
-#include <linux/termios.h>
-#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>
-#include <linux/serial.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/rfkill.h>
-#include <linux/fs.h>
-#include <linux/ip.h>
-#include <linux/dmapool.h>
-#include <linux/gpio.h>
-#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>
-#include <linux/delay.h>
-
-#include "ifx6x60.h"
-
-#define IFX_SPI_MORE_MASK 0x10
-#define IFX_SPI_MORE_BIT 12 /* bit position in u16 */
-#define IFX_SPI_CTS_BIT 13 /* bit position in u16 */
-#define IFX_SPI_TTY_ID 0
-#define IFX_SPI_TIMEOUT_SEC 2
-#define IFX_SPI_HEADER_0 (-1)
-#define IFX_SPI_HEADER_F (-2)
-
-/* forward reference */
-static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
-
-/* local variables */
-static int spi_b16 = 1; /* 8 or 16 bit word length */
-static struct tty_driver *tty_drv;
-static struct ifx_spi_device *saved_ifx_dev;
-static struct lock_class_key ifx_spi_key;
-
-/* GPIO/GPE settings */
-
-/**
- * mrdy_set_high - set MRDY GPIO
- * @ifx: device we are controlling
- *
- */
-static inline void mrdy_set_high(struct ifx_spi_device *ifx)
-{
- gpio_set_value(ifx->gpio.mrdy, 1);
-}
-
-/**
- * mrdy_set_low - clear MRDY GPIO
- * @ifx: device we are controlling
- *
- */
-static inline void mrdy_set_low(struct ifx_spi_device *ifx)
-{
- gpio_set_value(ifx->gpio.mrdy, 0);
-}
-
-/**
- * ifx_spi_power_state_set
- * @ifx_dev: our SPI device
- * @val: bits to set
- *
- * Set bit in power status and signal power system if status becomes non-0
- */
-static void
-ifx_spi_power_state_set(struct ifx_spi_device *ifx_dev, unsigned char val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ifx_dev->power_lock, flags);
-
- /*
- * if power status is already non-0, just update, else
- * tell power system
- */
- if (!ifx_dev->power_status)
- pm_runtime_get(&ifx_dev->spi_dev->dev);
- ifx_dev->power_status |= val;
-
- spin_unlock_irqrestore(&ifx_dev->power_lock, flags);
-}
-
-/**
- * ifx_spi_power_state_clear - clear power bit
- * @ifx_dev: our SPI device
- * @val: bits to clear
- *
- * clear bit in power status and signal power system if status becomes 0
- */
-static void
-ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ifx_dev->power_lock, flags);
-
- if (ifx_dev->power_status) {
- ifx_dev->power_status &= ~val;
- if (!ifx_dev->power_status)
- pm_runtime_put(&ifx_dev->spi_dev->dev);
- }
-
- spin_unlock_irqrestore(&ifx_dev->power_lock, flags);
-}
-
-/**
- * swap_buf
- * @buf: our buffer
- * @len : number of bytes (not words) in the buffer
- * @end: end of buffer
- *
- * Swap the contents of a buffer into big endian format
- */
-static inline void swap_buf(u16 *buf, int len, void *end)
-{
- int n;
-
- len = ((len + 1) >> 1);
- if ((void *)&buf[len] > end) {
- pr_err("swap_buf: swap exceeds boundary (%p > %p)!",
- &buf[len], end);
- return;
- }
- for (n = 0; n < len; n++) {
- *buf = cpu_to_be16(*buf);
- buf++;
- }
-}
-
-/**
- * mrdy_assert - assert MRDY line
- * @ifx_dev: our SPI device
- *
- * Assert mrdy and set timer to wait for SRDY interrupt, if SRDY is low
- * now.
- *
- * FIXME: Can SRDY even go high as we are running this code ?
- */
-static void mrdy_assert(struct ifx_spi_device *ifx_dev)
-{
- int val = gpio_get_value(ifx_dev->gpio.srdy);
- if (!val) {
- if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
- &ifx_dev->flags)) {
- ifx_dev->spi_timer.expires =
- jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
- add_timer(&ifx_dev->spi_timer);
-
- }
- }
- ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_DATA_PENDING);
- mrdy_set_high(ifx_dev);
-}
-
-/**
- * ifx_spi_hangup - hang up an IFX device
- * @ifx_dev: our SPI device
- *
- * Hang up the tty attached to the IFX device if one is currently
- * open. If not take no action
- */
-static void ifx_spi_ttyhangup(struct ifx_spi_device *ifx_dev)
-{
- struct tty_port *pport = &ifx_dev->tty_port;
- struct tty_struct *tty = tty_port_tty_get(pport);
- if (tty) {
- tty_hangup(tty);
- tty_kref_put(tty);
- }
-}
-
-/**
- * ifx_spi_timeout - SPI timeout
- * @arg: our SPI device
- *
- * The SPI has timed out: hang up the tty. Users will then see a hangup
- * and error events.
- */
-static void ifx_spi_timeout(unsigned long arg)
-{
- struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
-
- dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
- ifx_spi_ttyhangup(ifx_dev);
- mrdy_set_low(ifx_dev);
- clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
-}
-
-/* char/tty operations */
-
-/**
- * ifx_spi_tiocmget - get modem lines
- * @tty: our tty device
- * @filp: file handle issuing the request
- *
- * Map the signal state into Linux modem flags and report the value
- * in Linux terms
- */
-static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp)
-{
- unsigned int value;
- struct ifx_spi_device *ifx_dev = tty->driver_data;
-
- value =
- (test_bit(IFX_SPI_RTS, &ifx_dev->signal_state) ? TIOCM_RTS : 0) |
- (test_bit(IFX_SPI_DTR, &ifx_dev->signal_state) ? TIOCM_DTR : 0) |
- (test_bit(IFX_SPI_CTS, &ifx_dev->signal_state) ? TIOCM_CTS : 0) |
- (test_bit(IFX_SPI_DSR, &ifx_dev->signal_state) ? TIOCM_DSR : 0) |
- (test_bit(IFX_SPI_DCD, &ifx_dev->signal_state) ? TIOCM_CAR : 0) |
- (test_bit(IFX_SPI_RI, &ifx_dev->signal_state) ? TIOCM_RNG : 0);
- return value;
-}
-
-/**
- * ifx_spi_tiocmset - set modem bits
- * @tty: the tty structure
- * @filp: file handle issuing the request
- * @set: bits to set
- * @clear: bits to clear
- *
- * The IFX6x60 only supports DTR and RTS. Set them accordingly
- * and flag that an update to the modem is needed.
- *
- * FIXME: do we need to kick the tranfers when we do this ?
- */
-static int ifx_spi_tiocmset(struct tty_struct *tty, struct file *filp,
- unsigned int set, unsigned int clear)
-{
- struct ifx_spi_device *ifx_dev = tty->driver_data;
-
- if (set & TIOCM_RTS)
- set_bit(IFX_SPI_RTS, &ifx_dev->signal_state);
- if (set & TIOCM_DTR)
- set_bit(IFX_SPI_DTR, &ifx_dev->signal_state);
- if (clear & TIOCM_RTS)
- clear_bit(IFX_SPI_RTS, &ifx_dev->signal_state);
- if (clear & TIOCM_DTR)
- clear_bit(IFX_SPI_DTR, &ifx_dev->signal_state);
-
- set_bit(IFX_SPI_UPDATE, &ifx_dev->signal_state);
- return 0;
-}
-
-/**
- * ifx_spi_open - called on tty open
- * @tty: our tty device
- * @filp: file handle being associated with the tty
- *
- * Open the tty interface. We let the tty_port layer do all the work
- * for us.
- *
- * FIXME: Remove single device assumption and saved_ifx_dev
- */
-static int ifx_spi_open(struct tty_struct *tty, struct file *filp)
-{
- return tty_port_open(&saved_ifx_dev->tty_port, tty, filp);
-}
-
-/**
- * ifx_spi_close - called when our tty closes
- * @tty: the tty being closed
- * @filp: the file handle being closed
- *
- * Perform the close of the tty. We use the tty_port layer to do all
- * our hard work.
- */
-static void ifx_spi_close(struct tty_struct *tty, struct file *filp)
-{
- struct ifx_spi_device *ifx_dev = tty->driver_data;
- tty_port_close(&ifx_dev->tty_port, tty, filp);
- /* FIXME: should we do an ifx_spi_reset here ? */
-}
-
-/**
- * ifx_decode_spi_header - decode received header
- * @buffer: the received data
- * @length: decoded length
- * @more: decoded more flag
- * @received_cts: status of cts we received
- *
- * Note how received_cts is handled -- if header is all F it is left
- * the same as it was, if header is all 0 it is set to 0 otherwise it is
- * taken from the incoming header.
- *
- * FIXME: endianness
- */
-static int ifx_spi_decode_spi_header(unsigned char *buffer, int *length,
- unsigned char *more, unsigned char *received_cts)
-{
- u16 h1;
- u16 h2;
- u16 *in_buffer = (u16 *)buffer;
-
- h1 = *in_buffer;
- h2 = *(in_buffer+1);
-
- if (h1 == 0 && h2 == 0) {
- *received_cts = 0;
- return IFX_SPI_HEADER_0;
- } else if (h1 == 0xffff && h2 == 0xffff) {
- /* spi_slave_cts remains as it was */
- return IFX_SPI_HEADER_F;
- }
-
- *length = h1 & 0xfff; /* upper bits of byte are flags */
- *more = (buffer[1] >> IFX_SPI_MORE_BIT) & 1;
- *received_cts = (buffer[3] >> IFX_SPI_CTS_BIT) & 1;
- return 0;
-}
-
-/**
- * ifx_setup_spi_header - set header fields
- * @txbuffer: pointer to start of SPI buffer
- * @tx_count: bytes
- * @more: indicate if more to follow
- *
- * Format up an SPI header for a transfer
- *
- * FIXME: endianness?
- */
-static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count,
- unsigned char more)
-{
- *(u16 *)(txbuffer) = tx_count;
- *(u16 *)(txbuffer+2) = IFX_SPI_PAYLOAD_SIZE;
- txbuffer[1] |= (more << IFX_SPI_MORE_BIT) & IFX_SPI_MORE_MASK;
-}
-
-/**
- * ifx_spi_wakeup_serial - SPI space made
- * @port_data: our SPI device
- *
- * We have emptied the FIFO enough that we want to get more data
- * queued into it. Poke the line discipline via tty_wakeup so that
- * it will feed us more bits
- */
-static void ifx_spi_wakeup_serial(struct ifx_spi_device *ifx_dev)
-{
- struct tty_struct *tty;
-
- tty = tty_port_tty_get(&ifx_dev->tty_port);
- if (!tty)
- return;
- tty_wakeup(tty);
- tty_kref_put(tty);
-}
-
-/**
- * ifx_spi_prepare_tx_buffer - prepare transmit frame
- * @ifx_dev: our SPI device
- *
- * The transmit buffr needs a header and various other bits of
- * information followed by as much data as we can pull from the FIFO
- * and transfer. This function formats up a suitable buffer in the
- * ifx_dev->tx_buffer
- *
- * FIXME: performance - should we wake the tty when the queue is half
- * empty ?
- */
-static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
-{
- int temp_count;
- int queue_length;
- int tx_count;
- unsigned char *tx_buffer;
-
- tx_buffer = ifx_dev->tx_buffer;
- memset(tx_buffer, 0, IFX_SPI_TRANSFER_SIZE);
-
- /* make room for required SPI header */
- tx_buffer += IFX_SPI_HEADER_OVERHEAD;
- tx_count = IFX_SPI_HEADER_OVERHEAD;
-
- /* clear to signal no more data if this turns out to be the
- * last buffer sent in a sequence */
- ifx_dev->spi_more = 0;
-
- /* if modem cts is set, just send empty buffer */
- if (!ifx_dev->spi_slave_cts) {
- /* see if there's tx data */
- queue_length = kfifo_len(&ifx_dev->tx_fifo);
- if (queue_length != 0) {
- /* data to mux -- see if there's room for it */
- temp_count = min(queue_length, IFX_SPI_PAYLOAD_SIZE);
- temp_count = kfifo_out_locked(&ifx_dev->tx_fifo,
- tx_buffer, temp_count,
- &ifx_dev->fifo_lock);
-
- /* update buffer pointer and data count in message */
- tx_buffer += temp_count;
- tx_count += temp_count;
- if (temp_count == queue_length)
- /* poke port to get more data */
- ifx_spi_wakeup_serial(ifx_dev);
- else /* more data in port, use next SPI message */
- ifx_dev->spi_more = 1;
- }
- }
- /* have data and info for header -- set up SPI header in buffer */
- /* spi header needs payload size, not entire buffer size */
- ifx_spi_setup_spi_header(ifx_dev->tx_buffer,
- tx_count-IFX_SPI_HEADER_OVERHEAD,
- ifx_dev->spi_more);
- /* swap actual data in the buffer */
- swap_buf((u16 *)(ifx_dev->tx_buffer), tx_count,
- &ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]);
- return tx_count;
-}
-
-/**
- * ifx_spi_write - line discipline write
- * @tty: our tty device
- * @buf: pointer to buffer to write (kernel space)
- * @count: size of buffer
- *
- * Write the characters we have been given into the FIFO. If the device
- * is not active then activate it, when the SRDY line is asserted back
- * this will commence I/O
- */
-static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf,
- int count)
-{
- struct ifx_spi_device *ifx_dev = tty->driver_data;
- unsigned char *tmp_buf = (unsigned char *)buf;
- int tx_count = kfifo_in_locked(&ifx_dev->tx_fifo, tmp_buf, count,
- &ifx_dev->fifo_lock);
- mrdy_assert(ifx_dev);
- return tx_count;
-}
-
-/**
- * ifx_spi_chars_in_buffer - line discipline helper
- * @tty: our tty device
- *
- * Report how much data we can accept before we drop bytes. As we use
- * a simple FIFO this is nice and easy.
- */
-static int ifx_spi_write_room(struct tty_struct *tty)
-{
- struct ifx_spi_device *ifx_dev = tty->driver_data;
- return IFX_SPI_FIFO_SIZE - kfifo_len(&ifx_dev->tx_fifo);
-}
-
-/**
- * ifx_spi_chars_in_buffer - line discipline helper
- * @tty: our tty device
- *
- * Report how many characters we have buffered. In our case this is the
- * number of bytes sitting in our transmit FIFO.
- */
-static int ifx_spi_chars_in_buffer(struct tty_struct *tty)
-{
- struct ifx_spi_device *ifx_dev = tty->driver_data;
- return kfifo_len(&ifx_dev->tx_fifo);
-}
-
-/**
- * ifx_port_hangup
- * @port: our tty port
- *
- * tty port hang up. Called when tty_hangup processing is invoked either
- * by loss of carrier, or by software (eg vhangup). Serialized against
- * activate/shutdown by the tty layer.
- */
-static void ifx_spi_hangup(struct tty_struct *tty)
-{
- struct ifx_spi_device *ifx_dev = tty->driver_data;
- tty_port_hangup(&ifx_dev->tty_port);
-}
-
-/**
- * ifx_port_activate
- * @port: our tty port
- *
- * tty port activate method - called for first open. Serialized
- * with hangup and shutdown by the tty layer.
- */
-static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
-{
- struct ifx_spi_device *ifx_dev =
- container_of(port, struct ifx_spi_device, tty_port);
-
- /* clear any old data; can't do this in 'close' */
- kfifo_reset(&ifx_dev->tx_fifo);
-
- /* put port data into this tty */
- tty->driver_data = ifx_dev;
-
- /* allows flip string push from int context */
- tty->low_latency = 1;
-
- return 0;
-}
-
-/**
- * ifx_port_shutdown
- * @port: our tty port
- *
- * tty port shutdown method - called for last port close. Serialized
- * with hangup and activate by the tty layer.
- */
-static void ifx_port_shutdown(struct tty_port *port)
-{
- struct ifx_spi_device *ifx_dev =
- container_of(port, struct ifx_spi_device, tty_port);
-
- mrdy_set_low(ifx_dev);
- clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
- tasklet_kill(&ifx_dev->io_work_tasklet);
-}
-
-static const struct tty_port_operations ifx_tty_port_ops = {
- .activate = ifx_port_activate,
- .shutdown = ifx_port_shutdown,
-};
-
-static const struct tty_operations ifx_spi_serial_ops = {
- .open = ifx_spi_open,
- .close = ifx_spi_close,
- .write = ifx_spi_write,
- .hangup = ifx_spi_hangup,
- .write_room = ifx_spi_write_room,
- .chars_in_buffer = ifx_spi_chars_in_buffer,
- .tiocmget = ifx_spi_tiocmget,
- .tiocmset = ifx_spi_tiocmset,
-};
-
-/**
- * ifx_spi_insert_fip_string - queue received data
- * @ifx_ser: our SPI device
- * @chars: buffer we have received
- * @size: number of chars reeived
- *
- * Queue bytes to the tty assuming the tty side is currently open. If
- * not the discard the data.
- */
-static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev,
- unsigned char *chars, size_t size)
-{
- struct tty_struct *tty = tty_port_tty_get(&ifx_dev->tty_port);
- if (!tty)
- return;
- tty_insert_flip_string(tty, chars, size);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
-}
-
-/**
- * ifx_spi_complete - SPI transfer completed
- * @ctx: our SPI device
- *
- * An SPI transfer has completed. Process any received data and kick off
- * any further transmits we can commence.
- */
-static void ifx_spi_complete(void *ctx)
-{
- struct ifx_spi_device *ifx_dev = ctx;
- struct tty_struct *tty;
- struct tty_ldisc *ldisc = NULL;
- int length;
- int actual_length;
- unsigned char more;
- unsigned char cts;
- int local_write_pending = 0;
- int queue_length;
- int srdy;
- int decode_result;
-
- mrdy_set_low(ifx_dev);
-
- if (!ifx_dev->spi_msg.status) {
- /* check header validity, get comm flags */
- swap_buf((u16 *)ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
- &ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]);
- decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer,
- &length, &more, &cts);
- if (decode_result == IFX_SPI_HEADER_0) {
- dev_dbg(&ifx_dev->spi_dev->dev,
- "ignore input: invalid header 0");
- ifx_dev->spi_slave_cts = 0;
- goto complete_exit;
- } else if (decode_result == IFX_SPI_HEADER_F) {
- dev_dbg(&ifx_dev->spi_dev->dev,
- "ignore input: invalid header F");
- goto complete_exit;
- }
-
- ifx_dev->spi_slave_cts = cts;
-
- actual_length = min((unsigned int)length,
- ifx_dev->spi_msg.actual_length);
- swap_buf((u16 *)(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
- actual_length,
- &ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]);
- ifx_spi_insert_flip_string(
- ifx_dev,
- ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD,
- (size_t)actual_length);
- } else {
- dev_dbg(&ifx_dev->spi_dev->dev, "SPI transfer error %d",
- ifx_dev->spi_msg.status);
- }
-
-complete_exit:
- if (ifx_dev->write_pending) {
- ifx_dev->write_pending = 0;
- local_write_pending = 1;
- }
-
- clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &(ifx_dev->flags));
-
- queue_length = kfifo_len(&ifx_dev->tx_fifo);
- srdy = gpio_get_value(ifx_dev->gpio.srdy);
- if (!srdy)
- ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_SRDY);
-
- /* schedule output if there is more to do */
- if (test_and_clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags))
- tasklet_schedule(&ifx_dev->io_work_tasklet);
- else {
- if (more || ifx_dev->spi_more || queue_length > 0 ||
- local_write_pending) {
- if (ifx_dev->spi_slave_cts) {
- if (more)
- mrdy_assert(ifx_dev);
- } else
- mrdy_assert(ifx_dev);
- } else {
- /*
- * poke line discipline driver if any for more data
- * may or may not get more data to write
- * for now, say not busy
- */
- ifx_spi_power_state_clear(ifx_dev,
- IFX_SPI_POWER_DATA_PENDING);
- tty = tty_port_tty_get(&ifx_dev->tty_port);
- if (tty) {
- ldisc = tty_ldisc_ref(tty);
- if (ldisc) {
- ldisc->ops->write_wakeup(tty);
- tty_ldisc_deref(ldisc);
- }
- tty_kref_put(tty);
- }
- }
- }
-}
-
-/**
- * ifx_spio_io - I/O tasklet
- * @data: our SPI device
- *
- * Queue data for transmission if possible and then kick off the
- * transfer.
- */
-static void ifx_spi_io(unsigned long data)
-{
- int retval;
- struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
-
- if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) {
- if (ifx_dev->gpio.unack_srdy_int_nb > 0)
- ifx_dev->gpio.unack_srdy_int_nb--;
-
- ifx_spi_prepare_tx_buffer(ifx_dev);
-
- spi_message_init(&ifx_dev->spi_msg);
- INIT_LIST_HEAD(&ifx_dev->spi_msg.queue);
-
- ifx_dev->spi_msg.context = ifx_dev;
- ifx_dev->spi_msg.complete = ifx_spi_complete;
-
- /* set up our spi transfer */
- /* note len is BYTES, not transfers */
- ifx_dev->spi_xfer.len = IFX_SPI_TRANSFER_SIZE;
- ifx_dev->spi_xfer.cs_change = 0;
- ifx_dev->spi_xfer.speed_hz = 12500000;
- /* ifx_dev->spi_xfer.speed_hz = 390625; */
- ifx_dev->spi_xfer.bits_per_word = spi_b16 ? 16 : 8;
-
- ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer;
- ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer;
-
- /*
- * setup dma pointers
- */
- if (ifx_dev->is_6160) {
- ifx_dev->spi_msg.is_dma_mapped = 1;
- ifx_dev->tx_dma = ifx_dev->tx_bus;
- ifx_dev->rx_dma = ifx_dev->rx_bus;
- ifx_dev->spi_xfer.tx_dma = ifx_dev->tx_dma;
- ifx_dev->spi_xfer.rx_dma = ifx_dev->rx_dma;
- } else {
- ifx_dev->spi_msg.is_dma_mapped = 0;
- ifx_dev->tx_dma = (dma_addr_t)0;
- ifx_dev->rx_dma = (dma_addr_t)0;
- ifx_dev->spi_xfer.tx_dma = (dma_addr_t)0;
- ifx_dev->spi_xfer.rx_dma = (dma_addr_t)0;
- }
-
- spi_message_add_tail(&ifx_dev->spi_xfer, &ifx_dev->spi_msg);
-
- /* Assert MRDY. This may have already been done by the write
- * routine.
- */
- mrdy_assert(ifx_dev);
-
- retval = spi_async(ifx_dev->spi_dev, &ifx_dev->spi_msg);
- if (retval) {
- clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS,
- &ifx_dev->flags);
- tasklet_schedule(&ifx_dev->io_work_tasklet);
- return;
- }
- } else
- ifx_dev->write_pending = 1;
-}
-
-/**
- * ifx_spi_free_port - free up the tty side
- * @ifx_dev: IFX device going away
- *
- * Unregister and free up a port when the device goes away
- */
-static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev)
-{
- if (ifx_dev->tty_dev)
- tty_unregister_device(tty_drv, ifx_dev->minor);
- kfifo_free(&ifx_dev->tx_fifo);
-}
-
-/**
- * ifx_spi_create_port - create a new port
- * @ifx_dev: our spi device
- *
- * Allocate and initialise the tty port that goes with this interface
- * and add it to the tty layer so that it can be opened.
- */
-static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
-{
- int ret = 0;
- struct tty_port *pport = &ifx_dev->tty_port;
-
- spin_lock_init(&ifx_dev->fifo_lock);
- lockdep_set_class_and_subclass(&ifx_dev->fifo_lock,
- &ifx_spi_key, 0);
-
- if (kfifo_alloc(&ifx_dev->tx_fifo, IFX_SPI_FIFO_SIZE, GFP_KERNEL)) {
- ret = -ENOMEM;
- goto error_ret;
- }
-
- pport->ops = &ifx_tty_port_ops;
- tty_port_init(pport);
- ifx_dev->minor = IFX_SPI_TTY_ID;
- ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor,
- &ifx_dev->spi_dev->dev);
- if (IS_ERR(ifx_dev->tty_dev)) {
- dev_dbg(&ifx_dev->spi_dev->dev,
- "%s: registering tty device failed", __func__);
- ret = PTR_ERR(ifx_dev->tty_dev);
- goto error_ret;
- }
- return 0;
-
-error_ret:
- ifx_spi_free_port(ifx_dev);
- return ret;
-}
-
-/**
- * ifx_spi_handle_srdy - handle SRDY
- * @ifx_dev: device asserting SRDY
- *
- * Check our device state and see what we need to kick off when SRDY
- * is asserted. This usually means killing the timer and firing off the
- * I/O processing.
- */
-static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev)
-{
- if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) {
- del_timer_sync(&ifx_dev->spi_timer);
- clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
- }
-
- ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_SRDY);
-
- if (!test_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags))
- tasklet_schedule(&ifx_dev->io_work_tasklet);
- else
- set_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
-}
-
-/**
- * ifx_spi_srdy_interrupt - SRDY asserted
- * @irq: our IRQ number
- * @dev: our ifx device
- *
- * The modem asserted SRDY. Handle the srdy event
- */
-static irqreturn_t ifx_spi_srdy_interrupt(int irq, void *dev)
-{
- struct ifx_spi_device *ifx_dev = dev;
- ifx_dev->gpio.unack_srdy_int_nb++;
- ifx_spi_handle_srdy(ifx_dev);
- return IRQ_HANDLED;
-}
-
-/**
- * ifx_spi_reset_interrupt - Modem has changed reset state
- * @irq: interrupt number
- * @dev: our device pointer
- *
- * The modem has either entered or left reset state. Check the GPIO
- * line to see which.
- *
- * FIXME: review locking on MR_INPROGRESS versus
- * parallel unsolicited reset/solicited reset
- */
-static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
-{
- struct ifx_spi_device *ifx_dev = dev;
- int val = gpio_get_value(ifx_dev->gpio.reset_out);
- int solreset = test_bit(MR_START, &ifx_dev->mdm_reset_state);
-
- if (val == 0) {
- /* entered reset */
- set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
- if (!solreset) {
- /* unsolicited reset */
- ifx_spi_ttyhangup(ifx_dev);
- }
- } else {
- /* exited reset */
- clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
- if (solreset) {
- set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state);
- wake_up(&ifx_dev->mdm_reset_wait);
- }
- }
- return IRQ_HANDLED;
-}
-
-/**
- * ifx_spi_free_device - free device
- * @ifx_dev: device to free
- *
- * Free the IFX device
- */
-static void ifx_spi_free_device(struct ifx_spi_device *ifx_dev)
-{
- ifx_spi_free_port(ifx_dev);
- dma_free_coherent(&ifx_dev->spi_dev->dev,
- IFX_SPI_TRANSFER_SIZE,
- ifx_dev->tx_buffer,
- ifx_dev->tx_bus);
- dma_free_coherent(&ifx_dev->spi_dev->dev,
- IFX_SPI_TRANSFER_SIZE,
- ifx_dev->rx_buffer,
- ifx_dev->rx_bus);
-}
-
-/**
- * ifx_spi_reset - reset modem
- * @ifx_dev: modem to reset
- *
- * Perform a reset on the modem
- */
-static int ifx_spi_reset(struct ifx_spi_device *ifx_dev)
-{
- int ret;
- /*
- * set up modem power, reset
- *
- * delays are required on some platforms for the modem
- * to reset properly
- */
- set_bit(MR_START, &ifx_dev->mdm_reset_state);
- gpio_set_value(ifx_dev->gpio.po, 0);
- gpio_set_value(ifx_dev->gpio.reset, 0);
- msleep(25);
- gpio_set_value(ifx_dev->gpio.reset, 1);
- msleep(1);
- gpio_set_value(ifx_dev->gpio.po, 1);
- msleep(1);
- gpio_set_value(ifx_dev->gpio.po, 0);
- ret = wait_event_timeout(ifx_dev->mdm_reset_wait,
- test_bit(MR_COMPLETE,
- &ifx_dev->mdm_reset_state),
- IFX_RESET_TIMEOUT);
- if (!ret)
- dev_warn(&ifx_dev->spi_dev->dev, "Modem reset timeout: (state:%lx)",
- ifx_dev->mdm_reset_state);
-
- ifx_dev->mdm_reset_state = 0;
- return ret;
-}
-
-/**
- * ifx_spi_spi_probe - probe callback
- * @spi: our possible matching SPI device
- *
- * Probe for a 6x60 modem on SPI bus. Perform any needed device and
- * GPIO setup.
- *
- * FIXME:
- * - Support for multiple devices
- * - Split out MID specific GPIO handling eventually
- */
-
-static int ifx_spi_spi_probe(struct spi_device *spi)
-{
- int ret;
- int srdy;
- struct ifx_modem_platform_data *pl_data = NULL;
- struct ifx_spi_device *ifx_dev;
-
- if (saved_ifx_dev) {
- dev_dbg(&spi->dev, "ignoring subsequent detection");
- return -ENODEV;
- }
-
- /* initialize structure to hold our device variables */
- ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL);
- if (!ifx_dev) {
- dev_err(&spi->dev, "spi device allocation failed");
- return -ENOMEM;
- }
- saved_ifx_dev = ifx_dev;
- ifx_dev->spi_dev = spi;
- clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
- spin_lock_init(&ifx_dev->write_lock);
- spin_lock_init(&ifx_dev->power_lock);
- ifx_dev->power_status = 0;
- init_timer(&ifx_dev->spi_timer);
- ifx_dev->spi_timer.function = ifx_spi_timeout;
- ifx_dev->spi_timer.data = (unsigned long)ifx_dev;
- ifx_dev->is_6160 = pl_data->is_6160;
-
- /* ensure SPI protocol flags are initialized to enable transfer */
- ifx_dev->spi_more = 0;
- ifx_dev->spi_slave_cts = 0;
-
- /*initialize transfer and dma buffers */
- ifx_dev->tx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev,
- IFX_SPI_TRANSFER_SIZE,
- &ifx_dev->tx_bus,
- GFP_KERNEL);
- if (!ifx_dev->tx_buffer) {
- dev_err(&spi->dev, "DMA-TX buffer allocation failed");
- ret = -ENOMEM;
- goto error_ret;
- }
- ifx_dev->rx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev,
- IFX_SPI_TRANSFER_SIZE,
- &ifx_dev->rx_bus,
- GFP_KERNEL);
- if (!ifx_dev->rx_buffer) {
- dev_err(&spi->dev, "DMA-RX buffer allocation failed");
- ret = -ENOMEM;
- goto error_ret;
- }
-
- /* initialize waitq for modem reset */
- init_waitqueue_head(&ifx_dev->mdm_reset_wait);
-
- spi_set_drvdata(spi, ifx_dev);
- tasklet_init(&ifx_dev->io_work_tasklet, ifx_spi_io,
- (unsigned long)ifx_dev);
-
- set_bit(IFX_SPI_STATE_PRESENT, &ifx_dev->flags);
-
- /* create our tty port */
- ret = ifx_spi_create_port(ifx_dev);
- if (ret != 0) {
- dev_err(&spi->dev, "create default tty port failed");
- goto error_ret;
- }
-
- pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data;
- if (pl_data) {
- ifx_dev->gpio.reset = pl_data->rst_pmu;
- ifx_dev->gpio.po = pl_data->pwr_on;
- ifx_dev->gpio.mrdy = pl_data->mrdy;
- ifx_dev->gpio.srdy = pl_data->srdy;
- ifx_dev->gpio.reset_out = pl_data->rst_out;
- } else {
- dev_err(&spi->dev, "missing platform data!");
- ret = -ENODEV;
- goto error_ret;
- }
-
- dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d",
- ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy,
- ifx_dev->gpio.srdy, ifx_dev->gpio.reset_out);
-
- /* Configure gpios */
- ret = gpio_request(ifx_dev->gpio.reset, "ifxModem");
- if (ret < 0) {
- dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET)",
- ifx_dev->gpio.reset);
- goto error_ret;
- }
- ret += gpio_direction_output(ifx_dev->gpio.reset, 0);
- ret += gpio_export(ifx_dev->gpio.reset, 1);
- if (ret) {
- dev_err(&spi->dev, "Unable to configure GPIO%d (RESET)",
- ifx_dev->gpio.reset);
- ret = -EBUSY;
- goto error_ret2;
- }
-
- ret = gpio_request(ifx_dev->gpio.po, "ifxModem");
- ret += gpio_direction_output(ifx_dev->gpio.po, 0);
- ret += gpio_export(ifx_dev->gpio.po, 1);
- if (ret) {
- dev_err(&spi->dev, "Unable to configure GPIO%d (ON)",
- ifx_dev->gpio.po);
- ret = -EBUSY;
- goto error_ret3;
- }
-
- ret = gpio_request(ifx_dev->gpio.mrdy, "ifxModem");
- if (ret < 0) {
- dev_err(&spi->dev, "Unable to allocate GPIO%d (MRDY)",
- ifx_dev->gpio.mrdy);
- goto error_ret3;
- }
- ret += gpio_export(ifx_dev->gpio.mrdy, 1);
- ret += gpio_direction_output(ifx_dev->gpio.mrdy, 0);
- if (ret) {
- dev_err(&spi->dev, "Unable to configure GPIO%d (MRDY)",
- ifx_dev->gpio.mrdy);
- ret = -EBUSY;
- goto error_ret4;
- }
-
- ret = gpio_request(ifx_dev->gpio.srdy, "ifxModem");
- if (ret < 0) {
- dev_err(&spi->dev, "Unable to allocate GPIO%d (SRDY)",
- ifx_dev->gpio.srdy);
- ret = -EBUSY;
- goto error_ret4;
- }
- ret += gpio_export(ifx_dev->gpio.srdy, 1);
- ret += gpio_direction_input(ifx_dev->gpio.srdy);
- if (ret) {
- dev_err(&spi->dev, "Unable to configure GPIO%d (SRDY)",
- ifx_dev->gpio.srdy);
- ret = -EBUSY;
- goto error_ret5;
- }
-
- ret = gpio_request(ifx_dev->gpio.reset_out, "ifxModem");
- if (ret < 0) {
- dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET_OUT)",
- ifx_dev->gpio.reset_out);
- goto error_ret5;
- }
- ret += gpio_export(ifx_dev->gpio.reset_out, 1);
- ret += gpio_direction_input(ifx_dev->gpio.reset_out);
- if (ret) {
- dev_err(&spi->dev, "Unable to configure GPIO%d (RESET_OUT)",
- ifx_dev->gpio.reset_out);
- ret = -EBUSY;
- goto error_ret6;
- }
-
- ret = request_irq(gpio_to_irq(ifx_dev->gpio.reset_out),
- ifx_spi_reset_interrupt,
- IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME,
- (void *)ifx_dev);
- if (ret) {
- dev_err(&spi->dev, "Unable to get irq %x\n",
- gpio_to_irq(ifx_dev->gpio.reset_out));
- goto error_ret6;
- }
-
- ret = ifx_spi_reset(ifx_dev);
-
- ret = request_irq(gpio_to_irq(ifx_dev->gpio.srdy),
- ifx_spi_srdy_interrupt,
- IRQF_TRIGGER_RISING, DRVNAME,
- (void *)ifx_dev);
- if (ret) {
- dev_err(&spi->dev, "Unable to get irq %x",
- gpio_to_irq(ifx_dev->gpio.srdy));
- goto error_ret7;
- }
-
- /* set pm runtime power state and register with power system */
- pm_runtime_set_active(&spi->dev);
- pm_runtime_enable(&spi->dev);
-
- /* handle case that modem is already signaling SRDY */
- /* no outgoing tty open at this point, this just satisfies the
- * modem's read and should reset communication properly
- */
- srdy = gpio_get_value(ifx_dev->gpio.srdy);
-
- if (srdy) {
- mrdy_assert(ifx_dev);
- ifx_spi_handle_srdy(ifx_dev);
- } else
- mrdy_set_low(ifx_dev);
- return 0;
-
-error_ret7:
- free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), (void *)ifx_dev);
-error_ret6:
- gpio_free(ifx_dev->gpio.srdy);
-error_ret5:
- gpio_free(ifx_dev->gpio.mrdy);
-error_ret4:
- gpio_free(ifx_dev->gpio.reset);
-error_ret3:
- gpio_free(ifx_dev->gpio.po);
-error_ret2:
- gpio_free(ifx_dev->gpio.reset_out);
-error_ret:
- ifx_spi_free_device(ifx_dev);
- saved_ifx_dev = NULL;
- return ret;
-}
-
-/**
- * ifx_spi_spi_remove - SPI device was removed
- * @spi: SPI device
- *
- * FIXME: We should be shutting the device down here not in
- * the module unload path.
- */
-
-static int ifx_spi_spi_remove(struct spi_device *spi)
-{
- struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
- /* stop activity */
- tasklet_kill(&ifx_dev->io_work_tasklet);
- /* free irq */
- free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), (void *)ifx_dev);
- free_irq(gpio_to_irq(ifx_dev->gpio.srdy), (void *)ifx_dev);
-
- gpio_free(ifx_dev->gpio.srdy);
- gpio_free(ifx_dev->gpio.mrdy);
- gpio_free(ifx_dev->gpio.reset);
- gpio_free(ifx_dev->gpio.po);
- gpio_free(ifx_dev->gpio.reset_out);
-
- /* free allocations */
- ifx_spi_free_device(ifx_dev);
-
- saved_ifx_dev = NULL;
- return 0;
-}
-
-/**
- * ifx_spi_spi_shutdown - called on SPI shutdown
- * @spi: SPI device
- *
- * No action needs to be taken here
- */
-
-static void ifx_spi_spi_shutdown(struct spi_device *spi)
-{
-}
-
-/*
- * various suspends and resumes have nothing to do
- * no hardware to save state for
- */
-
-/**
- * ifx_spi_spi_suspend - suspend SPI on system suspend
- * @dev: device being suspended
- *
- * Suspend the SPI side. No action needed on Intel MID platforms, may
- * need extending for other systems.
- */
-static int ifx_spi_spi_suspend(struct spi_device *spi, pm_message_t msg)
-{
- return 0;
-}
-
-/**
- * ifx_spi_spi_resume - resume SPI side on system resume
- * @dev: device being suspended
- *
- * Suspend the SPI side. No action needed on Intel MID platforms, may
- * need extending for other systems.
- */
-static int ifx_spi_spi_resume(struct spi_device *spi)
-{
- return 0;
-}
-
-/**
- * ifx_spi_pm_suspend - suspend modem on system suspend
- * @dev: device being suspended
- *
- * Suspend the modem. No action needed on Intel MID platforms, may
- * need extending for other systems.
- */
-static int ifx_spi_pm_suspend(struct device *dev)
-{
- return 0;
-}
-
-/**
- * ifx_spi_pm_resume - resume modem on system resume
- * @dev: device being suspended
- *
- * Allow the modem to resume. No action needed.
- *
- * FIXME: do we need to reset anything here ?
- */
-static int ifx_spi_pm_resume(struct device *dev)
-{
- return 0;
-}
-
-/**
- * ifx_spi_pm_runtime_resume - suspend modem
- * @dev: device being suspended
- *
- * Allow the modem to resume. No action needed.
- */
-static int ifx_spi_pm_runtime_resume(struct device *dev)
-{
- return 0;
-}
-
-/**
- * ifx_spi_pm_runtime_suspend - suspend modem
- * @dev: device being suspended
- *
- * Allow the modem to suspend and thus suspend to continue up the
- * device tree.
- */
-static int ifx_spi_pm_runtime_suspend(struct device *dev)
-{
- return 0;
-}
-
-/**
- * ifx_spi_pm_runtime_idle - check if modem idle
- * @dev: our device
- *
- * Check conditions and queue runtime suspend if idle.
- */
-static int ifx_spi_pm_runtime_idle(struct device *dev)
-{
- struct spi_device *spi = to_spi_device(dev);
- struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
-
- if (!ifx_dev->power_status)
- pm_runtime_suspend(dev);
-
- return 0;
-}
-
-static const struct dev_pm_ops ifx_spi_pm = {
- .resume = ifx_spi_pm_resume,
- .suspend = ifx_spi_pm_suspend,
- .runtime_resume = ifx_spi_pm_runtime_resume,
- .runtime_suspend = ifx_spi_pm_runtime_suspend,
- .runtime_idle = ifx_spi_pm_runtime_idle
-};
-
-static const struct spi_device_id ifx_id_table[] = {
- {"ifx6160", 0},
- {"ifx6260", 0},
- { }
-};
-MODULE_DEVICE_TABLE(spi, ifx_id_table);
-
-/* spi operations */
-static const struct spi_driver ifx_spi_driver_6160 = {
- .driver = {
- .name = "ifx6160",
- .bus = &spi_bus_type,
- .pm = &ifx_spi_pm,
- .owner = THIS_MODULE},
- .probe = ifx_spi_spi_probe,
- .shutdown = ifx_spi_spi_shutdown,
- .remove = __devexit_p(ifx_spi_spi_remove),
- .suspend = ifx_spi_spi_suspend,
- .resume = ifx_spi_spi_resume,
- .id_table = ifx_id_table
-};
-
-/**
- * ifx_spi_exit - module exit
- *
- * Unload the module.
- */
-
-static void __exit ifx_spi_exit(void)
-{
- /* unregister */
- tty_unregister_driver(tty_drv);
- spi_unregister_driver((void *)&ifx_spi_driver_6160);
-}
-
-/**
- * ifx_spi_init - module entry point
- *
- * Initialise the SPI and tty interfaces for the IFX SPI driver
- * We need to initialize upper-edge spi driver after the tty
- * driver because otherwise the spi probe will race
- */
-
-static int __init ifx_spi_init(void)
-{
- int result;
-
- tty_drv = alloc_tty_driver(1);
- if (!tty_drv) {
- pr_err("%s: alloc_tty_driver failed", DRVNAME);
- return -ENOMEM;
- }
-
- tty_drv->magic = TTY_DRIVER_MAGIC;
- tty_drv->owner = THIS_MODULE;
- tty_drv->driver_name = DRVNAME;
- tty_drv->name = TTYNAME;
- tty_drv->minor_start = IFX_SPI_TTY_ID;
- tty_drv->num = 1;
- tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
- tty_drv->subtype = SERIAL_TYPE_NORMAL;
- tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- tty_drv->init_termios = tty_std_termios;
-
- tty_set_operations(tty_drv, &ifx_spi_serial_ops);
-
- result = tty_register_driver(tty_drv);
- if (result) {
- pr_err("%s: tty_register_driver failed(%d)",
- DRVNAME, result);
- put_tty_driver(tty_drv);
- return result;
- }
-
- result = spi_register_driver((void *)&ifx_spi_driver_6160);
- if (result) {
- pr_err("%s: spi_register_driver failed(%d)",
- DRVNAME, result);
- tty_unregister_driver(tty_drv);
- }
- return result;
-}
-
-module_init(ifx_spi_init);
-module_exit(ifx_spi_exit);
-
-MODULE_AUTHOR("Intel");
-MODULE_DESCRIPTION("IFX6x60 spi driver");
-MODULE_LICENSE("GPL");
-MODULE_INFO(Version, "0.1-IFX6x60");
diff --git a/drivers/serial/ifx6x60.h b/drivers/serial/ifx6x60.h
deleted file mode 100644
index deb7b8d977dc..000000000000
--- a/drivers/serial/ifx6x60.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/****************************************************************************
- *
- * Driver for the IFX spi modem.
- *
- * Copyright (C) 2009, 2010 Intel Corp
- * Jim Stanley <jim.stanley@intel.com>
- *
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA
- *
- *
- *
- *****************************************************************************/
-#ifndef _IFX6X60_H
-#define _IFX6X60_H
-
-#define DRVNAME "ifx6x60"
-#define TTYNAME "ttyIFX"
-
-/* #define IFX_THROTTLE_CODE */
-
-#define IFX_SPI_MAX_MINORS 1
-#define IFX_SPI_TRANSFER_SIZE 2048
-#define IFX_SPI_FIFO_SIZE 4096
-
-#define IFX_SPI_HEADER_OVERHEAD 4
-#define IFX_RESET_TIMEOUT msecs_to_jiffies(50)
-
-/* device flags bitfield definitions */
-#define IFX_SPI_STATE_PRESENT 0
-#define IFX_SPI_STATE_IO_IN_PROGRESS 1
-#define IFX_SPI_STATE_IO_READY 2
-#define IFX_SPI_STATE_TIMER_PENDING 3
-
-/* flow control bitfields */
-#define IFX_SPI_DCD 0
-#define IFX_SPI_CTS 1
-#define IFX_SPI_DSR 2
-#define IFX_SPI_RI 3
-#define IFX_SPI_DTR 4
-#define IFX_SPI_RTS 5
-#define IFX_SPI_TX_FC 6
-#define IFX_SPI_RX_FC 7
-#define IFX_SPI_UPDATE 8
-
-#define IFX_SPI_PAYLOAD_SIZE (IFX_SPI_TRANSFER_SIZE - \
- IFX_SPI_HEADER_OVERHEAD)
-
-#define IFX_SPI_IRQ_TYPE DETECT_EDGE_RISING
-#define IFX_SPI_GPIO_TARGET 0
-#define IFX_SPI_GPIO0 0x105
-
-#define IFX_SPI_STATUS_TIMEOUT (2000*HZ)
-
-/* values for bits in power status byte */
-#define IFX_SPI_POWER_DATA_PENDING 1
-#define IFX_SPI_POWER_SRDY 2
-
-struct ifx_spi_device {
- /* Our SPI device */
- struct spi_device *spi_dev;
-
- /* Port specific data */
- struct kfifo tx_fifo;
- spinlock_t fifo_lock;
- unsigned long signal_state;
-
- /* TTY Layer logic */
- struct tty_port tty_port;
- struct device *tty_dev;
- int minor;
-
- /* Low level I/O work */
- struct tasklet_struct io_work_tasklet;
- unsigned long flags;
- dma_addr_t rx_dma;
- dma_addr_t tx_dma;
-
- int is_6160; /* Modem type */
-
- spinlock_t write_lock;
- int write_pending;
- spinlock_t power_lock;
- unsigned char power_status;
-
- unsigned char *rx_buffer;
- unsigned char *tx_buffer;
- dma_addr_t rx_bus;
- dma_addr_t tx_bus;
- unsigned char spi_more;
- unsigned char spi_slave_cts;
-
- struct timer_list spi_timer;
-
- struct spi_message spi_msg;
- struct spi_transfer spi_xfer;
-
- struct {
- /* gpio lines */
- unsigned short srdy; /* slave-ready gpio */
- unsigned short mrdy; /* master-ready gpio */
- unsigned short reset; /* modem-reset gpio */
- unsigned short po; /* modem-on gpio */
- unsigned short reset_out; /* modem-in-reset gpio */
- /* state/stats */
- int unack_srdy_int_nb;
- } gpio;
-
- /* modem reset */
- unsigned long mdm_reset_state;
-#define MR_START 0
-#define MR_INPROGRESS 1
-#define MR_COMPLETE 2
- wait_queue_head_t mdm_reset_wait;
-};
-
-#endif /* _IFX6X60_H */
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
deleted file mode 100644
index dfcf4b1878aa..000000000000
--- a/drivers/serial/imx.c
+++ /dev/null
@@ -1,1380 +0,0 @@
-/*
- * linux/drivers/serial/imx.c
- *
- * Driver for Motorola IMX serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Author: Sascha Hauer <sascha@saschahauer.de>
- * Copyright (C) 2004 Pengutronix
- *
- * Copyright (C) 2009 emlix GmbH
- * Author: Fabian Godehardt (added IrDA support for iMX)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * [29-Mar-2005] Mike Lee
- * Added hardware handshake
- */
-
-#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/rational.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/imx-uart.h>
-
-/* Register definitions */
-#define URXD0 0x0 /* Receiver Register */
-#define URTX0 0x40 /* Transmitter Register */
-#define UCR1 0x80 /* Control Register 1 */
-#define UCR2 0x84 /* Control Register 2 */
-#define UCR3 0x88 /* Control Register 3 */
-#define UCR4 0x8c /* Control Register 4 */
-#define UFCR 0x90 /* FIFO Control Register */
-#define USR1 0x94 /* Status Register 1 */
-#define USR2 0x98 /* Status Register 2 */
-#define UESC 0x9c /* Escape Character Register */
-#define UTIM 0xa0 /* Escape Timer Register */
-#define UBIR 0xa4 /* BRM Incremental Register */
-#define UBMR 0xa8 /* BRM Modulator Register */
-#define UBRC 0xac /* Baud Rate Count Register */
-#define MX2_ONEMS 0xb0 /* One Millisecond register */
-#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
-
-/* UART Control Register Bit Fields.*/
-#define URXD_CHARRDY (1<<15)
-#define URXD_ERR (1<<14)
-#define URXD_OVRRUN (1<<13)
-#define URXD_FRMERR (1<<12)
-#define URXD_BRK (1<<11)
-#define URXD_PRERR (1<<10)
-#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
-#define UCR1_ADBR (1<<14) /* Auto detect baud rate */
-#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
-#define UCR1_IDEN (1<<12) /* Idle condition interrupt */
-#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
-#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
-#define UCR1_IREN (1<<7) /* Infrared interface enable */
-#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
-#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
-#define UCR1_SNDBRK (1<<4) /* Send break */
-#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
-#define MX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, mx1 only */
-#define UCR1_DOZE (1<<1) /* Doze */
-#define UCR1_UARTEN (1<<0) /* UART enabled */
-#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
-#define UCR2_IRTS (1<<14) /* Ignore RTS pin */
-#define UCR2_CTSC (1<<13) /* CTS pin control */
-#define UCR2_CTS (1<<12) /* Clear to send */
-#define UCR2_ESCEN (1<<11) /* Escape enable */
-#define UCR2_PREN (1<<8) /* Parity enable */
-#define UCR2_PROE (1<<7) /* Parity odd/even */
-#define UCR2_STPB (1<<6) /* Stop */
-#define UCR2_WS (1<<5) /* Word size */
-#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
-#define UCR2_TXEN (1<<2) /* Transmitter enabled */
-#define UCR2_RXEN (1<<1) /* Receiver enabled */
-#define UCR2_SRST (1<<0) /* SW reset */
-#define UCR3_DTREN (1<<13) /* DTR interrupt enable */
-#define UCR3_PARERREN (1<<12) /* Parity enable */
-#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */
-#define UCR3_DSR (1<<10) /* Data set ready */
-#define UCR3_DCD (1<<9) /* Data carrier detect */
-#define UCR3_RI (1<<8) /* Ring indicator */
-#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */
-#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
-#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
-#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
-#define MX1_UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */
-#define MX1_UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */
-#define MX2_UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */
-#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
-#define UCR3_BPEN (1<<0) /* Preset registers enable */
-#define UCR4_CTSTL_SHF 10 /* CTS trigger level shift */
-#define UCR4_CTSTL_MASK 0x3F /* CTS trigger is 6 bits wide */
-#define UCR4_INVR (1<<9) /* Inverted infrared reception */
-#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
-#define UCR4_WKEN (1<<7) /* Wake interrupt enable */
-#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */
-#define UCR4_IRSC (1<<5) /* IR special case */
-#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */
-#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */
-#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
-#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
-#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
-#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
-#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7)
-#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */
-#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */
-#define USR1_RTSS (1<<14) /* RTS pin status */
-#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */
-#define USR1_RTSD (1<<12) /* RTS delta */
-#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
-#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
-#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
-#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
-#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
-#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
-#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */
-#define USR2_ADET (1<<15) /* Auto baud rate detect complete */
-#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
-#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
-#define USR2_IDLE (1<<12) /* Idle condition */
-#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */
-#define USR2_WAKE (1<<7) /* Wake */
-#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */
-#define USR2_TXDC (1<<3) /* Transmitter complete */
-#define USR2_BRCD (1<<2) /* Break condition */
-#define USR2_ORE (1<<1) /* Overrun error */
-#define USR2_RDR (1<<0) /* Recv data ready */
-#define UTS_FRCPERR (1<<13) /* Force parity error */
-#define UTS_LOOP (1<<12) /* Loop tx and rx */
-#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
-#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
-#define UTS_TXFULL (1<<4) /* TxFIFO full */
-#define UTS_RXFULL (1<<3) /* RxFIFO full */
-#define UTS_SOFTRST (1<<0) /* Software reset */
-
-/* We've been assigned a range on the "Low-density serial ports" major */
-#define SERIAL_IMX_MAJOR 207
-#define MINOR_START 16
-#define DEV_NAME "ttymxc"
-#define MAX_INTERNAL_IRQ MXC_INTERNAL_IRQS
-
-/*
- * This determines how often we check the modem status signals
- * for any change. They generally aren't connected to an IRQ
- * so we have to poll them. We also check immediately before
- * filling the TX fifo incase CTS has been dropped.
- */
-#define MCTRL_TIMEOUT (250*HZ/1000)
-
-#define DRIVER_NAME "IMX-uart"
-
-#define UART_NR 8
-
-struct imx_port {
- struct uart_port port;
- struct timer_list timer;
- unsigned int old_status;
- int txirq,rxirq,rtsirq;
- unsigned int have_rtscts:1;
- unsigned int use_irda:1;
- unsigned int irda_inv_rx:1;
- unsigned int irda_inv_tx:1;
- unsigned short trcv_delay; /* transceiver delay */
- struct clk *clk;
-};
-
-#ifdef CONFIG_IRDA
-#define USE_IRDA(sport) ((sport)->use_irda)
-#else
-#define USE_IRDA(sport) (0)
-#endif
-
-/*
- * Handle any change of modem status signal since we were last called.
- */
-static void imx_mctrl_check(struct imx_port *sport)
-{
- unsigned int status, changed;
-
- status = sport->port.ops->get_mctrl(&sport->port);
- changed = status ^ sport->old_status;
-
- if (changed == 0)
- return;
-
- sport->old_status = status;
-
- if (changed & TIOCM_RI)
- sport->port.icount.rng++;
- if (changed & TIOCM_DSR)
- sport->port.icount.dsr++;
- if (changed & TIOCM_CAR)
- uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
- if (changed & TIOCM_CTS)
- uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
-
- wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
-}
-
-/*
- * This is our per-port timeout handler, for checking the
- * modem status signals.
- */
-static void imx_timeout(unsigned long data)
-{
- struct imx_port *sport = (struct imx_port *)data;
- unsigned long flags;
-
- if (sport->port.state) {
- spin_lock_irqsave(&sport->port.lock, flags);
- imx_mctrl_check(sport);
- spin_unlock_irqrestore(&sport->port.lock, flags);
-
- mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
- }
-}
-
-/*
- * interrupts disabled on entry
- */
-static void imx_stop_tx(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned long temp;
-
- if (USE_IRDA(sport)) {
- /* half duplex - wait for end of transmission */
- int n = 256;
- while ((--n > 0) &&
- !(readl(sport->port.membase + USR2) & USR2_TXDC)) {
- udelay(5);
- barrier();
- }
- /*
- * irda transceiver - wait a bit more to avoid
- * cutoff, hardware dependent
- */
- udelay(sport->trcv_delay);
-
- /*
- * half duplex - reactivate receive mode,
- * flush receive pipe echo crap
- */
- if (readl(sport->port.membase + USR2) & USR2_TXDC) {
- temp = readl(sport->port.membase + UCR1);
- temp &= ~(UCR1_TXMPTYEN | UCR1_TRDYEN);
- writel(temp, sport->port.membase + UCR1);
-
- temp = readl(sport->port.membase + UCR4);
- temp &= ~(UCR4_TCEN);
- writel(temp, sport->port.membase + UCR4);
-
- while (readl(sport->port.membase + URXD0) &
- URXD_CHARRDY)
- barrier();
-
- temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_RRDYEN;
- writel(temp, sport->port.membase + UCR1);
-
- temp = readl(sport->port.membase + UCR4);
- temp |= UCR4_DREN;
- writel(temp, sport->port.membase + UCR4);
- }
- return;
- }
-
- temp = readl(sport->port.membase + UCR1);
- writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
-}
-
-/*
- * interrupts disabled on entry
- */
-static void imx_stop_rx(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned long temp;
-
- temp = readl(sport->port.membase + UCR2);
- writel(temp &~ UCR2_RXEN, sport->port.membase + UCR2);
-}
-
-/*
- * Set the modem control timer to fire immediately.
- */
-static void imx_enable_ms(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
-
- mod_timer(&sport->timer, jiffies);
-}
-
-static inline void imx_transmit_buffer(struct imx_port *sport)
-{
- struct circ_buf *xmit = &sport->port.state->xmit;
-
- while (!uart_circ_empty(xmit) &&
- !(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
- /* send xmit->buf[xmit->tail]
- * out the port here */
- writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- sport->port.icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&sport->port);
-
- if (uart_circ_empty(xmit))
- imx_stop_tx(&sport->port);
-}
-
-/*
- * interrupts disabled on entry
- */
-static void imx_start_tx(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned long temp;
-
- if (USE_IRDA(sport)) {
- /* half duplex in IrDA mode; have to disable receive mode */
- temp = readl(sport->port.membase + UCR4);
- temp &= ~(UCR4_DREN);
- writel(temp, sport->port.membase + UCR4);
-
- temp = readl(sport->port.membase + UCR1);
- temp &= ~(UCR1_RRDYEN);
- writel(temp, sport->port.membase + UCR1);
- }
-
- temp = readl(sport->port.membase + UCR1);
- writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
-
- if (USE_IRDA(sport)) {
- temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_TRDYEN;
- writel(temp, sport->port.membase + UCR1);
-
- temp = readl(sport->port.membase + UCR4);
- temp |= UCR4_TCEN;
- writel(temp, sport->port.membase + UCR4);
- }
-
- if (readl(sport->port.membase + UTS) & UTS_TXEMPTY)
- imx_transmit_buffer(sport);
-}
-
-static irqreturn_t imx_rtsint(int irq, void *dev_id)
-{
- struct imx_port *sport = dev_id;
- unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
- unsigned long flags;
-
- spin_lock_irqsave(&sport->port.lock, flags);
-
- writel(USR1_RTSD, sport->port.membase + USR1);
- uart_handle_cts_change(&sport->port, !!val);
- wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t imx_txint(int irq, void *dev_id)
-{
- struct imx_port *sport = dev_id;
- struct circ_buf *xmit = &sport->port.state->xmit;
- unsigned long flags;
-
- spin_lock_irqsave(&sport->port.lock,flags);
- if (sport->port.x_char)
- {
- /* Send next char */
- writel(sport->port.x_char, sport->port.membase + URTX0);
- goto out;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- imx_stop_tx(&sport->port);
- goto out;
- }
-
- imx_transmit_buffer(sport);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&sport->port);
-
-out:
- spin_unlock_irqrestore(&sport->port.lock,flags);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t imx_rxint(int irq, void *dev_id)
-{
- struct imx_port *sport = dev_id;
- unsigned int rx,flg,ignored = 0;
- struct tty_struct *tty = sport->port.state->port.tty;
- unsigned long flags, temp;
-
- spin_lock_irqsave(&sport->port.lock,flags);
-
- while (readl(sport->port.membase + USR2) & USR2_RDR) {
- flg = TTY_NORMAL;
- sport->port.icount.rx++;
-
- rx = readl(sport->port.membase + URXD0);
-
- temp = readl(sport->port.membase + USR2);
- if (temp & USR2_BRCD) {
- writel(USR2_BRCD, sport->port.membase + USR2);
- if (uart_handle_break(&sport->port))
- continue;
- }
-
- if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
- continue;
-
- if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) {
- if (rx & URXD_PRERR)
- sport->port.icount.parity++;
- else if (rx & URXD_FRMERR)
- sport->port.icount.frame++;
- if (rx & URXD_OVRRUN)
- sport->port.icount.overrun++;
-
- if (rx & sport->port.ignore_status_mask) {
- if (++ignored > 100)
- goto out;
- continue;
- }
-
- rx &= sport->port.read_status_mask;
-
- if (rx & URXD_PRERR)
- flg = TTY_PARITY;
- else if (rx & URXD_FRMERR)
- flg = TTY_FRAME;
- if (rx & URXD_OVRRUN)
- flg = TTY_OVERRUN;
-
-#ifdef SUPPORT_SYSRQ
- sport->port.sysrq = 0;
-#endif
- }
-
- tty_insert_flip_char(tty, rx, flg);
- }
-
-out:
- spin_unlock_irqrestore(&sport->port.lock,flags);
- tty_flip_buffer_push(tty);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t imx_int(int irq, void *dev_id)
-{
- struct imx_port *sport = dev_id;
- unsigned int sts;
-
- sts = readl(sport->port.membase + USR1);
-
- if (sts & USR1_RRDY)
- imx_rxint(irq, dev_id);
-
- if (sts & USR1_TRDY &&
- readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
- imx_txint(irq, dev_id);
-
- if (sts & USR1_RTSD)
- imx_rtsint(irq, dev_id);
-
- return IRQ_HANDLED;
-}
-
-/*
- * Return TIOCSER_TEMT when transmitter is not busy.
- */
-static unsigned int imx_tx_empty(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
-
- return (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0;
-}
-
-/*
- * We have a modem side uart, so the meanings of RTS and CTS are inverted.
- */
-static unsigned int imx_get_mctrl(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
-
- if (readl(sport->port.membase + USR1) & USR1_RTSS)
- tmp |= TIOCM_CTS;
-
- if (readl(sport->port.membase + UCR2) & UCR2_CTS)
- tmp |= TIOCM_RTS;
-
- return tmp;
-}
-
-static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned long temp;
-
- temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
-
- if (mctrl & TIOCM_RTS)
- temp |= UCR2_CTS;
-
- writel(temp, sport->port.membase + UCR2);
-}
-
-/*
- * Interrupts always disabled.
- */
-static void imx_break_ctl(struct uart_port *port, int break_state)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned long flags, temp;
-
- spin_lock_irqsave(&sport->port.lock, flags);
-
- temp = readl(sport->port.membase + UCR1) & ~UCR1_SNDBRK;
-
- if ( break_state != 0 )
- temp |= UCR1_SNDBRK;
-
- writel(temp, sport->port.membase + UCR1);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-#define TXTL 2 /* reset default */
-#define RXTL 1 /* reset default */
-
-static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
-{
- unsigned int val;
- unsigned int ufcr_rfdiv;
-
- /* set receiver / transmitter trigger level.
- * RFDIV is set such way to satisfy requested uartclk value
- */
- val = TXTL << 10 | RXTL;
- ufcr_rfdiv = (clk_get_rate(sport->clk) + sport->port.uartclk / 2)
- / sport->port.uartclk;
-
- if(!ufcr_rfdiv)
- ufcr_rfdiv = 1;
-
- val |= UFCR_RFDIV_REG(ufcr_rfdiv);
-
- writel(val, sport->port.membase + UFCR);
-
- return 0;
-}
-
-/* half the RX buffer size */
-#define CTSTL 16
-
-static int imx_startup(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
- int retval;
- unsigned long flags, temp;
-
- imx_setup_ufcr(sport, 0);
-
- /* disable the DREN bit (Data Ready interrupt enable) before
- * requesting IRQs
- */
- temp = readl(sport->port.membase + UCR4);
-
- if (USE_IRDA(sport))
- temp |= UCR4_IRSC;
-
- /* set the trigger level for CTS */
- temp &= ~(UCR4_CTSTL_MASK<< UCR4_CTSTL_SHF);
- temp |= CTSTL<< UCR4_CTSTL_SHF;
-
- writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
-
- if (USE_IRDA(sport)) {
- /* reset fifo's and state machines */
- int i = 100;
- temp = readl(sport->port.membase + UCR2);
- temp &= ~UCR2_SRST;
- writel(temp, sport->port.membase + UCR2);
- while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) &&
- (--i > 0)) {
- udelay(1);
- }
- }
-
- /*
- * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
- * chips only have one interrupt.
- */
- if (sport->txirq > 0) {
- retval = request_irq(sport->rxirq, imx_rxint, 0,
- DRIVER_NAME, sport);
- if (retval)
- goto error_out1;
-
- retval = request_irq(sport->txirq, imx_txint, 0,
- DRIVER_NAME, sport);
- if (retval)
- goto error_out2;
-
- /* do not use RTS IRQ on IrDA */
- if (!USE_IRDA(sport)) {
- retval = request_irq(sport->rtsirq, imx_rtsint,
- (sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 :
- IRQF_TRIGGER_FALLING |
- IRQF_TRIGGER_RISING,
- DRIVER_NAME, sport);
- if (retval)
- goto error_out3;
- }
- } else {
- retval = request_irq(sport->port.irq, imx_int, 0,
- DRIVER_NAME, sport);
- if (retval) {
- free_irq(sport->port.irq, sport);
- goto error_out1;
- }
- }
-
- /*
- * Finally, clear and enable interrupts
- */
- writel(USR1_RTSD, sport->port.membase + USR1);
-
- temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
-
- if (USE_IRDA(sport)) {
- temp |= UCR1_IREN;
- temp &= ~(UCR1_RTSDEN);
- }
-
- writel(temp, sport->port.membase + UCR1);
-
- temp = readl(sport->port.membase + UCR2);
- temp |= (UCR2_RXEN | UCR2_TXEN);
- writel(temp, sport->port.membase + UCR2);
-
- if (USE_IRDA(sport)) {
- /* clear RX-FIFO */
- int i = 64;
- while ((--i > 0) &&
- (readl(sport->port.membase + URXD0) & URXD_CHARRDY)) {
- barrier();
- }
- }
-
- if (!cpu_is_mx1()) {
- temp = readl(sport->port.membase + UCR3);
- temp |= MX2_UCR3_RXDMUXSEL;
- writel(temp, sport->port.membase + UCR3);
- }
-
- if (USE_IRDA(sport)) {
- temp = readl(sport->port.membase + UCR4);
- if (sport->irda_inv_rx)
- temp |= UCR4_INVR;
- else
- temp &= ~(UCR4_INVR);
- writel(temp | UCR4_DREN, sport->port.membase + UCR4);
-
- temp = readl(sport->port.membase + UCR3);
- if (sport->irda_inv_tx)
- temp |= UCR3_INVT;
- else
- temp &= ~(UCR3_INVT);
- writel(temp, sport->port.membase + UCR3);
- }
-
- /*
- * Enable modem status interrupts
- */
- spin_lock_irqsave(&sport->port.lock,flags);
- imx_enable_ms(&sport->port);
- spin_unlock_irqrestore(&sport->port.lock,flags);
-
- if (USE_IRDA(sport)) {
- struct imxuart_platform_data *pdata;
- pdata = sport->port.dev->platform_data;
- sport->irda_inv_rx = pdata->irda_inv_rx;
- sport->irda_inv_tx = pdata->irda_inv_tx;
- sport->trcv_delay = pdata->transceiver_delay;
- if (pdata->irda_enable)
- pdata->irda_enable(1);
- }
-
- return 0;
-
-error_out3:
- if (sport->txirq)
- free_irq(sport->txirq, sport);
-error_out2:
- if (sport->rxirq)
- free_irq(sport->rxirq, sport);
-error_out1:
- return retval;
-}
-
-static void imx_shutdown(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned long temp;
-
- temp = readl(sport->port.membase + UCR2);
- temp &= ~(UCR2_TXEN);
- writel(temp, sport->port.membase + UCR2);
-
- if (USE_IRDA(sport)) {
- struct imxuart_platform_data *pdata;
- pdata = sport->port.dev->platform_data;
- if (pdata->irda_enable)
- pdata->irda_enable(0);
- }
-
- /*
- * Stop our timer.
- */
- del_timer_sync(&sport->timer);
-
- /*
- * Free the interrupts
- */
- if (sport->txirq > 0) {
- if (!USE_IRDA(sport))
- free_irq(sport->rtsirq, sport);
- free_irq(sport->txirq, sport);
- free_irq(sport->rxirq, sport);
- } else
- free_irq(sport->port.irq, sport);
-
- /*
- * Disable all interrupts, port and break condition.
- */
-
- temp = readl(sport->port.membase + UCR1);
- temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
- if (USE_IRDA(sport))
- temp &= ~(UCR1_IREN);
-
- writel(temp, sport->port.membase + UCR1);
-}
-
-static void
-imx_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct imx_port *sport = (struct imx_port *)port;
- unsigned long flags;
- unsigned int ucr2, old_ucr1, old_txrxen, baud, quot;
- unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
- unsigned int div, ufcr;
- unsigned long num, denom;
- uint64_t tdiv64;
-
- /*
- * If we don't support modem control lines, don't allow
- * these to be set.
- */
- if (0) {
- termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
- termios->c_cflag |= CLOCAL;
- }
-
- /*
- * We only support CS7 and CS8.
- */
- while ((termios->c_cflag & CSIZE) != CS7 &&
- (termios->c_cflag & CSIZE) != CS8) {
- termios->c_cflag &= ~CSIZE;
- termios->c_cflag |= old_csize;
- old_csize = CS8;
- }
-
- if ((termios->c_cflag & CSIZE) == CS8)
- ucr2 = UCR2_WS | UCR2_SRST | UCR2_IRTS;
- else
- ucr2 = UCR2_SRST | UCR2_IRTS;
-
- if (termios->c_cflag & CRTSCTS) {
- if( sport->have_rtscts ) {
- ucr2 &= ~UCR2_IRTS;
- ucr2 |= UCR2_CTSC;
- } else {
- termios->c_cflag &= ~CRTSCTS;
- }
- }
-
- if (termios->c_cflag & CSTOPB)
- ucr2 |= UCR2_STPB;
- if (termios->c_cflag & PARENB) {
- ucr2 |= UCR2_PREN;
- if (termios->c_cflag & PARODD)
- ucr2 |= UCR2_PROE;
- }
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
- quot = uart_get_divisor(port, baud);
-
- spin_lock_irqsave(&sport->port.lock, flags);
-
- sport->port.read_status_mask = 0;
- if (termios->c_iflag & INPCK)
- sport->port.read_status_mask |= (URXD_FRMERR | URXD_PRERR);
- if (termios->c_iflag & (BRKINT | PARMRK))
- sport->port.read_status_mask |= URXD_BRK;
-
- /*
- * Characters to ignore
- */
- sport->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- sport->port.ignore_status_mask |= URXD_PRERR;
- if (termios->c_iflag & IGNBRK) {
- sport->port.ignore_status_mask |= URXD_BRK;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- sport->port.ignore_status_mask |= URXD_OVRRUN;
- }
-
- del_timer_sync(&sport->timer);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /*
- * disable interrupts and drain transmitter
- */
- old_ucr1 = readl(sport->port.membase + UCR1);
- writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
- sport->port.membase + UCR1);
-
- while ( !(readl(sport->port.membase + USR2) & USR2_TXDC))
- barrier();
-
- /* then, disable everything */
- old_txrxen = readl(sport->port.membase + UCR2);
- writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN),
- sport->port.membase + UCR2);
- old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
-
- if (USE_IRDA(sport)) {
- /*
- * use maximum available submodule frequency to
- * avoid missing short pulses due to low sampling rate
- */
- div = 1;
- } else {
- div = sport->port.uartclk / (baud * 16);
- if (div > 7)
- div = 7;
- if (!div)
- div = 1;
- }
-
- rational_best_approximation(16 * div * baud, sport->port.uartclk,
- 1 << 16, 1 << 16, &num, &denom);
-
- tdiv64 = sport->port.uartclk;
- tdiv64 *= num;
- do_div(tdiv64, denom * 16 * div);
- tty_termios_encode_baud_rate(termios,
- (speed_t)tdiv64, (speed_t)tdiv64);
-
- num -= 1;
- denom -= 1;
-
- ufcr = readl(sport->port.membase + UFCR);
- ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div);
- writel(ufcr, sport->port.membase + UFCR);
-
- writel(num, sport->port.membase + UBIR);
- writel(denom, sport->port.membase + UBMR);
-
- if (!cpu_is_mx1())
- writel(sport->port.uartclk / div / 1000,
- sport->port.membase + MX2_ONEMS);
-
- writel(old_ucr1, sport->port.membase + UCR1);
-
- /* set the parity, stop bits and data size */
- writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
-
- if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
- imx_enable_ms(&sport->port);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-static const char *imx_type(struct uart_port *port)
-{
- struct imx_port *sport = (struct imx_port *)port;
-
- return sport->port.type == PORT_IMX ? "IMX" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'.
- */
-static void imx_release_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- struct resource *mmres;
-
- mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mmres->start, mmres->end - mmres->start + 1);
-}
-
-/*
- * Request the memory region(s) being used by 'port'.
- */
-static int imx_request_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- struct resource *mmres;
- void *ret;
-
- mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mmres)
- return -ENODEV;
-
- ret = request_mem_region(mmres->start, mmres->end - mmres->start + 1,
- "imx-uart");
-
- return ret ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void imx_config_port(struct uart_port *port, int flags)
-{
- struct imx_port *sport = (struct imx_port *)port;
-
- if (flags & UART_CONFIG_TYPE &&
- imx_request_port(&sport->port) == 0)
- sport->port.type = PORT_IMX;
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- * The only change we allow are to the flags and type, and
- * even then only between PORT_IMX and PORT_UNKNOWN
- */
-static int
-imx_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- struct imx_port *sport = (struct imx_port *)port;
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_IMX)
- ret = -EINVAL;
- if (sport->port.irq != ser->irq)
- ret = -EINVAL;
- if (ser->io_type != UPIO_MEM)
- ret = -EINVAL;
- if (sport->port.uartclk / 16 != ser->baud_base)
- ret = -EINVAL;
- if ((void *)sport->port.mapbase != ser->iomem_base)
- ret = -EINVAL;
- if (sport->port.iobase != ser->port)
- ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops imx_pops = {
- .tx_empty = imx_tx_empty,
- .set_mctrl = imx_set_mctrl,
- .get_mctrl = imx_get_mctrl,
- .stop_tx = imx_stop_tx,
- .start_tx = imx_start_tx,
- .stop_rx = imx_stop_rx,
- .enable_ms = imx_enable_ms,
- .break_ctl = imx_break_ctl,
- .startup = imx_startup,
- .shutdown = imx_shutdown,
- .set_termios = imx_set_termios,
- .type = imx_type,
- .release_port = imx_release_port,
- .request_port = imx_request_port,
- .config_port = imx_config_port,
- .verify_port = imx_verify_port,
-};
-
-static struct imx_port *imx_ports[UART_NR];
-
-#ifdef CONFIG_SERIAL_IMX_CONSOLE
-static void imx_console_putchar(struct uart_port *port, int ch)
-{
- struct imx_port *sport = (struct imx_port *)port;
-
- while (readl(sport->port.membase + UTS) & UTS_TXFULL)
- barrier();
-
- writel(ch, sport->port.membase + URTX0);
-}
-
-/*
- * Interrupts are disabled on entering
- */
-static void
-imx_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct imx_port *sport = imx_ports[co->index];
- unsigned int old_ucr1, old_ucr2, ucr1;
-
- /*
- * First, save UCR1/2 and then disable interrupts
- */
- ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
- old_ucr2 = readl(sport->port.membase + UCR2);
-
- if (cpu_is_mx1())
- ucr1 |= MX1_UCR1_UARTCLKEN;
- ucr1 |= UCR1_UARTEN;
- ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
-
- writel(ucr1, sport->port.membase + UCR1);
-
- writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2);
-
- uart_console_write(&sport->port, s, count, imx_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore UCR1/2
- */
- while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
-
- writel(old_ucr1, sport->port.membase + UCR1);
- writel(old_ucr2, sport->port.membase + UCR2);
-}
-
-/*
- * If the port was already initialised (eg, by a boot loader),
- * try to determine the current setup.
- */
-static void __init
-imx_console_get_options(struct imx_port *sport, int *baud,
- int *parity, int *bits)
-{
-
- if (readl(sport->port.membase + UCR1) & UCR1_UARTEN) {
- /* ok, the port was enabled */
- unsigned int ucr2, ubir,ubmr, uartclk;
- unsigned int baud_raw;
- unsigned int ucfr_rfdiv;
-
- ucr2 = readl(sport->port.membase + UCR2);
-
- *parity = 'n';
- if (ucr2 & UCR2_PREN) {
- if (ucr2 & UCR2_PROE)
- *parity = 'o';
- else
- *parity = 'e';
- }
-
- if (ucr2 & UCR2_WS)
- *bits = 8;
- else
- *bits = 7;
-
- ubir = readl(sport->port.membase + UBIR) & 0xffff;
- ubmr = readl(sport->port.membase + UBMR) & 0xffff;
-
- ucfr_rfdiv = (readl(sport->port.membase + UFCR) & UFCR_RFDIV) >> 7;
- if (ucfr_rfdiv == 6)
- ucfr_rfdiv = 7;
- else
- ucfr_rfdiv = 6 - ucfr_rfdiv;
-
- uartclk = clk_get_rate(sport->clk);
- uartclk /= ucfr_rfdiv;
-
- { /*
- * The next code provides exact computation of
- * baud_raw = round(((uartclk/16) * (ubir + 1)) / (ubmr + 1))
- * without need of float support or long long division,
- * which would be required to prevent 32bit arithmetic overflow
- */
- unsigned int mul = ubir + 1;
- unsigned int div = 16 * (ubmr + 1);
- unsigned int rem = uartclk % div;
-
- baud_raw = (uartclk / div) * mul;
- baud_raw += (rem * mul + div / 2) / div;
- *baud = (baud_raw + 50) / 100 * 100;
- }
-
- if(*baud != baud_raw)
- printk(KERN_INFO "Serial: Console IMX rounded baud rate from %d to %d\n",
- baud_raw, *baud);
- }
-}
-
-static int __init
-imx_console_setup(struct console *co, char *options)
-{
- struct imx_port *sport;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index == -1 || co->index >= ARRAY_SIZE(imx_ports))
- co->index = 0;
- sport = imx_ports[co->index];
- if(sport == NULL)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- imx_console_get_options(sport, &baud, &parity, &bits);
-
- imx_setup_ufcr(sport, 0);
-
- return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver imx_reg;
-static struct console imx_console = {
- .name = DEV_NAME,
- .write = imx_console_write,
- .device = uart_console_device,
- .setup = imx_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &imx_reg,
-};
-
-#define IMX_CONSOLE &imx_console
-#else
-#define IMX_CONSOLE NULL
-#endif
-
-static struct uart_driver imx_reg = {
- .owner = THIS_MODULE,
- .driver_name = DRIVER_NAME,
- .dev_name = DEV_NAME,
- .major = SERIAL_IMX_MAJOR,
- .minor = MINOR_START,
- .nr = ARRAY_SIZE(imx_ports),
- .cons = IMX_CONSOLE,
-};
-
-static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct imx_port *sport = platform_get_drvdata(dev);
-
- if (sport)
- uart_suspend_port(&imx_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_imx_resume(struct platform_device *dev)
-{
- struct imx_port *sport = platform_get_drvdata(dev);
-
- if (sport)
- uart_resume_port(&imx_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_imx_probe(struct platform_device *pdev)
-{
- struct imx_port *sport;
- struct imxuart_platform_data *pdata;
- void __iomem *base;
- int ret = 0;
- struct resource *res;
-
- sport = kzalloc(sizeof(*sport), GFP_KERNEL);
- if (!sport)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENODEV;
- goto free;
- }
-
- base = ioremap(res->start, PAGE_SIZE);
- if (!base) {
- ret = -ENOMEM;
- goto free;
- }
-
- sport->port.dev = &pdev->dev;
- sport->port.mapbase = res->start;
- sport->port.membase = base;
- sport->port.type = PORT_IMX,
- sport->port.iotype = UPIO_MEM;
- sport->port.irq = platform_get_irq(pdev, 0);
- sport->rxirq = platform_get_irq(pdev, 0);
- sport->txirq = platform_get_irq(pdev, 1);
- sport->rtsirq = platform_get_irq(pdev, 2);
- sport->port.fifosize = 32;
- sport->port.ops = &imx_pops;
- sport->port.flags = UPF_BOOT_AUTOCONF;
- sport->port.line = pdev->id;
- init_timer(&sport->timer);
- sport->timer.function = imx_timeout;
- sport->timer.data = (unsigned long)sport;
-
- sport->clk = clk_get(&pdev->dev, "uart");
- if (IS_ERR(sport->clk)) {
- ret = PTR_ERR(sport->clk);
- goto unmap;
- }
- clk_enable(sport->clk);
-
- sport->port.uartclk = clk_get_rate(sport->clk);
-
- imx_ports[pdev->id] = sport;
-
- pdata = pdev->dev.platform_data;
- if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
- sport->have_rtscts = 1;
-
-#ifdef CONFIG_IRDA
- if (pdata && (pdata->flags & IMXUART_IRDA))
- sport->use_irda = 1;
-#endif
-
- if (pdata && pdata->init) {
- ret = pdata->init(pdev);
- if (ret)
- goto clkput;
- }
-
- ret = uart_add_one_port(&imx_reg, &sport->port);
- if (ret)
- goto deinit;
- platform_set_drvdata(pdev, &sport->port);
-
- return 0;
-deinit:
- if (pdata && pdata->exit)
- pdata->exit(pdev);
-clkput:
- clk_put(sport->clk);
- clk_disable(sport->clk);
-unmap:
- iounmap(sport->port.membase);
-free:
- kfree(sport);
-
- return ret;
-}
-
-static int serial_imx_remove(struct platform_device *pdev)
-{
- struct imxuart_platform_data *pdata;
- struct imx_port *sport = platform_get_drvdata(pdev);
-
- pdata = pdev->dev.platform_data;
-
- platform_set_drvdata(pdev, NULL);
-
- if (sport) {
- uart_remove_one_port(&imx_reg, &sport->port);
- clk_put(sport->clk);
- }
-
- clk_disable(sport->clk);
-
- if (pdata && pdata->exit)
- pdata->exit(pdev);
-
- iounmap(sport->port.membase);
- kfree(sport);
-
- return 0;
-}
-
-static struct platform_driver serial_imx_driver = {
- .probe = serial_imx_probe,
- .remove = serial_imx_remove,
-
- .suspend = serial_imx_suspend,
- .resume = serial_imx_resume,
- .driver = {
- .name = "imx-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init imx_serial_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: IMX driver\n");
-
- ret = uart_register_driver(&imx_reg);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&serial_imx_driver);
- if (ret != 0)
- uart_unregister_driver(&imx_reg);
-
- return 0;
-}
-
-static void __exit imx_serial_exit(void)
-{
- platform_driver_unregister(&serial_imx_driver);
- uart_unregister_driver(&imx_reg);
-}
-
-module_init(imx_serial_init);
-module_exit(imx_serial_exit);
-
-MODULE_AUTHOR("Sascha Hauer");
-MODULE_DESCRIPTION("IMX generic serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx-uart");
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
deleted file mode 100644
index ee43efc7bdcc..000000000000
--- a/drivers/serial/ioc3_serial.c
+++ /dev/null
@@ -1,2199 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-/*
- * This file contains a module version of the ioc3 serial driver. This
- * includes all the support functions needed (support functions, etc.)
- * and the serial driver itself.
- */
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/circ_buf.h>
-#include <linux/serial_reg.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/serial_core.h>
-#include <linux/ioc3.h>
-#include <linux/slab.h>
-
-/*
- * Interesting things about the ioc3
- */
-
-#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */
-#define PORTS_PER_CARD 2
-#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS)
-#define MAX_CARDS 8
-#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS)
-
-/* determine given the sio_ir what port it applies to */
-#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1
-
-
-/*
- * we have 2 logical ports (rs232, rs422) for each physical port
- * evens are rs232, odds are rs422
- */
-#define GET_PHYSICAL_PORT(_x) ((_x) >> 1)
-#define GET_LOGICAL_PORT(_x) ((_x) & 1)
-#define IS_PHYSICAL_PORT(_x) !((_x) & 1)
-#define IS_RS232(_x) !((_x) & 1)
-
-static unsigned int Num_of_ioc3_cards;
-static unsigned int Submodule_slot;
-
-/* defining this will get you LOTS of great debug info */
-//#define DEBUG_INTERRUPTS
-#define DPRINT_CONFIG(_x...) ;
-//#define DPRINT_CONFIG(_x...) printk _x
-#define NOT_PROGRESS() ;
-//#define NOT_PROGRESS() printk("%s : fails %d\n", __func__, __LINE__)
-
-/* number of characters we want to transmit to the lower level at a time */
-#define MAX_CHARS 256
-#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */
-
-/* Device name we're using */
-#define DEVICE_NAME "ttySIOC"
-#define DEVICE_MAJOR 204
-#define DEVICE_MINOR 116
-
-/* flags for next_char_state */
-#define NCS_BREAK 0x1
-#define NCS_PARITY 0x2
-#define NCS_FRAMING 0x4
-#define NCS_OVERRUN 0x8
-
-/* cause we need SOME parameters ... */
-#define MIN_BAUD_SUPPORTED 1200
-#define MAX_BAUD_SUPPORTED 115200
-
-/* protocol types supported */
-#define PROTO_RS232 0
-#define PROTO_RS422 1
-
-/* Notification types */
-#define N_DATA_READY 0x01
-#define N_OUTPUT_LOWAT 0x02
-#define N_BREAK 0x04
-#define N_PARITY_ERROR 0x08
-#define N_FRAMING_ERROR 0x10
-#define N_OVERRUN_ERROR 0x20
-#define N_DDCD 0x40
-#define N_DCTS 0x80
-
-#define N_ALL_INPUT (N_DATA_READY | N_BREAK \
- | N_PARITY_ERROR | N_FRAMING_ERROR \
- | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define N_ALL_OUTPUT N_OUTPUT_LOWAT
-
-#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \
- | N_OVERRUN_ERROR)
-
-#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \
- | N_PARITY_ERROR | N_FRAMING_ERROR \
- | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv)
-#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16))
-#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div))
-
-/* Some masks */
-#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \
- | UART_LCR_WLEN7 | UART_LCR_WLEN8)
-#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
-
-#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable)
-
-#define RING_BUF_SIZE 4096
-#define BUF_SIZE_BIT SBBR_L_SIZE
-#define PROD_CONS_MASK PROD_CONS_PTR_4K
-
-#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
-
-/* driver specific - one per card */
-struct ioc3_card {
- struct {
- /* uart ports are allocated here */
- struct uart_port icp_uart_port[LOGICAL_PORTS];
- /* the ioc3_port used for this port */
- struct ioc3_port *icp_port;
- } ic_port[PORTS_PER_CARD];
- /* currently enabled interrupts */
- uint32_t ic_enable;
-};
-
-/* Local port info for each IOC3 serial port */
-struct ioc3_port {
- /* handy reference material */
- struct uart_port *ip_port;
- struct ioc3_card *ip_card;
- struct ioc3_driver_data *ip_idd;
- struct ioc3_submodule *ip_is;
-
- /* pci mem addresses for this port */
- struct ioc3_serialregs __iomem *ip_serial_regs;
- struct ioc3_uartregs __iomem *ip_uart_regs;
-
- /* Ring buffer page for this port */
- dma_addr_t ip_dma_ringbuf;
- /* vaddr of ring buffer */
- struct ring_buffer *ip_cpu_ringbuf;
-
- /* Rings for this port */
- struct ring *ip_inring;
- struct ring *ip_outring;
-
- /* Hook to port specific values */
- struct port_hooks *ip_hooks;
-
- spinlock_t ip_lock;
-
- /* Various rx/tx parameters */
- int ip_baud;
- int ip_tx_lowat;
- int ip_rx_timeout;
-
- /* Copy of notification bits */
- int ip_notify;
-
- /* Shadow copies of various registers so we don't need to PIO
- * read them constantly
- */
- uint32_t ip_sscr;
- uint32_t ip_tx_prod;
- uint32_t ip_rx_cons;
- unsigned char ip_flags;
-};
-
-/* tx low water mark. We need to notify the driver whenever tx is getting
- * close to empty so it can refill the tx buffer and keep things going.
- * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
- * have no trouble getting in more chars in time (I certainly hope so).
- */
-#define TX_LOWAT_LATENCY 1000
-#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY)
-#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
-
-/* Flags per port */
-#define INPUT_HIGH 0x01
- /* used to signify that we have turned off the rx_high
- * temporarily - we need to drain the fifo and don't
- * want to get blasted with interrupts.
- */
-#define DCD_ON 0x02
- /* DCD state is on */
-#define LOWAT_WRITTEN 0x04
-#define READ_ABORTED 0x08
- /* the read was aborted - used to avaoid infinate looping
- * in the interrupt handler
- */
-#define INPUT_ENABLE 0x10
-
-/* Since each port has different register offsets and bitmasks
- * for everything, we'll store those that we need in tables so we
- * don't have to be constantly checking the port we are dealing with.
- */
-struct port_hooks {
- uint32_t intr_delta_dcd;
- uint32_t intr_delta_cts;
- uint32_t intr_tx_mt;
- uint32_t intr_rx_timer;
- uint32_t intr_rx_high;
- uint32_t intr_tx_explicit;
- uint32_t intr_clear;
- uint32_t intr_all;
- char rs422_select_pin;
-};
-
-static struct port_hooks hooks_array[PORTS_PER_CARD] = {
- /* values for port A */
- {
- .intr_delta_dcd = SIO_IR_SA_DELTA_DCD,
- .intr_delta_cts = SIO_IR_SA_DELTA_CTS,
- .intr_tx_mt = SIO_IR_SA_TX_MT,
- .intr_rx_timer = SIO_IR_SA_RX_TIMER,
- .intr_rx_high = SIO_IR_SA_RX_HIGH,
- .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT,
- .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL
- | SIO_IR_SA_RX_HIGH
- | SIO_IR_SA_RX_TIMER
- | SIO_IR_SA_DELTA_DCD
- | SIO_IR_SA_DELTA_CTS
- | SIO_IR_SA_INT
- | SIO_IR_SA_TX_EXPLICIT
- | SIO_IR_SA_MEMERR),
- .intr_all = SIO_IR_SA,
- .rs422_select_pin = GPPR_UARTA_MODESEL_PIN,
- },
-
- /* values for port B */
- {
- .intr_delta_dcd = SIO_IR_SB_DELTA_DCD,
- .intr_delta_cts = SIO_IR_SB_DELTA_CTS,
- .intr_tx_mt = SIO_IR_SB_TX_MT,
- .intr_rx_timer = SIO_IR_SB_RX_TIMER,
- .intr_rx_high = SIO_IR_SB_RX_HIGH,
- .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT,
- .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL
- | SIO_IR_SB_RX_HIGH
- | SIO_IR_SB_RX_TIMER
- | SIO_IR_SB_DELTA_DCD
- | SIO_IR_SB_DELTA_CTS
- | SIO_IR_SB_INT
- | SIO_IR_SB_TX_EXPLICIT
- | SIO_IR_SB_MEMERR),
- .intr_all = SIO_IR_SB,
- .rs422_select_pin = GPPR_UARTB_MODESEL_PIN,
- }
-};
-
-struct ring_entry {
- union {
- struct {
- uint32_t alldata;
- uint32_t allsc;
- } all;
- struct {
- char data[4]; /* data bytes */
- char sc[4]; /* status/control */
- } s;
- } u;
-};
-
-/* Test the valid bits in any of the 4 sc chars using "allsc" member */
-#define RING_ANY_VALID \
- ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101)
-
-#define ring_sc u.s.sc
-#define ring_data u.s.data
-#define ring_allsc u.all.allsc
-
-/* Number of entries per ring buffer. */
-#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
-
-/* An individual ring */
-struct ring {
- struct ring_entry entries[ENTRIES_PER_RING];
-};
-
-/* The whole enchilada */
-struct ring_buffer {
- struct ring TX_A;
- struct ring RX_A;
- struct ring TX_B;
- struct ring RX_B;
-};
-
-/* Get a ring from a port struct */
-#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
-
-/* for Infinite loop detection */
-#define MAXITER 10000000
-
-
-/**
- * set_baud - Baud rate setting code
- * @port: port to set
- * @baud: baud rate to use
- */
-static int set_baud(struct ioc3_port *port, int baud)
-{
- int divisor;
- int actual_baud;
- int diff;
- int lcr, prediv;
- struct ioc3_uartregs __iomem *uart;
-
- for (prediv = 6; prediv < 64; prediv++) {
- divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv));
- if (!divisor)
- continue; /* invalid divisor */
- actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv));
-
- diff = actual_baud - baud;
- if (diff < 0)
- diff = -diff;
-
- /* if we're within 1% we've found a match */
- if (diff * 100 <= actual_baud)
- break;
- }
-
- /* if the above loop completed, we didn't match
- * the baud rate. give up.
- */
- if (prediv == 64) {
- NOT_PROGRESS();
- return 1;
- }
-
- uart = port->ip_uart_regs;
- lcr = readb(&uart->iu_lcr);
-
- writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr);
- writeb((unsigned char)divisor, &uart->iu_dll);
- writeb((unsigned char)(divisor >> 8), &uart->iu_dlm);
- writeb((unsigned char)prediv, &uart->iu_scr);
- writeb((unsigned char)lcr, &uart->iu_lcr);
-
- return 0;
-}
-
-/**
- * get_ioc3_port - given a uart port, return the control structure
- * @the_port: uart port to find
- */
-static struct ioc3_port *get_ioc3_port(struct uart_port *the_port)
-{
- struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev);
- struct ioc3_card *card_ptr = idd->data[Submodule_slot];
- int ii, jj;
-
- if (!card_ptr) {
- NOT_PROGRESS();
- return NULL;
- }
- for (ii = 0; ii < PORTS_PER_CARD; ii++) {
- for (jj = 0; jj < LOGICAL_PORTS; jj++) {
- if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj])
- return card_ptr->ic_port[ii].icp_port;
- }
- }
- NOT_PROGRESS();
- return NULL;
-}
-
-/**
- * port_init - Initialize the sio and ioc3 hardware for a given port
- * called per port from attach...
- * @port: port to initialize
- */
-static int inline port_init(struct ioc3_port *port)
-{
- uint32_t sio_cr;
- struct port_hooks *hooks = port->ip_hooks;
- struct ioc3_uartregs __iomem *uart;
- int reset_loop_counter = 0xfffff;
- struct ioc3_driver_data *idd = port->ip_idd;
-
- /* Idle the IOC3 serial interface */
- writel(SSCR_RESET, &port->ip_serial_regs->sscr);
-
- /* Wait until any pending bus activity for this port has ceased */
- do {
- sio_cr = readl(&idd->vma->sio_cr);
- if (reset_loop_counter-- <= 0) {
- printk(KERN_WARNING
- "IOC3 unable to come out of reset"
- " scr 0x%x\n", sio_cr);
- return -1;
- }
- } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) &&
- (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA)
- || sio_cr == SIO_CR_ARB_DIAG_TXB
- || sio_cr == SIO_CR_ARB_DIAG_RXA
- || sio_cr == SIO_CR_ARB_DIAG_RXB));
-
- /* Finish reset sequence */
- writel(0, &port->ip_serial_regs->sscr);
-
- /* Once RESET is done, reload cached tx_prod and rx_cons values
- * and set rings to empty by making prod == cons
- */
- port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
- port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- /* Disable interrupts for this 16550 */
- uart = port->ip_uart_regs;
- writeb(0, &uart->iu_lcr);
- writeb(0, &uart->iu_ier);
-
- /* Set the default baud */
- set_baud(port, port->ip_baud);
-
- /* Set line control to 8 bits no parity */
- writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Enable the FIFOs */
- writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr);
- /* then reset 16550 FIFOs */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
- &uart->iu_fcr);
-
- /* Clear modem control register */
- writeb(0, &uart->iu_mcr);
-
- /* Clear deltas in modem status register */
- writel(0, &port->ip_serial_regs->shadow);
-
- /* Only do this once per port pair */
- if (port->ip_hooks == &hooks_array[0]) {
- unsigned long ring_pci_addr;
- uint32_t __iomem *sbbr_l, *sbbr_h;
-
- sbbr_l = &idd->vma->sbbr_l;
- sbbr_h = &idd->vma->sbbr_h;
- ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
- DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n",
- __func__, (void *)ring_pci_addr));
-
- writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h);
- writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l);
- }
-
- /* Set the receive timeout value to 10 msec */
- writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr);
-
- /* Set rx threshold, enable DMA */
- /* Set high water mark at 3/4 of full ring */
- port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
-
- /* uart experiences pauses at high baud rate reducing actual
- * throughput by 10% or so unless we enable high speed polling
- * XXX when this hardware bug is resolved we should revert to
- * normal polling speed
- */
- port->ip_sscr |= SSCR_HIGH_SPD;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Disable and clear all serial related interrupt bits */
- port->ip_card->ic_enable &= ~hooks->intr_clear;
- ioc3_disable(port->ip_is, idd, hooks->intr_clear);
- ioc3_ack(port->ip_is, idd, hooks->intr_clear);
- return 0;
-}
-
-/**
- * enable_intrs - enable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static void enable_intrs(struct ioc3_port *port, uint32_t mask)
-{
- if ((port->ip_card->ic_enable & mask) != mask) {
- port->ip_card->ic_enable |= mask;
- ioc3_enable(port->ip_is, port->ip_idd, mask);
- }
-}
-
-/**
- * local_open - local open a port
- * @port: port to open
- */
-static inline int local_open(struct ioc3_port *port)
-{
- int spiniter = 0;
-
- port->ip_flags = INPUT_ENABLE;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr | SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER) {
- NOT_PROGRESS();
- return -1;
- }
- }
- }
-
- /* Reset the input fifo. If the uart received chars while the port
- * was closed and DMA is not enabled, the uart may have a bunch of
- * chars hanging around in its rx fifo which will not be discarded
- * by rclr in the upper layer. We must get rid of them here.
- */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
- &port->ip_uart_regs->iu_fcr);
-
- writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Re-enable DMA, set default threshold to intr whenever there is
- * data available.
- */
- port->ip_sscr &= ~SSCR_RX_THRESHOLD;
- port->ip_sscr |= 1; /* default threshold */
-
- /* Plug in the new sscr. This implicitly clears the DMA_PAUSE
- * flag if it was set above
- */
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- port->ip_tx_lowat = 1;
- return 0;
-}
-
-/**
- * set_rx_timeout - Set rx timeout and threshold values.
- * @port: port to use
- * @timeout: timeout value in ticks
- */
-static inline int set_rx_timeout(struct ioc3_port *port, int timeout)
-{
- int threshold;
-
- port->ip_rx_timeout = timeout;
-
- /* Timeout is in ticks. Let's figure out how many chars we
- * can receive at the current baud rate in that interval
- * and set the rx threshold to that amount. There are 4 chars
- * per ring entry, so we'll divide the number of chars that will
- * arrive in timeout by 4.
- * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
- */
- threshold = timeout * port->ip_baud / 4000;
- if (threshold == 0)
- threshold = 1; /* otherwise we'll intr all the time! */
-
- if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD)
- return 1;
-
- port->ip_sscr &= ~SSCR_RX_THRESHOLD;
- port->ip_sscr |= threshold;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Now set the rx timeout to the given value
- * again timeout * SRTR_HZ / HZ
- */
- timeout = timeout * SRTR_HZ / 100;
- if (timeout > SRTR_CNT)
- timeout = SRTR_CNT;
- writel(timeout, &port->ip_serial_regs->srtr);
- return 0;
-}
-
-/**
- * config_port - config the hardware
- * @port: port to config
- * @baud: baud rate for the port
- * @byte_size: data size
- * @stop_bits: number of stop bits
- * @parenb: parity enable ?
- * @parodd: odd parity ?
- */
-static inline int
-config_port(struct ioc3_port *port,
- int baud, int byte_size, int stop_bits, int parenb, int parodd)
-{
- char lcr, sizebits;
- int spiniter = 0;
-
- DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d "
- "parodd %d\n",
- __func__, ((struct uart_port *)port->ip_port)->line,
- baud, byte_size, stop_bits, parenb, parodd));
-
- if (set_baud(port, baud))
- return 1;
-
- switch (byte_size) {
- case 5:
- sizebits = UART_LCR_WLEN5;
- break;
- case 6:
- sizebits = UART_LCR_WLEN6;
- break;
- case 7:
- sizebits = UART_LCR_WLEN7;
- break;
- case 8:
- sizebits = UART_LCR_WLEN8;
- break;
- default:
- return 1;
- }
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr | SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
-
- /* Clear relevant fields in lcr */
- lcr = readb(&port->ip_uart_regs->iu_lcr);
- lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
- UART_LCR_PARITY | LCR_MASK_STOP_BITS);
-
- /* Set byte size in lcr */
- lcr |= sizebits;
-
- /* Set parity */
- if (parenb) {
- lcr |= UART_LCR_PARITY;
- if (!parodd)
- lcr |= UART_LCR_EPAR;
- }
-
- /* Set stop bits */
- if (stop_bits)
- lcr |= UART_LCR_STOP /* 2 stop bits */ ;
-
- writeb(lcr, &port->ip_uart_regs->iu_lcr);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- port->ip_baud = baud;
-
- /* When we get within this number of ring entries of filling the
- * entire ring on tx, place an EXPLICIT intr to generate a lowat
- * notification when output has drained.
- */
- port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
- if (port->ip_tx_lowat == 0)
- port->ip_tx_lowat = 1;
-
- set_rx_timeout(port, 2);
- return 0;
-}
-
-/**
- * do_write - Write bytes to the port. Returns the number of bytes
- * actually written. Called from transmit_chars
- * @port: port to use
- * @buf: the stuff to write
- * @len: how many bytes in 'buf'
- */
-static inline int do_write(struct ioc3_port *port, char *buf, int len)
-{
- int prod_ptr, cons_ptr, total = 0;
- struct ring *outring;
- struct ring_entry *entry;
- struct port_hooks *hooks = port->ip_hooks;
-
- BUG_ON(!(len >= 0));
-
- prod_ptr = port->ip_tx_prod;
- cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- outring = port->ip_outring;
-
- /* Maintain a 1-entry red-zone. The ring buffer is full when
- * (cons - prod) % ring_size is 1. Rather than do this subtraction
- * in the body of the loop, I'll do it now.
- */
- cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
-
- /* Stuff the bytes into the output */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- int xx;
-
- /* Get 4 bytes (one ring entry) at a time */
- entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
-
- /* Invalidate all entries */
- entry->ring_allsc = 0;
-
- /* Copy in some bytes */
- for (xx = 0; (xx < 4) && (len > 0); xx++) {
- entry->ring_data[xx] = *buf++;
- entry->ring_sc[xx] = TXCB_VALID;
- len--;
- total++;
- }
-
- /* If we are within some small threshold of filling up the
- * entire ring buffer, we must place an EXPLICIT intr here
- * to generate a lowat interrupt in case we subsequently
- * really do fill up the ring and the caller goes to sleep.
- * No need to place more than one though.
- */
- if (!(port->ip_flags & LOWAT_WRITTEN) &&
- ((cons_ptr - prod_ptr) & PROD_CONS_MASK)
- <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) {
- port->ip_flags |= LOWAT_WRITTEN;
- entry->ring_sc[0] |= TXCB_INT_WHEN_DONE;
- }
-
- /* Go on to next entry */
- prod_ptr += sizeof(struct ring_entry);
- prod_ptr &= PROD_CONS_MASK;
- }
-
- /* If we sent something, start DMA if necessary */
- if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) {
- port->ip_sscr |= SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
-
- /* Store the new producer pointer. If tx is disabled, we stuff the
- * data into the ring buffer, but we don't actually start tx.
- */
- if (!uart_tx_stopped(port->ip_port)) {
- writel(prod_ptr, &port->ip_serial_regs->stpir);
-
- /* If we are now transmitting, enable tx_mt interrupt so we
- * can disable DMA if necessary when the tx finishes.
- */
- if (total > 0)
- enable_intrs(port, hooks->intr_tx_mt);
- }
- port->ip_tx_prod = prod_ptr;
-
- return total;
-}
-
-/**
- * disable_intrs - disable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static inline void disable_intrs(struct ioc3_port *port, uint32_t mask)
-{
- if (port->ip_card->ic_enable & mask) {
- ioc3_disable(port->ip_is, port->ip_idd, mask);
- port->ip_card->ic_enable &= ~mask;
- }
-}
-
-/**
- * set_notification - Modify event notification
- * @port: port to use
- * @mask: events mask
- * @set_on: set ?
- */
-static int set_notification(struct ioc3_port *port, int mask, int set_on)
-{
- struct port_hooks *hooks = port->ip_hooks;
- uint32_t intrbits, sscrbits;
-
- BUG_ON(!mask);
-
- intrbits = sscrbits = 0;
-
- if (mask & N_DATA_READY)
- intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
- if (mask & N_OUTPUT_LOWAT)
- intrbits |= hooks->intr_tx_explicit;
- if (mask & N_DDCD) {
- intrbits |= hooks->intr_delta_dcd;
- sscrbits |= SSCR_RX_RING_DCD;
- }
- if (mask & N_DCTS)
- intrbits |= hooks->intr_delta_cts;
-
- if (set_on) {
- enable_intrs(port, intrbits);
- port->ip_notify |= mask;
- port->ip_sscr |= sscrbits;
- } else {
- disable_intrs(port, intrbits);
- port->ip_notify &= ~mask;
- port->ip_sscr &= ~sscrbits;
- }
-
- /* We require DMA if either DATA_READY or DDCD notification is
- * currently requested. If neither of these is requested and
- * there is currently no tx in progress, DMA may be disabled.
- */
- if (port->ip_notify & (N_DATA_READY | N_DDCD))
- port->ip_sscr |= SSCR_DMA_EN;
- else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt))
- port->ip_sscr &= ~SSCR_DMA_EN;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- return 0;
-}
-
-/**
- * set_mcr - set the master control reg
- * @the_port: port to use
- * @mask1: mcr mask
- * @mask2: shadow mask
- */
-static inline int set_mcr(struct uart_port *the_port,
- int mask1, int mask2)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
- uint32_t shadow;
- int spiniter = 0;
- char mcr;
-
- if (!port)
- return -1;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr | SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
- shadow = readl(&port->ip_serial_regs->shadow);
- mcr = (shadow & 0xff000000) >> 24;
-
- /* Set new value */
- mcr |= mask1;
- shadow |= mask2;
- writeb(mcr, &port->ip_uart_regs->iu_mcr);
- writel(shadow, &port->ip_serial_regs->shadow);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- return 0;
-}
-
-/**
- * ioc3_set_proto - set the protocol for the port
- * @port: port to use
- * @proto: protocol to use
- */
-static int ioc3_set_proto(struct ioc3_port *port, int proto)
-{
- struct port_hooks *hooks = port->ip_hooks;
-
- switch (proto) {
- default:
- case PROTO_RS232:
- /* Clear the appropriate GIO pin */
- DPRINT_CONFIG(("%s: rs232\n", __func__));
- writel(0, (&port->ip_idd->vma->gppr[0]
- + hooks->rs422_select_pin));
- break;
-
- case PROTO_RS422:
- /* Set the appropriate GIO pin */
- DPRINT_CONFIG(("%s: rs422\n", __func__));
- writel(1, (&port->ip_idd->vma->gppr[0]
- + hooks->rs422_select_pin));
- break;
- }
- return 0;
-}
-
-/**
- * transmit_chars - upper level write, called with the_port->lock
- * @the_port: port to write
- */
-static void transmit_chars(struct uart_port *the_port)
-{
- int xmit_count, tail, head;
- int result;
- char *start;
- struct tty_struct *tty;
- struct ioc3_port *port = get_ioc3_port(the_port);
- struct uart_state *state;
-
- if (!the_port)
- return;
- if (!port)
- return;
-
- state = the_port->state;
- tty = state->port.tty;
-
- if (uart_circ_empty(&state->xmit) || uart_tx_stopped(the_port)) {
- /* Nothing to do or hw stopped */
- set_notification(port, N_ALL_OUTPUT, 0);
- return;
- }
-
- head = state->xmit.head;
- tail = state->xmit.tail;
- start = (char *)&state->xmit.buf[tail];
-
- /* write out all the data or until the end of the buffer */
- xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
- if (xmit_count > 0) {
- result = do_write(port, start, xmit_count);
- if (result > 0) {
- /* booking */
- xmit_count -= result;
- the_port->icount.tx += result;
- /* advance the pointers */
- tail += result;
- tail &= UART_XMIT_SIZE - 1;
- state->xmit.tail = tail;
- start = (char *)&state->xmit.buf[tail];
- }
- }
- if (uart_circ_chars_pending(&state->xmit) < WAKEUP_CHARS)
- uart_write_wakeup(the_port);
-
- if (uart_circ_empty(&state->xmit)) {
- set_notification(port, N_OUTPUT_LOWAT, 0);
- } else {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- }
-}
-
-/**
- * ioc3_change_speed - change the speed of the port
- * @the_port: port to change
- * @new_termios: new termios settings
- * @old_termios: old termios settings
- */
-static void
-ioc3_change_speed(struct uart_port *the_port,
- struct ktermios *new_termios, struct ktermios *old_termios)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
- unsigned int cflag, iflag;
- int baud;
- int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
- struct uart_state *state = the_port->state;
-
- cflag = new_termios->c_cflag;
- iflag = new_termios->c_iflag;
-
- switch (cflag & CSIZE) {
- case CS5:
- new_data = 5;
- break;
- case CS6:
- new_data = 6;
- break;
- case CS7:
- new_data = 7;
- break;
- case CS8:
- new_data = 8;
- break;
- default:
- /* cuz we always need a default ... */
- new_data = 5;
- break;
- }
- if (cflag & CSTOPB) {
- new_stop = 1;
- }
- if (cflag & PARENB) {
- new_parity_enable = 1;
- if (cflag & PARODD)
- new_parity = 1;
- }
- baud = uart_get_baud_rate(the_port, new_termios, old_termios,
- MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
- DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __func__, baud,
- the_port->line));
-
- if (!the_port->fifosize)
- the_port->fifosize = FIFO_SIZE;
- uart_update_timeout(the_port, cflag, baud);
-
- the_port->ignore_status_mask = N_ALL_INPUT;
-
- state->port.tty->low_latency = 1;
-
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~(N_PARITY_ERROR
- | N_FRAMING_ERROR);
- if (iflag & IGNBRK) {
- the_port->ignore_status_mask &= ~N_BREAK;
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
- }
- if (!(cflag & CREAD)) {
- /* ignore everything */
- the_port->ignore_status_mask &= ~N_DATA_READY;
- }
-
- if (cflag & CRTSCTS) {
- /* enable hardware flow control */
- port->ip_sscr |= SSCR_HFC_EN;
- }
- else {
- /* disable hardware flow control */
- port->ip_sscr &= ~SSCR_HFC_EN;
- }
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Set the configuration and proper notification call */
- DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o "
- "config_port(baud %d data %d stop %d penable %d "
- " parity %d), notification 0x%x\n",
- __func__, (void *)port, the_port->line, cflag, baud,
- new_data, new_stop, new_parity_enable, new_parity,
- the_port->ignore_status_mask));
-
- if ((config_port(port, baud, /* baud */
- new_data, /* byte size */
- new_stop, /* stop bits */
- new_parity_enable, /* set parity */
- new_parity)) >= 0) { /* parity 1==odd */
- set_notification(port, the_port->ignore_status_mask, 1);
- }
-}
-
-/**
- * ic3_startup_local - Start up the serial port - returns >= 0 if no errors
- * @the_port: Port to operate on
- */
-static inline int ic3_startup_local(struct uart_port *the_port)
-{
- struct ioc3_port *port;
-
- if (!the_port) {
- NOT_PROGRESS();
- return -1;
- }
-
- port = get_ioc3_port(the_port);
- if (!port) {
- NOT_PROGRESS();
- return -1;
- }
-
- local_open(port);
-
- /* set the protocol */
- ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 :
- PROTO_RS422);
- return 0;
-}
-
-/*
- * ioc3_cb_output_lowat - called when the output low water mark is hit
- * @port: port to output
- */
-static void ioc3_cb_output_lowat(struct ioc3_port *port)
-{
- unsigned long pflags;
-
- /* the_port->lock is set on the call here */
- if (port->ip_port) {
- spin_lock_irqsave(&port->ip_port->lock, pflags);
- transmit_chars(port->ip_port);
- spin_unlock_irqrestore(&port->ip_port->lock, pflags);
- }
-}
-
-/*
- * ioc3_cb_post_ncs - called for some basic errors
- * @port: port to use
- * @ncs: event
- */
-static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs)
-{
- struct uart_icount *icount;
-
- icount = &the_port->icount;
-
- if (ncs & NCS_BREAK)
- icount->brk++;
- if (ncs & NCS_FRAMING)
- icount->frame++;
- if (ncs & NCS_OVERRUN)
- icount->overrun++;
- if (ncs & NCS_PARITY)
- icount->parity++;
-}
-
-/**
- * do_read - Read in bytes from the port. Return the number of bytes
- * actually read.
- * @the_port: port to use
- * @buf: place to put the stuff we read
- * @len: how big 'buf' is
- */
-
-static inline int do_read(struct uart_port *the_port, char *buf, int len)
-{
- int prod_ptr, cons_ptr, total;
- struct ioc3_port *port = get_ioc3_port(the_port);
- struct ring *inring;
- struct ring_entry *entry;
- struct port_hooks *hooks = port->ip_hooks;
- int byte_num;
- char *sc;
- int loop_counter;
-
- BUG_ON(!(len >= 0));
- BUG_ON(!port);
-
- /* There is a nasty timing issue in the IOC3. When the rx_timer
- * expires or the rx_high condition arises, we take an interrupt.
- * At some point while servicing the interrupt, we read bytes from
- * the ring buffer and re-arm the rx_timer. However the rx_timer is
- * not started until the first byte is received *after* it is armed,
- * and any bytes pending in the rx construction buffers are not drained
- * to memory until either there are 4 bytes available or the rx_timer
- * expires. This leads to a potential situation where data is left
- * in the construction buffers forever - 1 to 3 bytes were received
- * after the interrupt was generated but before the rx_timer was
- * re-armed. At that point as long as no subsequent bytes are received
- * the timer will never be started and the bytes will remain in the
- * construction buffer forever. The solution is to execute a DRAIN
- * command after rearming the timer. This way any bytes received before
- * the DRAIN will be drained to memory, and any bytes received after
- * the DRAIN will start the TIMER and be drained when it expires.
- * Luckily, this only needs to be done when the DMA buffer is empty
- * since there is no requirement that this function return all
- * available data as long as it returns some.
- */
- /* Re-arm the timer */
-
- writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- cons_ptr = port->ip_rx_cons;
-
- if (prod_ptr == cons_ptr) {
- int reset_dma = 0;
-
- /* Input buffer appears empty, do a flush. */
-
- /* DMA must be enabled for this to work. */
- if (!(port->ip_sscr & SSCR_DMA_EN)) {
- port->ip_sscr |= SSCR_DMA_EN;
- reset_dma = 1;
- }
-
- /* Potential race condition: we must reload the srpir after
- * issuing the drain command, otherwise we could think the rx
- * buffer is empty, then take a very long interrupt, and when
- * we come back it's full and we wait forever for the drain to
- * complete.
- */
- writel(port->ip_sscr | SSCR_RX_DRAIN,
- &port->ip_serial_regs->sscr);
- prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
-
- /* We must not wait for the DRAIN to complete unless there are
- * at least 8 bytes (2 ring entries) available to receive the
- * data otherwise the DRAIN will never complete and we'll
- * deadlock here.
- * In fact, to make things easier, I'll just ignore the flush if
- * there is any data at all now available.
- */
- if (prod_ptr == cons_ptr) {
- loop_counter = 0;
- while (readl(&port->ip_serial_regs->sscr) &
- SSCR_RX_DRAIN) {
- loop_counter++;
- if (loop_counter > MAXITER)
- return -1;
- }
-
- /* SIGH. We have to reload the prod_ptr *again* since
- * the drain may have caused it to change
- */
- prod_ptr = readl(&port->ip_serial_regs->srpir)
- & PROD_CONS_MASK;
- }
- if (reset_dma) {
- port->ip_sscr &= ~SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- }
- inring = port->ip_inring;
- port->ip_flags &= ~READ_ABORTED;
-
- total = 0;
- loop_counter = 0xfffff; /* to avoid hangs */
-
- /* Grab bytes from the hardware */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- entry = (struct ring_entry *)((caddr_t) inring + cons_ptr);
-
- if (loop_counter-- <= 0) {
- printk(KERN_WARNING "IOC3 serial: "
- "possible hang condition/"
- "port stuck on read (line %d).\n",
- the_port->line);
- break;
- }
-
- /* According to the producer pointer, this ring entry
- * must contain some data. But if the PIO happened faster
- * than the DMA, the data may not be available yet, so let's
- * wait until it arrives.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- /* Indicate the read is aborted so we don't disable
- * the interrupt thinking that the consumer is
- * congested.
- */
- port->ip_flags |= READ_ABORTED;
- len = 0;
- break;
- }
-
- /* Load the bytes/status out of the ring entry */
- for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
- sc = &(entry->ring_sc[byte_num]);
-
- /* Check for change in modem state or overrun */
- if ((*sc & RXSB_MODEM_VALID)
- && (port->ip_notify & N_DDCD)) {
- /* Notify upper layer if DCD dropped */
- if ((port->ip_flags & DCD_ON)
- && !(*sc & RXSB_DCD)) {
- /* If we have already copied some data,
- * return it. We'll pick up the carrier
- * drop on the next pass. That way we
- * don't throw away the data that has
- * already been copied back to
- * the caller's buffer.
- */
- if (total > 0) {
- len = 0;
- break;
- }
- port->ip_flags &= ~DCD_ON;
-
- /* Turn off this notification so the
- * carrier drop protocol won't see it
- * again when it does a read.
- */
- *sc &= ~RXSB_MODEM_VALID;
-
- /* To keep things consistent, we need
- * to update the consumer pointer so
- * the next reader won't come in and
- * try to read the same ring entries
- * again. This must be done here before
- * the dcd change.
- */
-
- if ((entry->ring_allsc & RING_ANY_VALID)
- == 0) {
- cons_ptr += (int)sizeof
- (struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- writel(cons_ptr,
- &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* Notify upper layer of carrier drop */
- if ((port->ip_notify & N_DDCD)
- && port->ip_port) {
- uart_handle_dcd_change
- (port->ip_port, 0);
- wake_up_interruptible
- (&the_port->state->
- port.delta_msr_wait);
- }
-
- /* If we had any data to return, we
- * would have returned it above.
- */
- return 0;
- }
- }
- if (*sc & RXSB_MODEM_VALID) {
- /* Notify that an input overrun occurred */
- if ((*sc & RXSB_OVERRUN)
- && (port->ip_notify & N_OVERRUN_ERROR)) {
- ioc3_cb_post_ncs(the_port, NCS_OVERRUN);
- }
- /* Don't look at this byte again */
- *sc &= ~RXSB_MODEM_VALID;
- }
-
- /* Check for valid data or RX errors */
- if ((*sc & RXSB_DATA_VALID) &&
- ((*sc & (RXSB_PAR_ERR
- | RXSB_FRAME_ERR | RXSB_BREAK))
- && (port->ip_notify & (N_PARITY_ERROR
- | N_FRAMING_ERROR
- | N_BREAK)))) {
- /* There is an error condition on the next byte.
- * If we have already transferred some bytes,
- * we'll stop here. Otherwise if this is the
- * first byte to be read, we'll just transfer
- * it alone after notifying the
- * upper layer of its status.
- */
- if (total > 0) {
- len = 0;
- break;
- } else {
- if ((*sc & RXSB_PAR_ERR) &&
- (port->
- ip_notify & N_PARITY_ERROR)) {
- ioc3_cb_post_ncs(the_port,
- NCS_PARITY);
- }
- if ((*sc & RXSB_FRAME_ERR) &&
- (port->
- ip_notify & N_FRAMING_ERROR)) {
- ioc3_cb_post_ncs(the_port,
- NCS_FRAMING);
- }
- if ((*sc & RXSB_BREAK)
- && (port->ip_notify & N_BREAK)) {
- ioc3_cb_post_ncs
- (the_port, NCS_BREAK);
- }
- len = 1;
- }
- }
- if (*sc & RXSB_DATA_VALID) {
- *sc &= ~RXSB_DATA_VALID;
- *buf = entry->ring_data[byte_num];
- buf++;
- len--;
- total++;
- }
- }
-
- /* If we used up this entry entirely, go on to the next one,
- * otherwise we must have run out of buffer space, so
- * leave the consumer pointer here for the next read in case
- * there are still unread bytes in this entry.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- cons_ptr += (int)sizeof(struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- }
-
- /* Update consumer pointer and re-arm rx timer interrupt */
- writel(cons_ptr, &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* If we have now dipped below the rx high water mark and we have
- * rx_high interrupt turned off, we can now turn it back on again.
- */
- if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
- & PROD_CONS_MASK) <
- ((port->
- ip_sscr &
- SSCR_RX_THRESHOLD)
- << PROD_CONS_PTR_OFF))) {
- port->ip_flags &= ~INPUT_HIGH;
- enable_intrs(port, hooks->intr_rx_high);
- }
- return total;
-}
-
-/**
- * receive_chars - upper level read.
- * @the_port: port to read from
- */
-static int receive_chars(struct uart_port *the_port)
-{
- struct tty_struct *tty;
- unsigned char ch[MAX_CHARS];
- int read_count = 0, read_room, flip = 0;
- struct uart_state *state = the_port->state;
- struct ioc3_port *port = get_ioc3_port(the_port);
- unsigned long pflags;
-
- /* Make sure all the pointers are "good" ones */
- if (!state)
- return 0;
- if (!state->port.tty)
- return 0;
-
- if (!(port->ip_flags & INPUT_ENABLE))
- return 0;
-
- spin_lock_irqsave(&the_port->lock, pflags);
- tty = state->port.tty;
-
- read_count = do_read(the_port, ch, MAX_CHARS);
- if (read_count > 0) {
- flip = 1;
- read_room = tty_insert_flip_string(tty, ch, read_count);
- the_port->icount.rx += read_count;
- }
- spin_unlock_irqrestore(&the_port->lock, pflags);
-
- if (flip)
- tty_flip_buffer_push(tty);
-
- return read_count;
-}
-
-/**
- * ioc3uart_intr_one - lowest level (per port) interrupt handler.
- * @is : submodule
- * @idd: driver data
- * @pending: interrupts to handle
- */
-
-static int inline
-ioc3uart_intr_one(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd,
- unsigned int pending)
-{
- int port_num = GET_PORT_FROM_SIO_IR(pending);
- struct port_hooks *hooks;
- unsigned int rx_high_rd_aborted = 0;
- unsigned long flags;
- struct uart_port *the_port;
- struct ioc3_port *port;
- int loop_counter;
- struct ioc3_card *card_ptr;
- unsigned int sio_ir;
-
- card_ptr = idd->data[is->id];
- port = card_ptr->ic_port[port_num].icp_port;
- hooks = port->ip_hooks;
-
- /* Possible race condition here: The tx_mt interrupt bit may be
- * cleared without the intervention of the interrupt handler,
- * e.g. by a write. If the top level interrupt handler reads a
- * tx_mt, then some other processor does a write, starting up
- * output, then we come in here, see the tx_mt and stop DMA, the
- * output started by the other processor will hang. Thus we can
- * only rely on tx_mt being legitimate if it is read while the
- * port lock is held. Therefore this bit must be ignored in the
- * passed in interrupt mask which was read by the top level
- * interrupt handler since the port lock was not held at the time
- * it was read. We can only rely on this bit being accurate if it
- * is read while the port lock is held. So we'll clear it for now,
- * and reload it later once we have the port lock.
- */
-
- sio_ir = pending & ~(hooks->intr_tx_mt);
- spin_lock_irqsave(&port->ip_lock, flags);
-
- loop_counter = MAXITER; /* to avoid hangs */
-
- do {
- uint32_t shadow;
-
- if (loop_counter-- <= 0) {
- printk(KERN_WARNING "IOC3 serial: "
- "possible hang condition/"
- "port stuck on interrupt (line %d).\n",
- ((struct uart_port *)port->ip_port)->line);
- break;
- }
- /* Handle a DCD change */
- if (sio_ir & hooks->intr_delta_dcd) {
- ioc3_ack(is, idd, hooks->intr_delta_dcd);
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DDCD)
- && (shadow & SHADOW_DCD)
- && (port->ip_port)) {
- the_port = port->ip_port;
- uart_handle_dcd_change(the_port,
- shadow & SHADOW_DCD);
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- } else if ((port->ip_notify & N_DDCD)
- && !(shadow & SHADOW_DCD)) {
- /* Flag delta DCD/no DCD */
- uart_handle_dcd_change(port->ip_port,
- shadow & SHADOW_DCD);
- port->ip_flags |= DCD_ON;
- }
- }
-
- /* Handle a CTS change */
- if (sio_ir & hooks->intr_delta_cts) {
- ioc3_ack(is, idd, hooks->intr_delta_cts);
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DCTS) && (port->ip_port)) {
- the_port = port->ip_port;
- uart_handle_cts_change(the_port, shadow
- & SHADOW_CTS);
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- }
- }
-
- /* rx timeout interrupt. Must be some data available. Put this
- * before the check for rx_high since servicing this condition
- * may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_rx_timer) {
- ioc3_ack(is, idd, hooks->intr_rx_timer);
- if ((port->ip_notify & N_DATA_READY)
- && (port->ip_port)) {
- receive_chars(port->ip_port);
- }
- }
-
- /* rx high interrupt. Must be after rx_timer. */
- else if (sio_ir & hooks->intr_rx_high) {
- /* Data available, notify upper layer */
- if ((port->ip_notify & N_DATA_READY) && port->ip_port) {
- receive_chars(port->ip_port);
- }
-
- /* We can't ACK this interrupt. If receive_chars didn't
- * cause the condition to clear, we'll have to disable
- * the interrupt until the data is drained.
- * If the read was aborted, don't disable the interrupt
- * as this may cause us to hang indefinitely. An
- * aborted read generally means that this interrupt
- * hasn't been delivered to the cpu yet anyway, even
- * though we see it as asserted when we read the sio_ir.
- */
- if ((sio_ir = PENDING(card_ptr, idd))
- & hooks->intr_rx_high) {
- if (port->ip_flags & READ_ABORTED) {
- rx_high_rd_aborted++;
- }
- else {
- card_ptr->ic_enable &= ~hooks->intr_rx_high;
- port->ip_flags |= INPUT_HIGH;
- }
- }
- }
-
- /* We got a low water interrupt: notify upper layer to
- * send more data. Must come before tx_mt since servicing
- * this condition may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_tx_explicit) {
- port->ip_flags &= ~LOWAT_WRITTEN;
- ioc3_ack(is, idd, hooks->intr_tx_explicit);
- if (port->ip_notify & N_OUTPUT_LOWAT)
- ioc3_cb_output_lowat(port);
- }
-
- /* Handle tx_mt. Must come after tx_explicit. */
- else if (sio_ir & hooks->intr_tx_mt) {
- /* If we are expecting a lowat notification
- * and we get to this point it probably means that for
- * some reason the tx_explicit didn't work as expected
- * (that can legitimately happen if the output buffer is
- * filled up in just the right way).
- * So send the notification now.
- */
- if (port->ip_notify & N_OUTPUT_LOWAT) {
- ioc3_cb_output_lowat(port);
-
- /* We need to reload the sio_ir since the lowat
- * call may have caused another write to occur,
- * clearing the tx_mt condition.
- */
- sio_ir = PENDING(card_ptr, idd);
- }
-
- /* If the tx_mt condition still persists even after the
- * lowat call, we've got some work to do.
- */
- if (sio_ir & hooks->intr_tx_mt) {
- /* If we are not currently expecting DMA input,
- * and the transmitter has just gone idle,
- * there is no longer any reason for DMA, so
- * disable it.
- */
- if (!(port->ip_notify
- & (N_DATA_READY | N_DDCD))) {
- BUG_ON(!(port->ip_sscr
- & SSCR_DMA_EN));
- port->ip_sscr &= ~SSCR_DMA_EN;
- writel(port->ip_sscr,
- &port->ip_serial_regs->sscr);
- }
- /* Prevent infinite tx_mt interrupt */
- card_ptr->ic_enable &= ~hooks->intr_tx_mt;
- }
- }
- sio_ir = PENDING(card_ptr, idd);
-
- /* if the read was aborted and only hooks->intr_rx_high,
- * clear hooks->intr_rx_high, so we do not loop forever.
- */
-
- if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
- sio_ir &= ~hooks->intr_rx_high;
- }
- } while (sio_ir & hooks->intr_all);
-
- spin_unlock_irqrestore(&port->ip_lock, flags);
- ioc3_enable(is, idd, card_ptr->ic_enable);
- return 0;
-}
-
-/**
- * ioc3uart_intr - field all serial interrupts
- * @is : submodule
- * @idd: driver data
- * @pending: interrupts to handle
- *
- */
-
-static int ioc3uart_intr(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd,
- unsigned int pending)
-{
- int ret = 0;
-
- /*
- * The upper level interrupt handler sends interrupts for both ports
- * here. So we need to call for each port with its interrupts.
- */
-
- if (pending & SIO_IR_SA)
- ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA);
- if (pending & SIO_IR_SB)
- ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB);
-
- return ret;
-}
-
-/**
- * ic3_type
- * @port: Port to operate with (we ignore since we only have one port)
- *
- */
-static const char *ic3_type(struct uart_port *the_port)
-{
- if (IS_RS232(the_port->line))
- return "SGI IOC3 Serial [rs232]";
- else
- return "SGI IOC3 Serial [rs422]";
-}
-
-/**
- * ic3_tx_empty - Is the transmitter empty?
- * @port: Port to operate on
- *
- */
-static unsigned int ic3_tx_empty(struct uart_port *the_port)
-{
- unsigned int ret = 0;
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT)
- ret = TIOCSER_TEMT;
- return ret;
-}
-
-/**
- * ic3_stop_tx - stop the transmitter
- * @port: Port to operate on
- *
- */
-static void ic3_stop_tx(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (port)
- set_notification(port, N_OUTPUT_LOWAT, 0);
-}
-
-/**
- * ic3_stop_rx - stop the receiver
- * @port: Port to operate on
- *
- */
-static void ic3_stop_rx(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (port)
- port->ip_flags &= ~INPUT_ENABLE;
-}
-
-/**
- * null_void_function
- * @port: Port to operate on
- *
- */
-static void null_void_function(struct uart_port *the_port)
-{
-}
-
-/**
- * ic3_shutdown - shut down the port - free irq and disable
- * @port: port to shut down
- *
- */
-static void ic3_shutdown(struct uart_port *the_port)
-{
- unsigned long port_flags;
- struct ioc3_port *port;
- struct uart_state *state;
-
- port = get_ioc3_port(the_port);
- if (!port)
- return;
-
- state = the_port->state;
- wake_up_interruptible(&state->port.delta_msr_wait);
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- set_notification(port, N_ALL, 0);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic3_set_mctrl - set control lines (dtr, rts, etc)
- * @port: Port to operate on
- * @mctrl: Lines to set/unset
- *
- */
-static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
-{
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- set_mcr(the_port, mcr, SHADOW_DTR);
-}
-
-/**
- * ic3_get_mctrl - get control line info
- * @port: port to operate on
- *
- */
-static unsigned int ic3_get_mctrl(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
- uint32_t shadow;
- unsigned int ret = 0;
-
- if (!port)
- return 0;
-
- shadow = readl(&port->ip_serial_regs->shadow);
- if (shadow & SHADOW_DCD)
- ret |= TIOCM_CD;
- if (shadow & SHADOW_DR)
- ret |= TIOCM_DSR;
- if (shadow & SHADOW_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-/**
- * ic3_start_tx - Start transmitter. Called with the_port->lock
- * @port: Port to operate on
- *
- */
-static void ic3_start_tx(struct uart_port *the_port)
-{
- struct ioc3_port *port = get_ioc3_port(the_port);
-
- if (port) {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- enable_intrs(port, port->ip_hooks->intr_tx_mt);
- }
-}
-
-/**
- * ic3_break_ctl - handle breaks
- * @port: Port to operate on
- * @break_state: Break state
- *
- */
-static void ic3_break_ctl(struct uart_port *the_port, int break_state)
-{
-}
-
-/**
- * ic3_startup - Start up the serial port - always return 0 (We're always on)
- * @port: Port to operate on
- *
- */
-static int ic3_startup(struct uart_port *the_port)
-{
- int retval;
- struct ioc3_port *port;
- struct ioc3_card *card_ptr;
- unsigned long port_flags;
-
- if (!the_port) {
- NOT_PROGRESS();
- return -ENODEV;
- }
- port = get_ioc3_port(the_port);
- if (!port) {
- NOT_PROGRESS();
- return -ENODEV;
- }
- card_ptr = port->ip_card;
- port->ip_port = the_port;
-
- if (!card_ptr) {
- NOT_PROGRESS();
- return -ENODEV;
- }
-
- /* Start up the serial port */
- spin_lock_irqsave(&the_port->lock, port_flags);
- retval = ic3_startup_local(the_port);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
- return retval;
-}
-
-/**
- * ic3_set_termios - set termios stuff
- * @port: port to operate on
- * @termios: New settings
- * @termios: Old
- *
- */
-static void
-ic3_set_termios(struct uart_port *the_port,
- struct ktermios *termios, struct ktermios *old_termios)
-{
- unsigned long port_flags;
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- ioc3_change_speed(the_port, termios, old_termios);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic3_request_port - allocate resources for port - no op....
- * @port: port to operate on
- *
- */
-static int ic3_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/* Associate the uart functions above - given to serial core */
-static struct uart_ops ioc3_ops = {
- .tx_empty = ic3_tx_empty,
- .set_mctrl = ic3_set_mctrl,
- .get_mctrl = ic3_get_mctrl,
- .stop_tx = ic3_stop_tx,
- .start_tx = ic3_start_tx,
- .stop_rx = ic3_stop_rx,
- .enable_ms = null_void_function,
- .break_ctl = ic3_break_ctl,
- .startup = ic3_startup,
- .shutdown = ic3_shutdown,
- .set_termios = ic3_set_termios,
- .type = ic3_type,
- .release_port = null_void_function,
- .request_port = ic3_request_port,
-};
-
-/*
- * Boot-time initialization code
- */
-
-static struct uart_driver ioc3_uart = {
- .owner = THIS_MODULE,
- .driver_name = "ioc3_serial",
- .dev_name = DEVICE_NAME,
- .major = DEVICE_MAJOR,
- .minor = DEVICE_MINOR,
- .nr = MAX_LOGICAL_PORTS
-};
-
-/**
- * ioc3_serial_core_attach - register with serial core
- * This is done during pci probing
- * @is: submodule struct for this
- * @idd: handle for this card
- */
-static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
- struct ioc3_driver_data *idd)
-{
- struct ioc3_port *port;
- struct uart_port *the_port;
- struct ioc3_card *card_ptr = idd->data[is->id];
- int ii, phys_port;
- struct pci_dev *pdev = idd->pdev;
-
- DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n",
- __func__, pdev, (void *)card_ptr));
-
- if (!card_ptr)
- return -ENODEV;
-
- /* once around for each logical port on this card */
- for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
- phys_port = GET_PHYSICAL_PORT(ii);
- the_port = &card_ptr->ic_port[phys_port].
- icp_uart_port[GET_LOGICAL_PORT(ii)];
- port = card_ptr->ic_port[phys_port].icp_port;
- port->ip_port = the_port;
-
- DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n",
- __func__, (void *)the_port, (void *)port,
- phys_port, ii));
-
- /* membase, iobase and mapbase just need to be non-0 */
- the_port->membase = (unsigned char __iomem *)1;
- the_port->iobase = (pdev->bus->number << 16) | ii;
- the_port->line = (Num_of_ioc3_cards << 2) | ii;
- the_port->mapbase = 1;
- the_port->type = PORT_16550A;
- the_port->fifosize = FIFO_SIZE;
- the_port->ops = &ioc3_ops;
- the_port->irq = idd->irq_io;
- the_port->dev = &pdev->dev;
-
- if (uart_add_one_port(&ioc3_uart, the_port) < 0) {
- printk(KERN_WARNING
- "%s: unable to add port %d bus %d\n",
- __func__, the_port->line, pdev->bus->number);
- } else {
- DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n",
- the_port->line, the_port->irq, pdev->bus->number));
- }
-
- /* all ports are rs232 for now */
- if (IS_PHYSICAL_PORT(ii))
- ioc3_set_proto(port, PROTO_RS232);
- }
- return 0;
-}
-
-/**
- * ioc3uart_remove - register detach function
- * @is: submodule struct for this submodule
- * @idd: ioc3 driver data for this submodule
- */
-
-static int ioc3uart_remove(struct ioc3_submodule *is,
- struct ioc3_driver_data *idd)
-{
- struct ioc3_card *card_ptr = idd->data[is->id];
- struct uart_port *the_port;
- struct ioc3_port *port;
- int ii;
-
- if (card_ptr) {
- for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
- the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
- icp_uart_port[GET_LOGICAL_PORT(ii)];
- if (the_port)
- uart_remove_one_port(&ioc3_uart, the_port);
- port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port;
- if (port && IS_PHYSICAL_PORT(ii)
- && (GET_PHYSICAL_PORT(ii) == 0)) {
- pci_free_consistent(port->ip_idd->pdev,
- TOTAL_RING_BUF_SIZE,
- (void *)port->ip_cpu_ringbuf,
- port->ip_dma_ringbuf);
- kfree(port);
- card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
- icp_port = NULL;
- }
- }
- kfree(card_ptr);
- idd->data[is->id] = NULL;
- }
- return 0;
-}
-
-/**
- * ioc3uart_probe - card probe function called from shim driver
- * @is: submodule struct for this submodule
- * @idd: ioc3 driver data for this card
- */
-
-static int __devinit
-ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
-{
- struct pci_dev *pdev = idd->pdev;
- struct ioc3_card *card_ptr;
- int ret = 0;
- struct ioc3_port *port;
- struct ioc3_port *ports[PORTS_PER_CARD];
- int phys_port;
- int cnt;
-
- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd));
-
- card_ptr = kzalloc(sizeof(struct ioc3_card), GFP_KERNEL);
- if (!card_ptr) {
- printk(KERN_WARNING "ioc3_attach_one"
- ": unable to get memory for the IOC3\n");
- return -ENOMEM;
- }
- idd->data[is->id] = card_ptr;
- Submodule_slot = is->id;
-
- writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) |
- ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) |
- (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr);
-
- pci_write_config_dword(pdev, PCI_LAT, 0xff00);
-
- /* Enable serial port mode select generic PIO pins as outputs */
- ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL);
-
- /* Create port structures for each port */
- for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) {
- port = kzalloc(sizeof(struct ioc3_port), GFP_KERNEL);
- if (!port) {
- printk(KERN_WARNING
- "IOC3 serial memory not available for port\n");
- ret = -ENOMEM;
- goto out4;
- }
- spin_lock_init(&port->ip_lock);
-
- /* we need to remember the previous ones, to point back to
- * them farther down - setting up the ring buffers.
- */
- ports[phys_port] = port;
-
- /* init to something useful */
- card_ptr->ic_port[phys_port].icp_port = port;
- port->ip_is = is;
- port->ip_idd = idd;
- port->ip_baud = 9600;
- port->ip_card = card_ptr;
- port->ip_hooks = &hooks_array[phys_port];
-
- /* Setup each port */
- if (phys_port == 0) {
- port->ip_serial_regs = &idd->vma->port_a;
- port->ip_uart_regs = &idd->vma->sregs.uarta;
-
- DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p "
- "ip_uart_regs 0x%p\n",
- __func__,
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* setup ring buffers */
- port->ip_cpu_ringbuf = pci_alloc_consistent(pdev,
- TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf);
-
- BUG_ON(!((((int64_t) port->ip_dma_ringbuf) &
- (TOTAL_RING_BUF_SIZE - 1)) == 0));
- port->ip_inring = RING(port, RX_A);
- port->ip_outring = RING(port, TX_A);
- DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p "
- "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
- "ip_outring 0x%p\n",
- __func__,
- (void *)port->ip_cpu_ringbuf,
- (void *)port->ip_dma_ringbuf,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
- }
- else {
- port->ip_serial_regs = &idd->vma->port_b;
- port->ip_uart_regs = &idd->vma->sregs.uartb;
-
- DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p "
- "ip_uart_regs 0x%p\n",
- __func__,
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* share the ring buffers */
- port->ip_dma_ringbuf =
- ports[phys_port - 1]->ip_dma_ringbuf;
- port->ip_cpu_ringbuf =
- ports[phys_port - 1]->ip_cpu_ringbuf;
- port->ip_inring = RING(port, RX_B);
- port->ip_outring = RING(port, TX_B);
- DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p "
- "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
- "ip_outring 0x%p\n",
- __func__,
- (void *)port->ip_cpu_ringbuf,
- (void *)port->ip_dma_ringbuf,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
- }
-
- DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p",
- __func__,
- phys_port, (void *)port, (void *)card_ptr));
- DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* Initialize the hardware for IOC3 */
- port_init(port);
-
- DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p "
- "outring 0x%p\n",
- __func__,
- phys_port, (void *)port,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
-
- }
-
- /* register port with the serial core */
-
- if ((ret = ioc3_serial_core_attach(is, idd)))
- goto out4;
-
- Num_of_ioc3_cards++;
-
- return ret;
-
- /* error exits that give back resources */
-out4:
- for (cnt = 0; cnt < phys_port; cnt++)
- kfree(ports[cnt]);
-
- kfree(card_ptr);
- return ret;
-}
-
-static struct ioc3_submodule ioc3uart_ops = {
- .name = "IOC3uart",
- .probe = ioc3uart_probe,
- .remove = ioc3uart_remove,
- /* call .intr for both ports initially */
- .irq_mask = SIO_IR_SA | SIO_IR_SB,
- .intr = ioc3uart_intr,
- .owner = THIS_MODULE,
-};
-
-/**
- * ioc3_detect - module init called,
- */
-static int __init ioc3uart_init(void)
-{
- int ret;
-
- /* register with serial core */
- if ((ret = uart_register_driver(&ioc3_uart)) < 0) {
- printk(KERN_WARNING
- "%s: Couldn't register IOC3 uart serial driver\n",
- __func__);
- return ret;
- }
- ret = ioc3_register_submodule(&ioc3uart_ops);
- if (ret)
- uart_unregister_driver(&ioc3_uart);
- return ret;
-}
-
-static void __exit ioc3uart_exit(void)
-{
- ioc3_unregister_submodule(&ioc3uart_ops);
- uart_unregister_driver(&ioc3_uart);
-}
-
-module_init(ioc3uart_init);
-module_exit(ioc3uart_exit);
-
-MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
-MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
deleted file mode 100644
index fcfe82653ac8..000000000000
--- a/drivers/serial/ioc4_serial.c
+++ /dev/null
@@ -1,2953 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-
-/*
- * This file contains a module version of the ioc4 serial driver. This
- * includes all the support functions needed (support functions, etc.)
- * and the serial driver itself.
- */
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/circ_buf.h>
-#include <linux/serial_reg.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ioc4.h>
-#include <linux/serial_core.h>
-#include <linux/slab.h>
-
-/*
- * interesting things about the ioc4
- */
-
-#define IOC4_NUM_SERIAL_PORTS 4 /* max ports per card */
-#define IOC4_NUM_CARDS 8 /* max cards per partition */
-
-#define GET_SIO_IR(_n) (_n == 0) ? (IOC4_SIO_IR_S0) : \
- (_n == 1) ? (IOC4_SIO_IR_S1) : \
- (_n == 2) ? (IOC4_SIO_IR_S2) : \
- (IOC4_SIO_IR_S3)
-
-#define GET_OTHER_IR(_n) (_n == 0) ? (IOC4_OTHER_IR_S0_MEMERR) : \
- (_n == 1) ? (IOC4_OTHER_IR_S1_MEMERR) : \
- (_n == 2) ? (IOC4_OTHER_IR_S2_MEMERR) : \
- (IOC4_OTHER_IR_S3_MEMERR)
-
-
-/*
- * All IOC4 registers are 32 bits wide.
- */
-
-/*
- * PCI Memory Space Map
- */
-#define IOC4_PCI_ERR_ADDR_L 0x000 /* Low Error Address */
-#define IOC4_PCI_ERR_ADDR_VLD (0x1 << 0)
-#define IOC4_PCI_ERR_ADDR_MST_ID_MSK (0xf << 1)
-#define IOC4_PCI_ERR_ADDR_MST_NUM_MSK (0xe << 1)
-#define IOC4_PCI_ERR_ADDR_MST_TYP_MSK (0x1 << 1)
-#define IOC4_PCI_ERR_ADDR_MUL_ERR (0x1 << 5)
-#define IOC4_PCI_ERR_ADDR_ADDR_MSK (0x3ffffff << 6)
-
-/* Interrupt types */
-#define IOC4_SIO_INTR_TYPE 0
-#define IOC4_OTHER_INTR_TYPE 1
-#define IOC4_NUM_INTR_TYPES 2
-
-/* Bitmasks for IOC4_SIO_IR, IOC4_SIO_IEC, and IOC4_SIO_IES */
-#define IOC4_SIO_IR_S0_TX_MT 0x00000001 /* Serial port 0 TX empty */
-#define IOC4_SIO_IR_S0_RX_FULL 0x00000002 /* Port 0 RX buf full */
-#define IOC4_SIO_IR_S0_RX_HIGH 0x00000004 /* Port 0 RX hiwat */
-#define IOC4_SIO_IR_S0_RX_TIMER 0x00000008 /* Port 0 RX timeout */
-#define IOC4_SIO_IR_S0_DELTA_DCD 0x00000010 /* Port 0 delta DCD */
-#define IOC4_SIO_IR_S0_DELTA_CTS 0x00000020 /* Port 0 delta CTS */
-#define IOC4_SIO_IR_S0_INT 0x00000040 /* Port 0 pass-thru intr */
-#define IOC4_SIO_IR_S0_TX_EXPLICIT 0x00000080 /* Port 0 explicit TX thru */
-#define IOC4_SIO_IR_S1_TX_MT 0x00000100 /* Serial port 1 */
-#define IOC4_SIO_IR_S1_RX_FULL 0x00000200 /* */
-#define IOC4_SIO_IR_S1_RX_HIGH 0x00000400 /* */
-#define IOC4_SIO_IR_S1_RX_TIMER 0x00000800 /* */
-#define IOC4_SIO_IR_S1_DELTA_DCD 0x00001000 /* */
-#define IOC4_SIO_IR_S1_DELTA_CTS 0x00002000 /* */
-#define IOC4_SIO_IR_S1_INT 0x00004000 /* */
-#define IOC4_SIO_IR_S1_TX_EXPLICIT 0x00008000 /* */
-#define IOC4_SIO_IR_S2_TX_MT 0x00010000 /* Serial port 2 */
-#define IOC4_SIO_IR_S2_RX_FULL 0x00020000 /* */
-#define IOC4_SIO_IR_S2_RX_HIGH 0x00040000 /* */
-#define IOC4_SIO_IR_S2_RX_TIMER 0x00080000 /* */
-#define IOC4_SIO_IR_S2_DELTA_DCD 0x00100000 /* */
-#define IOC4_SIO_IR_S2_DELTA_CTS 0x00200000 /* */
-#define IOC4_SIO_IR_S2_INT 0x00400000 /* */
-#define IOC4_SIO_IR_S2_TX_EXPLICIT 0x00800000 /* */
-#define IOC4_SIO_IR_S3_TX_MT 0x01000000 /* Serial port 3 */
-#define IOC4_SIO_IR_S3_RX_FULL 0x02000000 /* */
-#define IOC4_SIO_IR_S3_RX_HIGH 0x04000000 /* */
-#define IOC4_SIO_IR_S3_RX_TIMER 0x08000000 /* */
-#define IOC4_SIO_IR_S3_DELTA_DCD 0x10000000 /* */
-#define IOC4_SIO_IR_S3_DELTA_CTS 0x20000000 /* */
-#define IOC4_SIO_IR_S3_INT 0x40000000 /* */
-#define IOC4_SIO_IR_S3_TX_EXPLICIT 0x80000000 /* */
-
-/* Per device interrupt masks */
-#define IOC4_SIO_IR_S0 (IOC4_SIO_IR_S0_TX_MT | \
- IOC4_SIO_IR_S0_RX_FULL | \
- IOC4_SIO_IR_S0_RX_HIGH | \
- IOC4_SIO_IR_S0_RX_TIMER | \
- IOC4_SIO_IR_S0_DELTA_DCD | \
- IOC4_SIO_IR_S0_DELTA_CTS | \
- IOC4_SIO_IR_S0_INT | \
- IOC4_SIO_IR_S0_TX_EXPLICIT)
-#define IOC4_SIO_IR_S1 (IOC4_SIO_IR_S1_TX_MT | \
- IOC4_SIO_IR_S1_RX_FULL | \
- IOC4_SIO_IR_S1_RX_HIGH | \
- IOC4_SIO_IR_S1_RX_TIMER | \
- IOC4_SIO_IR_S1_DELTA_DCD | \
- IOC4_SIO_IR_S1_DELTA_CTS | \
- IOC4_SIO_IR_S1_INT | \
- IOC4_SIO_IR_S1_TX_EXPLICIT)
-#define IOC4_SIO_IR_S2 (IOC4_SIO_IR_S2_TX_MT | \
- IOC4_SIO_IR_S2_RX_FULL | \
- IOC4_SIO_IR_S2_RX_HIGH | \
- IOC4_SIO_IR_S2_RX_TIMER | \
- IOC4_SIO_IR_S2_DELTA_DCD | \
- IOC4_SIO_IR_S2_DELTA_CTS | \
- IOC4_SIO_IR_S2_INT | \
- IOC4_SIO_IR_S2_TX_EXPLICIT)
-#define IOC4_SIO_IR_S3 (IOC4_SIO_IR_S3_TX_MT | \
- IOC4_SIO_IR_S3_RX_FULL | \
- IOC4_SIO_IR_S3_RX_HIGH | \
- IOC4_SIO_IR_S3_RX_TIMER | \
- IOC4_SIO_IR_S3_DELTA_DCD | \
- IOC4_SIO_IR_S3_DELTA_CTS | \
- IOC4_SIO_IR_S3_INT | \
- IOC4_SIO_IR_S3_TX_EXPLICIT)
-
-/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */
-#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */
-#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */
-#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */
-#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */
-#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */
-#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */
-#define IOC4_OTHER_IR_KBD_INT 0x00000040 /* Keyboard/mouse */
-#define IOC4_OTHER_IR_RESERVED 0x007fff80 /* Reserved */
-#define IOC4_OTHER_IR_RT_INT 0x00800000 /* INT_OUT section output */
-#define IOC4_OTHER_IR_GEN_INT 0xff000000 /* Generic pins */
-
-#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \
- IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR)
-
-/* Bitmasks for IOC4_SIO_CR */
-#define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */
-#define IOC4_SIO_CR_ARB_DIAG_TX0 0x00000000
-#define IOC4_SIO_CR_ARB_DIAG_RX0 0x00000010
-#define IOC4_SIO_CR_ARB_DIAG_TX1 0x00000020
-#define IOC4_SIO_CR_ARB_DIAG_RX1 0x00000030
-#define IOC4_SIO_CR_ARB_DIAG_TX2 0x00000040
-#define IOC4_SIO_CR_ARB_DIAG_RX2 0x00000050
-#define IOC4_SIO_CR_ARB_DIAG_TX3 0x00000060
-#define IOC4_SIO_CR_ARB_DIAG_RX3 0x00000070
-#define IOC4_SIO_CR_SIO_DIAG_IDLE 0x00000080 /* 0 -> active request among
- serial ports (ro) */
-/* Defs for some of the generic I/O pins */
-#define IOC4_GPCR_UART0_MODESEL 0x10 /* Pin is output to port 0
- mode sel */
-#define IOC4_GPCR_UART1_MODESEL 0x20 /* Pin is output to port 1
- mode sel */
-#define IOC4_GPCR_UART2_MODESEL 0x40 /* Pin is output to port 2
- mode sel */
-#define IOC4_GPCR_UART3_MODESEL 0x80 /* Pin is output to port 3
- mode sel */
-
-#define IOC4_GPPR_UART0_MODESEL_PIN 4 /* GIO pin controlling
- uart 0 mode select */
-#define IOC4_GPPR_UART1_MODESEL_PIN 5 /* GIO pin controlling
- uart 1 mode select */
-#define IOC4_GPPR_UART2_MODESEL_PIN 6 /* GIO pin controlling
- uart 2 mode select */
-#define IOC4_GPPR_UART3_MODESEL_PIN 7 /* GIO pin controlling
- uart 3 mode select */
-
-/* Bitmasks for serial RX status byte */
-#define IOC4_RXSB_OVERRUN 0x01 /* Char(s) lost */
-#define IOC4_RXSB_PAR_ERR 0x02 /* Parity error */
-#define IOC4_RXSB_FRAME_ERR 0x04 /* Framing error */
-#define IOC4_RXSB_BREAK 0x08 /* Break character */
-#define IOC4_RXSB_CTS 0x10 /* State of CTS */
-#define IOC4_RXSB_DCD 0x20 /* State of DCD */
-#define IOC4_RXSB_MODEM_VALID 0x40 /* DCD, CTS, and OVERRUN are valid */
-#define IOC4_RXSB_DATA_VALID 0x80 /* Data byte, FRAME_ERR PAR_ERR
- * & BREAK valid */
-
-/* Bitmasks for serial TX control byte */
-#define IOC4_TXCB_INT_WHEN_DONE 0x20 /* Interrupt after this byte is sent */
-#define IOC4_TXCB_INVALID 0x00 /* Byte is invalid */
-#define IOC4_TXCB_VALID 0x40 /* Byte is valid */
-#define IOC4_TXCB_MCR 0x80 /* Data<7:0> to modem control reg */
-#define IOC4_TXCB_DELAY 0xc0 /* Delay data<7:0> mSec */
-
-/* Bitmasks for IOC4_SBBR_L */
-#define IOC4_SBBR_L_SIZE 0x00000001 /* 0 == 1KB rings, 1 == 4KB rings */
-
-/* Bitmasks for IOC4_SSCR_<3:0> */
-#define IOC4_SSCR_RX_THRESHOLD 0x000001ff /* Hiwater mark */
-#define IOC4_SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */
-#define IOC4_SSCR_HFC_EN 0x00020000 /* Hardware flow control enabled */
-#define IOC4_SSCR_RX_RING_DCD 0x00040000 /* Post RX record on delta-DCD */
-#define IOC4_SSCR_RX_RING_CTS 0x00080000 /* Post RX record on delta-CTS */
-#define IOC4_SSCR_DIAG 0x00200000 /* Bypass clock divider for sim */
-#define IOC4_SSCR_RX_DRAIN 0x08000000 /* Drain RX buffer to memory */
-#define IOC4_SSCR_DMA_EN 0x10000000 /* Enable ring buffer DMA */
-#define IOC4_SSCR_DMA_PAUSE 0x20000000 /* Pause DMA */
-#define IOC4_SSCR_PAUSE_STATE 0x40000000 /* Sets when PAUSE takes effect */
-#define IOC4_SSCR_RESET 0x80000000 /* Reset DMA channels */
-
-/* All producer/comsumer pointers are the same bitfield */
-#define IOC4_PROD_CONS_PTR_4K 0x00000ff8 /* For 4K buffers */
-#define IOC4_PROD_CONS_PTR_1K 0x000003f8 /* For 1K buffers */
-#define IOC4_PROD_CONS_PTR_OFF 3
-
-/* Bitmasks for IOC4_SRCIR_<3:0> */
-#define IOC4_SRCIR_ARM 0x80000000 /* Arm RX timer */
-
-/* Bitmasks for IOC4_SHADOW_<3:0> */
-#define IOC4_SHADOW_DR 0x00000001 /* Data ready */
-#define IOC4_SHADOW_OE 0x00000002 /* Overrun error */
-#define IOC4_SHADOW_PE 0x00000004 /* Parity error */
-#define IOC4_SHADOW_FE 0x00000008 /* Framing error */
-#define IOC4_SHADOW_BI 0x00000010 /* Break interrupt */
-#define IOC4_SHADOW_THRE 0x00000020 /* Xmit holding register empty */
-#define IOC4_SHADOW_TEMT 0x00000040 /* Xmit shift register empty */
-#define IOC4_SHADOW_RFCE 0x00000080 /* Char in RX fifo has an error */
-#define IOC4_SHADOW_DCTS 0x00010000 /* Delta clear to send */
-#define IOC4_SHADOW_DDCD 0x00080000 /* Delta data carrier detect */
-#define IOC4_SHADOW_CTS 0x00100000 /* Clear to send */
-#define IOC4_SHADOW_DCD 0x00800000 /* Data carrier detect */
-#define IOC4_SHADOW_DTR 0x01000000 /* Data terminal ready */
-#define IOC4_SHADOW_RTS 0x02000000 /* Request to send */
-#define IOC4_SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */
-#define IOC4_SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */
-#define IOC4_SHADOW_LOOP 0x10000000 /* Loopback enabled */
-
-/* Bitmasks for IOC4_SRTR_<3:0> */
-#define IOC4_SRTR_CNT 0x00000fff /* Reload value for RX timer */
-#define IOC4_SRTR_CNT_VAL 0x0fff0000 /* Current value of RX timer */
-#define IOC4_SRTR_CNT_VAL_SHIFT 16
-#define IOC4_SRTR_HZ 16000 /* SRTR clock frequency */
-
-/* Serial port register map used for DMA and PIO serial I/O */
-struct ioc4_serialregs {
- uint32_t sscr;
- uint32_t stpir;
- uint32_t stcir;
- uint32_t srpir;
- uint32_t srcir;
- uint32_t srtr;
- uint32_t shadow;
-};
-
-/* IOC4 UART register map */
-struct ioc4_uartregs {
- char i4u_lcr;
- union {
- char iir; /* read only */
- char fcr; /* write only */
- } u3;
- union {
- char ier; /* DLAB == 0 */
- char dlm; /* DLAB == 1 */
- } u2;
- union {
- char rbr; /* read only, DLAB == 0 */
- char thr; /* write only, DLAB == 0 */
- char dll; /* DLAB == 1 */
- } u1;
- char i4u_scr;
- char i4u_msr;
- char i4u_lsr;
- char i4u_mcr;
-};
-
-/* short names */
-#define i4u_dll u1.dll
-#define i4u_ier u2.ier
-#define i4u_dlm u2.dlm
-#define i4u_fcr u3.fcr
-
-/* Serial port registers used for DMA serial I/O */
-struct ioc4_serial {
- uint32_t sbbr01_l;
- uint32_t sbbr01_h;
- uint32_t sbbr23_l;
- uint32_t sbbr23_h;
-
- struct ioc4_serialregs port_0;
- struct ioc4_serialregs port_1;
- struct ioc4_serialregs port_2;
- struct ioc4_serialregs port_3;
- struct ioc4_uartregs uart_0;
- struct ioc4_uartregs uart_1;
- struct ioc4_uartregs uart_2;
- struct ioc4_uartregs uart_3;
-} ioc4_serial;
-
-/* UART clock speed */
-#define IOC4_SER_XIN_CLK_66 66666667
-#define IOC4_SER_XIN_CLK_33 33333333
-
-#define IOC4_W_IES 0
-#define IOC4_W_IEC 1
-
-typedef void ioc4_intr_func_f(void *, uint32_t);
-typedef ioc4_intr_func_f *ioc4_intr_func_t;
-
-static unsigned int Num_of_ioc4_cards;
-
-/* defining this will get you LOTS of great debug info */
-//#define DEBUG_INTERRUPTS
-#define DPRINT_CONFIG(_x...) ;
-//#define DPRINT_CONFIG(_x...) printk _x
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/* number of characters we want to transmit to the lower level at a time */
-#define IOC4_MAX_CHARS 256
-#define IOC4_FIFO_CHARS 255
-
-/* Device name we're using */
-#define DEVICE_NAME_RS232 "ttyIOC"
-#define DEVICE_NAME_RS422 "ttyAIOC"
-#define DEVICE_MAJOR 204
-#define DEVICE_MINOR_RS232 50
-#define DEVICE_MINOR_RS422 84
-
-
-/* register offsets */
-#define IOC4_SERIAL_OFFSET 0x300
-
-/* flags for next_char_state */
-#define NCS_BREAK 0x1
-#define NCS_PARITY 0x2
-#define NCS_FRAMING 0x4
-#define NCS_OVERRUN 0x8
-
-/* cause we need SOME parameters ... */
-#define MIN_BAUD_SUPPORTED 1200
-#define MAX_BAUD_SUPPORTED 115200
-
-/* protocol types supported */
-#define PROTO_RS232 3
-#define PROTO_RS422 7
-
-/* Notification types */
-#define N_DATA_READY 0x01
-#define N_OUTPUT_LOWAT 0x02
-#define N_BREAK 0x04
-#define N_PARITY_ERROR 0x08
-#define N_FRAMING_ERROR 0x10
-#define N_OVERRUN_ERROR 0x20
-#define N_DDCD 0x40
-#define N_DCTS 0x80
-
-#define N_ALL_INPUT (N_DATA_READY | N_BREAK | \
- N_PARITY_ERROR | N_FRAMING_ERROR | \
- N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define N_ALL_OUTPUT N_OUTPUT_LOWAT
-
-#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR | N_OVERRUN_ERROR)
-
-#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK | \
- N_PARITY_ERROR | N_FRAMING_ERROR | \
- N_OVERRUN_ERROR | N_DDCD | N_DCTS)
-
-#define SER_DIVISOR(_x, clk) (((clk) + (_x) * 8) / ((_x) * 16))
-#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div))
-
-/* Some masks */
-#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \
- | UART_LCR_WLEN7 | UART_LCR_WLEN8)
-#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
-
-#define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb)
-#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw)
-
-/* Default to 4k buffers */
-#ifdef IOC4_1K_BUFFERS
-#define RING_BUF_SIZE 1024
-#define IOC4_BUF_SIZE_BIT 0
-#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_1K
-#else
-#define RING_BUF_SIZE 4096
-#define IOC4_BUF_SIZE_BIT IOC4_SBBR_L_SIZE
-#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_4K
-#endif
-
-#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
-
-/*
- * This is the entry saved by the driver - one per card
- */
-
-#define UART_PORT_MIN 0
-#define UART_PORT_RS232 UART_PORT_MIN
-#define UART_PORT_RS422 1
-#define UART_PORT_COUNT 2 /* one for each mode */
-
-struct ioc4_control {
- int ic_irq;
- struct {
- /* uart ports are allocated here - 1 for rs232, 1 for rs422 */
- struct uart_port icp_uart_port[UART_PORT_COUNT];
- /* Handy reference material */
- struct ioc4_port *icp_port;
- } ic_port[IOC4_NUM_SERIAL_PORTS];
- struct ioc4_soft *ic_soft;
-};
-
-/*
- * per-IOC4 data structure
- */
-#define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t))
-struct ioc4_soft {
- struct ioc4_misc_regs __iomem *is_ioc4_misc_addr;
- struct ioc4_serial __iomem *is_ioc4_serial_addr;
-
- /* Each interrupt type has an entry in the array */
- struct ioc4_intr_type {
-
- /*
- * Each in-use entry in this array contains at least
- * one nonzero bit in sd_bits; no two entries in this
- * array have overlapping sd_bits values.
- */
- struct ioc4_intr_info {
- uint32_t sd_bits;
- ioc4_intr_func_f *sd_intr;
- void *sd_info;
- } is_intr_info[MAX_IOC4_INTR_ENTS];
-
- /* Number of entries active in the above array */
- atomic_t is_num_intrs;
- } is_intr_type[IOC4_NUM_INTR_TYPES];
-
- /* is_ir_lock must be held while
- * modifying sio_ie values, so
- * we can be sure that sio_ie is
- * not changing when we read it
- * along with sio_ir.
- */
- spinlock_t is_ir_lock; /* SIO_IE[SC] mod lock */
-};
-
-/* Local port info for each IOC4 serial ports */
-struct ioc4_port {
- struct uart_port *ip_port; /* current active port ptr */
- /* Ptrs for all ports */
- struct uart_port *ip_all_ports[UART_PORT_COUNT];
- /* Back ptrs for this port */
- struct ioc4_control *ip_control;
- struct pci_dev *ip_pdev;
- struct ioc4_soft *ip_ioc4_soft;
-
- /* pci mem addresses */
- struct ioc4_misc_regs __iomem *ip_mem;
- struct ioc4_serial __iomem *ip_serial;
- struct ioc4_serialregs __iomem *ip_serial_regs;
- struct ioc4_uartregs __iomem *ip_uart_regs;
-
- /* Ring buffer page for this port */
- dma_addr_t ip_dma_ringbuf;
- /* vaddr of ring buffer */
- struct ring_buffer *ip_cpu_ringbuf;
-
- /* Rings for this port */
- struct ring *ip_inring;
- struct ring *ip_outring;
-
- /* Hook to port specific values */
- struct hooks *ip_hooks;
-
- spinlock_t ip_lock;
-
- /* Various rx/tx parameters */
- int ip_baud;
- int ip_tx_lowat;
- int ip_rx_timeout;
-
- /* Copy of notification bits */
- int ip_notify;
-
- /* Shadow copies of various registers so we don't need to PIO
- * read them constantly
- */
- uint32_t ip_ienb; /* Enabled interrupts */
- uint32_t ip_sscr;
- uint32_t ip_tx_prod;
- uint32_t ip_rx_cons;
- int ip_pci_bus_speed;
- unsigned char ip_flags;
-};
-
-/* tx low water mark. We need to notify the driver whenever tx is getting
- * close to empty so it can refill the tx buffer and keep things going.
- * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
- * have no trouble getting in more chars in time (I certainly hope so).
- */
-#define TX_LOWAT_LATENCY 1000
-#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY)
-#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
-
-/* Flags per port */
-#define INPUT_HIGH 0x01
-#define DCD_ON 0x02
-#define LOWAT_WRITTEN 0x04
-#define READ_ABORTED 0x08
-#define PORT_ACTIVE 0x10
-#define PORT_INACTIVE 0 /* This is the value when "off" */
-
-
-/* Since each port has different register offsets and bitmasks
- * for everything, we'll store those that we need in tables so we
- * don't have to be constantly checking the port we are dealing with.
- */
-struct hooks {
- uint32_t intr_delta_dcd;
- uint32_t intr_delta_cts;
- uint32_t intr_tx_mt;
- uint32_t intr_rx_timer;
- uint32_t intr_rx_high;
- uint32_t intr_tx_explicit;
- uint32_t intr_dma_error;
- uint32_t intr_clear;
- uint32_t intr_all;
- int rs422_select_pin;
-};
-
-static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
- /* Values for port 0 */
- {
- IOC4_SIO_IR_S0_DELTA_DCD, IOC4_SIO_IR_S0_DELTA_CTS,
- IOC4_SIO_IR_S0_TX_MT, IOC4_SIO_IR_S0_RX_TIMER,
- IOC4_SIO_IR_S0_RX_HIGH, IOC4_SIO_IR_S0_TX_EXPLICIT,
- IOC4_OTHER_IR_S0_MEMERR,
- (IOC4_SIO_IR_S0_TX_MT | IOC4_SIO_IR_S0_RX_FULL |
- IOC4_SIO_IR_S0_RX_HIGH | IOC4_SIO_IR_S0_RX_TIMER |
- IOC4_SIO_IR_S0_DELTA_DCD | IOC4_SIO_IR_S0_DELTA_CTS |
- IOC4_SIO_IR_S0_INT | IOC4_SIO_IR_S0_TX_EXPLICIT),
- IOC4_SIO_IR_S0, IOC4_GPPR_UART0_MODESEL_PIN,
- },
-
- /* Values for port 1 */
- {
- IOC4_SIO_IR_S1_DELTA_DCD, IOC4_SIO_IR_S1_DELTA_CTS,
- IOC4_SIO_IR_S1_TX_MT, IOC4_SIO_IR_S1_RX_TIMER,
- IOC4_SIO_IR_S1_RX_HIGH, IOC4_SIO_IR_S1_TX_EXPLICIT,
- IOC4_OTHER_IR_S1_MEMERR,
- (IOC4_SIO_IR_S1_TX_MT | IOC4_SIO_IR_S1_RX_FULL |
- IOC4_SIO_IR_S1_RX_HIGH | IOC4_SIO_IR_S1_RX_TIMER |
- IOC4_SIO_IR_S1_DELTA_DCD | IOC4_SIO_IR_S1_DELTA_CTS |
- IOC4_SIO_IR_S1_INT | IOC4_SIO_IR_S1_TX_EXPLICIT),
- IOC4_SIO_IR_S1, IOC4_GPPR_UART1_MODESEL_PIN,
- },
-
- /* Values for port 2 */
- {
- IOC4_SIO_IR_S2_DELTA_DCD, IOC4_SIO_IR_S2_DELTA_CTS,
- IOC4_SIO_IR_S2_TX_MT, IOC4_SIO_IR_S2_RX_TIMER,
- IOC4_SIO_IR_S2_RX_HIGH, IOC4_SIO_IR_S2_TX_EXPLICIT,
- IOC4_OTHER_IR_S2_MEMERR,
- (IOC4_SIO_IR_S2_TX_MT | IOC4_SIO_IR_S2_RX_FULL |
- IOC4_SIO_IR_S2_RX_HIGH | IOC4_SIO_IR_S2_RX_TIMER |
- IOC4_SIO_IR_S2_DELTA_DCD | IOC4_SIO_IR_S2_DELTA_CTS |
- IOC4_SIO_IR_S2_INT | IOC4_SIO_IR_S2_TX_EXPLICIT),
- IOC4_SIO_IR_S2, IOC4_GPPR_UART2_MODESEL_PIN,
- },
-
- /* Values for port 3 */
- {
- IOC4_SIO_IR_S3_DELTA_DCD, IOC4_SIO_IR_S3_DELTA_CTS,
- IOC4_SIO_IR_S3_TX_MT, IOC4_SIO_IR_S3_RX_TIMER,
- IOC4_SIO_IR_S3_RX_HIGH, IOC4_SIO_IR_S3_TX_EXPLICIT,
- IOC4_OTHER_IR_S3_MEMERR,
- (IOC4_SIO_IR_S3_TX_MT | IOC4_SIO_IR_S3_RX_FULL |
- IOC4_SIO_IR_S3_RX_HIGH | IOC4_SIO_IR_S3_RX_TIMER |
- IOC4_SIO_IR_S3_DELTA_DCD | IOC4_SIO_IR_S3_DELTA_CTS |
- IOC4_SIO_IR_S3_INT | IOC4_SIO_IR_S3_TX_EXPLICIT),
- IOC4_SIO_IR_S3, IOC4_GPPR_UART3_MODESEL_PIN,
- }
-};
-
-/* A ring buffer entry */
-struct ring_entry {
- union {
- struct {
- uint32_t alldata;
- uint32_t allsc;
- } all;
- struct {
- char data[4]; /* data bytes */
- char sc[4]; /* status/control */
- } s;
- } u;
-};
-
-/* Test the valid bits in any of the 4 sc chars using "allsc" member */
-#define RING_ANY_VALID \
- ((uint32_t)(IOC4_RXSB_MODEM_VALID | IOC4_RXSB_DATA_VALID) * 0x01010101)
-
-#define ring_sc u.s.sc
-#define ring_data u.s.data
-#define ring_allsc u.all.allsc
-
-/* Number of entries per ring buffer. */
-#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
-
-/* An individual ring */
-struct ring {
- struct ring_entry entries[ENTRIES_PER_RING];
-};
-
-/* The whole enchilada */
-struct ring_buffer {
- struct ring TX_0_OR_2;
- struct ring RX_0_OR_2;
- struct ring TX_1_OR_3;
- struct ring RX_1_OR_3;
-};
-
-/* Get a ring from a port struct */
-#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
-
-/* Infinite loop detection.
- */
-#define MAXITER 10000000
-
-/* Prototypes */
-static void receive_chars(struct uart_port *);
-static void handle_intr(void *arg, uint32_t sio_ir);
-
-/*
- * port_is_active - determines if this port is currently active
- * @port: ptr to soft struct for this port
- * @uart_port: uart port to test for
- */
-static inline int port_is_active(struct ioc4_port *port,
- struct uart_port *uart_port)
-{
- if (port) {
- if ((port->ip_flags & PORT_ACTIVE)
- && (port->ip_port == uart_port))
- return 1;
- }
- return 0;
-}
-
-
-/**
- * write_ireg - write the interrupt regs
- * @ioc4_soft: ptr to soft struct for this port
- * @val: value to write
- * @which: which register
- * @type: which ireg set
- */
-static inline void
-write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
-{
- struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
-
- switch (type) {
- case IOC4_SIO_INTR_TYPE:
- switch (which) {
- case IOC4_W_IES:
- writel(val, &mem->sio_ies.raw);
- break;
-
- case IOC4_W_IEC:
- writel(val, &mem->sio_iec.raw);
- break;
- }
- break;
-
- case IOC4_OTHER_INTR_TYPE:
- switch (which) {
- case IOC4_W_IES:
- writel(val, &mem->other_ies.raw);
- break;
-
- case IOC4_W_IEC:
- writel(val, &mem->other_iec.raw);
- break;
- }
- break;
-
- default:
- break;
- }
- spin_unlock_irqrestore(&ioc4_soft->is_ir_lock, flags);
-}
-
-/**
- * set_baud - Baud rate setting code
- * @port: port to set
- * @baud: baud rate to use
- */
-static int set_baud(struct ioc4_port *port, int baud)
-{
- int actual_baud;
- int diff;
- int lcr;
- unsigned short divisor;
- struct ioc4_uartregs __iomem *uart;
-
- divisor = SER_DIVISOR(baud, port->ip_pci_bus_speed);
- if (!divisor)
- return 1;
- actual_baud = DIVISOR_TO_BAUD(divisor, port->ip_pci_bus_speed);
-
- diff = actual_baud - baud;
- if (diff < 0)
- diff = -diff;
-
- /* If we're within 1%, we've found a match */
- if (diff * 100 > actual_baud)
- return 1;
-
- uart = port->ip_uart_regs;
- lcr = readb(&uart->i4u_lcr);
- writeb(lcr | UART_LCR_DLAB, &uart->i4u_lcr);
- writeb((unsigned char)divisor, &uart->i4u_dll);
- writeb((unsigned char)(divisor >> 8), &uart->i4u_dlm);
- writeb(lcr, &uart->i4u_lcr);
- return 0;
-}
-
-
-/**
- * get_ioc4_port - given a uart port, return the control structure
- * @port: uart port
- * @set: set this port as current
- */
-static struct ioc4_port *get_ioc4_port(struct uart_port *the_port, int set)
-{
- struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev);
- struct ioc4_control *control = idd->idd_serial_data;
- struct ioc4_port *port;
- int port_num, port_type;
-
- if (control) {
- for ( port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS;
- port_num++ ) {
- port = control->ic_port[port_num].icp_port;
- if (!port)
- continue;
- for (port_type = UART_PORT_MIN;
- port_type < UART_PORT_COUNT;
- port_type++) {
- if (the_port == port->ip_all_ports
- [port_type]) {
- /* set local copy */
- if (set) {
- port->ip_port = the_port;
- }
- return port;
- }
- }
- }
- }
- return NULL;
-}
-
-/* The IOC4 hardware provides no atomic way to determine if interrupts
- * are pending since two reads are required to do so. The handler must
- * read the SIO_IR and the SIO_IES, and take the logical and of the
- * two. When this value is zero, all interrupts have been serviced and
- * the handler may return.
- *
- * This has the unfortunate "hole" that, if some other CPU or
- * some other thread or some higher level interrupt manages to
- * modify SIO_IE between our reads of SIO_IR and SIO_IE, we may
- * think we have observed SIO_IR&SIO_IE==0 when in fact this
- * condition never really occurred.
- *
- * To solve this, we use a simple spinlock that must be held
- * whenever modifying SIO_IE; holding this lock while observing
- * both SIO_IR and SIO_IE guarantees that we do not falsely
- * conclude that no enabled interrupts are pending.
- */
-
-static inline uint32_t
-pending_intrs(struct ioc4_soft *soft, int type)
-{
- struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
- unsigned long flag;
- uint32_t intrs = 0;
-
- BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
- || (type == IOC4_OTHER_INTR_TYPE)));
-
- spin_lock_irqsave(&soft->is_ir_lock, flag);
-
- switch (type) {
- case IOC4_SIO_INTR_TYPE:
- intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw);
- break;
-
- case IOC4_OTHER_INTR_TYPE:
- intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw);
-
- /* Don't process any ATA interrupte */
- intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
- break;
-
- default:
- break;
- }
- spin_unlock_irqrestore(&soft->is_ir_lock, flag);
- return intrs;
-}
-
-/**
- * port_init - Initialize the sio and ioc4 hardware for a given port
- * called per port from attach...
- * @port: port to initialize
- */
-static int inline port_init(struct ioc4_port *port)
-{
- uint32_t sio_cr;
- struct hooks *hooks = port->ip_hooks;
- struct ioc4_uartregs __iomem *uart;
-
- /* Idle the IOC4 serial interface */
- writel(IOC4_SSCR_RESET, &port->ip_serial_regs->sscr);
-
- /* Wait until any pending bus activity for this port has ceased */
- do
- sio_cr = readl(&port->ip_mem->sio_cr.raw);
- while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
-
- /* Finish reset sequence */
- writel(0, &port->ip_serial_regs->sscr);
-
- /* Once RESET is done, reload cached tx_prod and rx_cons values
- * and set rings to empty by making prod == cons
- */
- port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
- port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- /* Disable interrupts for this 16550 */
- uart = port->ip_uart_regs;
- writeb(0, &uart->i4u_lcr);
- writeb(0, &uart->i4u_ier);
-
- /* Set the default baud */
- set_baud(port, port->ip_baud);
-
- /* Set line control to 8 bits no parity */
- writeb(UART_LCR_WLEN8 | 0, &uart->i4u_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Enable the FIFOs */
- writeb(UART_FCR_ENABLE_FIFO, &uart->i4u_fcr);
- /* then reset 16550 FIFOs */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
- &uart->i4u_fcr);
-
- /* Clear modem control register */
- writeb(0, &uart->i4u_mcr);
-
- /* Clear deltas in modem status register */
- readb(&uart->i4u_msr);
-
- /* Only do this once per port pair */
- if (port->ip_hooks == &hooks_array[0]
- || port->ip_hooks == &hooks_array[2]) {
- unsigned long ring_pci_addr;
- uint32_t __iomem *sbbr_l;
- uint32_t __iomem *sbbr_h;
-
- if (port->ip_hooks == &hooks_array[0]) {
- sbbr_l = &port->ip_serial->sbbr01_l;
- sbbr_h = &port->ip_serial->sbbr01_h;
- } else {
- sbbr_l = &port->ip_serial->sbbr23_l;
- sbbr_h = &port->ip_serial->sbbr23_h;
- }
-
- ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
- DPRINT_CONFIG(("%s: ring_pci_addr 0x%lx\n",
- __func__, ring_pci_addr));
-
- writel((unsigned int)((uint64_t)ring_pci_addr >> 32), sbbr_h);
- writel((unsigned int)ring_pci_addr | IOC4_BUF_SIZE_BIT, sbbr_l);
- }
-
- /* Set the receive timeout value to 10 msec */
- writel(IOC4_SRTR_HZ / 100, &port->ip_serial_regs->srtr);
-
- /* Set rx threshold, enable DMA */
- /* Set high water mark at 3/4 of full ring */
- port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Disable and clear all serial related interrupt bits */
- write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
- IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
- port->ip_ienb &= ~hooks->intr_clear;
- writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw);
- return 0;
-}
-
-/**
- * handle_dma_error_intr - service any pending DMA error interrupts for the
- * given port - 2nd level called via sd_intr
- * @arg: handler arg
- * @other_ir: ioc4regs
- */
-static void handle_dma_error_intr(void *arg, uint32_t other_ir)
-{
- struct ioc4_port *port = (struct ioc4_port *)arg;
- struct hooks *hooks = port->ip_hooks;
- unsigned long flags;
-
- spin_lock_irqsave(&port->ip_lock, flags);
-
- /* ACK the interrupt */
- writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw);
-
- if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) {
- printk(KERN_ERR
- "PCI error address is 0x%llx, "
- "master is serial port %c %s\n",
- (((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
- << 32)
- | readl(&port->ip_mem->pci_err_addr_l.raw))
- & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
- ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) &
- IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
- (readl(&port->ip_mem->pci_err_addr_l.raw)
- & IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
- ? "RX" : "TX");
-
- if (readl(&port->ip_mem->pci_err_addr_l.raw)
- & IOC4_PCI_ERR_ADDR_MUL_ERR) {
- printk(KERN_ERR
- "Multiple errors occurred\n");
- }
- }
- spin_unlock_irqrestore(&port->ip_lock, flags);
-
- /* Re-enable DMA error interrupts */
- write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error, IOC4_W_IES,
- IOC4_OTHER_INTR_TYPE);
-}
-
-/**
- * intr_connect - interrupt connect function
- * @soft: soft struct for this card
- * @type: interrupt type
- * @intrbits: bit pattern to set
- * @intr: handler function
- * @info: handler arg
- */
-static void
-intr_connect(struct ioc4_soft *soft, int type,
- uint32_t intrbits, ioc4_intr_func_f * intr, void *info)
-{
- int i;
- struct ioc4_intr_info *intr_ptr;
-
- BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
- || (type == IOC4_OTHER_INTR_TYPE)));
-
- i = atomic_inc(&soft-> is_intr_type[type].is_num_intrs) - 1;
- BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0)));
-
- /* Save off the lower level interrupt handler */
- intr_ptr = &soft->is_intr_type[type].is_intr_info[i];
- intr_ptr->sd_bits = intrbits;
- intr_ptr->sd_intr = intr;
- intr_ptr->sd_info = info;
-}
-
-/**
- * ioc4_intr - Top level IOC4 interrupt handler.
- * @irq: irq value
- * @arg: handler arg
- */
-
-static irqreturn_t ioc4_intr(int irq, void *arg)
-{
- struct ioc4_soft *soft;
- uint32_t this_ir, this_mir;
- int xx, num_intrs = 0;
- int intr_type;
- int handled = 0;
- struct ioc4_intr_info *intr_info;
-
- soft = arg;
- for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) {
- num_intrs = (int)atomic_read(
- &soft->is_intr_type[intr_type].is_num_intrs);
-
- this_mir = this_ir = pending_intrs(soft, intr_type);
-
- /* Farm out the interrupt to the various drivers depending on
- * which interrupt bits are set.
- */
- for (xx = 0; xx < num_intrs; xx++) {
- intr_info = &soft->is_intr_type[intr_type].is_intr_info[xx];
- if ((this_mir = this_ir & intr_info->sd_bits)) {
- /* Disable owned interrupts, call handler */
- handled++;
- write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC,
- intr_type);
- intr_info->sd_intr(intr_info->sd_info, this_mir);
- this_ir &= ~this_mir;
- }
- }
- }
-#ifdef DEBUG_INTERRUPTS
- {
- struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
- unsigned long flag;
-
- spin_lock_irqsave(&soft->is_ir_lock, flag);
- printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
- "other_ir 0x%x other_ies 0x%x mask 0x%x\n",
- __func__, __LINE__,
- (void *)mem, readl(&mem->sio_ir.raw),
- readl(&mem->sio_ies.raw),
- readl(&mem->other_ir.raw),
- readl(&mem->other_ies.raw),
- IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
- spin_unlock_irqrestore(&soft->is_ir_lock, flag);
- }
-#endif
- return handled ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/**
- * ioc4_attach_local - Device initialization.
- * Called at *_attach() time for each
- * IOC4 with serial ports in the system.
- * @idd: Master module data for this IOC4
- */
-static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
-{
- struct ioc4_port *port;
- struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS];
- int port_number;
- uint16_t ioc4_revid_min = 62;
- uint16_t ioc4_revid;
- struct pci_dev *pdev = idd->idd_pdev;
- struct ioc4_control* control = idd->idd_serial_data;
- struct ioc4_soft *soft = control->ic_soft;
- void __iomem *ioc4_misc = idd->idd_misc_regs;
- void __iomem *ioc4_serial = soft->is_ioc4_serial_addr;
-
- /* IOC4 firmware must be at least rev 62 */
- pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid);
-
- printk(KERN_INFO "IOC4 firmware revision %d\n", ioc4_revid);
- if (ioc4_revid < ioc4_revid_min) {
- printk(KERN_WARNING
- "IOC4 serial not supported on firmware rev %d, "
- "please upgrade to rev %d or higher\n",
- ioc4_revid, ioc4_revid_min);
- return -EPERM;
- }
- BUG_ON(ioc4_misc == NULL);
- BUG_ON(ioc4_serial == NULL);
-
- /* Create port structures for each port */
- for (port_number = 0; port_number < IOC4_NUM_SERIAL_PORTS;
- port_number++) {
- port = kzalloc(sizeof(struct ioc4_port), GFP_KERNEL);
- if (!port) {
- printk(KERN_WARNING
- "IOC4 serial memory not available for port\n");
- return -ENOMEM;
- }
- spin_lock_init(&port->ip_lock);
-
- /* we need to remember the previous ones, to point back to
- * them farther down - setting up the ring buffers.
- */
- ports[port_number] = port;
-
- /* Allocate buffers and jumpstart the hardware. */
- control->ic_port[port_number].icp_port = port;
- port->ip_ioc4_soft = soft;
- port->ip_pdev = pdev;
- port->ip_ienb = 0;
- /* Use baud rate calculations based on detected PCI
- * bus speed. Simply test whether the PCI clock is
- * running closer to 66MHz or 33MHz.
- */
- if (idd->count_period/IOC4_EXTINT_COUNT_DIVISOR < 20) {
- port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_66;
- } else {
- port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_33;
- }
- port->ip_baud = 9600;
- port->ip_control = control;
- port->ip_mem = ioc4_misc;
- port->ip_serial = ioc4_serial;
-
- /* point to the right hook */
- port->ip_hooks = &hooks_array[port_number];
-
- /* Get direct hooks to the serial regs and uart regs
- * for this port
- */
- switch (port_number) {
- case 0:
- port->ip_serial_regs = &(port->ip_serial->port_0);
- port->ip_uart_regs = &(port->ip_serial->uart_0);
- break;
- case 1:
- port->ip_serial_regs = &(port->ip_serial->port_1);
- port->ip_uart_regs = &(port->ip_serial->uart_1);
- break;
- case 2:
- port->ip_serial_regs = &(port->ip_serial->port_2);
- port->ip_uart_regs = &(port->ip_serial->uart_2);
- break;
- default:
- case 3:
- port->ip_serial_regs = &(port->ip_serial->port_3);
- port->ip_uart_regs = &(port->ip_serial->uart_3);
- break;
- }
-
- /* ring buffers are 1 to a pair of ports */
- if (port_number && (port_number & 1)) {
- /* odd use the evens buffer */
- port->ip_dma_ringbuf =
- ports[port_number - 1]->ip_dma_ringbuf;
- port->ip_cpu_ringbuf =
- ports[port_number - 1]->ip_cpu_ringbuf;
- port->ip_inring = RING(port, RX_1_OR_3);
- port->ip_outring = RING(port, TX_1_OR_3);
-
- } else {
- if (port->ip_dma_ringbuf == 0) {
- port->ip_cpu_ringbuf = pci_alloc_consistent
- (pdev, TOTAL_RING_BUF_SIZE,
- &port->ip_dma_ringbuf);
-
- }
- BUG_ON(!((((int64_t)port->ip_dma_ringbuf) &
- (TOTAL_RING_BUF_SIZE - 1)) == 0));
- DPRINT_CONFIG(("%s : ip_cpu_ringbuf 0x%p "
- "ip_dma_ringbuf 0x%p\n",
- __func__,
- (void *)port->ip_cpu_ringbuf,
- (void *)port->ip_dma_ringbuf));
- port->ip_inring = RING(port, RX_0_OR_2);
- port->ip_outring = RING(port, TX_0_OR_2);
- }
- DPRINT_CONFIG(("%s : port %d [addr 0x%p] control 0x%p",
- __func__,
- port_number, (void *)port, (void *)control));
- DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
- (void *)port->ip_serial_regs,
- (void *)port->ip_uart_regs));
-
- /* Initialize the hardware for IOC4 */
- port_init(port);
-
- DPRINT_CONFIG(("%s: port_number %d port 0x%p inring 0x%p "
- "outring 0x%p\n",
- __func__,
- port_number, (void *)port,
- (void *)port->ip_inring,
- (void *)port->ip_outring));
-
- /* Attach interrupt handlers */
- intr_connect(soft, IOC4_SIO_INTR_TYPE,
- GET_SIO_IR(port_number),
- handle_intr, port);
-
- intr_connect(soft, IOC4_OTHER_INTR_TYPE,
- GET_OTHER_IR(port_number),
- handle_dma_error_intr, port);
- }
- return 0;
-}
-
-/**
- * enable_intrs - enable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static void enable_intrs(struct ioc4_port *port, uint32_t mask)
-{
- struct hooks *hooks = port->ip_hooks;
-
- if ((port->ip_ienb & mask) != mask) {
- write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IES,
- IOC4_SIO_INTR_TYPE);
- port->ip_ienb |= mask;
- }
-
- if (port->ip_ienb)
- write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
- IOC4_W_IES, IOC4_OTHER_INTR_TYPE);
-}
-
-/**
- * local_open - local open a port
- * @port: port to open
- */
-static inline int local_open(struct ioc4_port *port)
-{
- int spiniter = 0;
-
- port->ip_flags = PORT_ACTIVE;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while((readl(&port->ip_serial_regs-> sscr)
- & IOC4_SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER) {
- port->ip_flags = PORT_INACTIVE;
- return -1;
- }
- }
- }
-
- /* Reset the input fifo. If the uart received chars while the port
- * was closed and DMA is not enabled, the uart may have a bunch of
- * chars hanging around in its rx fifo which will not be discarded
- * by rclr in the upper layer. We must get rid of them here.
- */
- writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
- &port->ip_uart_regs->i4u_fcr);
-
- writeb(UART_LCR_WLEN8, &port->ip_uart_regs->i4u_lcr);
- /* UART_LCR_STOP == 1 stop */
-
- /* Re-enable DMA, set default threshold to intr whenever there is
- * data available.
- */
- port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
- port->ip_sscr |= 1; /* default threshold */
-
- /* Plug in the new sscr. This implicitly clears the DMA_PAUSE
- * flag if it was set above
- */
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- port->ip_tx_lowat = 1;
- return 0;
-}
-
-/**
- * set_rx_timeout - Set rx timeout and threshold values.
- * @port: port to use
- * @timeout: timeout value in ticks
- */
-static inline int set_rx_timeout(struct ioc4_port *port, int timeout)
-{
- int threshold;
-
- port->ip_rx_timeout = timeout;
-
- /* Timeout is in ticks. Let's figure out how many chars we
- * can receive at the current baud rate in that interval
- * and set the rx threshold to that amount. There are 4 chars
- * per ring entry, so we'll divide the number of chars that will
- * arrive in timeout by 4.
- * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
- */
- threshold = timeout * port->ip_baud / 4000;
- if (threshold == 0)
- threshold = 1; /* otherwise we'll intr all the time! */
-
- if ((unsigned)threshold > (unsigned)IOC4_SSCR_RX_THRESHOLD)
- return 1;
-
- port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
- port->ip_sscr |= threshold;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Now set the rx timeout to the given value
- * again timeout * IOC4_SRTR_HZ / HZ
- */
- timeout = timeout * IOC4_SRTR_HZ / 100;
- if (timeout > IOC4_SRTR_CNT)
- timeout = IOC4_SRTR_CNT;
-
- writel(timeout, &port->ip_serial_regs->srtr);
- return 0;
-}
-
-/**
- * config_port - config the hardware
- * @port: port to config
- * @baud: baud rate for the port
- * @byte_size: data size
- * @stop_bits: number of stop bits
- * @parenb: parity enable ?
- * @parodd: odd parity ?
- */
-static inline int
-config_port(struct ioc4_port *port,
- int baud, int byte_size, int stop_bits, int parenb, int parodd)
-{
- char lcr, sizebits;
- int spiniter = 0;
-
- DPRINT_CONFIG(("%s: baud %d byte_size %d stop %d parenb %d parodd %d\n",
- __func__, baud, byte_size, stop_bits, parenb, parodd));
-
- if (set_baud(port, baud))
- return 1;
-
- switch (byte_size) {
- case 5:
- sizebits = UART_LCR_WLEN5;
- break;
- case 6:
- sizebits = UART_LCR_WLEN6;
- break;
- case 7:
- sizebits = UART_LCR_WLEN7;
- break;
- case 8:
- sizebits = UART_LCR_WLEN8;
- break;
- default:
- return 1;
- }
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while((readl(&port->ip_serial_regs->sscr)
- & IOC4_SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
-
- /* Clear relevant fields in lcr */
- lcr = readb(&port->ip_uart_regs->i4u_lcr);
- lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
- UART_LCR_PARITY | LCR_MASK_STOP_BITS);
-
- /* Set byte size in lcr */
- lcr |= sizebits;
-
- /* Set parity */
- if (parenb) {
- lcr |= UART_LCR_PARITY;
- if (!parodd)
- lcr |= UART_LCR_EPAR;
- }
-
- /* Set stop bits */
- if (stop_bits)
- lcr |= UART_LCR_STOP /* 2 stop bits */ ;
-
- writeb(lcr, &port->ip_uart_regs->i4u_lcr);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- port->ip_baud = baud;
-
- /* When we get within this number of ring entries of filling the
- * entire ring on tx, place an EXPLICIT intr to generate a lowat
- * notification when output has drained.
- */
- port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
- if (port->ip_tx_lowat == 0)
- port->ip_tx_lowat = 1;
-
- set_rx_timeout(port, 2);
-
- return 0;
-}
-
-/**
- * do_write - Write bytes to the port. Returns the number of bytes
- * actually written. Called from transmit_chars
- * @port: port to use
- * @buf: the stuff to write
- * @len: how many bytes in 'buf'
- */
-static inline int do_write(struct ioc4_port *port, char *buf, int len)
-{
- int prod_ptr, cons_ptr, total = 0;
- struct ring *outring;
- struct ring_entry *entry;
- struct hooks *hooks = port->ip_hooks;
-
- BUG_ON(!(len >= 0));
-
- prod_ptr = port->ip_tx_prod;
- cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
- outring = port->ip_outring;
-
- /* Maintain a 1-entry red-zone. The ring buffer is full when
- * (cons - prod) % ring_size is 1. Rather than do this subtraction
- * in the body of the loop, I'll do it now.
- */
- cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
-
- /* Stuff the bytes into the output */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- int xx;
-
- /* Get 4 bytes (one ring entry) at a time */
- entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
-
- /* Invalidate all entries */
- entry->ring_allsc = 0;
-
- /* Copy in some bytes */
- for (xx = 0; (xx < 4) && (len > 0); xx++) {
- entry->ring_data[xx] = *buf++;
- entry->ring_sc[xx] = IOC4_TXCB_VALID;
- len--;
- total++;
- }
-
- /* If we are within some small threshold of filling up the
- * entire ring buffer, we must place an EXPLICIT intr here
- * to generate a lowat interrupt in case we subsequently
- * really do fill up the ring and the caller goes to sleep.
- * No need to place more than one though.
- */
- if (!(port->ip_flags & LOWAT_WRITTEN) &&
- ((cons_ptr - prod_ptr) & PROD_CONS_MASK)
- <= port->ip_tx_lowat
- * (int)sizeof(struct ring_entry)) {
- port->ip_flags |= LOWAT_WRITTEN;
- entry->ring_sc[0] |= IOC4_TXCB_INT_WHEN_DONE;
- }
-
- /* Go on to next entry */
- prod_ptr += sizeof(struct ring_entry);
- prod_ptr &= PROD_CONS_MASK;
- }
-
- /* If we sent something, start DMA if necessary */
- if (total > 0 && !(port->ip_sscr & IOC4_SSCR_DMA_EN)) {
- port->ip_sscr |= IOC4_SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
-
- /* Store the new producer pointer. If tx is disabled, we stuff the
- * data into the ring buffer, but we don't actually start tx.
- */
- if (!uart_tx_stopped(port->ip_port)) {
- writel(prod_ptr, &port->ip_serial_regs->stpir);
-
- /* If we are now transmitting, enable tx_mt interrupt so we
- * can disable DMA if necessary when the tx finishes.
- */
- if (total > 0)
- enable_intrs(port, hooks->intr_tx_mt);
- }
- port->ip_tx_prod = prod_ptr;
- return total;
-}
-
-/**
- * disable_intrs - disable interrupts
- * @port: port to enable
- * @mask: mask to use
- */
-static void disable_intrs(struct ioc4_port *port, uint32_t mask)
-{
- struct hooks *hooks = port->ip_hooks;
-
- if (port->ip_ienb & mask) {
- write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IEC,
- IOC4_SIO_INTR_TYPE);
- port->ip_ienb &= ~mask;
- }
-
- if (!port->ip_ienb)
- write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
- IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
-}
-
-/**
- * set_notification - Modify event notification
- * @port: port to use
- * @mask: events mask
- * @set_on: set ?
- */
-static int set_notification(struct ioc4_port *port, int mask, int set_on)
-{
- struct hooks *hooks = port->ip_hooks;
- uint32_t intrbits, sscrbits;
-
- BUG_ON(!mask);
-
- intrbits = sscrbits = 0;
-
- if (mask & N_DATA_READY)
- intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
- if (mask & N_OUTPUT_LOWAT)
- intrbits |= hooks->intr_tx_explicit;
- if (mask & N_DDCD) {
- intrbits |= hooks->intr_delta_dcd;
- sscrbits |= IOC4_SSCR_RX_RING_DCD;
- }
- if (mask & N_DCTS)
- intrbits |= hooks->intr_delta_cts;
-
- if (set_on) {
- enable_intrs(port, intrbits);
- port->ip_notify |= mask;
- port->ip_sscr |= sscrbits;
- } else {
- disable_intrs(port, intrbits);
- port->ip_notify &= ~mask;
- port->ip_sscr &= ~sscrbits;
- }
-
- /* We require DMA if either DATA_READY or DDCD notification is
- * currently requested. If neither of these is requested and
- * there is currently no tx in progress, DMA may be disabled.
- */
- if (port->ip_notify & (N_DATA_READY | N_DDCD))
- port->ip_sscr |= IOC4_SSCR_DMA_EN;
- else if (!(port->ip_ienb & hooks->intr_tx_mt))
- port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
-
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- return 0;
-}
-
-/**
- * set_mcr - set the master control reg
- * @the_port: port to use
- * @mask1: mcr mask
- * @mask2: shadow mask
- */
-static inline int set_mcr(struct uart_port *the_port,
- int mask1, int mask2)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- uint32_t shadow;
- int spiniter = 0;
- char mcr;
-
- if (!port)
- return -1;
-
- /* Pause the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
- &port->ip_serial_regs->sscr);
- while ((readl(&port->ip_serial_regs->sscr)
- & IOC4_SSCR_PAUSE_STATE) == 0) {
- spiniter++;
- if (spiniter > MAXITER)
- return -1;
- }
- }
- shadow = readl(&port->ip_serial_regs->shadow);
- mcr = (shadow & 0xff000000) >> 24;
-
- /* Set new value */
- mcr |= mask1;
- shadow |= mask2;
-
- writeb(mcr, &port->ip_uart_regs->i4u_mcr);
- writel(shadow, &port->ip_serial_regs->shadow);
-
- /* Re-enable the DMA interface if necessary */
- if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- return 0;
-}
-
-/**
- * ioc4_set_proto - set the protocol for the port
- * @port: port to use
- * @proto: protocol to use
- */
-static int ioc4_set_proto(struct ioc4_port *port, int proto)
-{
- struct hooks *hooks = port->ip_hooks;
-
- switch (proto) {
- case PROTO_RS232:
- /* Clear the appropriate GIO pin */
- writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
- break;
-
- case PROTO_RS422:
- /* Set the appropriate GIO pin */
- writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
- break;
-
- default:
- return 1;
- }
- return 0;
-}
-
-/**
- * transmit_chars - upper level write, called with ip_lock
- * @the_port: port to write
- */
-static void transmit_chars(struct uart_port *the_port)
-{
- int xmit_count, tail, head;
- int result;
- char *start;
- struct tty_struct *tty;
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- struct uart_state *state;
-
- if (!the_port)
- return;
- if (!port)
- return;
-
- state = the_port->state;
- tty = state->port.tty;
-
- if (uart_circ_empty(&state->xmit) || uart_tx_stopped(the_port)) {
- /* Nothing to do or hw stopped */
- set_notification(port, N_ALL_OUTPUT, 0);
- return;
- }
-
- head = state->xmit.head;
- tail = state->xmit.tail;
- start = (char *)&state->xmit.buf[tail];
-
- /* write out all the data or until the end of the buffer */
- xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
- if (xmit_count > 0) {
- result = do_write(port, start, xmit_count);
- if (result > 0) {
- /* booking */
- xmit_count -= result;
- the_port->icount.tx += result;
- /* advance the pointers */
- tail += result;
- tail &= UART_XMIT_SIZE - 1;
- state->xmit.tail = tail;
- start = (char *)&state->xmit.buf[tail];
- }
- }
- if (uart_circ_chars_pending(&state->xmit) < WAKEUP_CHARS)
- uart_write_wakeup(the_port);
-
- if (uart_circ_empty(&state->xmit)) {
- set_notification(port, N_OUTPUT_LOWAT, 0);
- } else {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- }
-}
-
-/**
- * ioc4_change_speed - change the speed of the port
- * @the_port: port to change
- * @new_termios: new termios settings
- * @old_termios: old termios settings
- */
-static void
-ioc4_change_speed(struct uart_port *the_port,
- struct ktermios *new_termios, struct ktermios *old_termios)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- int baud, bits;
- unsigned cflag, iflag;
- int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
- struct uart_state *state = the_port->state;
-
- cflag = new_termios->c_cflag;
- iflag = new_termios->c_iflag;
-
- switch (cflag & CSIZE) {
- case CS5:
- new_data = 5;
- bits = 7;
- break;
- case CS6:
- new_data = 6;
- bits = 8;
- break;
- case CS7:
- new_data = 7;
- bits = 9;
- break;
- case CS8:
- new_data = 8;
- bits = 10;
- break;
- default:
- /* cuz we always need a default ... */
- new_data = 5;
- bits = 7;
- break;
- }
- if (cflag & CSTOPB) {
- bits++;
- new_stop = 1;
- }
- if (cflag & PARENB) {
- bits++;
- new_parity_enable = 1;
- if (cflag & PARODD)
- new_parity = 1;
- }
- baud = uart_get_baud_rate(the_port, new_termios, old_termios,
- MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
- DPRINT_CONFIG(("%s: returned baud %d\n", __func__, baud));
-
- /* default is 9600 */
- if (!baud)
- baud = 9600;
-
- if (!the_port->fifosize)
- the_port->fifosize = IOC4_FIFO_CHARS;
- the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10));
- the_port->timeout += HZ / 50; /* Add .02 seconds of slop */
-
- the_port->ignore_status_mask = N_ALL_INPUT;
-
- state->port.tty->low_latency = 1;
-
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~(N_PARITY_ERROR
- | N_FRAMING_ERROR);
- if (iflag & IGNBRK) {
- the_port->ignore_status_mask &= ~N_BREAK;
- if (iflag & IGNPAR)
- the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
- }
- if (!(cflag & CREAD)) {
- /* ignore everything */
- the_port->ignore_status_mask &= ~N_DATA_READY;
- }
-
- if (cflag & CRTSCTS) {
- port->ip_sscr |= IOC4_SSCR_HFC_EN;
- }
- else {
- port->ip_sscr &= ~IOC4_SSCR_HFC_EN;
- }
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-
- /* Set the configuration and proper notification call */
- DPRINT_CONFIG(("%s : port 0x%p cflag 0%o "
- "config_port(baud %d data %d stop %d p enable %d parity %d),"
- " notification 0x%x\n",
- __func__, (void *)port, cflag, baud, new_data, new_stop,
- new_parity_enable, new_parity, the_port->ignore_status_mask));
-
- if ((config_port(port, baud, /* baud */
- new_data, /* byte size */
- new_stop, /* stop bits */
- new_parity_enable, /* set parity */
- new_parity)) >= 0) { /* parity 1==odd */
- set_notification(port, the_port->ignore_status_mask, 1);
- }
-}
-
-/**
- * ic4_startup_local - Start up the serial port - returns >= 0 if no errors
- * @the_port: Port to operate on
- */
-static inline int ic4_startup_local(struct uart_port *the_port)
-{
- struct ioc4_port *port;
- struct uart_state *state;
-
- if (!the_port)
- return -1;
-
- port = get_ioc4_port(the_port, 0);
- if (!port)
- return -1;
-
- state = the_port->state;
-
- local_open(port);
-
- /* set the protocol - mapbase has the port type */
- ioc4_set_proto(port, the_port->mapbase);
-
- /* set the speed of the serial port */
- ioc4_change_speed(the_port, state->port.tty->termios,
- (struct ktermios *)0);
-
- return 0;
-}
-
-/*
- * ioc4_cb_output_lowat - called when the output low water mark is hit
- * @the_port: port to output
- */
-static void ioc4_cb_output_lowat(struct uart_port *the_port)
-{
- unsigned long pflags;
-
- /* ip_lock is set on the call here */
- if (the_port) {
- spin_lock_irqsave(&the_port->lock, pflags);
- transmit_chars(the_port);
- spin_unlock_irqrestore(&the_port->lock, pflags);
- }
-}
-
-/**
- * handle_intr - service any interrupts for the given port - 2nd level
- * called via sd_intr
- * @arg: handler arg
- * @sio_ir: ioc4regs
- */
-static void handle_intr(void *arg, uint32_t sio_ir)
-{
- struct ioc4_port *port = (struct ioc4_port *)arg;
- struct hooks *hooks = port->ip_hooks;
- unsigned int rx_high_rd_aborted = 0;
- unsigned long flags;
- struct uart_port *the_port;
- int loop_counter;
-
- /* Possible race condition here: The tx_mt interrupt bit may be
- * cleared without the intervention of the interrupt handler,
- * e.g. by a write. If the top level interrupt handler reads a
- * tx_mt, then some other processor does a write, starting up
- * output, then we come in here, see the tx_mt and stop DMA, the
- * output started by the other processor will hang. Thus we can
- * only rely on tx_mt being legitimate if it is read while the
- * port lock is held. Therefore this bit must be ignored in the
- * passed in interrupt mask which was read by the top level
- * interrupt handler since the port lock was not held at the time
- * it was read. We can only rely on this bit being accurate if it
- * is read while the port lock is held. So we'll clear it for now,
- * and reload it later once we have the port lock.
- */
- sio_ir &= ~(hooks->intr_tx_mt);
-
- spin_lock_irqsave(&port->ip_lock, flags);
-
- loop_counter = MAXITER; /* to avoid hangs */
-
- do {
- uint32_t shadow;
-
- if ( loop_counter-- <= 0 ) {
- printk(KERN_WARNING "IOC4 serial: "
- "possible hang condition/"
- "port stuck on interrupt.\n");
- break;
- }
-
- /* Handle a DCD change */
- if (sio_ir & hooks->intr_delta_dcd) {
- /* ACK the interrupt */
- writel(hooks->intr_delta_dcd,
- &port->ip_mem->sio_ir.raw);
-
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DDCD)
- && (shadow & IOC4_SHADOW_DCD)
- && (port->ip_port)) {
- the_port = port->ip_port;
- the_port->icount.dcd = 1;
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- } else if ((port->ip_notify & N_DDCD)
- && !(shadow & IOC4_SHADOW_DCD)) {
- /* Flag delta DCD/no DCD */
- port->ip_flags |= DCD_ON;
- }
- }
-
- /* Handle a CTS change */
- if (sio_ir & hooks->intr_delta_cts) {
- /* ACK the interrupt */
- writel(hooks->intr_delta_cts,
- &port->ip_mem->sio_ir.raw);
-
- shadow = readl(&port->ip_serial_regs->shadow);
-
- if ((port->ip_notify & N_DCTS)
- && (port->ip_port)) {
- the_port = port->ip_port;
- the_port->icount.cts =
- (shadow & IOC4_SHADOW_CTS) ? 1 : 0;
- wake_up_interruptible
- (&the_port->state->port.delta_msr_wait);
- }
- }
-
- /* rx timeout interrupt. Must be some data available. Put this
- * before the check for rx_high since servicing this condition
- * may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_rx_timer) {
- /* ACK the interrupt */
- writel(hooks->intr_rx_timer,
- &port->ip_mem->sio_ir.raw);
-
- if ((port->ip_notify & N_DATA_READY)
- && (port->ip_port)) {
- /* ip_lock is set on call here */
- receive_chars(port->ip_port);
- }
- }
-
- /* rx high interrupt. Must be after rx_timer. */
- else if (sio_ir & hooks->intr_rx_high) {
- /* Data available, notify upper layer */
- if ((port->ip_notify & N_DATA_READY)
- && port->ip_port) {
- /* ip_lock is set on call here */
- receive_chars(port->ip_port);
- }
-
- /* We can't ACK this interrupt. If receive_chars didn't
- * cause the condition to clear, we'll have to disable
- * the interrupt until the data is drained.
- * If the read was aborted, don't disable the interrupt
- * as this may cause us to hang indefinitely. An
- * aborted read generally means that this interrupt
- * hasn't been delivered to the cpu yet anyway, even
- * though we see it as asserted when we read the sio_ir.
- */
- if ((sio_ir = PENDING(port)) & hooks->intr_rx_high) {
- if ((port->ip_flags & READ_ABORTED) == 0) {
- port->ip_ienb &= ~hooks->intr_rx_high;
- port->ip_flags |= INPUT_HIGH;
- } else {
- rx_high_rd_aborted++;
- }
- }
- }
-
- /* We got a low water interrupt: notify upper layer to
- * send more data. Must come before tx_mt since servicing
- * this condition may cause that condition to clear.
- */
- if (sio_ir & hooks->intr_tx_explicit) {
- port->ip_flags &= ~LOWAT_WRITTEN;
-
- /* ACK the interrupt */
- writel(hooks->intr_tx_explicit,
- &port->ip_mem->sio_ir.raw);
-
- if (port->ip_notify & N_OUTPUT_LOWAT)
- ioc4_cb_output_lowat(port->ip_port);
- }
-
- /* Handle tx_mt. Must come after tx_explicit. */
- else if (sio_ir & hooks->intr_tx_mt) {
- /* If we are expecting a lowat notification
- * and we get to this point it probably means that for
- * some reason the tx_explicit didn't work as expected
- * (that can legitimately happen if the output buffer is
- * filled up in just the right way).
- * So send the notification now.
- */
- if (port->ip_notify & N_OUTPUT_LOWAT) {
- ioc4_cb_output_lowat(port->ip_port);
-
- /* We need to reload the sio_ir since the lowat
- * call may have caused another write to occur,
- * clearing the tx_mt condition.
- */
- sio_ir = PENDING(port);
- }
-
- /* If the tx_mt condition still persists even after the
- * lowat call, we've got some work to do.
- */
- if (sio_ir & hooks->intr_tx_mt) {
-
- /* If we are not currently expecting DMA input,
- * and the transmitter has just gone idle,
- * there is no longer any reason for DMA, so
- * disable it.
- */
- if (!(port->ip_notify
- & (N_DATA_READY | N_DDCD))) {
- BUG_ON(!(port->ip_sscr
- & IOC4_SSCR_DMA_EN));
- port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
- writel(port->ip_sscr,
- &port->ip_serial_regs->sscr);
- }
-
- /* Prevent infinite tx_mt interrupt */
- port->ip_ienb &= ~hooks->intr_tx_mt;
- }
- }
- sio_ir = PENDING(port);
-
- /* if the read was aborted and only hooks->intr_rx_high,
- * clear hooks->intr_rx_high, so we do not loop forever.
- */
-
- if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
- sio_ir &= ~hooks->intr_rx_high;
- }
- } while (sio_ir & hooks->intr_all);
-
- spin_unlock_irqrestore(&port->ip_lock, flags);
-
- /* Re-enable interrupts before returning from interrupt handler.
- * Getting interrupted here is okay. It'll just v() our semaphore, and
- * we'll come through the loop again.
- */
-
- write_ireg(port->ip_ioc4_soft, port->ip_ienb, IOC4_W_IES,
- IOC4_SIO_INTR_TYPE);
-}
-
-/*
- * ioc4_cb_post_ncs - called for some basic errors
- * @port: port to use
- * @ncs: event
- */
-static void ioc4_cb_post_ncs(struct uart_port *the_port, int ncs)
-{
- struct uart_icount *icount;
-
- icount = &the_port->icount;
-
- if (ncs & NCS_BREAK)
- icount->brk++;
- if (ncs & NCS_FRAMING)
- icount->frame++;
- if (ncs & NCS_OVERRUN)
- icount->overrun++;
- if (ncs & NCS_PARITY)
- icount->parity++;
-}
-
-/**
- * do_read - Read in bytes from the port. Return the number of bytes
- * actually read.
- * @the_port: port to use
- * @buf: place to put the stuff we read
- * @len: how big 'buf' is
- */
-
-static inline int do_read(struct uart_port *the_port, unsigned char *buf,
- int len)
-{
- int prod_ptr, cons_ptr, total;
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- struct ring *inring;
- struct ring_entry *entry;
- struct hooks *hooks = port->ip_hooks;
- int byte_num;
- char *sc;
- int loop_counter;
-
- BUG_ON(!(len >= 0));
- BUG_ON(!port);
-
- /* There is a nasty timing issue in the IOC4. When the rx_timer
- * expires or the rx_high condition arises, we take an interrupt.
- * At some point while servicing the interrupt, we read bytes from
- * the ring buffer and re-arm the rx_timer. However the rx_timer is
- * not started until the first byte is received *after* it is armed,
- * and any bytes pending in the rx construction buffers are not drained
- * to memory until either there are 4 bytes available or the rx_timer
- * expires. This leads to a potential situation where data is left
- * in the construction buffers forever - 1 to 3 bytes were received
- * after the interrupt was generated but before the rx_timer was
- * re-armed. At that point as long as no subsequent bytes are received
- * the timer will never be started and the bytes will remain in the
- * construction buffer forever. The solution is to execute a DRAIN
- * command after rearming the timer. This way any bytes received before
- * the DRAIN will be drained to memory, and any bytes received after
- * the DRAIN will start the TIMER and be drained when it expires.
- * Luckily, this only needs to be done when the DMA buffer is empty
- * since there is no requirement that this function return all
- * available data as long as it returns some.
- */
- /* Re-arm the timer */
- writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir);
-
- prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
- cons_ptr = port->ip_rx_cons;
-
- if (prod_ptr == cons_ptr) {
- int reset_dma = 0;
-
- /* Input buffer appears empty, do a flush. */
-
- /* DMA must be enabled for this to work. */
- if (!(port->ip_sscr & IOC4_SSCR_DMA_EN)) {
- port->ip_sscr |= IOC4_SSCR_DMA_EN;
- reset_dma = 1;
- }
-
- /* Potential race condition: we must reload the srpir after
- * issuing the drain command, otherwise we could think the rx
- * buffer is empty, then take a very long interrupt, and when
- * we come back it's full and we wait forever for the drain to
- * complete.
- */
- writel(port->ip_sscr | IOC4_SSCR_RX_DRAIN,
- &port->ip_serial_regs->sscr);
- prod_ptr = readl(&port->ip_serial_regs->srpir)
- & PROD_CONS_MASK;
-
- /* We must not wait for the DRAIN to complete unless there are
- * at least 8 bytes (2 ring entries) available to receive the
- * data otherwise the DRAIN will never complete and we'll
- * deadlock here.
- * In fact, to make things easier, I'll just ignore the flush if
- * there is any data at all now available.
- */
- if (prod_ptr == cons_ptr) {
- loop_counter = 0;
- while (readl(&port->ip_serial_regs->sscr) &
- IOC4_SSCR_RX_DRAIN) {
- loop_counter++;
- if (loop_counter > MAXITER)
- return -1;
- }
-
- /* SIGH. We have to reload the prod_ptr *again* since
- * the drain may have caused it to change
- */
- prod_ptr = readl(&port->ip_serial_regs->srpir)
- & PROD_CONS_MASK;
- }
- if (reset_dma) {
- port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
- writel(port->ip_sscr, &port->ip_serial_regs->sscr);
- }
- }
- inring = port->ip_inring;
- port->ip_flags &= ~READ_ABORTED;
-
- total = 0;
- loop_counter = 0xfffff; /* to avoid hangs */
-
- /* Grab bytes from the hardware */
- while ((prod_ptr != cons_ptr) && (len > 0)) {
- entry = (struct ring_entry *)((caddr_t)inring + cons_ptr);
-
- if ( loop_counter-- <= 0 ) {
- printk(KERN_WARNING "IOC4 serial: "
- "possible hang condition/"
- "port stuck on read.\n");
- break;
- }
-
- /* According to the producer pointer, this ring entry
- * must contain some data. But if the PIO happened faster
- * than the DMA, the data may not be available yet, so let's
- * wait until it arrives.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- /* Indicate the read is aborted so we don't disable
- * the interrupt thinking that the consumer is
- * congested.
- */
- port->ip_flags |= READ_ABORTED;
- len = 0;
- break;
- }
-
- /* Load the bytes/status out of the ring entry */
- for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
- sc = &(entry->ring_sc[byte_num]);
-
- /* Check for change in modem state or overrun */
- if ((*sc & IOC4_RXSB_MODEM_VALID)
- && (port->ip_notify & N_DDCD)) {
- /* Notify upper layer if DCD dropped */
-
- if ((port->ip_flags & DCD_ON)
- && !(*sc & IOC4_RXSB_DCD)) {
-
- /* If we have already copied some data,
- * return it. We'll pick up the carrier
- * drop on the next pass. That way we
- * don't throw away the data that has
- * already been copied back to
- * the caller's buffer.
- */
- if (total > 0) {
- len = 0;
- break;
- }
- port->ip_flags &= ~DCD_ON;
-
- /* Turn off this notification so the
- * carrier drop protocol won't see it
- * again when it does a read.
- */
- *sc &= ~IOC4_RXSB_MODEM_VALID;
-
- /* To keep things consistent, we need
- * to update the consumer pointer so
- * the next reader won't come in and
- * try to read the same ring entries
- * again. This must be done here before
- * the dcd change.
- */
-
- if ((entry->ring_allsc & RING_ANY_VALID)
- == 0) {
- cons_ptr += (int)sizeof
- (struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- writel(cons_ptr,
- &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* Notify upper layer of carrier drop */
- if ((port->ip_notify & N_DDCD)
- && port->ip_port) {
- the_port->icount.dcd = 0;
- wake_up_interruptible
- (&the_port->state->
- port.delta_msr_wait);
- }
-
- /* If we had any data to return, we
- * would have returned it above.
- */
- return 0;
- }
- }
- if (*sc & IOC4_RXSB_MODEM_VALID) {
- /* Notify that an input overrun occurred */
- if ((*sc & IOC4_RXSB_OVERRUN)
- && (port->ip_notify & N_OVERRUN_ERROR)) {
- ioc4_cb_post_ncs(the_port, NCS_OVERRUN);
- }
- /* Don't look at this byte again */
- *sc &= ~IOC4_RXSB_MODEM_VALID;
- }
-
- /* Check for valid data or RX errors */
- if ((*sc & IOC4_RXSB_DATA_VALID) &&
- ((*sc & (IOC4_RXSB_PAR_ERR
- | IOC4_RXSB_FRAME_ERR
- | IOC4_RXSB_BREAK))
- && (port->ip_notify & (N_PARITY_ERROR
- | N_FRAMING_ERROR
- | N_BREAK)))) {
- /* There is an error condition on the next byte.
- * If we have already transferred some bytes,
- * we'll stop here. Otherwise if this is the
- * first byte to be read, we'll just transfer
- * it alone after notifying the
- * upper layer of its status.
- */
- if (total > 0) {
- len = 0;
- break;
- } else {
- if ((*sc & IOC4_RXSB_PAR_ERR) &&
- (port->ip_notify & N_PARITY_ERROR)) {
- ioc4_cb_post_ncs(the_port,
- NCS_PARITY);
- }
- if ((*sc & IOC4_RXSB_FRAME_ERR) &&
- (port->ip_notify & N_FRAMING_ERROR)){
- ioc4_cb_post_ncs(the_port,
- NCS_FRAMING);
- }
- if ((*sc & IOC4_RXSB_BREAK)
- && (port->ip_notify & N_BREAK)) {
- ioc4_cb_post_ncs
- (the_port,
- NCS_BREAK);
- }
- len = 1;
- }
- }
- if (*sc & IOC4_RXSB_DATA_VALID) {
- *sc &= ~IOC4_RXSB_DATA_VALID;
- *buf = entry->ring_data[byte_num];
- buf++;
- len--;
- total++;
- }
- }
-
- /* If we used up this entry entirely, go on to the next one,
- * otherwise we must have run out of buffer space, so
- * leave the consumer pointer here for the next read in case
- * there are still unread bytes in this entry.
- */
- if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
- cons_ptr += (int)sizeof(struct ring_entry);
- cons_ptr &= PROD_CONS_MASK;
- }
- }
-
- /* Update consumer pointer and re-arm rx timer interrupt */
- writel(cons_ptr, &port->ip_serial_regs->srcir);
- port->ip_rx_cons = cons_ptr;
-
- /* If we have now dipped below the rx high water mark and we have
- * rx_high interrupt turned off, we can now turn it back on again.
- */
- if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
- & PROD_CONS_MASK) < ((port->ip_sscr &
- IOC4_SSCR_RX_THRESHOLD)
- << IOC4_PROD_CONS_PTR_OFF))) {
- port->ip_flags &= ~INPUT_HIGH;
- enable_intrs(port, hooks->intr_rx_high);
- }
- return total;
-}
-
-/**
- * receive_chars - upper level read. Called with ip_lock.
- * @the_port: port to read from
- */
-static void receive_chars(struct uart_port *the_port)
-{
- struct tty_struct *tty;
- unsigned char ch[IOC4_MAX_CHARS];
- int read_count, request_count = IOC4_MAX_CHARS;
- struct uart_icount *icount;
- struct uart_state *state = the_port->state;
- unsigned long pflags;
-
- /* Make sure all the pointers are "good" ones */
- if (!state)
- return;
- if (!state->port.tty)
- return;
-
- spin_lock_irqsave(&the_port->lock, pflags);
- tty = state->port.tty;
-
- request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS);
-
- if (request_count > 0) {
- icount = &the_port->icount;
- read_count = do_read(the_port, ch, request_count);
- if (read_count > 0) {
- tty_insert_flip_string(tty, ch, read_count);
- icount->rx += read_count;
- }
- }
-
- spin_unlock_irqrestore(&the_port->lock, pflags);
-
- tty_flip_buffer_push(tty);
-}
-
-/**
- * ic4_type - What type of console are we?
- * @port: Port to operate with (we ignore since we only have one port)
- *
- */
-static const char *ic4_type(struct uart_port *the_port)
-{
- if (the_port->mapbase == PROTO_RS232)
- return "SGI IOC4 Serial [rs232]";
- else
- return "SGI IOC4 Serial [rs422]";
-}
-
-/**
- * ic4_tx_empty - Is the transmitter empty?
- * @port: Port to operate on
- *
- */
-static unsigned int ic4_tx_empty(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- unsigned int ret = 0;
-
- if (port_is_active(port, the_port)) {
- if (readl(&port->ip_serial_regs->shadow) & IOC4_SHADOW_TEMT)
- ret = TIOCSER_TEMT;
- }
- return ret;
-}
-
-/**
- * ic4_stop_tx - stop the transmitter
- * @port: Port to operate on
- *
- */
-static void ic4_stop_tx(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
-
- if (port_is_active(port, the_port))
- set_notification(port, N_OUTPUT_LOWAT, 0);
-}
-
-/**
- * null_void_function -
- * @port: Port to operate on
- *
- */
-static void null_void_function(struct uart_port *the_port)
-{
-}
-
-/**
- * ic4_shutdown - shut down the port - free irq and disable
- * @port: Port to shut down
- *
- */
-static void ic4_shutdown(struct uart_port *the_port)
-{
- unsigned long port_flags;
- struct ioc4_port *port;
- struct uart_state *state;
-
- port = get_ioc4_port(the_port, 0);
- if (!port)
- return;
-
- state = the_port->state;
- port->ip_port = NULL;
-
- wake_up_interruptible(&state->port.delta_msr_wait);
-
- if (state->port.tty)
- set_bit(TTY_IO_ERROR, &state->port.tty->flags);
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- set_notification(port, N_ALL, 0);
- port->ip_flags = PORT_INACTIVE;
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic4_set_mctrl - set control lines (dtr, rts, etc)
- * @port: Port to operate on
- * @mctrl: Lines to set/unset
- *
- */
-static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
-{
- unsigned char mcr = 0;
- struct ioc4_port *port;
-
- port = get_ioc4_port(the_port, 0);
- if (!port_is_active(port, the_port))
- return;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- set_mcr(the_port, mcr, IOC4_SHADOW_DTR);
-}
-
-/**
- * ic4_get_mctrl - get control line info
- * @port: port to operate on
- *
- */
-static unsigned int ic4_get_mctrl(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
- uint32_t shadow;
- unsigned int ret = 0;
-
- if (!port_is_active(port, the_port))
- return 0;
-
- shadow = readl(&port->ip_serial_regs->shadow);
- if (shadow & IOC4_SHADOW_DCD)
- ret |= TIOCM_CAR;
- if (shadow & IOC4_SHADOW_DR)
- ret |= TIOCM_DSR;
- if (shadow & IOC4_SHADOW_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-/**
- * ic4_start_tx - Start transmitter, flush any output
- * @port: Port to operate on
- *
- */
-static void ic4_start_tx(struct uart_port *the_port)
-{
- struct ioc4_port *port = get_ioc4_port(the_port, 0);
-
- if (port_is_active(port, the_port)) {
- set_notification(port, N_OUTPUT_LOWAT, 1);
- enable_intrs(port, port->ip_hooks->intr_tx_mt);
- }
-}
-
-/**
- * ic4_break_ctl - handle breaks
- * @port: Port to operate on
- * @break_state: Break state
- *
- */
-static void ic4_break_ctl(struct uart_port *the_port, int break_state)
-{
-}
-
-/**
- * ic4_startup - Start up the serial port
- * @port: Port to operate on
- *
- */
-static int ic4_startup(struct uart_port *the_port)
-{
- int retval;
- struct ioc4_port *port;
- struct ioc4_control *control;
- struct uart_state *state;
- unsigned long port_flags;
-
- if (!the_port)
- return -ENODEV;
- port = get_ioc4_port(the_port, 1);
- if (!port)
- return -ENODEV;
- state = the_port->state;
-
- control = port->ip_control;
- if (!control) {
- port->ip_port = NULL;
- return -ENODEV;
- }
-
- /* Start up the serial port */
- spin_lock_irqsave(&the_port->lock, port_flags);
- retval = ic4_startup_local(the_port);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
- return retval;
-}
-
-/**
- * ic4_set_termios - set termios stuff
- * @port: port to operate on
- * @termios: New settings
- * @termios: Old
- *
- */
-static void
-ic4_set_termios(struct uart_port *the_port,
- struct ktermios *termios, struct ktermios *old_termios)
-{
- unsigned long port_flags;
-
- spin_lock_irqsave(&the_port->lock, port_flags);
- ioc4_change_speed(the_port, termios, old_termios);
- spin_unlock_irqrestore(&the_port->lock, port_flags);
-}
-
-/**
- * ic4_request_port - allocate resources for port - no op....
- * @port: port to operate on
- *
- */
-static int ic4_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/* Associate the uart functions above - given to serial core */
-
-static struct uart_ops ioc4_ops = {
- .tx_empty = ic4_tx_empty,
- .set_mctrl = ic4_set_mctrl,
- .get_mctrl = ic4_get_mctrl,
- .stop_tx = ic4_stop_tx,
- .start_tx = ic4_start_tx,
- .stop_rx = null_void_function,
- .enable_ms = null_void_function,
- .break_ctl = ic4_break_ctl,
- .startup = ic4_startup,
- .shutdown = ic4_shutdown,
- .set_termios = ic4_set_termios,
- .type = ic4_type,
- .release_port = null_void_function,
- .request_port = ic4_request_port,
-};
-
-/*
- * Boot-time initialization code
- */
-
-static struct uart_driver ioc4_uart_rs232 = {
- .owner = THIS_MODULE,
- .driver_name = "ioc4_serial_rs232",
- .dev_name = DEVICE_NAME_RS232,
- .major = DEVICE_MAJOR,
- .minor = DEVICE_MINOR_RS232,
- .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
-};
-
-static struct uart_driver ioc4_uart_rs422 = {
- .owner = THIS_MODULE,
- .driver_name = "ioc4_serial_rs422",
- .dev_name = DEVICE_NAME_RS422,
- .major = DEVICE_MAJOR,
- .minor = DEVICE_MINOR_RS422,
- .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
-};
-
-
-/**
- * ioc4_serial_remove_one - detach function
- *
- * @idd: IOC4 master module data for this IOC4
- */
-
-static int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
-{
- int port_num, port_type;
- struct ioc4_control *control;
- struct uart_port *the_port;
- struct ioc4_port *port;
- struct ioc4_soft *soft;
-
- /* If serial driver did not attach, don't try to detach */
- control = idd->idd_serial_data;
- if (!control)
- return 0;
-
- for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
- for (port_type = UART_PORT_MIN;
- port_type < UART_PORT_COUNT;
- port_type++) {
- the_port = &control->ic_port[port_num].icp_uart_port
- [port_type];
- if (the_port) {
- switch (port_type) {
- case UART_PORT_RS422:
- uart_remove_one_port(&ioc4_uart_rs422,
- the_port);
- break;
- default:
- case UART_PORT_RS232:
- uart_remove_one_port(&ioc4_uart_rs232,
- the_port);
- break;
- }
- }
- }
- port = control->ic_port[port_num].icp_port;
- /* we allocate in pairs */
- if (!(port_num & 1) && port) {
- pci_free_consistent(port->ip_pdev,
- TOTAL_RING_BUF_SIZE,
- port->ip_cpu_ringbuf,
- port->ip_dma_ringbuf);
- kfree(port);
- }
- }
- soft = control->ic_soft;
- if (soft) {
- free_irq(control->ic_irq, soft);
- if (soft->is_ioc4_serial_addr) {
- iounmap(soft->is_ioc4_serial_addr);
- release_mem_region((unsigned long)
- soft->is_ioc4_serial_addr,
- sizeof(struct ioc4_serial));
- }
- kfree(soft);
- }
- kfree(control);
- idd->idd_serial_data = NULL;
-
- return 0;
-}
-
-
-/**
- * ioc4_serial_core_attach_rs232 - register with serial core
- * This is done during pci probing
- * @pdev: handle for this card
- */
-static inline int
-ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
-{
- struct ioc4_port *port;
- struct uart_port *the_port;
- struct ioc4_driver_data *idd = pci_get_drvdata(pdev);
- struct ioc4_control *control = idd->idd_serial_data;
- int port_num;
- int port_type_idx;
- struct uart_driver *u_driver;
-
-
- DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
- __func__, pdev, (void *)control));
-
- if (!control)
- return -ENODEV;
-
- port_type_idx = (port_type == PROTO_RS232) ? UART_PORT_RS232
- : UART_PORT_RS422;
-
- u_driver = (port_type == PROTO_RS232) ? &ioc4_uart_rs232
- : &ioc4_uart_rs422;
-
- /* once around for each port on this card */
- for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
- the_port = &control->ic_port[port_num].icp_uart_port
- [port_type_idx];
- port = control->ic_port[port_num].icp_port;
- port->ip_all_ports[port_type_idx] = the_port;
-
- DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n",
- __func__, (void *)the_port,
- (void *)port,
- port_type == PROTO_RS232 ? "rs232" : "rs422"));
-
- /* membase, iobase and mapbase just need to be non-0 */
- the_port->membase = (unsigned char __iomem *)1;
- the_port->iobase = (pdev->bus->number << 16) | port_num;
- the_port->line = (Num_of_ioc4_cards << 2) | port_num;
- the_port->mapbase = port_type;
- the_port->type = PORT_16550A;
- the_port->fifosize = IOC4_FIFO_CHARS;
- the_port->ops = &ioc4_ops;
- the_port->irq = control->ic_irq;
- the_port->dev = &pdev->dev;
- spin_lock_init(&the_port->lock);
- if (uart_add_one_port(u_driver, the_port) < 0) {
- printk(KERN_WARNING
- "%s: unable to add port %d bus %d\n",
- __func__, the_port->line, pdev->bus->number);
- } else {
- DPRINT_CONFIG(
- ("IOC4 serial port %d irq = %d, bus %d\n",
- the_port->line, the_port->irq, pdev->bus->number));
- }
- }
- return 0;
-}
-
-/**
- * ioc4_serial_attach_one - register attach function
- * called per card found from IOC4 master module.
- * @idd: Master module data for this IOC4
- */
-int
-ioc4_serial_attach_one(struct ioc4_driver_data *idd)
-{
- unsigned long tmp_addr1;
- struct ioc4_serial __iomem *serial;
- struct ioc4_soft *soft;
- struct ioc4_control *control;
- int ret = 0;
-
-
- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, idd->idd_pdev,
- idd->idd_pci_id));
-
- /* PCI-RT does not bring out serial connections.
- * Do not attach to this particular IOC4.
- */
- if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
- return 0;
-
- /* request serial registers */
- tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
-
- if (!request_mem_region(tmp_addr1, sizeof(struct ioc4_serial),
- "sioc4_uart")) {
- printk(KERN_WARNING
- "ioc4 (%p): unable to get request region for "
- "uart space\n", (void *)idd->idd_pdev);
- ret = -ENODEV;
- goto out1;
- }
- serial = ioremap(tmp_addr1, sizeof(struct ioc4_serial));
- if (!serial) {
- printk(KERN_WARNING
- "ioc4 (%p) : unable to remap ioc4 serial register\n",
- (void *)idd->idd_pdev);
- ret = -ENODEV;
- goto out2;
- }
- DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
- __func__, (void *)idd->idd_misc_regs,
- (void *)serial));
-
- /* Get memory for the new card */
- control = kzalloc(sizeof(struct ioc4_control), GFP_KERNEL);
-
- if (!control) {
- printk(KERN_WARNING "ioc4_attach_one"
- ": unable to get memory for the IOC4\n");
- ret = -ENOMEM;
- goto out2;
- }
- idd->idd_serial_data = control;
-
- /* Allocate the soft structure */
- soft = kzalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
- if (!soft) {
- printk(KERN_WARNING
- "ioc4 (%p): unable to get memory for the soft struct\n",
- (void *)idd->idd_pdev);
- ret = -ENOMEM;
- goto out3;
- }
-
- spin_lock_init(&soft->is_ir_lock);
- soft->is_ioc4_misc_addr = idd->idd_misc_regs;
- soft->is_ioc4_serial_addr = serial;
-
- /* Init the IOC4 */
- writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT,
- &idd->idd_misc_regs->sio_cr.raw);
-
- /* Enable serial port mode select generic PIO pins as outputs */
- writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
- | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
- &idd->idd_misc_regs->gpcr_s.raw);
-
- /* Clear and disable all serial interrupts */
- write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
- writel(~0, &idd->idd_misc_regs->sio_ir.raw);
- write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC,
- IOC4_OTHER_INTR_TYPE);
- writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw);
- control->ic_soft = soft;
-
- /* Hook up interrupt handler */
- if (!request_irq(idd->idd_pdev->irq, ioc4_intr, IRQF_SHARED,
- "sgi-ioc4serial", soft)) {
- control->ic_irq = idd->idd_pdev->irq;
- } else {
- printk(KERN_WARNING
- "%s : request_irq fails for IRQ 0x%x\n ",
- __func__, idd->idd_pdev->irq);
- }
- ret = ioc4_attach_local(idd);
- if (ret)
- goto out4;
-
- /* register port with the serial core - 1 rs232, 1 rs422 */
-
- if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS232)))
- goto out4;
-
- if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS422)))
- goto out5;
-
- Num_of_ioc4_cards++;
-
- return ret;
-
- /* error exits that give back resources */
-out5:
- ioc4_serial_remove_one(idd);
-out4:
- kfree(soft);
-out3:
- kfree(control);
-out2:
- if (serial)
- iounmap(serial);
- release_mem_region(tmp_addr1, sizeof(struct ioc4_serial));
-out1:
-
- return ret;
-}
-
-
-static struct ioc4_submodule ioc4_serial_submodule = {
- .is_name = "IOC4_serial",
- .is_owner = THIS_MODULE,
- .is_probe = ioc4_serial_attach_one,
- .is_remove = ioc4_serial_remove_one,
-};
-
-/**
- * ioc4_serial_init - module init
- */
-static int __init ioc4_serial_init(void)
-{
- int ret;
-
- /* register with serial core */
- if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) {
- printk(KERN_WARNING
- "%s: Couldn't register rs232 IOC4 serial driver\n",
- __func__);
- goto out;
- }
- if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) {
- printk(KERN_WARNING
- "%s: Couldn't register rs422 IOC4 serial driver\n",
- __func__);
- goto out_uart_rs232;
- }
-
- /* register with IOC4 main module */
- ret = ioc4_register_submodule(&ioc4_serial_submodule);
- if (ret)
- goto out_uart_rs422;
- return 0;
-
-out_uart_rs422:
- uart_unregister_driver(&ioc4_uart_rs422);
-out_uart_rs232:
- uart_unregister_driver(&ioc4_uart_rs232);
-out:
- return ret;
-}
-
-static void __exit ioc4_serial_exit(void)
-{
- ioc4_unregister_submodule(&ioc4_serial_submodule);
- uart_unregister_driver(&ioc4_uart_rs232);
- uart_unregister_driver(&ioc4_uart_rs422);
-}
-
-late_initcall(ioc4_serial_init); /* Call only after tty init is done */
-module_exit(ioc4_serial_exit);
-
-MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
-MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
deleted file mode 100644
index ebff4a1d4bcc..000000000000
--- a/drivers/serial/ip22zilog.c
+++ /dev/null
@@ -1,1221 +0,0 @@
-/*
- * Driver for Zilog serial chips found on SGI workstations and
- * servers. This driver could actually be made more generic.
- *
- * This is based on the drivers/serial/sunzilog.c code as of 2.6.0-test7 and the
- * old drivers/sgi/char/sgiserial.c code which itself is based of the original
- * drivers/sbus/char/zs.c code. A lot of code has been simply moved over
- * directly from there but much has been rewritten. Credits therefore go out
- * to David S. Miller, Eddie C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell
- * for their work there.
- *
- * Copyright (C) 2002 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/circ_buf.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/sgialib.h>
-#include <asm/sgi/ioc.h>
-#include <asm/sgi/hpc3.h>
-#include <asm/sgi/ip22.h>
-
-#if defined(CONFIG_SERIAL_IP22_ZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#include "ip22zilog.h"
-
-/*
- * On IP22 we need to delay after register accesses but we do not need to
- * flush writes.
- */
-#define ZSDELAY() udelay(5)
-#define ZSDELAY_LONG() udelay(20)
-#define ZS_WSYNC(channel) do { } while (0)
-
-#define NUM_IP22ZILOG 1
-#define NUM_CHANNELS (NUM_IP22ZILOG * 2)
-
-#define ZS_CLOCK 3672000 /* Zilog input clock rate. */
-#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
-
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct uart_ip22zilog_port {
- struct uart_port port;
-
- /* IRQ servicing chain. */
- struct uart_ip22zilog_port *next;
-
- /* Current values of Zilog write registers. */
- unsigned char curregs[NUM_ZSREGS];
-
- unsigned int flags;
-#define IP22ZILOG_FLAG_IS_CONS 0x00000004
-#define IP22ZILOG_FLAG_IS_KGDB 0x00000008
-#define IP22ZILOG_FLAG_MODEM_STATUS 0x00000010
-#define IP22ZILOG_FLAG_IS_CHANNEL_A 0x00000020
-#define IP22ZILOG_FLAG_REGS_HELD 0x00000040
-#define IP22ZILOG_FLAG_TX_STOPPED 0x00000080
-#define IP22ZILOG_FLAG_TX_ACTIVE 0x00000100
-#define IP22ZILOG_FLAG_RESET_DONE 0x00000200
-
- unsigned int tty_break;
-
- unsigned char parity_mask;
- unsigned char prev_status;
-};
-
-#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->membase))
-#define UART_ZILOG(PORT) ((struct uart_ip22zilog_port *)(PORT))
-#define IP22ZILOG_GET_CURR_REG(PORT, REGNUM) \
- (UART_ZILOG(PORT)->curregs[REGNUM])
-#define IP22ZILOG_SET_CURR_REG(PORT, REGNUM, REGVAL) \
- ((UART_ZILOG(PORT)->curregs[REGNUM]) = (REGVAL))
-#define ZS_IS_CONS(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_CONS)
-#define ZS_IS_KGDB(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_KGDB)
-#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & IP22ZILOG_FLAG_MODEM_STATUS)
-#define ZS_IS_CHANNEL_A(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_CHANNEL_A)
-#define ZS_REGS_HELD(UP) ((UP)->flags & IP22ZILOG_FLAG_REGS_HELD)
-#define ZS_TX_STOPPED(UP) ((UP)->flags & IP22ZILOG_FLAG_TX_STOPPED)
-#define ZS_TX_ACTIVE(UP) ((UP)->flags & IP22ZILOG_FLAG_TX_ACTIVE)
-
-/* Reading and writing Zilog8530 registers. The delays are to make this
- * driver work on the IP22 which needs a settling delay after each chip
- * register access, other machines handle this in hardware via auxiliary
- * flip-flops which implement the settle time we do in software.
- *
- * The port lock must be held and local IRQs must be disabled
- * when {read,write}_zsreg is invoked.
- */
-static unsigned char read_zsreg(struct zilog_channel *channel,
- unsigned char reg)
-{
- unsigned char retval;
-
- writeb(reg, &channel->control);
- ZSDELAY();
- retval = readb(&channel->control);
- ZSDELAY();
-
- return retval;
-}
-
-static void write_zsreg(struct zilog_channel *channel,
- unsigned char reg, unsigned char value)
-{
- writeb(reg, &channel->control);
- ZSDELAY();
- writeb(value, &channel->control);
- ZSDELAY();
-}
-
-static void ip22zilog_clear_fifo(struct zilog_channel *channel)
-{
- int i;
-
- for (i = 0; i < 32; i++) {
- unsigned char regval;
-
- regval = readb(&channel->control);
- ZSDELAY();
- if (regval & Rx_CH_AV)
- break;
-
- regval = read_zsreg(channel, R1);
- readb(&channel->data);
- ZSDELAY();
-
- if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- writeb(ERR_RES, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
- }
- }
-}
-
-/* This function must only be called when the TX is not busy. The UART
- * port lock must be held and local interrupts disabled.
- */
-static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs)
-{
- int i;
-
- /* Let pending transmits finish. */
- for (i = 0; i < 1000; i++) {
- unsigned char stat = read_zsreg(channel, R1);
- if (stat & ALL_SNT)
- break;
- udelay(100);
- }
-
- writeb(ERR_RES, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- ip22zilog_clear_fifo(channel);
-
- /* Disable all interrupts. */
- write_zsreg(channel, R1,
- regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
-
- /* Set parity, sync config, stop bits, and clock divisor. */
- write_zsreg(channel, R4, regs[R4]);
-
- /* Set misc. TX/RX control bits. */
- write_zsreg(channel, R10, regs[R10]);
-
- /* Set TX/RX controls sans the enable bits. */
- write_zsreg(channel, R3, regs[R3] & ~RxENAB);
- write_zsreg(channel, R5, regs[R5] & ~TxENAB);
-
- /* Synchronous mode config. */
- write_zsreg(channel, R6, regs[R6]);
- write_zsreg(channel, R7, regs[R7]);
-
- /* Don't mess with the interrupt vector (R2, unused by us) and
- * master interrupt control (R9). We make sure this is setup
- * properly at probe time then never touch it again.
- */
-
- /* Disable baud generator. */
- write_zsreg(channel, R14, regs[R14] & ~BRENAB);
-
- /* Clock mode control. */
- write_zsreg(channel, R11, regs[R11]);
-
- /* Lower and upper byte of baud rate generator divisor. */
- write_zsreg(channel, R12, regs[R12]);
- write_zsreg(channel, R13, regs[R13]);
-
- /* Now rewrite R14, with BRENAB (if set). */
- write_zsreg(channel, R14, regs[R14]);
-
- /* External status interrupt control. */
- write_zsreg(channel, R15, regs[R15]);
-
- /* Reset external status interrupts. */
- write_zsreg(channel, R0, RES_EXT_INT);
- write_zsreg(channel, R0, RES_EXT_INT);
-
- /* Rewrite R3/R5, this time without enables masked. */
- write_zsreg(channel, R3, regs[R3]);
- write_zsreg(channel, R5, regs[R5]);
-
- /* Rewrite R1, this time without IRQ enabled masked. */
- write_zsreg(channel, R1, regs[R1]);
-}
-
-/* Reprogram the Zilog channel HW registers with the copies found in the
- * software state struct. If the transmitter is busy, we defer this update
- * until the next TX complete interrupt. Else, we do it right now.
- *
- * The UART port lock must be held and local interrupts disabled.
- */
-static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up,
- struct zilog_channel *channel)
-{
- if (!ZS_REGS_HELD(up)) {
- if (ZS_TX_ACTIVE(up)) {
- up->flags |= IP22ZILOG_FLAG_REGS_HELD;
- } else {
- __load_zsregs(channel, up->curregs);
- }
- }
-}
-
-#define Rx_BRK 0x0100 /* BREAK event software flag. */
-#define Rx_SYS 0x0200 /* SysRq event software flag. */
-
-static struct tty_struct *ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
- struct zilog_channel *channel)
-{
- struct tty_struct *tty;
- unsigned char ch, flag;
- unsigned int r1;
-
- tty = NULL;
- if (up->port.state != NULL &&
- up->port.state->port.tty != NULL)
- tty = up->port.state->port.tty;
-
- for (;;) {
- ch = readb(&channel->control);
- ZSDELAY();
- if (!(ch & Rx_CH_AV))
- break;
-
- r1 = read_zsreg(channel, R1);
- if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- writeb(ERR_RES, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
- }
-
- ch = readb(&channel->data);
- ZSDELAY();
-
- ch &= up->parity_mask;
-
- /* Handle the null char got when BREAK is removed. */
- if (!ch)
- r1 |= up->tty_break;
-
- /* A real serial line, record the character and status. */
- flag = TTY_NORMAL;
- up->port.icount.rx++;
- if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | Rx_SYS | Rx_BRK)) {
- up->tty_break = 0;
-
- if (r1 & (Rx_SYS | Rx_BRK)) {
- up->port.icount.brk++;
- if (r1 & Rx_SYS)
- continue;
- r1 &= ~(PAR_ERR | CRC_ERR);
- }
- else if (r1 & PAR_ERR)
- up->port.icount.parity++;
- else if (r1 & CRC_ERR)
- up->port.icount.frame++;
- if (r1 & Rx_OVR)
- up->port.icount.overrun++;
- r1 &= up->port.read_status_mask;
- if (r1 & Rx_BRK)
- flag = TTY_BREAK;
- else if (r1 & PAR_ERR)
- flag = TTY_PARITY;
- else if (r1 & CRC_ERR)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&up->port, ch))
- continue;
-
- if (tty)
- uart_insert_char(&up->port, r1, Rx_OVR, ch, flag);
- }
- return tty;
-}
-
-static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
- struct zilog_channel *channel)
-{
- unsigned char status;
-
- status = readb(&channel->control);
- ZSDELAY();
-
- writeb(RES_EXT_INT, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- if (up->curregs[R15] & BRKIE) {
- if ((status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) {
- if (uart_handle_break(&up->port))
- up->tty_break = Rx_SYS;
- else
- up->tty_break = Rx_BRK;
- }
- }
-
- if (ZS_WANTS_MODEM_STATUS(up)) {
- if (status & SYNC)
- up->port.icount.dsr++;
-
- /* The Zilog just gives us an interrupt when DCD/CTS/etc. change.
- * But it does not tell us which bit has changed, we have to keep
- * track of this ourselves.
- */
- if ((status ^ up->prev_status) ^ DCD)
- uart_handle_dcd_change(&up->port,
- (status & DCD));
- if ((status ^ up->prev_status) ^ CTS)
- uart_handle_cts_change(&up->port,
- (status & CTS));
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
- }
-
- up->prev_status = status;
-}
-
-static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up,
- struct zilog_channel *channel)
-{
- struct circ_buf *xmit;
-
- if (ZS_IS_CONS(up)) {
- unsigned char status = readb(&channel->control);
- ZSDELAY();
-
- /* TX still busy? Just wait for the next TX done interrupt.
- *
- * It can occur because of how we do serial console writes. It would
- * be nice to transmit console writes just like we normally would for
- * a TTY line. (ie. buffered and TX interrupt driven). That is not
- * easy because console writes cannot sleep. One solution might be
- * to poll on enough port->xmit space becomming free. -DaveM
- */
- if (!(status & Tx_BUF_EMP))
- return;
- }
-
- up->flags &= ~IP22ZILOG_FLAG_TX_ACTIVE;
-
- if (ZS_REGS_HELD(up)) {
- __load_zsregs(channel, up->curregs);
- up->flags &= ~IP22ZILOG_FLAG_REGS_HELD;
- }
-
- if (ZS_TX_STOPPED(up)) {
- up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED;
- goto ack_tx_int;
- }
-
- if (up->port.x_char) {
- up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
- writeb(up->port.x_char, &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
-
- if (up->port.state == NULL)
- goto ack_tx_int;
- xmit = &up->port.state->xmit;
- if (uart_circ_empty(xmit))
- goto ack_tx_int;
- if (uart_tx_stopped(&up->port))
- goto ack_tx_int;
-
- up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
- writeb(xmit->buf[xmit->tail], &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- return;
-
-ack_tx_int:
- writeb(RES_Tx_P, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-}
-
-static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
-{
- struct uart_ip22zilog_port *up = dev_id;
-
- while (up) {
- struct zilog_channel *channel
- = ZILOG_CHANNEL_FROM_PORT(&up->port);
- struct tty_struct *tty;
- unsigned char r3;
-
- spin_lock(&up->port.lock);
- r3 = read_zsreg(channel, R3);
-
- /* Channel A */
- tty = NULL;
- if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
- writeb(RES_H_IUS, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- if (r3 & CHARxIP)
- tty = ip22zilog_receive_chars(up, channel);
- if (r3 & CHAEXT)
- ip22zilog_status_handle(up, channel);
- if (r3 & CHATxIP)
- ip22zilog_transmit_chars(up, channel);
- }
- spin_unlock(&up->port.lock);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- /* Channel B */
- up = up->next;
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
-
- spin_lock(&up->port.lock);
- tty = NULL;
- if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
- writeb(RES_H_IUS, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- if (r3 & CHBRxIP)
- tty = ip22zilog_receive_chars(up, channel);
- if (r3 & CHBEXT)
- ip22zilog_status_handle(up, channel);
- if (r3 & CHBTxIP)
- ip22zilog_transmit_chars(up, channel);
- }
- spin_unlock(&up->port.lock);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- up = up->next;
- }
-
- return IRQ_HANDLED;
-}
-
-/* A convenient way to quickly get R0 status. The caller must _not_ hold the
- * port lock, it is acquired here.
- */
-static __inline__ unsigned char ip22zilog_read_channel_status(struct uart_port *port)
-{
- struct zilog_channel *channel;
- unsigned char status;
-
- channel = ZILOG_CHANNEL_FROM_PORT(port);
- status = readb(&channel->control);
- ZSDELAY();
-
- return status;
-}
-
-/* The port lock is not held. */
-static unsigned int ip22zilog_tx_empty(struct uart_port *port)
-{
- unsigned long flags;
- unsigned char status;
- unsigned int ret;
-
- spin_lock_irqsave(&port->lock, flags);
-
- status = ip22zilog_read_channel_status(port);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (status & Tx_BUF_EMP)
- ret = TIOCSER_TEMT;
- else
- ret = 0;
-
- return ret;
-}
-
-/* The port lock is held and interrupts are disabled. */
-static unsigned int ip22zilog_get_mctrl(struct uart_port *port)
-{
- unsigned char status;
- unsigned int ret;
-
- status = ip22zilog_read_channel_status(port);
-
- ret = 0;
- if (status & DCD)
- ret |= TIOCM_CAR;
- if (status & SYNC)
- ret |= TIOCM_DSR;
- if (status & CTS)
- ret |= TIOCM_CTS;
-
- return ret;
-}
-
-/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char set_bits, clear_bits;
-
- set_bits = clear_bits = 0;
-
- if (mctrl & TIOCM_RTS)
- set_bits |= RTS;
- else
- clear_bits |= RTS;
- if (mctrl & TIOCM_DTR)
- set_bits |= DTR;
- else
- clear_bits |= DTR;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- up->curregs[R5] |= set_bits;
- up->curregs[R5] &= ~clear_bits;
- write_zsreg(channel, R5, up->curregs[R5]);
-}
-
-/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_stop_tx(struct uart_port *port)
-{
- struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
-
- up->flags |= IP22ZILOG_FLAG_TX_STOPPED;
-}
-
-/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_start_tx(struct uart_port *port)
-{
- struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char status;
-
- up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
- up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED;
-
- status = readb(&channel->control);
- ZSDELAY();
-
- /* TX busy? Just wait for the TX done interrupt. */
- if (!(status & Tx_BUF_EMP))
- return;
-
- /* Send the first character to jump-start the TX done
- * IRQ sending engine.
- */
- if (port->x_char) {
- writeb(port->x_char, &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- port->icount.tx++;
- port->x_char = 0;
- } else {
- struct circ_buf *xmit = &port->state->xmit;
-
- writeb(xmit->buf[xmit->tail], &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
- }
-}
-
-/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_stop_rx(struct uart_port *port)
-{
- struct uart_ip22zilog_port *up = UART_ZILOG(port);
- struct zilog_channel *channel;
-
- if (ZS_IS_CONS(up))
- return;
-
- channel = ZILOG_CHANNEL_FROM_PORT(port);
-
- /* Disable all RX interrupts. */
- up->curregs[R1] &= ~RxINT_MASK;
- ip22zilog_maybe_update_regs(up, channel);
-}
-
-/* The port lock is held. */
-static void ip22zilog_enable_ms(struct uart_port *port)
-{
- struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char new_reg;
-
- new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
- if (new_reg != up->curregs[R15]) {
- up->curregs[R15] = new_reg;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- write_zsreg(channel, R15, up->curregs[R15]);
- }
-}
-
-/* The port lock is not held. */
-static void ip22zilog_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char set_bits, clear_bits, new_reg;
- unsigned long flags;
-
- set_bits = clear_bits = 0;
-
- if (break_state)
- set_bits |= SND_BRK;
- else
- clear_bits |= SND_BRK;
-
- spin_lock_irqsave(&port->lock, flags);
-
- new_reg = (up->curregs[R5] | set_bits) & ~clear_bits;
- if (new_reg != up->curregs[R5]) {
- up->curregs[R5] = new_reg;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- write_zsreg(channel, R5, up->curregs[R5]);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void __ip22zilog_reset(struct uart_ip22zilog_port *up)
-{
- struct zilog_channel *channel;
- int i;
-
- if (up->flags & IP22ZILOG_FLAG_RESET_DONE)
- return;
-
- /* Let pending transmits finish. */
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- for (i = 0; i < 1000; i++) {
- unsigned char stat = read_zsreg(channel, R1);
- if (stat & ALL_SNT)
- break;
- udelay(100);
- }
-
- if (!ZS_IS_CHANNEL_A(up)) {
- up++;
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- }
- write_zsreg(channel, R9, FHWRES);
- ZSDELAY_LONG();
- (void) read_zsreg(channel, R0);
-
- up->flags |= IP22ZILOG_FLAG_RESET_DONE;
- up->next->flags |= IP22ZILOG_FLAG_RESET_DONE;
-}
-
-static void __ip22zilog_startup(struct uart_ip22zilog_port *up)
-{
- struct zilog_channel *channel;
-
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
-
- __ip22zilog_reset(up);
-
- __load_zsregs(channel, up->curregs);
- /* set master interrupt enable */
- write_zsreg(channel, R9, up->curregs[R9]);
- up->prev_status = readb(&channel->control);
-
- /* Enable receiver and transmitter. */
- up->curregs[R3] |= RxENAB;
- up->curregs[R5] |= TxENAB;
-
- up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- ip22zilog_maybe_update_regs(up, channel);
-}
-
-static int ip22zilog_startup(struct uart_port *port)
-{
- struct uart_ip22zilog_port *up = UART_ZILOG(port);
- unsigned long flags;
-
- if (ZS_IS_CONS(up))
- return 0;
-
- spin_lock_irqsave(&port->lock, flags);
- __ip22zilog_startup(up);
- spin_unlock_irqrestore(&port->lock, flags);
- return 0;
-}
-
-/*
- * The test for ZS_IS_CONS is explained by the following e-mail:
- *****
- * From: Russell King <rmk@arm.linux.org.uk>
- * Date: Sun, 8 Dec 2002 10:18:38 +0000
- *
- * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote:
- * > I boot my 2.5 boxes using "console=ttyS0,9600" argument,
- * > and I noticed that something is not right with reference
- * > counting in this case. It seems that when the console
- * > is open by kernel initially, this is not accounted
- * > as an open, and uart_startup is not called.
- *
- * That is correct. We are unable to call uart_startup when the serial
- * console is initialised because it may need to allocate memory (as
- * request_irq does) and the memory allocators may not have been
- * initialised.
- *
- * 1. initialise the port into a state where it can send characters in the
- * console write method.
- *
- * 2. don't do the actual hardware shutdown in your shutdown() method (but
- * do the normal software shutdown - ie, free irqs etc)
- *****
- */
-static void ip22zilog_shutdown(struct uart_port *port)
-{
- struct uart_ip22zilog_port *up = UART_ZILOG(port);
- struct zilog_channel *channel;
- unsigned long flags;
-
- if (ZS_IS_CONS(up))
- return;
-
- spin_lock_irqsave(&port->lock, flags);
-
- channel = ZILOG_CHANNEL_FROM_PORT(port);
-
- /* Disable receiver and transmitter. */
- up->curregs[R3] &= ~RxENAB;
- up->curregs[R5] &= ~TxENAB;
-
- /* Disable all interrupts and BRK assertion. */
- up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
- up->curregs[R5] &= ~SND_BRK;
- ip22zilog_maybe_update_regs(up, channel);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/* Shared by TTY driver and serial console setup. The port lock is held
- * and local interrupts are disabled.
- */
-static void
-ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,
- unsigned int iflag, int brg)
-{
-
- up->curregs[R10] = NRZ;
- up->curregs[R11] = TCBR | RCBR;
-
- /* Program BAUD and clock source. */
- up->curregs[R4] &= ~XCLK_MASK;
- up->curregs[R4] |= X16CLK;
- up->curregs[R12] = brg & 0xff;
- up->curregs[R13] = (brg >> 8) & 0xff;
- up->curregs[R14] = BRENAB;
-
- /* Character size, stop bits, and parity. */
- up->curregs[3] &= ~RxN_MASK;
- up->curregs[5] &= ~TxN_MASK;
- switch (cflag & CSIZE) {
- case CS5:
- up->curregs[3] |= Rx5;
- up->curregs[5] |= Tx5;
- up->parity_mask = 0x1f;
- break;
- case CS6:
- up->curregs[3] |= Rx6;
- up->curregs[5] |= Tx6;
- up->parity_mask = 0x3f;
- break;
- case CS7:
- up->curregs[3] |= Rx7;
- up->curregs[5] |= Tx7;
- up->parity_mask = 0x7f;
- break;
- case CS8:
- default:
- up->curregs[3] |= Rx8;
- up->curregs[5] |= Tx8;
- up->parity_mask = 0xff;
- break;
- };
- up->curregs[4] &= ~0x0c;
- if (cflag & CSTOPB)
- up->curregs[4] |= SB2;
- else
- up->curregs[4] |= SB1;
- if (cflag & PARENB)
- up->curregs[4] |= PAR_ENAB;
- else
- up->curregs[4] &= ~PAR_ENAB;
- if (!(cflag & PARODD))
- up->curregs[4] |= PAR_EVEN;
- else
- up->curregs[4] &= ~PAR_EVEN;
-
- up->port.read_status_mask = Rx_OVR;
- if (iflag & INPCK)
- up->port.read_status_mask |= CRC_ERR | PAR_ERR;
- if (iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= BRK_ABRT;
-
- up->port.ignore_status_mask = 0;
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= CRC_ERR | PAR_ERR;
- if (iflag & IGNBRK) {
- up->port.ignore_status_mask |= BRK_ABRT;
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= Rx_OVR;
- }
-
- if ((cflag & CREAD) == 0)
- up->port.ignore_status_mask = 0xff;
-}
-
-/* The port lock is not held. */
-static void
-ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
- unsigned long flags;
- int baud, brg;
-
- baud = uart_get_baud_rate(port, termios, old, 1200, 76800);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
-
- ip22zilog_convert_to_zs(up, termios->c_cflag, termios->c_iflag, brg);
-
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->flags |= IP22ZILOG_FLAG_MODEM_STATUS;
- else
- up->flags &= ~IP22ZILOG_FLAG_MODEM_STATUS;
-
- ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static const char *ip22zilog_type(struct uart_port *port)
-{
- return "IP22-Zilog";
-}
-
-/* We do not request/release mappings of the registers here, this
- * happens at early serial probe time.
- */
-static void ip22zilog_release_port(struct uart_port *port)
-{
-}
-
-static int ip22zilog_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/* These do not need to do anything interesting either. */
-static void ip22zilog_config_port(struct uart_port *port, int flags)
-{
-}
-
-/* We do not support letting the user mess with the divisor, IRQ, etc. */
-static int ip22zilog_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-static struct uart_ops ip22zilog_pops = {
- .tx_empty = ip22zilog_tx_empty,
- .set_mctrl = ip22zilog_set_mctrl,
- .get_mctrl = ip22zilog_get_mctrl,
- .stop_tx = ip22zilog_stop_tx,
- .start_tx = ip22zilog_start_tx,
- .stop_rx = ip22zilog_stop_rx,
- .enable_ms = ip22zilog_enable_ms,
- .break_ctl = ip22zilog_break_ctl,
- .startup = ip22zilog_startup,
- .shutdown = ip22zilog_shutdown,
- .set_termios = ip22zilog_set_termios,
- .type = ip22zilog_type,
- .release_port = ip22zilog_release_port,
- .request_port = ip22zilog_request_port,
- .config_port = ip22zilog_config_port,
- .verify_port = ip22zilog_verify_port,
-};
-
-static struct uart_ip22zilog_port *ip22zilog_port_table;
-static struct zilog_layout **ip22zilog_chip_regs;
-
-static struct uart_ip22zilog_port *ip22zilog_irq_chain;
-static int zilog_irq = -1;
-
-static void * __init alloc_one_table(unsigned long size)
-{
- return kzalloc(size, GFP_KERNEL);
-}
-
-static void __init ip22zilog_alloc_tables(void)
-{
- ip22zilog_port_table = (struct uart_ip22zilog_port *)
- alloc_one_table(NUM_CHANNELS * sizeof(struct uart_ip22zilog_port));
- ip22zilog_chip_regs = (struct zilog_layout **)
- alloc_one_table(NUM_IP22ZILOG * sizeof(struct zilog_layout *));
-
- if (ip22zilog_port_table == NULL || ip22zilog_chip_regs == NULL) {
- panic("IP22-Zilog: Cannot allocate IP22-Zilog tables.");
- }
-}
-
-/* Get the address of the registers for IP22-Zilog instance CHIP. */
-static struct zilog_layout * __init get_zs(int chip)
-{
- unsigned long base;
-
- if (chip < 0 || chip >= NUM_IP22ZILOG) {
- panic("IP22-Zilog: Illegal chip number %d in get_zs.", chip);
- }
-
- /* Not probe-able, hard code it. */
- base = (unsigned long) &sgioc->uart;
-
- zilog_irq = SGI_SERIAL_IRQ;
- request_mem_region(base, 8, "IP22-Zilog");
-
- return (struct zilog_layout *) base;
-}
-
-#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
-
-#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE
-static void ip22zilog_put_char(struct uart_port *port, int ch)
-{
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
- int loops = ZS_PUT_CHAR_MAX_DELAY;
-
- /* This is a timed polling loop so do not switch the explicit
- * udelay with ZSDELAY as that is a NOP on some platforms. -DaveM
- */
- do {
- unsigned char val = readb(&channel->control);
- if (val & Tx_BUF_EMP) {
- ZSDELAY();
- break;
- }
- udelay(5);
- } while (--loops);
-
- writeb(ch, &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-}
-
-static void
-ip22zilog_console_write(struct console *con, const char *s, unsigned int count)
-{
- struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- uart_console_write(&up->port, s, count, ip22zilog_put_char);
- udelay(2);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int __init ip22zilog_console_setup(struct console *con, char *options)
-{
- struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
- unsigned long flags;
- int baud = 9600, bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- up->flags |= IP22ZILOG_FLAG_IS_CONS;
-
- printk(KERN_INFO "Console: ttyS%d (IP22-Zilog)\n", con->index);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->curregs[R15] |= BRKIE;
-
- __ip22zilog_startup(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- return uart_set_options(&up->port, con, baud, parity, bits, flow);
-}
-
-static struct uart_driver ip22zilog_reg;
-
-static struct console ip22zilog_console = {
- .name = "ttyS",
- .write = ip22zilog_console_write,
- .device = uart_console_device,
- .setup = ip22zilog_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &ip22zilog_reg,
-};
-#endif /* CONFIG_SERIAL_IP22_ZILOG_CONSOLE */
-
-static struct uart_driver ip22zilog_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = NUM_CHANNELS,
-#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE
- .cons = &ip22zilog_console,
-#endif
-};
-
-static void __init ip22zilog_prepare(void)
-{
- struct uart_ip22zilog_port *up;
- struct zilog_layout *rp;
- int channel, chip;
-
- /*
- * Temporary fix.
- */
- for (channel = 0; channel < NUM_CHANNELS; channel++)
- spin_lock_init(&ip22zilog_port_table[channel].port.lock);
-
- ip22zilog_irq_chain = &ip22zilog_port_table[NUM_CHANNELS - 1];
- up = &ip22zilog_port_table[0];
- for (channel = NUM_CHANNELS - 1 ; channel > 0; channel--)
- up[channel].next = &up[channel - 1];
- up[channel].next = NULL;
-
- for (chip = 0; chip < NUM_IP22ZILOG; chip++) {
- if (!ip22zilog_chip_regs[chip]) {
- ip22zilog_chip_regs[chip] = rp = get_zs(chip);
-
- up[(chip * 2) + 0].port.membase = (char *) &rp->channelB;
- up[(chip * 2) + 1].port.membase = (char *) &rp->channelA;
-
- /* In theory mapbase is the physical address ... */
- up[(chip * 2) + 0].port.mapbase =
- (unsigned long) ioremap((unsigned long) &rp->channelB, 8);
- up[(chip * 2) + 1].port.mapbase =
- (unsigned long) ioremap((unsigned long) &rp->channelA, 8);
- }
-
- /* Channel A */
- up[(chip * 2) + 0].port.iotype = UPIO_MEM;
- up[(chip * 2) + 0].port.irq = zilog_irq;
- up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
- up[(chip * 2) + 0].port.fifosize = 1;
- up[(chip * 2) + 0].port.ops = &ip22zilog_pops;
- up[(chip * 2) + 0].port.type = PORT_IP22ZILOG;
- up[(chip * 2) + 0].port.flags = 0;
- up[(chip * 2) + 0].port.line = (chip * 2) + 0;
- up[(chip * 2) + 0].flags = 0;
-
- /* Channel B */
- up[(chip * 2) + 1].port.iotype = UPIO_MEM;
- up[(chip * 2) + 1].port.irq = zilog_irq;
- up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
- up[(chip * 2) + 1].port.fifosize = 1;
- up[(chip * 2) + 1].port.ops = &ip22zilog_pops;
- up[(chip * 2) + 1].port.type = PORT_IP22ZILOG;
- up[(chip * 2) + 1].port.line = (chip * 2) + 1;
- up[(chip * 2) + 1].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A;
- }
-
- for (channel = 0; channel < NUM_CHANNELS; channel++) {
- struct uart_ip22zilog_port *up = &ip22zilog_port_table[channel];
- int brg;
-
- /* Normal serial TTY. */
- up->parity_mask = 0xff;
- up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
- up->curregs[R3] = RxENAB | Rx8;
- up->curregs[R5] = TxENAB | Tx8;
- up->curregs[R9] = NV | MIE;
- up->curregs[R10] = NRZ;
- up->curregs[R11] = TCBR | RCBR;
- brg = BPS_TO_BRG(9600, ZS_CLOCK / ZS_CLOCK_DIVISOR);
- up->curregs[R12] = (brg & 0xff);
- up->curregs[R13] = (brg >> 8) & 0xff;
- up->curregs[R14] = BRENAB;
- }
-}
-
-static int __init ip22zilog_ports_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: IP22 Zilog driver (%d chips).\n", NUM_IP22ZILOG);
-
- ip22zilog_prepare();
-
- if (request_irq(zilog_irq, ip22zilog_interrupt, 0,
- "IP22-Zilog", ip22zilog_irq_chain)) {
- panic("IP22-Zilog: Unable to register zs interrupt handler.\n");
- }
-
- ret = uart_register_driver(&ip22zilog_reg);
- if (ret == 0) {
- int i;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_ip22zilog_port *up = &ip22zilog_port_table[i];
-
- uart_add_one_port(&ip22zilog_reg, &up->port);
- }
- }
-
- return ret;
-}
-
-static int __init ip22zilog_init(void)
-{
- /* IP22 Zilog setup is hard coded, no probing to do. */
- ip22zilog_alloc_tables();
- ip22zilog_ports_init();
-
- return 0;
-}
-
-static void __exit ip22zilog_exit(void)
-{
- int i;
- struct uart_ip22zilog_port *up;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- up = &ip22zilog_port_table[i];
-
- uart_remove_one_port(&ip22zilog_reg, &up->port);
- }
-
- /* Free IO mem */
- up = &ip22zilog_port_table[0];
- for (i = 0; i < NUM_IP22ZILOG; i++) {
- if (up[(i * 2) + 0].port.mapbase) {
- iounmap((void*)up[(i * 2) + 0].port.mapbase);
- up[(i * 2) + 0].port.mapbase = 0;
- }
- if (up[(i * 2) + 1].port.mapbase) {
- iounmap((void*)up[(i * 2) + 1].port.mapbase);
- up[(i * 2) + 1].port.mapbase = 0;
- }
- }
-
- uart_unregister_driver(&ip22zilog_reg);
-}
-
-module_init(ip22zilog_init);
-module_exit(ip22zilog_exit);
-
-/* David wrote it but I'm to blame for the bugs ... */
-MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
-MODULE_DESCRIPTION("SGI Zilog serial port driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/ip22zilog.h b/drivers/serial/ip22zilog.h
deleted file mode 100644
index a59a9a8341d2..000000000000
--- a/drivers/serial/ip22zilog.h
+++ /dev/null
@@ -1,281 +0,0 @@
-#ifndef _IP22_ZILOG_H
-#define _IP22_ZILOG_H
-
-#include <asm/byteorder.h>
-
-struct zilog_channel {
-#ifdef __BIG_ENDIAN
- volatile unsigned char unused0[3];
- volatile unsigned char control;
- volatile unsigned char unused1[3];
- volatile unsigned char data;
-#else /* __LITTLE_ENDIAN */
- volatile unsigned char control;
- volatile unsigned char unused0[3];
- volatile unsigned char data;
- volatile unsigned char unused1[3];
-#endif
-};
-
-struct zilog_layout {
- struct zilog_channel channelB;
- struct zilog_channel channelA;
-};
-
-#define NUM_ZSREGS 16
-
-/* Conversion routines to/from brg time constants from/to bits
- * per second.
- */
-#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
-#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
-
-/* The Zilog register set */
-
-#define FLAG 0x7e
-
-/* Write Register 0 */
-#define R0 0 /* Register selects */
-#define R1 1
-#define R2 2
-#define R3 3
-#define R4 4
-#define R5 5
-#define R6 6
-#define R7 7
-#define R8 8
-#define R9 9
-#define R10 10
-#define R11 11
-#define R12 12
-#define R13 13
-#define R14 14
-#define R15 15
-
-#define NULLCODE 0 /* Null Code */
-#define POINT_HIGH 0x8 /* Select upper half of registers */
-#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
-#define SEND_ABORT 0x18 /* HDLC Abort */
-#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
-#define RES_Tx_P 0x28 /* Reset TxINT Pending */
-#define ERR_RES 0x30 /* Error Reset */
-#define RES_H_IUS 0x38 /* Reset highest IUS */
-
-#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
-#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
-#define RES_EOM_L 0xC0 /* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
-#define TxINT_ENAB 0x2 /* Tx Int Enable */
-#define PAR_SPEC 0x4 /* Parity is special condition */
-
-#define RxINT_DISAB 0 /* Rx Int Disable */
-#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
-#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
-#define INT_ERR_Rx 0x18 /* Int on error only */
-#define RxINT_MASK 0x18
-
-#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
-#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
-#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
-
-/* Write Register #2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define RxENAB 0x1 /* Rx Enable */
-#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
-#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
-#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
-#define ENT_HM 0x10 /* Enter Hunt Mode */
-#define AUTO_ENAB 0x20 /* Auto Enables */
-#define Rx5 0x0 /* Rx 5 Bits/Character */
-#define Rx7 0x40 /* Rx 7 Bits/Character */
-#define Rx6 0x80 /* Rx 6 Bits/Character */
-#define Rx8 0xc0 /* Rx 8 Bits/Character */
-#define RxN_MASK 0xc0
-
-/* Write Register 4 */
-
-#define PAR_ENAB 0x1 /* Parity Enable */
-#define PAR_EVEN 0x2 /* Parity Even/Odd* */
-
-#define SYNC_ENAB 0 /* Sync Modes Enable */
-#define SB1 0x4 /* 1 stop bit/char */
-#define SB15 0x8 /* 1.5 stop bits/char */
-#define SB2 0xc /* 2 stop bits/char */
-
-#define MONSYNC 0 /* 8 Bit Sync character */
-#define BISYNC 0x10 /* 16 bit sync character */
-#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
-#define EXTSYNC 0x30 /* External Sync Mode */
-
-#define X1CLK 0x0 /* x1 clock mode */
-#define X16CLK 0x40 /* x16 clock mode */
-#define X32CLK 0x80 /* x32 clock mode */
-#define X64CLK 0xC0 /* x64 clock mode */
-#define XCLK_MASK 0xC0
-
-/* Write Register 5 */
-
-#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
-#define RTS 0x2 /* RTS */
-#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
-#define TxENAB 0x8 /* Tx Enable */
-#define SND_BRK 0x10 /* Send Break */
-#define Tx5 0x0 /* Tx 5 bits (or less)/character */
-#define Tx7 0x20 /* Tx 7 bits/character */
-#define Tx6 0x40 /* Tx 6 bits/character */
-#define Tx8 0x60 /* Tx 8 bits/character */
-#define TxN_MASK 0x60
-#define DTR 0x80 /* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define VIS 1 /* Vector Includes Status */
-#define NV 2 /* No Vector */
-#define DLC 4 /* Disable Lower Chain */
-#define MIE 8 /* Master Interrupt Enable */
-#define STATHI 0x10 /* Status high */
-#define NORESET 0 /* No reset on write to R9 */
-#define CHRB 0x40 /* Reset channel B */
-#define CHRA 0x80 /* Reset channel A */
-#define FHWRES 0xc0 /* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define BIT6 1 /* 6 bit/8bit sync */
-#define LOOPMODE 2 /* SDLC Loop mode */
-#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
-#define MARKIDLE 8 /* Mark/flag on idle */
-#define GAOP 0x10 /* Go active on poll */
-#define NRZ 0 /* NRZ mode */
-#define NRZI 0x20 /* NRZI mode */
-#define FM1 0x40 /* FM1 (transition = 1) */
-#define FM0 0x60 /* FM0 (transition = 0) */
-#define CRCPS 0x80 /* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define TRxCXT 0 /* TRxC = Xtal output */
-#define TRxCTC 1 /* TRxC = Transmit clock */
-#define TRxCBR 2 /* TRxC = BR Generator Output */
-#define TRxCDP 3 /* TRxC = DPLL output */
-#define TRxCOI 4 /* TRxC O/I */
-#define TCRTxCP 0 /* Transmit clock = RTxC pin */
-#define TCTRxCP 8 /* Transmit clock = TRxC pin */
-#define TCBR 0x10 /* Transmit clock = BR Generator output */
-#define TCDPLL 0x18 /* Transmit clock = DPLL output */
-#define RCRTxCP 0 /* Receive clock = RTxC pin */
-#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
-#define RCBR 0x40 /* Receive clock = BR Generator output */
-#define RCDPLL 0x60 /* Receive clock = DPLL output */
-#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define BRENAB 1 /* Baud rate generator enable */
-#define BRSRC 2 /* Baud rate generator source */
-#define DTRREQ 4 /* DTR/Request function */
-#define AUTOECHO 8 /* Auto Echo */
-#define LOOPBAK 0x10 /* Local loopback */
-#define SEARCH 0x20 /* Enter search mode */
-#define RMC 0x40 /* Reset missing clock */
-#define DISDPLL 0x60 /* Disable DPLL */
-#define SSBR 0x80 /* Set DPLL source = BR generator */
-#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
-#define SFMM 0xc0 /* Set FM mode */
-#define SNRZI 0xe0 /* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define ZCIE 2 /* Zero count IE */
-#define DCDIE 8 /* DCD IE */
-#define SYNCIE 0x10 /* Sync/hunt IE */
-#define CTSIE 0x20 /* CTS IE */
-#define TxUIE 0x40 /* Tx Underrun/EOM IE */
-#define BRKIE 0x80 /* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define Rx_CH_AV 0x1 /* Rx Character Available */
-#define ZCOUNT 0x2 /* Zero count */
-#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
-#define DCD 0x8 /* DCD */
-#define SYNC 0x10 /* Sync/hunt */
-#define CTS 0x20 /* CTS */
-#define TxEOM 0x40 /* Tx underrun */
-#define BRK_ABRT 0x80 /* Break/Abort */
-
-/* Read Register 1 */
-#define ALL_SNT 0x1 /* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define RES3 0x8 /* 0/3 */
-#define RES4 0x4 /* 0/4 */
-#define RES5 0xc /* 0/5 */
-#define RES6 0x2 /* 0/6 */
-#define RES7 0xa /* 0/7 */
-#define RES8 0x6 /* 0/8 */
-#define RES18 0xe /* 1/8 */
-#define RES28 0x0 /* 2/8 */
-/* Special Rx Condition Interrupts */
-#define PAR_ERR 0x10 /* Parity error */
-#define Rx_OVR 0x20 /* Rx Overrun Error */
-#define CRC_ERR 0x40 /* CRC/Framing Error */
-#define END_FR 0x80 /* End of Frame (SDLC) */
-
-/* Read Register 2 (channel b only) - Interrupt vector */
-#define CHB_Tx_EMPTY 0x00
-#define CHB_EXT_STAT 0x02
-#define CHB_Rx_AVAIL 0x04
-#define CHB_SPECIAL 0x06
-#define CHA_Tx_EMPTY 0x08
-#define CHA_EXT_STAT 0x0a
-#define CHA_Rx_AVAIL 0x0c
-#define CHA_SPECIAL 0x0e
-#define STATUS_MASK 0x0e
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
-#define CHBTxIP 0x2 /* Channel B Tx IP */
-#define CHBRxIP 0x4 /* Channel B Rx IP */
-#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
-#define CHATxIP 0x10 /* Channel A Tx IP */
-#define CHARxIP 0x20 /* Channel A Rx IP */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10 (misc status bits) */
-#define ONLOOP 2 /* On loop */
-#define LOOPSEND 0x10 /* Loop sending */
-#define CLK2MIS 0x40 /* Two clocks missing */
-#define CLK1MIS 0x80 /* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
-
-/* Misc macros */
-#define ZS_CLEARERR(channel) do { writeb(ERR_RES, &channel->control); \
- udelay(5); } while(0)
-
-#define ZS_CLEARSTAT(channel) do { writeb(RES_EXT_INT, &channel->control); \
- udelay(5); } while(0)
-
-#define ZS_CLEARFIFO(channel) do { readb(&channel->data); \
- udelay(2); \
- readb(&channel->data); \
- udelay(2); \
- readb(&channel->data); \
- udelay(2); } while(0)
-
-#endif /* _IP22_ZILOG_H */
diff --git a/drivers/serial/jsm/Makefile b/drivers/serial/jsm/Makefile
deleted file mode 100644
index e46b6e0f8b18..000000000000
--- a/drivers/serial/jsm/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Jasmine adapter
-#
-
-obj-$(CONFIG_SERIAL_JSM) += jsm.o
-
-jsm-objs := jsm_driver.o jsm_neo.o jsm_tty.o
-
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
deleted file mode 100644
index 38a509c684cd..000000000000
--- a/drivers/serial/jsm/jsm.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/************************************************************************
- * Copyright 2003 Digi International (www.digi.com)
- *
- * Copyright (C) 2004 IBM Corporation. All rights reserved.
- *
- * 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * Contact Information:
- * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ibm.com>
- *
- ***********************************************************************/
-
-#ifndef __JSM_DRIVER_H
-#define __JSM_DRIVER_H
-
-#include <linux/kernel.h>
-#include <linux/types.h> /* To pick up the varions Linux types */
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/device.h>
-
-/*
- * Debugging levels can be set using debug insmod variable
- * They can also be compiled out completely.
- */
-enum {
- DBG_INIT = 0x01,
- DBG_BASIC = 0x02,
- DBG_CORE = 0x04,
- DBG_OPEN = 0x08,
- DBG_CLOSE = 0x10,
- DBG_READ = 0x20,
- DBG_WRITE = 0x40,
- DBG_IOCTL = 0x80,
- DBG_PROC = 0x100,
- DBG_PARAM = 0x200,
- DBG_PSCAN = 0x400,
- DBG_EVENT = 0x800,
- DBG_DRAIN = 0x1000,
- DBG_MSIGS = 0x2000,
- DBG_MGMT = 0x4000,
- DBG_INTR = 0x8000,
- DBG_CARR = 0x10000,
-};
-
-#define jsm_printk(nlevel, klevel, pdev, fmt, args...) \
- if ((DBG_##nlevel & jsm_debug)) \
- dev_printk(KERN_##klevel, pdev->dev, fmt, ## args)
-
-#define MAXLINES 256
-#define MAXPORTS 8
-#define MAX_STOPS_SENT 5
-
-/* Board type definitions */
-
-#define T_NEO 0000
-#define T_CLASSIC 0001
-#define T_PCIBUS 0400
-
-/* Board State Definitions */
-
-#define BD_RUNNING 0x0
-#define BD_REASON 0x7f
-#define BD_NOTFOUND 0x1
-#define BD_NOIOPORT 0x2
-#define BD_NOMEM 0x3
-#define BD_NOBIOS 0x4
-#define BD_NOFEP 0x5
-#define BD_FAILED 0x6
-#define BD_ALLOCATED 0x7
-#define BD_TRIBOOT 0x8
-#define BD_BADKME 0x80
-
-
-/* 4 extra for alignment play space */
-#define WRITEBUFLEN ((4096) + 4)
-#define MYFLIPLEN N_TTY_BUF_SIZE
-
-#define JSM_VERSION "jsm: 1.2-1-INKERNEL"
-#define JSM_PARTNUM "40002438_A-INKERNEL"
-
-struct jsm_board;
-struct jsm_channel;
-
-/************************************************************************
- * Per board operations structure *
- ************************************************************************/
-struct board_ops {
- irq_handler_t intr;
- void (*uart_init) (struct jsm_channel *ch);
- void (*uart_off) (struct jsm_channel *ch);
- void (*param) (struct jsm_channel *ch);
- void (*assert_modem_signals) (struct jsm_channel *ch);
- void (*flush_uart_write) (struct jsm_channel *ch);
- void (*flush_uart_read) (struct jsm_channel *ch);
- void (*disable_receiver) (struct jsm_channel *ch);
- void (*enable_receiver) (struct jsm_channel *ch);
- void (*send_break) (struct jsm_channel *ch);
- void (*clear_break) (struct jsm_channel *ch, int);
- void (*send_start_character) (struct jsm_channel *ch);
- void (*send_stop_character) (struct jsm_channel *ch);
- void (*copy_data_from_queue_to_uart) (struct jsm_channel *ch);
- u32 (*get_uart_bytes_left) (struct jsm_channel *ch);
- void (*send_immediate_char) (struct jsm_channel *ch, unsigned char);
-};
-
-
-/*
- * Per-board information
- */
-struct jsm_board
-{
- int boardnum; /* Board number: 0-32 */
-
- int type; /* Type of board */
- u8 rev; /* PCI revision ID */
- struct pci_dev *pci_dev;
- u32 maxports; /* MAX ports this board can handle */
-
- spinlock_t bd_intr_lock; /* Used to protect the poller tasklet and
- * the interrupt routine from each other.
- */
-
- u32 nasync; /* Number of ports on card */
-
- u32 irq; /* Interrupt request number */
-
- u64 membase; /* Start of base memory of the card */
- u64 membase_end; /* End of base memory of the card */
-
- u8 __iomem *re_map_membase;/* Remapped memory of the card */
-
- u64 iobase; /* Start of io base of the card */
- u64 iobase_end; /* End of io base of the card */
-
- u32 bd_uart_offset; /* Space between each UART */
-
- struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */
- char *flipbuf; /* Our flip buffer, alloced if board is found */
-
- u32 bd_dividend; /* Board/UARTs specific dividend */
-
- struct board_ops *bd_ops;
-
- struct list_head jsm_board_entry;
-};
-
-/************************************************************************
- * Device flag definitions for ch_flags.
- ************************************************************************/
-#define CH_PRON 0x0001 /* Printer on string */
-#define CH_STOP 0x0002 /* Output is stopped */
-#define CH_STOPI 0x0004 /* Input is stopped */
-#define CH_CD 0x0008 /* Carrier is present */
-#define CH_FCAR 0x0010 /* Carrier forced on */
-#define CH_HANGUP 0x0020 /* Hangup received */
-
-#define CH_RECEIVER_OFF 0x0040 /* Receiver is off */
-#define CH_OPENING 0x0080 /* Port in fragile open state */
-#define CH_CLOSING 0x0100 /* Port in fragile close state */
-#define CH_FIFO_ENABLED 0x0200 /* Port has FIFOs enabled */
-#define CH_TX_FIFO_EMPTY 0x0400 /* TX Fifo is completely empty */
-#define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */
-#define CH_BREAK_SENDING 0x1000 /* Break is being sent */
-#define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */
-#define CH_FLIPBUF_IN_USE 0x4000 /* Channel's flipbuf is in use */
-#define CH_BAUD0 0x08000 /* Used for checking B0 transitions */
-
-/* Our Read/Error/Write queue sizes */
-#define RQUEUEMASK 0x1FFF /* 8 K - 1 */
-#define EQUEUEMASK 0x1FFF /* 8 K - 1 */
-#define WQUEUEMASK 0x0FFF /* 4 K - 1 */
-#define RQUEUESIZE (RQUEUEMASK + 1)
-#define EQUEUESIZE RQUEUESIZE
-#define WQUEUESIZE (WQUEUEMASK + 1)
-
-
-/************************************************************************
- * Channel information structure.
- ************************************************************************/
-struct jsm_channel {
- struct uart_port uart_port;
- struct jsm_board *ch_bd; /* Board structure pointer */
-
- spinlock_t ch_lock; /* provide for serialization */
- wait_queue_head_t ch_flags_wait;
-
- u32 ch_portnum; /* Port number, 0 offset. */
- u32 ch_open_count; /* open count */
- u32 ch_flags; /* Channel flags */
-
- u64 ch_close_delay; /* How long we should drop RTS/DTR for */
-
- tcflag_t ch_c_iflag; /* channel iflags */
- tcflag_t ch_c_cflag; /* channel cflags */
- tcflag_t ch_c_oflag; /* channel oflags */
- tcflag_t ch_c_lflag; /* channel lflags */
- u8 ch_stopc; /* Stop character */
- u8 ch_startc; /* Start character */
-
- u8 ch_mostat; /* FEP output modem status */
- u8 ch_mistat; /* FEP input modem status */
-
- struct neo_uart_struct __iomem *ch_neo_uart; /* Pointer to the "mapped" UART struct */
- u8 ch_cached_lsr; /* Cached value of the LSR register */
-
- u8 *ch_rqueue; /* Our read queue buffer - malloc'ed */
- u16 ch_r_head; /* Head location of the read queue */
- u16 ch_r_tail; /* Tail location of the read queue */
-
- u8 *ch_equeue; /* Our error queue buffer - malloc'ed */
- u16 ch_e_head; /* Head location of the error queue */
- u16 ch_e_tail; /* Tail location of the error queue */
-
- u8 *ch_wqueue; /* Our write queue buffer - malloc'ed */
- u16 ch_w_head; /* Head location of the write queue */
- u16 ch_w_tail; /* Tail location of the write queue */
-
- u64 ch_rxcount; /* total of data received so far */
- u64 ch_txcount; /* total of data transmitted so far */
-
- u8 ch_r_tlevel; /* Receive Trigger level */
- u8 ch_t_tlevel; /* Transmit Trigger level */
-
- u8 ch_r_watermark; /* Receive Watermark */
-
-
- u32 ch_stops_sent; /* How many times I have sent a stop character
- * to try to stop the other guy sending.
- */
- u64 ch_err_parity; /* Count of parity errors on channel */
- u64 ch_err_frame; /* Count of framing errors on channel */
- u64 ch_err_break; /* Count of breaks on channel */
- u64 ch_err_overrun; /* Count of overruns on channel */
-
- u64 ch_xon_sends; /* Count of xons transmitted */
- u64 ch_xoff_sends; /* Count of xoffs transmitted */
-};
-
-
-/************************************************************************
- * Per channel/port NEO UART structure *
- ************************************************************************
- * Base Structure Entries Usage Meanings to Host *
- * *
- * W = read write R = read only *
- * U = Unused. *
- ************************************************************************/
-
-struct neo_uart_struct {
- u8 txrx; /* WR RHR/THR - Holding Reg */
- u8 ier; /* WR IER - Interrupt Enable Reg */
- u8 isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
- u8 lcr; /* WR LCR - Line Control Reg */
- u8 mcr; /* WR MCR - Modem Control Reg */
- u8 lsr; /* WR LSR - Line Status Reg */
- u8 msr; /* WR MSR - Modem Status Reg */
- u8 spr; /* WR SPR - Scratch Pad Reg */
- u8 fctr; /* WR FCTR - Feature Control Reg */
- u8 efr; /* WR EFR - Enhanced Function Reg */
- u8 tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */
- u8 rfifo; /* WR RXCNT/RXTRG - Recieve FIFO Reg */
- u8 xoffchar1; /* WR XOFF 1 - XOff Character 1 Reg */
- u8 xoffchar2; /* WR XOFF 2 - XOff Character 2 Reg */
- u8 xonchar1; /* WR XON 1 - Xon Character 1 Reg */
- u8 xonchar2; /* WR XON 2 - XOn Character 2 Reg */
-
- u8 reserved1[0x2ff - 0x200]; /* U Reserved by Exar */
- u8 txrxburst[64]; /* RW 64 bytes of RX/TX FIFO Data */
- u8 reserved2[0x37f - 0x340]; /* U Reserved by Exar */
- u8 rxburst_with_errors[64]; /* R 64 bytes of RX FIFO Data + LSR */
-};
-
-/* Where to read the extended interrupt register (32bits instead of 8bits) */
-#define UART_17158_POLL_ADDR_OFFSET 0x80
-
-/*
- * These are the redefinitions for the FCTR on the XR17C158, since
- * Exar made them different than their earlier design. (XR16C854)
- */
-
-/* These are only applicable when table D is selected */
-#define UART_17158_FCTR_RTS_NODELAY 0x00
-#define UART_17158_FCTR_RTS_4DELAY 0x01
-#define UART_17158_FCTR_RTS_6DELAY 0x02
-#define UART_17158_FCTR_RTS_8DELAY 0x03
-#define UART_17158_FCTR_RTS_12DELAY 0x12
-#define UART_17158_FCTR_RTS_16DELAY 0x05
-#define UART_17158_FCTR_RTS_20DELAY 0x13
-#define UART_17158_FCTR_RTS_24DELAY 0x06
-#define UART_17158_FCTR_RTS_28DELAY 0x14
-#define UART_17158_FCTR_RTS_32DELAY 0x07
-#define UART_17158_FCTR_RTS_36DELAY 0x16
-#define UART_17158_FCTR_RTS_40DELAY 0x08
-#define UART_17158_FCTR_RTS_44DELAY 0x09
-#define UART_17158_FCTR_RTS_48DELAY 0x10
-#define UART_17158_FCTR_RTS_52DELAY 0x11
-
-#define UART_17158_FCTR_RTS_IRDA 0x10
-#define UART_17158_FCTR_RS485 0x20
-#define UART_17158_FCTR_TRGA 0x00
-#define UART_17158_FCTR_TRGB 0x40
-#define UART_17158_FCTR_TRGC 0x80
-#define UART_17158_FCTR_TRGD 0xC0
-
-/* 17158 trigger table selects.. */
-#define UART_17158_FCTR_BIT6 0x40
-#define UART_17158_FCTR_BIT7 0x80
-
-/* 17158 TX/RX memmapped buffer offsets */
-#define UART_17158_RX_FIFOSIZE 64
-#define UART_17158_TX_FIFOSIZE 64
-
-/* 17158 Extended IIR's */
-#define UART_17158_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */
-#define UART_17158_IIR_XONXOFF 0x10 /* Received an XON/XOFF char */
-#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20 /* CTS/DSR or RTS/DTR state change */
-#define UART_17158_IIR_FIFO_ENABLED 0xC0 /* 16550 FIFOs are Enabled */
-
-/*
- * These are the extended interrupts that get sent
- * back to us from the UART's 32bit interrupt register
- */
-#define UART_17158_RX_LINE_STATUS 0x1 /* RX Ready */
-#define UART_17158_RXRDY_TIMEOUT 0x2 /* RX Ready Timeout */
-#define UART_17158_TXRDY 0x3 /* TX Ready */
-#define UART_17158_MSR 0x4 /* Modem State Change */
-#define UART_17158_TX_AND_FIFO_CLR 0x40 /* Transmitter Holding Reg Empty */
-#define UART_17158_RX_FIFO_DATA_ERROR 0x80 /* UART detected an RX FIFO Data error */
-
-/*
- * These are the EXTENDED definitions for the 17C158's Interrupt
- * Enable Register.
- */
-#define UART_17158_EFR_ECB 0x10 /* Enhanced control bit */
-#define UART_17158_EFR_IXON 0x2 /* Receiver compares Xon1/Xoff1 */
-#define UART_17158_EFR_IXOFF 0x8 /* Transmit Xon1/Xoff1 */
-#define UART_17158_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */
-#define UART_17158_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow COntrol Enable */
-
-#define UART_17158_XOFF_DETECT 0x1 /* Indicates whether chip saw an incoming XOFF char */
-#define UART_17158_XON_DETECT 0x2 /* Indicates whether chip saw an incoming XON char */
-
-#define UART_17158_IER_RSVD1 0x10 /* Reserved by Exar */
-#define UART_17158_IER_XOFF 0x20 /* Xoff Interrupt Enable */
-#define UART_17158_IER_RTSDTR 0x40 /* Output Interrupt Enable */
-#define UART_17158_IER_CTSDSR 0x80 /* Input Interrupt Enable */
-
-#define PCI_DEVICE_NEO_2DB9_PCI_NAME "Neo 2 - DB9 Universal PCI"
-#define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME "Neo 2 - DB9 Universal PCI - Powered Ring Indicator"
-#define PCI_DEVICE_NEO_2RJ45_PCI_NAME "Neo 2 - RJ45 Universal PCI"
-#define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME "Neo 2 - RJ45 Universal PCI - Powered Ring Indicator"
-#define PCIE_DEVICE_NEO_IBM_PCI_NAME "Neo 4 - PCI Express - IBM"
-
-/*
- * Our Global Variables.
- */
-extern struct uart_driver jsm_uart_driver;
-extern struct board_ops jsm_neo_ops;
-extern int jsm_debug;
-
-/*************************************************************************
- *
- * Prototypes for non-static functions used in more than one module
- *
- *************************************************************************/
-int jsm_tty_write(struct uart_port *port);
-int jsm_tty_init(struct jsm_board *);
-int jsm_uart_port_init(struct jsm_board *);
-int jsm_remove_uart_port(struct jsm_board *);
-void jsm_input(struct jsm_channel *ch);
-void jsm_check_queue_flow_control(struct jsm_channel *ch);
-
-#endif
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
deleted file mode 100644
index 18f548449c63..000000000000
--- a/drivers/serial/jsm/jsm_driver.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/************************************************************************
- * Copyright 2003 Digi International (www.digi.com)
- *
- * Copyright (C) 2004 IBM Corporation. All rights reserved.
- *
- * 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * Contact Information:
- * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ibm.com>
- *
- *
- ***********************************************************************/
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "jsm.h"
-
-MODULE_AUTHOR("Digi International, http://www.digi.com");
-MODULE_DESCRIPTION("Driver for the Digi International "
- "Neo PCI based product line");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("jsm");
-
-#define JSM_DRIVER_NAME "jsm"
-#define NR_PORTS 32
-#define JSM_MINOR_START 0
-
-struct uart_driver jsm_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = JSM_DRIVER_NAME,
- .dev_name = "ttyn",
- .major = 0,
- .minor = JSM_MINOR_START,
- .nr = NR_PORTS,
-};
-
-static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev,
- pci_channel_state_t state);
-static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev);
-static void jsm_io_resume(struct pci_dev *pdev);
-
-static struct pci_error_handlers jsm_err_handler = {
- .error_detected = jsm_io_error_detected,
- .slot_reset = jsm_io_slot_reset,
- .resume = jsm_io_resume,
-};
-
-int jsm_debug;
-module_param(jsm_debug, int, 0);
-MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
-
-static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- int rc = 0;
- struct jsm_board *brd;
- static int adapter_count = 0;
-
- rc = pci_enable_device(pdev);
- if (rc) {
- dev_err(&pdev->dev, "Device enable FAILED\n");
- goto out;
- }
-
- rc = pci_request_regions(pdev, "jsm");
- if (rc) {
- dev_err(&pdev->dev, "pci_request_region FAILED\n");
- goto out_disable_device;
- }
-
- brd = kzalloc(sizeof(struct jsm_board), GFP_KERNEL);
- if (!brd) {
- dev_err(&pdev->dev,
- "memory allocation for board structure failed\n");
- rc = -ENOMEM;
- goto out_release_regions;
- }
-
- /* store the info for the board we've found */
- brd->boardnum = adapter_count++;
- brd->pci_dev = pdev;
- if (pdev->device == PCIE_DEVICE_ID_NEO_4_IBM)
- brd->maxports = 4;
- else if (pdev->device == PCI_DEVICE_ID_DIGI_NEO_8)
- brd->maxports = 8;
- else
- brd->maxports = 2;
-
- spin_lock_init(&brd->bd_intr_lock);
-
- /* store which revision we have */
- brd->rev = pdev->revision;
-
- brd->irq = pdev->irq;
-
- jsm_printk(INIT, INFO, &brd->pci_dev,
- "jsm_found_board - NEO adapter\n");
-
- /* get the PCI Base Address Registers */
- brd->membase = pci_resource_start(pdev, 0);
- brd->membase_end = pci_resource_end(pdev, 0);
-
- if (brd->membase & 1)
- brd->membase &= ~3;
- else
- brd->membase &= ~15;
-
- /* Assign the board_ops struct */
- brd->bd_ops = &jsm_neo_ops;
-
- brd->bd_uart_offset = 0x200;
- brd->bd_dividend = 921600;
-
- brd->re_map_membase = ioremap(brd->membase, 0x1000);
- if (!brd->re_map_membase) {
- dev_err(&pdev->dev,
- "card has no PCI Memory resources, "
- "failing board.\n");
- rc = -ENOMEM;
- goto out_kfree_brd;
- }
-
- rc = request_irq(brd->irq, brd->bd_ops->intr,
- IRQF_SHARED, "JSM", brd);
- if (rc) {
- printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq);
- goto out_iounmap;
- }
-
- rc = jsm_tty_init(brd);
- if (rc < 0) {
- dev_err(&pdev->dev, "Can't init tty devices (%d)\n", rc);
- rc = -ENXIO;
- goto out_free_irq;
- }
-
- rc = jsm_uart_port_init(brd);
- if (rc < 0) {
- /* XXX: leaking all resources from jsm_tty_init here! */
- dev_err(&pdev->dev, "Can't init uart port (%d)\n", rc);
- rc = -ENXIO;
- goto out_free_irq;
- }
-
- /* Log the information about the board */
- dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n",
- adapter_count, brd->rev, brd->irq);
-
- /*
- * allocate flip buffer for board.
- *
- * Okay to malloc with GFP_KERNEL, we are not at interrupt
- * context, and there are no locks held.
- */
- brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
- if (!brd->flipbuf) {
- /* XXX: leaking all resources from jsm_tty_init and
- jsm_uart_port_init here! */
- dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
- rc = -ENOMEM;
- goto out_free_uart;
- }
-
- pci_set_drvdata(pdev, brd);
- pci_save_state(pdev);
-
- return 0;
- out_free_uart:
- jsm_remove_uart_port(brd);
- out_free_irq:
- jsm_remove_uart_port(brd);
- free_irq(brd->irq, brd);
- out_iounmap:
- iounmap(brd->re_map_membase);
- out_kfree_brd:
- kfree(brd);
- out_release_regions:
- pci_release_regions(pdev);
- out_disable_device:
- pci_disable_device(pdev);
- out:
- return rc;
-}
-
-static void __devexit jsm_remove_one(struct pci_dev *pdev)
-{
- struct jsm_board *brd = pci_get_drvdata(pdev);
- int i = 0;
-
- jsm_remove_uart_port(brd);
-
- free_irq(brd->irq, brd);
- iounmap(brd->re_map_membase);
-
- /* Free all allocated channels structs */
- for (i = 0; i < brd->maxports; i++) {
- if (brd->channels[i]) {
- kfree(brd->channels[i]->ch_rqueue);
- kfree(brd->channels[i]->ch_equeue);
- kfree(brd->channels[i]->ch_wqueue);
- kfree(brd->channels[i]);
- }
- }
-
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- kfree(brd->flipbuf);
- kfree(brd);
-}
-
-static struct pci_device_id jsm_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9), 0, 0, 0 },
- { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI), 0, 0, 1 },
- { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 },
- { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 },
- { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4_IBM), 0, 0, 4 },
- { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_NEO_8), 0, 0, 5 },
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
-
-static struct pci_driver jsm_driver = {
- .name = "jsm",
- .id_table = jsm_pci_tbl,
- .probe = jsm_probe_one,
- .remove = __devexit_p(jsm_remove_one),
- .err_handler = &jsm_err_handler,
-};
-
-static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev,
- pci_channel_state_t state)
-{
- struct jsm_board *brd = pci_get_drvdata(pdev);
-
- jsm_remove_uart_port(brd);
-
- return PCI_ERS_RESULT_NEED_RESET;
-}
-
-static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev)
-{
- int rc;
-
- rc = pci_enable_device(pdev);
-
- if (rc)
- return PCI_ERS_RESULT_DISCONNECT;
-
- pci_set_master(pdev);
-
- return PCI_ERS_RESULT_RECOVERED;
-}
-
-static void jsm_io_resume(struct pci_dev *pdev)
-{
- struct jsm_board *brd = pci_get_drvdata(pdev);
-
- pci_restore_state(pdev);
-
- jsm_uart_port_init(brd);
-}
-
-static int __init jsm_init_module(void)
-{
- int rc;
-
- rc = uart_register_driver(&jsm_uart_driver);
- if (!rc) {
- rc = pci_register_driver(&jsm_driver);
- if (rc)
- uart_unregister_driver(&jsm_uart_driver);
- }
- return rc;
-}
-
-static void __exit jsm_exit_module(void)
-{
- pci_unregister_driver(&jsm_driver);
- uart_unregister_driver(&jsm_uart_driver);
-}
-
-module_init(jsm_init_module);
-module_exit(jsm_exit_module);
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
deleted file mode 100644
index 7960d9633c15..000000000000
--- a/drivers/serial/jsm/jsm_neo.c
+++ /dev/null
@@ -1,1412 +0,0 @@
-/************************************************************************
- * Copyright 2003 Digi International (www.digi.com)
- *
- * Copyright (C) 2004 IBM Corporation. All rights reserved.
- *
- * 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * Contact Information:
- * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ibm.com>
- *
- ***********************************************************************/
-#include <linux/delay.h> /* For udelay */
-#include <linux/serial_reg.h> /* For the various UART offsets */
-#include <linux/tty.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-#include "jsm.h" /* Driver main header file */
-
-static u32 jsm_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
-
-/*
- * This function allows calls to ensure that all outstanding
- * PCI writes have been completed, by doing a PCI read against
- * a non-destructive, read-only location on the Neo card.
- *
- * In this case, we are reading the DVID (Read-only Device Identification)
- * value of the Neo card.
- */
-static inline void neo_pci_posting_flush(struct jsm_board *bd)
-{
- readb(bd->re_map_membase + 0x8D);
-}
-
-static void neo_set_cts_flow_control(struct jsm_channel *ch)
-{
- u8 ier, efr;
- ier = readb(&ch->ch_neo_uart->ier);
- efr = readb(&ch->ch_neo_uart->efr);
-
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
-
- /* Turn on auto CTS flow control */
- ier |= (UART_17158_IER_CTSDSR);
- efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
-
- /* Turn off auto Xon flow control */
- efr &= ~(UART_17158_EFR_IXON);
-
- /* Why? Becuz Exar's spec says we have to zero it out before setting it */
- writeb(0, &ch->ch_neo_uart->efr);
-
- /* Turn on UART enhanced bits */
- writeb(efr, &ch->ch_neo_uart->efr);
-
- /* Turn on table D, with 8 char hi/low watermarks */
- writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
-
- /* Feed the UART our trigger levels */
- writeb(8, &ch->ch_neo_uart->tfifo);
- ch->ch_t_tlevel = 8;
-
- writeb(ier, &ch->ch_neo_uart->ier);
-}
-
-static void neo_set_rts_flow_control(struct jsm_channel *ch)
-{
- u8 ier, efr;
- ier = readb(&ch->ch_neo_uart->ier);
- efr = readb(&ch->ch_neo_uart->efr);
-
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
-
- /* Turn on auto RTS flow control */
- ier |= (UART_17158_IER_RTSDTR);
- efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
-
- /* Turn off auto Xoff flow control */
- ier &= ~(UART_17158_IER_XOFF);
- efr &= ~(UART_17158_EFR_IXOFF);
-
- /* Why? Becuz Exar's spec says we have to zero it out before setting it */
- writeb(0, &ch->ch_neo_uart->efr);
-
- /* Turn on UART enhanced bits */
- writeb(efr, &ch->ch_neo_uart->efr);
-
- writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
- ch->ch_r_watermark = 4;
-
- writeb(56, &ch->ch_neo_uart->rfifo);
- ch->ch_r_tlevel = 56;
-
- writeb(ier, &ch->ch_neo_uart->ier);
-
- /*
- * From the Neo UART spec sheet:
- * The auto RTS/DTR function must be started by asserting
- * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
- * it is enabled.
- */
- ch->ch_mostat |= (UART_MCR_RTS);
-}
-
-
-static void neo_set_ixon_flow_control(struct jsm_channel *ch)
-{
- u8 ier, efr;
- ier = readb(&ch->ch_neo_uart->ier);
- efr = readb(&ch->ch_neo_uart->efr);
-
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
-
- /* Turn off auto CTS flow control */
- ier &= ~(UART_17158_IER_CTSDSR);
- efr &= ~(UART_17158_EFR_CTSDSR);
-
- /* Turn on auto Xon flow control */
- efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
-
- /* Why? Becuz Exar's spec says we have to zero it out before setting it */
- writeb(0, &ch->ch_neo_uart->efr);
-
- /* Turn on UART enhanced bits */
- writeb(efr, &ch->ch_neo_uart->efr);
-
- writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
- ch->ch_r_watermark = 4;
-
- writeb(32, &ch->ch_neo_uart->rfifo);
- ch->ch_r_tlevel = 32;
-
- /* Tell UART what start/stop chars it should be looking for */
- writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
- writeb(0, &ch->ch_neo_uart->xonchar2);
-
- writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
- writeb(0, &ch->ch_neo_uart->xoffchar2);
-
- writeb(ier, &ch->ch_neo_uart->ier);
-}
-
-static void neo_set_ixoff_flow_control(struct jsm_channel *ch)
-{
- u8 ier, efr;
- ier = readb(&ch->ch_neo_uart->ier);
- efr = readb(&ch->ch_neo_uart->efr);
-
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
-
- /* Turn off auto RTS flow control */
- ier &= ~(UART_17158_IER_RTSDTR);
- efr &= ~(UART_17158_EFR_RTSDTR);
-
- /* Turn on auto Xoff flow control */
- ier |= (UART_17158_IER_XOFF);
- efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
-
- /* Why? Becuz Exar's spec says we have to zero it out before setting it */
- writeb(0, &ch->ch_neo_uart->efr);
-
- /* Turn on UART enhanced bits */
- writeb(efr, &ch->ch_neo_uart->efr);
-
- /* Turn on table D, with 8 char hi/low watermarks */
- writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
-
- writeb(8, &ch->ch_neo_uart->tfifo);
- ch->ch_t_tlevel = 8;
-
- /* Tell UART what start/stop chars it should be looking for */
- writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
- writeb(0, &ch->ch_neo_uart->xonchar2);
-
- writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
- writeb(0, &ch->ch_neo_uart->xoffchar2);
-
- writeb(ier, &ch->ch_neo_uart->ier);
-}
-
-static void neo_set_no_input_flow_control(struct jsm_channel *ch)
-{
- u8 ier, efr;
- ier = readb(&ch->ch_neo_uart->ier);
- efr = readb(&ch->ch_neo_uart->efr);
-
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
-
- /* Turn off auto RTS flow control */
- ier &= ~(UART_17158_IER_RTSDTR);
- efr &= ~(UART_17158_EFR_RTSDTR);
-
- /* Turn off auto Xoff flow control */
- ier &= ~(UART_17158_IER_XOFF);
- if (ch->ch_c_iflag & IXON)
- efr &= ~(UART_17158_EFR_IXOFF);
- else
- efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
-
- /* Why? Becuz Exar's spec says we have to zero it out before setting it */
- writeb(0, &ch->ch_neo_uart->efr);
-
- /* Turn on UART enhanced bits */
- writeb(efr, &ch->ch_neo_uart->efr);
-
- /* Turn on table D, with 8 char hi/low watermarks */
- writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
-
- ch->ch_r_watermark = 0;
-
- writeb(16, &ch->ch_neo_uart->tfifo);
- ch->ch_t_tlevel = 16;
-
- writeb(16, &ch->ch_neo_uart->rfifo);
- ch->ch_r_tlevel = 16;
-
- writeb(ier, &ch->ch_neo_uart->ier);
-}
-
-static void neo_set_no_output_flow_control(struct jsm_channel *ch)
-{
- u8 ier, efr;
- ier = readb(&ch->ch_neo_uart->ier);
- efr = readb(&ch->ch_neo_uart->efr);
-
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
-
- /* Turn off auto CTS flow control */
- ier &= ~(UART_17158_IER_CTSDSR);
- efr &= ~(UART_17158_EFR_CTSDSR);
-
- /* Turn off auto Xon flow control */
- if (ch->ch_c_iflag & IXOFF)
- efr &= ~(UART_17158_EFR_IXON);
- else
- efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
-
- /* Why? Becuz Exar's spec says we have to zero it out before setting it */
- writeb(0, &ch->ch_neo_uart->efr);
-
- /* Turn on UART enhanced bits */
- writeb(efr, &ch->ch_neo_uart->efr);
-
- /* Turn on table D, with 8 char hi/low watermarks */
- writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
-
- ch->ch_r_watermark = 0;
-
- writeb(16, &ch->ch_neo_uart->tfifo);
- ch->ch_t_tlevel = 16;
-
- writeb(16, &ch->ch_neo_uart->rfifo);
- ch->ch_r_tlevel = 16;
-
- writeb(ier, &ch->ch_neo_uart->ier);
-}
-
-static inline void neo_set_new_start_stop_chars(struct jsm_channel *ch)
-{
-
- /* if hardware flow control is set, then skip this whole thing */
- if (ch->ch_c_cflag & CRTSCTS)
- return;
-
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "start\n");
-
- /* Tell UART what start/stop chars it should be looking for */
- writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
- writeb(0, &ch->ch_neo_uart->xonchar2);
-
- writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
- writeb(0, &ch->ch_neo_uart->xoffchar2);
-}
-
-static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
-{
- int qleft = 0;
- u8 linestatus = 0;
- u8 error_mask = 0;
- int n = 0;
- int total = 0;
- u16 head;
- u16 tail;
-
- if (!ch)
- return;
-
- /* cache head and tail of queue */
- head = ch->ch_r_head & RQUEUEMASK;
- tail = ch->ch_r_tail & RQUEUEMASK;
-
- /* Get our cached LSR */
- linestatus = ch->ch_cached_lsr;
- ch->ch_cached_lsr = 0;
-
- /* Store how much space we have left in the queue */
- if ((qleft = tail - head - 1) < 0)
- qleft += RQUEUEMASK + 1;
-
- /*
- * If the UART is not in FIFO mode, force the FIFO copy to
- * NOT be run, by setting total to 0.
- *
- * On the other hand, if the UART IS in FIFO mode, then ask
- * the UART to give us an approximation of data it has RX'ed.
- */
- if (!(ch->ch_flags & CH_FIFO_ENABLED))
- total = 0;
- else {
- total = readb(&ch->ch_neo_uart->rfifo);
-
- /*
- * EXAR chip bug - RX FIFO COUNT - Fudge factor.
- *
- * This resolves a problem/bug with the Exar chip that sometimes
- * returns a bogus value in the rfifo register.
- * The count can be any where from 0-3 bytes "off".
- * Bizarre, but true.
- */
- total -= 3;
- }
-
- /*
- * Finally, bound the copy to make sure we don't overflow
- * our own queue...
- * The byte by byte copy loop below this loop this will
- * deal with the queue overflow possibility.
- */
- total = min(total, qleft);
-
- while (total > 0) {
- /*
- * Grab the linestatus register, we need to check
- * to see if there are any errors in the FIFO.
- */
- linestatus = readb(&ch->ch_neo_uart->lsr);
-
- /*
- * Break out if there is a FIFO error somewhere.
- * This will allow us to go byte by byte down below,
- * finding the exact location of the error.
- */
- if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
- break;
-
- /* Make sure we don't go over the end of our queue */
- n = min(((u32) total), (RQUEUESIZE - (u32) head));
-
- /*
- * Cut down n even further if needed, this is to fix
- * a problem with memcpy_fromio() with the Neo on the
- * IBM pSeries platform.
- * 15 bytes max appears to be the magic number.
- */
- n = min((u32) n, (u32) 12);
-
- /*
- * Since we are grabbing the linestatus register, which
- * will reset some bits after our read, we need to ensure
- * we don't miss our TX FIFO emptys.
- */
- if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR))
- ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-
- linestatus = 0;
-
- /* Copy data from uart to the queue */
- memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n);
- /*
- * Since RX_FIFO_DATA_ERROR was 0, we are guarenteed
- * that all the data currently in the FIFO is free of
- * breaks and parity/frame/orun errors.
- */
- memset(ch->ch_equeue + head, 0, n);
-
- /* Add to and flip head if needed */
- head = (head + n) & RQUEUEMASK;
- total -= n;
- qleft -= n;
- ch->ch_rxcount += n;
- }
-
- /*
- * Create a mask to determine whether we should
- * insert the character (if any) into our queue.
- */
- if (ch->ch_c_iflag & IGNBRK)
- error_mask |= UART_LSR_BI;
-
- /*
- * Now cleanup any leftover bytes still in the UART.
- * Also deal with any possible queue overflow here as well.
- */
- while (1) {
-
- /*
- * Its possible we have a linestatus from the loop above
- * this, so we "OR" on any extra bits.
- */
- linestatus |= readb(&ch->ch_neo_uart->lsr);
-
- /*
- * If the chip tells us there is no more data pending to
- * be read, we can then leave.
- * But before we do, cache the linestatus, just in case.
- */
- if (!(linestatus & UART_LSR_DR)) {
- ch->ch_cached_lsr = linestatus;
- break;
- }
-
- /* No need to store this bit */
- linestatus &= ~UART_LSR_DR;
-
- /*
- * Since we are grabbing the linestatus register, which
- * will reset some bits after our read, we need to ensure
- * we don't miss our TX FIFO emptys.
- */
- if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
- linestatus &= ~(UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR);
- ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
- }
-
- /*
- * Discard character if we are ignoring the error mask.
- */
- if (linestatus & error_mask) {
- u8 discard;
- linestatus = 0;
- memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1);
- continue;
- }
-
- /*
- * If our queue is full, we have no choice but to drop some data.
- * The assumption is that HWFLOW or SWFLOW should have stopped
- * things way way before we got to this point.
- *
- * I decided that I wanted to ditch the oldest data first,
- * I hope thats okay with everyone? Yes? Good.
- */
- while (qleft < 1) {
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Queue full, dropping DATA:%x LSR:%x\n",
- ch->ch_rqueue[tail], ch->ch_equeue[tail]);
-
- ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK;
- ch->ch_err_overrun++;
- qleft++;
- }
-
- memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
- ch->ch_equeue[head] = (u8) linestatus;
-
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]);
-
- /* Ditch any remaining linestatus value. */
- linestatus = 0;
-
- /* Add to and flip head if needed */
- head = (head + 1) & RQUEUEMASK;
-
- qleft--;
- ch->ch_rxcount++;
- }
-
- /*
- * Write new final heads to channel structure.
- */
- ch->ch_r_head = head & RQUEUEMASK;
- ch->ch_e_head = head & EQUEUEMASK;
- jsm_input(ch);
-}
-
-static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
-{
- u16 head;
- u16 tail;
- int n;
- int s;
- int qlen;
- u32 len_written = 0;
-
- if (!ch)
- return;
-
- /* No data to write to the UART */
- if (ch->ch_w_tail == ch->ch_w_head)
- return;
-
- /* If port is "stopped", don't send any data to the UART */
- if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))
- return;
- /*
- * If FIFOs are disabled. Send data directly to txrx register
- */
- if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
- u8 lsrbits = readb(&ch->ch_neo_uart->lsr);
-
- ch->ch_cached_lsr |= lsrbits;
- if (ch->ch_cached_lsr & UART_LSR_THRE) {
- ch->ch_cached_lsr &= ~(UART_LSR_THRE);
-
- writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx);
- jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
- "Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]);
- ch->ch_w_tail++;
- ch->ch_w_tail &= WQUEUEMASK;
- ch->ch_txcount++;
- }
- return;
- }
-
- /*
- * We have to do it this way, because of the EXAR TXFIFO count bug.
- */
- if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
- return;
-
- n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
-
- /* cache head and tail of queue */
- head = ch->ch_w_head & WQUEUEMASK;
- tail = ch->ch_w_tail & WQUEUEMASK;
- qlen = (head - tail) & WQUEUEMASK;
-
- /* Find minimum of the FIFO space, versus queue length */
- n = min(n, qlen);
-
- while (n > 0) {
-
- s = ((head >= tail) ? head : WQUEUESIZE) - tail;
- s = min(s, n);
-
- if (s <= 0)
- break;
-
- memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
- /* Add and flip queue if needed */
- tail = (tail + s) & WQUEUEMASK;
- n -= s;
- ch->ch_txcount += s;
- len_written += s;
- }
-
- /* Update the final tail */
- ch->ch_w_tail = tail & WQUEUEMASK;
-
- if (len_written >= ch->ch_t_tlevel)
- ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-
- if (!jsm_tty_write(&ch->uart_port))
- uart_write_wakeup(&ch->uart_port);
-}
-
-static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
-{
- u8 msignals = signals;
-
- jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
- "neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
-
- /* Scrub off lower bits. They signify delta's, which I don't care about */
- /* Keep DDCD and DDSR though */
- msignals &= 0xf8;
-
- if (msignals & UART_MSR_DDCD)
- uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_DCD);
- if (msignals & UART_MSR_DDSR)
- uart_handle_cts_change(&ch->uart_port, msignals & UART_MSR_CTS);
- if (msignals & UART_MSR_DCD)
- ch->ch_mistat |= UART_MSR_DCD;
- else
- ch->ch_mistat &= ~UART_MSR_DCD;
-
- if (msignals & UART_MSR_DSR)
- ch->ch_mistat |= UART_MSR_DSR;
- else
- ch->ch_mistat &= ~UART_MSR_DSR;
-
- if (msignals & UART_MSR_RI)
- ch->ch_mistat |= UART_MSR_RI;
- else
- ch->ch_mistat &= ~UART_MSR_RI;
-
- if (msignals & UART_MSR_CTS)
- ch->ch_mistat |= UART_MSR_CTS;
- else
- ch->ch_mistat &= ~UART_MSR_CTS;
-
- jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
- "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
- ch->ch_portnum,
- !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
- !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
- !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),
- !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),
- !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
- !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD));
-}
-
-/* Make the UART raise any of the output signals we want up */
-static void neo_assert_modem_signals(struct jsm_channel *ch)
-{
- if (!ch)
- return;
-
- writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
-}
-
-/*
- * Flush the WRITE FIFO on the Neo.
- *
- * NOTE: Channel lock MUST be held before calling this function!
- */
-static void neo_flush_uart_write(struct jsm_channel *ch)
-{
- u8 tmp = 0;
- int i = 0;
-
- if (!ch)
- return;
-
- writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
-
- for (i = 0; i < 10; i++) {
-
- /* Check to see if the UART feels it completely flushed the FIFO. */
- tmp = readb(&ch->ch_neo_uart->isr_fcr);
- if (tmp & 4) {
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
- "Still flushing TX UART... i: %d\n", i);
- udelay(10);
- }
- else
- break;
- }
-
- ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-}
-
-
-/*
- * Flush the READ FIFO on the Neo.
- *
- * NOTE: Channel lock MUST be held before calling this function!
- */
-static void neo_flush_uart_read(struct jsm_channel *ch)
-{
- u8 tmp = 0;
- int i = 0;
-
- if (!ch)
- return;
-
- writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr);
-
- for (i = 0; i < 10; i++) {
-
- /* Check to see if the UART feels it completely flushed the FIFO. */
- tmp = readb(&ch->ch_neo_uart->isr_fcr);
- if (tmp & 2) {
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
- "Still flushing RX UART... i: %d\n", i);
- udelay(10);
- }
- else
- break;
- }
-}
-
-/*
- * No locks are assumed to be held when calling this function.
- */
-static void neo_clear_break(struct jsm_channel *ch, int force)
-{
- unsigned long lock_flags;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- /* Turn break off, and unset some variables */
- if (ch->ch_flags & CH_BREAK_SENDING) {
- u8 temp = readb(&ch->ch_neo_uart->lcr);
- writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
-
- ch->ch_flags &= ~(CH_BREAK_SENDING);
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
- "clear break Finishing UART_LCR_SBC! finished: %lx\n", jiffies);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
- }
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-}
-
-/*
- * Parse the ISR register.
- */
-static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
-{
- struct jsm_channel *ch;
- u8 isr;
- u8 cause;
- unsigned long lock_flags;
-
- if (!brd)
- return;
-
- if (port > brd->maxports)
- return;
-
- ch = brd->channels[port];
- if (!ch)
- return;
-
- /* Here we try to figure out what caused the interrupt to happen */
- while (1) {
-
- isr = readb(&ch->ch_neo_uart->isr_fcr);
-
- /* Bail if no pending interrupt */
- if (isr & UART_IIR_NO_INT)
- break;
-
- /*
- * Yank off the upper 2 bits, which just show that the FIFO's are enabled.
- */
- isr &= ~(UART_17158_IIR_FIFO_ENABLED);
-
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "%s:%d isr: %x\n", __FILE__, __LINE__, isr);
-
- if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
- /* Read data from uart -> queue */
- neo_copy_data_from_uart_to_queue(ch);
-
- /* Call our tty layer to enforce queue flow control if needed. */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- jsm_check_queue_flow_control(ch);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- }
-
- if (isr & UART_IIR_THRI) {
- /* Transfer data (if any) from Write Queue -> UART. */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- neo_copy_data_from_queue_to_uart(ch);
- }
-
- if (isr & UART_17158_IIR_XONXOFF) {
- cause = readb(&ch->ch_neo_uart->xoffchar1);
-
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause);
-
- /*
- * Since the UART detected either an XON or
- * XOFF match, we need to figure out which
- * one it was, so we can suspend or resume data flow.
- */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- if (cause == UART_17158_XON_DETECT) {
- /* Is output stopped right now, if so, resume it */
- if (brd->channels[port]->ch_flags & CH_STOP) {
- ch->ch_flags &= ~(CH_STOP);
- }
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Port %d. XON detected in incoming data\n", port);
- }
- else if (cause == UART_17158_XOFF_DETECT) {
- if (!(brd->channels[port]->ch_flags & CH_STOP)) {
- ch->ch_flags |= CH_STOP;
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Setting CH_STOP\n");
- }
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Port: %d. XOFF detected in incoming data\n", port);
- }
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- }
-
- if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) {
- /*
- * If we get here, this means the hardware is doing auto flow control.
- * Check to see whether RTS/DTR or CTS/DSR caused this interrupt.
- */
- cause = readb(&ch->ch_neo_uart->mcr);
-
- /* Which pin is doing auto flow? RTS or DTR? */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- if ((cause & 0x4) == 0) {
- if (cause & UART_MCR_RTS)
- ch->ch_mostat |= UART_MCR_RTS;
- else
- ch->ch_mostat &= ~(UART_MCR_RTS);
- } else {
- if (cause & UART_MCR_DTR)
- ch->ch_mostat |= UART_MCR_DTR;
- else
- ch->ch_mostat &= ~(UART_MCR_DTR);
- }
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- }
-
- /* Parse any modem signal changes */
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "MOD_STAT: sending to parse_modem_sigs\n");
- neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
- }
-}
-
-static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
-{
- struct jsm_channel *ch;
- int linestatus;
- unsigned long lock_flags;
-
- if (!brd)
- return;
-
- if (port > brd->maxports)
- return;
-
- ch = brd->channels[port];
- if (!ch)
- return;
-
- linestatus = readb(&ch->ch_neo_uart->lsr);
-
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus);
-
- ch->ch_cached_lsr |= linestatus;
-
- if (ch->ch_cached_lsr & UART_LSR_DR) {
- /* Read data from uart -> queue */
- neo_copy_data_from_uart_to_queue(ch);
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- jsm_check_queue_flow_control(ch);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- }
-
- /*
- * This is a special flag. It indicates that at least 1
- * RX error (parity, framing, or break) has happened.
- * Mark this in our struct, which will tell me that I have
- *to do the special RX+LSR read for this FIFO load.
- */
- if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d Got an RX error, need to parse LSR\n",
- __FILE__, __LINE__, port);
-
- /*
- * The next 3 tests should *NOT* happen, as the above test
- * should encapsulate all 3... At least, thats what Exar says.
- */
-
- if (linestatus & UART_LSR_PE) {
- ch->ch_err_parity++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port);
- }
-
- if (linestatus & UART_LSR_FE) {
- ch->ch_err_frame++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port);
- }
-
- if (linestatus & UART_LSR_BI) {
- ch->ch_err_break++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port);
- }
-
- if (linestatus & UART_LSR_OE) {
- /*
- * Rx Oruns. Exar says that an orun will NOT corrupt
- * the FIFO. It will just replace the holding register
- * with this new data byte. So basically just ignore this.
- * Probably we should eventually have an orun stat in our driver...
- */
- ch->ch_err_overrun++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port);
- }
-
- if (linestatus & UART_LSR_THRE) {
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- /* Transfer data (if any) from Write Queue -> UART. */
- neo_copy_data_from_queue_to_uart(ch);
- }
- else if (linestatus & UART_17158_TX_AND_FIFO_CLR) {
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- /* Transfer data (if any) from Write Queue -> UART. */
- neo_copy_data_from_queue_to_uart(ch);
- }
-}
-
-/*
- * neo_param()
- * Send any/all changes to the line to the UART.
- */
-static void neo_param(struct jsm_channel *ch)
-{
- u8 lcr = 0;
- u8 uart_lcr, ier;
- u32 baud;
- int quot;
- struct jsm_board *bd;
-
- bd = ch->ch_bd;
- if (!bd)
- return;
-
- /*
- * If baud rate is zero, flush queues, and set mval to drop DTR.
- */
- if ((ch->ch_c_cflag & (CBAUD)) == 0) {
- ch->ch_r_head = ch->ch_r_tail = 0;
- ch->ch_e_head = ch->ch_e_tail = 0;
- ch->ch_w_head = ch->ch_w_tail = 0;
-
- neo_flush_uart_write(ch);
- neo_flush_uart_read(ch);
-
- ch->ch_flags |= (CH_BAUD0);
- ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
- neo_assert_modem_signals(ch);
- return;
-
- } else {
- int i;
- unsigned int cflag;
- static struct {
- unsigned int rate;
- unsigned int cflag;
- } baud_rates[] = {
- { 921600, B921600 },
- { 460800, B460800 },
- { 230400, B230400 },
- { 115200, B115200 },
- { 57600, B57600 },
- { 38400, B38400 },
- { 19200, B19200 },
- { 9600, B9600 },
- { 4800, B4800 },
- { 2400, B2400 },
- { 1200, B1200 },
- { 600, B600 },
- { 300, B300 },
- { 200, B200 },
- { 150, B150 },
- { 134, B134 },
- { 110, B110 },
- { 75, B75 },
- { 50, B50 },
- };
-
- cflag = C_BAUD(ch->uart_port.state->port.tty);
- baud = 9600;
- for (i = 0; i < ARRAY_SIZE(baud_rates); i++) {
- if (baud_rates[i].cflag == cflag) {
- baud = baud_rates[i].rate;
- break;
- }
- }
-
- if (ch->ch_flags & CH_BAUD0)
- ch->ch_flags &= ~(CH_BAUD0);
- }
-
- if (ch->ch_c_cflag & PARENB)
- lcr |= UART_LCR_PARITY;
-
- if (!(ch->ch_c_cflag & PARODD))
- lcr |= UART_LCR_EPAR;
-
- /*
- * Not all platforms support mark/space parity,
- * so this will hide behind an ifdef.
- */
-#ifdef CMSPAR
- if (ch->ch_c_cflag & CMSPAR)
- lcr |= UART_LCR_SPAR;
-#endif
-
- if (ch->ch_c_cflag & CSTOPB)
- lcr |= UART_LCR_STOP;
-
- switch (ch->ch_c_cflag & CSIZE) {
- case CS5:
- lcr |= UART_LCR_WLEN5;
- break;
- case CS6:
- lcr |= UART_LCR_WLEN6;
- break;
- case CS7:
- lcr |= UART_LCR_WLEN7;
- break;
- case CS8:
- default:
- lcr |= UART_LCR_WLEN8;
- break;
- }
-
- ier = readb(&ch->ch_neo_uart->ier);
- uart_lcr = readb(&ch->ch_neo_uart->lcr);
-
- if (baud == 0)
- baud = 9600;
-
- quot = ch->ch_bd->bd_dividend / baud;
-
- if (quot != 0) {
- writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
- writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
- writeb((quot >> 8), &ch->ch_neo_uart->ier);
- writeb(lcr, &ch->ch_neo_uart->lcr);
- }
-
- if (uart_lcr != lcr)
- writeb(lcr, &ch->ch_neo_uart->lcr);
-
- if (ch->ch_c_cflag & CREAD)
- ier |= (UART_IER_RDI | UART_IER_RLSI);
-
- ier |= (UART_IER_THRI | UART_IER_MSI);
-
- writeb(ier, &ch->ch_neo_uart->ier);
-
- /* Set new start/stop chars */
- neo_set_new_start_stop_chars(ch);
-
- if (ch->ch_c_cflag & CRTSCTS)
- neo_set_cts_flow_control(ch);
- else if (ch->ch_c_iflag & IXON) {
- /* If start/stop is set to disable, then we should disable flow control */
- if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
- neo_set_no_output_flow_control(ch);
- else
- neo_set_ixon_flow_control(ch);
- }
- else
- neo_set_no_output_flow_control(ch);
-
- if (ch->ch_c_cflag & CRTSCTS)
- neo_set_rts_flow_control(ch);
- else if (ch->ch_c_iflag & IXOFF) {
- /* If start/stop is set to disable, then we should disable flow control */
- if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
- neo_set_no_input_flow_control(ch);
- else
- neo_set_ixoff_flow_control(ch);
- }
- else
- neo_set_no_input_flow_control(ch);
- /*
- * Adjust the RX FIFO Trigger level if baud is less than 9600.
- * Not exactly elegant, but this is needed because of the Exar chip's
- * delay on firing off the RX FIFO interrupt on slower baud rates.
- */
- if (baud < 9600) {
- writeb(1, &ch->ch_neo_uart->rfifo);
- ch->ch_r_tlevel = 1;
- }
-
- neo_assert_modem_signals(ch);
-
- /* Get current status of the modem signals now */
- neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
- return;
-}
-
-/*
- * jsm_neo_intr()
- *
- * Neo specific interrupt handler.
- */
-static irqreturn_t neo_intr(int irq, void *voidbrd)
-{
- struct jsm_board *brd = voidbrd;
- struct jsm_channel *ch;
- int port = 0;
- int type = 0;
- int current_port;
- u32 tmp;
- u32 uart_poll;
- unsigned long lock_flags;
- unsigned long lock_flags2;
- int outofloop_count = 0;
-
- /* Lock out the slow poller from running on this board. */
- spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);
-
- /*
- * Read in "extended" IRQ information from the 32bit Neo register.
- * Bits 0-7: What port triggered the interrupt.
- * Bits 8-31: Each 3bits indicate what type of interrupt occurred.
- */
- uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
-
- jsm_printk(INTR, INFO, &brd->pci_dev,
- "%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll);
-
- if (!uart_poll) {
- jsm_printk(INTR, INFO, &brd->pci_dev,
- "Kernel interrupted to me, but no pending interrupts...\n");
- spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
- return IRQ_NONE;
- }
-
- /* At this point, we have at least SOMETHING to service, dig further... */
-
- current_port = 0;
-
- /* Loop on each port */
- while (((uart_poll & 0xff) != 0) && (outofloop_count < 0xff)){
-
- tmp = uart_poll;
- outofloop_count++;
-
- /* Check current port to see if it has interrupt pending */
- if ((tmp & jsm_offset_table[current_port]) != 0) {
- port = current_port;
- type = tmp >> (8 + (port * 3));
- type &= 0x7;
- } else {
- current_port++;
- continue;
- }
-
- jsm_printk(INTR, INFO, &brd->pci_dev,
- "%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type);
-
- /* Remove this port + type from uart_poll */
- uart_poll &= ~(jsm_offset_table[port]);
-
- if (!type) {
- /* If no type, just ignore it, and move onto next port */
- jsm_printk(INTR, ERR, &brd->pci_dev,
- "Interrupt with no type! port: %d\n", port);
- continue;
- }
-
- /* Switch on type of interrupt we have */
- switch (type) {
-
- case UART_17158_RXRDY_TIMEOUT:
- /*
- * RXRDY Time-out is cleared by reading data in the
- * RX FIFO until it falls below the trigger level.
- */
-
- /* Verify the port is in range. */
- if (port > brd->nasync)
- continue;
-
- ch = brd->channels[port];
- neo_copy_data_from_uart_to_queue(ch);
-
- /* Call our tty layer to enforce queue flow control if needed. */
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
- jsm_check_queue_flow_control(ch);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
-
- continue;
-
- case UART_17158_RX_LINE_STATUS:
- /*
- * RXRDY and RX LINE Status (logic OR of LSR[4:1])
- */
- neo_parse_lsr(brd, port);
- continue;
-
- case UART_17158_TXRDY:
- /*
- * TXRDY interrupt clears after reading ISR register for the UART channel.
- */
-
- /*
- * Yes, this is odd...
- * Why would I check EVERY possibility of type of
- * interrupt, when we know its TXRDY???
- * Becuz for some reason, even tho we got triggered for TXRDY,
- * it seems to be occassionally wrong. Instead of TX, which
- * it should be, I was getting things like RXDY too. Weird.
- */
- neo_parse_isr(brd, port);
- continue;
-
- case UART_17158_MSR:
- /*
- * MSR or flow control was seen.
- */
- neo_parse_isr(brd, port);
- continue;
-
- default:
- /*
- * The UART triggered us with a bogus interrupt type.
- * It appears the Exar chip, when REALLY bogged down, will throw
- * these once and awhile.
- * Its harmless, just ignore it and move on.
- */
- jsm_printk(INTR, ERR, &brd->pci_dev,
- "%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type);
- continue;
- }
- }
-
- spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
-
- jsm_printk(INTR, INFO, &brd->pci_dev, "finish.\n");
- return IRQ_HANDLED;
-}
-
-/*
- * Neo specific way of turning off the receiver.
- * Used as a way to enforce queue flow control when in
- * hardware flow control mode.
- */
-static void neo_disable_receiver(struct jsm_channel *ch)
-{
- u8 tmp = readb(&ch->ch_neo_uart->ier);
- tmp &= ~(UART_IER_RDI);
- writeb(tmp, &ch->ch_neo_uart->ier);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
-}
-
-
-/*
- * Neo specific way of turning on the receiver.
- * Used as a way to un-enforce queue flow control when in
- * hardware flow control mode.
- */
-static void neo_enable_receiver(struct jsm_channel *ch)
-{
- u8 tmp = readb(&ch->ch_neo_uart->ier);
- tmp |= (UART_IER_RDI);
- writeb(tmp, &ch->ch_neo_uart->ier);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
-}
-
-static void neo_send_start_character(struct jsm_channel *ch)
-{
- if (!ch)
- return;
-
- if (ch->ch_startc != __DISABLED_CHAR) {
- ch->ch_xon_sends++;
- writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
- }
-}
-
-static void neo_send_stop_character(struct jsm_channel *ch)
-{
- if (!ch)
- return;
-
- if (ch->ch_stopc != __DISABLED_CHAR) {
- ch->ch_xoff_sends++;
- writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
- }
-}
-
-/*
- * neo_uart_init
- */
-static void neo_uart_init(struct jsm_channel *ch)
-{
- writeb(0, &ch->ch_neo_uart->ier);
- writeb(0, &ch->ch_neo_uart->efr);
- writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);
-
- /* Clear out UART and FIFO */
- readb(&ch->ch_neo_uart->txrx);
- writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
- readb(&ch->ch_neo_uart->lsr);
- readb(&ch->ch_neo_uart->msr);
-
- ch->ch_flags |= CH_FIFO_ENABLED;
-
- /* Assert any signals we want up */
- writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
-}
-
-/*
- * Make the UART completely turn off.
- */
-static void neo_uart_off(struct jsm_channel *ch)
-{
- /* Turn off UART enhanced bits */
- writeb(0, &ch->ch_neo_uart->efr);
-
- /* Stop all interrupts from occurring. */
- writeb(0, &ch->ch_neo_uart->ier);
-}
-
-static u32 neo_get_uart_bytes_left(struct jsm_channel *ch)
-{
- u8 left = 0;
- u8 lsr = readb(&ch->ch_neo_uart->lsr);
-
- /* We must cache the LSR as some of the bits get reset once read... */
- ch->ch_cached_lsr |= lsr;
-
- /* Determine whether the Transmitter is empty or not */
- if (!(lsr & UART_LSR_TEMT))
- left = 1;
- else {
- ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
- left = 0;
- }
-
- return left;
-}
-
-/* Channel lock MUST be held by the calling function! */
-static void neo_send_break(struct jsm_channel *ch)
-{
- /*
- * Set the time we should stop sending the break.
- * If we are already sending a break, toss away the existing
- * time to stop, and use this new value instead.
- */
-
- /* Tell the UART to start sending the break */
- if (!(ch->ch_flags & CH_BREAK_SENDING)) {
- u8 temp = readb(&ch->ch_neo_uart->lcr);
- writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr);
- ch->ch_flags |= (CH_BREAK_SENDING);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
- }
-}
-
-/*
- * neo_send_immediate_char.
- *
- * Sends a specific character as soon as possible to the UART,
- * jumping over any bytes that might be in the write queue.
- *
- * The channel lock MUST be held by the calling function.
- */
-static void neo_send_immediate_char(struct jsm_channel *ch, unsigned char c)
-{
- if (!ch)
- return;
-
- writeb(c, &ch->ch_neo_uart->txrx);
-
- /* flush write operation */
- neo_pci_posting_flush(ch->ch_bd);
-}
-
-struct board_ops jsm_neo_ops = {
- .intr = neo_intr,
- .uart_init = neo_uart_init,
- .uart_off = neo_uart_off,
- .param = neo_param,
- .assert_modem_signals = neo_assert_modem_signals,
- .flush_uart_write = neo_flush_uart_write,
- .flush_uart_read = neo_flush_uart_read,
- .disable_receiver = neo_disable_receiver,
- .enable_receiver = neo_enable_receiver,
- .send_break = neo_send_break,
- .clear_break = neo_clear_break,
- .send_start_character = neo_send_start_character,
- .send_stop_character = neo_send_stop_character,
- .copy_data_from_queue_to_uart = neo_copy_data_from_queue_to_uart,
- .get_uart_bytes_left = neo_get_uart_bytes_left,
- .send_immediate_char = neo_send_immediate_char
-};
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
deleted file mode 100644
index 7a4a914ecff0..000000000000
--- a/drivers/serial/jsm/jsm_tty.c
+++ /dev/null
@@ -1,910 +0,0 @@
-/************************************************************************
- * Copyright 2003 Digi International (www.digi.com)
- *
- * Copyright (C) 2004 IBM Corporation. All rights reserved.
- *
- * 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * Contact Information:
- * Scott H Kilau <Scott_Kilau@digi.com>
- * Ananda Venkatarman <mansarov@us.ibm.com>
- * Modifications:
- * 01/19/06: changed jsm_input routine to use the dynamically allocated
- * tty_buffer changes. Contributors: Scott Kilau and Ananda V.
- ***********************************************************************/
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/delay.h> /* For udelay */
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "jsm.h"
-
-static DECLARE_BITMAP(linemap, MAXLINES);
-
-static void jsm_carrier(struct jsm_channel *ch);
-
-static inline int jsm_get_mstat(struct jsm_channel *ch)
-{
- unsigned char mstat;
- unsigned result;
-
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "start\n");
-
- mstat = (ch->ch_mostat | ch->ch_mistat);
-
- result = 0;
-
- if (mstat & UART_MCR_DTR)
- result |= TIOCM_DTR;
- if (mstat & UART_MCR_RTS)
- result |= TIOCM_RTS;
- if (mstat & UART_MSR_CTS)
- result |= TIOCM_CTS;
- if (mstat & UART_MSR_DSR)
- result |= TIOCM_DSR;
- if (mstat & UART_MSR_RI)
- result |= TIOCM_RI;
- if (mstat & UART_MSR_DCD)
- result |= TIOCM_CD;
-
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
- return result;
-}
-
-static unsigned int jsm_tty_tx_empty(struct uart_port *port)
-{
- return TIOCSER_TEMT;
-}
-
-/*
- * Return modem signals to ld.
- */
-static unsigned int jsm_tty_get_mctrl(struct uart_port *port)
-{
- int result;
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
-
- result = jsm_get_mstat(channel);
-
- if (result < 0)
- return -ENXIO;
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
-
- return result;
-}
-
-/*
- * jsm_set_modem_info()
- *
- * Set modem signals, called by ld.
- */
-static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
-
- if (mctrl & TIOCM_RTS)
- channel->ch_mostat |= UART_MCR_RTS;
- else
- channel->ch_mostat &= ~UART_MCR_RTS;
-
- if (mctrl & TIOCM_DTR)
- channel->ch_mostat |= UART_MCR_DTR;
- else
- channel->ch_mostat &= ~UART_MCR_DTR;
-
- channel->ch_bd->bd_ops->assert_modem_signals(channel);
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
- udelay(10);
-}
-
-static void jsm_tty_start_tx(struct uart_port *port)
-{
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
-
- channel->ch_flags &= ~(CH_STOP);
- jsm_tty_write(port);
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
-}
-
-static void jsm_tty_stop_tx(struct uart_port *port)
-{
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
-
- channel->ch_flags |= (CH_STOP);
-
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
-}
-
-static void jsm_tty_send_xchar(struct uart_port *port, char ch)
-{
- unsigned long lock_flags;
- struct jsm_channel *channel = (struct jsm_channel *)port;
- struct ktermios *termios;
-
- spin_lock_irqsave(&port->lock, lock_flags);
- termios = port->state->port.tty->termios;
- if (ch == termios->c_cc[VSTART])
- channel->ch_bd->bd_ops->send_start_character(channel);
-
- if (ch == termios->c_cc[VSTOP])
- channel->ch_bd->bd_ops->send_stop_character(channel);
- spin_unlock_irqrestore(&port->lock, lock_flags);
-}
-
-static void jsm_tty_stop_rx(struct uart_port *port)
-{
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- channel->ch_bd->bd_ops->disable_receiver(channel);
-}
-
-static void jsm_tty_enable_ms(struct uart_port *port)
-{
- /* Nothing needed */
-}
-
-static void jsm_tty_break(struct uart_port *port, int break_state)
-{
- unsigned long lock_flags;
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- spin_lock_irqsave(&port->lock, lock_flags);
- if (break_state == -1)
- channel->ch_bd->bd_ops->send_break(channel);
- else
- channel->ch_bd->bd_ops->clear_break(channel, 0);
-
- spin_unlock_irqrestore(&port->lock, lock_flags);
-}
-
-static int jsm_tty_open(struct uart_port *port)
-{
- struct jsm_board *brd;
- struct jsm_channel *channel = (struct jsm_channel *)port;
- struct ktermios *termios;
-
- /* Get board pointer from our array of majors we have allocated */
- brd = channel->ch_bd;
-
- /*
- * Allocate channel buffers for read/write/error.
- * Set flag, so we don't get trounced on.
- */
- channel->ch_flags |= (CH_OPENING);
-
- /* Drop locks, as malloc with GFP_KERNEL can sleep */
-
- if (!channel->ch_rqueue) {
- channel->ch_rqueue = kzalloc(RQUEUESIZE, GFP_KERNEL);
- if (!channel->ch_rqueue) {
- jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
- "unable to allocate read queue buf");
- return -ENOMEM;
- }
- }
- if (!channel->ch_equeue) {
- channel->ch_equeue = kzalloc(EQUEUESIZE, GFP_KERNEL);
- if (!channel->ch_equeue) {
- jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
- "unable to allocate error queue buf");
- return -ENOMEM;
- }
- }
- if (!channel->ch_wqueue) {
- channel->ch_wqueue = kzalloc(WQUEUESIZE, GFP_KERNEL);
- if (!channel->ch_wqueue) {
- jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
- "unable to allocate write queue buf");
- return -ENOMEM;
- }
- }
-
- channel->ch_flags &= ~(CH_OPENING);
- /*
- * Initialize if neither terminal is open.
- */
- jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev,
- "jsm_open: initializing channel in open...\n");
-
- /*
- * Flush input queues.
- */
- channel->ch_r_head = channel->ch_r_tail = 0;
- channel->ch_e_head = channel->ch_e_tail = 0;
- channel->ch_w_head = channel->ch_w_tail = 0;
-
- brd->bd_ops->flush_uart_write(channel);
- brd->bd_ops->flush_uart_read(channel);
-
- channel->ch_flags = 0;
- channel->ch_cached_lsr = 0;
- channel->ch_stops_sent = 0;
-
- termios = port->state->port.tty->termios;
- channel->ch_c_cflag = termios->c_cflag;
- channel->ch_c_iflag = termios->c_iflag;
- channel->ch_c_oflag = termios->c_oflag;
- channel->ch_c_lflag = termios->c_lflag;
- channel->ch_startc = termios->c_cc[VSTART];
- channel->ch_stopc = termios->c_cc[VSTOP];
-
- /* Tell UART to init itself */
- brd->bd_ops->uart_init(channel);
-
- /*
- * Run param in case we changed anything
- */
- brd->bd_ops->param(channel);
-
- jsm_carrier(channel);
-
- channel->ch_open_count++;
-
- jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev, "finish\n");
- return 0;
-}
-
-static void jsm_tty_close(struct uart_port *port)
-{
- struct jsm_board *bd;
- struct ktermios *ts;
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
-
- bd = channel->ch_bd;
- ts = port->state->port.tty->termios;
-
- channel->ch_flags &= ~(CH_STOPI);
-
- channel->ch_open_count--;
-
- /*
- * If we have HUPCL set, lower DTR and RTS
- */
- if (channel->ch_c_cflag & HUPCL) {
- jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev,
- "Close. HUPCL set, dropping DTR/RTS\n");
-
- /* Drop RTS/DTR */
- channel->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS);
- bd->bd_ops->assert_modem_signals(channel);
- }
-
- /* Turn off UART interrupts for this port */
- channel->ch_bd->bd_ops->uart_off(channel);
-
- jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "finish\n");
-}
-
-static void jsm_tty_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old_termios)
-{
- unsigned long lock_flags;
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- spin_lock_irqsave(&port->lock, lock_flags);
- channel->ch_c_cflag = termios->c_cflag;
- channel->ch_c_iflag = termios->c_iflag;
- channel->ch_c_oflag = termios->c_oflag;
- channel->ch_c_lflag = termios->c_lflag;
- channel->ch_startc = termios->c_cc[VSTART];
- channel->ch_stopc = termios->c_cc[VSTOP];
-
- channel->ch_bd->bd_ops->param(channel);
- jsm_carrier(channel);
- spin_unlock_irqrestore(&port->lock, lock_flags);
-}
-
-static const char *jsm_tty_type(struct uart_port *port)
-{
- return "jsm";
-}
-
-static void jsm_tty_release_port(struct uart_port *port)
-{
-}
-
-static int jsm_tty_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void jsm_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_JSM;
-}
-
-static struct uart_ops jsm_ops = {
- .tx_empty = jsm_tty_tx_empty,
- .set_mctrl = jsm_tty_set_mctrl,
- .get_mctrl = jsm_tty_get_mctrl,
- .stop_tx = jsm_tty_stop_tx,
- .start_tx = jsm_tty_start_tx,
- .send_xchar = jsm_tty_send_xchar,
- .stop_rx = jsm_tty_stop_rx,
- .enable_ms = jsm_tty_enable_ms,
- .break_ctl = jsm_tty_break,
- .startup = jsm_tty_open,
- .shutdown = jsm_tty_close,
- .set_termios = jsm_tty_set_termios,
- .type = jsm_tty_type,
- .release_port = jsm_tty_release_port,
- .request_port = jsm_tty_request_port,
- .config_port = jsm_config_port,
-};
-
-/*
- * jsm_tty_init()
- *
- * Init the tty subsystem. Called once per board after board has been
- * downloaded and init'ed.
- */
-int __devinit jsm_tty_init(struct jsm_board *brd)
-{
- int i;
- void __iomem *vaddr;
- struct jsm_channel *ch;
-
- if (!brd)
- return -ENXIO;
-
- jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
-
- /*
- * Initialize board structure elements.
- */
-
- brd->nasync = brd->maxports;
-
- /*
- * Allocate channel memory that might not have been allocated
- * when the driver was first loaded.
- */
- for (i = 0; i < brd->nasync; i++) {
- if (!brd->channels[i]) {
-
- /*
- * Okay to malloc with GFP_KERNEL, we are not at
- * interrupt context, and there are no locks held.
- */
- brd->channels[i] = kzalloc(sizeof(struct jsm_channel), GFP_KERNEL);
- if (!brd->channels[i]) {
- jsm_printk(CORE, ERR, &brd->pci_dev,
- "%s:%d Unable to allocate memory for channel struct\n",
- __FILE__, __LINE__);
- }
- }
- }
-
- ch = brd->channels[0];
- vaddr = brd->re_map_membase;
-
- /* Set up channel variables */
- for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
-
- if (!brd->channels[i])
- continue;
-
- spin_lock_init(&ch->ch_lock);
-
- if (brd->bd_uart_offset == 0x200)
- ch->ch_neo_uart = vaddr + (brd->bd_uart_offset * i);
-
- ch->ch_bd = brd;
- ch->ch_portnum = i;
-
- /* .25 second delay */
- ch->ch_close_delay = 250;
-
- init_waitqueue_head(&ch->ch_flags_wait);
- }
-
- jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
- return 0;
-}
-
-int jsm_uart_port_init(struct jsm_board *brd)
-{
- int i, rc;
- unsigned int line;
- struct jsm_channel *ch;
-
- if (!brd)
- return -ENXIO;
-
- jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
-
- /*
- * Initialize board structure elements.
- */
-
- brd->nasync = brd->maxports;
-
- /* Set up channel variables */
- for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
-
- if (!brd->channels[i])
- continue;
-
- brd->channels[i]->uart_port.irq = brd->irq;
- brd->channels[i]->uart_port.uartclk = 14745600;
- brd->channels[i]->uart_port.type = PORT_JSM;
- brd->channels[i]->uart_port.iotype = UPIO_MEM;
- brd->channels[i]->uart_port.membase = brd->re_map_membase;
- brd->channels[i]->uart_port.fifosize = 16;
- brd->channels[i]->uart_port.ops = &jsm_ops;
- line = find_first_zero_bit(linemap, MAXLINES);
- if (line >= MAXLINES) {
- printk(KERN_INFO "jsm: linemap is full, added device failed\n");
- continue;
- } else
- set_bit(line, linemap);
- brd->channels[i]->uart_port.line = line;
- rc = uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port);
- if (rc){
- printk(KERN_INFO "jsm: Port %d failed. Aborting...\n", i);
- return rc;
- }
- else
- printk(KERN_INFO "jsm: Port %d added\n", i);
- }
-
- jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
- return 0;
-}
-
-int jsm_remove_uart_port(struct jsm_board *brd)
-{
- int i;
- struct jsm_channel *ch;
-
- if (!brd)
- return -ENXIO;
-
- jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
-
- /*
- * Initialize board structure elements.
- */
-
- brd->nasync = brd->maxports;
-
- /* Set up channel variables */
- for (i = 0; i < brd->nasync; i++) {
-
- if (!brd->channels[i])
- continue;
-
- ch = brd->channels[i];
-
- clear_bit(ch->uart_port.line, linemap);
- uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port);
- }
-
- jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
- return 0;
-}
-
-void jsm_input(struct jsm_channel *ch)
-{
- struct jsm_board *bd;
- struct tty_struct *tp;
- u32 rmask;
- u16 head;
- u16 tail;
- int data_len;
- unsigned long lock_flags;
- int len = 0;
- int n = 0;
- int s = 0;
- int i = 0;
-
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
-
- if (!ch)
- return;
-
- tp = ch->uart_port.state->port.tty;
-
- bd = ch->ch_bd;
- if(!bd)
- return;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- /*
- *Figure the number of characters in the buffer.
- *Exit immediately if none.
- */
-
- rmask = RQUEUEMASK;
-
- head = ch->ch_r_head & rmask;
- tail = ch->ch_r_tail & rmask;
-
- data_len = (head - tail) & rmask;
- if (data_len == 0) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- return;
- }
-
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
-
- /*
- *If the device is not open, or CREAD is off, flush
- *input data and return immediately.
- */
- if (!tp ||
- !(tp->termios->c_cflag & CREAD) ) {
-
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
- ch->ch_r_head = tail;
-
- /* Force queue flow control to be released, if needed */
- jsm_check_queue_flow_control(ch);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- return;
- }
-
- /*
- * If we are throttled, simply don't read any data.
- */
- if (ch->ch_flags & CH_STOPI) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Port %d throttled, not reading any data. head: %x tail: %x\n",
- ch->ch_portnum, head, tail);
- return;
- }
-
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");
-
- if (data_len <= 0) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
- return;
- }
-
- len = tty_buffer_request_room(tp, data_len);
- n = len;
-
- /*
- * n now contains the most amount of data we can copy,
- * bounded either by the flip buffer size or the amount
- * of data the card actually has pending...
- */
- while (n) {
- s = ((head >= tail) ? head : RQUEUESIZE) - tail;
- s = min(s, n);
-
- if (s <= 0)
- break;
-
- /*
- * If conditions are such that ld needs to see all
- * UART errors, we will have to walk each character
- * and error byte and send them to the buffer one at
- * a time.
- */
-
- if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
- for (i = 0; i < s; i++) {
- /*
- * Give the Linux ld the flags in the
- * format it likes.
- */
- if (*(ch->ch_equeue +tail +i) & UART_LSR_BI)
- tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_BREAK);
- else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE)
- tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY);
- else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
- tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME);
- else
- tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
- }
- } else {
- tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ;
- }
- tail += s;
- n -= s;
- /* Flip queue if needed */
- tail &= rmask;
- }
-
- ch->ch_r_tail = tail & rmask;
- ch->ch_e_tail = tail & rmask;
- jsm_check_queue_flow_control(ch);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- /* Tell the tty layer its okay to "eat" the data now */
- tty_flip_buffer_push(tp);
-
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
-}
-
-static void jsm_carrier(struct jsm_channel *ch)
-{
- struct jsm_board *bd;
-
- int virt_carrier = 0;
- int phys_carrier = 0;
-
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev, "start\n");
- if (!ch)
- return;
-
- bd = ch->ch_bd;
-
- if (!bd)
- return;
-
- if (ch->ch_mistat & UART_MSR_DCD) {
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
- "mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
- phys_carrier = 1;
- }
-
- if (ch->ch_c_cflag & CLOCAL)
- virt_carrier = 1;
-
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
- "DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier);
-
- /*
- * Test for a VIRTUAL carrier transition to HIGH.
- */
- if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
-
- /*
- * When carrier rises, wake any threads waiting
- * for carrier in the open routine.
- */
-
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
- "carrier: virt DCD rose\n");
-
- if (waitqueue_active(&(ch->ch_flags_wait)))
- wake_up_interruptible(&ch->ch_flags_wait);
- }
-
- /*
- * Test for a PHYSICAL carrier transition to HIGH.
- */
- if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
-
- /*
- * When carrier rises, wake any threads waiting
- * for carrier in the open routine.
- */
-
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
- "carrier: physical DCD rose\n");
-
- if (waitqueue_active(&(ch->ch_flags_wait)))
- wake_up_interruptible(&ch->ch_flags_wait);
- }
-
- /*
- * Test for a PHYSICAL transition to low, so long as we aren't
- * currently ignoring physical transitions (which is what "virtual
- * carrier" indicates).
- *
- * The transition of the virtual carrier to low really doesn't
- * matter... it really only means "ignore carrier state", not
- * "make pretend that carrier is there".
- */
- if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0)
- && (phys_carrier == 0)) {
- /*
- * When carrier drops:
- *
- * Drop carrier on all open units.
- *
- * Flush queues, waking up any task waiting in the
- * line discipline.
- *
- * Send a hangup to the control terminal.
- *
- * Enable all select calls.
- */
- if (waitqueue_active(&(ch->ch_flags_wait)))
- wake_up_interruptible(&ch->ch_flags_wait);
- }
-
- /*
- * Make sure that our cached values reflect the current reality.
- */
- if (virt_carrier == 1)
- ch->ch_flags |= CH_FCAR;
- else
- ch->ch_flags &= ~CH_FCAR;
-
- if (phys_carrier == 1)
- ch->ch_flags |= CH_CD;
- else
- ch->ch_flags &= ~CH_CD;
-}
-
-
-void jsm_check_queue_flow_control(struct jsm_channel *ch)
-{
- struct board_ops *bd_ops = ch->ch_bd->bd_ops;
- int qleft;
-
- /* Store how much space we have left in the queue */
- if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0)
- qleft += RQUEUEMASK + 1;
-
- /*
- * Check to see if we should enforce flow control on our queue because
- * the ld (or user) isn't reading data out of our queue fast enuf.
- *
- * NOTE: This is done based on what the current flow control of the
- * port is set for.
- *
- * 1) HWFLOW (RTS) - Turn off the UART's Receive interrupt.
- * This will cause the UART's FIFO to back up, and force
- * the RTS signal to be dropped.
- * 2) SWFLOW (IXOFF) - Keep trying to send a stop character to
- * the other side, in hopes it will stop sending data to us.
- * 3) NONE - Nothing we can do. We will simply drop any extra data
- * that gets sent into us when the queue fills up.
- */
- if (qleft < 256) {
- /* HWFLOW */
- if (ch->ch_c_cflag & CRTSCTS) {
- if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
- bd_ops->disable_receiver(ch);
- ch->ch_flags |= (CH_RECEIVER_OFF);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
- qleft);
- }
- }
- /* SWFLOW */
- else if (ch->ch_c_iflag & IXOFF) {
- if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
- bd_ops->send_stop_character(ch);
- ch->ch_stops_sent++;
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
- }
- }
- }
-
- /*
- * Check to see if we should unenforce flow control because
- * ld (or user) finally read enuf data out of our queue.
- *
- * NOTE: This is done based on what the current flow control of the
- * port is set for.
- *
- * 1) HWFLOW (RTS) - Turn back on the UART's Receive interrupt.
- * This will cause the UART's FIFO to raise RTS back up,
- * which will allow the other side to start sending data again.
- * 2) SWFLOW (IXOFF) - Send a start character to
- * the other side, so it will start sending data to us again.
- * 3) NONE - Do nothing. Since we didn't do anything to turn off the
- * other side, we don't need to do anything now.
- */
- if (qleft > (RQUEUESIZE / 2)) {
- /* HWFLOW */
- if (ch->ch_c_cflag & CRTSCTS) {
- if (ch->ch_flags & CH_RECEIVER_OFF) {
- bd_ops->enable_receiver(ch);
- ch->ch_flags &= ~(CH_RECEIVER_OFF);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
- qleft);
- }
- }
- /* SWFLOW */
- else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
- ch->ch_stops_sent = 0;
- bd_ops->send_start_character(ch);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
- }
- }
-}
-
-/*
- * jsm_tty_write()
- *
- * Take data from the user or kernel and send it out to the FEP.
- * In here exists all the Transparent Print magic as well.
- */
-int jsm_tty_write(struct uart_port *port)
-{
- int bufcount;
- int data_count = 0,data_count1 =0;
- u16 head;
- u16 tail;
- u16 tmask;
- u32 remain;
- int temp_tail = port->state->xmit.tail;
- struct jsm_channel *channel = (struct jsm_channel *)port;
-
- tmask = WQUEUEMASK;
- head = (channel->ch_w_head) & tmask;
- tail = (channel->ch_w_tail) & tmask;
-
- if ((bufcount = tail - head - 1) < 0)
- bufcount += WQUEUESIZE;
-
- bufcount = min(bufcount, 56);
- remain = WQUEUESIZE - head;
-
- data_count = 0;
- if (bufcount >= remain) {
- bufcount -= remain;
- while ((port->state->xmit.head != temp_tail) &&
- (data_count < remain)) {
- channel->ch_wqueue[head++] =
- port->state->xmit.buf[temp_tail];
-
- temp_tail++;
- temp_tail &= (UART_XMIT_SIZE - 1);
- data_count++;
- }
- if (data_count == remain) head = 0;
- }
-
- data_count1 = 0;
- if (bufcount > 0) {
- remain = bufcount;
- while ((port->state->xmit.head != temp_tail) &&
- (data_count1 < remain)) {
- channel->ch_wqueue[head++] =
- port->state->xmit.buf[temp_tail];
-
- temp_tail++;
- temp_tail &= (UART_XMIT_SIZE - 1);
- data_count1++;
-
- }
- }
-
- port->state->xmit.tail = temp_tail;
-
- data_count += data_count1;
- if (data_count) {
- head &= tmask;
- channel->ch_w_head = head;
- }
-
- if (data_count) {
- channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel);
- }
-
- return data_count;
-}
diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
deleted file mode 100644
index 25a8bc565f40..000000000000
--- a/drivers/serial/kgdboc.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Based on the same principle as kgdboe using the NETPOLL api, this
- * driver uses a console polling api to implement a gdb serial inteface
- * which is multiplexed on a console port.
- *
- * Maintainer: Jason Wessel <jason.wessel@windriver.com>
- *
- * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/kgdb.h>
-#include <linux/kdb.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/vt_kern.h>
-#include <linux/input.h>
-
-#define MAX_CONFIG_LEN 40
-
-static struct kgdb_io kgdboc_io_ops;
-
-/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
-static int configured = -1;
-
-static char config[MAX_CONFIG_LEN];
-static struct kparam_string kps = {
- .string = config,
- .maxlen = MAX_CONFIG_LEN,
-};
-
-static int kgdboc_use_kms; /* 1 if we use kernel mode switching */
-static struct tty_driver *kgdb_tty_driver;
-static int kgdb_tty_line;
-
-#ifdef CONFIG_KDB_KEYBOARD
-static int kgdboc_reset_connect(struct input_handler *handler,
- struct input_dev *dev,
- const struct input_device_id *id)
-{
- input_reset_device(dev);
-
- /* Retrun an error - we do not want to bind, just to reset */
- return -ENODEV;
-}
-
-static void kgdboc_reset_disconnect(struct input_handle *handle)
-{
- /* We do not expect anyone to actually bind to us */
- BUG();
-}
-
-static const struct input_device_id kgdboc_reset_ids[] = {
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
- .evbit = { BIT_MASK(EV_KEY) },
- },
- { }
-};
-
-static struct input_handler kgdboc_reset_handler = {
- .connect = kgdboc_reset_connect,
- .disconnect = kgdboc_reset_disconnect,
- .name = "kgdboc_reset",
- .id_table = kgdboc_reset_ids,
-};
-
-static DEFINE_MUTEX(kgdboc_reset_mutex);
-
-static void kgdboc_restore_input_helper(struct work_struct *dummy)
-{
- /*
- * We need to take a mutex to prevent several instances of
- * this work running on different CPUs so they don't try
- * to register again already registered handler.
- */
- mutex_lock(&kgdboc_reset_mutex);
-
- if (input_register_handler(&kgdboc_reset_handler) == 0)
- input_unregister_handler(&kgdboc_reset_handler);
-
- mutex_unlock(&kgdboc_reset_mutex);
-}
-
-static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
-
-static void kgdboc_restore_input(void)
-{
- if (likely(system_state == SYSTEM_RUNNING))
- schedule_work(&kgdboc_restore_input_work);
-}
-
-static int kgdboc_register_kbd(char **cptr)
-{
- if (strncmp(*cptr, "kbd", 3) == 0) {
- if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
- kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
- kdb_poll_idx++;
- if (cptr[0][3] == ',')
- *cptr += 4;
- else
- return 1;
- }
- }
- return 0;
-}
-
-static void kgdboc_unregister_kbd(void)
-{
- int i;
-
- for (i = 0; i < kdb_poll_idx; i++) {
- if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
- kdb_poll_idx--;
- kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
- kdb_poll_funcs[kdb_poll_idx] = NULL;
- i--;
- }
- }
- flush_work_sync(&kgdboc_restore_input_work);
-}
-#else /* ! CONFIG_KDB_KEYBOARD */
-#define kgdboc_register_kbd(x) 0
-#define kgdboc_unregister_kbd()
-#define kgdboc_restore_input()
-#endif /* ! CONFIG_KDB_KEYBOARD */
-
-static int kgdboc_option_setup(char *opt)
-{
- if (strlen(opt) > MAX_CONFIG_LEN) {
- printk(KERN_ERR "kgdboc: config string too long\n");
- return -ENOSPC;
- }
- strcpy(config, opt);
-
- return 0;
-}
-
-__setup("kgdboc=", kgdboc_option_setup);
-
-static void cleanup_kgdboc(void)
-{
- kgdboc_unregister_kbd();
- if (configured == 1)
- kgdb_unregister_io_module(&kgdboc_io_ops);
-}
-
-static int configure_kgdboc(void)
-{
- struct tty_driver *p;
- int tty_line = 0;
- int err;
- char *cptr = config;
- struct console *cons;
-
- err = kgdboc_option_setup(config);
- if (err || !strlen(config) || isspace(config[0]))
- goto noconfig;
-
- err = -ENODEV;
- kgdboc_io_ops.is_console = 0;
- kgdb_tty_driver = NULL;
-
- kgdboc_use_kms = 0;
- if (strncmp(cptr, "kms,", 4) == 0) {
- cptr += 4;
- kgdboc_use_kms = 1;
- }
-
- if (kgdboc_register_kbd(&cptr))
- goto do_register;
-
- p = tty_find_polling_driver(cptr, &tty_line);
- if (!p)
- goto noconfig;
-
- cons = console_drivers;
- while (cons) {
- int idx;
- if (cons->device && cons->device(cons, &idx) == p &&
- idx == tty_line) {
- kgdboc_io_ops.is_console = 1;
- break;
- }
- cons = cons->next;
- }
-
- kgdb_tty_driver = p;
- kgdb_tty_line = tty_line;
-
-do_register:
- err = kgdb_register_io_module(&kgdboc_io_ops);
- if (err)
- goto noconfig;
-
- configured = 1;
-
- return 0;
-
-noconfig:
- config[0] = 0;
- configured = 0;
- cleanup_kgdboc();
-
- return err;
-}
-
-static int __init init_kgdboc(void)
-{
- /* Already configured? */
- if (configured == 1)
- return 0;
-
- return configure_kgdboc();
-}
-
-static int kgdboc_get_char(void)
-{
- if (!kgdb_tty_driver)
- return -1;
- return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
- kgdb_tty_line);
-}
-
-static void kgdboc_put_char(u8 chr)
-{
- if (!kgdb_tty_driver)
- return;
- kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
- kgdb_tty_line, chr);
-}
-
-static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
-{
- int len = strlen(kmessage);
-
- if (len >= MAX_CONFIG_LEN) {
- printk(KERN_ERR "kgdboc: config string too long\n");
- return -ENOSPC;
- }
-
- /* Only copy in the string if the init function has not run yet */
- if (configured < 0) {
- strcpy(config, kmessage);
- return 0;
- }
-
- if (kgdb_connected) {
- printk(KERN_ERR
- "kgdboc: Cannot reconfigure while KGDB is connected.\n");
-
- return -EBUSY;
- }
-
- strcpy(config, kmessage);
- /* Chop out \n char as a result of echo */
- if (config[len - 1] == '\n')
- config[len - 1] = '\0';
-
- if (configured == 1)
- cleanup_kgdboc();
-
- /* Go and configure with the new params. */
- return configure_kgdboc();
-}
-
-static int dbg_restore_graphics;
-
-static void kgdboc_pre_exp_handler(void)
-{
- if (!dbg_restore_graphics && kgdboc_use_kms) {
- dbg_restore_graphics = 1;
- con_debug_enter(vc_cons[fg_console].d);
- }
- /* Increment the module count when the debugger is active */
- if (!kgdb_connected)
- try_module_get(THIS_MODULE);
-}
-
-static void kgdboc_post_exp_handler(void)
-{
- /* decrement the module count when the debugger detaches */
- if (!kgdb_connected)
- module_put(THIS_MODULE);
- if (kgdboc_use_kms && dbg_restore_graphics) {
- dbg_restore_graphics = 0;
- con_debug_leave();
- }
- kgdboc_restore_input();
-}
-
-static struct kgdb_io kgdboc_io_ops = {
- .name = "kgdboc",
- .read_char = kgdboc_get_char,
- .write_char = kgdboc_put_char,
- .pre_exception = kgdboc_pre_exp_handler,
- .post_exception = kgdboc_post_exp_handler,
-};
-
-#ifdef CONFIG_KGDB_SERIAL_CONSOLE
-/* This is only available if kgdboc is a built in for early debugging */
-static int __init kgdboc_early_init(char *opt)
-{
- /* save the first character of the config string because the
- * init routine can destroy it.
- */
- char save_ch;
-
- kgdboc_option_setup(opt);
- save_ch = config[0];
- init_kgdboc();
- config[0] = save_ch;
- return 0;
-}
-
-early_param("ekgdboc", kgdboc_early_init);
-#endif /* CONFIG_KGDB_SERIAL_CONSOLE */
-
-module_init(init_kgdboc);
-module_exit(cleanup_kgdboc);
-module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
-MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
-MODULE_DESCRIPTION("KGDB Console TTY Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
deleted file mode 100644
index bea5c215460c..000000000000
--- a/drivers/serial/m32r_sio.c
+++ /dev/null
@@ -1,1192 +0,0 @@
-/*
- * m32r_sio.c
- *
- * Driver for M32R serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- * Based on drivers/serial/8250.c.
- *
- * Copyright (C) 2001 Russell King.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
- *
- * 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.
- */
-
-/*
- * A note about mapbase / membase
- *
- * mapbase is the physical address of the IO port. Currently, we don't
- * support this very well, and it may well be dropped from this driver
- * in future. As such, mapbase should be NULL.
- *
- * membase is an 'ioremapped' cookie. This is compatible with the old
- * serial.c driver, and is currently the preferred form.
- */
-
-#if defined(CONFIG_SERIAL_M32R_SIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/delay.h>
-
-#include <asm/m32r.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define PORT_M32R_BASE PORT_M32R_SIO
-#define PORT_INDEX(x) (x - PORT_M32R_BASE + 1)
-#define BAUD_RATE 115200
-
-#include <linux/serial_core.h>
-#include "m32r_sio.h"
-#include "m32r_sio_reg.h"
-
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...) printk(fmt)
-#else
-#define DEBUG_INTR(fmt...) do { } while (0)
-#endif
-
-#define PASS_LIMIT 256
-
-/*
- * We default to IRQ0 for the "no irq" hack. Some
- * machine types want others as well - they're free
- * to redefine this in their header file.
- */
-#define is_real_interrupt(irq) ((irq) != 0)
-
-#define BASE_BAUD 115200
-
-/* Standard COM flags */
-#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
-
-/*
- * SERIAL_PORT_DFNS tells us about built-in ports that have no
- * standard enumeration mechanism. Platforms that can find all
- * serial ports via mechanisms like ACPI or PCI need not supply it.
- */
-#if defined(CONFIG_PLAT_USRV)
-
-#define SERIAL_PORT_DFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS }, /* ttyS1 */
-
-#else /* !CONFIG_PLAT_USRV */
-
-#if defined(CONFIG_SERIAL_M32R_PLDSIO)
-#define SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV, \
- STD_COM_FLAGS }, /* ttyS0 */
-#else
-#define SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, M32R_SIO_OFFSET, M32R_IRQ_SIO0_R, \
- STD_COM_FLAGS }, /* ttyS0 */
-#endif
-
-#endif /* !CONFIG_PLAT_USRV */
-
-static struct old_serial_port old_serial_port[] = {
- SERIAL_PORT_DFNS
-};
-
-#define UART_NR ARRAY_SIZE(old_serial_port)
-
-struct uart_sio_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short rev;
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char lsr_break_flag;
-
- /*
- * We provide a per-port pm hook.
- */
- void (*pm)(struct uart_port *port,
- unsigned int state, unsigned int old);
-};
-
-struct irq_info {
- spinlock_t lock;
- struct list_head *head;
-};
-
-static struct irq_info irq_lists[NR_IRQS];
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial_uart_config uart_config[] = {
- [PORT_UNKNOWN] = {
- .name = "unknown",
- .dfl_xmit_fifo_size = 1,
- .flags = 0,
- },
- [PORT_INDEX(PORT_M32R_SIO)] = {
- .name = "M32RSIO",
- .dfl_xmit_fifo_size = 1,
- .flags = 0,
- },
-};
-
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
-
-#define __sio_in(x) inw((unsigned long)(x))
-#define __sio_out(v,x) outw((v),(unsigned long)(x))
-
-static inline void sio_set_baud_rate(unsigned long baud)
-{
- unsigned short sbaud;
- sbaud = (boot_cpu_data.bus_clock / (baud * 4))-1;
- __sio_out(sbaud, PLD_ESIO0BAUR);
-}
-
-static void sio_reset(void)
-{
- unsigned short tmp;
-
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0CR);
- sio_set_baud_rate(BAUD_RATE);
- __sio_out(0x0300, PLD_ESIO0CR);
- __sio_out(0x0003, PLD_ESIO0CR);
-}
-
-static void sio_init(void)
-{
- unsigned short tmp;
-
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0CR);
- __sio_out(0x0300, PLD_ESIO0CR);
- __sio_out(0x0003, PLD_ESIO0CR);
-}
-
-static void sio_error(int *status)
-{
- printk("SIO0 error[%04x]\n", *status);
- do {
- sio_init();
- } while ((*status = __sio_in(PLD_ESIO0CR)) != 3);
-}
-
-#else /* not CONFIG_SERIAL_M32R_PLDSIO */
-
-#define __sio_in(x) inl(x)
-#define __sio_out(v,x) outl((v),(x))
-
-static inline void sio_set_baud_rate(unsigned long baud)
-{
- unsigned long i, j;
-
- i = boot_cpu_data.bus_clock / (baud * 16);
- j = (boot_cpu_data.bus_clock - (i * baud * 16)) / baud;
- i -= 1;
- j = (j + 1) >> 1;
-
- __sio_out(i, M32R_SIO0_BAUR_PORTL);
- __sio_out(j, M32R_SIO0_RBAUR_PORTL);
-}
-
-static void sio_reset(void)
-{
- __sio_out(0x00000300, M32R_SIO0_CR_PORTL); /* init status */
- __sio_out(0x00000800, M32R_SIO0_MOD1_PORTL); /* 8bit */
- __sio_out(0x00000080, M32R_SIO0_MOD0_PORTL); /* 1stop non */
- sio_set_baud_rate(BAUD_RATE);
- __sio_out(0x00000000, M32R_SIO0_TRCR_PORTL);
- __sio_out(0x00000003, M32R_SIO0_CR_PORTL); /* RXCEN */
-}
-
-static void sio_init(void)
-{
- unsigned int tmp;
-
- tmp = __sio_in(M32R_SIO0_RXB_PORTL);
- tmp = __sio_in(M32R_SIO0_RXB_PORTL);
- tmp = __sio_in(M32R_SIO0_STS_PORTL);
- __sio_out(0x00000003, M32R_SIO0_CR_PORTL);
-}
-
-static void sio_error(int *status)
-{
- printk("SIO0 error[%04x]\n", *status);
- do {
- sio_init();
- } while ((*status = __sio_in(M32R_SIO0_CR_PORTL)) != 3);
-}
-
-#endif /* CONFIG_SERIAL_M32R_PLDSIO */
-
-static unsigned int sio_in(struct uart_sio_port *up, int offset)
-{
- return __sio_in(up->port.iobase + offset);
-}
-
-static void sio_out(struct uart_sio_port *up, int offset, int value)
-{
- __sio_out(value, up->port.iobase + offset);
-}
-
-static unsigned int serial_in(struct uart_sio_port *up, int offset)
-{
- if (!offset)
- return 0;
-
- return __sio_in(offset);
-}
-
-static void serial_out(struct uart_sio_port *up, int offset, int value)
-{
- if (!offset)
- return;
-
- __sio_out(value, offset);
-}
-
-static void m32r_sio_stop_tx(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void m32r_sio_start_tx(struct uart_port *port)
-{
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- struct circ_buf *xmit = &up->port.state->xmit;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- }
- while((serial_in(up, UART_LSR) & UART_EMPTY) != UART_EMPTY);
-#else
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-#endif
-}
-
-static void m32r_sio_stop_rx(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void m32r_sio_enable_ms(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void receive_chars(struct uart_sio_port *up, int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned char ch;
- unsigned char flag;
- int max_count = 256;
-
- do {
- ch = sio_in(up, SIORXB);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE))) {
- /*
- * For statistics only
- */
- if (*status & UART_LSR_BI) {
- *status &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (*status & UART_LSR_PE)
- up->port.icount.parity++;
- else if (*status & UART_LSR_FE)
- up->port.icount.frame++;
- if (*status & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ingored.
- */
- *status &= up->port.read_status_mask;
-
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- *status |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-
- if (*status & UART_LSR_BI) {
- DEBUG_INTR("handling break....");
- flag = TTY_BREAK;
- } else if (*status & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (*status & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0)
- tty_insert_flip_char(tty, ch, flag);
-
- if (*status & UART_LSR_OE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
- ignore_char:
- *status = serial_in(up, UART_LSR);
- } while ((*status & UART_LSR_DR) && (max_count-- > 0));
- tty_flip_buffer_push(tty);
-}
-
-static void transmit_chars(struct uart_sio_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
-#ifndef CONFIG_SERIAL_M32R_PLDSIO /* XXX */
- serial_out(up, UART_TX, up->port.x_char);
-#endif
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- m32r_sio_stop_tx(&up->port);
- return;
- }
-
- count = up->port.fifosize;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- while (!(serial_in(up, UART_LSR) & UART_LSR_THRE));
-
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- DEBUG_INTR("THRE...");
-
- if (uart_circ_empty(xmit))
- m32r_sio_stop_tx(&up->port);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline void m32r_sio_handle_port(struct uart_sio_port *up,
- unsigned int status)
-{
- DEBUG_INTR("status = %x...", status);
-
- if (status & 0x04)
- receive_chars(up, &status);
- if (status & 0x01)
- transmit_chars(up);
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts. (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id)
-{
- struct irq_info *i = dev_id;
- struct list_head *l, *end = NULL;
- int pass_counter = 0;
-
- DEBUG_INTR("m32r_sio_interrupt(%d)...", irq);
-
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
-// if (irq == PLD_IRQ_SIO0_SND)
-// irq = PLD_IRQ_SIO0_RCV;
-#else
- if (irq == M32R_IRQ_SIO0_S)
- irq = M32R_IRQ_SIO0_R;
-#endif
-
- spin_lock(&i->lock);
-
- l = i->head;
- do {
- struct uart_sio_port *up;
- unsigned int sts;
-
- up = list_entry(l, struct uart_sio_port, list);
-
- sts = sio_in(up, SIOSTS);
- if (sts & 0x5) {
- spin_lock(&up->port.lock);
- m32r_sio_handle_port(up, sts);
- spin_unlock(&up->port.lock);
-
- end = NULL;
- } else if (end == NULL)
- end = l;
-
- l = l->next;
-
- if (l == i->head && pass_counter++ > PASS_LIMIT) {
- if (sts & 0xe0)
- sio_error(&sts);
- break;
- }
- } while (l != end);
-
- spin_unlock(&i->lock);
-
- DEBUG_INTR("end.\n");
-
- return IRQ_HANDLED;
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning. Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_sio_port *up)
-{
- spin_lock_irq(&i->lock);
-
- if (!list_empty(i->head)) {
- if (i->head == &up->list)
- i->head = i->head->next;
- list_del(&up->list);
- } else {
- BUG_ON(i->head != &up->list);
- i->head = NULL;
- }
-
- spin_unlock_irq(&i->lock);
-}
-
-static int serial_link_irq_chain(struct uart_sio_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
- int ret, irq_flags = 0;
-
- spin_lock_irq(&i->lock);
-
- if (i->head) {
- list_add(&up->list, i->head);
- spin_unlock_irq(&i->lock);
-
- ret = 0;
- } else {
- INIT_LIST_HEAD(&up->list);
- i->head = &up->list;
- spin_unlock_irq(&i->lock);
-
- ret = request_irq(up->port.irq, m32r_sio_interrupt,
- irq_flags, "SIO0-RX", i);
- ret |= request_irq(up->port.irq + 1, m32r_sio_interrupt,
- irq_flags, "SIO0-TX", i);
- if (ret < 0)
- serial_do_unlink(i, up);
- }
-
- return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_sio_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
-
- BUG_ON(i->head == NULL);
-
- if (list_empty(i->head)) {
- free_irq(up->port.irq, i);
- free_irq(up->port.irq + 1, i);
- }
-
- serial_do_unlink(i, up);
-}
-
-/*
- * This function is used to handle ports that do not have an interrupt.
- */
-static void m32r_sio_timeout(unsigned long data)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)data;
- unsigned int timeout;
- unsigned int sts;
-
- sts = sio_in(up, SIOSTS);
- if (sts & 0x5) {
- spin_lock(&up->port.lock);
- m32r_sio_handle_port(up, sts);
- spin_unlock(&up->port.lock);
- }
-
- timeout = up->port.timeout;
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
- mod_timer(&up->timer, jiffies + timeout);
-}
-
-static unsigned int m32r_sio_tx_empty(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int m32r_sio_get_mctrl(struct uart_port *port)
-{
- return 0;
-}
-
-static void m32r_sio_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-
-}
-
-static void m32r_sio_break_ctl(struct uart_port *port, int break_state)
-{
-
-}
-
-static int m32r_sio_startup(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- int retval;
-
- sio_init();
-
- /*
- * If the "interrupt" for this port doesn't correspond with any
- * hardware interrupt, we use a timer-based system. The original
- * driver used to do this with IRQ0.
- */
- if (!is_real_interrupt(up->port.irq)) {
- unsigned int timeout = up->port.timeout;
-
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies + timeout);
- } else {
- retval = serial_link_irq_chain(up);
- if (retval)
- return retval;
- }
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- * - M32R_SIO: 0x0c
- * - M32R_PLDSIO: 0x04
- */
- up->ier = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
- sio_out(up, SIOTRCR, up->ier);
-
- /*
- * And clear the interrupt registers again for luck.
- */
- sio_reset();
-
- return 0;
-}
-
-static void m32r_sio_shutdown(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- sio_out(up, SIOTRCR, 0);
-
- /*
- * Disable break condition and FIFOs
- */
-
- sio_init();
-
- if (!is_real_interrupt(up->port.irq))
- del_timer_sync(&up->timer);
- else
- serial_unlink_irq_chain(up);
-}
-
-static unsigned int m32r_sio_get_divisor(struct uart_port *port,
- unsigned int baud)
-{
- return uart_get_divisor(port, baud);
-}
-
-static void m32r_sio_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- unsigned char cval = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (termios->c_cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- /*
- * Ask the core to calculate the divisor for us.
- */
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4);
-#else
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-#endif
- quot = m32r_sio_get_divisor(port, baud);
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- sio_set_baud_rate(baud);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
-
- serial_out(up, UART_IER, up->ier);
-
- up->lcr = cval; /* Save LCR */
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void m32r_sio_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- if (up->pm)
- up->pm(port, state, oldstate);
-}
-
-/*
- * Resource handling. This is complicated by the fact that resources
- * depend on the port type. Maybe we should be claiming the standard
- * 8250 ports, and then trying to get other resources as necessary?
- */
-static int
-m32r_sio_request_std_resource(struct uart_sio_port *up, struct resource **res)
-{
- unsigned int size = 8 << up->port.regshift;
-#ifndef CONFIG_SERIAL_M32R_PLDSIO
- unsigned long start;
-#endif
- int ret = 0;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
- *res = request_mem_region(up->port.mapbase, size, "serial");
-#else
- start = up->port.mapbase;
- *res = request_mem_region(start, size, "serial");
-#endif
- if (!*res)
- ret = -EBUSY;
- }
- break;
-
- case UPIO_PORT:
- *res = request_region(up->port.iobase, size, "serial");
- if (!*res)
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-static void m32r_sio_release_port(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- unsigned long start, offset = 0, size = 0;
-
- size <<= up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
- /*
- * Unmap the area.
- */
- iounmap(up->port.membase);
- up->port.membase = NULL;
-
- start = up->port.mapbase;
-
- if (size)
- release_mem_region(start + offset, size);
- release_mem_region(start, 8 << up->port.regshift);
- }
- break;
-
- case UPIO_PORT:
- start = up->port.iobase;
-
- if (size)
- release_region(start + offset, size);
- release_region(start + offset, 8 << up->port.regshift);
- break;
-
- default:
- break;
- }
-}
-
-static int m32r_sio_request_port(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- struct resource *res = NULL;
- int ret = 0;
-
- ret = m32r_sio_request_std_resource(up, &res);
-
- /*
- * If we have a mapbase, then request that as well.
- */
- if (ret == 0 && up->port.flags & UPF_IOREMAP) {
- int size = res->end - res->start + 1;
-
- up->port.membase = ioremap(up->port.mapbase, size);
- if (!up->port.membase)
- ret = -ENOMEM;
- }
-
- if (ret < 0) {
- if (res)
- release_resource(res);
- }
-
- return ret;
-}
-
-static void m32r_sio_config_port(struct uart_port *port, int flags)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1);
- up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int
-m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->irq >= nr_irqs || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type >= ARRAY_SIZE(uart_config))
- return -EINVAL;
- return 0;
-}
-
-static const char *
-m32r_sio_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static struct uart_ops m32r_sio_pops = {
- .tx_empty = m32r_sio_tx_empty,
- .set_mctrl = m32r_sio_set_mctrl,
- .get_mctrl = m32r_sio_get_mctrl,
- .stop_tx = m32r_sio_stop_tx,
- .start_tx = m32r_sio_start_tx,
- .stop_rx = m32r_sio_stop_rx,
- .enable_ms = m32r_sio_enable_ms,
- .break_ctl = m32r_sio_break_ctl,
- .startup = m32r_sio_startup,
- .shutdown = m32r_sio_shutdown,
- .set_termios = m32r_sio_set_termios,
- .pm = m32r_sio_pm,
- .type = m32r_sio_type,
- .release_port = m32r_sio_release_port,
- .request_port = m32r_sio_request_port,
- .config_port = m32r_sio_config_port,
- .verify_port = m32r_sio_verify_port,
-};
-
-static struct uart_sio_port m32r_sio_ports[UART_NR];
-
-static void __init m32r_sio_init_ports(void)
-{
- struct uart_sio_port *up;
- static int first = 1;
- int i;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0, up = m32r_sio_ports; i < ARRAY_SIZE(old_serial_port);
- i++, up++) {
- up->port.iobase = old_serial_port[i].port;
- up->port.irq = irq_canonicalize(old_serial_port[i].irq);
- up->port.uartclk = old_serial_port[i].baud_base * 16;
- up->port.flags = old_serial_port[i].flags;
- up->port.membase = old_serial_port[i].iomem_base;
- up->port.iotype = old_serial_port[i].io_type;
- up->port.regshift = old_serial_port[i].iomem_reg_shift;
- up->port.ops = &m32r_sio_pops;
- }
-}
-
-static void __init m32r_sio_register_ports(struct uart_driver *drv)
-{
- int i;
-
- m32r_sio_init_ports();
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_sio_port *up = &m32r_sio_ports[i];
-
- up->port.line = i;
- up->port.ops = &m32r_sio_pops;
- init_timer(&up->timer);
- up->timer.function = m32r_sio_timeout;
-
- /*
- * ALPHA_KLUDGE_MCR needs to be killed.
- */
- up->mcr_mask = ~ALPHA_KLUDGE_MCR;
- up->mcr_force = ALPHA_KLUDGE_MCR;
-
- uart_add_one_port(drv, &up->port);
- }
-}
-
-#ifdef CONFIG_SERIAL_M32R_SIO_CONSOLE
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_sio_port *up)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = sio_in(up, SIOSTS);
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & UART_EMPTY) != UART_EMPTY);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout)
- udelay(1);
- }
-}
-
-static void m32r_sio_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- wait_for_xmitr(up);
- sio_out(up, SIOTXB, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void m32r_sio_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_sio_port *up = &m32r_sio_ports[co->index];
- unsigned int ier;
-
- /*
- * First save the UER then disable the interrupts
- */
- ier = sio_in(up, SIOTRCR);
- sio_out(up, SIOTRCR, 0);
-
- uart_console_write(&up->port, s, count, m32r_sio_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- sio_out(up, SIOTRCR, ier);
-}
-
-static int __init m32r_sio_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- port = &m32r_sio_ports[co->index].port;
-
- /*
- * Temporary fix.
- */
- spin_lock_init(&port->lock);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver m32r_sio_reg;
-static struct console m32r_sio_console = {
- .name = "ttyS",
- .write = m32r_sio_console_write,
- .device = uart_console_device,
- .setup = m32r_sio_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &m32r_sio_reg,
-};
-
-static int __init m32r_sio_console_init(void)
-{
- sio_reset();
- sio_init();
- m32r_sio_init_ports();
- register_console(&m32r_sio_console);
- return 0;
-}
-console_initcall(m32r_sio_console_init);
-
-#define M32R_SIO_CONSOLE &m32r_sio_console
-#else
-#define M32R_SIO_CONSOLE NULL
-#endif
-
-static struct uart_driver m32r_sio_reg = {
- .owner = THIS_MODULE,
- .driver_name = "sio",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = UART_NR,
- .cons = M32R_SIO_CONSOLE,
-};
-
-/**
- * m32r_sio_suspend_port - suspend one serial port
- * @line: serial line number
- *
- * Suspend one serial port.
- */
-void m32r_sio_suspend_port(int line)
-{
- uart_suspend_port(&m32r_sio_reg, &m32r_sio_ports[line].port);
-}
-
-/**
- * m32r_sio_resume_port - resume one serial port
- * @line: serial line number
- *
- * Resume one serial port.
- */
-void m32r_sio_resume_port(int line)
-{
- uart_resume_port(&m32r_sio_reg, &m32r_sio_ports[line].port);
-}
-
-static int __init m32r_sio_init(void)
-{
- int ret, i;
-
- printk(KERN_INFO "Serial: M32R SIO driver\n");
-
- for (i = 0; i < nr_irqs; i++)
- spin_lock_init(&irq_lists[i].lock);
-
- ret = uart_register_driver(&m32r_sio_reg);
- if (ret >= 0)
- m32r_sio_register_ports(&m32r_sio_reg);
-
- return ret;
-}
-
-static void __exit m32r_sio_exit(void)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++)
- uart_remove_one_port(&m32r_sio_reg, &m32r_sio_ports[i].port);
-
- uart_unregister_driver(&m32r_sio_reg);
-}
-
-module_init(m32r_sio_init);
-module_exit(m32r_sio_exit);
-
-EXPORT_SYMBOL(m32r_sio_suspend_port);
-EXPORT_SYMBOL(m32r_sio_resume_port);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic M32R SIO serial driver");
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h
deleted file mode 100644
index e9b7e11793b1..000000000000
--- a/drivers/serial/m32r_sio.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * m32r_sio.h
- *
- * Driver for M32R serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- * Based on drivers/serial/8250.h.
- *
- * Copyright (C) 2001 Russell King.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
- *
- * 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.
- */
-
-
-struct m32r_sio_probe {
- struct module *owner;
- int (*pci_init_one)(struct pci_dev *dev);
- void (*pci_remove_one)(struct pci_dev *dev);
- void (*pnp_init)(void);
-};
-
-int m32r_sio_register_probe(struct m32r_sio_probe *probe);
-void m32r_sio_unregister_probe(struct m32r_sio_probe *probe);
-void m32r_sio_get_irq_map(unsigned int *map);
-void m32r_sio_suspend_port(int line);
-void m32r_sio_resume_port(int line);
-
-struct old_serial_port {
- unsigned int uart;
- unsigned int baud_base;
- unsigned int port;
- unsigned int irq;
- unsigned int flags;
- unsigned char io_type;
- unsigned char __iomem *iomem_base;
- unsigned short iomem_reg_shift;
-};
-
-#define _INLINE_ inline
-
-#define PROBE_RSA (1 << 0)
-#define PROBE_ANY (~0)
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
diff --git a/drivers/serial/m32r_sio_reg.h b/drivers/serial/m32r_sio_reg.h
deleted file mode 100644
index 4671473793e3..000000000000
--- a/drivers/serial/m32r_sio_reg.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * m32r_sio_reg.h
- *
- * Copyright (C) 1992, 1994 by Theodore Ts'o.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
- *
- * Redistribution of this file is permitted under the terms of the GNU
- * Public License (GPL)
- *
- * These are the UART port assignments, expressed as offsets from the base
- * register. These assignments should hold for any serial port based on
- * a 8250, 16450, or 16550(A).
- */
-
-#ifndef _M32R_SIO_REG_H
-#define _M32R_SIO_REG_H
-
-
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
-
-#define SIOCR 0x000
-#define SIOMOD0 0x002
-#define SIOMOD1 0x004
-#define SIOSTS 0x006
-#define SIOTRCR 0x008
-#define SIOBAUR 0x00a
-// #define SIORBAUR 0x018
-#define SIOTXB 0x00c
-#define SIORXB 0x00e
-
-#define UART_RX ((unsigned long) PLD_ESIO0RXB)
- /* In: Receive buffer (DLAB=0) */
-#define UART_TX ((unsigned long) PLD_ESIO0TXB)
- /* Out: Transmit buffer (DLAB=0) */
-#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
-#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
- * In: Fifo count
- * Out: Fifo custom trigger levels
- * XR16C85x only */
-
-#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
-#define UART_IER ((unsigned long) PLD_ESIO0INTCR)
- /* Out: Interrupt Enable Register */
-#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
- * XR16C85x only */
-
-#define UART_IIR 0 /* In: Interrupt ID Register */
-#define UART_FCR 0 /* Out: FIFO Control Register */
-#define UART_EFR 0 /* I/O: Extended Features Register */
- /* (DLAB=1, 16C660 only) */
-
-#define UART_LCR 0 /* Out: Line Control Register */
-#define UART_MCR 0 /* Out: Modem Control Register */
-#define UART_LSR ((unsigned long) PLD_ESIO0STS)
- /* In: Line Status Register */
-#define UART_MSR 0 /* In: Modem Status Register */
-#define UART_SCR 0 /* I/O: Scratch Register */
-#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
- * FCTR bit 6 selects SCR or EMSR
- * XR16c85x only */
-
-#else /* not CONFIG_SERIAL_M32R_PLDSIO */
-
-#define SIOCR 0x000
-#define SIOMOD0 0x004
-#define SIOMOD1 0x008
-#define SIOSTS 0x00c
-#define SIOTRCR 0x010
-#define SIOBAUR 0x014
-#define SIORBAUR 0x018
-#define SIOTXB 0x01c
-#define SIORXB 0x020
-
-#define UART_RX M32R_SIO0_RXB_PORTL /* In: Receive buffer (DLAB=0) */
-#define UART_TX M32R_SIO0_TXB_PORTL /* Out: Transmit buffer (DLAB=0) */
-#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
-#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
- * In: Fifo count
- * Out: Fifo custom trigger levels
- * XR16C85x only */
-
-#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
-#define UART_IER M32R_SIO0_TRCR_PORTL /* Out: Interrupt Enable Register */
-#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
- * XR16C85x only */
-
-#define UART_IIR 0 /* In: Interrupt ID Register */
-#define UART_FCR 0 /* Out: FIFO Control Register */
-#define UART_EFR 0 /* I/O: Extended Features Register */
- /* (DLAB=1, 16C660 only) */
-
-#define UART_LCR 0 /* Out: Line Control Register */
-#define UART_MCR 0 /* Out: Modem Control Register */
-#define UART_LSR M32R_SIO0_STS_PORTL /* In: Line Status Register */
-#define UART_MSR 0 /* In: Modem Status Register */
-#define UART_SCR 0 /* I/O: Scratch Register */
-#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
- * FCTR bit 6 selects SCR or EMSR
- * XR16c85x only */
-
-#endif /* CONFIG_SERIAL_M32R_PLDSIO */
-
-#define UART_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- * These are the definitions for the Line Control Register
- *
- * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
- * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
- */
-#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
-#define UART_LCR_SBC 0x40 /* Set break control */
-#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
-#define UART_LCR_EPAR 0x10 /* Even parity select */
-#define UART_LCR_PARITY 0x08 /* Parity Enable */
-#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
-#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
-#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
-#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
-#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
-
-/*
- * These are the definitions for the Line Status Register
- */
-#define UART_LSR_TEMT 0x02 /* Transmitter empty */
-#define UART_LSR_THRE 0x01 /* Transmit-hold-register empty */
-#define UART_LSR_BI 0x00 /* Break interrupt indicator */
-#define UART_LSR_FE 0x80 /* Frame error indicator */
-#define UART_LSR_PE 0x40 /* Parity error indicator */
-#define UART_LSR_OE 0x20 /* Overrun error indicator */
-#define UART_LSR_DR 0x04 /* Receiver data ready */
-
-/*
- * These are the definitions for the Interrupt Identification Register
- */
-#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
-#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
-
-#define UART_IIR_MSI 0x00 /* Modem status interrupt */
-#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
-#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
-#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
-
-/*
- * These are the definitions for the Interrupt Enable Register
- */
-#define UART_IER_MSI 0x00 /* Enable Modem status interrupt */
-#define UART_IER_RLSI 0x08 /* Enable receiver line status interrupt */
-#define UART_IER_THRI 0x03 /* Enable Transmitter holding register int. */
-#define UART_IER_RDI 0x04 /* Enable receiver data interrupt */
-
-#endif /* _M32R_SIO_REG_H */
diff --git a/drivers/serial/max3100.c b/drivers/serial/max3100.c
deleted file mode 100644
index beb1afa27d8d..000000000000
--- a/drivers/serial/max3100.c
+++ /dev/null
@@ -1,926 +0,0 @@
-/*
- *
- * Copyright (C) 2008 Christian Pellegrin <chripell@evolware.org>
- *
- * 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.
- *
- *
- * Notes: the MAX3100 doesn't provide an interrupt on CTS so we have
- * to use polling for flow control. TX empty IRQ is unusable, since
- * writing conf clears FIFO buffer and we cannot have this interrupt
- * always asking us for attention.
- *
- * Example platform data:
-
- static struct plat_max3100 max3100_plat_data = {
- .loopback = 0,
- .crystal = 0,
- .poll_time = 100,
- };
-
- static struct spi_board_info spi_board_info[] = {
- {
- .modalias = "max3100",
- .platform_data = &max3100_plat_data,
- .irq = IRQ_EINT12,
- .max_speed_hz = 5*1000*1000,
- .chip_select = 0,
- },
- };
-
- * The initial minor number is 209 in the low-density serial port:
- * mknod /dev/ttyMAX0 c 204 209
- */
-
-#define MAX3100_MAJOR 204
-#define MAX3100_MINOR 209
-/* 4 MAX3100s should be enough for everyone */
-#define MAX_MAX3100 4
-
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-
-#include <linux/serial_max3100.h>
-
-#define MAX3100_C (1<<14)
-#define MAX3100_D (0<<14)
-#define MAX3100_W (1<<15)
-#define MAX3100_RX (0<<15)
-
-#define MAX3100_WC (MAX3100_W | MAX3100_C)
-#define MAX3100_RC (MAX3100_RX | MAX3100_C)
-#define MAX3100_WD (MAX3100_W | MAX3100_D)
-#define MAX3100_RD (MAX3100_RX | MAX3100_D)
-#define MAX3100_CMD (3 << 14)
-
-#define MAX3100_T (1<<14)
-#define MAX3100_R (1<<15)
-
-#define MAX3100_FEN (1<<13)
-#define MAX3100_SHDN (1<<12)
-#define MAX3100_TM (1<<11)
-#define MAX3100_RM (1<<10)
-#define MAX3100_PM (1<<9)
-#define MAX3100_RAM (1<<8)
-#define MAX3100_IR (1<<7)
-#define MAX3100_ST (1<<6)
-#define MAX3100_PE (1<<5)
-#define MAX3100_L (1<<4)
-#define MAX3100_BAUD (0xf)
-
-#define MAX3100_TE (1<<10)
-#define MAX3100_RAFE (1<<10)
-#define MAX3100_RTS (1<<9)
-#define MAX3100_CTS (1<<9)
-#define MAX3100_PT (1<<8)
-#define MAX3100_DATA (0xff)
-
-#define MAX3100_RT (MAX3100_R | MAX3100_T)
-#define MAX3100_RTC (MAX3100_RT | MAX3100_CTS | MAX3100_RAFE)
-
-/* the following simulate a status reg for ignore_status_mask */
-#define MAX3100_STATUS_PE 1
-#define MAX3100_STATUS_FE 2
-#define MAX3100_STATUS_OE 4
-
-struct max3100_port {
- struct uart_port port;
- struct spi_device *spi;
-
- int cts; /* last CTS received for flow ctrl */
- int tx_empty; /* last TX empty bit */
-
- spinlock_t conf_lock; /* shared data */
- int conf_commit; /* need to make changes */
- int conf; /* configuration for the MAX31000
- * (bits 0-7, bits 8-11 are irqs) */
- int rts_commit; /* need to change rts */
- int rts; /* rts status */
- int baud; /* current baud rate */
-
- int parity; /* keeps track if we should send parity */
-#define MAX3100_PARITY_ON 1
-#define MAX3100_PARITY_ODD 2
-#define MAX3100_7BIT 4
- int rx_enabled; /* if we should rx chars */
-
- int irq; /* irq assigned to the max3100 */
-
- int minor; /* minor number */
- int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */
- int loopback; /* 1 if we are in loopback mode */
-
- /* for handling irqs: need workqueue since we do spi_sync */
- struct workqueue_struct *workqueue;
- struct work_struct work;
- /* set to 1 to make the workhandler exit as soon as possible */
- int force_end_work;
- /* need to know we are suspending to avoid deadlock on workqueue */
- int suspending;
-
- /* hook for suspending MAX3100 via dedicated pin */
- void (*max3100_hw_suspend) (int suspend);
-
- /* poll time (in ms) for ctrl lines */
- int poll_time;
- /* and its timer */
- struct timer_list timer;
-};
-
-static struct max3100_port *max3100s[MAX_MAX3100]; /* the chips */
-static DEFINE_MUTEX(max3100s_lock); /* race on probe */
-
-static int max3100_do_parity(struct max3100_port *s, u16 c)
-{
- int parity;
-
- if (s->parity & MAX3100_PARITY_ODD)
- parity = 1;
- else
- parity = 0;
-
- if (s->parity & MAX3100_7BIT)
- c &= 0x7f;
- else
- c &= 0xff;
-
- parity = parity ^ (hweight8(c) & 1);
- return parity;
-}
-
-static int max3100_check_parity(struct max3100_port *s, u16 c)
-{
- return max3100_do_parity(s, c) == ((c >> 8) & 1);
-}
-
-static void max3100_calc_parity(struct max3100_port *s, u16 *c)
-{
- if (s->parity & MAX3100_7BIT)
- *c &= 0x7f;
- else
- *c &= 0xff;
-
- if (s->parity & MAX3100_PARITY_ON)
- *c |= max3100_do_parity(s, *c) << 8;
-}
-
-static void max3100_work(struct work_struct *w);
-
-static void max3100_dowork(struct max3100_port *s)
-{
- if (!s->force_end_work && !work_pending(&s->work) &&
- !freezing(current) && !s->suspending)
- queue_work(s->workqueue, &s->work);
-}
-
-static void max3100_timeout(unsigned long data)
-{
- struct max3100_port *s = (struct max3100_port *)data;
-
- if (s->port.state) {
- max3100_dowork(s);
- mod_timer(&s->timer, jiffies + s->poll_time);
- }
-}
-
-static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx)
-{
- struct spi_message message;
- u16 etx, erx;
- int status;
- struct spi_transfer tran = {
- .tx_buf = &etx,
- .rx_buf = &erx,
- .len = 2,
- };
-
- etx = cpu_to_be16(tx);
- spi_message_init(&message);
- spi_message_add_tail(&tran, &message);
- status = spi_sync(s->spi, &message);
- if (status) {
- dev_warn(&s->spi->dev, "error while calling spi_sync\n");
- return -EIO;
- }
- *rx = be16_to_cpu(erx);
- s->tx_empty = (*rx & MAX3100_T) > 0;
- dev_dbg(&s->spi->dev, "%04x - %04x\n", tx, *rx);
- return 0;
-}
-
-static int max3100_handlerx(struct max3100_port *s, u16 rx)
-{
- unsigned int ch, flg, status = 0;
- int ret = 0, cts;
-
- if (rx & MAX3100_R && s->rx_enabled) {
- dev_dbg(&s->spi->dev, "%s\n", __func__);
- ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff);
- if (rx & MAX3100_RAFE) {
- s->port.icount.frame++;
- flg = TTY_FRAME;
- status |= MAX3100_STATUS_FE;
- } else {
- if (s->parity & MAX3100_PARITY_ON) {
- if (max3100_check_parity(s, rx)) {
- s->port.icount.rx++;
- flg = TTY_NORMAL;
- } else {
- s->port.icount.parity++;
- flg = TTY_PARITY;
- status |= MAX3100_STATUS_PE;
- }
- } else {
- s->port.icount.rx++;
- flg = TTY_NORMAL;
- }
- }
- uart_insert_char(&s->port, status, MAX3100_STATUS_OE, ch, flg);
- ret = 1;
- }
-
- cts = (rx & MAX3100_CTS) > 0;
- if (s->cts != cts) {
- s->cts = cts;
- uart_handle_cts_change(&s->port, cts ? TIOCM_CTS : 0);
- }
-
- return ret;
-}
-
-static void max3100_work(struct work_struct *w)
-{
- struct max3100_port *s = container_of(w, struct max3100_port, work);
- int rxchars;
- u16 tx, rx;
- int conf, cconf, rts, crts;
- struct circ_buf *xmit = &s->port.state->xmit;
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- rxchars = 0;
- do {
- spin_lock(&s->conf_lock);
- conf = s->conf;
- cconf = s->conf_commit;
- s->conf_commit = 0;
- rts = s->rts;
- crts = s->rts_commit;
- s->rts_commit = 0;
- spin_unlock(&s->conf_lock);
- if (cconf)
- max3100_sr(s, MAX3100_WC | conf, &rx);
- if (crts) {
- max3100_sr(s, MAX3100_WD | MAX3100_TE |
- (s->rts ? MAX3100_RTS : 0), &rx);
- rxchars += max3100_handlerx(s, rx);
- }
-
- max3100_sr(s, MAX3100_RD, &rx);
- rxchars += max3100_handlerx(s, rx);
-
- if (rx & MAX3100_T) {
- tx = 0xffff;
- if (s->port.x_char) {
- tx = s->port.x_char;
- s->port.icount.tx++;
- s->port.x_char = 0;
- } else if (!uart_circ_empty(xmit) &&
- !uart_tx_stopped(&s->port)) {
- tx = xmit->buf[xmit->tail];
- xmit->tail = (xmit->tail + 1) &
- (UART_XMIT_SIZE - 1);
- s->port.icount.tx++;
- }
- if (tx != 0xffff) {
- max3100_calc_parity(s, &tx);
- tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0);
- max3100_sr(s, tx, &rx);
- rxchars += max3100_handlerx(s, rx);
- }
- }
-
- if (rxchars > 16 && s->port.state->port.tty != NULL) {
- tty_flip_buffer_push(s->port.state->port.tty);
- rxchars = 0;
- }
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&s->port);
-
- } while (!s->force_end_work &&
- !freezing(current) &&
- ((rx & MAX3100_R) ||
- (!uart_circ_empty(xmit) &&
- !uart_tx_stopped(&s->port))));
-
- if (rxchars > 0 && s->port.state->port.tty != NULL)
- tty_flip_buffer_push(s->port.state->port.tty);
-}
-
-static irqreturn_t max3100_irq(int irqno, void *dev_id)
-{
- struct max3100_port *s = dev_id;
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- max3100_dowork(s);
- return IRQ_HANDLED;
-}
-
-static void max3100_enable_ms(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- if (s->poll_time > 0)
- mod_timer(&s->timer, jiffies);
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-}
-
-static void max3100_start_tx(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- max3100_dowork(s);
-}
-
-static void max3100_stop_rx(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- s->rx_enabled = 0;
- spin_lock(&s->conf_lock);
- s->conf &= ~MAX3100_RM;
- s->conf_commit = 1;
- spin_unlock(&s->conf_lock);
- max3100_dowork(s);
-}
-
-static unsigned int max3100_tx_empty(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- /* may not be truly up-to-date */
- max3100_dowork(s);
- return s->tx_empty;
-}
-
-static unsigned int max3100_get_mctrl(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- /* may not be truly up-to-date */
- max3100_dowork(s);
- /* always assert DCD and DSR since these lines are not wired */
- return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR;
-}
-
-static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
- int rts;
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- rts = (mctrl & TIOCM_RTS) > 0;
-
- spin_lock(&s->conf_lock);
- if (s->rts != rts) {
- s->rts = rts;
- s->rts_commit = 1;
- max3100_dowork(s);
- }
- spin_unlock(&s->conf_lock);
-}
-
-static void
-max3100_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
- int baud = 0;
- unsigned cflag;
- u32 param_new, param_mask, parity = 0;
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- cflag = termios->c_cflag;
- param_new = 0;
- param_mask = 0;
-
- baud = tty_termios_baud_rate(termios);
- param_new = s->conf & MAX3100_BAUD;
- switch (baud) {
- case 300:
- if (s->crystal)
- baud = s->baud;
- else
- param_new = 15;
- break;
- case 600:
- param_new = 14 + s->crystal;
- break;
- case 1200:
- param_new = 13 + s->crystal;
- break;
- case 2400:
- param_new = 12 + s->crystal;
- break;
- case 4800:
- param_new = 11 + s->crystal;
- break;
- case 9600:
- param_new = 10 + s->crystal;
- break;
- case 19200:
- param_new = 9 + s->crystal;
- break;
- case 38400:
- param_new = 8 + s->crystal;
- break;
- case 57600:
- param_new = 1 + s->crystal;
- break;
- case 115200:
- param_new = 0 + s->crystal;
- break;
- case 230400:
- if (s->crystal)
- param_new = 0;
- else
- baud = s->baud;
- break;
- default:
- baud = s->baud;
- }
- tty_termios_encode_baud_rate(termios, baud, baud);
- s->baud = baud;
- param_mask |= MAX3100_BAUD;
-
- if ((cflag & CSIZE) == CS8) {
- param_new &= ~MAX3100_L;
- parity &= ~MAX3100_7BIT;
- } else {
- param_new |= MAX3100_L;
- parity |= MAX3100_7BIT;
- cflag = (cflag & ~CSIZE) | CS7;
- }
- param_mask |= MAX3100_L;
-
- if (cflag & CSTOPB)
- param_new |= MAX3100_ST;
- else
- param_new &= ~MAX3100_ST;
- param_mask |= MAX3100_ST;
-
- if (cflag & PARENB) {
- param_new |= MAX3100_PE;
- parity |= MAX3100_PARITY_ON;
- } else {
- param_new &= ~MAX3100_PE;
- parity &= ~MAX3100_PARITY_ON;
- }
- param_mask |= MAX3100_PE;
-
- if (cflag & PARODD)
- parity |= MAX3100_PARITY_ODD;
- else
- parity &= ~MAX3100_PARITY_ODD;
-
- /* mask termios capabilities we don't support */
- cflag &= ~CMSPAR;
- termios->c_cflag = cflag;
-
- s->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- s->port.ignore_status_mask |=
- MAX3100_STATUS_PE | MAX3100_STATUS_FE |
- MAX3100_STATUS_OE;
-
- /* we are sending char from a workqueue so enable */
- s->port.state->port.tty->low_latency = 1;
-
- if (s->poll_time > 0)
- del_timer_sync(&s->timer);
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_lock(&s->conf_lock);
- s->conf = (s->conf & ~param_mask) | (param_new & param_mask);
- s->conf_commit = 1;
- s->parity = parity;
- spin_unlock(&s->conf_lock);
- max3100_dowork(s);
-
- if (UART_ENABLE_MS(&s->port, termios->c_cflag))
- max3100_enable_ms(&s->port);
-}
-
-static void max3100_shutdown(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- if (s->suspending)
- return;
-
- s->force_end_work = 1;
-
- if (s->poll_time > 0)
- del_timer_sync(&s->timer);
-
- if (s->workqueue) {
- flush_workqueue(s->workqueue);
- destroy_workqueue(s->workqueue);
- s->workqueue = NULL;
- }
- if (s->irq)
- free_irq(s->irq, s);
-
- /* set shutdown mode to save power */
- if (s->max3100_hw_suspend)
- s->max3100_hw_suspend(1);
- else {
- u16 tx, rx;
-
- tx = MAX3100_WC | MAX3100_SHDN;
- max3100_sr(s, tx, &rx);
- }
-}
-
-static int max3100_startup(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
- char b[12];
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- s->conf = MAX3100_RM;
- s->baud = s->crystal ? 230400 : 115200;
- s->rx_enabled = 1;
-
- if (s->suspending)
- return 0;
-
- s->force_end_work = 0;
- s->parity = 0;
- s->rts = 0;
-
- sprintf(b, "max3100-%d", s->minor);
- s->workqueue = create_freezeable_workqueue(b);
- if (!s->workqueue) {
- dev_warn(&s->spi->dev, "cannot create workqueue\n");
- return -EBUSY;
- }
- INIT_WORK(&s->work, max3100_work);
-
- if (request_irq(s->irq, max3100_irq,
- IRQF_TRIGGER_FALLING, "max3100", s) < 0) {
- dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq);
- s->irq = 0;
- destroy_workqueue(s->workqueue);
- s->workqueue = NULL;
- return -EBUSY;
- }
-
- if (s->loopback) {
- u16 tx, rx;
- tx = 0x4001;
- max3100_sr(s, tx, &rx);
- }
-
- if (s->max3100_hw_suspend)
- s->max3100_hw_suspend(0);
- s->conf_commit = 1;
- max3100_dowork(s);
- /* wait for clock to settle */
- msleep(50);
-
- max3100_enable_ms(&s->port);
-
- return 0;
-}
-
-static const char *max3100_type(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- return s->port.type == PORT_MAX3100 ? "MAX3100" : NULL;
-}
-
-static void max3100_release_port(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-}
-
-static void max3100_config_port(struct uart_port *port, int flags)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- if (flags & UART_CONFIG_TYPE)
- s->port.type = PORT_MAX3100;
-}
-
-static int max3100_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
- int ret = -EINVAL;
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100)
- ret = 0;
- return ret;
-}
-
-static void max3100_stop_tx(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-}
-
-static int max3100_request_port(struct uart_port *port)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
- return 0;
-}
-
-static void max3100_break_ctl(struct uart_port *port, int break_state)
-{
- struct max3100_port *s = container_of(port,
- struct max3100_port,
- port);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-}
-
-static struct uart_ops max3100_ops = {
- .tx_empty = max3100_tx_empty,
- .set_mctrl = max3100_set_mctrl,
- .get_mctrl = max3100_get_mctrl,
- .stop_tx = max3100_stop_tx,
- .start_tx = max3100_start_tx,
- .stop_rx = max3100_stop_rx,
- .enable_ms = max3100_enable_ms,
- .break_ctl = max3100_break_ctl,
- .startup = max3100_startup,
- .shutdown = max3100_shutdown,
- .set_termios = max3100_set_termios,
- .type = max3100_type,
- .release_port = max3100_release_port,
- .request_port = max3100_request_port,
- .config_port = max3100_config_port,
- .verify_port = max3100_verify_port,
-};
-
-static struct uart_driver max3100_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "ttyMAX",
- .dev_name = "ttyMAX",
- .major = MAX3100_MAJOR,
- .minor = MAX3100_MINOR,
- .nr = MAX_MAX3100,
-};
-static int uart_driver_registered;
-
-static int __devinit max3100_probe(struct spi_device *spi)
-{
- int i, retval;
- struct plat_max3100 *pdata;
- u16 tx, rx;
-
- mutex_lock(&max3100s_lock);
-
- if (!uart_driver_registered) {
- uart_driver_registered = 1;
- retval = uart_register_driver(&max3100_uart_driver);
- if (retval) {
- printk(KERN_ERR "Couldn't register max3100 uart driver\n");
- mutex_unlock(&max3100s_lock);
- return retval;
- }
- }
-
- for (i = 0; i < MAX_MAX3100; i++)
- if (!max3100s[i])
- break;
- if (i == MAX_MAX3100) {
- dev_warn(&spi->dev, "too many MAX3100 chips\n");
- mutex_unlock(&max3100s_lock);
- return -ENOMEM;
- }
-
- max3100s[i] = kzalloc(sizeof(struct max3100_port), GFP_KERNEL);
- if (!max3100s[i]) {
- dev_warn(&spi->dev,
- "kmalloc for max3100 structure %d failed!\n", i);
- mutex_unlock(&max3100s_lock);
- return -ENOMEM;
- }
- max3100s[i]->spi = spi;
- max3100s[i]->irq = spi->irq;
- spin_lock_init(&max3100s[i]->conf_lock);
- dev_set_drvdata(&spi->dev, max3100s[i]);
- pdata = spi->dev.platform_data;
- max3100s[i]->crystal = pdata->crystal;
- max3100s[i]->loopback = pdata->loopback;
- max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;
- if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
- max3100s[i]->poll_time = 1;
- max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;
- max3100s[i]->minor = i;
- init_timer(&max3100s[i]->timer);
- max3100s[i]->timer.function = max3100_timeout;
- max3100s[i]->timer.data = (unsigned long) max3100s[i];
-
- dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i);
- max3100s[i]->port.irq = max3100s[i]->irq;
- max3100s[i]->port.uartclk = max3100s[i]->crystal ? 3686400 : 1843200;
- max3100s[i]->port.fifosize = 16;
- max3100s[i]->port.ops = &max3100_ops;
- max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
- max3100s[i]->port.line = i;
- max3100s[i]->port.type = PORT_MAX3100;
- max3100s[i]->port.dev = &spi->dev;
- retval = uart_add_one_port(&max3100_uart_driver, &max3100s[i]->port);
- if (retval < 0)
- dev_warn(&spi->dev,
- "uart_add_one_port failed for line %d with error %d\n",
- i, retval);
-
- /* set shutdown mode to save power. Will be woken-up on open */
- if (max3100s[i]->max3100_hw_suspend)
- max3100s[i]->max3100_hw_suspend(1);
- else {
- tx = MAX3100_WC | MAX3100_SHDN;
- max3100_sr(max3100s[i], tx, &rx);
- }
- mutex_unlock(&max3100s_lock);
- return 0;
-}
-
-static int __devexit max3100_remove(struct spi_device *spi)
-{
- struct max3100_port *s = dev_get_drvdata(&spi->dev);
- int i;
-
- mutex_lock(&max3100s_lock);
-
- /* find out the index for the chip we are removing */
- for (i = 0; i < MAX_MAX3100; i++)
- if (max3100s[i] == s)
- break;
-
- dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i);
- uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port);
- kfree(max3100s[i]);
- max3100s[i] = NULL;
-
- /* check if this is the last chip we have */
- for (i = 0; i < MAX_MAX3100; i++)
- if (max3100s[i]) {
- mutex_unlock(&max3100s_lock);
- return 0;
- }
- pr_debug("removing max3100 driver\n");
- uart_unregister_driver(&max3100_uart_driver);
-
- mutex_unlock(&max3100s_lock);
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int max3100_suspend(struct spi_device *spi, pm_message_t state)
-{
- struct max3100_port *s = dev_get_drvdata(&spi->dev);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- disable_irq(s->irq);
-
- s->suspending = 1;
- uart_suspend_port(&max3100_uart_driver, &s->port);
-
- if (s->max3100_hw_suspend)
- s->max3100_hw_suspend(1);
- else {
- /* no HW suspend, so do SW one */
- u16 tx, rx;
-
- tx = MAX3100_WC | MAX3100_SHDN;
- max3100_sr(s, tx, &rx);
- }
- return 0;
-}
-
-static int max3100_resume(struct spi_device *spi)
-{
- struct max3100_port *s = dev_get_drvdata(&spi->dev);
-
- dev_dbg(&s->spi->dev, "%s\n", __func__);
-
- if (s->max3100_hw_suspend)
- s->max3100_hw_suspend(0);
- uart_resume_port(&max3100_uart_driver, &s->port);
- s->suspending = 0;
-
- enable_irq(s->irq);
-
- s->conf_commit = 1;
- if (s->workqueue)
- max3100_dowork(s);
-
- return 0;
-}
-
-#else
-#define max3100_suspend NULL
-#define max3100_resume NULL
-#endif
-
-static struct spi_driver max3100_driver = {
- .driver = {
- .name = "max3100",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
-
- .probe = max3100_probe,
- .remove = __devexit_p(max3100_remove),
- .suspend = max3100_suspend,
- .resume = max3100_resume,
-};
-
-static int __init max3100_init(void)
-{
- return spi_register_driver(&max3100_driver);
-}
-module_init(max3100_init);
-
-static void __exit max3100_exit(void)
-{
- spi_unregister_driver(&max3100_driver);
-}
-module_exit(max3100_exit);
-
-MODULE_DESCRIPTION("MAX3100 driver");
-MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:max3100");
diff --git a/drivers/serial/max3107-aava.c b/drivers/serial/max3107-aava.c
deleted file mode 100644
index a1fe304f2f52..000000000000
--- a/drivers/serial/max3107-aava.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * max3107.c - spi uart protocol driver for Maxim 3107
- * Based on max3100.c
- * by Christian Pellegrin <chripell@evolware.org>
- * and max3110.c
- * by Feng Tang <feng.tang@intel.com>
- *
- * Copyright (C) Aavamobile 2009
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/sfi.h>
-#include <asm/mrst.h>
-#include "max3107.h"
-
-/* GPIO direction to input function */
-static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration register */
- buf[0] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to input */
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO direction to output function */
-static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration and data registers */
- buf[0] = MAX3107_GPIOCFG_REG;
- buf[1] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to output */
- buf[0] |= (0x0001 << offset);
- /* Set value */
- if (value)
- buf[1] |= (0x0001 << offset);
- else
- buf[1] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration and data register values */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO conf data w failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO value query function */
-static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO data register */
- buf[0] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Return value */
- return buf[0] & (0x0001 << offset);
-}
-
-/* GPIO value set function */
-static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return;
- }
-
- /* Read current GPIO configuration registers*/
- buf[0] = MAX3107_GPIODATA_REG;
- buf[1] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO data and config read failed\n");
- return;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- if (!(buf[1] & (0x0001 << offset))) {
- /* Configured as input, can't set value */
- dev_warn(&s->spi->dev,
- "Trying to set value for input GPIO\n");
- return;
- }
-
- /* Set value */
- if (value)
- buf[0] |= (0x0001 << offset);
- else
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO data register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
-}
-
-/* GPIO chip data */
-static struct gpio_chip max3107_gpio_chip = {
- .owner = THIS_MODULE,
- .direction_input = max3107_gpio_direction_in,
- .direction_output = max3107_gpio_direction_out,
- .get = max3107_gpio_get,
- .set = max3107_gpio_set,
- .can_sleep = 1,
- .base = MAX3107_GPIO_BASE,
- .ngpio = MAX3107_GPIO_COUNT,
-};
-
-/**
- * max3107_aava_reset - reset on AAVA systems
- * @spi: The SPI device we are probing
- *
- * Reset the device ready for probing.
- */
-
-static int max3107_aava_reset(struct spi_device *spi)
-{
- /* Reset the chip */
- if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
- pr_err("Requesting RESET GPIO failed\n");
- return -EIO;
- }
- if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
- pr_err("Setting RESET GPIO to 0 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- msleep(MAX3107_RESET_DELAY);
- if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
- pr_err("Setting RESET GPIO to 1 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- gpio_free(MAX3107_RESET_GPIO);
- msleep(MAX3107_WAKEUP_DELAY);
- return 0;
-}
-
-static int max3107_aava_configure(struct max3107_port *s)
-{
- int retval;
-
- /* Initialize GPIO chip data */
- s->chip = max3107_gpio_chip;
- s->chip.label = s->spi->modalias;
- s->chip.dev = &s->spi->dev;
-
- /* Add GPIO chip */
- retval = gpiochip_add(&s->chip);
- if (retval) {
- dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
- return retval;
- }
-
- /* Temporary fix for EV2 boot problems, set modem reset to 0 */
- max3107_gpio_direction_out(&s->chip, 3, 0);
- return 0;
-}
-
-#if 0
-/* This will get enabled once we have the board stuff merged for this
- specific case */
-
-static const struct baud_table brg13_ext[] = {
- { 300, MAX3107_BRG13_B300 },
- { 600, MAX3107_BRG13_B600 },
- { 1200, MAX3107_BRG13_B1200 },
- { 2400, MAX3107_BRG13_B2400 },
- { 4800, MAX3107_BRG13_B4800 },
- { 9600, MAX3107_BRG13_B9600 },
- { 19200, MAX3107_BRG13_B19200 },
- { 57600, MAX3107_BRG13_B57600 },
- { 115200, MAX3107_BRG13_B115200 },
- { 230400, MAX3107_BRG13_B230400 },
- { 460800, MAX3107_BRG13_B460800 },
- { 921600, MAX3107_BRG13_B921600 },
- { 0, 0 }
-};
-
-static void max3107_aava_init(struct max3107_port *s)
-{
- /*override for AAVA SC specific*/
- if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
- if (get_koski_build_id() <= KOSKI_EV2)
- if (s->ext_clk) {
- s->brg_cfg = MAX3107_BRG13_B9600;
- s->baud_tbl = (struct baud_table *)brg13_ext;
- }
- }
-}
-#endif
-
-static int __devexit max3107_aava_remove(struct spi_device *spi)
-{
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- /* Remove GPIO chip */
- if (gpiochip_remove(&s->chip))
- dev_warn(&spi->dev, "Removing GPIO chip failed\n");
-
- /* Then do the default remove */
- return max3107_remove(spi);
-}
-
-/* Platform data */
-static struct max3107_plat aava_plat_data = {
- .loopback = 0,
- .ext_clk = 1,
-/* .init = max3107_aava_init, */
- .configure = max3107_aava_configure,
- .hw_suspend = max3107_hw_susp,
- .polled_mode = 0,
- .poll_time = 0,
-};
-
-
-static int __devinit max3107_probe_aava(struct spi_device *spi)
-{
- int err = max3107_aava_reset(spi);
- if (err < 0)
- return err;
- return max3107_probe(spi, &aava_plat_data);
-}
-
-/* Spi driver data */
-static struct spi_driver max3107_driver = {
- .driver = {
- .name = "aava-max3107",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
- .probe = max3107_probe_aava,
- .remove = __devexit_p(max3107_aava_remove),
- .suspend = max3107_suspend,
- .resume = max3107_resume,
-};
-
-/* Driver init function */
-static int __init max3107_init(void)
-{
- return spi_register_driver(&max3107_driver);
-}
-
-/* Driver exit function */
-static void __exit max3107_exit(void)
-{
- spi_unregister_driver(&max3107_driver);
-}
-
-module_init(max3107_init);
-module_exit(max3107_exit);
-
-MODULE_DESCRIPTION("MAX3107 driver");
-MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("aava-max3107-spi");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c
deleted file mode 100644
index 910870edf708..000000000000
--- a/drivers/serial/max3107.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-/*
- * max3107.c - spi uart protocol driver for Maxim 3107
- * Based on max3100.c
- * by Christian Pellegrin <chripell@evolware.org>
- * and max3110.c
- * by Feng Tang <feng.tang@intel.com>
- *
- * Copyright (C) Aavamobile 2009
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include "max3107.h"
-
-static const struct baud_table brg26_ext[] = {
- { 300, MAX3107_BRG26_B300 },
- { 600, MAX3107_BRG26_B600 },
- { 1200, MAX3107_BRG26_B1200 },
- { 2400, MAX3107_BRG26_B2400 },
- { 4800, MAX3107_BRG26_B4800 },
- { 9600, MAX3107_BRG26_B9600 },
- { 19200, MAX3107_BRG26_B19200 },
- { 57600, MAX3107_BRG26_B57600 },
- { 115200, MAX3107_BRG26_B115200 },
- { 230400, MAX3107_BRG26_B230400 },
- { 460800, MAX3107_BRG26_B460800 },
- { 921600, MAX3107_BRG26_B921600 },
- { 0, 0 }
-};
-
-static const struct baud_table brg13_int[] = {
- { 300, MAX3107_BRG13_IB300 },
- { 600, MAX3107_BRG13_IB600 },
- { 1200, MAX3107_BRG13_IB1200 },
- { 2400, MAX3107_BRG13_IB2400 },
- { 4800, MAX3107_BRG13_IB4800 },
- { 9600, MAX3107_BRG13_IB9600 },
- { 19200, MAX3107_BRG13_IB19200 },
- { 57600, MAX3107_BRG13_IB57600 },
- { 115200, MAX3107_BRG13_IB115200 },
- { 230400, MAX3107_BRG13_IB230400 },
- { 460800, MAX3107_BRG13_IB460800 },
- { 921600, MAX3107_BRG13_IB921600 },
- { 0, 0 }
-};
-
-static u32 get_new_brg(int baud, struct max3107_port *s)
-{
- int i;
- const struct baud_table *baud_tbl = s->baud_tbl;
-
- for (i = 0; i < 13; i++) {
- if (baud == baud_tbl[i].baud)
- return baud_tbl[i].new_brg;
- }
-
- return 0;
-}
-
-/* Perform SPI transfer for write/read of device register(s) */
-int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
-{
- struct spi_message spi_msg;
- struct spi_transfer spi_xfer;
-
- /* Initialize SPI ,message */
- spi_message_init(&spi_msg);
-
- /* Initialize SPI transfer */
- memset(&spi_xfer, 0, sizeof spi_xfer);
- spi_xfer.len = len;
- spi_xfer.tx_buf = tx;
- spi_xfer.rx_buf = rx;
- spi_xfer.speed_hz = MAX3107_SPI_SPEED;
-
- /* Add SPI transfer to SPI message */
- spi_message_add_tail(&spi_xfer, &spi_msg);
-
-#ifdef DBG_TRACE_SPI_DATA
- {
- int i;
- pr_info("tx len %d:\n", spi_xfer.len);
- for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
- pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]);
- pr_info("\n");
- }
-#endif
-
- /* Perform synchronous SPI transfer */
- if (spi_sync(s->spi, &spi_msg)) {
- dev_err(&s->spi->dev, "spi_sync failure\n");
- return -EIO;
- }
-
-#ifdef DBG_TRACE_SPI_DATA
- if (spi_xfer.rx_buf) {
- int i;
- pr_info("rx len %d:\n", spi_xfer.len);
- for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
- pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]);
- pr_info("\n");
- }
-#endif
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_rw);
-
-/* Puts received data to circular buffer */
-static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data,
- int len)
-{
- struct uart_port *port = &s->port;
- struct tty_struct *tty;
-
- if (!port->state)
- return;
-
- tty = port->state->port.tty;
- if (!tty)
- return;
-
- /* Insert received data */
- tty_insert_flip_string(tty, data, len);
- /* Update RX counter */
- port->icount.rx += len;
-}
-
-/* Handle data receiving */
-static void max3107_handlerx(struct max3107_port *s, u16 rxlvl)
-{
- int i;
- int j;
- int len; /* SPI transfer buffer length */
- u16 *buf;
- u8 *valid_str;
-
- if (!s->rx_enabled)
- /* RX is disabled */
- return;
-
- if (rxlvl == 0) {
- /* RX fifo is empty */
- return;
- } else if (rxlvl >= MAX3107_RX_FIFO_SIZE) {
- dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl);
- /* Ensure sanity of RX level */
- rxlvl = MAX3107_RX_FIFO_SIZE;
- }
- if ((s->rxbuf == 0) || (s->rxstr == 0)) {
- dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n");
- return;
- }
- buf = s->rxbuf;
- valid_str = s->rxstr;
- while (rxlvl) {
- pr_debug("rxlvl %d\n", rxlvl);
- /* Clear buffer */
- memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2));
- len = 0;
- if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) {
- /* First disable RX FIFO interrupt */
- pr_debug("Disabling RX INT\n");
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT;
- buf[0] |= s->irqen_reg;
- len++;
- }
- /* Just increase the length by amount of words in FIFO since
- * buffer was zeroed and SPI transfer of 0x0000 means reading
- * from RX FIFO
- */
- len += rxlvl;
- /* Append RX level query */
- buf[len] = MAX3107_RXFIFOLVL_REG;
- len++;
-
- /* Perform the SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) {
- dev_err(&s->spi->dev, "SPI transfer for RX h failed\n");
- return;
- }
-
- /* Skip RX FIFO interrupt disabling word if it was added */
- j = ((len - 1) - rxlvl);
- /* Read received words */
- for (i = 0; i < rxlvl; i++, j++)
- valid_str[i] = (u8)buf[j];
- put_data_to_circ_buf(s, valid_str, rxlvl);
- /* Get new RX level */
- rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK);
- }
-
- if (s->rx_enabled) {
- /* RX still enabled, re-enable RX FIFO interrupt */
- pr_debug("Enabling RX INT\n");
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
- buf[0] |= s->irqen_reg;
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n");
- }
-
- /* Push the received data to receivers */
- if (s->port.state->port.tty)
- tty_flip_buffer_push(s->port.state->port.tty);
-}
-
-
-/* Handle data sending */
-static void max3107_handletx(struct max3107_port *s)
-{
- struct circ_buf *xmit = &s->port.state->xmit;
- int i;
- unsigned long flags;
- int len; /* SPI transfer buffer length */
- u16 *buf;
-
- if (!s->tx_fifo_empty)
- /* Don't send more data before previous data is sent */
- return;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
- /* No data to send or TX is stopped */
- return;
-
- if (!s->txbuf) {
- dev_warn(&s->spi->dev, "Txbuf isn't ready\n");
- return;
- }
- buf = s->txbuf;
- /* Get length of data pending in circular buffer */
- len = uart_circ_chars_pending(xmit);
- if (len) {
- /* Limit to size of TX FIFO */
- if (len > MAX3107_TX_FIFO_SIZE)
- len = MAX3107_TX_FIFO_SIZE;
-
- pr_debug("txlen %d\n", len);
-
- /* Update TX counter */
- s->port.icount.tx += len;
-
- /* TX FIFO will no longer be empty */
- s->tx_fifo_empty = 0;
-
- i = 0;
- if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) {
- /* First disable TX empty interrupt */
- pr_debug("Disabling TE INT\n");
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT;
- buf[i] |= s->irqen_reg;
- i++;
- len++;
- }
- /* Add data to send */
- spin_lock_irqsave(&s->port.lock, flags);
- for ( ; i < len ; i++) {
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG);
- buf[i] |= ((u16)xmit->buf[xmit->tail] &
- MAX3107_SPI_TX_DATA_MASK);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- }
- spin_unlock_irqrestore(&s->port.lock, flags);
- if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) {
- /* Enable TX empty interrupt */
- pr_debug("Enabling TE INT\n");
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT;
- buf[i] |= s->irqen_reg;
- i++;
- len++;
- }
- if (!s->tx_enabled) {
- /* Enable TX */
- pr_debug("Enable TX\n");
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- spin_lock_irqsave(&s->data_lock, flags);
- s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT;
- buf[i] |= s->mode1_reg;
- spin_unlock_irqrestore(&s->data_lock, flags);
- s->tx_enabled = 1;
- i++;
- len++;
- }
-
- /* Perform the SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, len*2)) {
- dev_err(&s->spi->dev,
- "SPI transfer TX handling failed\n");
- return;
- }
- }
-
- /* Indicate wake up if circular buffer is getting low on data */
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&s->port);
-
-}
-
-/* Handle interrupts
- * Also reads and returns current RX FIFO level
- */
-static u16 handle_interrupt(struct max3107_port *s)
-{
- u16 buf[4]; /* Buffer for SPI transfers */
- u8 irq_status;
- u16 rx_level;
- unsigned long flags;
-
- /* Read IRQ status register */
- buf[0] = MAX3107_IRQSTS_REG;
- /* Read status IRQ status register */
- buf[1] = MAX3107_STS_IRQSTS_REG;
- /* Read LSR IRQ status register */
- buf[2] = MAX3107_LSR_IRQSTS_REG;
- /* Query RX level */
- buf[3] = MAX3107_RXFIFOLVL_REG;
-
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) {
- dev_err(&s->spi->dev,
- "SPI transfer for INTR handling failed\n");
- return 0;
- }
-
- irq_status = (u8)buf[0];
- pr_debug("IRQSTS %x\n", irq_status);
- rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK);
-
- if (irq_status & MAX3107_IRQ_LSR_BIT) {
- /* LSR interrupt */
- if (buf[2] & MAX3107_LSR_RXTO_BIT)
- /* RX timeout interrupt,
- * handled by normal RX handling
- */
- pr_debug("RX TO INT\n");
- }
-
- if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) {
- /* Tx empty interrupt,
- * disable TX and set tx_fifo_empty flag
- */
- pr_debug("TE INT, disabling TX\n");
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- spin_lock_irqsave(&s->data_lock, flags);
- s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
- buf[0] |= s->mode1_reg;
- spin_unlock_irqrestore(&s->data_lock, flags);
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer TX dis failed\n");
- s->tx_enabled = 0;
- s->tx_fifo_empty = 1;
- }
-
- if (irq_status & MAX3107_IRQ_RXFIFO_BIT)
- /* RX FIFO interrupt,
- * handled by normal RX handling
- */
- pr_debug("RFIFO INT\n");
-
- /* Return RX level */
- return rx_level;
-}
-
-/* Trigger work thread*/
-static void max3107_dowork(struct max3107_port *s)
-{
- if (!work_pending(&s->work) && !freezing(current) && !s->suspended)
- queue_work(s->workqueue, &s->work);
- else
- dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n");
-}
-
-/* Work thread */
-static void max3107_work(struct work_struct *w)
-{
- struct max3107_port *s = container_of(w, struct max3107_port, work);
- u16 rxlvl = 0;
- int len; /* SPI transfer buffer length */
- u16 buf[5]; /* Buffer for SPI transfers */
- unsigned long flags;
-
- /* Start by reading current RX FIFO level */
- buf[0] = MAX3107_RXFIFOLVL_REG;
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer RX lev failed\n");
- rxlvl = 0;
- } else {
- rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK);
- }
-
- do {
- pr_debug("rxlvl %d\n", rxlvl);
-
- /* Handle RX */
- max3107_handlerx(s, rxlvl);
- rxlvl = 0;
-
- if (s->handle_irq) {
- /* Handle pending interrupts
- * We also get new RX FIFO level since new data may
- * have been received while pushing received data to
- * receivers
- */
- s->handle_irq = 0;
- rxlvl = handle_interrupt(s);
- }
-
- /* Handle TX */
- max3107_handletx(s);
-
- /* Handle configuration changes */
- len = 0;
- spin_lock_irqsave(&s->data_lock, flags);
- if (s->mode1_commit) {
- pr_debug("mode1_commit\n");
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- buf[len++] |= s->mode1_reg;
- s->mode1_commit = 0;
- }
- if (s->lcr_commit) {
- pr_debug("lcr_commit\n");
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG);
- buf[len++] |= s->lcr_reg;
- s->lcr_commit = 0;
- }
- if (s->brg_commit) {
- pr_debug("brg_commit\n");
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG);
- buf[len++] |= ((s->brg_cfg >> 16) &
- MAX3107_SPI_TX_DATA_MASK);
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG);
- buf[len++] |= ((s->brg_cfg >> 8) &
- MAX3107_SPI_TX_DATA_MASK);
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG);
- buf[len++] |= ((s->brg_cfg) & 0xff);
- s->brg_commit = 0;
- }
- spin_unlock_irqrestore(&s->data_lock, flags);
-
- if (len > 0) {
- if (max3107_rw(s, (u8 *)buf, NULL, len * 2))
- dev_err(&s->spi->dev,
- "SPI transfer config failed\n");
- }
-
- /* Reloop if interrupt handling indicated data in RX FIFO */
- } while (rxlvl);
-
-}
-
-/* Set sleep mode */
-static void max3107_set_sleep(struct max3107_port *s, int mode)
-{
- u16 buf[1]; /* Buffer for SPI transfer */
- unsigned long flags;
- pr_debug("enter, mode %d\n", mode);
-
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- spin_lock_irqsave(&s->data_lock, flags);
- switch (mode) {
- case MAX3107_DISABLE_FORCED_SLEEP:
- s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT;
- break;
- case MAX3107_ENABLE_FORCED_SLEEP:
- s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT;
- break;
- case MAX3107_DISABLE_AUTOSLEEP:
- s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT;
- break;
- case MAX3107_ENABLE_AUTOSLEEP:
- s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT;
- break;
- default:
- spin_unlock_irqrestore(&s->data_lock, flags);
- dev_warn(&s->spi->dev, "invalid sleep mode\n");
- return;
- }
- buf[0] |= s->mode1_reg;
- spin_unlock_irqrestore(&s->data_lock, flags);
-
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n");
-
- if (mode == MAX3107_DISABLE_AUTOSLEEP ||
- mode == MAX3107_DISABLE_FORCED_SLEEP)
- msleep(MAX3107_WAKEUP_DELAY);
-}
-
-/* Perform full register initialization */
-static void max3107_register_init(struct max3107_port *s)
-{
- u16 buf[11]; /* Buffer for SPI transfers */
-
- /* 1. Configure baud rate, 9600 as default */
- s->baud = 9600;
- /* the below is default*/
- if (s->ext_clk) {
- s->brg_cfg = MAX3107_BRG26_B9600;
- s->baud_tbl = (struct baud_table *)brg26_ext;
- } else {
- s->brg_cfg = MAX3107_BRG13_IB9600;
- s->baud_tbl = (struct baud_table *)brg13_int;
- }
-
- if (s->pdata->init)
- s->pdata->init(s);
-
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG)
- | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK);
- buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG)
- | ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK);
- buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG)
- | ((s->brg_cfg) & 0xff);
-
- /* 2. Configure LCR register, 8N1 mode by default */
- s->lcr_reg = MAX3107_LCR_WORD_LEN_8;
- buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG)
- | s->lcr_reg;
-
- /* 3. Configure MODE 1 register */
- s->mode1_reg = 0;
- /* Enable IRQ pin */
- s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT;
- /* Disable TX */
- s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
- s->tx_enabled = 0;
- /* RX is enabled */
- s->rx_enabled = 1;
- buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG)
- | s->mode1_reg;
-
- /* 4. Configure MODE 2 register */
- buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
- if (s->loopback) {
- /* Enable loopback */
- buf[5] |= MAX3107_MODE2_LOOPBACK_BIT;
- }
- /* Reset FIFOs */
- buf[5] |= MAX3107_MODE2_FIFORST_BIT;
- s->tx_fifo_empty = 1;
-
- /* 5. Configure FIFO trigger level register */
- buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG);
- /* RX FIFO trigger for 16 words, TX FIFO trigger not used */
- buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0));
-
- /* 6. Configure flow control levels */
- buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG);
- /* Flow control halt level 96, resume level 48 */
- buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96));
-
- /* 7. Configure flow control */
- buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG);
- /* Enable auto CTS and auto RTS flow control */
- buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT);
-
- /* 8. Configure RX timeout register */
- buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG);
- /* Timeout after 48 character intervals */
- buf[9] |= 0x0030;
-
- /* 9. Configure LSR interrupt enable register */
- buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG);
- /* Enable RX timeout interrupt */
- buf[10] |= MAX3107_LSR_RXTO_BIT;
-
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 22))
- dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-
- /* 10. Clear IRQ status register by reading it */
- buf[0] = MAX3107_IRQSTS_REG;
-
- /* 11. Configure interrupt enable register */
- /* Enable LSR interrupt */
- s->irqen_reg = MAX3107_IRQ_LSR_BIT;
- /* Enable RX FIFO interrupt */
- s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
- buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG)
- | s->irqen_reg;
-
- /* 12. Clear FIFO reset that was set in step 6 */
- buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
- if (s->loopback) {
- /* Keep loopback enabled */
- buf[2] |= MAX3107_MODE2_LOOPBACK_BIT;
- }
-
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6))
- dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-
-}
-
-/* IRQ handler */
-static irqreturn_t max3107_irq(int irqno, void *dev_id)
-{
- struct max3107_port *s = dev_id;
-
- if (irqno != s->spi->irq) {
- /* Unexpected IRQ */
- return IRQ_NONE;
- }
-
- /* Indicate irq */
- s->handle_irq = 1;
-
- /* Trigger work thread */
- max3107_dowork(s);
-
- return IRQ_HANDLED;
-}
-
-/* HW suspension function
- *
- * Currently autosleep is used to decrease current consumption, alternative
- * approach would be to set the chip to reset mode if UART is not being
- * used but that would mess the GPIOs
- *
- */
-void max3107_hw_susp(struct max3107_port *s, int suspend)
-{
- pr_debug("enter, suspend %d\n", suspend);
-
- if (suspend) {
- /* Suspend requested,
- * enable autosleep to decrease current consumption
- */
- s->suspended = 1;
- max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP);
- } else {
- /* Resume requested,
- * disable autosleep
- */
- s->suspended = 0;
- max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP);
- }
-}
-EXPORT_SYMBOL_GPL(max3107_hw_susp);
-
-/* Modem status IRQ enabling */
-static void max3107_enable_ms(struct uart_port *port)
-{
- /* Modem status not supported */
-}
-
-/* Data send function */
-static void max3107_start_tx(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- /* Trigger work thread for sending data */
- max3107_dowork(s);
-}
-
-/* Function for checking that there is no pending transfers */
-static unsigned int max3107_tx_empty(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- pr_debug("returning %d\n",
- (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit)));
- return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit);
-}
-
-/* Function for stopping RX */
-static void max3107_stop_rx(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- unsigned long flags;
-
- /* Set RX disabled in MODE 1 register */
- spin_lock_irqsave(&s->data_lock, flags);
- s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT;
- s->mode1_commit = 1;
- spin_unlock_irqrestore(&s->data_lock, flags);
- /* Set RX disabled */
- s->rx_enabled = 0;
- /* Trigger work thread for doing the actual configuration change */
- max3107_dowork(s);
-}
-
-/* Function for returning control pin states */
-static unsigned int max3107_get_mctrl(struct uart_port *port)
-{
- /* DCD and DSR are not wired and CTS/RTS is handled automatically
- * so just indicate DSR and CAR asserted
- */
- return TIOCM_DSR | TIOCM_CAR;
-}
-
-/* Function for setting control pin states */
-static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- /* DCD and DSR are not wired and CTS/RTS is hadnled automatically
- * so do nothing
- */
-}
-
-/* Function for configuring UART parameters */
-static void max3107_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- struct tty_struct *tty;
- int baud;
- u16 new_lcr = 0;
- u32 new_brg = 0;
- unsigned long flags;
-
- if (!port->state)
- return;
-
- tty = port->state->port.tty;
- if (!tty)
- return;
-
- /* Get new LCR register values */
- /* Word size */
- if ((termios->c_cflag & CSIZE) == CS7)
- new_lcr |= MAX3107_LCR_WORD_LEN_7;
- else
- new_lcr |= MAX3107_LCR_WORD_LEN_8;
-
- /* Parity */
- if (termios->c_cflag & PARENB) {
- new_lcr |= MAX3107_LCR_PARITY_BIT;
- if (!(termios->c_cflag & PARODD))
- new_lcr |= MAX3107_LCR_EVENPARITY_BIT;
- }
-
- /* Stop bits */
- if (termios->c_cflag & CSTOPB) {
- /* 2 stop bits */
- new_lcr |= MAX3107_LCR_STOPLEN_BIT;
- }
-
- /* Mask termios capabilities we don't support */
- termios->c_cflag &= ~CMSPAR;
-
- /* Set status ignore mask */
- s->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- s->port.ignore_status_mask |= MAX3107_ALL_ERRORS;
-
- /* Set low latency to immediately handle pushed data */
- s->port.state->port.tty->low_latency = 1;
-
- /* Get new baud rate generator configuration */
- baud = tty_get_baud_rate(tty);
-
- spin_lock_irqsave(&s->data_lock, flags);
- new_brg = get_new_brg(baud, s);
- /* if can't find the corrent config, use previous */
- if (!new_brg) {
- baud = s->baud;
- new_brg = s->brg_cfg;
- }
- spin_unlock_irqrestore(&s->data_lock, flags);
- tty_termios_encode_baud_rate(termios, baud, baud);
- s->baud = baud;
-
- /* Update timeout according to new baud rate */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_lock_irqsave(&s->data_lock, flags);
- if (s->lcr_reg != new_lcr) {
- s->lcr_reg = new_lcr;
- s->lcr_commit = 1;
- }
- if (s->brg_cfg != new_brg) {
- s->brg_cfg = new_brg;
- s->brg_commit = 1;
- }
- spin_unlock_irqrestore(&s->data_lock, flags);
-
- /* Trigger work thread for doing the actual configuration change */
- max3107_dowork(s);
-}
-
-/* Port shutdown function */
-static void max3107_shutdown(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- if (s->suspended && s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 0);
-
- /* Free the interrupt */
- free_irq(s->spi->irq, s);
-
- if (s->workqueue) {
- /* Flush and destroy work queue */
- flush_workqueue(s->workqueue);
- destroy_workqueue(s->workqueue);
- s->workqueue = NULL;
- }
-
- /* Suspend HW */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 1);
-}
-
-/* Port startup function */
-static int max3107_startup(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- /* Initialize work queue */
- s->workqueue = create_freezeable_workqueue("max3107");
- if (!s->workqueue) {
- dev_err(&s->spi->dev, "Workqueue creation failed\n");
- return -EBUSY;
- }
- INIT_WORK(&s->work, max3107_work);
-
- /* Setup IRQ */
- if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING,
- "max3107", s)) {
- dev_err(&s->spi->dev, "IRQ reguest failed\n");
- destroy_workqueue(s->workqueue);
- s->workqueue = NULL;
- return -EBUSY;
- }
-
- /* Resume HW */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 0);
-
- /* Init registers */
- max3107_register_init(s);
-
- return 0;
-}
-
-/* Port type function */
-static const char *max3107_type(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- return s->spi->modalias;
-}
-
-/* Port release function */
-static void max3107_release_port(struct uart_port *port)
-{
- /* Do nothing */
-}
-
-/* Port request function */
-static int max3107_request_port(struct uart_port *port)
-{
- /* Do nothing */
- return 0;
-}
-
-/* Port config function */
-static void max3107_config_port(struct uart_port *port, int flags)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- s->port.type = PORT_MAX3107;
-}
-
-/* Port verify function */
-static int max3107_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107)
- return 0;
-
- return -EINVAL;
-}
-
-/* Port stop TX function */
-static void max3107_stop_tx(struct uart_port *port)
-{
- /* Do nothing */
-}
-
-/* Port break control function */
-static void max3107_break_ctl(struct uart_port *port, int break_state)
-{
- /* We don't support break control, do nothing */
-}
-
-
-/* Port functions */
-static struct uart_ops max3107_ops = {
- .tx_empty = max3107_tx_empty,
- .set_mctrl = max3107_set_mctrl,
- .get_mctrl = max3107_get_mctrl,
- .stop_tx = max3107_stop_tx,
- .start_tx = max3107_start_tx,
- .stop_rx = max3107_stop_rx,
- .enable_ms = max3107_enable_ms,
- .break_ctl = max3107_break_ctl,
- .startup = max3107_startup,
- .shutdown = max3107_shutdown,
- .set_termios = max3107_set_termios,
- .type = max3107_type,
- .release_port = max3107_release_port,
- .request_port = max3107_request_port,
- .config_port = max3107_config_port,
- .verify_port = max3107_verify_port,
-};
-
-/* UART driver data */
-static struct uart_driver max3107_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "ttyMAX",
- .dev_name = "ttyMAX",
- .nr = 1,
-};
-
-static int driver_registered = 0;
-
-
-
-/* 'Generic' platform data */
-static struct max3107_plat generic_plat_data = {
- .loopback = 0,
- .ext_clk = 1,
- .hw_suspend = max3107_hw_susp,
- .polled_mode = 0,
- .poll_time = 0,
-};
-
-
-/*******************************************************************/
-
-/**
- * max3107_probe - SPI bus probe entry point
- * @spi: the spi device
- *
- * SPI wants us to probe this device and if appropriate claim it.
- * Perform any platform specific requirements and then initialise
- * the device.
- */
-
-int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
-{
- struct max3107_port *s;
- u16 buf[2]; /* Buffer for SPI transfers */
- int retval;
-
- pr_info("enter max3107 probe\n");
-
- /* Allocate port structure */
- s = kzalloc(sizeof(*s), GFP_KERNEL);
- if (!s) {
- pr_err("Allocating port structure failed\n");
- return -ENOMEM;
- }
-
- s->pdata = pdata;
-
- /* SPI Rx buffer
- * +2 for RX FIFO interrupt
- * disabling and RX level query
- */
- s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
- if (!s->rxbuf) {
- pr_err("Allocating RX buffer failed\n");
- retval = -ENOMEM;
- goto err_free4;
- }
- s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
- if (!s->rxstr) {
- pr_err("Allocating RX buffer failed\n");
- retval = -ENOMEM;
- goto err_free3;
- }
- /* SPI Tx buffer
- * SPI transfer buffer
- * +3 for TX FIFO empty
- * interrupt disabling and
- * enabling and TX enabling
- */
- s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
- if (!s->txbuf) {
- pr_err("Allocating TX buffer failed\n");
- retval = -ENOMEM;
- goto err_free2;
- }
- /* Initialize shared data lock */
- spin_lock_init(&s->data_lock);
-
- /* SPI intializations */
- dev_set_drvdata(&spi->dev, s);
- spi->mode = SPI_MODE_0;
- spi->dev.platform_data = pdata;
- spi->bits_per_word = 16;
- s->ext_clk = pdata->ext_clk;
- s->loopback = pdata->loopback;
- spi_setup(spi);
- s->spi = spi;
-
- /* Check REV ID to ensure we are talking to what we expect */
- buf[0] = MAX3107_REVID_REG;
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
- retval = -EIO;
- goto err_free1;
- }
- if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
- (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
- dev_err(&s->spi->dev, "REVID %x does not match\n",
- (buf[0] & MAX3107_SPI_RX_DATA_MASK));
- retval = -ENODEV;
- goto err_free1;
- }
-
- /* Disable all interrupts */
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000);
- buf[0] |= 0x0000;
-
- /* Configure clock source */
- buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG);
- if (s->ext_clk) {
- /* External clock */
- buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT;
- }
-
- /* PLL bypass ON */
- buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT;
-
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
- dev_err(&s->spi->dev, "SPI transfer for init failed\n");
- retval = -EIO;
- goto err_free1;
- }
-
- /* Register UART driver */
- if (!driver_registered) {
- retval = uart_register_driver(&max3107_uart_driver);
- if (retval) {
- dev_err(&s->spi->dev, "Registering UART driver failed\n");
- goto err_free1;
- }
- driver_registered = 1;
- }
-
- /* Initialize UART port data */
- s->port.fifosize = 128;
- s->port.ops = &max3107_ops;
- s->port.line = 0;
- s->port.dev = &spi->dev;
- s->port.uartclk = 9600;
- s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
- s->port.irq = s->spi->irq;
- s->port.type = PORT_MAX3107;
-
- /* Add UART port */
- retval = uart_add_one_port(&max3107_uart_driver, &s->port);
- if (retval < 0) {
- dev_err(&s->spi->dev, "Adding UART port failed\n");
- goto err_free1;
- }
-
- if (pdata->configure) {
- retval = pdata->configure(s);
- if (retval < 0)
- goto err_free1;
- }
-
- /* Go to suspend mode */
- if (pdata->hw_suspend)
- pdata->hw_suspend(s, 1);
-
- return 0;
-
-err_free1:
- kfree(s->txbuf);
-err_free2:
- kfree(s->rxstr);
-err_free3:
- kfree(s->rxbuf);
-err_free4:
- kfree(s);
- return retval;
-}
-EXPORT_SYMBOL_GPL(max3107_probe);
-
-/* Driver remove function */
-int max3107_remove(struct spi_device *spi)
-{
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- pr_info("enter max3107 remove\n");
-
- /* Remove port */
- if (uart_remove_one_port(&max3107_uart_driver, &s->port))
- dev_warn(&s->spi->dev, "Removing UART port failed\n");
-
-
- /* Free TxRx buffer */
- kfree(s->rxbuf);
- kfree(s->rxstr);
- kfree(s->txbuf);
-
- /* Free port structure */
- kfree(s);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_remove);
-
-/* Driver suspend function */
-int max3107_suspend(struct spi_device *spi, pm_message_t state)
-{
-#ifdef CONFIG_PM
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- pr_debug("enter suspend\n");
-
- /* Suspend UART port */
- uart_suspend_port(&max3107_uart_driver, &s->port);
-
- /* Go to suspend mode */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 1);
-#endif /* CONFIG_PM */
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_suspend);
-
-/* Driver resume function */
-int max3107_resume(struct spi_device *spi)
-{
-#ifdef CONFIG_PM
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- pr_debug("enter resume\n");
-
- /* Resume from suspend */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 0);
-
- /* Resume UART port */
- uart_resume_port(&max3107_uart_driver, &s->port);
-#endif /* CONFIG_PM */
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_resume);
-
-static int max3107_probe_generic(struct spi_device *spi)
-{
- return max3107_probe(spi, &generic_plat_data);
-}
-
-/* Spi driver data */
-static struct spi_driver max3107_driver = {
- .driver = {
- .name = "max3107",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
- .probe = max3107_probe_generic,
- .remove = __devexit_p(max3107_remove),
- .suspend = max3107_suspend,
- .resume = max3107_resume,
-};
-
-/* Driver init function */
-static int __init max3107_init(void)
-{
- pr_info("enter max3107 init\n");
- return spi_register_driver(&max3107_driver);
-}
-
-/* Driver exit function */
-static void __exit max3107_exit(void)
-{
- pr_info("enter max3107 exit\n");
- /* Unregister UART driver */
- if (driver_registered)
- uart_unregister_driver(&max3107_uart_driver);
- spi_unregister_driver(&max3107_driver);
-}
-
-module_init(max3107_init);
-module_exit(max3107_exit);
-
-MODULE_DESCRIPTION("MAX3107 driver");
-MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("max3107-spi");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/serial/max3107.h b/drivers/serial/max3107.h
deleted file mode 100644
index 7ab632392502..000000000000
--- a/drivers/serial/max3107.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * max3107.h - spi uart protocol driver header for Maxim 3107
- *
- * Copyright (C) Aavamobile 2009
- * Based on serial_max3100.h by Christian Pellegrin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef _MAX3107_H
-#define _MAX3107_H
-
-/* Serial error status definitions */
-#define MAX3107_PARITY_ERROR 1
-#define MAX3107_FRAME_ERROR 2
-#define MAX3107_OVERRUN_ERROR 4
-#define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \
- MAX3107_FRAME_ERROR | \
- MAX3107_OVERRUN_ERROR)
-
-/* GPIO definitions */
-#define MAX3107_GPIO_BASE 88
-#define MAX3107_GPIO_COUNT 4
-
-
-/* GPIO connected to chip's reset pin */
-#define MAX3107_RESET_GPIO 87
-
-
-/* Chip reset delay */
-#define MAX3107_RESET_DELAY 10
-
-/* Chip wakeup delay */
-#define MAX3107_WAKEUP_DELAY 50
-
-
-/* Sleep mode definitions */
-#define MAX3107_DISABLE_FORCED_SLEEP 0
-#define MAX3107_ENABLE_FORCED_SLEEP 1
-#define MAX3107_DISABLE_AUTOSLEEP 2
-#define MAX3107_ENABLE_AUTOSLEEP 3
-
-
-/* Definitions for register access with SPI transfers
- *
- * SPI transfer format:
- *
- * Master to slave bits xzzzzzzzyyyyyyyy
- * Slave to master bits aaaaaaaabbbbbbbb
- *
- * where:
- * x = 0 for reads, 1 for writes
- * z = register address
- * y = new register value if write, 0 if read
- * a = unspecified
- * b = register value if read, unspecified if write
- */
-
-/* SPI speed */
-#define MAX3107_SPI_SPEED (3125000 * 2)
-
-/* Write bit */
-#define MAX3107_WRITE_BIT (1 << 15)
-
-/* SPI TX data mask */
-#define MAX3107_SPI_RX_DATA_MASK (0x00ff)
-
-/* SPI RX data mask */
-#define MAX3107_SPI_TX_DATA_MASK (0x00ff)
-
-/* Register access masks */
-#define MAX3107_RHR_REG (0x0000) /* RX FIFO */
-#define MAX3107_THR_REG (0x0000) /* TX FIFO */
-#define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */
-#define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */
-#define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */
-#define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */
-#define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */
-#define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */
-#define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */
-#define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */
-#define MAX3107_MODE1_REG (0x0900) /* MODE1 */
-#define MAX3107_MODE2_REG (0x0a00) /* MODE2 */
-#define MAX3107_LCR_REG (0x0b00) /* LCR */
-#define MAX3107_RXTO_REG (0x0c00) /* RX timeout */
-#define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */
-#define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */
-#define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */
-#define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */
-#define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */
-#define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */
-#define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */
-#define MAX3107_XON1_REG (0x1400) /* XON1 character */
-#define MAX3107_XON2_REG (0x1500) /* XON2 character */
-#define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */
-#define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */
-#define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */
-#define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */
-#define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */
-#define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */
-#define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */
-#define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */
-#define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */
-#define MAX3107_REVID_REG (0x1f00) /* Revision identification */
-
-/* IRQ register bits */
-#define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
-#define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */
-#define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */
-#define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */
-#define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */
-#define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */
-#define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */
-#define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */
-
-/* LSR register bits */
-#define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */
-#define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */
-#define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */
-#define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */
-#define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */
-#define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */
-#define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */
-
-/* Special character register bits */
-#define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */
-#define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */
-#define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */
-#define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */
-#define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */
-#define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */
-#define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* Status register bits */
-#define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */
-#define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */
-#define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */
-#define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */
-#define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */
-#define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */
-#define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */
-#define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* MODE1 register bits */
-#define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */
-#define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */
-#define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */
-#define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */
-#define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */
-#define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */
-#define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */
-#define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */
-
-/* MODE2 register bits */
-#define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */
-#define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */
-#define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */
-#define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */
-#define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */
-#define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */
-#define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */
-#define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */
-
-/* LCR register bits */
-#define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */
-#define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1
- *
- * Word length bits table:
- * 00 -> 5 bit words
- * 01 -> 6 bit words
- * 10 -> 7 bit words
- * 11 -> 8 bit words
- */
-#define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit
- *
- * STOP length bit table:
- * 0 -> 1 stop bit
- * 1 -> 1-1.5 stop bits if
- * word length is 5,
- * 2 stop bits otherwise
- */
-#define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */
-#define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */
-#define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
-#define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
-#define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */
-#define MAX3107_LCR_WORD_LEN_5 (0x0000)
-#define MAX3107_LCR_WORD_LEN_6 (0x0001)
-#define MAX3107_LCR_WORD_LEN_7 (0x0002)
-#define MAX3107_LCR_WORD_LEN_8 (0x0003)
-
-
-/* IRDA register bits */
-#define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
-#define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
-#define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */
-#define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */
-#define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */
-#define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */
-#define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* Flow control trigger level register masks */
-#define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
-#define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */
-#define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f)
-#define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4)
-
-/* FIFO interrupt trigger level register masks */
-#define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */
-#define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */
-#define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f)
-#define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4)
-
-/* Flow control register bits */
-#define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */
-#define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */
-#define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs
- * are used in conjunction with
- * XOFF2 for definition of
- * special character */
-#define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */
-#define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */
-#define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1
- *
- * SWFLOW bits 1 & 0 table:
- * 00 -> no transmitter flow
- * control
- * 01 -> receiver compares
- * XON2 and XOFF2
- * and controls
- * transmitter
- * 10 -> receiver compares
- * XON1 and XOFF1
- * and controls
- * transmitter
- * 11 -> receiver compares
- * XON1, XON2, XOFF1 and
- * XOFF2 and controls
- * transmitter
- */
-#define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */
-#define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3
- *
- * SWFLOW bits 3 & 2 table:
- * 00 -> no received flow
- * control
- * 01 -> transmitter generates
- * XON2 and XOFF2
- * 10 -> transmitter generates
- * XON1 and XOFF1
- * 11 -> transmitter generates
- * XON1, XON2, XOFF1 and
- * XOFF2
- */
-
-/* GPIO configuration register bits */
-#define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */
-#define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */
-#define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */
-#define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */
-#define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */
-#define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */
-#define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */
-#define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */
-
-/* GPIO DATA register bits */
-#define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */
-#define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */
-#define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */
-#define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */
-#define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */
-#define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */
-#define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */
-#define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */
-
-/* PLL configuration register masks */
-#define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */
-#define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */
-
-/* Baud rate generator configuration register masks and bits */
-#define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of
- * Baud rate generator divisor
- */
-#define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */
-#define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */
-#define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* Clock source register bits */
-#define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */
-#define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */
-#define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */
-#define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */
-#define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */
-#define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */
-#define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */
-
-
-/* HW definitions */
-#define MAX3107_RX_FIFO_SIZE 128
-#define MAX3107_TX_FIFO_SIZE 128
-#define MAX3107_REVID1 0x00a0
-#define MAX3107_REVID2 0x00a1
-
-
-/* Baud rate generator configuration values for external clock 13MHz */
-#define MAX3107_BRG13_B300 (0x0A9400 | 0x05)
-#define MAX3107_BRG13_B600 (0x054A00 | 0x03)
-#define MAX3107_BRG13_B1200 (0x02A500 | 0x01)
-#define MAX3107_BRG13_B2400 (0x015200 | 0x09)
-#define MAX3107_BRG13_B4800 (0x00A900 | 0x04)
-#define MAX3107_BRG13_B9600 (0x005400 | 0x0A)
-#define MAX3107_BRG13_B19200 (0x002A00 | 0x05)
-#define MAX3107_BRG13_B38400 (0x001500 | 0x03)
-#define MAX3107_BRG13_B57600 (0x000E00 | 0x02)
-#define MAX3107_BRG13_B115200 (0x000700 | 0x01)
-#define MAX3107_BRG13_B230400 (0x000300 | 0x08)
-#define MAX3107_BRG13_B460800 (0x000100 | 0x0c)
-#define MAX3107_BRG13_B921600 (0x000100 | 0x1c)
-
-/* Baud rate generator configuration values for external clock 26MHz */
-#define MAX3107_BRG26_B300 (0x152800 | 0x0A)
-#define MAX3107_BRG26_B600 (0x0A9400 | 0x05)
-#define MAX3107_BRG26_B1200 (0x054A00 | 0x03)
-#define MAX3107_BRG26_B2400 (0x02A500 | 0x01)
-#define MAX3107_BRG26_B4800 (0x015200 | 0x09)
-#define MAX3107_BRG26_B9600 (0x00A900 | 0x04)
-#define MAX3107_BRG26_B19200 (0x005400 | 0x0A)
-#define MAX3107_BRG26_B38400 (0x002A00 | 0x05)
-#define MAX3107_BRG26_B57600 (0x001C00 | 0x03)
-#define MAX3107_BRG26_B115200 (0x000E00 | 0x02)
-#define MAX3107_BRG26_B230400 (0x000700 | 0x01)
-#define MAX3107_BRG26_B460800 (0x000300 | 0x08)
-#define MAX3107_BRG26_B921600 (0x000100 | 0x0C)
-
-/* Baud rate generator configuration values for internal clock */
-#define MAX3107_BRG13_IB300 (0x008000 | 0x00)
-#define MAX3107_BRG13_IB600 (0x004000 | 0x00)
-#define MAX3107_BRG13_IB1200 (0x002000 | 0x00)
-#define MAX3107_BRG13_IB2400 (0x001000 | 0x00)
-#define MAX3107_BRG13_IB4800 (0x000800 | 0x00)
-#define MAX3107_BRG13_IB9600 (0x000400 | 0x00)
-#define MAX3107_BRG13_IB19200 (0x000200 | 0x00)
-#define MAX3107_BRG13_IB38400 (0x000100 | 0x00)
-#define MAX3107_BRG13_IB57600 (0x000000 | 0x0B)
-#define MAX3107_BRG13_IB115200 (0x000000 | 0x05)
-#define MAX3107_BRG13_IB230400 (0x000000 | 0x03)
-#define MAX3107_BRG13_IB460800 (0x000000 | 0x00)
-#define MAX3107_BRG13_IB921600 (0x000000 | 0x00)
-
-
-struct baud_table {
- int baud;
- u32 new_brg;
-};
-
-struct max3107_port {
- /* UART port structure */
- struct uart_port port;
-
- /* SPI device structure */
- struct spi_device *spi;
-
-#if defined(CONFIG_GPIOLIB)
- /* GPIO chip stucture */
- struct gpio_chip chip;
-#endif
-
- /* Workqueue that does all the magic */
- struct workqueue_struct *workqueue;
- struct work_struct work;
-
- /* Lock for shared data */
- spinlock_t data_lock;
-
- /* Device configuration */
- int ext_clk; /* 1 if external clock used */
- int loopback; /* Current loopback mode state */
- int baud; /* Current baud rate */
-
- /* State flags */
- int suspended; /* Indicates suspend mode */
- int tx_fifo_empty; /* Flag for TX FIFO state */
- int rx_enabled; /* Flag for receiver state */
- int tx_enabled; /* Flag for transmitter state */
-
- u16 irqen_reg; /* Current IRQ enable register value */
- /* Shared data */
- u16 mode1_reg; /* Current mode1 register value*/
- int mode1_commit; /* Flag for setting new mode1 register value */
- u16 lcr_reg; /* Current LCR register value */
- int lcr_commit; /* Flag for setting new LCR register value */
- u32 brg_cfg; /* Current Baud rate generator config */
- int brg_commit; /* Flag for setting new baud rate generator
- * config
- */
- struct baud_table *baud_tbl;
- int handle_irq; /* Indicates that IRQ should be handled */
-
- /* Rx buffer and str*/
- u16 *rxbuf;
- u8 *rxstr;
- /* Tx buffer*/
- u16 *txbuf;
-
- struct max3107_plat *pdata; /* Platform data */
-};
-
-/* Platform data structure */
-struct max3107_plat {
- /* Loopback mode enable */
- int loopback;
- /* External clock enable */
- int ext_clk;
- /* Called during the register initialisation */
- void (*init)(struct max3107_port *s);
- /* Called when the port is found and configured */
- int (*configure)(struct max3107_port *s);
- /* HW suspend function */
- void (*hw_suspend) (struct max3107_port *s, int suspend);
- /* Polling mode enable */
- int polled_mode;
- /* Polling period if polling mode enabled */
- int poll_time;
-};
-
-extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len);
-extern void max3107_hw_susp(struct max3107_port *s, int suspend);
-extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata);
-extern int max3107_remove(struct spi_device *spi);
-extern int max3107_suspend(struct spi_device *spi, pm_message_t state);
-extern int max3107_resume(struct spi_device *spi);
-
-#endif /* _LINUX_SERIAL_MAX3107_H */
diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c
deleted file mode 100644
index 3394b7cc1722..000000000000
--- a/drivers/serial/mcf.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/****************************************************************************/
-
-/*
- * mcf.c -- Freescale ColdFire UART driver
- *
- * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/io.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/nettel.h>
-
-/****************************************************************************/
-
-/*
- * Some boards implement the DTR/DCD lines using GPIO lines, most
- * don't. Dummy out the access macros for those that don't. Those
- * that do should define these macros somewhere in there board
- * specific inlude files.
- */
-#if !defined(mcf_getppdcd)
-#define mcf_getppdcd(p) (1)
-#endif
-#if !defined(mcf_getppdtr)
-#define mcf_getppdtr(p) (1)
-#endif
-#if !defined(mcf_setppdtr)
-#define mcf_setppdtr(p, v) do { } while (0)
-#endif
-
-/****************************************************************************/
-
-/*
- * Local per-uart structure.
- */
-struct mcf_uart {
- struct uart_port port;
- unsigned int sigs; /* Local copy of line sigs */
- unsigned char imr; /* Local IMR mirror */
-};
-
-/****************************************************************************/
-
-static unsigned int mcf_tx_empty(struct uart_port *port)
-{
- return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ?
- TIOCSER_TEMT : 0;
-}
-
-/****************************************************************************/
-
-static unsigned int mcf_get_mctrl(struct uart_port *port)
-{
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
- unsigned int sigs;
-
- sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ?
- 0 : TIOCM_CTS;
- sigs |= (pp->sigs & TIOCM_RTS);
- sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0);
- sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0);
-
- return sigs;
-}
-
-/****************************************************************************/
-
-static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)
-{
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
-
- pp->sigs = sigs;
- mcf_setppdtr(port->line, (sigs & TIOCM_DTR));
- if (sigs & TIOCM_RTS)
- writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
- else
- writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);
-}
-
-/****************************************************************************/
-
-static void mcf_start_tx(struct uart_port *port)
-{
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
-
- pp->imr |= MCFUART_UIR_TXREADY;
- writeb(pp->imr, port->membase + MCFUART_UIMR);
-}
-
-/****************************************************************************/
-
-static void mcf_stop_tx(struct uart_port *port)
-{
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
-
- pp->imr &= ~MCFUART_UIR_TXREADY;
- writeb(pp->imr, port->membase + MCFUART_UIMR);
-}
-
-/****************************************************************************/
-
-static void mcf_stop_rx(struct uart_port *port)
-{
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
-
- pp->imr &= ~MCFUART_UIR_RXREADY;
- writeb(pp->imr, port->membase + MCFUART_UIMR);
-}
-
-/****************************************************************************/
-
-static void mcf_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- if (break_state == -1)
- writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR);
- else
- writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/****************************************************************************/
-
-static void mcf_enable_ms(struct uart_port *port)
-{
-}
-
-/****************************************************************************/
-
-static int mcf_startup(struct uart_port *port)
-{
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Reset UART, get it into known state... */
- writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
- writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
-
- /* Enable the UART transmitter and receiver */
- writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
- port->membase + MCFUART_UCR);
-
- /* Enable RX interrupts now */
- pp->imr = MCFUART_UIR_RXREADY;
- writeb(pp->imr, port->membase + MCFUART_UIMR);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- return 0;
-}
-
-/****************************************************************************/
-
-static void mcf_shutdown(struct uart_port *port)
-{
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Disable all interrupts now */
- pp->imr = 0;
- writeb(pp->imr, port->membase + MCFUART_UIMR);
-
- /* Disable UART transmitter and receiver */
- writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
- writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/****************************************************************************/
-
-static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned long flags;
- unsigned int baud, baudclk;
-#if defined(CONFIG_M5272)
- unsigned int baudfr;
-#endif
- unsigned char mr1, mr2;
-
- baud = uart_get_baud_rate(port, termios, old, 0, 230400);
-#if defined(CONFIG_M5272)
- baudclk = (MCF_BUSCLK / baud) / 32;
- baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16;
-#else
- baudclk = ((MCF_BUSCLK / baud) + 16) / 32;
-#endif
-
- mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
- mr2 = 0;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5: mr1 |= MCFUART_MR1_CS5; break;
- case CS6: mr1 |= MCFUART_MR1_CS6; break;
- case CS7: mr1 |= MCFUART_MR1_CS7; break;
- case CS8:
- default: mr1 |= MCFUART_MR1_CS8; break;
- }
-
- if (termios->c_cflag & PARENB) {
- if (termios->c_cflag & CMSPAR) {
- if (termios->c_cflag & PARODD)
- mr1 |= MCFUART_MR1_PARITYMARK;
- else
- mr1 |= MCFUART_MR1_PARITYSPACE;
- } else {
- if (termios->c_cflag & PARODD)
- mr1 |= MCFUART_MR1_PARITYODD;
- else
- mr1 |= MCFUART_MR1_PARITYEVEN;
- }
- } else {
- mr1 |= MCFUART_MR1_PARITYNONE;
- }
-
- if (termios->c_cflag & CSTOPB)
- mr2 |= MCFUART_MR2_STOP2;
- else
- mr2 |= MCFUART_MR2_STOP1;
-
- if (termios->c_cflag & CRTSCTS) {
- mr1 |= MCFUART_MR1_RXRTS;
- mr2 |= MCFUART_MR2_TXCTS;
- }
-
- spin_lock_irqsave(&port->lock, flags);
- uart_update_timeout(port, termios->c_cflag, baud);
- writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
- writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
- writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR);
- writeb(mr1, port->membase + MCFUART_UMR);
- writeb(mr2, port->membase + MCFUART_UMR);
- writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1);
- writeb((baudclk & 0xff), port->membase + MCFUART_UBG2);
-#if defined(CONFIG_M5272)
- writeb((baudfr & 0x0f), port->membase + MCFUART_UFPD);
-#endif
- writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER,
- port->membase + MCFUART_UCSR);
- writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
- port->membase + MCFUART_UCR);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/****************************************************************************/
-
-static void mcf_rx_chars(struct mcf_uart *pp)
-{
- struct uart_port *port = &pp->port;
- unsigned char status, ch, flag;
-
- while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) {
- ch = readb(port->membase + MCFUART_URB);
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- if (status & MCFUART_USR_RXERR) {
- writeb(MCFUART_UCR_CMDRESETERR,
- port->membase + MCFUART_UCR);
-
- if (status & MCFUART_USR_RXBREAK) {
- port->icount.brk++;
- if (uart_handle_break(port))
- continue;
- } else if (status & MCFUART_USR_RXPARITY) {
- port->icount.parity++;
- } else if (status & MCFUART_USR_RXOVERRUN) {
- port->icount.overrun++;
- } else if (status & MCFUART_USR_RXFRAMING) {
- port->icount.frame++;
- }
-
- status &= port->read_status_mask;
-
- if (status & MCFUART_USR_RXBREAK)
- flag = TTY_BREAK;
- else if (status & MCFUART_USR_RXPARITY)
- flag = TTY_PARITY;
- else if (status & MCFUART_USR_RXFRAMING)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, ch))
- continue;
- uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
- }
-
- tty_flip_buffer_push(port->state->port.tty);
-}
-
-/****************************************************************************/
-
-static void mcf_tx_chars(struct mcf_uart *pp)
-{
- struct uart_port *port = &pp->port;
- struct circ_buf *xmit = &port->state->xmit;
-
- if (port->x_char) {
- /* Send special char - probably flow control */
- writeb(port->x_char, port->membase + MCFUART_UTB);
- port->x_char = 0;
- port->icount.tx++;
- return;
- }
-
- while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) {
- if (xmit->head == xmit->tail)
- break;
- writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
- port->icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (xmit->head == xmit->tail) {
- pp->imr &= ~MCFUART_UIR_TXREADY;
- writeb(pp->imr, port->membase + MCFUART_UIMR);
- }
-}
-
-/****************************************************************************/
-
-static irqreturn_t mcf_interrupt(int irq, void *data)
-{
- struct uart_port *port = data;
- struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
- unsigned int isr;
- irqreturn_t ret = IRQ_NONE;
-
- isr = readb(port->membase + MCFUART_UISR) & pp->imr;
-
- spin_lock(&port->lock);
- if (isr & MCFUART_UIR_RXREADY) {
- mcf_rx_chars(pp);
- ret = IRQ_HANDLED;
- }
- if (isr & MCFUART_UIR_TXREADY) {
- mcf_tx_chars(pp);
- ret = IRQ_HANDLED;
- }
- spin_unlock(&port->lock);
-
- return ret;
-}
-
-/****************************************************************************/
-
-static void mcf_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_MCF;
- port->fifosize = MCFUART_TXFIFOSIZE;
-
- /* Clear mask, so no surprise interrupts. */
- writeb(0, port->membase + MCFUART_UIMR);
-
- if (request_irq(port->irq, mcf_interrupt, IRQF_DISABLED, "UART", port))
- printk(KERN_ERR "MCF: unable to attach ColdFire UART %d "
- "interrupt vector=%d\n", port->line, port->irq);
-}
-
-/****************************************************************************/
-
-static const char *mcf_type(struct uart_port *port)
-{
- return (port->type == PORT_MCF) ? "ColdFire UART" : NULL;
-}
-
-/****************************************************************************/
-
-static int mcf_request_port(struct uart_port *port)
-{
- /* UARTs always present */
- return 0;
-}
-
-/****************************************************************************/
-
-static void mcf_release_port(struct uart_port *port)
-{
- /* Nothing to release... */
-}
-
-/****************************************************************************/
-
-static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF))
- return -EINVAL;
- return 0;
-}
-
-/****************************************************************************/
-
-/*
- * Define the basic serial functions we support.
- */
-static const struct uart_ops mcf_uart_ops = {
- .tx_empty = mcf_tx_empty,
- .get_mctrl = mcf_get_mctrl,
- .set_mctrl = mcf_set_mctrl,
- .start_tx = mcf_start_tx,
- .stop_tx = mcf_stop_tx,
- .stop_rx = mcf_stop_rx,
- .enable_ms = mcf_enable_ms,
- .break_ctl = mcf_break_ctl,
- .startup = mcf_startup,
- .shutdown = mcf_shutdown,
- .set_termios = mcf_set_termios,
- .type = mcf_type,
- .request_port = mcf_request_port,
- .release_port = mcf_release_port,
- .config_port = mcf_config_port,
- .verify_port = mcf_verify_port,
-};
-
-static struct mcf_uart mcf_ports[4];
-
-#define MCF_MAXPORTS ARRAY_SIZE(mcf_ports)
-
-/****************************************************************************/
-#if defined(CONFIG_SERIAL_MCF_CONSOLE)
-/****************************************************************************/
-
-int __init early_mcf_setup(struct mcf_platform_uart *platp)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
- port = &mcf_ports[i].port;
-
- port->line = i;
- port->type = PORT_MCF;
- port->mapbase = platp[i].mapbase;
- port->membase = (platp[i].membase) ? platp[i].membase :
- (unsigned char __iomem *) port->mapbase;
- port->iotype = SERIAL_IO_MEM;
- port->irq = platp[i].irq;
- port->uartclk = MCF_BUSCLK;
- port->flags = ASYNC_BOOT_AUTOCONF;
- port->ops = &mcf_uart_ops;
- }
-
- return 0;
-}
-
-/****************************************************************************/
-
-static void mcf_console_putc(struct console *co, const char c)
-{
- struct uart_port *port = &(mcf_ports + co->index)->port;
- int i;
-
- for (i = 0; (i < 0x10000); i++) {
- if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
- break;
- }
- writeb(c, port->membase + MCFUART_UTB);
- for (i = 0; (i < 0x10000); i++) {
- if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
- break;
- }
-}
-
-/****************************************************************************/
-
-static void mcf_console_write(struct console *co, const char *s, unsigned int count)
-{
- for (; (count); count--, s++) {
- mcf_console_putc(co, *s);
- if (*s == '\n')
- mcf_console_putc(co, '\r');
- }
-}
-
-/****************************************************************************/
-
-static int __init mcf_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = CONFIG_SERIAL_MCF_BAUDRATE;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if ((co->index < 0) || (co->index >= MCF_MAXPORTS))
- co->index = 0;
- port = &mcf_ports[co->index].port;
- if (port->membase == 0)
- 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 mcf_driver;
-
-static struct console mcf_console = {
- .name = "ttyS",
- .write = mcf_console_write,
- .device = uart_console_device,
- .setup = mcf_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &mcf_driver,
-};
-
-static int __init mcf_console_init(void)
-{
- register_console(&mcf_console);
- return 0;
-}
-
-console_initcall(mcf_console_init);
-
-#define MCF_CONSOLE &mcf_console
-
-/****************************************************************************/
-#else
-/****************************************************************************/
-
-#define MCF_CONSOLE NULL
-
-/****************************************************************************/
-#endif /* CONFIG_MCF_CONSOLE */
-/****************************************************************************/
-
-/*
- * Define the mcf UART driver structure.
- */
-static struct uart_driver mcf_driver = {
- .owner = THIS_MODULE,
- .driver_name = "mcf",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = MCF_MAXPORTS,
- .cons = MCF_CONSOLE,
-};
-
-/****************************************************************************/
-
-static int __devinit mcf_probe(struct platform_device *pdev)
-{
- struct mcf_platform_uart *platp = pdev->dev.platform_data;
- struct uart_port *port;
- int i;
-
- for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
- port = &mcf_ports[i].port;
-
- port->line = i;
- port->type = PORT_MCF;
- port->mapbase = platp[i].mapbase;
- port->membase = (platp[i].membase) ? platp[i].membase :
- (unsigned char __iomem *) platp[i].mapbase;
- port->iotype = SERIAL_IO_MEM;
- port->irq = platp[i].irq;
- port->uartclk = MCF_BUSCLK;
- port->ops = &mcf_uart_ops;
- port->flags = ASYNC_BOOT_AUTOCONF;
-
- uart_add_one_port(&mcf_driver, port);
- }
-
- return 0;
-}
-
-/****************************************************************************/
-
-static int __devexit mcf_remove(struct platform_device *pdev)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; (i < MCF_MAXPORTS); i++) {
- port = &mcf_ports[i].port;
- if (port)
- uart_remove_one_port(&mcf_driver, port);
- }
-
- return 0;
-}
-
-/****************************************************************************/
-
-static struct platform_driver mcf_platform_driver = {
- .probe = mcf_probe,
- .remove = __devexit_p(mcf_remove),
- .driver = {
- .name = "mcfuart",
- .owner = THIS_MODULE,
- },
-};
-
-/****************************************************************************/
-
-static int __init mcf_init(void)
-{
- int rc;
-
- printk("ColdFire internal UART serial driver\n");
-
- rc = uart_register_driver(&mcf_driver);
- if (rc)
- return rc;
- rc = platform_driver_register(&mcf_platform_driver);
- if (rc)
- return rc;
- return 0;
-}
-
-/****************************************************************************/
-
-static void __exit mcf_exit(void)
-{
- platform_driver_unregister(&mcf_platform_driver);
- uart_unregister_driver(&mcf_driver);
-}
-
-/****************************************************************************/
-
-module_init(mcf_init);
-module_exit(mcf_exit);
-
-MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
-MODULE_DESCRIPTION("Freescale ColdFire UART driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mcfuart");
-
-/****************************************************************************/
diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c
deleted file mode 100644
index d40010a22ecd..000000000000
--- a/drivers/serial/mfd.c
+++ /dev/null
@@ -1,1513 +0,0 @@
-/*
- * mfd.c: driver for High Speed UART device of Intel Medfield platform
- *
- * Refer pxa.c, 8250.c and some other drivers in drivers/serial/
- *
- * (C) Copyright 2010 Intel Corporation
- *
- * 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; version 2
- * of the License.
- */
-
-/* Notes:
- * 1. DMA channel allocation: 0/1 channel are assigned to port 0,
- * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans
- * are used for RX, odd chans for TX
- *
- * 2. In A0 stepping, UART will not support TX half empty flag
- *
- * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always
- * asserted, only when the HW is reset the DDCD and DDSR will
- * be triggered
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/slab.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial_mfd.h>
-#include <linux/dma-mapping.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-
-#define MFD_HSU_A0_STEPPING 1
-
-#define HSU_DMA_BUF_SIZE 2048
-
-#define chan_readl(chan, offset) readl(chan->reg + offset)
-#define chan_writel(chan, offset, val) writel(val, chan->reg + offset)
-
-#define mfd_readl(obj, offset) readl(obj->reg + offset)
-#define mfd_writel(obj, offset, val) writel(val, obj->reg + offset)
-
-#define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10)
-
-struct hsu_dma_buffer {
- u8 *buf;
- dma_addr_t dma_addr;
- u32 dma_size;
- u32 ofs;
-};
-
-struct hsu_dma_chan {
- u32 id;
- enum dma_data_direction dirt;
- struct uart_hsu_port *uport;
- void __iomem *reg;
- struct timer_list rx_timer; /* only needed by RX channel */
-};
-
-struct uart_hsu_port {
- struct uart_port port;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr;
- unsigned int lsr_break_flag;
- char name[12];
- int index;
- struct device *dev;
-
- struct hsu_dma_chan *txc;
- struct hsu_dma_chan *rxc;
- struct hsu_dma_buffer txbuf;
- struct hsu_dma_buffer rxbuf;
- int use_dma; /* flag for DMA/PIO */
- int running;
- int dma_tx_on;
-};
-
-/* Top level data structure of HSU */
-struct hsu_port {
- void __iomem *reg;
- unsigned long paddr;
- unsigned long iolen;
- u32 irq;
-
- struct uart_hsu_port port[3];
- struct hsu_dma_chan chans[10];
-
- struct dentry *debugfs;
-};
-
-static inline unsigned int serial_in(struct uart_hsu_port *up, int offset)
-{
- unsigned int val;
-
- if (offset > UART_MSR) {
- offset <<= 2;
- val = readl(up->port.membase + offset);
- } else
- val = (unsigned int)readb(up->port.membase + offset);
-
- return val;
-}
-
-static inline void serial_out(struct uart_hsu_port *up, int offset, int value)
-{
- if (offset > UART_MSR) {
- offset <<= 2;
- writel(value, up->port.membase + offset);
- } else {
- unsigned char val = value & 0xff;
- writeb(val, up->port.membase + offset);
- }
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#define HSU_REGS_BUFSIZE 1024
-
-static int hsu_show_regs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t port_show_regs(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct uart_hsu_port *up = file->private_data;
- char *buf;
- u32 len = 0;
- ssize_t ret;
-
- buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
- if (!buf)
- return 0;
-
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "MFD HSU port[%d] regs:\n", up->index);
-
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "=================================\n");
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "IER: \t\t0x%08x\n", serial_in(up, UART_IER));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "PS: \t\t0x%08x\n", serial_in(up, UART_PS));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
-
- if (len > HSU_REGS_BUFSIZE)
- len = HSU_REGS_BUFSIZE;
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
- return ret;
-}
-
-static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct hsu_dma_chan *chan = file->private_data;
- char *buf;
- u32 len = 0;
- ssize_t ret;
-
- buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
- if (!buf)
- return 0;
-
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "MFD HSU DMA channel [%d] regs:\n", chan->id);
-
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "=================================\n");
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR));
- len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
- "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
-
- if (len > HSU_REGS_BUFSIZE)
- len = HSU_REGS_BUFSIZE;
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
- return ret;
-}
-
-static const struct file_operations port_regs_ops = {
- .owner = THIS_MODULE,
- .open = hsu_show_regs_open,
- .read = port_show_regs,
- .llseek = default_llseek,
-};
-
-static const struct file_operations dma_regs_ops = {
- .owner = THIS_MODULE,
- .open = hsu_show_regs_open,
- .read = dma_show_regs,
- .llseek = default_llseek,
-};
-
-static int hsu_debugfs_init(struct hsu_port *hsu)
-{
- int i;
- char name[32];
-
- hsu->debugfs = debugfs_create_dir("hsu", NULL);
- if (!hsu->debugfs)
- return -ENOMEM;
-
- for (i = 0; i < 3; i++) {
- snprintf(name, sizeof(name), "port_%d_regs", i);
- debugfs_create_file(name, S_IFREG | S_IRUGO,
- hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops);
- }
-
- for (i = 0; i < 6; i++) {
- snprintf(name, sizeof(name), "dma_chan_%d_regs", i);
- debugfs_create_file(name, S_IFREG | S_IRUGO,
- hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops);
- }
-
- return 0;
-}
-
-static void hsu_debugfs_remove(struct hsu_port *hsu)
-{
- if (hsu->debugfs)
- debugfs_remove_recursive(hsu->debugfs);
-}
-
-#else
-static inline int hsu_debugfs_init(struct hsu_port *hsu)
-{
- return 0;
-}
-
-static inline void hsu_debugfs_remove(struct hsu_port *hsu)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
-
-static void serial_hsu_enable_ms(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-void hsu_dma_tx(struct uart_hsu_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- struct hsu_dma_buffer *dbuf = &up->txbuf;
- int count;
-
- /* test_and_set_bit may be better, but anyway it's in lock protected mode */
- if (up->dma_tx_on)
- return;
-
- /* Update the circ buf info */
- xmit->tail += dbuf->ofs;
- xmit->tail &= UART_XMIT_SIZE - 1;
-
- up->port.icount.tx += dbuf->ofs;
- dbuf->ofs = 0;
-
- /* Disable the channel */
- chan_writel(up->txc, HSU_CH_CR, 0x0);
-
- if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) {
- dma_sync_single_for_device(up->port.dev,
- dbuf->dma_addr,
- dbuf->dma_size,
- DMA_TO_DEVICE);
-
- count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- dbuf->ofs = count;
-
- /* Reprogram the channel */
- chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail);
- chan_writel(up->txc, HSU_CH_D0TSR, count);
-
- /* Reenable the channel */
- chan_writel(up->txc, HSU_CH_DCR, 0x1
- | (0x1 << 8)
- | (0x1 << 16)
- | (0x1 << 24));
- up->dma_tx_on = 1;
- chan_writel(up->txc, HSU_CH_CR, 0x1);
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-}
-
-/* The buffer is already cache coherent */
-void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf)
-{
- dbuf->ofs = 0;
-
- chan_writel(rxc, HSU_CH_BSR, 32);
- chan_writel(rxc, HSU_CH_MOTSR, 4);
-
- chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr);
- chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size);
- chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8)
- | (0x1 << 16)
- | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
- );
- chan_writel(rxc, HSU_CH_CR, 0x3);
-
- mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
-}
-
-/* Protected by spin_lock_irqsave(port->lock) */
-static void serial_hsu_start_tx(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
-
- if (up->use_dma) {
- hsu_dma_tx(up);
- } else if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial_hsu_stop_tx(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- struct hsu_dma_chan *txc = up->txc;
-
- if (up->use_dma)
- chan_writel(txc, HSU_CH_CR, 0x0);
- else if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-/* This is always called in spinlock protected mode, so
- * modify timeout timer is safe here */
-void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
-{
- struct hsu_dma_buffer *dbuf = &up->rxbuf;
- struct hsu_dma_chan *chan = up->rxc;
- struct uart_port *port = &up->port;
- struct tty_struct *tty = port->state->port.tty;
- int count;
-
- if (!tty)
- return;
-
- /*
- * First need to know how many is already transferred,
- * then check if its a timeout DMA irq, and return
- * the trail bytes out, push them up and reenable the
- * channel
- */
-
- /* Timeout IRQ, need wait some time, see Errata 2 */
- if (int_sts & 0xf00)
- udelay(2);
-
- /* Stop the channel */
- chan_writel(chan, HSU_CH_CR, 0x0);
-
- count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
- if (!count) {
- /* Restart the channel before we leave */
- chan_writel(chan, HSU_CH_CR, 0x3);
- return;
- }
- del_timer(&chan->rx_timer);
-
- dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
- dbuf->dma_size, DMA_FROM_DEVICE);
-
- /*
- * Head will only wrap around when we recycle
- * the DMA buffer, and when that happens, we
- * explicitly set tail to 0. So head will
- * always be greater than tail.
- */
- tty_insert_flip_string(tty, dbuf->buf, count);
- port->icount.rx += count;
-
- dma_sync_single_for_device(up->port.dev, dbuf->dma_addr,
- dbuf->dma_size, DMA_FROM_DEVICE);
-
- /* Reprogram the channel */
- chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr);
- chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size);
- chan_writel(chan, HSU_CH_DCR, 0x1
- | (0x1 << 8)
- | (0x1 << 16)
- | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
- );
- tty_flip_buffer_push(tty);
-
- chan_writel(chan, HSU_CH_CR, 0x3);
- chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ;
- add_timer(&chan->rx_timer);
-
-}
-
-static void serial_hsu_stop_rx(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- struct hsu_dma_chan *chan = up->rxc;
-
- if (up->use_dma)
- chan_writel(chan, HSU_CH_CR, 0x2);
- else {
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static inline void receive_chars(struct uart_hsu_port *up, int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned int ch, flag;
- unsigned int max_count = 256;
-
- if (!tty)
- return;
-
- do {
- ch = serial_in(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE))) {
-
- dev_warn(up->dev, "We really rush into ERR/BI case"
- "status = 0x%02x", *status);
- /* For statistics only */
- if (*status & UART_LSR_BI) {
- *status &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (*status & UART_LSR_PE)
- up->port.icount.parity++;
- else if (*status & UART_LSR_FE)
- up->port.icount.frame++;
- if (*status & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /* Mask off conditions which should be ignored. */
- *status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
- if (up->port.cons &&
- up->port.cons->index == up->port.line) {
- /* Recover the break flag from console xmit */
- *status |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-#endif
- if (*status & UART_LSR_BI) {
- flag = TTY_BREAK;
- } else if (*status & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (*status & UART_LSR_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
-
- uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
- ignore_char:
- *status = serial_in(up, UART_LSR);
- } while ((*status & UART_LSR_DR) && max_count--);
- tty_flip_buffer_push(tty);
-}
-
-static void transmit_chars(struct uart_hsu_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_out(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_hsu_stop_tx(&up->port);
- return;
- }
-
-#ifndef MFD_HSU_A0_STEPPING
- count = up->port.fifosize / 2;
-#else
- /*
- * A0 only supports fully empty IRQ, and the first char written
- * into it won't clear the EMPT bit, so we may need be cautious
- * by useing a shorter buffer
- */
- count = up->port.fifosize - 4;
-#endif
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit))
- serial_hsu_stop_tx(&up->port);
-}
-
-static inline void check_modem_status(struct uart_hsu_port *up)
-{
- int status;
-
- status = serial_in(up, UART_MSR);
-
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return;
-
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- /* We may only get DDCD when HW init and reset */
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- /* Will start/stop_tx accordingly */
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static irqreturn_t port_irq(int irq, void *dev_id)
-{
- struct uart_hsu_port *up = dev_id;
- unsigned int iir, lsr;
- unsigned long flags;
-
- if (unlikely(!up->running))
- return IRQ_NONE;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->use_dma) {
- lsr = serial_in(up, UART_LSR);
- if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE)))
- dev_warn(up->dev,
- "Got lsr irq while using DMA, lsr = 0x%2x\n",
- lsr);
- check_modem_status(up);
- spin_unlock_irqrestore(&up->port.lock, flags);
- return IRQ_HANDLED;
- }
-
- iir = serial_in(up, UART_IIR);
- if (iir & UART_IIR_NO_INT) {
- spin_unlock_irqrestore(&up->port.lock, flags);
- return IRQ_NONE;
- }
-
- lsr = serial_in(up, UART_LSR);
- if (lsr & UART_LSR_DR)
- receive_chars(up, &lsr);
- check_modem_status(up);
-
- /* lsr will be renewed during the receive_chars */
- if (lsr & UART_LSR_THRE)
- transmit_chars(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
- return IRQ_HANDLED;
-}
-
-static inline void dma_chan_irq(struct hsu_dma_chan *chan)
-{
- struct uart_hsu_port *up = chan->uport;
- unsigned long flags;
- u32 int_sts;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- if (!up->use_dma || !up->running)
- goto exit;
-
- /*
- * No matter what situation, need read clear the IRQ status
- * There is a bug, see Errata 5, HSD 2900918
- */
- int_sts = chan_readl(chan, HSU_CH_SR);
-
- /* Rx channel */
- if (chan->dirt == DMA_FROM_DEVICE)
- hsu_dma_rx(up, int_sts);
-
- /* Tx channel */
- if (chan->dirt == DMA_TO_DEVICE) {
- chan_writel(chan, HSU_CH_CR, 0x0);
- up->dma_tx_on = 0;
- hsu_dma_tx(up);
- }
-
-exit:
- spin_unlock_irqrestore(&up->port.lock, flags);
- return;
-}
-
-static irqreturn_t dma_irq(int irq, void *dev_id)
-{
- struct hsu_port *hsu = dev_id;
- u32 int_sts, i;
-
- int_sts = mfd_readl(hsu, HSU_GBL_DMAISR);
-
- /* Currently we only have 6 channels may be used */
- for (i = 0; i < 6; i++) {
- if (int_sts & 0x1)
- dma_chan_irq(&hsu->chans[i]);
- int_sts >>= 1;
- }
-
- return IRQ_HANDLED;
-}
-
-static unsigned int serial_hsu_tx_empty(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int serial_hsu_get_mctrl(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- unsigned char status;
- unsigned int ret;
-
- status = serial_in(up, UART_MSR);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr |= up->mcr;
-
- serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_hsu_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/*
- * What special to do:
- * 1. chose the 64B fifo mode
- * 2. make sure not to select half empty mode for A0 stepping
- * 3. start dma or pio depends on configuration
- * 4. we only allocate dma memory when needed
- */
-static int serial_hsu_startup(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- unsigned long flags;
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_out(up, UART_FCR, 0);
-
- /* Clear the interrupt registers. */
- (void) serial_in(up, UART_LSR);
- (void) serial_in(up, UART_RX);
- (void) serial_in(up, UART_IIR);
- (void) serial_in(up, UART_MSR);
-
- /* Now, initialize the UART, default is 8n1 */
- serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->port.mctrl |= TIOCM_OUT2;
- serial_hsu_set_mctrl(&up->port, up->port.mctrl);
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- if (!up->use_dma)
- up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE;
- else
- up->ier = 0;
- serial_out(up, UART_IER, up->ier);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /* DMA init */
- if (up->use_dma) {
- struct hsu_dma_buffer *dbuf;
- struct circ_buf *xmit = &port->state->xmit;
-
- up->dma_tx_on = 0;
-
- /* First allocate the RX buffer */
- dbuf = &up->rxbuf;
- dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL);
- if (!dbuf->buf) {
- up->use_dma = 0;
- goto exit;
- }
- dbuf->dma_addr = dma_map_single(port->dev,
- dbuf->buf,
- HSU_DMA_BUF_SIZE,
- DMA_FROM_DEVICE);
- dbuf->dma_size = HSU_DMA_BUF_SIZE;
-
- /* Start the RX channel right now */
- hsu_dma_start_rx_chan(up->rxc, dbuf);
-
- /* Next init the TX DMA */
- dbuf = &up->txbuf;
- dbuf->buf = xmit->buf;
- dbuf->dma_addr = dma_map_single(port->dev,
- dbuf->buf,
- UART_XMIT_SIZE,
- DMA_TO_DEVICE);
- dbuf->dma_size = UART_XMIT_SIZE;
-
- /* This should not be changed all around */
- chan_writel(up->txc, HSU_CH_BSR, 32);
- chan_writel(up->txc, HSU_CH_MOTSR, 4);
- dbuf->ofs = 0;
- }
-
-exit:
- /* And clear the interrupt registers again for luck. */
- (void) serial_in(up, UART_LSR);
- (void) serial_in(up, UART_RX);
- (void) serial_in(up, UART_IIR);
- (void) serial_in(up, UART_MSR);
-
- up->running = 1;
- return 0;
-}
-
-static void serial_hsu_shutdown(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- unsigned long flags;
-
- del_timer_sync(&up->rxc->rx_timer);
-
- /* Disable interrupts from this port */
- up->ier = 0;
- serial_out(up, UART_IER, 0);
- up->running = 0;
-
- spin_lock_irqsave(&up->port.lock, flags);
- up->port.mctrl &= ~TIOCM_OUT2;
- serial_hsu_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /* Disable break condition and FIFOs */
- serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT);
- serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- struct tty_struct *tty = port->state->port.tty;
- unsigned char cval, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
- u32 ps, mul;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- /* CMSPAR isn't supported by this driver */
- if (tty)
- tty->termios->c_cflag &= ~CMSPAR;
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-
- /*
- * The base clk is 50Mhz, and the baud rate come from:
- * baud = 50M * MUL / (DIV * PS * DLAB)
- *
- * For those basic low baud rate we can get the direct
- * scalar from 2746800, like 115200 = 2746800/24. For those
- * higher baud rate, we handle them case by case, mainly by
- * adjusting the MUL/PS registers, and DIV register is kept
- * as default value 0x3d09 to make things simple
- */
- baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
-
- quot = 1;
- ps = 0x10;
- mul = 0x3600;
- switch (baud) {
- case 3500000:
- mul = 0x3345;
- ps = 0xC;
- break;
- case 1843200:
- mul = 0x2400;
- break;
- case 3000000:
- case 2500000:
- case 2000000:
- case 1500000:
- case 1000000:
- case 500000:
- /* mul/ps/quot = 0x9C4/0x10/0x1 will make a 500000 bps */
- mul = baud / 500000 * 0x9C4;
- break;
- default:
- /* Use uart_get_divisor to get quot for other baud rates */
- quot = 0;
- }
-
- if (!quot)
- quot = uart_get_divisor(port, baud);
-
- if ((up->port.uartclk / quot) < (2400 * 16))
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
- else if ((up->port.uartclk / quot) < (230400 * 16))
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B;
- else
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B;
-
- fcr |= UART_FCR_HSU_64B_FIFO;
-#ifdef MFD_HSU_A0_STEPPING
- /* A0 doesn't support half empty IRQ */
- fcr |= UART_FCR_FULL_EMPT_TXI;
-#endif
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /* Update the per-port timeout */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /* Characters to ignore */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /* Ignore all characters if CREAD is not set */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts, disable
- * MSI by default
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
-
- serial_out(up, UART_IER, up->ier);
-
- if (termios->c_cflag & CRTSCTS)
- up->mcr |= UART_MCR_AFE | UART_MCR_RTS;
- else
- up->mcr &= ~UART_MCR_AFE;
-
- serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
- serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
- serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
- serial_out(up, UART_LCR, cval); /* reset DLAB */
- serial_out(up, UART_MUL, mul); /* set MUL */
- serial_out(up, UART_PS, ps); /* set PS */
- up->lcr = cval; /* Save LCR */
- serial_hsu_set_mctrl(&up->port, up->port.mctrl);
- serial_out(up, UART_FCR, fcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_hsu_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
-}
-
-static void serial_hsu_release_port(struct uart_port *port)
-{
-}
-
-static int serial_hsu_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void serial_hsu_config_port(struct uart_port *port, int flags)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- up->port.type = PORT_MFD;
-}
-
-static int
-serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- /* We don't want the core code to modify any port params */
- return -EINVAL;
-}
-
-static const char *
-serial_hsu_type(struct uart_port *port)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
- return up->name;
-}
-
-/* Mainly for uart console use */
-static struct uart_hsu_port *serial_hsu_ports[3];
-static struct uart_driver serial_hsu_reg;
-
-#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/* Wait for transmitter & holding register to empty */
-static inline void wait_for_xmitr(struct uart_hsu_port *up)
-{
- unsigned int status, tmout = 1000;
-
- /* Wait up to 1ms for the character to be sent. */
- do {
- status = serial_in(up, UART_LSR);
-
- if (status & UART_LSR_BI)
- up->lsr_break_flag = UART_LSR_BI;
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while (!(status & BOTH_EMPTY));
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
- udelay(1);
- }
-}
-
-static void serial_hsu_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_hsu_port *up =
- container_of(port, struct uart_hsu_port, port);
-
- wait_for_xmitr(up);
- serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void
-serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_hsu_port *up = serial_hsu_ports[co->index];
- unsigned long flags;
- unsigned int ier;
- int locked = 1;
-
- local_irq_save(flags);
- if (up->port.sysrq)
- locked = 0;
- else if (oops_in_progress) {
- locked = spin_trylock(&up->port.lock);
- } else
- spin_lock(&up->port.lock);
-
- /* First save the IER then disable the interrupts */
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
-
- uart_console_write(&up->port, s, count, serial_hsu_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- serial_out(up, UART_IER, ier);
-
- if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
-}
-
-static struct console serial_hsu_console;
-
-static int __init
-serial_hsu_console_setup(struct console *co, char *options)
-{
- struct uart_hsu_port *up;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- int ret;
-
- if (co->index == -1 || co->index >= serial_hsu_reg.nr)
- co->index = 0;
- up = serial_hsu_ports[co->index];
- if (!up)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- ret = uart_set_options(&up->port, co, baud, parity, bits, flow);
-
- return ret;
-}
-
-static struct console serial_hsu_console = {
- .name = "ttyMFD",
- .write = serial_hsu_console_write,
- .device = uart_console_device,
- .setup = serial_hsu_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = 2,
- .data = &serial_hsu_reg,
-};
-#endif
-
-struct uart_ops serial_hsu_pops = {
- .tx_empty = serial_hsu_tx_empty,
- .set_mctrl = serial_hsu_set_mctrl,
- .get_mctrl = serial_hsu_get_mctrl,
- .stop_tx = serial_hsu_stop_tx,
- .start_tx = serial_hsu_start_tx,
- .stop_rx = serial_hsu_stop_rx,
- .enable_ms = serial_hsu_enable_ms,
- .break_ctl = serial_hsu_break_ctl,
- .startup = serial_hsu_startup,
- .shutdown = serial_hsu_shutdown,
- .set_termios = serial_hsu_set_termios,
- .pm = serial_hsu_pm,
- .type = serial_hsu_type,
- .release_port = serial_hsu_release_port,
- .request_port = serial_hsu_request_port,
- .config_port = serial_hsu_config_port,
- .verify_port = serial_hsu_verify_port,
-};
-
-static struct uart_driver serial_hsu_reg = {
- .owner = THIS_MODULE,
- .driver_name = "MFD serial",
- .dev_name = "ttyMFD",
- .major = TTY_MAJOR,
- .minor = 128,
- .nr = 3,
-};
-
-#ifdef CONFIG_PM
-static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- void *priv = pci_get_drvdata(pdev);
- struct uart_hsu_port *up;
-
- /* Make sure this is not the internal dma controller */
- if (priv && (pdev->device != 0x081E)) {
- up = priv;
- uart_suspend_port(&serial_hsu_reg, &up->port);
- }
-
- pci_save_state(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- return 0;
-}
-
-static int serial_hsu_resume(struct pci_dev *pdev)
-{
- void *priv = pci_get_drvdata(pdev);
- struct uart_hsu_port *up;
- int ret;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
-
- ret = pci_enable_device(pdev);
- if (ret)
- dev_warn(&pdev->dev,
- "HSU: can't re-enable device, try to continue\n");
-
- if (priv && (pdev->device != 0x081E)) {
- up = priv;
- uart_resume_port(&serial_hsu_reg, &up->port);
- }
- return 0;
-}
-#else
-#define serial_hsu_suspend NULL
-#define serial_hsu_resume NULL
-#endif
-
-/* temp global pointer before we settle down on using one or four PCI dev */
-static struct hsu_port *phsu;
-
-static int serial_hsu_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct uart_hsu_port *uport;
- int index, ret;
-
- printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n",
- pdev->vendor, pdev->device);
-
- switch (pdev->device) {
- case 0x081B:
- index = 0;
- break;
- case 0x081C:
- index = 1;
- break;
- case 0x081D:
- index = 2;
- break;
- case 0x081E:
- /* internal DMA controller */
- index = 3;
- break;
- default:
- dev_err(&pdev->dev, "HSU: out of index!");
- return -ENODEV;
- }
-
- ret = pci_enable_device(pdev);
- if (ret)
- return ret;
-
- if (index == 3) {
- /* DMA controller */
- ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu);
- if (ret) {
- dev_err(&pdev->dev, "can not get IRQ\n");
- goto err_disable;
- }
- pci_set_drvdata(pdev, phsu);
- } else {
- /* UART port 0~2 */
- uport = &phsu->port[index];
- uport->port.irq = pdev->irq;
- uport->port.dev = &pdev->dev;
- uport->dev = &pdev->dev;
-
- ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport);
- if (ret) {
- dev_err(&pdev->dev, "can not get IRQ\n");
- goto err_disable;
- }
- uart_add_one_port(&serial_hsu_reg, &uport->port);
-
-#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
- if (index == 2) {
- register_console(&serial_hsu_console);
- uport->port.cons = &serial_hsu_console;
- }
-#endif
- pci_set_drvdata(pdev, uport);
- }
-
- return 0;
-
-err_disable:
- pci_disable_device(pdev);
- return ret;
-}
-
-static void hsu_dma_rx_timeout(unsigned long data)
-{
- struct hsu_dma_chan *chan = (void *)data;
- struct uart_hsu_port *up = chan->uport;
- struct hsu_dma_buffer *dbuf = &up->rxbuf;
- int count = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
-
- if (!count) {
- mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
- goto exit;
- }
-
- hsu_dma_rx(up, 0);
-exit:
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void hsu_global_init(void)
-{
- struct hsu_port *hsu;
- struct uart_hsu_port *uport;
- struct hsu_dma_chan *dchan;
- int i, ret;
-
- hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL);
- if (!hsu)
- return;
-
- /* Get basic io resource and map it */
- hsu->paddr = 0xffa28000;
- hsu->iolen = 0x1000;
-
- if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global")))
- pr_warning("HSU: error in request mem region\n");
-
- hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen);
- if (!hsu->reg) {
- pr_err("HSU: error in ioremap\n");
- ret = -ENOMEM;
- goto err_free_region;
- }
-
- /* Initialise the 3 UART ports */
- uport = hsu->port;
- for (i = 0; i < 3; i++) {
- uport->port.type = PORT_MFD;
- uport->port.iotype = UPIO_MEM;
- uport->port.mapbase = (resource_size_t)hsu->paddr
- + HSU_PORT_REG_OFFSET
- + i * HSU_PORT_REG_LENGTH;
- uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET
- + i * HSU_PORT_REG_LENGTH;
-
- sprintf(uport->name, "hsu_port%d", i);
- uport->port.fifosize = 64;
- uport->port.ops = &serial_hsu_pops;
- uport->port.line = i;
- uport->port.flags = UPF_IOREMAP;
- /* set the scalable maxim support rate to 2746800 bps */
- uport->port.uartclk = 115200 * 24 * 16;
-
- uport->running = 0;
- uport->txc = &hsu->chans[i * 2];
- uport->rxc = &hsu->chans[i * 2 + 1];
-
- serial_hsu_ports[i] = uport;
- uport->index = i;
- uport++;
- }
-
- /* Initialise 6 dma channels */
- dchan = hsu->chans;
- for (i = 0; i < 6; i++) {
- dchan->id = i;
- dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- dchan->uport = &hsu->port[i/2];
- dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +
- i * HSU_DMA_CHANS_REG_LENGTH;
-
- /* Work around for RX */
- if (dchan->dirt == DMA_FROM_DEVICE) {
- init_timer(&dchan->rx_timer);
- dchan->rx_timer.function = hsu_dma_rx_timeout;
- dchan->rx_timer.data = (unsigned long)dchan;
- }
- dchan++;
- }
-
- phsu = hsu;
- hsu_debugfs_init(hsu);
- return;
-
-err_free_region:
- release_mem_region(hsu->paddr, hsu->iolen);
- kfree(hsu);
- return;
-}
-
-static void serial_hsu_remove(struct pci_dev *pdev)
-{
- void *priv = pci_get_drvdata(pdev);
- struct uart_hsu_port *up;
-
- if (!priv)
- return;
-
- /* For port 0/1/2, priv is the address of uart_hsu_port */
- if (pdev->device != 0x081E) {
- up = priv;
- uart_remove_one_port(&serial_hsu_reg, &up->port);
- }
-
- pci_set_drvdata(pdev, NULL);
- free_irq(pdev->irq, priv);
- pci_disable_device(pdev);
-}
-
-/* First 3 are UART ports, and the 4th is the DMA */
-static const struct pci_device_id pci_ids[] __devinitdata = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) },
- {},
-};
-
-static struct pci_driver hsu_pci_driver = {
- .name = "HSU serial",
- .id_table = pci_ids,
- .probe = serial_hsu_probe,
- .remove = __devexit_p(serial_hsu_remove),
- .suspend = serial_hsu_suspend,
- .resume = serial_hsu_resume,
-};
-
-static int __init hsu_pci_init(void)
-{
- int ret;
-
- hsu_global_init();
-
- ret = uart_register_driver(&serial_hsu_reg);
- if (ret)
- return ret;
-
- return pci_register_driver(&hsu_pci_driver);
-}
-
-static void __exit hsu_pci_exit(void)
-{
- pci_unregister_driver(&hsu_pci_driver);
- uart_unregister_driver(&serial_hsu_reg);
-
- hsu_debugfs_remove(phsu);
-
- kfree(phsu);
-}
-
-module_init(hsu_pci_init);
-module_exit(hsu_pci_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:medfield-hsu");
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
deleted file mode 100644
index 126ec7f568ec..000000000000
--- a/drivers/serial/mpc52xx_uart.c
+++ /dev/null
@@ -1,1527 +0,0 @@
-/*
- * Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs.
- *
- * FIXME According to the usermanual the status bits in the status register
- * are only updated when the peripherals access the FIFO and not when the
- * CPU access them. So since we use this bits to know when we stop writing
- * and reading, they may not be updated in-time and a race condition may
- * exists. But I haven't be able to prove this and I don't care. But if
- * any problem arises, it might worth checking. The TX/RX FIFO Stats
- * registers should be used in addition.
- * Update: Actually, they seem updated ... At least the bits we use.
- *
- *
- * Maintainer : Sylvain Munaut <tnt@246tNt.com>
- *
- * Some of the code has been inspired/copied from the 2.4 code written
- * by Dale Farnsworth <dfarnsworth@mvista.com>.
- *
- * Copyright (C) 2008 Freescale Semiconductor Inc.
- * John Rigby <jrigby@gmail.com>
- * Added support for MPC5121
- * Copyright (C) 2006 Secret Lab Technologies Ltd.
- * Grant Likely <grant.likely@secretlab.ca>
- * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2003 MontaVista, Software, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#undef DEBUG
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-
-#include <asm/mpc52xx.h>
-#include <asm/mpc52xx_psc.h>
-
-#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-
-/* We've been assigned a range on the "Low-density serial ports" major */
-#define SERIAL_PSC_MAJOR 204
-#define SERIAL_PSC_MINOR 148
-
-
-#define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */
-
-
-static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
- /* Rem: - We use the read_status_mask as a shadow of
- * psc->mpc52xx_psc_imr
- * - It's important that is array is all zero on start as we
- * use it to know if it's initialized or not ! If it's not sure
- * it's cleared, then a memset(...,0,...) should be added to
- * the console_init
- */
-
-/* lookup table for matching device nodes to index numbers */
-static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
-
-static void mpc52xx_uart_of_enumerate(void);
-
-
-#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
-
-
-/* Forward declaration of the interruption handling routine */
-static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id);
-static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port);
-
-
-/* Simple macro to test if a port is console or not. This one is taken
- * for serial_core.c and maybe should be moved to serial_core.h ? */
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-#define uart_console(port) \
- ((port)->cons && (port)->cons->index == (port)->line)
-#else
-#define uart_console(port) (0)
-#endif
-
-/* ======================================================================== */
-/* PSC fifo operations for isolating differences between 52xx and 512x */
-/* ======================================================================== */
-
-struct psc_ops {
- void (*fifo_init)(struct uart_port *port);
- int (*raw_rx_rdy)(struct uart_port *port);
- int (*raw_tx_rdy)(struct uart_port *port);
- int (*rx_rdy)(struct uart_port *port);
- int (*tx_rdy)(struct uart_port *port);
- int (*tx_empty)(struct uart_port *port);
- void (*stop_rx)(struct uart_port *port);
- void (*start_tx)(struct uart_port *port);
- void (*stop_tx)(struct uart_port *port);
- void (*rx_clr_irq)(struct uart_port *port);
- void (*tx_clr_irq)(struct uart_port *port);
- void (*write_char)(struct uart_port *port, unsigned char c);
- unsigned char (*read_char)(struct uart_port *port);
- void (*cw_disable_ints)(struct uart_port *port);
- void (*cw_restore_ints)(struct uart_port *port);
- unsigned int (*set_baudrate)(struct uart_port *port,
- struct ktermios *new,
- struct ktermios *old);
- int (*clock)(struct uart_port *port, int enable);
- int (*fifoc_init)(void);
- void (*fifoc_uninit)(void);
- void (*get_irq)(struct uart_port *, struct device_node *);
- irqreturn_t (*handle_irq)(struct uart_port *port);
-};
-
-/* setting the prescaler and divisor reg is common for all chips */
-static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc,
- u16 prescaler, unsigned int divisor)
-{
- /* select prescaler */
- out_be16(&psc->mpc52xx_psc_clock_select, prescaler);
- out_8(&psc->ctur, divisor >> 8);
- out_8(&psc->ctlr, divisor & 0xff);
-}
-
-#ifdef CONFIG_PPC_MPC52xx
-#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
-static void mpc52xx_psc_fifo_init(struct uart_port *port)
-{
- struct mpc52xx_psc __iomem *psc = PSC(port);
- struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port);
-
- out_8(&fifo->rfcntl, 0x00);
- out_be16(&fifo->rfalarm, 0x1ff);
- out_8(&fifo->tfcntl, 0x07);
- out_be16(&fifo->tfalarm, 0x80);
-
- port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY;
- out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
-}
-
-static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port)
-{
- return in_be16(&PSC(port)->mpc52xx_psc_status)
- & MPC52xx_PSC_SR_RXRDY;
-}
-
-static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port)
-{
- return in_be16(&PSC(port)->mpc52xx_psc_status)
- & MPC52xx_PSC_SR_TXRDY;
-}
-
-
-static int mpc52xx_psc_rx_rdy(struct uart_port *port)
-{
- return in_be16(&PSC(port)->mpc52xx_psc_isr)
- & port->read_status_mask
- & MPC52xx_PSC_IMR_RXRDY;
-}
-
-static int mpc52xx_psc_tx_rdy(struct uart_port *port)
-{
- return in_be16(&PSC(port)->mpc52xx_psc_isr)
- & port->read_status_mask
- & MPC52xx_PSC_IMR_TXRDY;
-}
-
-static int mpc52xx_psc_tx_empty(struct uart_port *port)
-{
- return in_be16(&PSC(port)->mpc52xx_psc_status)
- & MPC52xx_PSC_SR_TXEMP;
-}
-
-static void mpc52xx_psc_start_tx(struct uart_port *port)
-{
- port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
-}
-
-static void mpc52xx_psc_stop_tx(struct uart_port *port)
-{
- port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
-}
-
-static void mpc52xx_psc_stop_rx(struct uart_port *port)
-{
- port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY;
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
-}
-
-static void mpc52xx_psc_rx_clr_irq(struct uart_port *port)
-{
-}
-
-static void mpc52xx_psc_tx_clr_irq(struct uart_port *port)
-{
-}
-
-static void mpc52xx_psc_write_char(struct uart_port *port, unsigned char c)
-{
- out_8(&PSC(port)->mpc52xx_psc_buffer_8, c);
-}
-
-static unsigned char mpc52xx_psc_read_char(struct uart_port *port)
-{
- return in_8(&PSC(port)->mpc52xx_psc_buffer_8);
-}
-
-static void mpc52xx_psc_cw_disable_ints(struct uart_port *port)
-{
- out_be16(&PSC(port)->mpc52xx_psc_imr, 0);
-}
-
-static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
-{
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
-}
-
-static unsigned int mpc5200_psc_set_baudrate(struct uart_port *port,
- struct ktermios *new,
- struct ktermios *old)
-{
- unsigned int baud;
- unsigned int divisor;
-
- /* The 5200 has a fixed /32 prescaler, uartclk contains the ipb freq */
- baud = uart_get_baud_rate(port, new, old,
- port->uartclk / (32 * 0xffff) + 1,
- port->uartclk / 32);
- divisor = (port->uartclk + 16 * baud) / (32 * baud);
-
- /* enable the /32 prescaler and set the divisor */
- mpc52xx_set_divisor(PSC(port), 0xdd00, divisor);
- return baud;
-}
-
-static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port,
- struct ktermios *new,
- struct ktermios *old)
-{
- unsigned int baud;
- unsigned int divisor;
- u16 prescaler;
-
- /* The 5200B has a selectable /4 or /32 prescaler, uartclk contains the
- * ipb freq */
- baud = uart_get_baud_rate(port, new, old,
- port->uartclk / (32 * 0xffff) + 1,
- port->uartclk / 4);
- divisor = (port->uartclk + 2 * baud) / (4 * baud);
-
- /* select the proper prescaler and set the divisor */
- if (divisor > 0xffff) {
- divisor = (divisor + 4) / 8;
- prescaler = 0xdd00; /* /32 */
- } else
- prescaler = 0xff00; /* /4 */
- mpc52xx_set_divisor(PSC(port), prescaler, divisor);
- return baud;
-}
-
-static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np)
-{
- port->irqflags = IRQF_DISABLED;
- port->irq = irq_of_parse_and_map(np, 0);
-}
-
-/* 52xx specific interrupt handler. The caller holds the port lock */
-static irqreturn_t mpc52xx_psc_handle_irq(struct uart_port *port)
-{
- return mpc5xxx_uart_process_int(port);
-}
-
-static struct psc_ops mpc52xx_psc_ops = {
- .fifo_init = mpc52xx_psc_fifo_init,
- .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy,
- .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy,
- .rx_rdy = mpc52xx_psc_rx_rdy,
- .tx_rdy = mpc52xx_psc_tx_rdy,
- .tx_empty = mpc52xx_psc_tx_empty,
- .stop_rx = mpc52xx_psc_stop_rx,
- .start_tx = mpc52xx_psc_start_tx,
- .stop_tx = mpc52xx_psc_stop_tx,
- .rx_clr_irq = mpc52xx_psc_rx_clr_irq,
- .tx_clr_irq = mpc52xx_psc_tx_clr_irq,
- .write_char = mpc52xx_psc_write_char,
- .read_char = mpc52xx_psc_read_char,
- .cw_disable_ints = mpc52xx_psc_cw_disable_ints,
- .cw_restore_ints = mpc52xx_psc_cw_restore_ints,
- .set_baudrate = mpc5200_psc_set_baudrate,
- .get_irq = mpc52xx_psc_get_irq,
- .handle_irq = mpc52xx_psc_handle_irq,
-};
-
-static struct psc_ops mpc5200b_psc_ops = {
- .fifo_init = mpc52xx_psc_fifo_init,
- .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy,
- .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy,
- .rx_rdy = mpc52xx_psc_rx_rdy,
- .tx_rdy = mpc52xx_psc_tx_rdy,
- .tx_empty = mpc52xx_psc_tx_empty,
- .stop_rx = mpc52xx_psc_stop_rx,
- .start_tx = mpc52xx_psc_start_tx,
- .stop_tx = mpc52xx_psc_stop_tx,
- .rx_clr_irq = mpc52xx_psc_rx_clr_irq,
- .tx_clr_irq = mpc52xx_psc_tx_clr_irq,
- .write_char = mpc52xx_psc_write_char,
- .read_char = mpc52xx_psc_read_char,
- .cw_disable_ints = mpc52xx_psc_cw_disable_ints,
- .cw_restore_ints = mpc52xx_psc_cw_restore_ints,
- .set_baudrate = mpc5200b_psc_set_baudrate,
- .get_irq = mpc52xx_psc_get_irq,
- .handle_irq = mpc52xx_psc_handle_irq,
-};
-
-#endif /* CONFIG_MPC52xx */
-
-#ifdef CONFIG_PPC_MPC512x
-#define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1))
-
-/* PSC FIFO Controller for mpc512x */
-struct psc_fifoc {
- u32 fifoc_cmd;
- u32 fifoc_int;
- u32 fifoc_dma;
- u32 fifoc_axe;
- u32 fifoc_debug;
-};
-
-static struct psc_fifoc __iomem *psc_fifoc;
-static unsigned int psc_fifoc_irq;
-
-static void mpc512x_psc_fifo_init(struct uart_port *port)
-{
- /* /32 prescaler */
- out_be16(&PSC(port)->mpc52xx_psc_clock_select, 0xdd00);
-
- out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE);
- out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
- out_be32(&FIFO_512x(port)->txalarm, 1);
- out_be32(&FIFO_512x(port)->tximr, 0);
-
- out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE);
- out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
- out_be32(&FIFO_512x(port)->rxalarm, 1);
- out_be32(&FIFO_512x(port)->rximr, 0);
-
- out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM);
- out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM);
-}
-
-static int mpc512x_psc_raw_rx_rdy(struct uart_port *port)
-{
- return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY);
-}
-
-static int mpc512x_psc_raw_tx_rdy(struct uart_port *port)
-{
- return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL);
-}
-
-static int mpc512x_psc_rx_rdy(struct uart_port *port)
-{
- return in_be32(&FIFO_512x(port)->rxsr)
- & in_be32(&FIFO_512x(port)->rximr)
- & MPC512x_PSC_FIFO_ALARM;
-}
-
-static int mpc512x_psc_tx_rdy(struct uart_port *port)
-{
- return in_be32(&FIFO_512x(port)->txsr)
- & in_be32(&FIFO_512x(port)->tximr)
- & MPC512x_PSC_FIFO_ALARM;
-}
-
-static int mpc512x_psc_tx_empty(struct uart_port *port)
-{
- return in_be32(&FIFO_512x(port)->txsr)
- & MPC512x_PSC_FIFO_EMPTY;
-}
-
-static void mpc512x_psc_stop_rx(struct uart_port *port)
-{
- unsigned long rx_fifo_imr;
-
- rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr);
- rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
- out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr);
-}
-
-static void mpc512x_psc_start_tx(struct uart_port *port)
-{
- unsigned long tx_fifo_imr;
-
- tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
- tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM;
- out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
-}
-
-static void mpc512x_psc_stop_tx(struct uart_port *port)
-{
- unsigned long tx_fifo_imr;
-
- tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
- tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
- out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
-}
-
-static void mpc512x_psc_rx_clr_irq(struct uart_port *port)
-{
- out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr));
-}
-
-static void mpc512x_psc_tx_clr_irq(struct uart_port *port)
-{
- out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr));
-}
-
-static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c)
-{
- out_8(&FIFO_512x(port)->txdata_8, c);
-}
-
-static unsigned char mpc512x_psc_read_char(struct uart_port *port)
-{
- return in_8(&FIFO_512x(port)->rxdata_8);
-}
-
-static void mpc512x_psc_cw_disable_ints(struct uart_port *port)
-{
- port->read_status_mask =
- in_be32(&FIFO_512x(port)->tximr) << 16 |
- in_be32(&FIFO_512x(port)->rximr);
- out_be32(&FIFO_512x(port)->tximr, 0);
- out_be32(&FIFO_512x(port)->rximr, 0);
-}
-
-static void mpc512x_psc_cw_restore_ints(struct uart_port *port)
-{
- out_be32(&FIFO_512x(port)->tximr,
- (port->read_status_mask >> 16) & 0x7f);
- out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f);
-}
-
-static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
- struct ktermios *new,
- struct ktermios *old)
-{
- unsigned int baud;
- unsigned int divisor;
-
- /*
- * The "MPC5121e Microcontroller Reference Manual, Rev. 3" says on
- * pg. 30-10 that the chip supports a /32 and a /10 prescaler.
- * Furthermore, it states that "After reset, the prescaler by 10
- * for the UART mode is selected", but the reset register value is
- * 0x0000 which means a /32 prescaler. This is wrong.
- *
- * In reality using /32 prescaler doesn't work, as it is not supported!
- * Use /16 or /10 prescaler, see "MPC5121e Hardware Design Guide",
- * Chapter 4.1 PSC in UART Mode.
- * Calculate with a /16 prescaler here.
- */
-
- /* uartclk contains the ips freq */
- baud = uart_get_baud_rate(port, new, old,
- port->uartclk / (16 * 0xffff) + 1,
- port->uartclk / 16);
- divisor = (port->uartclk + 8 * baud) / (16 * baud);
-
- /* enable the /16 prescaler and set the divisor */
- mpc52xx_set_divisor(PSC(port), 0xdd00, divisor);
- return baud;
-}
-
-/* Init PSC FIFO Controller */
-static int __init mpc512x_psc_fifoc_init(void)
-{
- struct device_node *np;
-
- np = of_find_compatible_node(NULL, NULL,
- "fsl,mpc5121-psc-fifo");
- if (!np) {
- pr_err("%s: Can't find FIFOC node\n", __func__);
- return -ENODEV;
- }
-
- psc_fifoc = of_iomap(np, 0);
- if (!psc_fifoc) {
- pr_err("%s: Can't map FIFOC\n", __func__);
- of_node_put(np);
- return -ENODEV;
- }
-
- psc_fifoc_irq = irq_of_parse_and_map(np, 0);
- of_node_put(np);
- if (psc_fifoc_irq == NO_IRQ) {
- pr_err("%s: Can't get FIFOC irq\n", __func__);
- iounmap(psc_fifoc);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit mpc512x_psc_fifoc_uninit(void)
-{
- iounmap(psc_fifoc);
-}
-
-/* 512x specific interrupt handler. The caller holds the port lock */
-static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
-{
- unsigned long fifoc_int;
- int psc_num;
-
- /* Read pending PSC FIFOC interrupts */
- fifoc_int = in_be32(&psc_fifoc->fifoc_int);
-
- /* Check if it is an interrupt for this port */
- psc_num = (port->mapbase & 0xf00) >> 8;
- if (test_bit(psc_num, &fifoc_int) ||
- test_bit(psc_num + 16, &fifoc_int))
- return mpc5xxx_uart_process_int(port);
-
- return IRQ_NONE;
-}
-
-static int mpc512x_psc_clock(struct uart_port *port, int enable)
-{
- struct clk *psc_clk;
- int psc_num;
- char clk_name[10];
-
- if (uart_console(port))
- return 0;
-
- psc_num = (port->mapbase & 0xf00) >> 8;
- snprintf(clk_name, sizeof(clk_name), "psc%d_clk", psc_num);
- psc_clk = clk_get(port->dev, clk_name);
- if (IS_ERR(psc_clk)) {
- dev_err(port->dev, "Failed to get PSC clock entry!\n");
- return -ENODEV;
- }
-
- dev_dbg(port->dev, "%s %sable\n", clk_name, enable ? "en" : "dis");
-
- if (enable)
- clk_enable(psc_clk);
- else
- clk_disable(psc_clk);
-
- return 0;
-}
-
-static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np)
-{
- port->irqflags = IRQF_SHARED;
- port->irq = psc_fifoc_irq;
-}
-
-static struct psc_ops mpc512x_psc_ops = {
- .fifo_init = mpc512x_psc_fifo_init,
- .raw_rx_rdy = mpc512x_psc_raw_rx_rdy,
- .raw_tx_rdy = mpc512x_psc_raw_tx_rdy,
- .rx_rdy = mpc512x_psc_rx_rdy,
- .tx_rdy = mpc512x_psc_tx_rdy,
- .tx_empty = mpc512x_psc_tx_empty,
- .stop_rx = mpc512x_psc_stop_rx,
- .start_tx = mpc512x_psc_start_tx,
- .stop_tx = mpc512x_psc_stop_tx,
- .rx_clr_irq = mpc512x_psc_rx_clr_irq,
- .tx_clr_irq = mpc512x_psc_tx_clr_irq,
- .write_char = mpc512x_psc_write_char,
- .read_char = mpc512x_psc_read_char,
- .cw_disable_ints = mpc512x_psc_cw_disable_ints,
- .cw_restore_ints = mpc512x_psc_cw_restore_ints,
- .set_baudrate = mpc512x_psc_set_baudrate,
- .clock = mpc512x_psc_clock,
- .fifoc_init = mpc512x_psc_fifoc_init,
- .fifoc_uninit = mpc512x_psc_fifoc_uninit,
- .get_irq = mpc512x_psc_get_irq,
- .handle_irq = mpc512x_psc_handle_irq,
-};
-#endif
-
-static struct psc_ops *psc_ops;
-
-/* ======================================================================== */
-/* UART operations */
-/* ======================================================================== */
-
-static unsigned int
-mpc52xx_uart_tx_empty(struct uart_port *port)
-{
- return psc_ops->tx_empty(port) ? TIOCSER_TEMT : 0;
-}
-
-static void
-mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- if (mctrl & TIOCM_RTS)
- out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS);
- else
- out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS);
-}
-
-static unsigned int
-mpc52xx_uart_get_mctrl(struct uart_port *port)
-{
- unsigned int ret = TIOCM_DSR;
- u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr);
-
- if (!(status & MPC52xx_PSC_CTS))
- ret |= TIOCM_CTS;
- if (!(status & MPC52xx_PSC_DCD))
- ret |= TIOCM_CAR;
-
- return ret;
-}
-
-static void
-mpc52xx_uart_stop_tx(struct uart_port *port)
-{
- /* port->lock taken by caller */
- psc_ops->stop_tx(port);
-}
-
-static void
-mpc52xx_uart_start_tx(struct uart_port *port)
-{
- /* port->lock taken by caller */
- psc_ops->start_tx(port);
-}
-
-static void
-mpc52xx_uart_send_xchar(struct uart_port *port, char ch)
-{
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
-
- port->x_char = ch;
- if (ch) {
- /* Make sure tx interrupts are on */
- /* Truly necessary ??? They should be anyway */
- psc_ops->start_tx(port);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void
-mpc52xx_uart_stop_rx(struct uart_port *port)
-{
- /* port->lock taken by caller */
- psc_ops->stop_rx(port);
-}
-
-static void
-mpc52xx_uart_enable_ms(struct uart_port *port)
-{
- struct mpc52xx_psc __iomem *psc = PSC(port);
-
- /* clear D_*-bits by reading them */
- in_8(&psc->mpc52xx_psc_ipcr);
- /* enable CTS and DCD as IPC interrupts */
- out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD);
-
- port->read_status_mask |= MPC52xx_PSC_IMR_IPC;
- out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
-}
-
-static void
-mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
-{
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
-
- if (ctl == -1)
- out_8(&PSC(port)->command, MPC52xx_PSC_START_BRK);
- else
- out_8(&PSC(port)->command, MPC52xx_PSC_STOP_BRK);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int
-mpc52xx_uart_startup(struct uart_port *port)
-{
- struct mpc52xx_psc __iomem *psc = PSC(port);
- int ret;
-
- if (psc_ops->clock) {
- ret = psc_ops->clock(port, 1);
- if (ret)
- return ret;
- }
-
- /* Request IRQ */
- ret = request_irq(port->irq, mpc52xx_uart_int,
- port->irqflags, "mpc52xx_psc_uart", port);
- if (ret)
- return ret;
-
- /* Reset/activate the port, clear and enable interrupts */
- out_8(&psc->command, MPC52xx_PSC_RST_RX);
- out_8(&psc->command, MPC52xx_PSC_RST_TX);
-
- out_be32(&psc->sicr, 0); /* UART mode DCD ignored */
-
- psc_ops->fifo_init(port);
-
- out_8(&psc->command, MPC52xx_PSC_TX_ENABLE);
- out_8(&psc->command, MPC52xx_PSC_RX_ENABLE);
-
- return 0;
-}
-
-static void
-mpc52xx_uart_shutdown(struct uart_port *port)
-{
- struct mpc52xx_psc __iomem *psc = PSC(port);
-
- /* Shut down the port. Leave TX active if on a console port */
- out_8(&psc->command, MPC52xx_PSC_RST_RX);
- if (!uart_console(port))
- out_8(&psc->command, MPC52xx_PSC_RST_TX);
-
- port->read_status_mask = 0;
- out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
-
- if (psc_ops->clock)
- psc_ops->clock(port, 0);
-
- /* Release interrupt */
- free_irq(port->irq, port);
-}
-
-static void
-mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
- struct ktermios *old)
-{
- struct mpc52xx_psc __iomem *psc = PSC(port);
- unsigned long flags;
- unsigned char mr1, mr2;
- unsigned int j;
- unsigned int baud;
-
- /* Prepare what we're gonna write */
- mr1 = 0;
-
- switch (new->c_cflag & CSIZE) {
- case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS;
- break;
- case CS6: mr1 |= MPC52xx_PSC_MODE_6_BITS;
- break;
- case CS7: mr1 |= MPC52xx_PSC_MODE_7_BITS;
- break;
- case CS8:
- default: mr1 |= MPC52xx_PSC_MODE_8_BITS;
- }
-
- if (new->c_cflag & PARENB) {
- mr1 |= (new->c_cflag & PARODD) ?
- MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
- } else
- mr1 |= MPC52xx_PSC_MODE_PARNONE;
-
-
- mr2 = 0;
-
- if (new->c_cflag & CSTOPB)
- mr2 |= MPC52xx_PSC_MODE_TWO_STOP;
- else
- mr2 |= ((new->c_cflag & CSIZE) == CS5) ?
- MPC52xx_PSC_MODE_ONE_STOP_5_BITS :
- MPC52xx_PSC_MODE_ONE_STOP;
-
- if (new->c_cflag & CRTSCTS) {
- mr1 |= MPC52xx_PSC_MODE_RXRTS;
- mr2 |= MPC52xx_PSC_MODE_TXCTS;
- }
-
- /* Get the lock */
- spin_lock_irqsave(&port->lock, flags);
-
- /* Do our best to flush TX & RX, so we don't lose anything */
- /* But we don't wait indefinitely ! */
- j = 5000000; /* Maximum wait */
- /* FIXME Can't receive chars since set_termios might be called at early
- * boot for the console, all stuff is not yet ready to receive at that
- * time and that just makes the kernel oops */
- /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */
- while (!mpc52xx_uart_tx_empty(port) && --j)
- udelay(1);
-
- if (!j)
- printk(KERN_ERR "mpc52xx_uart.c: "
- "Unable to flush RX & TX fifos in-time in set_termios."
- "Some chars may have been lost.\n");
-
- /* Reset the TX & RX */
- out_8(&psc->command, MPC52xx_PSC_RST_RX);
- out_8(&psc->command, MPC52xx_PSC_RST_TX);
-
- /* Send new mode settings */
- out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
- out_8(&psc->mode, mr1);
- out_8(&psc->mode, mr2);
- baud = psc_ops->set_baudrate(port, new, old);
-
- /* Update the per-port timeout */
- uart_update_timeout(port, new->c_cflag, baud);
-
- if (UART_ENABLE_MS(port, new->c_cflag))
- mpc52xx_uart_enable_ms(port);
-
- /* Reenable TX & RX */
- out_8(&psc->command, MPC52xx_PSC_TX_ENABLE);
- out_8(&psc->command, MPC52xx_PSC_RX_ENABLE);
-
- /* We're all set, release the lock */
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *
-mpc52xx_uart_type(struct uart_port *port)
-{
- /*
- * We keep using PORT_MPC52xx for historic reasons although it applies
- * for MPC512x, too, but print "MPC5xxx" to not irritate users
- */
- return port->type == PORT_MPC52xx ? "MPC5xxx PSC" : NULL;
-}
-
-static void
-mpc52xx_uart_release_port(struct uart_port *port)
-{
- /* remapped by us ? */
- if (port->flags & UPF_IOREMAP) {
- iounmap(port->membase);
- port->membase = NULL;
- }
-
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
-}
-
-static int
-mpc52xx_uart_request_port(struct uart_port *port)
-{
- int err;
-
- if (port->flags & UPF_IOREMAP) /* Need to remap ? */
- port->membase = ioremap(port->mapbase,
- sizeof(struct mpc52xx_psc));
-
- if (!port->membase)
- return -EINVAL;
-
- err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
- "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
-
- if (err && (port->flags & UPF_IOREMAP)) {
- iounmap(port->membase);
- port->membase = NULL;
- }
-
- return err;
-}
-
-static void
-mpc52xx_uart_config_port(struct uart_port *port, int flags)
-{
- if ((flags & UART_CONFIG_TYPE)
- && (mpc52xx_uart_request_port(port) == 0))
- port->type = PORT_MPC52xx;
-}
-
-static int
-mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_MPC52xx)
- return -EINVAL;
-
- if ((ser->irq != port->irq) ||
- (ser->io_type != UPIO_MEM) ||
- (ser->baud_base != port->uartclk) ||
- (ser->iomem_base != (void *)port->mapbase) ||
- (ser->hub6 != 0))
- return -EINVAL;
-
- return 0;
-}
-
-
-static struct uart_ops mpc52xx_uart_ops = {
- .tx_empty = mpc52xx_uart_tx_empty,
- .set_mctrl = mpc52xx_uart_set_mctrl,
- .get_mctrl = mpc52xx_uart_get_mctrl,
- .stop_tx = mpc52xx_uart_stop_tx,
- .start_tx = mpc52xx_uart_start_tx,
- .send_xchar = mpc52xx_uart_send_xchar,
- .stop_rx = mpc52xx_uart_stop_rx,
- .enable_ms = mpc52xx_uart_enable_ms,
- .break_ctl = mpc52xx_uart_break_ctl,
- .startup = mpc52xx_uart_startup,
- .shutdown = mpc52xx_uart_shutdown,
- .set_termios = mpc52xx_uart_set_termios,
-/* .pm = mpc52xx_uart_pm, Not supported yet */
-/* .set_wake = mpc52xx_uart_set_wake, Not supported yet */
- .type = mpc52xx_uart_type,
- .release_port = mpc52xx_uart_release_port,
- .request_port = mpc52xx_uart_request_port,
- .config_port = mpc52xx_uart_config_port,
- .verify_port = mpc52xx_uart_verify_port
-};
-
-
-/* ======================================================================== */
-/* Interrupt handling */
-/* ======================================================================== */
-
-static inline int
-mpc52xx_uart_int_rx_chars(struct uart_port *port)
-{
- struct tty_struct *tty = port->state->port.tty;
- unsigned char ch, flag;
- unsigned short status;
-
- /* While we can read, do so ! */
- while (psc_ops->raw_rx_rdy(port)) {
- /* Get the char */
- ch = psc_ops->read_char(port);
-
- /* Handle sysreq char */
-#ifdef SUPPORT_SYSRQ
- if (uart_handle_sysrq_char(port, ch)) {
- port->sysrq = 0;
- continue;
- }
-#endif
-
- /* Store it */
-
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- status = in_be16(&PSC(port)->mpc52xx_psc_status);
-
- if (status & (MPC52xx_PSC_SR_PE |
- MPC52xx_PSC_SR_FE |
- MPC52xx_PSC_SR_RB)) {
-
- if (status & MPC52xx_PSC_SR_RB) {
- flag = TTY_BREAK;
- uart_handle_break(port);
- port->icount.brk++;
- } else if (status & MPC52xx_PSC_SR_PE) {
- flag = TTY_PARITY;
- port->icount.parity++;
- }
- else if (status & MPC52xx_PSC_SR_FE) {
- flag = TTY_FRAME;
- port->icount.frame++;
- }
-
- /* Clear error condition */
- out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT);
-
- }
- tty_insert_flip_char(tty, ch, flag);
- if (status & MPC52xx_PSC_SR_OE) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- port->icount.overrun++;
- }
- }
-
- spin_unlock(&port->lock);
- tty_flip_buffer_push(tty);
- spin_lock(&port->lock);
-
- return psc_ops->raw_rx_rdy(port);
-}
-
-static inline int
-mpc52xx_uart_int_tx_chars(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- /* Process out of band chars */
- if (port->x_char) {
- psc_ops->write_char(port, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return 1;
- }
-
- /* Nothing to do ? */
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- mpc52xx_uart_stop_tx(port);
- return 0;
- }
-
- /* Send chars */
- while (psc_ops->raw_tx_rdy(port)) {
- psc_ops->write_char(port, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- }
-
- /* Wake up */
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- /* Maybe we're done after all */
- if (uart_circ_empty(xmit)) {
- mpc52xx_uart_stop_tx(port);
- return 0;
- }
-
- return 1;
-}
-
-static irqreturn_t
-mpc5xxx_uart_process_int(struct uart_port *port)
-{
- unsigned long pass = ISR_PASS_LIMIT;
- unsigned int keepgoing;
- u8 status;
-
- /* While we have stuff to do, we continue */
- do {
- /* If we don't find anything to do, we stop */
- keepgoing = 0;
-
- psc_ops->rx_clr_irq(port);
- if (psc_ops->rx_rdy(port))
- keepgoing |= mpc52xx_uart_int_rx_chars(port);
-
- psc_ops->tx_clr_irq(port);
- if (psc_ops->tx_rdy(port))
- keepgoing |= mpc52xx_uart_int_tx_chars(port);
-
- status = in_8(&PSC(port)->mpc52xx_psc_ipcr);
- if (status & MPC52xx_PSC_D_DCD)
- uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD));
-
- if (status & MPC52xx_PSC_D_CTS)
- uart_handle_cts_change(port, !(status & MPC52xx_PSC_CTS));
-
- /* Limit number of iteration */
- if (!(--pass))
- keepgoing = 0;
-
- } while (keepgoing);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t
-mpc52xx_uart_int(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- irqreturn_t ret;
-
- spin_lock(&port->lock);
-
- ret = psc_ops->handle_irq(port);
-
- spin_unlock(&port->lock);
-
- return ret;
-}
-
-/* ======================================================================== */
-/* Console ( if applicable ) */
-/* ======================================================================== */
-
-#ifdef CONFIG_SERIAL_MPC52xx_CONSOLE
-
-static void __init
-mpc52xx_console_get_options(struct uart_port *port,
- int *baud, int *parity, int *bits, int *flow)
-{
- struct mpc52xx_psc __iomem *psc = PSC(port);
- unsigned char mr1;
-
- pr_debug("mpc52xx_console_get_options(port=%p)\n", port);
-
- /* Read the mode registers */
- out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
- mr1 = in_8(&psc->mode);
-
- /* CT{U,L}R are write-only ! */
- *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
-
- /* Parse them */
- switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
- case MPC52xx_PSC_MODE_5_BITS:
- *bits = 5;
- break;
- case MPC52xx_PSC_MODE_6_BITS:
- *bits = 6;
- break;
- case MPC52xx_PSC_MODE_7_BITS:
- *bits = 7;
- break;
- case MPC52xx_PSC_MODE_8_BITS:
- default:
- *bits = 8;
- }
-
- if (mr1 & MPC52xx_PSC_MODE_PARNONE)
- *parity = 'n';
- else
- *parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e';
-}
-
-static void
-mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_port *port = &mpc52xx_uart_ports[co->index];
- unsigned int i, j;
-
- /* Disable interrupts */
- psc_ops->cw_disable_ints(port);
-
- /* Wait the TX buffer to be empty */
- j = 5000000; /* Maximum wait */
- while (!mpc52xx_uart_tx_empty(port) && --j)
- udelay(1);
-
- /* Write all the chars */
- for (i = 0; i < count; i++, s++) {
- /* Line return handling */
- if (*s == '\n')
- psc_ops->write_char(port, '\r');
-
- /* Send the char */
- psc_ops->write_char(port, *s);
-
- /* Wait the TX buffer to be empty */
- j = 20000; /* Maximum wait */
- while (!mpc52xx_uart_tx_empty(port) && --j)
- udelay(1);
- }
-
- /* Restore interrupt state */
- psc_ops->cw_restore_ints(port);
-}
-
-
-static int __init
-mpc52xx_console_setup(struct console *co, char *options)
-{
- struct uart_port *port = &mpc52xx_uart_ports[co->index];
- struct device_node *np = mpc52xx_uart_nodes[co->index];
- unsigned int uartclk;
- struct resource res;
- int ret;
-
- int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n",
- co, co->index, options);
-
- if ((co->index < 0) || (co->index >= MPC52xx_PSC_MAXNUM)) {
- pr_debug("PSC%x out of range\n", co->index);
- return -EINVAL;
- }
-
- if (!np) {
- pr_debug("PSC%x not found in device tree\n", co->index);
- return -EINVAL;
- }
-
- pr_debug("Console on ttyPSC%x is %s\n",
- co->index, mpc52xx_uart_nodes[co->index]->full_name);
-
- /* Fetch register locations */
- ret = of_address_to_resource(np, 0, &res);
- if (ret) {
- pr_debug("Could not get resources for PSC%x\n", co->index);
- return ret;
- }
-
- uartclk = mpc5xxx_get_bus_frequency(np);
- if (uartclk == 0) {
- pr_debug("Could not find uart clock frequency!\n");
- return -EINVAL;
- }
-
- /* Basic port init. Needed since we use some uart_??? func before
- * real init for early access */
- spin_lock_init(&port->lock);
- port->uartclk = uartclk;
- port->ops = &mpc52xx_uart_ops;
- port->mapbase = res.start;
- port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc));
- port->irq = irq_of_parse_and_map(np, 0);
-
- if (port->membase == NULL)
- return -EINVAL;
-
- pr_debug("mpc52xx-psc uart at %p, mapped to %p, irq=%x, freq=%i\n",
- (void *)port->mapbase, port->membase,
- port->irq, port->uartclk);
-
- /* Setup the port parameters accoding to options */
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
-
- pr_debug("Setting console parameters: %i %i%c1 flow=%c\n",
- baud, bits, parity, flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-
-static struct uart_driver mpc52xx_uart_driver;
-
-static struct console mpc52xx_console = {
- .name = "ttyPSC",
- .write = mpc52xx_console_write,
- .device = uart_console_device,
- .setup = mpc52xx_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1, /* Specified on the cmdline (e.g. console=ttyPSC0) */
- .data = &mpc52xx_uart_driver,
-};
-
-
-static int __init
-mpc52xx_console_init(void)
-{
- mpc52xx_uart_of_enumerate();
- register_console(&mpc52xx_console);
- return 0;
-}
-
-console_initcall(mpc52xx_console_init);
-
-#define MPC52xx_PSC_CONSOLE &mpc52xx_console
-#else
-#define MPC52xx_PSC_CONSOLE NULL
-#endif
-
-
-/* ======================================================================== */
-/* UART Driver */
-/* ======================================================================== */
-
-static struct uart_driver mpc52xx_uart_driver = {
- .driver_name = "mpc52xx_psc_uart",
- .dev_name = "ttyPSC",
- .major = SERIAL_PSC_MAJOR,
- .minor = SERIAL_PSC_MINOR,
- .nr = MPC52xx_PSC_MAXNUM,
- .cons = MPC52xx_PSC_CONSOLE,
-};
-
-/* ======================================================================== */
-/* OF Platform Driver */
-/* ======================================================================== */
-
-static struct of_device_id mpc52xx_uart_of_match[] = {
-#ifdef CONFIG_PPC_MPC52xx
- { .compatible = "fsl,mpc5200b-psc-uart", .data = &mpc5200b_psc_ops, },
- { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
- /* binding used by old lite5200 device trees: */
- { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
- /* binding used by efika: */
- { .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, },
-#endif
-#ifdef CONFIG_PPC_MPC512x
- { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
-#endif
- {},
-};
-
-static int __devinit
-mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match)
-{
- int idx = -1;
- unsigned int uartclk;
- struct uart_port *port = NULL;
- struct resource res;
- int ret;
-
- dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match);
-
- /* Check validity & presence */
- for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++)
- if (mpc52xx_uart_nodes[idx] == op->dev.of_node)
- break;
- if (idx >= MPC52xx_PSC_MAXNUM)
- return -EINVAL;
- pr_debug("Found %s assigned to ttyPSC%x\n",
- mpc52xx_uart_nodes[idx]->full_name, idx);
-
- /* set the uart clock to the input clock of the psc, the different
- * prescalers are taken into account in the set_baudrate() methods
- * of the respective chip */
- uartclk = mpc5xxx_get_bus_frequency(op->dev.of_node);
- if (uartclk == 0) {
- dev_dbg(&op->dev, "Could not find uart clock frequency!\n");
- return -EINVAL;
- }
-
- /* Init the port structure */
- port = &mpc52xx_uart_ports[idx];
-
- spin_lock_init(&port->lock);
- port->uartclk = uartclk;
- port->fifosize = 512;
- port->iotype = UPIO_MEM;
- port->flags = UPF_BOOT_AUTOCONF |
- (uart_console(port) ? 0 : UPF_IOREMAP);
- port->line = idx;
- port->ops = &mpc52xx_uart_ops;
- port->dev = &op->dev;
-
- /* Search for IRQ and mapbase */
- ret = of_address_to_resource(op->dev.of_node, 0, &res);
- if (ret)
- return ret;
-
- port->mapbase = res.start;
- if (!port->mapbase) {
- dev_dbg(&op->dev, "Could not allocate resources for PSC\n");
- return -EINVAL;
- }
-
- psc_ops->get_irq(port, op->dev.of_node);
- if (port->irq == NO_IRQ) {
- dev_dbg(&op->dev, "Could not get irq\n");
- return -EINVAL;
- }
-
- dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n",
- (void *)port->mapbase, port->irq, port->uartclk);
-
- /* Add the port to the uart sub-system */
- ret = uart_add_one_port(&mpc52xx_uart_driver, port);
- if (ret)
- return ret;
-
- dev_set_drvdata(&op->dev, (void *)port);
- return 0;
-}
-
-static int
-mpc52xx_uart_of_remove(struct platform_device *op)
-{
- struct uart_port *port = dev_get_drvdata(&op->dev);
- dev_set_drvdata(&op->dev, NULL);
-
- if (port)
- uart_remove_one_port(&mpc52xx_uart_driver, port);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state)
-{
- struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev);
-
- if (port)
- uart_suspend_port(&mpc52xx_uart_driver, port);
-
- return 0;
-}
-
-static int
-mpc52xx_uart_of_resume(struct platform_device *op)
-{
- struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev);
-
- if (port)
- uart_resume_port(&mpc52xx_uart_driver, port);
-
- return 0;
-}
-#endif
-
-static void
-mpc52xx_uart_of_assign(struct device_node *np)
-{
- int i;
-
- /* Find the first free PSC number */
- for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) {
- if (mpc52xx_uart_nodes[i] == NULL) {
- of_node_get(np);
- mpc52xx_uart_nodes[i] = np;
- return;
- }
- }
-}
-
-static void
-mpc52xx_uart_of_enumerate(void)
-{
- static int enum_done;
- struct device_node *np;
- const struct of_device_id *match;
- int i;
-
- if (enum_done)
- return;
-
- /* Assign index to each PSC in device tree */
- for_each_matching_node(np, mpc52xx_uart_of_match) {
- match = of_match_node(mpc52xx_uart_of_match, np);
- psc_ops = match->data;
- mpc52xx_uart_of_assign(np);
- }
-
- enum_done = 1;
-
- for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) {
- if (mpc52xx_uart_nodes[i])
- pr_debug("%s assigned to ttyPSC%x\n",
- mpc52xx_uart_nodes[i]->full_name, i);
- }
-}
-
-MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match);
-
-static struct of_platform_driver mpc52xx_uart_of_driver = {
- .probe = mpc52xx_uart_of_probe,
- .remove = mpc52xx_uart_of_remove,
-#ifdef CONFIG_PM
- .suspend = mpc52xx_uart_of_suspend,
- .resume = mpc52xx_uart_of_resume,
-#endif
- .driver = {
- .name = "mpc52xx-psc-uart",
- .owner = THIS_MODULE,
- .of_match_table = mpc52xx_uart_of_match,
- },
-};
-
-
-/* ======================================================================== */
-/* Module */
-/* ======================================================================== */
-
-static int __init
-mpc52xx_uart_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: MPC52xx PSC UART driver\n");
-
- ret = uart_register_driver(&mpc52xx_uart_driver);
- if (ret) {
- printk(KERN_ERR "%s: uart_register_driver failed (%i)\n",
- __FILE__, ret);
- return ret;
- }
-
- mpc52xx_uart_of_enumerate();
-
- /*
- * Map the PSC FIFO Controller and init if on MPC512x.
- */
- if (psc_ops && psc_ops->fifoc_init) {
- ret = psc_ops->fifoc_init();
- if (ret)
- return ret;
- }
-
- ret = of_register_platform_driver(&mpc52xx_uart_of_driver);
- if (ret) {
- printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n",
- __FILE__, ret);
- uart_unregister_driver(&mpc52xx_uart_driver);
- return ret;
- }
-
- return 0;
-}
-
-static void __exit
-mpc52xx_uart_exit(void)
-{
- if (psc_ops->fifoc_uninit)
- psc_ops->fifoc_uninit();
-
- of_unregister_platform_driver(&mpc52xx_uart_of_driver);
- uart_unregister_driver(&mpc52xx_uart_driver);
-}
-
-
-module_init(mpc52xx_uart_init);
-module_exit(mpc52xx_uart_exit);
-
-MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
-MODULE_DESCRIPTION("Freescale MPC52xx PSC UART");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
deleted file mode 100644
index 6a9c6605666a..000000000000
--- a/drivers/serial/mpsc.c
+++ /dev/null
@@ -1,2159 +0,0 @@
-/*
- * Generic driver for the MPSC (UART mode) on Marvell parts (e.g., GT64240,
- * GT64260, MV64340, MV64360, GT96100, ... ).
- *
- * Author: Mark A. Greer <mgreer@mvista.com>
- *
- * Based on an old MPSC driver that was in the linuxppc tree. It appears to
- * have been created by Chris Zankel (formerly of MontaVista) but there
- * is no proper Copyright so I'm not sure. Apparently, parts were also
- * taken from PPCBoot (now U-Boot). Also based on drivers/serial/8250.c
- * by Russell King.
- *
- * 2004 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-/*
- * The MPSC interface is much like a typical network controller's interface.
- * That is, you set up separate rings of descriptors for transmitting and
- * receiving data. There is also a pool of buffers with (one buffer per
- * descriptor) that incoming data are dma'd into or outgoing data are dma'd
- * out of.
- *
- * The MPSC requires two other controllers to be able to work. The Baud Rate
- * Generator (BRG) provides a clock at programmable frequencies which determines
- * the baud rate. The Serial DMA Controller (SDMA) takes incoming data from the
- * MPSC and DMA's it into memory or DMA's outgoing data and passes it to the
- * MPSC. It is actually the SDMA interrupt that the driver uses to keep the
- * transmit and receive "engines" going (i.e., indicate data has been
- * transmitted or received).
- *
- * NOTES:
- *
- * 1) Some chips have an erratum where several regs cannot be
- * read. To work around that, we keep a local copy of those regs in
- * 'mpsc_port_info'.
- *
- * 2) Some chips have an erratum where the ctlr will hang when the SDMA ctlr
- * accesses system mem with coherency enabled. For that reason, the driver
- * assumes that coherency for that ctlr has been disabled. This means
- * that when in a cache coherent system, the driver has to manually manage
- * the data cache on the areas that it touches because the dma_* macro are
- * basically no-ops.
- *
- * 3) There is an erratum (on PPC) where you can't use the instruction to do
- * a DMA_TO_DEVICE/cache clean so DMA_BIDIRECTIONAL/flushes are used in places
- * where a DMA_TO_DEVICE/clean would have [otherwise] sufficed.
- *
- * 4) AFAICT, hardware flow control isn't supported by the controller --MAG.
- */
-
-
-#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-#include <linux/gfp.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define MPSC_NUM_CTLRS 2
-
-/*
- * Descriptors and buffers must be cache line aligned.
- * Buffers lengths must be multiple of cache line size.
- * Number of Tx & Rx descriptors must be powers of 2.
- */
-#define MPSC_RXR_ENTRIES 32
-#define MPSC_RXRE_SIZE dma_get_cache_alignment()
-#define MPSC_RXR_SIZE (MPSC_RXR_ENTRIES * MPSC_RXRE_SIZE)
-#define MPSC_RXBE_SIZE dma_get_cache_alignment()
-#define MPSC_RXB_SIZE (MPSC_RXR_ENTRIES * MPSC_RXBE_SIZE)
-
-#define MPSC_TXR_ENTRIES 32
-#define MPSC_TXRE_SIZE dma_get_cache_alignment()
-#define MPSC_TXR_SIZE (MPSC_TXR_ENTRIES * MPSC_TXRE_SIZE)
-#define MPSC_TXBE_SIZE dma_get_cache_alignment()
-#define MPSC_TXB_SIZE (MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE)
-
-#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + MPSC_TXR_SIZE \
- + MPSC_TXB_SIZE + dma_get_cache_alignment() /* for alignment */)
-
-/* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */
-struct mpsc_rx_desc {
- u16 bufsize;
- u16 bytecnt;
- u32 cmdstat;
- u32 link;
- u32 buf_ptr;
-} __attribute((packed));
-
-struct mpsc_tx_desc {
- u16 bytecnt;
- u16 shadow;
- u32 cmdstat;
- u32 link;
- u32 buf_ptr;
-} __attribute((packed));
-
-/*
- * Some regs that have the erratum that you can't read them are are shared
- * between the two MPSC controllers. This struct contains those shared regs.
- */
-struct mpsc_shared_regs {
- phys_addr_t mpsc_routing_base_p;
- phys_addr_t sdma_intr_base_p;
-
- void __iomem *mpsc_routing_base;
- void __iomem *sdma_intr_base;
-
- u32 MPSC_MRR_m;
- u32 MPSC_RCRR_m;
- u32 MPSC_TCRR_m;
- u32 SDMA_INTR_CAUSE_m;
- u32 SDMA_INTR_MASK_m;
-};
-
-/* The main driver data structure */
-struct mpsc_port_info {
- struct uart_port port; /* Overlay uart_port structure */
-
- /* Internal driver state for this ctlr */
- u8 ready;
- u8 rcv_data;
- tcflag_t c_iflag; /* save termios->c_iflag */
- tcflag_t c_cflag; /* save termios->c_cflag */
-
- /* Info passed in from platform */
- u8 mirror_regs; /* Need to mirror regs? */
- u8 cache_mgmt; /* Need manual cache mgmt? */
- u8 brg_can_tune; /* BRG has baud tuning? */
- u32 brg_clk_src;
- u16 mpsc_max_idle;
- int default_baud;
- int default_bits;
- int default_parity;
- int default_flow;
-
- /* Physical addresses of various blocks of registers (from platform) */
- phys_addr_t mpsc_base_p;
- phys_addr_t sdma_base_p;
- phys_addr_t brg_base_p;
-
- /* Virtual addresses of various blocks of registers (from platform) */
- void __iomem *mpsc_base;
- void __iomem *sdma_base;
- void __iomem *brg_base;
-
- /* Descriptor ring and buffer allocations */
- void *dma_region;
- dma_addr_t dma_region_p;
-
- dma_addr_t rxr; /* Rx descriptor ring */
- dma_addr_t rxr_p; /* Phys addr of rxr */
- u8 *rxb; /* Rx Ring I/O buf */
- u8 *rxb_p; /* Phys addr of rxb */
- u32 rxr_posn; /* First desc w/ Rx data */
-
- dma_addr_t txr; /* Tx descriptor ring */
- dma_addr_t txr_p; /* Phys addr of txr */
- u8 *txb; /* Tx Ring I/O buf */
- u8 *txb_p; /* Phys addr of txb */
- int txr_head; /* Where new data goes */
- int txr_tail; /* Where sent data comes off */
- spinlock_t tx_lock; /* transmit lock */
-
- /* Mirrored values of regs we can't read (if 'mirror_regs' set) */
- u32 MPSC_MPCR_m;
- u32 MPSC_CHR_1_m;
- u32 MPSC_CHR_2_m;
- u32 MPSC_CHR_10_m;
- u32 BRG_BCR_m;
- struct mpsc_shared_regs *shared_regs;
-};
-
-/* Hooks to platform-specific code */
-int mpsc_platform_register_driver(void);
-void mpsc_platform_unregister_driver(void);
-
-/* Hooks back in to mpsc common to be called by platform-specific code */
-struct mpsc_port_info *mpsc_device_probe(int index);
-struct mpsc_port_info *mpsc_device_remove(int index);
-
-/* Main MPSC Configuration Register Offsets */
-#define MPSC_MMCRL 0x0000
-#define MPSC_MMCRH 0x0004
-#define MPSC_MPCR 0x0008
-#define MPSC_CHR_1 0x000c
-#define MPSC_CHR_2 0x0010
-#define MPSC_CHR_3 0x0014
-#define MPSC_CHR_4 0x0018
-#define MPSC_CHR_5 0x001c
-#define MPSC_CHR_6 0x0020
-#define MPSC_CHR_7 0x0024
-#define MPSC_CHR_8 0x0028
-#define MPSC_CHR_9 0x002c
-#define MPSC_CHR_10 0x0030
-#define MPSC_CHR_11 0x0034
-
-#define MPSC_MPCR_FRZ (1 << 9)
-#define MPSC_MPCR_CL_5 0
-#define MPSC_MPCR_CL_6 1
-#define MPSC_MPCR_CL_7 2
-#define MPSC_MPCR_CL_8 3
-#define MPSC_MPCR_SBL_1 0
-#define MPSC_MPCR_SBL_2 1
-
-#define MPSC_CHR_2_TEV (1<<1)
-#define MPSC_CHR_2_TA (1<<7)
-#define MPSC_CHR_2_TTCS (1<<9)
-#define MPSC_CHR_2_REV (1<<17)
-#define MPSC_CHR_2_RA (1<<23)
-#define MPSC_CHR_2_CRD (1<<25)
-#define MPSC_CHR_2_EH (1<<31)
-#define MPSC_CHR_2_PAR_ODD 0
-#define MPSC_CHR_2_PAR_SPACE 1
-#define MPSC_CHR_2_PAR_EVEN 2
-#define MPSC_CHR_2_PAR_MARK 3
-
-/* MPSC Signal Routing */
-#define MPSC_MRR 0x0000
-#define MPSC_RCRR 0x0004
-#define MPSC_TCRR 0x0008
-
-/* Serial DMA Controller Interface Registers */
-#define SDMA_SDC 0x0000
-#define SDMA_SDCM 0x0008
-#define SDMA_RX_DESC 0x0800
-#define SDMA_RX_BUF_PTR 0x0808
-#define SDMA_SCRDP 0x0810
-#define SDMA_TX_DESC 0x0c00
-#define SDMA_SCTDP 0x0c10
-#define SDMA_SFTDP 0x0c14
-
-#define SDMA_DESC_CMDSTAT_PE (1<<0)
-#define SDMA_DESC_CMDSTAT_CDL (1<<1)
-#define SDMA_DESC_CMDSTAT_FR (1<<3)
-#define SDMA_DESC_CMDSTAT_OR (1<<6)
-#define SDMA_DESC_CMDSTAT_BR (1<<9)
-#define SDMA_DESC_CMDSTAT_MI (1<<10)
-#define SDMA_DESC_CMDSTAT_A (1<<11)
-#define SDMA_DESC_CMDSTAT_AM (1<<12)
-#define SDMA_DESC_CMDSTAT_CT (1<<13)
-#define SDMA_DESC_CMDSTAT_C (1<<14)
-#define SDMA_DESC_CMDSTAT_ES (1<<15)
-#define SDMA_DESC_CMDSTAT_L (1<<16)
-#define SDMA_DESC_CMDSTAT_F (1<<17)
-#define SDMA_DESC_CMDSTAT_P (1<<18)
-#define SDMA_DESC_CMDSTAT_EI (1<<23)
-#define SDMA_DESC_CMDSTAT_O (1<<31)
-
-#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O \
- | SDMA_DESC_CMDSTAT_EI)
-
-#define SDMA_SDC_RFT (1<<0)
-#define SDMA_SDC_SFM (1<<1)
-#define SDMA_SDC_BLMR (1<<6)
-#define SDMA_SDC_BLMT (1<<7)
-#define SDMA_SDC_POVR (1<<8)
-#define SDMA_SDC_RIFB (1<<9)
-
-#define SDMA_SDCM_ERD (1<<7)
-#define SDMA_SDCM_AR (1<<15)
-#define SDMA_SDCM_STD (1<<16)
-#define SDMA_SDCM_TXD (1<<23)
-#define SDMA_SDCM_AT (1<<31)
-
-#define SDMA_0_CAUSE_RXBUF (1<<0)
-#define SDMA_0_CAUSE_RXERR (1<<1)
-#define SDMA_0_CAUSE_TXBUF (1<<2)
-#define SDMA_0_CAUSE_TXEND (1<<3)
-#define SDMA_1_CAUSE_RXBUF (1<<8)
-#define SDMA_1_CAUSE_RXERR (1<<9)
-#define SDMA_1_CAUSE_TXBUF (1<<10)
-#define SDMA_1_CAUSE_TXEND (1<<11)
-
-#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR \
- | SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR)
-#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND \
- | SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND)
-
-/* SDMA Interrupt registers */
-#define SDMA_INTR_CAUSE 0x0000
-#define SDMA_INTR_MASK 0x0080
-
-/* Baud Rate Generator Interface Registers */
-#define BRG_BCR 0x0000
-#define BRG_BTR 0x0004
-
-/*
- * Define how this driver is known to the outside (we've been assigned a
- * range on the "Low-density serial ports" major).
- */
-#define MPSC_MAJOR 204
-#define MPSC_MINOR_START 44
-#define MPSC_DRIVER_NAME "MPSC"
-#define MPSC_DEV_NAME "ttyMM"
-#define MPSC_VERSION "1.00"
-
-static struct mpsc_port_info mpsc_ports[MPSC_NUM_CTLRS];
-static struct mpsc_shared_regs mpsc_shared_regs;
-static struct uart_driver mpsc_reg;
-
-static void mpsc_start_rx(struct mpsc_port_info *pi);
-static void mpsc_free_ring_mem(struct mpsc_port_info *pi);
-static void mpsc_release_port(struct uart_port *port);
-/*
- ******************************************************************************
- *
- * Baud Rate Generator Routines (BRG)
- *
- ******************************************************************************
- */
-static void mpsc_brg_init(struct mpsc_port_info *pi, u32 clk_src)
-{
- u32 v;
-
- v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
- v = (v & ~(0xf << 18)) | ((clk_src & 0xf) << 18);
-
- if (pi->brg_can_tune)
- v &= ~(1 << 25);
-
- if (pi->mirror_regs)
- pi->BRG_BCR_m = v;
- writel(v, pi->brg_base + BRG_BCR);
-
- writel(readl(pi->brg_base + BRG_BTR) & 0xffff0000,
- pi->brg_base + BRG_BTR);
-}
-
-static void mpsc_brg_enable(struct mpsc_port_info *pi)
-{
- u32 v;
-
- v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
- v |= (1 << 16);
-
- if (pi->mirror_regs)
- pi->BRG_BCR_m = v;
- writel(v, pi->brg_base + BRG_BCR);
-}
-
-static void mpsc_brg_disable(struct mpsc_port_info *pi)
-{
- u32 v;
-
- v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
- v &= ~(1 << 16);
-
- if (pi->mirror_regs)
- pi->BRG_BCR_m = v;
- writel(v, pi->brg_base + BRG_BCR);
-}
-
-/*
- * To set the baud, we adjust the CDV field in the BRG_BCR reg.
- * From manual: Baud = clk / ((CDV+1)*2) ==> CDV = (clk / (baud*2)) - 1.
- * However, the input clock is divided by 16 in the MPSC b/c of how
- * 'MPSC_MMCRH' was set up so we have to divide the 'clk' used in our
- * calculation by 16 to account for that. So the real calculation
- * that accounts for the way the mpsc is set up is:
- * CDV = (clk / (baud*2*16)) - 1 ==> CDV = (clk / (baud << 5)) - 1.
- */
-static void mpsc_set_baudrate(struct mpsc_port_info *pi, u32 baud)
-{
- u32 cdv = (pi->port.uartclk / (baud << 5)) - 1;
- u32 v;
-
- mpsc_brg_disable(pi);
- v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
- v = (v & 0xffff0000) | (cdv & 0xffff);
-
- if (pi->mirror_regs)
- pi->BRG_BCR_m = v;
- writel(v, pi->brg_base + BRG_BCR);
- mpsc_brg_enable(pi);
-}
-
-/*
- ******************************************************************************
- *
- * Serial DMA Routines (SDMA)
- *
- ******************************************************************************
- */
-
-static void mpsc_sdma_burstsize(struct mpsc_port_info *pi, u32 burst_size)
-{
- u32 v;
-
- pr_debug("mpsc_sdma_burstsize[%d]: burst_size: %d\n",
- pi->port.line, burst_size);
-
- burst_size >>= 3; /* Divide by 8 b/c reg values are 8-byte chunks */
-
- if (burst_size < 2)
- v = 0x0; /* 1 64-bit word */
- else if (burst_size < 4)
- v = 0x1; /* 2 64-bit words */
- else if (burst_size < 8)
- v = 0x2; /* 4 64-bit words */
- else
- v = 0x3; /* 8 64-bit words */
-
- writel((readl(pi->sdma_base + SDMA_SDC) & (0x3 << 12)) | (v << 12),
- pi->sdma_base + SDMA_SDC);
-}
-
-static void mpsc_sdma_init(struct mpsc_port_info *pi, u32 burst_size)
-{
- pr_debug("mpsc_sdma_init[%d]: burst_size: %d\n", pi->port.line,
- burst_size);
-
- writel((readl(pi->sdma_base + SDMA_SDC) & 0x3ff) | 0x03f,
- pi->sdma_base + SDMA_SDC);
- mpsc_sdma_burstsize(pi, burst_size);
-}
-
-static u32 mpsc_sdma_intr_mask(struct mpsc_port_info *pi, u32 mask)
-{
- u32 old, v;
-
- pr_debug("mpsc_sdma_intr_mask[%d]: mask: 0x%x\n", pi->port.line, mask);
-
- old = v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m :
- readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
-
- mask &= 0xf;
- if (pi->port.line)
- mask <<= 8;
- v &= ~mask;
-
- if (pi->mirror_regs)
- pi->shared_regs->SDMA_INTR_MASK_m = v;
- writel(v, pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
-
- if (pi->port.line)
- old >>= 8;
- return old & 0xf;
-}
-
-static void mpsc_sdma_intr_unmask(struct mpsc_port_info *pi, u32 mask)
-{
- u32 v;
-
- pr_debug("mpsc_sdma_intr_unmask[%d]: mask: 0x%x\n", pi->port.line,mask);
-
- v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m
- : readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
-
- mask &= 0xf;
- if (pi->port.line)
- mask <<= 8;
- v |= mask;
-
- if (pi->mirror_regs)
- pi->shared_regs->SDMA_INTR_MASK_m = v;
- writel(v, pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
-}
-
-static void mpsc_sdma_intr_ack(struct mpsc_port_info *pi)
-{
- pr_debug("mpsc_sdma_intr_ack[%d]: Acknowledging IRQ\n", pi->port.line);
-
- if (pi->mirror_regs)
- pi->shared_regs->SDMA_INTR_CAUSE_m = 0;
- writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE
- + pi->port.line);
-}
-
-static void mpsc_sdma_set_rx_ring(struct mpsc_port_info *pi,
- struct mpsc_rx_desc *rxre_p)
-{
- pr_debug("mpsc_sdma_set_rx_ring[%d]: rxre_p: 0x%x\n",
- pi->port.line, (u32)rxre_p);
-
- writel((u32)rxre_p, pi->sdma_base + SDMA_SCRDP);
-}
-
-static void mpsc_sdma_set_tx_ring(struct mpsc_port_info *pi,
- struct mpsc_tx_desc *txre_p)
-{
- writel((u32)txre_p, pi->sdma_base + SDMA_SFTDP);
- writel((u32)txre_p, pi->sdma_base + SDMA_SCTDP);
-}
-
-static void mpsc_sdma_cmd(struct mpsc_port_info *pi, u32 val)
-{
- u32 v;
-
- v = readl(pi->sdma_base + SDMA_SDCM);
- if (val)
- v |= val;
- else
- v = 0;
- wmb();
- writel(v, pi->sdma_base + SDMA_SDCM);
- wmb();
-}
-
-static uint mpsc_sdma_tx_active(struct mpsc_port_info *pi)
-{
- return readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_TXD;
-}
-
-static void mpsc_sdma_start_tx(struct mpsc_port_info *pi)
-{
- struct mpsc_tx_desc *txre, *txre_p;
-
- /* If tx isn't running & there's a desc ready to go, start it */
- if (!mpsc_sdma_tx_active(pi)) {
- txre = (struct mpsc_tx_desc *)(pi->txr
- + (pi->txr_tail * MPSC_TXRE_SIZE));
- dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,
- DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)txre,
- (ulong)txre + MPSC_TXRE_SIZE);
-#endif
-
- if (be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O) {
- txre_p = (struct mpsc_tx_desc *)
- (pi->txr_p + (pi->txr_tail * MPSC_TXRE_SIZE));
-
- mpsc_sdma_set_tx_ring(pi, txre_p);
- mpsc_sdma_cmd(pi, SDMA_SDCM_STD | SDMA_SDCM_TXD);
- }
- }
-}
-
-static void mpsc_sdma_stop(struct mpsc_port_info *pi)
-{
- pr_debug("mpsc_sdma_stop[%d]: Stopping SDMA\n", pi->port.line);
-
- /* Abort any SDMA transfers */
- mpsc_sdma_cmd(pi, 0);
- mpsc_sdma_cmd(pi, SDMA_SDCM_AR | SDMA_SDCM_AT);
-
- /* Clear the SDMA current and first TX and RX pointers */
- mpsc_sdma_set_tx_ring(pi, NULL);
- mpsc_sdma_set_rx_ring(pi, NULL);
-
- /* Disable interrupts */
- mpsc_sdma_intr_mask(pi, 0xf);
- mpsc_sdma_intr_ack(pi);
-}
-
-/*
- ******************************************************************************
- *
- * Multi-Protocol Serial Controller Routines (MPSC)
- *
- ******************************************************************************
- */
-
-static void mpsc_hw_init(struct mpsc_port_info *pi)
-{
- u32 v;
-
- pr_debug("mpsc_hw_init[%d]: Initializing hardware\n", pi->port.line);
-
- /* Set up clock routing */
- if (pi->mirror_regs) {
- v = pi->shared_regs->MPSC_MRR_m;
- v &= ~0x1c7;
- pi->shared_regs->MPSC_MRR_m = v;
- writel(v, pi->shared_regs->mpsc_routing_base + MPSC_MRR);
-
- v = pi->shared_regs->MPSC_RCRR_m;
- v = (v & ~0xf0f) | 0x100;
- pi->shared_regs->MPSC_RCRR_m = v;
- writel(v, pi->shared_regs->mpsc_routing_base + MPSC_RCRR);
-
- v = pi->shared_regs->MPSC_TCRR_m;
- v = (v & ~0xf0f) | 0x100;
- pi->shared_regs->MPSC_TCRR_m = v;
- writel(v, pi->shared_regs->mpsc_routing_base + MPSC_TCRR);
- } else {
- v = readl(pi->shared_regs->mpsc_routing_base + MPSC_MRR);
- v &= ~0x1c7;
- writel(v, pi->shared_regs->mpsc_routing_base + MPSC_MRR);
-
- v = readl(pi->shared_regs->mpsc_routing_base + MPSC_RCRR);
- v = (v & ~0xf0f) | 0x100;
- writel(v, pi->shared_regs->mpsc_routing_base + MPSC_RCRR);
-
- v = readl(pi->shared_regs->mpsc_routing_base + MPSC_TCRR);
- v = (v & ~0xf0f) | 0x100;
- writel(v, pi->shared_regs->mpsc_routing_base + MPSC_TCRR);
- }
-
- /* Put MPSC in UART mode & enabel Tx/Rx egines */
- writel(0x000004c4, pi->mpsc_base + MPSC_MMCRL);
-
- /* No preamble, 16x divider, low-latency, */
- writel(0x04400400, pi->mpsc_base + MPSC_MMCRH);
- mpsc_set_baudrate(pi, pi->default_baud);
-
- if (pi->mirror_regs) {
- pi->MPSC_CHR_1_m = 0;
- pi->MPSC_CHR_2_m = 0;
- }
- writel(0, pi->mpsc_base + MPSC_CHR_1);
- writel(0, pi->mpsc_base + MPSC_CHR_2);
- writel(pi->mpsc_max_idle, pi->mpsc_base + MPSC_CHR_3);
- writel(0, pi->mpsc_base + MPSC_CHR_4);
- writel(0, pi->mpsc_base + MPSC_CHR_5);
- writel(0, pi->mpsc_base + MPSC_CHR_6);
- writel(0, pi->mpsc_base + MPSC_CHR_7);
- writel(0, pi->mpsc_base + MPSC_CHR_8);
- writel(0, pi->mpsc_base + MPSC_CHR_9);
- writel(0, pi->mpsc_base + MPSC_CHR_10);
-}
-
-static void mpsc_enter_hunt(struct mpsc_port_info *pi)
-{
- pr_debug("mpsc_enter_hunt[%d]: Hunting...\n", pi->port.line);
-
- if (pi->mirror_regs) {
- writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_EH,
- pi->mpsc_base + MPSC_CHR_2);
- /* Erratum prevents reading CHR_2 so just delay for a while */
- udelay(100);
- } else {
- writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_EH,
- pi->mpsc_base + MPSC_CHR_2);
-
- while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_EH)
- udelay(10);
- }
-}
-
-static void mpsc_freeze(struct mpsc_port_info *pi)
-{
- u32 v;
-
- pr_debug("mpsc_freeze[%d]: Freezing\n", pi->port.line);
-
- v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
- readl(pi->mpsc_base + MPSC_MPCR);
- v |= MPSC_MPCR_FRZ;
-
- if (pi->mirror_regs)
- pi->MPSC_MPCR_m = v;
- writel(v, pi->mpsc_base + MPSC_MPCR);
-}
-
-static void mpsc_unfreeze(struct mpsc_port_info *pi)
-{
- u32 v;
-
- v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
- readl(pi->mpsc_base + MPSC_MPCR);
- v &= ~MPSC_MPCR_FRZ;
-
- if (pi->mirror_regs)
- pi->MPSC_MPCR_m = v;
- writel(v, pi->mpsc_base + MPSC_MPCR);
-
- pr_debug("mpsc_unfreeze[%d]: Unfrozen\n", pi->port.line);
-}
-
-static void mpsc_set_char_length(struct mpsc_port_info *pi, u32 len)
-{
- u32 v;
-
- pr_debug("mpsc_set_char_length[%d]: char len: %d\n", pi->port.line,len);
-
- v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
- readl(pi->mpsc_base + MPSC_MPCR);
- v = (v & ~(0x3 << 12)) | ((len & 0x3) << 12);
-
- if (pi->mirror_regs)
- pi->MPSC_MPCR_m = v;
- writel(v, pi->mpsc_base + MPSC_MPCR);
-}
-
-static void mpsc_set_stop_bit_length(struct mpsc_port_info *pi, u32 len)
-{
- u32 v;
-
- pr_debug("mpsc_set_stop_bit_length[%d]: stop bits: %d\n",
- pi->port.line, len);
-
- v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
- readl(pi->mpsc_base + MPSC_MPCR);
-
- v = (v & ~(1 << 14)) | ((len & 0x1) << 14);
-
- if (pi->mirror_regs)
- pi->MPSC_MPCR_m = v;
- writel(v, pi->mpsc_base + MPSC_MPCR);
-}
-
-static void mpsc_set_parity(struct mpsc_port_info *pi, u32 p)
-{
- u32 v;
-
- pr_debug("mpsc_set_parity[%d]: parity bits: 0x%x\n", pi->port.line, p);
-
- v = (pi->mirror_regs) ? pi->MPSC_CHR_2_m :
- readl(pi->mpsc_base + MPSC_CHR_2);
-
- p &= 0x3;
- v = (v & ~0xc000c) | (p << 18) | (p << 2);
-
- if (pi->mirror_regs)
- pi->MPSC_CHR_2_m = v;
- writel(v, pi->mpsc_base + MPSC_CHR_2);
-}
-
-/*
- ******************************************************************************
- *
- * Driver Init Routines
- *
- ******************************************************************************
- */
-
-static void mpsc_init_hw(struct mpsc_port_info *pi)
-{
- pr_debug("mpsc_init_hw[%d]: Initializing\n", pi->port.line);
-
- mpsc_brg_init(pi, pi->brg_clk_src);
- mpsc_brg_enable(pi);
- mpsc_sdma_init(pi, dma_get_cache_alignment()); /* burst a cacheline */
- mpsc_sdma_stop(pi);
- mpsc_hw_init(pi);
-}
-
-static int mpsc_alloc_ring_mem(struct mpsc_port_info *pi)
-{
- int rc = 0;
-
- pr_debug("mpsc_alloc_ring_mem[%d]: Allocating ring mem\n",
- pi->port.line);
-
- if (!pi->dma_region) {
- if (!dma_supported(pi->port.dev, 0xffffffff)) {
- printk(KERN_ERR "MPSC: Inadequate DMA support\n");
- rc = -ENXIO;
- } else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev,
- MPSC_DMA_ALLOC_SIZE,
- &pi->dma_region_p, GFP_KERNEL))
- == NULL) {
- printk(KERN_ERR "MPSC: Can't alloc Desc region\n");
- rc = -ENOMEM;
- }
- }
-
- return rc;
-}
-
-static void mpsc_free_ring_mem(struct mpsc_port_info *pi)
-{
- pr_debug("mpsc_free_ring_mem[%d]: Freeing ring mem\n", pi->port.line);
-
- if (pi->dma_region) {
- dma_free_noncoherent(pi->port.dev, MPSC_DMA_ALLOC_SIZE,
- pi->dma_region, pi->dma_region_p);
- pi->dma_region = NULL;
- pi->dma_region_p = (dma_addr_t)NULL;
- }
-}
-
-static void mpsc_init_rings(struct mpsc_port_info *pi)
-{
- struct mpsc_rx_desc *rxre;
- struct mpsc_tx_desc *txre;
- dma_addr_t dp, dp_p;
- u8 *bp, *bp_p;
- int i;
-
- pr_debug("mpsc_init_rings[%d]: Initializing rings\n", pi->port.line);
-
- BUG_ON(pi->dma_region == NULL);
-
- memset(pi->dma_region, 0, MPSC_DMA_ALLOC_SIZE);
-
- /*
- * Descriptors & buffers are multiples of cacheline size and must be
- * cacheline aligned.
- */
- dp = ALIGN((u32)pi->dma_region, dma_get_cache_alignment());
- dp_p = ALIGN((u32)pi->dma_region_p, dma_get_cache_alignment());
-
- /*
- * Partition dma region into rx ring descriptor, rx buffers,
- * tx ring descriptors, and tx buffers.
- */
- pi->rxr = dp;
- pi->rxr_p = dp_p;
- dp += MPSC_RXR_SIZE;
- dp_p += MPSC_RXR_SIZE;
-
- pi->rxb = (u8 *)dp;
- pi->rxb_p = (u8 *)dp_p;
- dp += MPSC_RXB_SIZE;
- dp_p += MPSC_RXB_SIZE;
-
- pi->rxr_posn = 0;
-
- pi->txr = dp;
- pi->txr_p = dp_p;
- dp += MPSC_TXR_SIZE;
- dp_p += MPSC_TXR_SIZE;
-
- pi->txb = (u8 *)dp;
- pi->txb_p = (u8 *)dp_p;
-
- pi->txr_head = 0;
- pi->txr_tail = 0;
-
- /* Init rx ring descriptors */
- dp = pi->rxr;
- dp_p = pi->rxr_p;
- bp = pi->rxb;
- bp_p = pi->rxb_p;
-
- for (i = 0; i < MPSC_RXR_ENTRIES; i++) {
- rxre = (struct mpsc_rx_desc *)dp;
-
- rxre->bufsize = cpu_to_be16(MPSC_RXBE_SIZE);
- rxre->bytecnt = cpu_to_be16(0);
- rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O
- | SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F
- | SDMA_DESC_CMDSTAT_L);
- rxre->link = cpu_to_be32(dp_p + MPSC_RXRE_SIZE);
- rxre->buf_ptr = cpu_to_be32(bp_p);
-
- dp += MPSC_RXRE_SIZE;
- dp_p += MPSC_RXRE_SIZE;
- bp += MPSC_RXBE_SIZE;
- bp_p += MPSC_RXBE_SIZE;
- }
- rxre->link = cpu_to_be32(pi->rxr_p); /* Wrap last back to first */
-
- /* Init tx ring descriptors */
- dp = pi->txr;
- dp_p = pi->txr_p;
- bp = pi->txb;
- bp_p = pi->txb_p;
-
- for (i = 0; i < MPSC_TXR_ENTRIES; i++) {
- txre = (struct mpsc_tx_desc *)dp;
-
- txre->link = cpu_to_be32(dp_p + MPSC_TXRE_SIZE);
- txre->buf_ptr = cpu_to_be32(bp_p);
-
- dp += MPSC_TXRE_SIZE;
- dp_p += MPSC_TXRE_SIZE;
- bp += MPSC_TXBE_SIZE;
- bp_p += MPSC_TXBE_SIZE;
- }
- txre->link = cpu_to_be32(pi->txr_p); /* Wrap last back to first */
-
- dma_cache_sync(pi->port.dev, (void *)pi->dma_region,
- MPSC_DMA_ALLOC_SIZE, DMA_BIDIRECTIONAL);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- flush_dcache_range((ulong)pi->dma_region,
- (ulong)pi->dma_region
- + MPSC_DMA_ALLOC_SIZE);
-#endif
-
- return;
-}
-
-static void mpsc_uninit_rings(struct mpsc_port_info *pi)
-{
- pr_debug("mpsc_uninit_rings[%d]: Uninitializing rings\n",pi->port.line);
-
- BUG_ON(pi->dma_region == NULL);
-
- pi->rxr = 0;
- pi->rxr_p = 0;
- pi->rxb = NULL;
- pi->rxb_p = NULL;
- pi->rxr_posn = 0;
-
- pi->txr = 0;
- pi->txr_p = 0;
- pi->txb = NULL;
- pi->txb_p = NULL;
- pi->txr_head = 0;
- pi->txr_tail = 0;
-}
-
-static int mpsc_make_ready(struct mpsc_port_info *pi)
-{
- int rc;
-
- pr_debug("mpsc_make_ready[%d]: Making cltr ready\n", pi->port.line);
-
- if (!pi->ready) {
- mpsc_init_hw(pi);
- if ((rc = mpsc_alloc_ring_mem(pi)))
- return rc;
- mpsc_init_rings(pi);
- pi->ready = 1;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-static int serial_polled;
-#endif
-
-/*
- ******************************************************************************
- *
- * Interrupt Handling Routines
- *
- ******************************************************************************
- */
-
-static int mpsc_rx_intr(struct mpsc_port_info *pi)
-{
- struct mpsc_rx_desc *rxre;
- struct tty_struct *tty = pi->port.state->port.tty;
- u32 cmdstat, bytes_in, i;
- int rc = 0;
- u8 *bp;
- char flag = TTY_NORMAL;
-
- pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
-
- rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE));
-
- dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,
- DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)rxre,
- (ulong)rxre + MPSC_RXRE_SIZE);
-#endif
-
- /*
- * Loop through Rx descriptors handling ones that have been completed.
- */
- while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
- & SDMA_DESC_CMDSTAT_O)) {
- bytes_in = be16_to_cpu(rxre->bytecnt);
-#ifdef CONFIG_CONSOLE_POLL
- if (unlikely(serial_polled)) {
- serial_polled = 0;
- return 0;
- }
-#endif
- /* Following use of tty struct directly is deprecated */
- if (unlikely(tty_buffer_request_room(tty, bytes_in)
- < bytes_in)) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the bytes
- * but must do so to clear interrupts.
- */
- }
-
- bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
- dma_cache_sync(pi->port.dev, (void *)bp, MPSC_RXBE_SIZE,
- DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)bp,
- (ulong)bp + MPSC_RXBE_SIZE);
-#endif
-
- /*
- * Other than for parity error, the manual provides little
- * info on what data will be in a frame flagged by any of
- * these errors. For parity error, it is the last byte in
- * the buffer that had the error. As for the rest, I guess
- * we'll assume there is no data in the buffer.
- * If there is...it gets lost.
- */
- if (unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR
- | SDMA_DESC_CMDSTAT_FR
- | SDMA_DESC_CMDSTAT_OR))) {
-
- pi->port.icount.rx++;
-
- if (cmdstat & SDMA_DESC_CMDSTAT_BR) { /* Break */
- pi->port.icount.brk++;
-
- if (uart_handle_break(&pi->port))
- goto next_frame;
- } else if (cmdstat & SDMA_DESC_CMDSTAT_FR) {
- pi->port.icount.frame++;
- } else if (cmdstat & SDMA_DESC_CMDSTAT_OR) {
- pi->port.icount.overrun++;
- }
-
- cmdstat &= pi->port.read_status_mask;
-
- if (cmdstat & SDMA_DESC_CMDSTAT_BR)
- flag = TTY_BREAK;
- else if (cmdstat & SDMA_DESC_CMDSTAT_FR)
- flag = TTY_FRAME;
- else if (cmdstat & SDMA_DESC_CMDSTAT_OR)
- flag = TTY_OVERRUN;
- else if (cmdstat & SDMA_DESC_CMDSTAT_PE)
- flag = TTY_PARITY;
- }
-
- if (uart_handle_sysrq_char(&pi->port, *bp)) {
- bp++;
- bytes_in--;
-#ifdef CONFIG_CONSOLE_POLL
- if (unlikely(serial_polled)) {
- serial_polled = 0;
- return 0;
- }
-#endif
- goto next_frame;
- }
-
- if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR
- | SDMA_DESC_CMDSTAT_FR
- | SDMA_DESC_CMDSTAT_OR)))
- && !(cmdstat & pi->port.ignore_status_mask)) {
- tty_insert_flip_char(tty, *bp, flag);
- } else {
- for (i=0; i<bytes_in; i++)
- tty_insert_flip_char(tty, *bp++, TTY_NORMAL);
-
- pi->port.icount.rx += bytes_in;
- }
-
-next_frame:
- rxre->bytecnt = cpu_to_be16(0);
- wmb();
- rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O
- | SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F
- | SDMA_DESC_CMDSTAT_L);
- wmb();
- dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,
- DMA_BIDIRECTIONAL);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- flush_dcache_range((ulong)rxre,
- (ulong)rxre + MPSC_RXRE_SIZE);
-#endif
-
- /* Advance to next descriptor */
- pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1);
- rxre = (struct mpsc_rx_desc *)
- (pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE));
- dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,
- DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)rxre,
- (ulong)rxre + MPSC_RXRE_SIZE);
-#endif
- rc = 1;
- }
-
- /* Restart rx engine, if its stopped */
- if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
- mpsc_start_rx(pi);
-
- tty_flip_buffer_push(tty);
- return rc;
-}
-
-static void mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr)
-{
- struct mpsc_tx_desc *txre;
-
- txre = (struct mpsc_tx_desc *)(pi->txr
- + (pi->txr_head * MPSC_TXRE_SIZE));
-
- txre->bytecnt = cpu_to_be16(count);
- txre->shadow = txre->bytecnt;
- wmb(); /* ensure cmdstat is last field updated */
- txre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | SDMA_DESC_CMDSTAT_F
- | SDMA_DESC_CMDSTAT_L
- | ((intr) ? SDMA_DESC_CMDSTAT_EI : 0));
- wmb();
- dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,
- DMA_BIDIRECTIONAL);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- flush_dcache_range((ulong)txre,
- (ulong)txre + MPSC_TXRE_SIZE);
-#endif
-}
-
-static void mpsc_copy_tx_data(struct mpsc_port_info *pi)
-{
- struct circ_buf *xmit = &pi->port.state->xmit;
- u8 *bp;
- u32 i;
-
- /* Make sure the desc ring isn't full */
- while (CIRC_CNT(pi->txr_head, pi->txr_tail, MPSC_TXR_ENTRIES)
- < (MPSC_TXR_ENTRIES - 1)) {
- if (pi->port.x_char) {
- /*
- * Ideally, we should use the TCS field in
- * CHR_1 to put the x_char out immediately but
- * errata prevents us from being able to read
- * CHR_2 to know that its safe to write to
- * CHR_1. Instead, just put it in-band with
- * all the other Tx data.
- */
- bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);
- *bp = pi->port.x_char;
- pi->port.x_char = 0;
- i = 1;
- } else if (!uart_circ_empty(xmit)
- && !uart_tx_stopped(&pi->port)) {
- i = min((u32)MPSC_TXBE_SIZE,
- (u32)uart_circ_chars_pending(xmit));
- i = min(i, (u32)CIRC_CNT_TO_END(xmit->head, xmit->tail,
- UART_XMIT_SIZE));
- bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);
- memcpy(bp, &xmit->buf[xmit->tail], i);
- xmit->tail = (xmit->tail + i) & (UART_XMIT_SIZE - 1);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&pi->port);
- } else { /* All tx data copied into ring bufs */
- return;
- }
-
- dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE,
- DMA_BIDIRECTIONAL);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- flush_dcache_range((ulong)bp,
- (ulong)bp + MPSC_TXBE_SIZE);
-#endif
- mpsc_setup_tx_desc(pi, i, 1);
-
- /* Advance to next descriptor */
- pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1);
- }
-}
-
-static int mpsc_tx_intr(struct mpsc_port_info *pi)
-{
- struct mpsc_tx_desc *txre;
- int rc = 0;
- unsigned long iflags;
-
- spin_lock_irqsave(&pi->tx_lock, iflags);
-
- if (!mpsc_sdma_tx_active(pi)) {
- txre = (struct mpsc_tx_desc *)(pi->txr
- + (pi->txr_tail * MPSC_TXRE_SIZE));
-
- dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,
- DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)txre,
- (ulong)txre + MPSC_TXRE_SIZE);
-#endif
-
- while (!(be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O)) {
- rc = 1;
- pi->port.icount.tx += be16_to_cpu(txre->bytecnt);
- pi->txr_tail = (pi->txr_tail+1) & (MPSC_TXR_ENTRIES-1);
-
- /* If no more data to tx, fall out of loop */
- if (pi->txr_head == pi->txr_tail)
- break;
-
- txre = (struct mpsc_tx_desc *)(pi->txr
- + (pi->txr_tail * MPSC_TXRE_SIZE));
- dma_cache_sync(pi->port.dev, (void *)txre,
- MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)txre,
- (ulong)txre + MPSC_TXRE_SIZE);
-#endif
- }
-
- mpsc_copy_tx_data(pi);
- mpsc_sdma_start_tx(pi); /* start next desc if ready */
- }
-
- spin_unlock_irqrestore(&pi->tx_lock, iflags);
- return rc;
-}
-
-/*
- * This is the driver's interrupt handler. To avoid a race, we first clear
- * the interrupt, then handle any completed Rx/Tx descriptors. When done
- * handling those descriptors, we restart the Rx/Tx engines if they're stopped.
- */
-static irqreturn_t mpsc_sdma_intr(int irq, void *dev_id)
-{
- struct mpsc_port_info *pi = dev_id;
- ulong iflags;
- int rc = IRQ_NONE;
-
- pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Received\n",pi->port.line);
-
- spin_lock_irqsave(&pi->port.lock, iflags);
- mpsc_sdma_intr_ack(pi);
- if (mpsc_rx_intr(pi))
- rc = IRQ_HANDLED;
- if (mpsc_tx_intr(pi))
- rc = IRQ_HANDLED;
- spin_unlock_irqrestore(&pi->port.lock, iflags);
-
- pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Handled\n", pi->port.line);
- return rc;
-}
-
-/*
- ******************************************************************************
- *
- * serial_core.c Interface routines
- *
- ******************************************************************************
- */
-static uint mpsc_tx_empty(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- ulong iflags;
- uint rc;
-
- spin_lock_irqsave(&pi->port.lock, iflags);
- rc = mpsc_sdma_tx_active(pi) ? 0 : TIOCSER_TEMT;
- spin_unlock_irqrestore(&pi->port.lock, iflags);
-
- return rc;
-}
-
-static void mpsc_set_mctrl(struct uart_port *port, uint mctrl)
-{
- /* Have no way to set modem control lines AFAICT */
-}
-
-static uint mpsc_get_mctrl(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- u32 mflags, status;
-
- status = (pi->mirror_regs) ? pi->MPSC_CHR_10_m
- : readl(pi->mpsc_base + MPSC_CHR_10);
-
- mflags = 0;
- if (status & 0x1)
- mflags |= TIOCM_CTS;
- if (status & 0x2)
- mflags |= TIOCM_CAR;
-
- return mflags | TIOCM_DSR; /* No way to tell if DSR asserted */
-}
-
-static void mpsc_stop_tx(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
-
- pr_debug("mpsc_stop_tx[%d]\n", port->line);
-
- mpsc_freeze(pi);
-}
-
-static void mpsc_start_tx(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- unsigned long iflags;
-
- spin_lock_irqsave(&pi->tx_lock, iflags);
-
- mpsc_unfreeze(pi);
- mpsc_copy_tx_data(pi);
- mpsc_sdma_start_tx(pi);
-
- spin_unlock_irqrestore(&pi->tx_lock, iflags);
-
- pr_debug("mpsc_start_tx[%d]\n", port->line);
-}
-
-static void mpsc_start_rx(struct mpsc_port_info *pi)
-{
- pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line);
-
- if (pi->rcv_data) {
- mpsc_enter_hunt(pi);
- mpsc_sdma_cmd(pi, SDMA_SDCM_ERD);
- }
-}
-
-static void mpsc_stop_rx(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
-
- pr_debug("mpsc_stop_rx[%d]: Stopping...\n", port->line);
-
- if (pi->mirror_regs) {
- writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_RA,
- pi->mpsc_base + MPSC_CHR_2);
- /* Erratum prevents reading CHR_2 so just delay for a while */
- udelay(100);
- } else {
- writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_RA,
- pi->mpsc_base + MPSC_CHR_2);
-
- while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_RA)
- udelay(10);
- }
-
- mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
-}
-
-static void mpsc_enable_ms(struct uart_port *port)
-{
-}
-
-static void mpsc_break_ctl(struct uart_port *port, int ctl)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- ulong flags;
- u32 v;
-
- v = ctl ? 0x00ff0000 : 0;
-
- spin_lock_irqsave(&pi->port.lock, flags);
- if (pi->mirror_regs)
- pi->MPSC_CHR_1_m = v;
- writel(v, pi->mpsc_base + MPSC_CHR_1);
- spin_unlock_irqrestore(&pi->port.lock, flags);
-}
-
-static int mpsc_startup(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- u32 flag = 0;
- int rc;
-
- pr_debug("mpsc_startup[%d]: Starting up MPSC, irq: %d\n",
- port->line, pi->port.irq);
-
- if ((rc = mpsc_make_ready(pi)) == 0) {
- /* Setup IRQ handler */
- mpsc_sdma_intr_ack(pi);
-
- /* If irq's are shared, need to set flag */
- if (mpsc_ports[0].port.irq == mpsc_ports[1].port.irq)
- flag = IRQF_SHARED;
-
- if (request_irq(pi->port.irq, mpsc_sdma_intr, flag,
- "mpsc-sdma", pi))
- printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d\n",
- pi->port.irq);
-
- mpsc_sdma_intr_unmask(pi, 0xf);
- mpsc_sdma_set_rx_ring(pi, (struct mpsc_rx_desc *)(pi->rxr_p
- + (pi->rxr_posn * MPSC_RXRE_SIZE)));
- }
-
- return rc;
-}
-
-static void mpsc_shutdown(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
-
- pr_debug("mpsc_shutdown[%d]: Shutting down MPSC\n", port->line);
-
- mpsc_sdma_stop(pi);
- free_irq(pi->port.irq, pi);
-}
-
-static void mpsc_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- u32 baud;
- ulong flags;
- u32 chr_bits, stop_bits, par;
-
- pi->c_iflag = termios->c_iflag;
- pi->c_cflag = termios->c_cflag;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- chr_bits = MPSC_MPCR_CL_5;
- break;
- case CS6:
- chr_bits = MPSC_MPCR_CL_6;
- break;
- case CS7:
- chr_bits = MPSC_MPCR_CL_7;
- break;
- case CS8:
- default:
- chr_bits = MPSC_MPCR_CL_8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- stop_bits = MPSC_MPCR_SBL_2;
- else
- stop_bits = MPSC_MPCR_SBL_1;
-
- par = MPSC_CHR_2_PAR_EVEN;
- if (termios->c_cflag & PARENB)
- if (termios->c_cflag & PARODD)
- par = MPSC_CHR_2_PAR_ODD;
-#ifdef CMSPAR
- if (termios->c_cflag & CMSPAR) {
- if (termios->c_cflag & PARODD)
- par = MPSC_CHR_2_PAR_MARK;
- else
- par = MPSC_CHR_2_PAR_SPACE;
- }
-#endif
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk);
-
- spin_lock_irqsave(&pi->port.lock, flags);
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- mpsc_set_char_length(pi, chr_bits);
- mpsc_set_stop_bit_length(pi, stop_bits);
- mpsc_set_parity(pi, par);
- mpsc_set_baudrate(pi, baud);
-
- /* Characters/events to read */
- pi->port.read_status_mask = SDMA_DESC_CMDSTAT_OR;
-
- if (termios->c_iflag & INPCK)
- pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_PE
- | SDMA_DESC_CMDSTAT_FR;
-
- if (termios->c_iflag & (BRKINT | PARMRK))
- pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_BR;
-
- /* Characters/events to ignore */
- pi->port.ignore_status_mask = 0;
-
- if (termios->c_iflag & IGNPAR)
- pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_PE
- | SDMA_DESC_CMDSTAT_FR;
-
- if (termios->c_iflag & IGNBRK) {
- pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_BR;
-
- if (termios->c_iflag & IGNPAR)
- pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_OR;
- }
-
- if ((termios->c_cflag & CREAD)) {
- if (!pi->rcv_data) {
- pi->rcv_data = 1;
- mpsc_start_rx(pi);
- }
- } else if (pi->rcv_data) {
- mpsc_stop_rx(port);
- pi->rcv_data = 0;
- }
-
- spin_unlock_irqrestore(&pi->port.lock, flags);
-}
-
-static const char *mpsc_type(struct uart_port *port)
-{
- pr_debug("mpsc_type[%d]: port type: %s\n", port->line,MPSC_DRIVER_NAME);
- return MPSC_DRIVER_NAME;
-}
-
-static int mpsc_request_port(struct uart_port *port)
-{
- /* Should make chip/platform specific call */
- return 0;
-}
-
-static void mpsc_release_port(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
-
- if (pi->ready) {
- mpsc_uninit_rings(pi);
- mpsc_free_ring_mem(pi);
- pi->ready = 0;
- }
-}
-
-static void mpsc_config_port(struct uart_port *port, int flags)
-{
-}
-
-static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- int rc = 0;
-
- pr_debug("mpsc_verify_port[%d]: Verifying port data\n", pi->port.line);
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_MPSC)
- rc = -EINVAL;
- else if (pi->port.irq != ser->irq)
- rc = -EINVAL;
- else if (ser->io_type != SERIAL_IO_MEM)
- rc = -EINVAL;
- else if (pi->port.uartclk / 16 != ser->baud_base) /* Not sure */
- rc = -EINVAL;
- else if ((void *)pi->port.mapbase != ser->iomem_base)
- rc = -EINVAL;
- else if (pi->port.iobase != ser->port)
- rc = -EINVAL;
- else if (ser->hub6 != 0)
- rc = -EINVAL;
-
- return rc;
-}
-#ifdef CONFIG_CONSOLE_POLL
-/* Serial polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static char poll_buf[2048];
-static int poll_ptr;
-static int poll_cnt;
-static void mpsc_put_poll_char(struct uart_port *port,
- unsigned char c);
-
-static int mpsc_get_poll_char(struct uart_port *port)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- struct mpsc_rx_desc *rxre;
- u32 cmdstat, bytes_in, i;
- u8 *bp;
-
- if (!serial_polled)
- serial_polled = 1;
-
- pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
-
- if (poll_cnt) {
- poll_cnt--;
- return poll_buf[poll_ptr++];
- }
- poll_ptr = 0;
- poll_cnt = 0;
-
- while (poll_cnt == 0) {
- rxre = (struct mpsc_rx_desc *)(pi->rxr +
- (pi->rxr_posn*MPSC_RXRE_SIZE));
- dma_cache_sync(pi->port.dev, (void *)rxre,
- MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)rxre,
- (ulong)rxre + MPSC_RXRE_SIZE);
-#endif
- /*
- * Loop through Rx descriptors handling ones that have
- * been completed.
- */
- while (poll_cnt == 0 &&
- !((cmdstat = be32_to_cpu(rxre->cmdstat)) &
- SDMA_DESC_CMDSTAT_O)){
- bytes_in = be16_to_cpu(rxre->bytecnt);
- bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
- dma_cache_sync(pi->port.dev, (void *) bp,
- MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)bp,
- (ulong)bp + MPSC_RXBE_SIZE);
-#endif
- if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR |
- SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) &&
- !(cmdstat & pi->port.ignore_status_mask)) {
- poll_buf[poll_cnt] = *bp;
- poll_cnt++;
- } else {
- for (i = 0; i < bytes_in; i++) {
- poll_buf[poll_cnt] = *bp++;
- poll_cnt++;
- }
- pi->port.icount.rx += bytes_in;
- }
- rxre->bytecnt = cpu_to_be16(0);
- wmb();
- rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O |
- SDMA_DESC_CMDSTAT_EI |
- SDMA_DESC_CMDSTAT_F |
- SDMA_DESC_CMDSTAT_L);
- wmb();
- dma_cache_sync(pi->port.dev, (void *)rxre,
- MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- flush_dcache_range((ulong)rxre,
- (ulong)rxre + MPSC_RXRE_SIZE);
-#endif
-
- /* Advance to next descriptor */
- pi->rxr_posn = (pi->rxr_posn + 1) &
- (MPSC_RXR_ENTRIES - 1);
- rxre = (struct mpsc_rx_desc *)(pi->rxr +
- (pi->rxr_posn * MPSC_RXRE_SIZE));
- dma_cache_sync(pi->port.dev, (void *)rxre,
- MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- invalidate_dcache_range((ulong)rxre,
- (ulong)rxre + MPSC_RXRE_SIZE);
-#endif
- }
-
- /* Restart rx engine, if its stopped */
- if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
- mpsc_start_rx(pi);
- }
- if (poll_cnt) {
- poll_cnt--;
- return poll_buf[poll_ptr++];
- }
-
- return 0;
-}
-
-
-static void mpsc_put_poll_char(struct uart_port *port,
- unsigned char c)
-{
- struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- u32 data;
-
- data = readl(pi->mpsc_base + MPSC_MPCR);
- writeb(c, pi->mpsc_base + MPSC_CHR_1);
- mb();
- data = readl(pi->mpsc_base + MPSC_CHR_2);
- data |= MPSC_CHR_2_TTCS;
- writel(data, pi->mpsc_base + MPSC_CHR_2);
- mb();
-
- while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS);
-}
-#endif
-
-static struct uart_ops mpsc_pops = {
- .tx_empty = mpsc_tx_empty,
- .set_mctrl = mpsc_set_mctrl,
- .get_mctrl = mpsc_get_mctrl,
- .stop_tx = mpsc_stop_tx,
- .start_tx = mpsc_start_tx,
- .stop_rx = mpsc_stop_rx,
- .enable_ms = mpsc_enable_ms,
- .break_ctl = mpsc_break_ctl,
- .startup = mpsc_startup,
- .shutdown = mpsc_shutdown,
- .set_termios = mpsc_set_termios,
- .type = mpsc_type,
- .release_port = mpsc_release_port,
- .request_port = mpsc_request_port,
- .config_port = mpsc_config_port,
- .verify_port = mpsc_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = mpsc_get_poll_char,
- .poll_put_char = mpsc_put_poll_char,
-#endif
-};
-
-/*
- ******************************************************************************
- *
- * Console Interface Routines
- *
- ******************************************************************************
- */
-
-#ifdef CONFIG_SERIAL_MPSC_CONSOLE
-static void mpsc_console_write(struct console *co, const char *s, uint count)
-{
- struct mpsc_port_info *pi = &mpsc_ports[co->index];
- u8 *bp, *dp, add_cr = 0;
- int i;
- unsigned long iflags;
-
- spin_lock_irqsave(&pi->tx_lock, iflags);
-
- while (pi->txr_head != pi->txr_tail) {
- while (mpsc_sdma_tx_active(pi))
- udelay(100);
- mpsc_sdma_intr_ack(pi);
- mpsc_tx_intr(pi);
- }
-
- while (mpsc_sdma_tx_active(pi))
- udelay(100);
-
- while (count > 0) {
- bp = dp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);
-
- for (i = 0; i < MPSC_TXBE_SIZE; i++) {
- if (count == 0)
- break;
-
- if (add_cr) {
- *(dp++) = '\r';
- add_cr = 0;
- } else {
- *(dp++) = *s;
-
- if (*(s++) == '\n') { /* add '\r' after '\n' */
- add_cr = 1;
- count++;
- }
- }
-
- count--;
- }
-
- dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE,
- DMA_BIDIRECTIONAL);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
- flush_dcache_range((ulong)bp,
- (ulong)bp + MPSC_TXBE_SIZE);
-#endif
- mpsc_setup_tx_desc(pi, i, 0);
- pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1);
- mpsc_sdma_start_tx(pi);
-
- while (mpsc_sdma_tx_active(pi))
- udelay(100);
-
- pi->txr_tail = (pi->txr_tail + 1) & (MPSC_TXR_ENTRIES - 1);
- }
-
- spin_unlock_irqrestore(&pi->tx_lock, iflags);
-}
-
-static int __init mpsc_console_setup(struct console *co, char *options)
-{
- struct mpsc_port_info *pi;
- int baud, bits, parity, flow;
-
- pr_debug("mpsc_console_setup[%d]: options: %s\n", co->index, options);
-
- if (co->index >= MPSC_NUM_CTLRS)
- co->index = 0;
-
- pi = &mpsc_ports[co->index];
-
- baud = pi->default_baud;
- bits = pi->default_bits;
- parity = pi->default_parity;
- flow = pi->default_flow;
-
- if (!pi->port.ops)
- return -ENODEV;
-
- spin_lock_init(&pi->port.lock); /* Temporary fix--copied from 8250.c */
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&pi->port, co, baud, parity, bits, flow);
-}
-
-static struct console mpsc_console = {
- .name = MPSC_DEV_NAME,
- .write = mpsc_console_write,
- .device = uart_console_device,
- .setup = mpsc_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &mpsc_reg,
-};
-
-static int __init mpsc_late_console_init(void)
-{
- pr_debug("mpsc_late_console_init: Enter\n");
-
- if (!(mpsc_console.flags & CON_ENABLED))
- register_console(&mpsc_console);
- return 0;
-}
-
-late_initcall(mpsc_late_console_init);
-
-#define MPSC_CONSOLE &mpsc_console
-#else
-#define MPSC_CONSOLE NULL
-#endif
-/*
- ******************************************************************************
- *
- * Dummy Platform Driver to extract & map shared register regions
- *
- ******************************************************************************
- */
-static void mpsc_resource_err(char *s)
-{
- printk(KERN_WARNING "MPSC: Platform device resource error in %s\n", s);
-}
-
-static int mpsc_shared_map_regs(struct platform_device *pd)
-{
- struct resource *r;
-
- if ((r = platform_get_resource(pd, IORESOURCE_MEM,
- MPSC_ROUTING_BASE_ORDER))
- && request_mem_region(r->start,
- MPSC_ROUTING_REG_BLOCK_SIZE,
- "mpsc_routing_regs")) {
- mpsc_shared_regs.mpsc_routing_base = ioremap(r->start,
- MPSC_ROUTING_REG_BLOCK_SIZE);
- mpsc_shared_regs.mpsc_routing_base_p = r->start;
- } else {
- mpsc_resource_err("MPSC routing base");
- return -ENOMEM;
- }
-
- if ((r = platform_get_resource(pd, IORESOURCE_MEM,
- MPSC_SDMA_INTR_BASE_ORDER))
- && request_mem_region(r->start,
- MPSC_SDMA_INTR_REG_BLOCK_SIZE,
- "sdma_intr_regs")) {
- mpsc_shared_regs.sdma_intr_base = ioremap(r->start,
- MPSC_SDMA_INTR_REG_BLOCK_SIZE);
- mpsc_shared_regs.sdma_intr_base_p = r->start;
- } else {
- iounmap(mpsc_shared_regs.mpsc_routing_base);
- release_mem_region(mpsc_shared_regs.mpsc_routing_base_p,
- MPSC_ROUTING_REG_BLOCK_SIZE);
- mpsc_resource_err("SDMA intr base");
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void mpsc_shared_unmap_regs(void)
-{
- if (!mpsc_shared_regs.mpsc_routing_base) {
- iounmap(mpsc_shared_regs.mpsc_routing_base);
- release_mem_region(mpsc_shared_regs.mpsc_routing_base_p,
- MPSC_ROUTING_REG_BLOCK_SIZE);
- }
- if (!mpsc_shared_regs.sdma_intr_base) {
- iounmap(mpsc_shared_regs.sdma_intr_base);
- release_mem_region(mpsc_shared_regs.sdma_intr_base_p,
- MPSC_SDMA_INTR_REG_BLOCK_SIZE);
- }
-
- mpsc_shared_regs.mpsc_routing_base = NULL;
- mpsc_shared_regs.sdma_intr_base = NULL;
-
- mpsc_shared_regs.mpsc_routing_base_p = 0;
- mpsc_shared_regs.sdma_intr_base_p = 0;
-}
-
-static int mpsc_shared_drv_probe(struct platform_device *dev)
-{
- struct mpsc_shared_pdata *pdata;
- int rc = -ENODEV;
-
- if (dev->id == 0) {
- if (!(rc = mpsc_shared_map_regs(dev))) {
- pdata = (struct mpsc_shared_pdata *)
- dev->dev.platform_data;
-
- mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val;
- mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val;
- mpsc_shared_regs.MPSC_TCRR_m= pdata->tcrr_val;
- mpsc_shared_regs.SDMA_INTR_CAUSE_m =
- pdata->intr_cause_val;
- mpsc_shared_regs.SDMA_INTR_MASK_m =
- pdata->intr_mask_val;
-
- rc = 0;
- }
- }
-
- return rc;
-}
-
-static int mpsc_shared_drv_remove(struct platform_device *dev)
-{
- int rc = -ENODEV;
-
- if (dev->id == 0) {
- mpsc_shared_unmap_regs();
- mpsc_shared_regs.MPSC_MRR_m = 0;
- mpsc_shared_regs.MPSC_RCRR_m = 0;
- mpsc_shared_regs.MPSC_TCRR_m = 0;
- mpsc_shared_regs.SDMA_INTR_CAUSE_m = 0;
- mpsc_shared_regs.SDMA_INTR_MASK_m = 0;
- rc = 0;
- }
-
- return rc;
-}
-
-static struct platform_driver mpsc_shared_driver = {
- .probe = mpsc_shared_drv_probe,
- .remove = mpsc_shared_drv_remove,
- .driver = {
- .name = MPSC_SHARED_NAME,
- },
-};
-
-/*
- ******************************************************************************
- *
- * Driver Interface Routines
- *
- ******************************************************************************
- */
-static struct uart_driver mpsc_reg = {
- .owner = THIS_MODULE,
- .driver_name = MPSC_DRIVER_NAME,
- .dev_name = MPSC_DEV_NAME,
- .major = MPSC_MAJOR,
- .minor = MPSC_MINOR_START,
- .nr = MPSC_NUM_CTLRS,
- .cons = MPSC_CONSOLE,
-};
-
-static int mpsc_drv_map_regs(struct mpsc_port_info *pi,
- struct platform_device *pd)
-{
- struct resource *r;
-
- if ((r = platform_get_resource(pd, IORESOURCE_MEM, MPSC_BASE_ORDER))
- && request_mem_region(r->start, MPSC_REG_BLOCK_SIZE,
- "mpsc_regs")) {
- pi->mpsc_base = ioremap(r->start, MPSC_REG_BLOCK_SIZE);
- pi->mpsc_base_p = r->start;
- } else {
- mpsc_resource_err("MPSC base");
- goto err;
- }
-
- if ((r = platform_get_resource(pd, IORESOURCE_MEM,
- MPSC_SDMA_BASE_ORDER))
- && request_mem_region(r->start,
- MPSC_SDMA_REG_BLOCK_SIZE, "sdma_regs")) {
- pi->sdma_base = ioremap(r->start,MPSC_SDMA_REG_BLOCK_SIZE);
- pi->sdma_base_p = r->start;
- } else {
- mpsc_resource_err("SDMA base");
- if (pi->mpsc_base) {
- iounmap(pi->mpsc_base);
- pi->mpsc_base = NULL;
- }
- goto err;
- }
-
- if ((r = platform_get_resource(pd,IORESOURCE_MEM,MPSC_BRG_BASE_ORDER))
- && request_mem_region(r->start,
- MPSC_BRG_REG_BLOCK_SIZE, "brg_regs")) {
- pi->brg_base = ioremap(r->start, MPSC_BRG_REG_BLOCK_SIZE);
- pi->brg_base_p = r->start;
- } else {
- mpsc_resource_err("BRG base");
- if (pi->mpsc_base) {
- iounmap(pi->mpsc_base);
- pi->mpsc_base = NULL;
- }
- if (pi->sdma_base) {
- iounmap(pi->sdma_base);
- pi->sdma_base = NULL;
- }
- goto err;
- }
- return 0;
-
-err:
- return -ENOMEM;
-}
-
-static void mpsc_drv_unmap_regs(struct mpsc_port_info *pi)
-{
- if (!pi->mpsc_base) {
- iounmap(pi->mpsc_base);
- release_mem_region(pi->mpsc_base_p, MPSC_REG_BLOCK_SIZE);
- }
- if (!pi->sdma_base) {
- iounmap(pi->sdma_base);
- release_mem_region(pi->sdma_base_p, MPSC_SDMA_REG_BLOCK_SIZE);
- }
- if (!pi->brg_base) {
- iounmap(pi->brg_base);
- release_mem_region(pi->brg_base_p, MPSC_BRG_REG_BLOCK_SIZE);
- }
-
- pi->mpsc_base = NULL;
- pi->sdma_base = NULL;
- pi->brg_base = NULL;
-
- pi->mpsc_base_p = 0;
- pi->sdma_base_p = 0;
- pi->brg_base_p = 0;
-}
-
-static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi,
- struct platform_device *pd, int num)
-{
- struct mpsc_pdata *pdata;
-
- pdata = (struct mpsc_pdata *)pd->dev.platform_data;
-
- pi->port.uartclk = pdata->brg_clk_freq;
- pi->port.iotype = UPIO_MEM;
- pi->port.line = num;
- pi->port.type = PORT_MPSC;
- pi->port.fifosize = MPSC_TXBE_SIZE;
- pi->port.membase = pi->mpsc_base;
- pi->port.mapbase = (ulong)pi->mpsc_base;
- pi->port.ops = &mpsc_pops;
-
- pi->mirror_regs = pdata->mirror_regs;
- pi->cache_mgmt = pdata->cache_mgmt;
- pi->brg_can_tune = pdata->brg_can_tune;
- pi->brg_clk_src = pdata->brg_clk_src;
- pi->mpsc_max_idle = pdata->max_idle;
- pi->default_baud = pdata->default_baud;
- pi->default_bits = pdata->default_bits;
- pi->default_parity = pdata->default_parity;
- pi->default_flow = pdata->default_flow;
-
- /* Initial values of mirrored regs */
- pi->MPSC_CHR_1_m = pdata->chr_1_val;
- pi->MPSC_CHR_2_m = pdata->chr_2_val;
- pi->MPSC_CHR_10_m = pdata->chr_10_val;
- pi->MPSC_MPCR_m = pdata->mpcr_val;
- pi->BRG_BCR_m = pdata->bcr_val;
-
- pi->shared_regs = &mpsc_shared_regs;
-
- pi->port.irq = platform_get_irq(pd, 0);
-}
-
-static int mpsc_drv_probe(struct platform_device *dev)
-{
- struct mpsc_port_info *pi;
- int rc = -ENODEV;
-
- pr_debug("mpsc_drv_probe: Adding MPSC %d\n", dev->id);
-
- if (dev->id < MPSC_NUM_CTLRS) {
- pi = &mpsc_ports[dev->id];
-
- if (!(rc = mpsc_drv_map_regs(pi, dev))) {
- mpsc_drv_get_platform_data(pi, dev, dev->id);
- pi->port.dev = &dev->dev;
-
- if (!(rc = mpsc_make_ready(pi))) {
- spin_lock_init(&pi->tx_lock);
- if (!(rc = uart_add_one_port(&mpsc_reg,
- &pi->port))) {
- rc = 0;
- } else {
- mpsc_release_port((struct uart_port *)
- pi);
- mpsc_drv_unmap_regs(pi);
- }
- } else {
- mpsc_drv_unmap_regs(pi);
- }
- }
- }
-
- return rc;
-}
-
-static int mpsc_drv_remove(struct platform_device *dev)
-{
- pr_debug("mpsc_drv_exit: Removing MPSC %d\n", dev->id);
-
- if (dev->id < MPSC_NUM_CTLRS) {
- uart_remove_one_port(&mpsc_reg, &mpsc_ports[dev->id].port);
- mpsc_release_port((struct uart_port *)
- &mpsc_ports[dev->id].port);
- mpsc_drv_unmap_regs(&mpsc_ports[dev->id]);
- return 0;
- } else {
- return -ENODEV;
- }
-}
-
-static struct platform_driver mpsc_driver = {
- .probe = mpsc_drv_probe,
- .remove = mpsc_drv_remove,
- .driver = {
- .name = MPSC_CTLR_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init mpsc_drv_init(void)
-{
- int rc;
-
- printk(KERN_INFO "Serial: MPSC driver\n");
-
- memset(mpsc_ports, 0, sizeof(mpsc_ports));
- memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs));
-
- if (!(rc = uart_register_driver(&mpsc_reg))) {
- if (!(rc = platform_driver_register(&mpsc_shared_driver))) {
- if ((rc = platform_driver_register(&mpsc_driver))) {
- platform_driver_unregister(&mpsc_shared_driver);
- uart_unregister_driver(&mpsc_reg);
- }
- } else {
- uart_unregister_driver(&mpsc_reg);
- }
- }
-
- return rc;
-}
-
-static void __exit mpsc_drv_exit(void)
-{
- platform_driver_unregister(&mpsc_driver);
- platform_driver_unregister(&mpsc_shared_driver);
- uart_unregister_driver(&mpsc_reg);
- memset(mpsc_ports, 0, sizeof(mpsc_ports));
- memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs));
-}
-
-module_init(mpsc_drv_init);
-module_exit(mpsc_drv_exit);
-
-MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
-MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver");
-MODULE_VERSION(MPSC_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(MPSC_MAJOR);
-MODULE_ALIAS("platform:" MPSC_CTLR_NAME);
diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c
deleted file mode 100644
index b62857bf2fdb..000000000000
--- a/drivers/serial/mrst_max3110.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- * mrst_max3110.c - spi uart protocol driver for Maxim 3110
- *
- * Copyright (c) 2008-2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
- * Note:
- * 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has
- * 1 word. If SPI master controller doesn't support sclk frequency change,
- * then the char need be sent out one by one with some delay
- *
- * 2. Currently only RX availabe interrrupt is used, no need for waiting TXE
- * interrupt for a low speed UART device
- */
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-
-#include <linux/kthread.h>
-#include <linux/spi/spi.h>
-
-#include "mrst_max3110.h"
-
-#define PR_FMT "mrst_max3110: "
-
-#define UART_TX_NEEDED 1
-#define CON_TX_NEEDED 2
-#define BIT_IRQ_PENDING 3
-
-struct uart_max3110 {
- struct uart_port port;
- struct spi_device *spi;
- char name[24];
-
- wait_queue_head_t wq;
- struct task_struct *main_thread;
- struct task_struct *read_thread;
- struct mutex thread_mutex;;
-
- u32 baud;
- u16 cur_conf;
- u8 clock;
- u8 parity, word_7bits;
- u16 irq;
-
- unsigned long uart_flags;
-
- /* console related */
- struct circ_buf con_xmit;
-};
-
-/* global data structure, may need be removed */
-static struct uart_max3110 *pmax;
-
-static void receive_chars(struct uart_max3110 *max,
- unsigned char *str, int len);
-static int max3110_read_multi(struct uart_max3110 *max, u8 *buf);
-static void max3110_con_receive(struct uart_max3110 *max);
-
-static int max3110_write_then_read(struct uart_max3110 *max,
- const void *txbuf, void *rxbuf, unsigned len, int always_fast)
-{
- struct spi_device *spi = max->spi;
- struct spi_message message;
- struct spi_transfer x;
- int ret;
-
- spi_message_init(&message);
- memset(&x, 0, sizeof x);
- x.len = len;
- x.tx_buf = txbuf;
- x.rx_buf = rxbuf;
- spi_message_add_tail(&x, &message);
-
- if (always_fast)
- x.speed_hz = spi->max_speed_hz;
- else if (max->baud)
- x.speed_hz = max->baud;
-
- /* Do the i/o */
- ret = spi_sync(spi, &message);
- return ret;
-}
-
-/* Write a 16b word to the device */
-static int max3110_out(struct uart_max3110 *max, const u16 out)
-{
- void *buf;
- u16 *obuf, *ibuf;
- u8 ch;
- int ret;
-
- buf = kzalloc(8, GFP_KERNEL | GFP_DMA);
- if (!buf)
- return -ENOMEM;
-
- obuf = buf;
- ibuf = buf + 4;
- *obuf = out;
- ret = max3110_write_then_read(max, obuf, ibuf, 2, 1);
- if (ret) {
- pr_warning(PR_FMT "%s(): get err msg %d when sending 0x%x\n",
- __func__, ret, out);
- goto exit;
- }
-
- /* If some valid data is read back */
- if (*ibuf & MAX3110_READ_DATA_AVAILABLE) {
- ch = *ibuf & 0xff;
- receive_chars(max, &ch, 1);
- }
-
-exit:
- kfree(buf);
- return ret;
-}
-
-/*
- * This is usually used to read data from SPIC RX FIFO, which doesn't
- * need any delay like flushing character out.
- *
- * Return how many valide bytes are read back
- */
-static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf)
-{
- void *buf;
- u16 *obuf, *ibuf;
- u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH];
- int i, j, blen;
-
- blen = M3110_RX_FIFO_DEPTH * sizeof(u16);
- buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA);
- if (!buf) {
- pr_warning(PR_FMT "%s(): fail to alloc dma buffer\n", __func__);
- return 0;
- }
-
- /* tx/rx always have the same length */
- obuf = buf;
- ibuf = buf + blen;
-
- if (max3110_write_then_read(max, obuf, ibuf, blen, 1)) {
- kfree(buf);
- return 0;
- }
-
- /* If caller doesn't provide a buffer, then handle received char */
- pbuf = rxbuf ? rxbuf : valid_str;
-
- for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) {
- if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
- pbuf[j++] = ibuf[i] & 0xff;
- }
-
- if (j && (pbuf == valid_str))
- receive_chars(max, valid_str, j);
-
- kfree(buf);
- return j;
-}
-
-static void serial_m3110_con_putchar(struct uart_port *port, int ch)
-{
- struct uart_max3110 *max =
- container_of(port, struct uart_max3110, port);
- struct circ_buf *xmit = &max->con_xmit;
-
- if (uart_circ_chars_free(xmit)) {
- xmit->buf[xmit->head] = (char)ch;
- xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1);
- }
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void serial_m3110_con_write(struct console *co,
- const char *s, unsigned int count)
-{
- if (!pmax)
- return;
-
- uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar);
-
- if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags))
- wake_up_process(pmax->main_thread);
-}
-
-static int __init
-serial_m3110_con_setup(struct console *co, char *options)
-{
- struct uart_max3110 *max = pmax;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- pr_info(PR_FMT "setting up console\n");
-
- if (co->index == -1)
- co->index = 0;
-
- if (!max) {
- pr_err(PR_FMT "pmax is NULL, return");
- return -ENODEV;
- }
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&max->port, co, baud, parity, bits, flow);
-}
-
-static struct tty_driver *serial_m3110_con_device(struct console *co,
- int *index)
-{
- struct uart_driver *p = co->data;
- *index = co->index;
- return p->tty_driver;
-}
-
-static struct uart_driver serial_m3110_reg;
-static struct console serial_m3110_console = {
- .name = "ttyS",
- .write = serial_m3110_con_write,
- .device = serial_m3110_con_device,
- .setup = serial_m3110_con_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &serial_m3110_reg,
-};
-
-static unsigned int serial_m3110_tx_empty(struct uart_port *port)
-{
- return 1;
-}
-
-static void serial_m3110_stop_tx(struct uart_port *port)
-{
- return;
-}
-
-/* stop_rx will be called in spin_lock env */
-static void serial_m3110_stop_rx(struct uart_port *port)
-{
- return;
-}
-
-#define WORDS_PER_XFER 128
-static void send_circ_buf(struct uart_max3110 *max,
- struct circ_buf *xmit)
-{
- void *buf;
- u16 *obuf, *ibuf;
- u8 valid_str[WORDS_PER_XFER];
- int i, j, len, blen, dma_size, left, ret = 0;
-
-
- dma_size = WORDS_PER_XFER * sizeof(u16) * 2;
- buf = kzalloc(dma_size, GFP_KERNEL | GFP_DMA);
- if (!buf)
- return;
- obuf = buf;
- ibuf = buf + dma_size/2;
-
- while (!uart_circ_empty(xmit)) {
- left = uart_circ_chars_pending(xmit);
- while (left) {
- len = min(left, WORDS_PER_XFER);
- blen = len * sizeof(u16);
- memset(ibuf, 0, blen);
-
- for (i = 0; i < len; i++) {
- obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG;
- xmit->tail = (xmit->tail + 1) &
- (UART_XMIT_SIZE - 1);
- }
-
- /* Fail to send msg to console is not very critical */
- ret = max3110_write_then_read(max, obuf, ibuf, blen, 0);
- if (ret)
- pr_warning(PR_FMT "%s(): get err msg %d\n",
- __func__, ret);
-
- for (i = 0, j = 0; i < len; i++) {
- if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
- valid_str[j++] = ibuf[i] & 0xff;
- }
-
- if (j)
- receive_chars(max, valid_str, j);
-
- max->port.icount.tx += len;
- left -= len;
- }
- }
-
- kfree(buf);
-}
-
-static void transmit_char(struct uart_max3110 *max)
-{
- struct uart_port *port = &max->port;
- struct circ_buf *xmit = &port->state->xmit;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port))
- return;
-
- send_circ_buf(max, xmit);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- serial_m3110_stop_tx(port);
-}
-
-/*
- * This will be called by uart_write() and tty_write, can't
- * go to sleep
- */
-static void serial_m3110_start_tx(struct uart_port *port)
-{
- struct uart_max3110 *max =
- container_of(port, struct uart_max3110, port);
-
- if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags))
- wake_up_process(max->main_thread);
-}
-
-static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len)
-{
- struct uart_port *port = &max->port;
- struct tty_struct *tty;
- int usable;
-
- /* If uart is not opened, just return */
- if (!port->state)
- return;
-
- tty = port->state->port.tty;
- if (!tty)
- return;
-
- while (len) {
- usable = tty_buffer_request_room(tty, len);
- if (usable) {
- tty_insert_flip_string(tty, str, usable);
- str += usable;
- port->icount.rx += usable;
- }
- len -= usable;
- }
- tty_flip_buffer_push(tty);
-}
-
-/*
- * This routine will be used in read_thread or RX IRQ handling,
- * it will first do one round buffer read(8 words), if there is some
- * valid RX data, will try to read 5 more rounds till all data
- * is read out.
- *
- * Use stack space as data buffer to save some system load, and chose
- * 504 Btyes as a threadhold to do a bulk push to upper tty layer when
- * receiving bulk data, a much bigger buffer may cause stack overflow
- */
-static void max3110_con_receive(struct uart_max3110 *max)
-{
- int loop = 1, num, total = 0;
- u8 recv_buf[512], *pbuf;
-
- pbuf = recv_buf;
- do {
- num = max3110_read_multi(max, pbuf);
-
- if (num) {
- loop = 5;
- pbuf += num;
- total += num;
-
- if (total >= 504) {
- receive_chars(max, recv_buf, total);
- pbuf = recv_buf;
- total = 0;
- }
- }
- } while (--loop);
-
- if (total)
- receive_chars(max, recv_buf, total);
-}
-
-static int max3110_main_thread(void *_max)
-{
- struct uart_max3110 *max = _max;
- wait_queue_head_t *wq = &max->wq;
- int ret = 0;
- struct circ_buf *xmit = &max->con_xmit;
-
- init_waitqueue_head(wq);
- pr_info(PR_FMT "start main thread\n");
-
- do {
- wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop());
-
- mutex_lock(&max->thread_mutex);
-
- if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
- max3110_con_receive(max);
-
- /* first handle console output */
- if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
- send_circ_buf(max, xmit);
-
- /* handle uart output */
- if (test_and_clear_bit(UART_TX_NEEDED, &max->uart_flags))
- transmit_char(max);
-
- mutex_unlock(&max->thread_mutex);
-
- } while (!kthread_should_stop());
-
- return ret;
-}
-
-static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
-{
- struct uart_max3110 *max = dev_id;
-
- /* max3110's irq is a falling edge, not level triggered,
- * so no need to disable the irq */
- if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags))
- wake_up_process(max->main_thread);
-
- return IRQ_HANDLED;
-}
-
-/* if don't use RX IRQ, then need a thread to polling read */
-static int max3110_read_thread(void *_max)
-{
- struct uart_max3110 *max = _max;
-
- pr_info(PR_FMT "start read thread\n");
- do {
- /*
- * If can't acquire the mutex, it means the main thread
- * is running which will also perform the rx job
- */
- if (mutex_trylock(&max->thread_mutex)) {
- max3110_con_receive(max);
- mutex_unlock(&max->thread_mutex);
- }
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 20);
- } while (!kthread_should_stop());
-
- return 0;
-}
-
-static int serial_m3110_startup(struct uart_port *port)
-{
- struct uart_max3110 *max =
- container_of(port, struct uart_max3110, port);
- u16 config = 0;
- int ret = 0;
-
- if (port->line != 0) {
- pr_err(PR_FMT "uart port startup failed\n");
- return -1;
- }
-
- /* Disable all IRQ and config it to 115200, 8n1 */
- config = WC_TAG | WC_FIFO_ENABLE
- | WC_1_STOPBITS
- | WC_8BIT_WORD
- | WC_BAUD_DR2;
-
- /* as we use thread to handle tx/rx, need set low latency */
- port->state->port.tty->low_latency = 1;
-
- if (max->irq) {
- max->read_thread = NULL;
- ret = request_irq(max->irq, serial_m3110_irq,
- IRQ_TYPE_EDGE_FALLING, "max3110", max);
- if (ret) {
- max->irq = 0;
- pr_err(PR_FMT "unable to allocate IRQ, polling\n");
- } else {
- /* Enable RX IRQ only */
- config |= WC_RXA_IRQ_ENABLE;
- }
- }
-
- if (max->irq == 0) {
- /* If IRQ is disabled, start a read thread for input data */
- max->read_thread =
- kthread_run(max3110_read_thread, max, "max3110_read");
- if (IS_ERR(max->read_thread)) {
- ret = PTR_ERR(max->read_thread);
- max->read_thread = NULL;
- pr_err(PR_FMT "Can't create read thread!\n");
- return ret;
- }
- }
-
- ret = max3110_out(max, config);
- if (ret) {
- if (max->irq)
- free_irq(max->irq, max);
- if (max->read_thread)
- kthread_stop(max->read_thread);
- max->read_thread = NULL;
- return ret;
- }
-
- max->cur_conf = config;
- return 0;
-}
-
-static void serial_m3110_shutdown(struct uart_port *port)
-{
- struct uart_max3110 *max =
- container_of(port, struct uart_max3110, port);
- u16 config;
-
- if (max->read_thread) {
- kthread_stop(max->read_thread);
- max->read_thread = NULL;
- }
-
- if (max->irq)
- free_irq(max->irq, max);
-
- /* Disable interrupts from this port */
- config = WC_TAG | WC_SW_SHDI;
- max3110_out(max, config);
-}
-
-static void serial_m3110_release_port(struct uart_port *port)
-{
-}
-
-static int serial_m3110_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void serial_m3110_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_MAX3100;
-}
-
-static int
-serial_m3110_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- /* we don't want the core code to modify any port params */
- return -EINVAL;
-}
-
-
-static const char *serial_m3110_type(struct uart_port *port)
-{
- struct uart_max3110 *max =
- container_of(port, struct uart_max3110, port);
- return max->name;
-}
-
-static void
-serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_max3110 *max =
- container_of(port, struct uart_max3110, port);
- unsigned char cval;
- unsigned int baud, parity = 0;
- int clk_div = -1;
- u16 new_conf = max->cur_conf;
-
- switch (termios->c_cflag & CSIZE) {
- case CS7:
- cval = UART_LCR_WLEN7;
- new_conf |= WC_7BIT_WORD;
- break;
- default:
- /* We only support CS7 & CS8 */
- termios->c_cflag &= ~CSIZE;
- termios->c_cflag |= CS8;
- case CS8:
- cval = UART_LCR_WLEN8;
- new_conf |= WC_8BIT_WORD;
- break;
- }
-
- baud = uart_get_baud_rate(port, termios, old, 0, 230400);
-
- /* First calc the div for 1.8MHZ clock case */
- switch (baud) {
- case 300:
- clk_div = WC_BAUD_DR384;
- break;
- case 600:
- clk_div = WC_BAUD_DR192;
- break;
- case 1200:
- clk_div = WC_BAUD_DR96;
- break;
- case 2400:
- clk_div = WC_BAUD_DR48;
- break;
- case 4800:
- clk_div = WC_BAUD_DR24;
- break;
- case 9600:
- clk_div = WC_BAUD_DR12;
- break;
- case 19200:
- clk_div = WC_BAUD_DR6;
- break;
- case 38400:
- clk_div = WC_BAUD_DR3;
- break;
- case 57600:
- clk_div = WC_BAUD_DR2;
- break;
- case 115200:
- clk_div = WC_BAUD_DR1;
- break;
- case 230400:
- if (max->clock & MAX3110_HIGH_CLK)
- break;
- default:
- /* Pick the previous baud rate */
- baud = max->baud;
- clk_div = max->cur_conf & WC_BAUD_DIV_MASK;
- tty_termios_encode_baud_rate(termios, baud, baud);
- }
-
- if (max->clock & MAX3110_HIGH_CLK) {
- clk_div += 1;
- /* High clk version max3110 doesn't support B300 */
- if (baud == 300) {
- baud = 600;
- clk_div = WC_BAUD_DR384;
- }
- if (baud == 230400)
- clk_div = WC_BAUD_DR1;
- tty_termios_encode_baud_rate(termios, baud, baud);
- }
-
- new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div;
-
- if (unlikely(termios->c_cflag & CMSPAR))
- termios->c_cflag &= ~CMSPAR;
-
- if (termios->c_cflag & CSTOPB)
- new_conf |= WC_2_STOPBITS;
- else
- new_conf &= ~WC_2_STOPBITS;
-
- if (termios->c_cflag & PARENB) {
- new_conf |= WC_PARITY_ENABLE;
- parity |= UART_LCR_PARITY;
- } else
- new_conf &= ~WC_PARITY_ENABLE;
-
- if (!(termios->c_cflag & PARODD))
- parity |= UART_LCR_EPAR;
- max->parity = parity;
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- new_conf |= WC_TAG;
- if (new_conf != max->cur_conf) {
- if (!max3110_out(max, new_conf)) {
- max->cur_conf = new_conf;
- max->baud = baud;
- }
- }
-}
-
-/* Don't handle hw handshaking */
-static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
-{
- return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
-}
-
-static void serial_m3110_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-static void serial_m3110_break_ctl(struct uart_port *port, int break_state)
-{
-}
-
-static void serial_m3110_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
-}
-
-static void serial_m3110_enable_ms(struct uart_port *port)
-{
-}
-
-struct uart_ops serial_m3110_ops = {
- .tx_empty = serial_m3110_tx_empty,
- .set_mctrl = serial_m3110_set_mctrl,
- .get_mctrl = serial_m3110_get_mctrl,
- .stop_tx = serial_m3110_stop_tx,
- .start_tx = serial_m3110_start_tx,
- .stop_rx = serial_m3110_stop_rx,
- .enable_ms = serial_m3110_enable_ms,
- .break_ctl = serial_m3110_break_ctl,
- .startup = serial_m3110_startup,
- .shutdown = serial_m3110_shutdown,
- .set_termios = serial_m3110_set_termios,
- .pm = serial_m3110_pm,
- .type = serial_m3110_type,
- .release_port = serial_m3110_release_port,
- .request_port = serial_m3110_request_port,
- .config_port = serial_m3110_config_port,
- .verify_port = serial_m3110_verify_port,
-};
-
-static struct uart_driver serial_m3110_reg = {
- .owner = THIS_MODULE,
- .driver_name = "MRST serial",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = 1,
- .cons = &serial_m3110_console,
-};
-
-#ifdef CONFIG_PM
-static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
-{
- struct uart_max3110 *max = spi_get_drvdata(spi);
-
- disable_irq(max->irq);
- uart_suspend_port(&serial_m3110_reg, &max->port);
- max3110_out(max, max->cur_conf | WC_SW_SHDI);
- return 0;
-}
-
-static int serial_m3110_resume(struct spi_device *spi)
-{
- struct uart_max3110 *max = spi_get_drvdata(spi);
-
- max3110_out(max, max->cur_conf);
- uart_resume_port(&serial_m3110_reg, &max->port);
- enable_irq(max->irq);
- return 0;
-}
-#else
-#define serial_m3110_suspend NULL
-#define serial_m3110_resume NULL
-#endif
-
-static int __devinit serial_m3110_probe(struct spi_device *spi)
-{
- struct uart_max3110 *max;
- void *buffer;
- u16 res;
- int ret = 0;
-
- max = kzalloc(sizeof(*max), GFP_KERNEL);
- if (!max)
- return -ENOMEM;
-
- /* Set spi info */
- spi->bits_per_word = 16;
- max->clock = MAX3110_HIGH_CLK;
-
- spi_setup(spi);
-
- max->port.type = PORT_MAX3100;
- max->port.fifosize = 2; /* Only have 16b buffer */
- max->port.ops = &serial_m3110_ops;
- max->port.line = 0;
- max->port.dev = &spi->dev;
- max->port.uartclk = 115200;
-
- max->spi = spi;
- strcpy(max->name, spi->modalias);
- max->irq = (u16)spi->irq;
-
- mutex_init(&max->thread_mutex);
-
- max->word_7bits = 0;
- max->parity = 0;
- max->baud = 0;
-
- max->cur_conf = 0;
- max->uart_flags = 0;
-
- /* Check if reading configuration register returns something sane */
-
- res = RC_TAG;
- ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0);
- if (ret < 0 || res == 0 || res == 0xffff) {
- printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)",
- res);
- ret = -ENODEV;
- goto err_get_page;
- }
-
- buffer = (void *)__get_free_page(GFP_KERNEL);
- if (!buffer) {
- ret = -ENOMEM;
- goto err_get_page;
- }
- max->con_xmit.buf = buffer;
- max->con_xmit.head = 0;
- max->con_xmit.tail = 0;
-
- max->main_thread = kthread_run(max3110_main_thread,
- max, "max3110_main");
- if (IS_ERR(max->main_thread)) {
- ret = PTR_ERR(max->main_thread);
- goto err_kthread;
- }
-
- spi_set_drvdata(spi, max);
- pmax = max;
-
- /* Give membase a psudo value to pass serial_core's check */
- max->port.membase = (void *)0xff110000;
- uart_add_one_port(&serial_m3110_reg, &max->port);
-
- return 0;
-
-err_kthread:
- free_page((unsigned long)buffer);
-err_get_page:
- kfree(max);
- return ret;
-}
-
-static int __devexit serial_m3110_remove(struct spi_device *dev)
-{
- struct uart_max3110 *max = spi_get_drvdata(dev);
-
- if (!max)
- return 0;
-
- uart_remove_one_port(&serial_m3110_reg, &max->port);
-
- free_page((unsigned long)max->con_xmit.buf);
-
- if (max->main_thread)
- kthread_stop(max->main_thread);
-
- kfree(max);
- return 0;
-}
-
-static struct spi_driver uart_max3110_driver = {
- .driver = {
- .name = "spi_max3111",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
- .probe = serial_m3110_probe,
- .remove = __devexit_p(serial_m3110_remove),
- .suspend = serial_m3110_suspend,
- .resume = serial_m3110_resume,
-};
-
-static int __init serial_m3110_init(void)
-{
- int ret = 0;
-
- ret = uart_register_driver(&serial_m3110_reg);
- if (ret)
- return ret;
-
- ret = spi_register_driver(&uart_max3110_driver);
- if (ret)
- uart_unregister_driver(&serial_m3110_reg);
-
- return ret;
-}
-
-static void __exit serial_m3110_exit(void)
-{
- spi_unregister_driver(&uart_max3110_driver);
- uart_unregister_driver(&serial_m3110_reg);
-}
-
-module_init(serial_m3110_init);
-module_exit(serial_m3110_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("max3110-uart");
diff --git a/drivers/serial/mrst_max3110.h b/drivers/serial/mrst_max3110.h
deleted file mode 100644
index d1ef43af397c..000000000000
--- a/drivers/serial/mrst_max3110.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef _MRST_MAX3110_H
-#define _MRST_MAX3110_H
-
-#define MAX3110_HIGH_CLK 0x1 /* 3.6864 MHZ */
-#define MAX3110_LOW_CLK 0x0 /* 1.8432 MHZ */
-
-/* status bits for all 4 MAX3110 operate modes */
-#define MAX3110_READ_DATA_AVAILABLE (1 << 15)
-#define MAX3110_WRITE_BUF_EMPTY (1 << 14)
-
-#define WC_TAG (3 << 14)
-#define RC_TAG (1 << 14)
-#define WD_TAG (2 << 14)
-#define RD_TAG (0 << 14)
-
-/* bits def for write configuration */
-#define WC_FIFO_ENABLE_MASK (1 << 13)
-#define WC_FIFO_ENABLE (0 << 13)
-
-#define WC_SW_SHDI (1 << 12)
-
-#define WC_IRQ_MASK (0xF << 8)
-#define WC_TXE_IRQ_ENABLE (1 << 11) /* TX empty irq */
-#define WC_RXA_IRQ_ENABLE (1 << 10) /* RX availabe irq */
-#define WC_PAR_HIGH_IRQ_ENABLE (1 << 9)
-#define WC_REC_ACT_IRQ_ENABLE (1 << 8)
-
-#define WC_IRDA_ENABLE (1 << 7)
-
-#define WC_STOPBITS_MASK (1 << 6)
-#define WC_2_STOPBITS (1 << 6)
-#define WC_1_STOPBITS (0 << 6)
-
-#define WC_PARITY_ENABLE_MASK (1 << 5)
-#define WC_PARITY_ENABLE (1 << 5)
-
-#define WC_WORDLEN_MASK (1 << 4)
-#define WC_7BIT_WORD (1 << 4)
-#define WC_8BIT_WORD (0 << 4)
-
-#define WC_BAUD_DIV_MASK (0xF)
-#define WC_BAUD_DR1 (0x0)
-#define WC_BAUD_DR2 (0x1)
-#define WC_BAUD_DR4 (0x2)
-#define WC_BAUD_DR8 (0x3)
-#define WC_BAUD_DR16 (0x4)
-#define WC_BAUD_DR32 (0x5)
-#define WC_BAUD_DR64 (0x6)
-#define WC_BAUD_DR128 (0x7)
-#define WC_BAUD_DR3 (0x8)
-#define WC_BAUD_DR6 (0x9)
-#define WC_BAUD_DR12 (0xA)
-#define WC_BAUD_DR24 (0xB)
-#define WC_BAUD_DR48 (0xC)
-#define WC_BAUD_DR96 (0xD)
-#define WC_BAUD_DR192 (0xE)
-#define WC_BAUD_DR384 (0xF)
-
-#define M3110_RX_FIFO_DEPTH 8
-#endif
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c
deleted file mode 100644
index 8e43a7b69e64..000000000000
--- a/drivers/serial/msm_serial.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * drivers/serial/msm_serial.c - driver for msm7k serial device and console
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Robert Love <rlove@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#if defined(CONFIG_SERIAL_MSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-# define SUPPORT_SYSRQ
-#endif
-
-#include <linux/hrtimer.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-#include "msm_serial.h"
-
-struct msm_port {
- struct uart_port uart;
- char name[16];
- struct clk *clk;
- unsigned int imr;
-};
-
-static void msm_stop_tx(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- msm_port->imr &= ~UART_IMR_TXLEV;
- msm_write(port, msm_port->imr, UART_IMR);
-}
-
-static void msm_start_tx(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- msm_port->imr |= UART_IMR_TXLEV;
- msm_write(port, msm_port->imr, UART_IMR);
-}
-
-static void msm_stop_rx(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
- msm_write(port, msm_port->imr, UART_IMR);
-}
-
-static void msm_enable_ms(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- msm_port->imr |= UART_IMR_DELTA_CTS;
- msm_write(port, msm_port->imr, UART_IMR);
-}
-
-static void handle_rx(struct uart_port *port)
-{
- struct tty_struct *tty = port->state->port.tty;
- unsigned int sr;
-
- /*
- * Handle overrun. My understanding of the hardware is that overrun
- * is not tied to the RX buffer, so we handle the case out of band.
- */
- if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) {
- port->icount.overrun++;
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
- }
-
- /* and now the main RX loop */
- while ((sr = msm_read(port, UART_SR)) & UART_SR_RX_READY) {
- unsigned int c;
- char flag = TTY_NORMAL;
-
- c = msm_read(port, UART_RF);
-
- if (sr & UART_SR_RX_BREAK) {
- port->icount.brk++;
- if (uart_handle_break(port))
- continue;
- } else if (sr & UART_SR_PAR_FRAME_ERR) {
- port->icount.frame++;
- } else {
- port->icount.rx++;
- }
-
- /* Mask conditions we're ignorning. */
- sr &= port->read_status_mask;
-
- if (sr & UART_SR_RX_BREAK) {
- flag = TTY_BREAK;
- } else if (sr & UART_SR_PAR_FRAME_ERR) {
- flag = TTY_FRAME;
- }
-
- if (!uart_handle_sysrq_char(port, c))
- tty_insert_flip_char(tty, c, flag);
- }
-
- tty_flip_buffer_push(tty);
-}
-
-static void handle_tx(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
- struct msm_port *msm_port = UART_TO_MSM(port);
- int sent_tx;
-
- if (port->x_char) {
- msm_write(port, port->x_char, UART_TF);
- port->icount.tx++;
- port->x_char = 0;
- }
-
- while (msm_read(port, UART_SR) & UART_SR_TX_READY) {
- if (uart_circ_empty(xmit)) {
- /* disable tx interrupts */
- msm_port->imr &= ~UART_IMR_TXLEV;
- msm_write(port, msm_port->imr, UART_IMR);
- break;
- }
-
- msm_write(port, xmit->buf[xmit->tail], UART_TF);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- sent_tx = 1;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-}
-
-static void handle_delta_cts(struct uart_port *port)
-{
- msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
- port->icount.cts++;
- wake_up_interruptible(&port->state->port.delta_msr_wait);
-}
-
-static irqreturn_t msm_irq(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- struct msm_port *msm_port = UART_TO_MSM(port);
- unsigned int misr;
-
- spin_lock(&port->lock);
- misr = msm_read(port, UART_MISR);
- msm_write(port, 0, UART_IMR); /* disable interrupt */
-
- if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE))
- handle_rx(port);
- if (misr & UART_IMR_TXLEV)
- handle_tx(port);
- if (misr & UART_IMR_DELTA_CTS)
- handle_delta_cts(port);
-
- msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */
- spin_unlock(&port->lock);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int msm_tx_empty(struct uart_port *port)
-{
- return (msm_read(port, UART_SR) & UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int msm_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS;
-}
-
-static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- unsigned int mr;
-
- mr = msm_read(port, UART_MR1);
-
- if (!(mctrl & TIOCM_RTS)) {
- mr &= ~UART_MR1_RX_RDY_CTL;
- msm_write(port, mr, UART_MR1);
- msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR);
- } else {
- mr |= UART_MR1_RX_RDY_CTL;
- msm_write(port, mr, UART_MR1);
- }
-}
-
-static void msm_break_ctl(struct uart_port *port, int break_ctl)
-{
- if (break_ctl)
- msm_write(port, UART_CR_CMD_START_BREAK, UART_CR);
- else
- msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR);
-}
-
-static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
-{
- unsigned int baud_code, rxstale, watermark;
-
- switch (baud) {
- case 300:
- baud_code = UART_CSR_300;
- rxstale = 1;
- break;
- case 600:
- baud_code = UART_CSR_600;
- rxstale = 1;
- break;
- case 1200:
- baud_code = UART_CSR_1200;
- rxstale = 1;
- break;
- case 2400:
- baud_code = UART_CSR_2400;
- rxstale = 1;
- break;
- case 4800:
- baud_code = UART_CSR_4800;
- rxstale = 1;
- break;
- case 9600:
- baud_code = UART_CSR_9600;
- rxstale = 2;
- break;
- case 14400:
- baud_code = UART_CSR_14400;
- rxstale = 3;
- break;
- case 19200:
- baud_code = UART_CSR_19200;
- rxstale = 4;
- break;
- case 28800:
- baud_code = UART_CSR_28800;
- rxstale = 6;
- break;
- case 38400:
- baud_code = UART_CSR_38400;
- rxstale = 8;
- break;
- case 57600:
- baud_code = UART_CSR_57600;
- rxstale = 16;
- break;
- case 115200:
- default:
- baud_code = UART_CSR_115200;
- baud = 115200;
- rxstale = 31;
- break;
- }
-
- msm_write(port, baud_code, UART_CSR);
-
- /* RX stale watermark */
- watermark = UART_IPR_STALE_LSB & rxstale;
- watermark |= UART_IPR_RXSTALE_LAST;
- watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
- msm_write(port, watermark, UART_IPR);
-
- /* set RX watermark */
- watermark = (port->fifosize * 3) / 4;
- msm_write(port, watermark, UART_RFWR);
-
- /* set TX watermark */
- msm_write(port, 10, UART_TFWR);
-
- return baud;
-}
-
-static void msm_reset(struct uart_port *port)
-{
- /* reset everything */
- msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
- msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
- msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
- msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
- msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
- msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
-}
-
-static void msm_init_clock(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- clk_enable(msm_port->clk);
- msm_serial_set_mnd_regs(port);
-}
-
-static int msm_startup(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
- unsigned int data, rfr_level;
- int ret;
-
- snprintf(msm_port->name, sizeof(msm_port->name),
- "msm_serial%d", port->line);
-
- ret = request_irq(port->irq, msm_irq, IRQF_TRIGGER_HIGH,
- msm_port->name, port);
- if (unlikely(ret))
- return ret;
-
- msm_init_clock(port);
-
- if (likely(port->fifosize > 12))
- rfr_level = port->fifosize - 12;
- else
- rfr_level = port->fifosize;
-
- /* set automatic RFR level */
- data = msm_read(port, UART_MR1);
- data &= ~UART_MR1_AUTO_RFR_LEVEL1;
- data &= ~UART_MR1_AUTO_RFR_LEVEL0;
- data |= UART_MR1_AUTO_RFR_LEVEL1 & (rfr_level << 2);
- data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level;
- msm_write(port, data, UART_MR1);
-
- /* make sure that RXSTALE count is non-zero */
- data = msm_read(port, UART_IPR);
- if (unlikely(!data)) {
- data |= UART_IPR_RXSTALE_LAST;
- data |= UART_IPR_STALE_LSB;
- msm_write(port, data, UART_IPR);
- }
-
- msm_reset(port);
-
- msm_write(port, 0x05, UART_CR); /* enable TX & RX */
-
- /* turn on RX and CTS interrupts */
- msm_port->imr = UART_IMR_RXLEV | UART_IMR_RXSTALE |
- UART_IMR_CURRENT_CTS;
- msm_write(port, msm_port->imr, UART_IMR);
-
- return 0;
-}
-
-static void msm_shutdown(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- msm_port->imr = 0;
- msm_write(port, 0, UART_IMR); /* disable interrupts */
-
- clk_disable(msm_port->clk);
-
- free_irq(port->irq, port);
-}
-
-static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned long flags;
- unsigned int baud, mr;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* calculate and set baud rate */
- baud = uart_get_baud_rate(port, termios, old, 300, 115200);
- baud = msm_set_baud_rate(port, baud);
- if (tty_termios_baud_rate(termios))
- tty_termios_encode_baud_rate(termios, baud, baud);
-
- /* calculate parity */
- mr = msm_read(port, UART_MR2);
- mr &= ~UART_MR2_PARITY_MODE;
- if (termios->c_cflag & PARENB) {
- if (termios->c_cflag & PARODD)
- mr |= UART_MR2_PARITY_MODE_ODD;
- else if (termios->c_cflag & CMSPAR)
- mr |= UART_MR2_PARITY_MODE_SPACE;
- else
- mr |= UART_MR2_PARITY_MODE_EVEN;
- }
-
- /* calculate bits per char */
- mr &= ~UART_MR2_BITS_PER_CHAR;
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- mr |= UART_MR2_BITS_PER_CHAR_5;
- break;
- case CS6:
- mr |= UART_MR2_BITS_PER_CHAR_6;
- break;
- case CS7:
- mr |= UART_MR2_BITS_PER_CHAR_7;
- break;
- case CS8:
- default:
- mr |= UART_MR2_BITS_PER_CHAR_8;
- break;
- }
-
- /* calculate stop bits */
- mr &= ~(UART_MR2_STOP_BIT_LEN_ONE | UART_MR2_STOP_BIT_LEN_TWO);
- if (termios->c_cflag & CSTOPB)
- mr |= UART_MR2_STOP_BIT_LEN_TWO;
- else
- mr |= UART_MR2_STOP_BIT_LEN_ONE;
-
- /* set parity, bits per char, and stop bit */
- msm_write(port, mr, UART_MR2);
-
- /* calculate and set hardware flow control */
- mr = msm_read(port, UART_MR1);
- mr &= ~(UART_MR1_CTS_CTL | UART_MR1_RX_RDY_CTL);
- if (termios->c_cflag & CRTSCTS) {
- mr |= UART_MR1_CTS_CTL;
- mr |= UART_MR1_RX_RDY_CTL;
- }
- msm_write(port, mr, UART_MR1);
-
- /* Configure status bits to ignore based on termio flags. */
- port->read_status_mask = 0;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= UART_SR_PAR_FRAME_ERR;
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= UART_SR_RX_BREAK;
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *msm_type(struct uart_port *port)
-{
- return "MSM";
-}
-
-static void msm_release_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- struct resource *resource;
- resource_size_t size;
-
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(!resource))
- return;
- size = resource->end - resource->start + 1;
-
- release_mem_region(port->mapbase, size);
- iounmap(port->membase);
- port->membase = NULL;
-}
-
-static int msm_request_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- struct resource *resource;
- resource_size_t size;
-
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(!resource))
- return -ENXIO;
- size = resource->end - resource->start + 1;
-
- if (unlikely(!request_mem_region(port->mapbase, size, "msm_serial")))
- return -EBUSY;
-
- port->membase = ioremap(port->mapbase, size);
- if (!port->membase) {
- release_mem_region(port->mapbase, size);
- return -EBUSY;
- }
-
- return 0;
-}
-
-static void msm_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_MSM;
- msm_request_port(port);
- }
-}
-
-static int msm_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_MSM))
- return -EINVAL;
- if (unlikely(port->irq != ser->irq))
- return -EINVAL;
- return 0;
-}
-
-static void msm_power(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- switch (state) {
- case 0:
- clk_enable(msm_port->clk);
- break;
- case 3:
- clk_disable(msm_port->clk);
- break;
- default:
- printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state);
- }
-}
-
-static struct uart_ops msm_uart_pops = {
- .tx_empty = msm_tx_empty,
- .set_mctrl = msm_set_mctrl,
- .get_mctrl = msm_get_mctrl,
- .stop_tx = msm_stop_tx,
- .start_tx = msm_start_tx,
- .stop_rx = msm_stop_rx,
- .enable_ms = msm_enable_ms,
- .break_ctl = msm_break_ctl,
- .startup = msm_startup,
- .shutdown = msm_shutdown,
- .set_termios = msm_set_termios,
- .type = msm_type,
- .release_port = msm_release_port,
- .request_port = msm_request_port,
- .config_port = msm_config_port,
- .verify_port = msm_verify_port,
- .pm = msm_power,
-};
-
-static struct msm_port msm_uart_ports[] = {
- {
- .uart = {
- .iotype = UPIO_MEM,
- .ops = &msm_uart_pops,
- .flags = UPF_BOOT_AUTOCONF,
- .fifosize = 512,
- .line = 0,
- },
- },
- {
- .uart = {
- .iotype = UPIO_MEM,
- .ops = &msm_uart_pops,
- .flags = UPF_BOOT_AUTOCONF,
- .fifosize = 512,
- .line = 1,
- },
- },
- {
- .uart = {
- .iotype = UPIO_MEM,
- .ops = &msm_uart_pops,
- .flags = UPF_BOOT_AUTOCONF,
- .fifosize = 64,
- .line = 2,
- },
- },
-};
-
-#define UART_NR ARRAY_SIZE(msm_uart_ports)
-
-static inline struct uart_port *get_port_from_line(unsigned int line)
-{
- return &msm_uart_ports[line].uart;
-}
-
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-
-static void msm_console_putchar(struct uart_port *port, int c)
-{
- while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
- ;
- msm_write(port, c, UART_TF);
-}
-
-static void msm_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_port *port;
- struct msm_port *msm_port;
-
- BUG_ON(co->index < 0 || co->index >= UART_NR);
-
- port = get_port_from_line(co->index);
- msm_port = UART_TO_MSM(port);
-
- spin_lock(&port->lock);
- uart_console_write(port, s, count, msm_console_putchar);
- spin_unlock(&port->lock);
-}
-
-static int __init msm_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud, flow, bits, parity;
-
- if (unlikely(co->index >= UART_NR || co->index < 0))
- return -ENXIO;
-
- port = get_port_from_line(co->index);
-
- if (unlikely(!port->membase))
- return -ENXIO;
-
- port->cons = co;
-
- msm_init_clock(port);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- bits = 8;
- parity = 'n';
- flow = 'n';
- msm_write(port, UART_MR2_BITS_PER_CHAR_8 | UART_MR2_STOP_BIT_LEN_ONE,
- UART_MR2); /* 8N1 */
-
- if (baud < 300 || baud > 115200)
- baud = 115200;
- msm_set_baud_rate(port, baud);
-
- msm_reset(port);
-
- printk(KERN_INFO "msm_serial: console setup on port #%d\n", port->line);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver msm_uart_driver;
-
-static struct console msm_console = {
- .name = "ttyMSM",
- .write = msm_console_write,
- .device = uart_console_device,
- .setup = msm_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &msm_uart_driver,
-};
-
-#define MSM_CONSOLE (&msm_console)
-
-#else
-#define MSM_CONSOLE NULL
-#endif
-
-static struct uart_driver msm_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "msm_serial",
- .dev_name = "ttyMSM",
- .nr = UART_NR,
- .cons = MSM_CONSOLE,
-};
-
-static int __init msm_serial_probe(struct platform_device *pdev)
-{
- struct msm_port *msm_port;
- struct resource *resource;
- struct uart_port *port;
- int irq;
-
- if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
- return -ENXIO;
-
- printk(KERN_INFO "msm_serial: detected port #%d\n", pdev->id);
-
- port = get_port_from_line(pdev->id);
- port->dev = &pdev->dev;
- msm_port = UART_TO_MSM(port);
-
- msm_port->clk = clk_get(&pdev->dev, "uart_clk");
- if (IS_ERR(msm_port->clk))
- return PTR_ERR(msm_port->clk);
- port->uartclk = clk_get_rate(msm_port->clk);
- printk(KERN_INFO "uartclk = %d\n", port->uartclk);
-
-
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(!resource))
- return -ENXIO;
- port->mapbase = resource->start;
-
- irq = platform_get_irq(pdev, 0);
- if (unlikely(irq < 0))
- return -ENXIO;
- port->irq = irq;
-
- platform_set_drvdata(pdev, port);
-
- return uart_add_one_port(&msm_uart_driver, port);
-}
-
-static int __devexit msm_serial_remove(struct platform_device *pdev)
-{
- struct msm_port *msm_port = platform_get_drvdata(pdev);
-
- clk_put(msm_port->clk);
-
- return 0;
-}
-
-static struct platform_driver msm_platform_driver = {
- .remove = msm_serial_remove,
- .driver = {
- .name = "msm_serial",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init msm_serial_init(void)
-{
- int ret;
-
- ret = uart_register_driver(&msm_uart_driver);
- if (unlikely(ret))
- return ret;
-
- ret = platform_driver_probe(&msm_platform_driver, msm_serial_probe);
- if (unlikely(ret))
- uart_unregister_driver(&msm_uart_driver);
-
- printk(KERN_INFO "msm_serial: driver initialized\n");
-
- return ret;
-}
-
-static void __exit msm_serial_exit(void)
-{
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
- unregister_console(&msm_console);
-#endif
- platform_driver_unregister(&msm_platform_driver);
- uart_unregister_driver(&msm_uart_driver);
-}
-
-module_init(msm_serial_init);
-module_exit(msm_serial_exit);
-
-MODULE_AUTHOR("Robert Love <rlove@google.com>");
-MODULE_DESCRIPTION("Driver for msm7x serial device");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/msm_serial.h b/drivers/serial/msm_serial.h
deleted file mode 100644
index f6ca9ca79e98..000000000000
--- a/drivers/serial/msm_serial.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * drivers/serial/msm_serial.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Robert Love <rlove@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#ifndef __DRIVERS_SERIAL_MSM_SERIAL_H
-#define __DRIVERS_SERIAL_MSM_SERIAL_H
-
-#define UART_MR1 0x0000
-
-#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
-#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
-#define UART_MR1_RX_RDY_CTL (1 << 7)
-#define UART_MR1_CTS_CTL (1 << 6)
-
-#define UART_MR2 0x0004
-#define UART_MR2_ERROR_MODE (1 << 6)
-#define UART_MR2_BITS_PER_CHAR 0x30
-#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
-#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
-#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
-#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
-#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
-#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
-#define UART_MR2_PARITY_MODE_NONE 0x0
-#define UART_MR2_PARITY_MODE_ODD 0x1
-#define UART_MR2_PARITY_MODE_EVEN 0x2
-#define UART_MR2_PARITY_MODE_SPACE 0x3
-#define UART_MR2_PARITY_MODE 0x3
-
-#define UART_CSR 0x0008
-#define UART_CSR_115200 0xFF
-#define UART_CSR_57600 0xEE
-#define UART_CSR_38400 0xDD
-#define UART_CSR_28800 0xCC
-#define UART_CSR_19200 0xBB
-#define UART_CSR_14400 0xAA
-#define UART_CSR_9600 0x99
-#define UART_CSR_4800 0x77
-#define UART_CSR_2400 0x55
-#define UART_CSR_1200 0x44
-#define UART_CSR_600 0x33
-#define UART_CSR_300 0x22
-
-#define UART_TF 0x000C
-
-#define UART_CR 0x0010
-#define UART_CR_CMD_NULL (0 << 4)
-#define UART_CR_CMD_RESET_RX (1 << 4)
-#define UART_CR_CMD_RESET_TX (2 << 4)
-#define UART_CR_CMD_RESET_ERR (3 << 4)
-#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
-#define UART_CR_CMD_START_BREAK (5 << 4)
-#define UART_CR_CMD_STOP_BREAK (6 << 4)
-#define UART_CR_CMD_RESET_CTS (7 << 4)
-#define UART_CR_CMD_PACKET_MODE (9 << 4)
-#define UART_CR_CMD_MODE_RESET (12 << 4)
-#define UART_CR_CMD_SET_RFR (13 << 4)
-#define UART_CR_CMD_RESET_RFR (14 << 4)
-#define UART_CR_TX_DISABLE (1 << 3)
-#define UART_CR_TX_ENABLE (1 << 3)
-#define UART_CR_RX_DISABLE (1 << 3)
-#define UART_CR_RX_ENABLE (1 << 3)
-
-#define UART_IMR 0x0014
-#define UART_IMR_TXLEV (1 << 0)
-#define UART_IMR_RXSTALE (1 << 3)
-#define UART_IMR_RXLEV (1 << 4)
-#define UART_IMR_DELTA_CTS (1 << 5)
-#define UART_IMR_CURRENT_CTS (1 << 6)
-
-#define UART_IPR_RXSTALE_LAST 0x20
-#define UART_IPR_STALE_LSB 0x1F
-#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
-
-#define UART_IPR 0x0018
-#define UART_TFWR 0x001C
-#define UART_RFWR 0x0020
-#define UART_HCR 0x0024
-
-#define UART_MREG 0x0028
-#define UART_NREG 0x002C
-#define UART_DREG 0x0030
-#define UART_MNDREG 0x0034
-#define UART_IRDA 0x0038
-#define UART_MISR_MODE 0x0040
-#define UART_MISR_RESET 0x0044
-#define UART_MISR_EXPORT 0x0048
-#define UART_MISR_VAL 0x004C
-#define UART_TEST_CTRL 0x0050
-
-#define UART_SR 0x0008
-#define UART_SR_HUNT_CHAR (1 << 7)
-#define UART_SR_RX_BREAK (1 << 6)
-#define UART_SR_PAR_FRAME_ERR (1 << 5)
-#define UART_SR_OVERRUN (1 << 4)
-#define UART_SR_TX_EMPTY (1 << 3)
-#define UART_SR_TX_READY (1 << 2)
-#define UART_SR_RX_FULL (1 << 1)
-#define UART_SR_RX_READY (1 << 0)
-
-#define UART_RF 0x000C
-#define UART_MISR 0x0010
-#define UART_ISR 0x0014
-
-#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
-
-static inline
-void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
-{
- __raw_writel(val, port->membase + off);
-}
-
-static inline
-unsigned int msm_read(struct uart_port *port, unsigned int off)
-{
- return __raw_readl(port->membase + off);
-}
-
-/*
- * Setup the MND registers to use the TCXO clock.
- */
-static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
-{
- msm_write(port, 0x06, UART_MREG);
- msm_write(port, 0xF1, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x1A, UART_MNDREG);
-}
-
-/*
- * Setup the MND registers to use the TCXO clock divided by 4.
- */
-static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
-{
- msm_write(port, 0x18, UART_MREG);
- msm_write(port, 0xF6, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x0A, UART_MNDREG);
-}
-
-static inline
-void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
-{
- if (port->uartclk == 19200000)
- msm_serial_set_mnd_regs_tcxo(port);
- else
- msm_serial_set_mnd_regs_tcxoby4(port);
-}
-
-/*
- * TROUT has a specific defect that makes it report it's uartclk
- * as 19.2Mhz (TCXO) when it's actually 4.8Mhz (TCXO/4). This special
- * cases TROUT to use the right clock.
- */
-#ifdef CONFIG_MACH_TROUT
-#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_tcxoby4
-#else
-#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
-#endif
-
-#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
deleted file mode 100644
index 9711e06a8374..000000000000
--- a/drivers/serial/mux.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
-** mux.c:
-** serial driver for the Mux console found in some PA-RISC servers.
-**
-** (c) Copyright 2002 Ryan Bradetich
-** (c) Copyright 2002 Hewlett-Packard Company
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This Driver currently only supports the console (port 0) on the MUX.
-** Additional work will be needed on this driver to enable the full
-** functionality of the MUX.
-**
-*/
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/delay.h> /* for udelay */
-#include <linux/device.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/parisc-device.h>
-
-#ifdef CONFIG_MAGIC_SYSRQ
-#include <linux/sysrq.h>
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#define MUX_OFFSET 0x800
-#define MUX_LINE_OFFSET 0x80
-
-#define MUX_FIFO_SIZE 255
-#define MUX_POLL_DELAY (30 * HZ / 1000)
-
-#define IO_DATA_REG_OFFSET 0x3c
-#define IO_DCOUNT_REG_OFFSET 0x40
-
-#define MUX_EOFIFO(status) ((status & 0xF000) == 0xF000)
-#define MUX_STATUS(status) ((status & 0xF000) == 0x8000)
-#define MUX_BREAK(status) ((status & 0xF000) == 0x2000)
-
-#define MUX_NR 256
-static unsigned int port_cnt __read_mostly;
-struct mux_port {
- struct uart_port port;
- int enabled;
-};
-static struct mux_port mux_ports[MUX_NR];
-
-static struct uart_driver mux_driver = {
- .owner = THIS_MODULE,
- .driver_name = "ttyB",
- .dev_name = "ttyB",
- .major = MUX_MAJOR,
- .minor = 0,
- .nr = MUX_NR,
-};
-
-static struct timer_list mux_timer;
-
-#define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET)
-#define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET)
-
-/**
- * get_mux_port_count - Get the number of available ports on the Mux.
- * @dev: The parisc device.
- *
- * This function is used to determine the number of ports the Mux
- * supports. The IODC data reports the number of ports the Mux
- * can support, but there are cases where not all the Mux ports
- * are connected. This function can override the IODC and
- * return the true port count.
- */
-static int __init get_mux_port_count(struct parisc_device *dev)
-{
- int status;
- u8 iodc_data[32];
- unsigned long bytecnt;
-
- /* If this is the built-in Mux for the K-Class (Eole CAP/MUX),
- * we only need to allocate resources for 1 port since the
- * other 7 ports are not connected.
- */
- if(dev->id.hversion == 0x15)
- return 1;
-
- status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
- BUG_ON(status != PDC_OK);
-
- /* Return the number of ports specified in the iodc data. */
- return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8;
-}
-
-/**
- * mux_tx_empty - Check if the transmitter fifo is empty.
- * @port: Ptr to the uart_port.
- *
- * This function test if the transmitter fifo for the port
- * described by 'port' is empty. If it is empty, this function
- * should return TIOCSER_TEMT, otherwise return 0.
- */
-static unsigned int mux_tx_empty(struct uart_port *port)
-{
- return UART_GET_FIFO_CNT(port) ? 0 : TIOCSER_TEMT;
-}
-
-/**
- * mux_set_mctrl - Set the current state of the modem control inputs.
- * @ports: Ptr to the uart_port.
- * @mctrl: Modem control bits.
- *
- * The Serial MUX does not support CTS, DCD or DSR so this function
- * is ignored.
- */
-static void mux_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-/**
- * mux_get_mctrl - Returns the current state of modem control inputs.
- * @port: Ptr to the uart_port.
- *
- * The Serial MUX does not support CTS, DCD or DSR so these lines are
- * treated as permanently active.
- */
-static unsigned int mux_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-}
-
-/**
- * mux_stop_tx - Stop transmitting characters.
- * @port: Ptr to the uart_port.
- *
- * The Serial MUX does not support this function.
- */
-static void mux_stop_tx(struct uart_port *port)
-{
-}
-
-/**
- * mux_start_tx - Start transmitting characters.
- * @port: Ptr to the uart_port.
- *
- * The Serial Mux does not support this function.
- */
-static void mux_start_tx(struct uart_port *port)
-{
-}
-
-/**
- * mux_stop_rx - Stop receiving characters.
- * @port: Ptr to the uart_port.
- *
- * The Serial Mux does not support this function.
- */
-static void mux_stop_rx(struct uart_port *port)
-{
-}
-
-/**
- * mux_enable_ms - Enable modum status interrupts.
- * @port: Ptr to the uart_port.
- *
- * The Serial Mux does not support this function.
- */
-static void mux_enable_ms(struct uart_port *port)
-{
-}
-
-/**
- * mux_break_ctl - Control the transmitssion of a break signal.
- * @port: Ptr to the uart_port.
- * @break_state: Raise/Lower the break signal.
- *
- * The Serial Mux does not support this function.
- */
-static void mux_break_ctl(struct uart_port *port, int break_state)
-{
-}
-
-/**
- * mux_write - Write chars to the mux fifo.
- * @port: Ptr to the uart_port.
- *
- * This function writes all the data from the uart buffer to
- * the mux fifo.
- */
-static void mux_write(struct uart_port *port)
-{
- int count;
- struct circ_buf *xmit = &port->state->xmit;
-
- if(port->x_char) {
- UART_PUT_CHAR(port, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
-
- if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- mux_stop_tx(port);
- return;
- }
-
- count = (port->fifosize) - UART_GET_FIFO_CNT(port);
- do {
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if(uart_circ_empty(xmit))
- break;
-
- } while(--count > 0);
-
- while(UART_GET_FIFO_CNT(port))
- udelay(1);
-
- if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- mux_stop_tx(port);
-}
-
-/**
- * mux_read - Read chars from the mux fifo.
- * @port: Ptr to the uart_port.
- *
- * This reads all available data from the mux's fifo and pushes
- * the data to the tty layer.
- */
-static void mux_read(struct uart_port *port)
-{
- int data;
- struct tty_struct *tty = port->state->port.tty;
- __u32 start_count = port->icount.rx;
-
- while(1) {
- data = __raw_readl(port->membase + IO_DATA_REG_OFFSET);
-
- if (MUX_STATUS(data))
- continue;
-
- if (MUX_EOFIFO(data))
- break;
-
- port->icount.rx++;
-
- if (MUX_BREAK(data)) {
- port->icount.brk++;
- if(uart_handle_break(port))
- continue;
- }
-
- if (uart_handle_sysrq_char(port, data & 0xffu))
- continue;
-
- tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
- }
-
- if (start_count != port->icount.rx) {
- tty_flip_buffer_push(tty);
- }
-}
-
-/**
- * mux_startup - Initialize the port.
- * @port: Ptr to the uart_port.
- *
- * Grab any resources needed for this port and start the
- * mux timer.
- */
-static int mux_startup(struct uart_port *port)
-{
- mux_ports[port->line].enabled = 1;
- return 0;
-}
-
-/**
- * mux_shutdown - Disable the port.
- * @port: Ptr to the uart_port.
- *
- * Release any resources needed for the port.
- */
-static void mux_shutdown(struct uart_port *port)
-{
- mux_ports[port->line].enabled = 0;
-}
-
-/**
- * mux_set_termios - Chane port parameters.
- * @port: Ptr to the uart_port.
- * @termios: new termios settings.
- * @old: old termios settings.
- *
- * The Serial Mux does not support this function.
- */
-static void
-mux_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
-}
-
-/**
- * mux_type - Describe the port.
- * @port: Ptr to the uart_port.
- *
- * Return a pointer to a string constant describing the
- * specified port.
- */
-static const char *mux_type(struct uart_port *port)
-{
- return "Mux";
-}
-
-/**
- * mux_release_port - Release memory and IO regions.
- * @port: Ptr to the uart_port.
- *
- * Release any memory and IO region resources currently in use by
- * the port.
- */
-static void mux_release_port(struct uart_port *port)
-{
-}
-
-/**
- * mux_request_port - Request memory and IO regions.
- * @port: Ptr to the uart_port.
- *
- * Request any memory and IO region resources required by the port.
- * If any fail, no resources should be registered when this function
- * returns, and it should return -EBUSY on failure.
- */
-static int mux_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/**
- * mux_config_port - Perform port autoconfiguration.
- * @port: Ptr to the uart_port.
- * @type: Bitmask of required configurations.
- *
- * Perform any autoconfiguration steps for the port. This function is
- * called if the UPF_BOOT_AUTOCONF flag is specified for the port.
- * [Note: This is required for now because of a bug in the Serial core.
- * rmk has already submitted a patch to linus, should be available for
- * 2.5.47.]
- */
-static void mux_config_port(struct uart_port *port, int type)
-{
- port->type = PORT_MUX;
-}
-
-/**
- * mux_verify_port - Verify the port information.
- * @port: Ptr to the uart_port.
- * @ser: Ptr to the serial information.
- *
- * Verify the new serial port information contained within serinfo is
- * suitable for this port type.
- */
-static int mux_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if(port->membase == NULL)
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * mux_drv_poll - Mux poll function.
- * @unused: Unused variable
- *
- * This function periodically polls the Serial MUX to check for new data.
- */
-static void mux_poll(unsigned long unused)
-{
- int i;
-
- for(i = 0; i < port_cnt; ++i) {
- if(!mux_ports[i].enabled)
- continue;
-
- mux_read(&mux_ports[i].port);
- mux_write(&mux_ports[i].port);
- }
-
- mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
-}
-
-
-#ifdef CONFIG_SERIAL_MUX_CONSOLE
-static void mux_console_write(struct console *co, const char *s, unsigned count)
-{
- /* Wait until the FIFO drains. */
- while(UART_GET_FIFO_CNT(&mux_ports[0].port))
- udelay(1);
-
- while(count--) {
- if(*s == '\n') {
- UART_PUT_CHAR(&mux_ports[0].port, '\r');
- }
- UART_PUT_CHAR(&mux_ports[0].port, *s++);
- }
-
-}
-
-static int mux_console_setup(struct console *co, char *options)
-{
- return 0;
-}
-
-struct tty_driver *mux_console_device(struct console *co, int *index)
-{
- *index = co->index;
- return mux_driver.tty_driver;
-}
-
-static struct console mux_console = {
- .name = "ttyB",
- .write = mux_console_write,
- .device = mux_console_device,
- .setup = mux_console_setup,
- .flags = CON_ENABLED | CON_PRINTBUFFER,
- .index = 0,
-};
-
-#define MUX_CONSOLE &mux_console
-#else
-#define MUX_CONSOLE NULL
-#endif
-
-static struct uart_ops mux_pops = {
- .tx_empty = mux_tx_empty,
- .set_mctrl = mux_set_mctrl,
- .get_mctrl = mux_get_mctrl,
- .stop_tx = mux_stop_tx,
- .start_tx = mux_start_tx,
- .stop_rx = mux_stop_rx,
- .enable_ms = mux_enable_ms,
- .break_ctl = mux_break_ctl,
- .startup = mux_startup,
- .shutdown = mux_shutdown,
- .set_termios = mux_set_termios,
- .type = mux_type,
- .release_port = mux_release_port,
- .request_port = mux_request_port,
- .config_port = mux_config_port,
- .verify_port = mux_verify_port,
-};
-
-/**
- * mux_probe - Determine if the Serial Mux should claim this device.
- * @dev: The parisc device.
- *
- * Deterimine if the Serial Mux should claim this chip (return 0)
- * or not (return 1).
- */
-static int __init mux_probe(struct parisc_device *dev)
-{
- int i, status;
-
- int port_count = get_mux_port_count(dev);
- printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count);
-
- dev_set_drvdata(&dev->dev, (void *)(long)port_count);
- request_mem_region(dev->hpa.start + MUX_OFFSET,
- port_count * MUX_LINE_OFFSET, "Mux");
-
- if(!port_cnt) {
- mux_driver.cons = MUX_CONSOLE;
-
- status = uart_register_driver(&mux_driver);
- if(status) {
- printk(KERN_ERR "Serial mux: Unable to register driver.\n");
- return 1;
- }
- }
-
- for(i = 0; i < port_count; ++i, ++port_cnt) {
- struct uart_port *port = &mux_ports[port_cnt].port;
- port->iobase = 0;
- port->mapbase = dev->hpa.start + MUX_OFFSET +
- (i * MUX_LINE_OFFSET);
- port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET);
- port->iotype = UPIO_MEM;
- port->type = PORT_MUX;
- port->irq = NO_IRQ;
- port->uartclk = 0;
- port->fifosize = MUX_FIFO_SIZE;
- port->ops = &mux_pops;
- port->flags = UPF_BOOT_AUTOCONF;
- port->line = port_cnt;
-
- /* The port->timeout needs to match what is present in
- * uart_wait_until_sent in serial_core.c. Otherwise
- * the time spent in msleep_interruptable will be very
- * long, causing the appearance of a console hang.
- */
- port->timeout = HZ / 50;
- spin_lock_init(&port->lock);
-
- status = uart_add_one_port(&mux_driver, port);
- BUG_ON(status);
- }
-
- return 0;
-}
-
-static int __devexit mux_remove(struct parisc_device *dev)
-{
- int i, j;
- int port_count = (long)dev_get_drvdata(&dev->dev);
-
- /* Find Port 0 for this card in the mux_ports list. */
- for(i = 0; i < port_cnt; ++i) {
- if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET)
- break;
- }
- BUG_ON(i + port_count > port_cnt);
-
- /* Release the resources associated with each port on the device. */
- for(j = 0; j < port_count; ++j, ++i) {
- struct uart_port *port = &mux_ports[i].port;
-
- uart_remove_one_port(&mux_driver, port);
- if(port->membase)
- iounmap(port->membase);
- }
-
- release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET);
- return 0;
-}
-
-/* Hack. This idea was taken from the 8250_gsc.c on how to properly order
- * the serial port detection in the proper order. The idea is we always
- * want the builtin mux to be detected before addin mux cards, so we
- * specifically probe for the builtin mux cards first.
- *
- * This table only contains the parisc_device_id of known builtin mux
- * devices. All other mux cards will be detected by the generic mux_tbl.
- */
-static struct parisc_device_id builtin_mux_tbl[] = {
- { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */
- { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */
- { 0, }
-};
-
-static struct parisc_device_id mux_tbl[] = {
- { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl);
-MODULE_DEVICE_TABLE(parisc, mux_tbl);
-
-static struct parisc_driver builtin_serial_mux_driver = {
- .name = "builtin_serial_mux",
- .id_table = builtin_mux_tbl,
- .probe = mux_probe,
- .remove = __devexit_p(mux_remove),
-};
-
-static struct parisc_driver serial_mux_driver = {
- .name = "serial_mux",
- .id_table = mux_tbl,
- .probe = mux_probe,
- .remove = __devexit_p(mux_remove),
-};
-
-/**
- * mux_init - Serial MUX initialization procedure.
- *
- * Register the Serial MUX driver.
- */
-static int __init mux_init(void)
-{
- register_parisc_driver(&builtin_serial_mux_driver);
- register_parisc_driver(&serial_mux_driver);
-
- if(port_cnt > 0) {
- /* Start the Mux timer */
- init_timer(&mux_timer);
- mux_timer.function = mux_poll;
- mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
-
-#ifdef CONFIG_SERIAL_MUX_CONSOLE
- register_console(&mux_console);
-#endif
- }
-
- return 0;
-}
-
-/**
- * mux_exit - Serial MUX cleanup procedure.
- *
- * Unregister the Serial MUX driver from the tty layer.
- */
-static void __exit mux_exit(void)
-{
- /* Delete the Mux timer. */
- if(port_cnt > 0) {
- del_timer(&mux_timer);
-#ifdef CONFIG_SERIAL_MUX_CONSOLE
- unregister_console(&mux_console);
-#endif
- }
-
- unregister_parisc_driver(&builtin_serial_mux_driver);
- unregister_parisc_driver(&serial_mux_driver);
- uart_unregister_driver(&mux_driver);
-}
-
-module_init(mux_init);
-module_exit(mux_exit);
-
-MODULE_AUTHOR("Ryan Bradetich");
-MODULE_DESCRIPTION("Serial MUX driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(MUX_MAJOR);
diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c
deleted file mode 100644
index 7735c9f35fa0..000000000000
--- a/drivers/serial/netx-serial.c
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * 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
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/netx-regs.h>
-
-/* We've been assigned a range on the "Low-density serial ports" major */
-#define SERIAL_NX_MAJOR 204
-#define MINOR_START 170
-
-enum uart_regs {
- UART_DR = 0x00,
- UART_SR = 0x04,
- UART_LINE_CR = 0x08,
- UART_BAUDDIV_MSB = 0x0c,
- UART_BAUDDIV_LSB = 0x10,
- UART_CR = 0x14,
- UART_FR = 0x18,
- UART_IIR = 0x1c,
- UART_ILPR = 0x20,
- UART_RTS_CR = 0x24,
- UART_RTS_LEAD = 0x28,
- UART_RTS_TRAIL = 0x2c,
- UART_DRV_ENABLE = 0x30,
- UART_BRM_CR = 0x34,
- UART_RXFIFO_IRQLEVEL = 0x38,
- UART_TXFIFO_IRQLEVEL = 0x3c,
-};
-
-#define SR_FE (1<<0)
-#define SR_PE (1<<1)
-#define SR_BE (1<<2)
-#define SR_OE (1<<3)
-
-#define LINE_CR_BRK (1<<0)
-#define LINE_CR_PEN (1<<1)
-#define LINE_CR_EPS (1<<2)
-#define LINE_CR_STP2 (1<<3)
-#define LINE_CR_FEN (1<<4)
-#define LINE_CR_5BIT (0<<5)
-#define LINE_CR_6BIT (1<<5)
-#define LINE_CR_7BIT (2<<5)
-#define LINE_CR_8BIT (3<<5)
-#define LINE_CR_BITS_MASK (3<<5)
-
-#define CR_UART_EN (1<<0)
-#define CR_SIREN (1<<1)
-#define CR_SIRLP (1<<2)
-#define CR_MSIE (1<<3)
-#define CR_RIE (1<<4)
-#define CR_TIE (1<<5)
-#define CR_RTIE (1<<6)
-#define CR_LBE (1<<7)
-
-#define FR_CTS (1<<0)
-#define FR_DSR (1<<1)
-#define FR_DCD (1<<2)
-#define FR_BUSY (1<<3)
-#define FR_RXFE (1<<4)
-#define FR_TXFF (1<<5)
-#define FR_RXFF (1<<6)
-#define FR_TXFE (1<<7)
-
-#define IIR_MIS (1<<0)
-#define IIR_RIS (1<<1)
-#define IIR_TIS (1<<2)
-#define IIR_RTIS (1<<3)
-#define IIR_MASK 0xf
-
-#define RTS_CR_AUTO (1<<0)
-#define RTS_CR_RTS (1<<1)
-#define RTS_CR_COUNT (1<<2)
-#define RTS_CR_MOD2 (1<<3)
-#define RTS_CR_RTS_POL (1<<4)
-#define RTS_CR_CTS_CTR (1<<5)
-#define RTS_CR_CTS_POL (1<<6)
-#define RTS_CR_STICK (1<<7)
-
-#define UART_PORT_SIZE 0x40
-#define DRIVER_NAME "netx-uart"
-
-struct netx_port {
- struct uart_port port;
-};
-
-static void netx_stop_tx(struct uart_port *port)
-{
- unsigned int val;
- val = readl(port->membase + UART_CR);
- writel(val & ~CR_TIE, port->membase + UART_CR);
-}
-
-static void netx_stop_rx(struct uart_port *port)
-{
- unsigned int val;
- val = readl(port->membase + UART_CR);
- writel(val & ~CR_RIE, port->membase + UART_CR);
-}
-
-static void netx_enable_ms(struct uart_port *port)
-{
- unsigned int val;
- val = readl(port->membase + UART_CR);
- writel(val | CR_MSIE, port->membase + UART_CR);
-}
-
-static inline void netx_transmit_buffer(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- if (port->x_char) {
- writel(port->x_char, port->membase + UART_DR);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
-
- if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
- netx_stop_tx(port);
- return;
- }
-
- do {
- /* send xmit->buf[xmit->tail]
- * out the port here */
- writel(xmit->buf[xmit->tail], port->membase + UART_DR);
- xmit->tail = (xmit->tail + 1) &
- (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (!(readl(port->membase + UART_FR) & FR_TXFF));
-
- if (uart_circ_empty(xmit))
- netx_stop_tx(port);
-}
-
-static void netx_start_tx(struct uart_port *port)
-{
- writel(
- readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR);
-
- if (!(readl(port->membase + UART_FR) & FR_TXFF))
- netx_transmit_buffer(port);
-}
-
-static unsigned int netx_tx_empty(struct uart_port *port)
-{
- return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT;
-}
-
-static void netx_txint(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- netx_stop_tx(port);
- return;
- }
-
- netx_transmit_buffer(port);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-}
-
-static void netx_rxint(struct uart_port *port)
-{
- unsigned char rx, flg, status;
- struct tty_struct *tty = port->state->port.tty;
-
- while (!(readl(port->membase + UART_FR) & FR_RXFE)) {
- rx = readl(port->membase + UART_DR);
- flg = TTY_NORMAL;
- port->icount.rx++;
- status = readl(port->membase + UART_SR);
- if (status & SR_BE) {
- writel(0, port->membase + UART_SR);
- if (uart_handle_break(port))
- continue;
- }
-
- if (unlikely(status & (SR_FE | SR_PE | SR_OE))) {
-
- if (status & SR_PE)
- port->icount.parity++;
- else if (status & SR_FE)
- port->icount.frame++;
- if (status & SR_OE)
- port->icount.overrun++;
-
- status &= port->read_status_mask;
-
- if (status & SR_BE)
- flg = TTY_BREAK;
- else if (status & SR_PE)
- flg = TTY_PARITY;
- else if (status & SR_FE)
- flg = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, rx))
- continue;
-
- uart_insert_char(port, status, SR_OE, rx, flg);
- }
-
- tty_flip_buffer_push(tty);
- return;
-}
-
-static irqreturn_t netx_int(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- unsigned long flags;
- unsigned char status;
-
- spin_lock_irqsave(&port->lock,flags);
-
- status = readl(port->membase + UART_IIR) & IIR_MASK;
- while (status) {
- if (status & IIR_RIS)
- netx_rxint(port);
- if (status & IIR_TIS)
- netx_txint(port);
- if (status & IIR_MIS) {
- if (readl(port->membase + UART_FR) & FR_CTS)
- uart_handle_cts_change(port, 1);
- else
- uart_handle_cts_change(port, 0);
- }
- writel(0, port->membase + UART_IIR);
- status = readl(port->membase + UART_IIR) & IIR_MASK;
- }
-
- spin_unlock_irqrestore(&port->lock,flags);
- return IRQ_HANDLED;
-}
-
-static unsigned int netx_get_mctrl(struct uart_port *port)
-{
- unsigned int ret = TIOCM_DSR | TIOCM_CAR;
-
- if (readl(port->membase + UART_FR) & FR_CTS)
- ret |= TIOCM_CTS;
-
- return ret;
-}
-
-static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- unsigned int val;
-
- /* FIXME: Locking needed ? */
- if (mctrl & TIOCM_RTS) {
- val = readl(port->membase + UART_RTS_CR);
- writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
- }
-}
-
-static void netx_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned int line_cr;
- spin_lock_irq(&port->lock);
-
- line_cr = readl(port->membase + UART_LINE_CR);
- if (break_state != 0)
- line_cr |= LINE_CR_BRK;
- else
- line_cr &= ~LINE_CR_BRK;
- writel(line_cr, port->membase + UART_LINE_CR);
-
- spin_unlock_irq(&port->lock);
-}
-
-static int netx_startup(struct uart_port *port)
-{
- int ret;
-
- ret = request_irq(port->irq, netx_int, 0,
- DRIVER_NAME, port);
- if (ret) {
- dev_err(port->dev, "unable to grab irq%d\n",port->irq);
- goto exit;
- }
-
- writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN,
- port->membase + UART_LINE_CR);
-
- writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN,
- port->membase + UART_CR);
-
-exit:
- return ret;
-}
-
-static void netx_shutdown(struct uart_port *port)
-{
- writel(0, port->membase + UART_CR) ;
-
- free_irq(port->irq, port);
-}
-
-static void
-netx_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int baud, quot;
- unsigned char old_cr;
- unsigned char line_cr = LINE_CR_FEN;
- unsigned char rts_cr = 0;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- line_cr |= LINE_CR_5BIT;
- break;
- case CS6:
- line_cr |= LINE_CR_6BIT;
- break;
- case CS7:
- line_cr |= LINE_CR_7BIT;
- break;
- case CS8:
- line_cr |= LINE_CR_8BIT;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- line_cr |= LINE_CR_STP2;
-
- if (termios->c_cflag & PARENB) {
- line_cr |= LINE_CR_PEN;
- if (!(termios->c_cflag & PARODD))
- line_cr |= LINE_CR_EPS;
- }
-
- if (termios->c_cflag & CRTSCTS)
- rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL;
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = baud * 4096;
- quot /= 1000;
- quot *= 256;
- quot /= 100000;
-
- spin_lock_irq(&port->lock);
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- old_cr = readl(port->membase + UART_CR);
-
- /* disable interrupts */
- writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE),
- port->membase + UART_CR);
-
- /* drain transmitter */
- while (readl(port->membase + UART_FR) & FR_BUSY);
-
- /* disable UART */
- writel(old_cr & ~CR_UART_EN, port->membase + UART_CR);
-
- /* modem status interrupts */
- old_cr &= ~CR_MSIE;
- if (UART_ENABLE_MS(port, termios->c_cflag))
- old_cr |= CR_MSIE;
-
- writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB);
- writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB);
- writel(line_cr, port->membase + UART_LINE_CR);
-
- writel(rts_cr, port->membase + UART_RTS_CR);
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= SR_PE;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= SR_BE;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= SR_PE;
- }
-
- port->read_status_mask = 0;
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= SR_BE;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= SR_PE | SR_FE;
-
- writel(old_cr, port->membase + UART_CR);
-
- spin_unlock_irq(&port->lock);
-}
-
-static const char *netx_type(struct uart_port *port)
-{
- return port->type == PORT_NETX ? "NETX" : NULL;
-}
-
-static void netx_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, UART_PORT_SIZE);
-}
-
-static int netx_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, UART_PORT_SIZE,
- DRIVER_NAME) != NULL ? 0 : -EBUSY;
-}
-
-static void netx_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0)
- port->type = PORT_NETX;
-}
-
-static int
-netx_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX)
- ret = -EINVAL;
-
- return ret;
-}
-
-static struct uart_ops netx_pops = {
- .tx_empty = netx_tx_empty,
- .set_mctrl = netx_set_mctrl,
- .get_mctrl = netx_get_mctrl,
- .stop_tx = netx_stop_tx,
- .start_tx = netx_start_tx,
- .stop_rx = netx_stop_rx,
- .enable_ms = netx_enable_ms,
- .break_ctl = netx_break_ctl,
- .startup = netx_startup,
- .shutdown = netx_shutdown,
- .set_termios = netx_set_termios,
- .type = netx_type,
- .release_port = netx_release_port,
- .request_port = netx_request_port,
- .config_port = netx_config_port,
- .verify_port = netx_verify_port,
-};
-
-static struct netx_port netx_ports[] = {
- {
- .port = {
- .type = PORT_NETX,
- .iotype = UPIO_MEM,
- .membase = (char __iomem *)io_p2v(NETX_PA_UART0),
- .mapbase = NETX_PA_UART0,
- .irq = NETX_IRQ_UART0,
- .uartclk = 100000000,
- .fifosize = 16,
- .flags = UPF_BOOT_AUTOCONF,
- .ops = &netx_pops,
- .line = 0,
- },
- }, {
- .port = {
- .type = PORT_NETX,
- .iotype = UPIO_MEM,
- .membase = (char __iomem *)io_p2v(NETX_PA_UART1),
- .mapbase = NETX_PA_UART1,
- .irq = NETX_IRQ_UART1,
- .uartclk = 100000000,
- .fifosize = 16,
- .flags = UPF_BOOT_AUTOCONF,
- .ops = &netx_pops,
- .line = 1,
- },
- }, {
- .port = {
- .type = PORT_NETX,
- .iotype = UPIO_MEM,
- .membase = (char __iomem *)io_p2v(NETX_PA_UART2),
- .mapbase = NETX_PA_UART2,
- .irq = NETX_IRQ_UART2,
- .uartclk = 100000000,
- .fifosize = 16,
- .flags = UPF_BOOT_AUTOCONF,
- .ops = &netx_pops,
- .line = 2,
- },
- }
-};
-
-#ifdef CONFIG_SERIAL_NETX_CONSOLE
-
-static void netx_console_putchar(struct uart_port *port, int ch)
-{
- while (readl(port->membase + UART_FR) & FR_BUSY);
- writel(ch, port->membase + UART_DR);
-}
-
-static void
-netx_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_port *port = &netx_ports[co->index].port;
- unsigned char cr_save;
-
- cr_save = readl(port->membase + UART_CR);
- writel(cr_save | CR_UART_EN, port->membase + UART_CR);
-
- uart_console_write(port, s, count, netx_console_putchar);
-
- while (readl(port->membase + UART_FR) & FR_BUSY);
- writel(cr_save, port->membase + UART_CR);
-}
-
-static void __init
-netx_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits, int *flow)
-{
- unsigned char line_cr;
-
- *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) |
- readl(port->membase + UART_BAUDDIV_LSB);
- *baud *= 1000;
- *baud /= 4096;
- *baud *= 1000;
- *baud /= 256;
- *baud *= 100;
-
- line_cr = readl(port->membase + UART_LINE_CR);
- *parity = 'n';
- if (line_cr & LINE_CR_PEN) {
- if (line_cr & LINE_CR_EPS)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- switch (line_cr & LINE_CR_BITS_MASK) {
- case LINE_CR_8BIT:
- *bits = 8;
- break;
- case LINE_CR_7BIT:
- *bits = 7;
- break;
- case LINE_CR_6BIT:
- *bits = 6;
- break;
- case LINE_CR_5BIT:
- *bits = 5;
- break;
- }
-
- if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO)
- *flow = 'r';
-}
-
-static int __init
-netx_console_setup(struct console *co, char *options)
-{
- struct netx_port *sport;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports))
- co->index = 0;
- sport = &netx_ports[co->index];
-
- if (options) {
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- } else {
- /* if the UART is enabled, assume it has been correctly setup
- * by the bootloader and get the options
- */
- if (readl(sport->port.membase + UART_CR) & CR_UART_EN) {
- netx_console_get_options(&sport->port, &baud,
- &parity, &bits, &flow);
- }
-
- }
-
- return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver netx_reg;
-static struct console netx_console = {
- .name = "ttyNX",
- .write = netx_console_write,
- .device = uart_console_device,
- .setup = netx_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &netx_reg,
-};
-
-static int __init netx_console_init(void)
-{
- register_console(&netx_console);
- return 0;
-}
-console_initcall(netx_console_init);
-
-#define NETX_CONSOLE &netx_console
-#else
-#define NETX_CONSOLE NULL
-#endif
-
-static struct uart_driver netx_reg = {
- .owner = THIS_MODULE,
- .driver_name = DRIVER_NAME,
- .dev_name = "ttyNX",
- .major = SERIAL_NX_MAJOR,
- .minor = MINOR_START,
- .nr = ARRAY_SIZE(netx_ports),
- .cons = NETX_CONSOLE,
-};
-
-static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct netx_port *sport = platform_get_drvdata(pdev);
-
- if (sport)
- uart_suspend_port(&netx_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_netx_resume(struct platform_device *pdev)
-{
- struct netx_port *sport = platform_get_drvdata(pdev);
-
- if (sport)
- uart_resume_port(&netx_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_netx_probe(struct platform_device *pdev)
-{
- struct uart_port *port = &netx_ports[pdev->id].port;
-
- dev_info(&pdev->dev, "initialising\n");
-
- port->dev = &pdev->dev;
-
- writel(1, port->membase + UART_RXFIFO_IRQLEVEL);
- uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port);
- platform_set_drvdata(pdev, &netx_ports[pdev->id]);
-
- return 0;
-}
-
-static int serial_netx_remove(struct platform_device *pdev)
-{
- struct netx_port *sport = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
-
- if (sport)
- uart_remove_one_port(&netx_reg, &sport->port);
-
- return 0;
-}
-
-static struct platform_driver serial_netx_driver = {
- .probe = serial_netx_probe,
- .remove = serial_netx_remove,
-
- .suspend = serial_netx_suspend,
- .resume = serial_netx_resume,
-
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init netx_serial_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: NetX driver\n");
-
- ret = uart_register_driver(&netx_reg);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&serial_netx_driver);
- if (ret != 0)
- uart_unregister_driver(&netx_reg);
-
- return 0;
-}
-
-static void __exit netx_serial_exit(void)
-{
- platform_driver_unregister(&serial_netx_driver);
- uart_unregister_driver(&netx_reg);
-}
-
-module_init(netx_serial_init);
-module_exit(netx_serial_exit);
-
-MODULE_AUTHOR("Sascha Hauer");
-MODULE_DESCRIPTION("NetX serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c
deleted file mode 100644
index de173671e3d0..000000000000
--- a/drivers/serial/nwpserial.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Serial Port driver for a NWP uart device
- *
- * Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org>
- *
- * 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/init.h>
-#include <linux/console.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/serial_core.h>
-#include <linux/tty.h>
-#include <linux/irqreturn.h>
-#include <linux/mutex.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
-#include <linux/nwpserial.h>
-#include <asm/prom.h>
-#include <asm/dcr.h>
-
-#define NWPSERIAL_NR 2
-
-#define NWPSERIAL_STATUS_RXVALID 0x1
-#define NWPSERIAL_STATUS_TXFULL 0x2
-
-struct nwpserial_port {
- struct uart_port port;
- dcr_host_t dcr_host;
- unsigned int ier;
- unsigned int mcr;
-};
-
-static DEFINE_MUTEX(nwpserial_mutex);
-static struct nwpserial_port nwpserial_ports[NWPSERIAL_NR];
-
-static void wait_for_bits(struct nwpserial_port *up, int bits)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = dcr_read(up->dcr_host, UART_LSR);
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & bits) != bits);
-}
-
-#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
-static void nwpserial_console_putchar(struct uart_port *port, int c)
-{
- struct nwpserial_port *up;
- up = container_of(port, struct nwpserial_port, port);
- /* check if tx buffer is full */
- wait_for_bits(up, UART_LSR_THRE);
- dcr_write(up->dcr_host, UART_TX, c);
- up->port.icount.tx++;
-}
-
-static void
-nwpserial_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct nwpserial_port *up = &nwpserial_ports[co->index];
- unsigned long flags;
- int locked = 1;
-
- if (oops_in_progress)
- locked = spin_trylock_irqsave(&up->port.lock, flags);
- else
- spin_lock_irqsave(&up->port.lock, flags);
-
- /* save and disable interrupt */
- up->ier = dcr_read(up->dcr_host, UART_IER);
- dcr_write(up->dcr_host, UART_IER, up->ier & ~UART_IER_RDI);
-
- uart_console_write(&up->port, s, count, nwpserial_console_putchar);
-
- /* wait for transmitter to become empty */
- while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0)
- cpu_relax();
-
- /* restore interrupt state */
- dcr_write(up->dcr_host, UART_IER, up->ier);
-
- if (locked)
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static struct uart_driver nwpserial_reg;
-static struct console nwpserial_console = {
- .name = "ttySQ",
- .write = nwpserial_console_write,
- .device = uart_console_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &nwpserial_reg,
-};
-#define NWPSERIAL_CONSOLE (&nwpserial_console)
-#else
-#define NWPSERIAL_CONSOLE NULL
-#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
-
-/**************************************************************************/
-
-static int nwpserial_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void nwpserial_release_port(struct uart_port *port)
-{
- /* N/A */
-}
-
-static void nwpserial_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_NWPSERIAL;
-}
-
-static irqreturn_t nwpserial_interrupt(int irq, void *dev_id)
-{
- struct nwpserial_port *up = dev_id;
- struct tty_struct *tty = up->port.state->port.tty;
- irqreturn_t ret;
- unsigned int iir;
- unsigned char ch;
-
- spin_lock(&up->port.lock);
-
- /* check if the uart was the interrupt source. */
- iir = dcr_read(up->dcr_host, UART_IIR);
- if (!iir) {
- ret = IRQ_NONE;
- goto out;
- }
-
- do {
- up->port.icount.rx++;
- ch = dcr_read(up->dcr_host, UART_RX);
- if (up->port.ignore_status_mask != NWPSERIAL_STATUS_RXVALID)
- tty_insert_flip_char(tty, ch, TTY_NORMAL);
- } while (dcr_read(up->dcr_host, UART_LSR) & UART_LSR_DR);
-
- tty_flip_buffer_push(tty);
- ret = IRQ_HANDLED;
-
- /* clear interrupt */
- dcr_write(up->dcr_host, UART_IIR, 1);
-out:
- spin_unlock(&up->port.lock);
- return ret;
-}
-
-static int nwpserial_startup(struct uart_port *port)
-{
- struct nwpserial_port *up;
- int err;
-
- up = container_of(port, struct nwpserial_port, port);
-
- /* disable flow control by default */
- up->mcr = dcr_read(up->dcr_host, UART_MCR) & ~UART_MCR_AFE;
- dcr_write(up->dcr_host, UART_MCR, up->mcr);
-
- /* register interrupt handler */
- err = request_irq(up->port.irq, nwpserial_interrupt,
- IRQF_SHARED, "nwpserial", up);
- if (err)
- return err;
-
- /* enable interrupts */
- up->ier = UART_IER_RDI;
- dcr_write(up->dcr_host, UART_IER, up->ier);
-
- /* enable receiving */
- up->port.ignore_status_mask &= ~NWPSERIAL_STATUS_RXVALID;
-
- return 0;
-}
-
-static void nwpserial_shutdown(struct uart_port *port)
-{
- struct nwpserial_port *up;
- up = container_of(port, struct nwpserial_port, port);
-
- /* disable receiving */
- up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
-
- /* disable interrupts from this port */
- up->ier = 0;
- dcr_write(up->dcr_host, UART_IER, up->ier);
-
- /* free irq */
- free_irq(up->port.irq, port);
-}
-
-static int nwpserial_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-static const char *nwpserial_type(struct uart_port *port)
-{
- return port->type == PORT_NWPSERIAL ? "nwpserial" : NULL;
-}
-
-static void nwpserial_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- struct nwpserial_port *up;
- up = container_of(port, struct nwpserial_port, port);
-
- up->port.read_status_mask = NWPSERIAL_STATUS_RXVALID
- | NWPSERIAL_STATUS_TXFULL;
-
- up->port.ignore_status_mask = 0;
- /* ignore all characters if CREAD is not set */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
-
- /* Copy back the old hardware settings */
- if (old)
- tty_termios_copy_hw(termios, old);
-}
-
-static void nwpserial_break_ctl(struct uart_port *port, int ctl)
-{
- /* N/A */
-}
-
-static void nwpserial_enable_ms(struct uart_port *port)
-{
- /* N/A */
-}
-
-static void nwpserial_stop_rx(struct uart_port *port)
-{
- struct nwpserial_port *up;
- up = container_of(port, struct nwpserial_port, port);
- /* don't forward any more data (like !CREAD) */
- up->port.ignore_status_mask = NWPSERIAL_STATUS_RXVALID;
-}
-
-static void nwpserial_putchar(struct nwpserial_port *up, unsigned char c)
-{
- /* check if tx buffer is full */
- wait_for_bits(up, UART_LSR_THRE);
- dcr_write(up->dcr_host, UART_TX, c);
- up->port.icount.tx++;
-}
-
-static void nwpserial_start_tx(struct uart_port *port)
-{
- struct nwpserial_port *up;
- struct circ_buf *xmit;
- up = container_of(port, struct nwpserial_port, port);
- xmit = &up->port.state->xmit;
-
- if (port->x_char) {
- nwpserial_putchar(up, up->port.x_char);
- port->x_char = 0;
- }
-
- while (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) {
- nwpserial_putchar(up, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
- }
-}
-
-static unsigned int nwpserial_get_mctrl(struct uart_port *port)
-{
- return 0;
-}
-
-static void nwpserial_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- /* N/A */
-}
-
-static void nwpserial_stop_tx(struct uart_port *port)
-{
- /* N/A */
-}
-
-static unsigned int nwpserial_tx_empty(struct uart_port *port)
-{
- struct nwpserial_port *up;
- unsigned long flags;
- int ret;
- up = container_of(port, struct nwpserial_port, port);
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = dcr_read(up->dcr_host, UART_LSR);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-}
-
-static struct uart_ops nwpserial_pops = {
- .tx_empty = nwpserial_tx_empty,
- .set_mctrl = nwpserial_set_mctrl,
- .get_mctrl = nwpserial_get_mctrl,
- .stop_tx = nwpserial_stop_tx,
- .start_tx = nwpserial_start_tx,
- .stop_rx = nwpserial_stop_rx,
- .enable_ms = nwpserial_enable_ms,
- .break_ctl = nwpserial_break_ctl,
- .startup = nwpserial_startup,
- .shutdown = nwpserial_shutdown,
- .set_termios = nwpserial_set_termios,
- .type = nwpserial_type,
- .release_port = nwpserial_release_port,
- .request_port = nwpserial_request_port,
- .config_port = nwpserial_config_port,
- .verify_port = nwpserial_verify_port,
-};
-
-static struct uart_driver nwpserial_reg = {
- .owner = THIS_MODULE,
- .driver_name = "nwpserial",
- .dev_name = "ttySQ",
- .major = TTY_MAJOR,
- .minor = 68,
- .nr = NWPSERIAL_NR,
- .cons = NWPSERIAL_CONSOLE,
-};
-
-int nwpserial_register_port(struct uart_port *port)
-{
- struct nwpserial_port *up = NULL;
- int ret = -1;
- int i;
- static int first = 1;
- int dcr_len;
- int dcr_base;
- struct device_node *dn;
-
- mutex_lock(&nwpserial_mutex);
-
- dn = port->dev->of_node;
- if (dn == NULL)
- goto out;
-
- /* get dcr base. */
- dcr_base = dcr_resource_start(dn, 0);
-
- /* find matching entry */
- for (i = 0; i < NWPSERIAL_NR; i++)
- if (nwpserial_ports[i].port.iobase == dcr_base) {
- up = &nwpserial_ports[i];
- break;
- }
-
- /* we didn't find a mtching entry, search for a free port */
- if (up == NULL)
- for (i = 0; i < NWPSERIAL_NR; i++)
- if (nwpserial_ports[i].port.type == PORT_UNKNOWN &&
- nwpserial_ports[i].port.iobase == 0) {
- up = &nwpserial_ports[i];
- break;
- }
-
- if (up == NULL) {
- ret = -EBUSY;
- goto out;
- }
-
- if (first)
- uart_register_driver(&nwpserial_reg);
- first = 0;
-
- up->port.membase = port->membase;
- up->port.irq = port->irq;
- up->port.uartclk = port->uartclk;
- up->port.fifosize = port->fifosize;
- up->port.regshift = port->regshift;
- up->port.iotype = port->iotype;
- up->port.flags = port->flags;
- up->port.mapbase = port->mapbase;
- up->port.private_data = port->private_data;
-
- if (port->dev)
- up->port.dev = port->dev;
-
- if (up->port.iobase != dcr_base) {
- up->port.ops = &nwpserial_pops;
- up->port.fifosize = 16;
-
- spin_lock_init(&up->port.lock);
-
- up->port.iobase = dcr_base;
- dcr_len = dcr_resource_len(dn, 0);
-
- up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
- if (!DCR_MAP_OK(up->dcr_host)) {
- printk(KERN_ERR "Cannot map DCR resources for NWPSERIAL");
- goto out;
- }
- }
-
- ret = uart_add_one_port(&nwpserial_reg, &up->port);
- if (ret == 0)
- ret = up->port.line;
-
-out:
- mutex_unlock(&nwpserial_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(nwpserial_register_port);
-
-void nwpserial_unregister_port(int line)
-{
- struct nwpserial_port *up = &nwpserial_ports[line];
- mutex_lock(&nwpserial_mutex);
- uart_remove_one_port(&nwpserial_reg, &up->port);
-
- up->port.type = PORT_UNKNOWN;
-
- mutex_unlock(&nwpserial_mutex);
-}
-EXPORT_SYMBOL(nwpserial_unregister_port);
-
-#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
-static int __init nwpserial_console_init(void)
-{
- struct nwpserial_port *up = NULL;
- struct device_node *dn;
- const char *name;
- int dcr_base;
- int dcr_len;
- int i;
-
- /* search for a free port */
- for (i = 0; i < NWPSERIAL_NR; i++)
- if (nwpserial_ports[i].port.type == PORT_UNKNOWN) {
- up = &nwpserial_ports[i];
- break;
- }
-
- if (up == NULL)
- return -1;
-
- name = of_get_property(of_chosen, "linux,stdout-path", NULL);
- if (name == NULL)
- return -1;
-
- dn = of_find_node_by_path(name);
- if (!dn)
- return -1;
-
- spin_lock_init(&up->port.lock);
- up->port.ops = &nwpserial_pops;
- up->port.type = PORT_NWPSERIAL;
- up->port.fifosize = 16;
-
- dcr_base = dcr_resource_start(dn, 0);
- dcr_len = dcr_resource_len(dn, 0);
- up->port.iobase = dcr_base;
-
- up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
- if (!DCR_MAP_OK(up->dcr_host)) {
- printk("Cannot map DCR resources for SERIAL");
- return -1;
- }
- register_console(&nwpserial_console);
- return 0;
-}
-console_initcall(nwpserial_console_init);
-#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
deleted file mode 100644
index 5c7abe4c94dd..000000000000
--- a/drivers/serial/of_serial.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Serial Port driver for Open Firmware platform devices
- *
- * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/nwpserial.h>
-
-struct of_serial_info {
- int type;
- int line;
-};
-
-/*
- * Fill a struct uart_port for a given device node
- */
-static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
- int type, struct uart_port *port)
-{
- struct resource resource;
- struct device_node *np = ofdev->dev.of_node;
- const __be32 *clk, *spd;
- const __be32 *prop;
- int ret, prop_size;
-
- memset(port, 0, sizeof *port);
- spd = of_get_property(np, "current-speed", NULL);
- clk = of_get_property(np, "clock-frequency", NULL);
- if (!clk) {
- dev_warn(&ofdev->dev, "no clock-frequency property set\n");
- return -ENODEV;
- }
-
- ret = of_address_to_resource(np, 0, &resource);
- if (ret) {
- dev_warn(&ofdev->dev, "invalid address\n");
- return ret;
- }
-
- spin_lock_init(&port->lock);
- port->mapbase = resource.start;
-
- /* Check for shifted address mapping */
- prop = of_get_property(np, "reg-offset", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- port->mapbase += be32_to_cpup(prop);
-
- /* Check for registers offset within the devices address range */
- prop = of_get_property(np, "reg-shift", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- port->regshift = be32_to_cpup(prop);
-
- port->irq = irq_of_parse_and_map(np, 0);
- port->iotype = UPIO_MEM;
- port->type = type;
- port->uartclk = be32_to_cpup(clk);
- port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
- | UPF_FIXED_PORT | UPF_FIXED_TYPE;
- port->dev = &ofdev->dev;
- /* If current-speed was set, then try not to change it. */
- if (spd)
- port->custom_divisor = be32_to_cpup(clk) / (16 * (be32_to_cpup(spd)));
-
- return 0;
-}
-
-/*
- * Try to register a serial port
- */
-static int __devinit of_platform_serial_probe(struct platform_device *ofdev,
- const struct of_device_id *id)
-{
- struct of_serial_info *info;
- struct uart_port port;
- int port_type;
- int ret;
-
- if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
- return -EBUSY;
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (info == NULL)
- return -ENOMEM;
-
- port_type = (unsigned long)id->data;
- ret = of_platform_serial_setup(ofdev, port_type, &port);
- if (ret)
- goto out;
-
- switch (port_type) {
-#ifdef CONFIG_SERIAL_8250
- case PORT_8250 ... PORT_MAX_8250:
- ret = serial8250_register_port(&port);
- break;
-#endif
-#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
- case PORT_NWPSERIAL:
- ret = nwpserial_register_port(&port);
- break;
-#endif
- default:
- /* need to add code for these */
- case PORT_UNKNOWN:
- dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
- ret = -ENODEV;
- break;
- }
- if (ret < 0)
- goto out;
-
- info->type = port_type;
- info->line = ret;
- dev_set_drvdata(&ofdev->dev, info);
- return 0;
-out:
- kfree(info);
- irq_dispose_mapping(port.irq);
- return ret;
-}
-
-/*
- * Release a line
- */
-static int of_platform_serial_remove(struct platform_device *ofdev)
-{
- struct of_serial_info *info = dev_get_drvdata(&ofdev->dev);
- switch (info->type) {
-#ifdef CONFIG_SERIAL_8250
- case PORT_8250 ... PORT_MAX_8250:
- serial8250_unregister_port(info->line);
- break;
-#endif
-#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
- case PORT_NWPSERIAL:
- nwpserial_unregister_port(info->line);
- break;
-#endif
- default:
- /* need to add code for these */
- break;
- }
- kfree(info);
- return 0;
-}
-
-/*
- * A few common types, add more as needed.
- */
-static struct of_device_id __devinitdata of_platform_serial_table[] = {
- { .type = "serial", .compatible = "ns8250", .data = (void *)PORT_8250, },
- { .type = "serial", .compatible = "ns16450", .data = (void *)PORT_16450, },
- { .type = "serial", .compatible = "ns16550a", .data = (void *)PORT_16550A, },
- { .type = "serial", .compatible = "ns16550", .data = (void *)PORT_16550, },
- { .type = "serial", .compatible = "ns16750", .data = (void *)PORT_16750, },
- { .type = "serial", .compatible = "ns16850", .data = (void *)PORT_16850, },
-#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
- { .type = "serial", .compatible = "ibm,qpace-nwp-serial",
- .data = (void *)PORT_NWPSERIAL, },
-#endif
- { .type = "serial", .data = (void *)PORT_UNKNOWN, },
- { /* end of list */ },
-};
-
-static struct of_platform_driver of_platform_serial_driver = {
- .driver = {
- .name = "of_serial",
- .owner = THIS_MODULE,
- .of_match_table = of_platform_serial_table,
- },
- .probe = of_platform_serial_probe,
- .remove = of_platform_serial_remove,
-};
-
-static int __init of_platform_serial_init(void)
-{
- return of_register_platform_driver(&of_platform_serial_driver);
-}
-module_init(of_platform_serial_init);
-
-static void __exit of_platform_serial_exit(void)
-{
- return of_unregister_platform_driver(&of_platform_serial_driver);
-};
-module_exit(of_platform_serial_exit);
-
-MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices");
diff --git a/drivers/serial/omap-serial.c b/drivers/serial/omap-serial.c
deleted file mode 100644
index 7f2f01058789..000000000000
--- a/drivers/serial/omap-serial.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
- * Driver for OMAP-UART controller.
- * Based on drivers/serial/8250.c
- *
- * Copyright (C) 2010 Texas Instruments.
- *
- * Authors:
- * Govindraj R <govindraj.raja@ti.com>
- * Thara Gopinath <thara@ti.com>
- *
- * 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.
- *
- * Note: This driver is made seperate from 8250 driver as we cannot
- * over load 8250 driver with omap platform specific configuration for
- * features like DMA, it makes easier to implement features like DMA and
- * hardware flow control and software flow control configuration with
- * this driver as required for the omap-platform.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/serial_reg.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/serial_core.h>
-#include <linux/irq.h>
-
-#include <plat/dma.h>
-#include <plat/dmtimer.h>
-#include <plat/omap-serial.h>
-
-static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
-
-/* Forward declaration of functions */
-static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
-static void serial_omap_rx_timeout(unsigned long uart_no);
-static int serial_omap_start_rxdma(struct uart_omap_port *up);
-
-static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
-{
- offset <<= up->port.regshift;
- return readw(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_omap_port *up, int offset, int value)
-{
- offset <<= up->port.regshift;
- writew(value, up->port.membase + offset);
-}
-
-static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
-{
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_out(up, UART_FCR, 0);
-}
-
-/*
- * serial_omap_get_divisor - calculate divisor value
- * @port: uart port info
- * @baud: baudrate for which divisor needs to be calculated.
- *
- * We have written our own function to get the divisor so as to support
- * 13x mode. 3Mbps Baudrate as an different divisor.
- * Reference OMAP TRM Chapter 17:
- * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
- * referring to oversampling - divisor value
- * baudrate 460,800 to 3,686,400 all have divisor 13
- * except 3,000,000 which has divisor value 16
- */
-static unsigned int
-serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
-{
- unsigned int divisor;
-
- if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
- divisor = 13;
- else
- divisor = 16;
- return port->uartclk/(baud * divisor);
-}
-
-static void serial_omap_stop_rxdma(struct uart_omap_port *up)
-{
- if (up->uart_dma.rx_dma_used) {
- del_timer(&up->uart_dma.rx_timer);
- omap_stop_dma(up->uart_dma.rx_dma_channel);
- omap_free_dma(up->uart_dma.rx_dma_channel);
- up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
- up->uart_dma.rx_dma_used = false;
- }
-}
-
-static void serial_omap_enable_ms(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
-
- dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_omap_stop_tx(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
-
- if (up->use_dma &&
- up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
- /*
- * Check if dma is still active. If yes do nothing,
- * return. Else stop dma
- */
- if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
- return;
- omap_stop_dma(up->uart_dma.tx_dma_channel);
- omap_free_dma(up->uart_dma.tx_dma_channel);
- up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
- }
-
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial_omap_stop_rx(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
-
- if (up->use_dma)
- serial_omap_stop_rxdma(up);
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_omap_port *up, int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned int flag;
- unsigned char ch, lsr = *status;
- int max_count = 256;
-
- do {
- if (likely(lsr & UART_LSR_DR))
- ch = serial_in(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
- /*
- * For statistics only
- */
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (lsr & UART_LSR_PE) {
- up->port.icount.parity++;
- } else if (lsr & UART_LSR_FE) {
- up->port.icount.frame++;
- }
-
- if (lsr & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- lsr &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_OMAP_CONSOLE
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- lsr |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-#endif
- if (lsr & UART_LSR_BI)
- flag = TTY_BREAK;
- else if (lsr & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (lsr & UART_LSR_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
- uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
-ignore_char:
- lsr = serial_in(up, UART_LSR);
- } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
-}
-
-static void transmit_chars(struct uart_omap_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_out(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_omap_stop_tx(&up->port);
- return;
- }
- count = up->port.fifosize / 4;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit))
- serial_omap_stop_tx(&up->port);
-}
-
-static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
-{
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial_omap_start_tx(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- struct circ_buf *xmit;
- unsigned int start;
- int ret = 0;
-
- if (!up->use_dma) {
- serial_omap_enable_ier_thri(up);
- return;
- }
-
- if (up->uart_dma.tx_dma_used)
- return;
-
- xmit = &up->port.state->xmit;
-
- if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
- ret = omap_request_dma(up->uart_dma.uart_dma_tx,
- "UART Tx DMA",
- (void *)uart_tx_dma_callback, up,
- &(up->uart_dma.tx_dma_channel));
-
- if (ret < 0) {
- serial_omap_enable_ier_thri(up);
- return;
- }
- }
- spin_lock(&(up->uart_dma.tx_lock));
- up->uart_dma.tx_dma_used = true;
- spin_unlock(&(up->uart_dma.tx_lock));
-
- start = up->uart_dma.tx_buf_dma_phys +
- (xmit->tail & (UART_XMIT_SIZE - 1));
-
- up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
- /*
- * It is a circular buffer. See if the buffer has wounded back.
- * If yes it will have to be transferred in two separate dma
- * transfers
- */
- if (start + up->uart_dma.tx_buf_size >=
- up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
- up->uart_dma.tx_buf_size =
- (up->uart_dma.tx_buf_dma_phys +
- UART_XMIT_SIZE) - start;
-
- omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC, start, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.tx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_tx, 0);
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.tx_dma_channel);
-}
-
-static unsigned int check_modem_status(struct uart_omap_port *up)
-{
- unsigned int status;
-
- status = serial_in(up, UART_MSR);
- status |= up->msr_saved_flags;
- up->msr_saved_flags = 0;
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return status;
-
- if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
- up->port.state != NULL) {
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change
- (&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change
- (&up->port, status & UART_MSR_CTS);
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
- }
-
- return status;
-}
-
-/**
- * serial_omap_irq() - This handles the interrupt from one port
- * @irq: uart port irq number
- * @dev_id: uart port info
- */
-static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
-{
- struct uart_omap_port *up = dev_id;
- unsigned int iir, lsr;
- unsigned long flags;
-
- iir = serial_in(up, UART_IIR);
- if (iir & UART_IIR_NO_INT)
- return IRQ_NONE;
-
- spin_lock_irqsave(&up->port.lock, flags);
- lsr = serial_in(up, UART_LSR);
- if (iir & UART_IIR_RLSI) {
- if (!up->use_dma) {
- if (lsr & UART_LSR_DR)
- receive_chars(up, &lsr);
- } else {
- up->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- if ((serial_omap_start_rxdma(up) != 0) &&
- (lsr & UART_LSR_DR))
- receive_chars(up, &lsr);
- }
- }
-
- check_modem_status(up);
- if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
- transmit_chars(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
- up->port_activity = jiffies;
- return IRQ_HANDLED;
-}
-
-static unsigned int serial_omap_tx_empty(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned long flags = 0;
- unsigned int ret = 0;
-
- dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int serial_omap_get_mctrl(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned char status;
- unsigned int ret = 0;
-
- status = check_modem_status(up);
- dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
-
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned char mcr = 0;
-
- dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr |= up->mcr;
- serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_omap_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned long flags = 0;
-
- dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial_omap_startup(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned long flags = 0;
- int retval;
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags,
- up->name, up);
- if (retval)
- return retval;
-
- dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- serial_omap_clear_fifos(up);
- /* For Hardware flow control */
- serial_out(up, UART_MCR, UART_MCR_RTS);
-
- /*
- * Clear the interrupt registers.
- */
- (void) serial_in(up, UART_LSR);
- if (serial_in(up, UART_LSR) & UART_LSR_DR)
- (void) serial_in(up, UART_RX);
- (void) serial_in(up, UART_IIR);
- (void) serial_in(up, UART_MSR);
-
- /*
- * Now, initialize the UART
- */
- serial_out(up, UART_LCR, UART_LCR_WLEN8);
- spin_lock_irqsave(&up->port.lock, flags);
- /*
- * Most PC uarts need OUT2 raised to enable interrupts.
- */
- up->port.mctrl |= TIOCM_OUT2;
- serial_omap_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- up->msr_saved_flags = 0;
- if (up->use_dma) {
- free_page((unsigned long)up->port.state->xmit.buf);
- up->port.state->xmit.buf = dma_alloc_coherent(NULL,
- UART_XMIT_SIZE,
- (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
- 0);
- init_timer(&(up->uart_dma.rx_timer));
- up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
- up->uart_dma.rx_timer.data = up->pdev->id;
- /* Currently the buffer size is 4KB. Can increase it */
- up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
- up->uart_dma.rx_buf_size,
- (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
- }
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI;
- serial_out(up, UART_IER, up->ier);
-
- up->port_activity = jiffies;
- return 0;
-}
-
-static void serial_omap_shutdown(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned long flags = 0;
-
- dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_out(up, UART_IER, 0);
-
- spin_lock_irqsave(&up->port.lock, flags);
- up->port.mctrl &= ~TIOCM_OUT2;
- serial_omap_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
- serial_omap_clear_fifos(up);
-
- /*
- * Read data port to reset things, and then free the irq
- */
- if (serial_in(up, UART_LSR) & UART_LSR_DR)
- (void) serial_in(up, UART_RX);
- if (up->use_dma) {
- dma_free_coherent(up->port.dev,
- UART_XMIT_SIZE, up->port.state->xmit.buf,
- up->uart_dma.tx_buf_dma_phys);
- up->port.state->xmit.buf = NULL;
- serial_omap_stop_rx(port);
- dma_free_coherent(up->port.dev,
- up->uart_dma.rx_buf_size, up->uart_dma.rx_buf,
- up->uart_dma.rx_buf_dma_phys);
- up->uart_dma.rx_buf = NULL;
- }
- free_irq(up->port.irq, up);
-}
-
-static inline void
-serial_omap_configure_xonxoff
- (struct uart_omap_port *up, struct ktermios *termios)
-{
- unsigned char efr = 0;
-
- up->lcr = serial_in(up, UART_LCR);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- up->efr = serial_in(up, UART_EFR);
- serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
-
- serial_out(up, UART_XON1, termios->c_cc[VSTART]);
- serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
-
- /* clear SW control mode bits */
- efr = up->efr;
- efr &= OMAP_UART_SW_CLR;
-
- /*
- * IXON Flag:
- * Enable XON/XOFF flow control on output.
- * Transmit XON1, XOFF1
- */
- if (termios->c_iflag & IXON)
- efr |= OMAP_UART_SW_TX;
-
- /*
- * IXOFF Flag:
- * Enable XON/XOFF flow control on input.
- * Receiver compares XON1, XOFF1.
- */
- if (termios->c_iflag & IXOFF)
- efr |= OMAP_UART_SW_RX;
-
- serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
- up->mcr = serial_in(up, UART_MCR);
-
- /*
- * IXANY Flag:
- * Enable any character to restart output.
- * Operation resumes after receiving any
- * character after recognition of the XOFF character
- */
- if (termios->c_iflag & IXANY)
- up->mcr |= UART_MCR_XONANY;
-
- serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
- /* Enable special char function UARTi.EFR_REG[5] and
- * load the new software flow control mode IXON or IXOFF
- * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
- */
- serial_out(up, UART_EFR, efr | UART_EFR_SCD);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
- serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
- serial_out(up, UART_LCR, up->lcr);
-}
-
-static void
-serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned char cval = 0;
- unsigned char efr = 0;
- unsigned long flags = 0;
- unsigned int baud, quot;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
- quot = serial_omap_get_divisor(port, baud);
-
- up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
- UART_FCR_ENABLE_FIFO;
- if (up->use_dma)
- up->fcr |= UART_FCR_DMA_SELECT;
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characters to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * Modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
- serial_out(up, UART_LCR, cval); /* reset DLAB */
-
- /* FIFOs and DMA Settings */
-
- /* FCR can be changed only when the
- * baud clock is not running
- * DLL_REG and DLH_REG set to 0.
- */
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_out(up, UART_DLL, 0);
- serial_out(up, UART_DLM, 0);
- serial_out(up, UART_LCR, 0);
-
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- up->efr = serial_in(up, UART_EFR);
- serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
-
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- up->mcr = serial_in(up, UART_MCR);
- serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
- /* FIFO ENABLE, DMA MODE */
- serial_out(up, UART_FCR, up->fcr);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- if (up->use_dma) {
- serial_out(up, UART_TI752_TLR, 0);
- serial_out(up, UART_OMAP_SCR,
- (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8));
- }
-
- serial_out(up, UART_EFR, up->efr);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_out(up, UART_MCR, up->mcr);
-
- /* Protocol, Baud Rate, and Interrupt Settings */
-
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- up->efr = serial_in(up, UART_EFR);
- serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
-
- serial_out(up, UART_LCR, 0);
- serial_out(up, UART_IER, 0);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
- serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
-
- serial_out(up, UART_LCR, 0);
- serial_out(up, UART_IER, up->ier);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- serial_out(up, UART_EFR, up->efr);
- serial_out(up, UART_LCR, cval);
-
- if (baud > 230400 && baud != 3000000)
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE);
- else
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
-
- /* Hardware Flow Control Configuration */
-
- if (termios->c_cflag & CRTSCTS) {
- efr |= (UART_EFR_CTS | UART_EFR_RTS);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
- up->mcr = serial_in(up, UART_MCR);
- serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
-
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- up->efr = serial_in(up, UART_EFR);
- serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
-
- serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
- serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
- serial_out(up, UART_LCR, cval);
- }
-
- serial_omap_set_mctrl(&up->port, up->port.mctrl);
- /* Software Flow Control Configuration */
- if (termios->c_iflag & (IXON | IXOFF))
- serial_omap_configure_xonxoff(up, termios);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
- dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
-}
-
-static void
-serial_omap_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned char efr;
-
- dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- efr = serial_in(up, UART_EFR);
- serial_out(up, UART_EFR, efr | UART_EFR_ECB);
- serial_out(up, UART_LCR, 0);
-
- serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, efr);
- serial_out(up, UART_LCR, 0);
- /* Enable module level wake up */
- serial_out(up, UART_OMAP_WER,
- (state != 0) ? OMAP_UART_WER_MOD_WKUP : 0);
-}
-
-static void serial_omap_release_port(struct uart_port *port)
-{
- dev_dbg(port->dev, "serial_omap_release_port+\n");
-}
-
-static int serial_omap_request_port(struct uart_port *port)
-{
- dev_dbg(port->dev, "serial_omap_request_port+\n");
- return 0;
-}
-
-static void serial_omap_config_port(struct uart_port *port, int flags)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
-
- dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
- up->pdev->id);
- up->port.type = PORT_OMAP;
-}
-
-static int
-serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- /* we don't want the core code to modify any port params */
- dev_dbg(port->dev, "serial_omap_verify_port+\n");
- return -EINVAL;
-}
-
-static const char *
-serial_omap_type(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
-
- dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id);
- return up->name;
-}
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static inline void wait_for_xmitr(struct uart_omap_port *up)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = serial_in(up, UART_LSR);
-
- if (status & UART_LSR_BI)
- up->lsr_break_flag = UART_LSR_BI;
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- for (tmout = 1000000; tmout; tmout--) {
- unsigned int msr = serial_in(up, UART_MSR);
-
- up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
- if (msr & UART_MSR_CTS)
- break;
-
- udelay(1);
- }
- }
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-
-static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- wait_for_xmitr(up);
- serial_out(up, UART_TX, ch);
-}
-
-static int serial_omap_poll_get_char(struct uart_port *port)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned int status = serial_in(up, UART_LSR);
-
- if (!(status & UART_LSR_DR))
- return NO_POLL_CHAR;
-
- return serial_in(up, UART_RX);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-#ifdef CONFIG_SERIAL_OMAP_CONSOLE
-
-static struct uart_omap_port *serial_omap_console_ports[4];
-
-static struct uart_driver serial_omap_reg;
-
-static void serial_omap_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
-
- wait_for_xmitr(up);
- serial_out(up, UART_TX, ch);
-}
-
-static void
-serial_omap_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_omap_port *up = serial_omap_console_ports[co->index];
- unsigned long flags;
- unsigned int ier;
- int locked = 1;
-
- local_irq_save(flags);
- if (up->port.sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = spin_trylock(&up->port.lock);
- else
- spin_lock(&up->port.lock);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
-
- uart_console_write(&up->port, s, count, serial_omap_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- serial_out(up, UART_IER, ier);
- /*
- * The receive handling will happen properly because the
- * receive ready bit will still be set; it is not cleared
- * on read. However, modem control will not, we must
- * call it if we have saved something in the saved flags
- * while processing with interrupts off.
- */
- if (up->msr_saved_flags)
- check_modem_status(up);
-
- if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
-}
-
-static int __init
-serial_omap_console_setup(struct console *co, char *options)
-{
- struct uart_omap_port *up;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (serial_omap_console_ports[co->index] == NULL)
- return -ENODEV;
- up = serial_omap_console_ports[co->index];
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_omap_console = {
- .name = OMAP_SERIAL_NAME,
- .write = serial_omap_console_write,
- .device = uart_console_device,
- .setup = serial_omap_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &serial_omap_reg,
-};
-
-static void serial_omap_add_console_port(struct uart_omap_port *up)
-{
- serial_omap_console_ports[up->pdev->id] = up;
-}
-
-#define OMAP_CONSOLE (&serial_omap_console)
-
-#else
-
-#define OMAP_CONSOLE NULL
-
-static inline void serial_omap_add_console_port(struct uart_omap_port *up)
-{}
-
-#endif
-
-static struct uart_ops serial_omap_pops = {
- .tx_empty = serial_omap_tx_empty,
- .set_mctrl = serial_omap_set_mctrl,
- .get_mctrl = serial_omap_get_mctrl,
- .stop_tx = serial_omap_stop_tx,
- .start_tx = serial_omap_start_tx,
- .stop_rx = serial_omap_stop_rx,
- .enable_ms = serial_omap_enable_ms,
- .break_ctl = serial_omap_break_ctl,
- .startup = serial_omap_startup,
- .shutdown = serial_omap_shutdown,
- .set_termios = serial_omap_set_termios,
- .pm = serial_omap_pm,
- .type = serial_omap_type,
- .release_port = serial_omap_release_port,
- .request_port = serial_omap_request_port,
- .config_port = serial_omap_config_port,
- .verify_port = serial_omap_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_put_char = serial_omap_poll_put_char,
- .poll_get_char = serial_omap_poll_get_char,
-#endif
-};
-
-static struct uart_driver serial_omap_reg = {
- .owner = THIS_MODULE,
- .driver_name = "OMAP-SERIAL",
- .dev_name = OMAP_SERIAL_NAME,
- .nr = OMAP_MAX_HSUART_PORTS,
- .cons = OMAP_CONSOLE,
-};
-
-static int
-serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct uart_omap_port *up = platform_get_drvdata(pdev);
-
- if (up)
- uart_suspend_port(&serial_omap_reg, &up->port);
- return 0;
-}
-
-static int serial_omap_resume(struct platform_device *dev)
-{
- struct uart_omap_port *up = platform_get_drvdata(dev);
-
- if (up)
- uart_resume_port(&serial_omap_reg, &up->port);
- return 0;
-}
-
-static void serial_omap_rx_timeout(unsigned long uart_no)
-{
- struct uart_omap_port *up = ui[uart_no];
- unsigned int curr_dma_pos, curr_transmitted_size;
- int ret = 0;
-
- curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel);
- if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
- (curr_dma_pos == 0)) {
- if (jiffies_to_msecs(jiffies - up->port_activity) <
- RX_TIMEOUT) {
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
- } else {
- serial_omap_stop_rxdma(up);
- up->ier |= (UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- }
- return;
- }
-
- curr_transmitted_size = curr_dma_pos -
- up->uart_dma.prev_rx_dma_pos;
- up->port.icount.rx += curr_transmitted_size;
- tty_insert_flip_string(up->port.state->port.tty,
- up->uart_dma.rx_buf +
- (up->uart_dma.prev_rx_dma_pos -
- up->uart_dma.rx_buf_dma_phys),
- curr_transmitted_size);
- tty_flip_buffer_push(up->port.state->port.tty);
- up->uart_dma.prev_rx_dma_pos = curr_dma_pos;
- if (up->uart_dma.rx_buf_size +
- up->uart_dma.rx_buf_dma_phys == curr_dma_pos) {
- ret = serial_omap_start_rxdma(up);
- if (ret < 0) {
- serial_omap_stop_rxdma(up);
- up->ier |= (UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- }
- } else {
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
- }
- up->port_activity = jiffies;
-}
-
-static void uart_rx_dma_callback(int lch, u16 ch_status, void *data)
-{
- return;
-}
-
-static int serial_omap_start_rxdma(struct uart_omap_port *up)
-{
- int ret = 0;
-
- if (up->uart_dma.rx_dma_channel == -1) {
- ret = omap_request_dma(up->uart_dma.uart_dma_rx,
- "UART Rx DMA",
- (void *)uart_rx_dma_callback, up,
- &(up->uart_dma.rx_dma_channel));
- if (ret < 0)
- return ret;
-
- omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC,
- up->uart_dma.rx_buf_dma_phys, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.rx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_rx, 0);
- }
- up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys;
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.rx_dma_channel);
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
- up->uart_dma.rx_dma_used = true;
- return ret;
-}
-
-static void serial_omap_continue_tx(struct uart_omap_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- unsigned int start = up->uart_dma.tx_buf_dma_phys
- + (xmit->tail & (UART_XMIT_SIZE - 1));
-
- if (uart_circ_empty(xmit))
- return;
-
- up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
- /*
- * It is a circular buffer. See if the buffer has wounded back.
- * If yes it will have to be transferred in two separate dma
- * transfers
- */
- if (start + up->uart_dma.tx_buf_size >=
- up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
- up->uart_dma.tx_buf_size =
- (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start;
- omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC, start, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.tx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_tx, 0);
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.tx_dma_channel);
-}
-
-static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)data;
- struct circ_buf *xmit = &up->port.state->xmit;
-
- xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
- (UART_XMIT_SIZE - 1);
- up->port.icount.tx += up->uart_dma.tx_buf_size;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit)) {
- spin_lock(&(up->uart_dma.tx_lock));
- serial_omap_stop_tx(&up->port);
- up->uart_dma.tx_dma_used = false;
- spin_unlock(&(up->uart_dma.tx_lock));
- } else {
- omap_stop_dma(up->uart_dma.tx_dma_channel);
- serial_omap_continue_tx(up);
- }
- up->port_activity = jiffies;
- return;
-}
-
-static int serial_omap_probe(struct platform_device *pdev)
-{
- struct uart_omap_port *up;
- struct resource *mem, *irq, *dma_tx, *dma_rx;
- struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
- int ret = -ENOSPC;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "no mem resource?\n");
- return -ENODEV;
- }
-
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq) {
- dev_err(&pdev->dev, "no irq resource?\n");
- return -ENODEV;
- }
-
- if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
- pdev->dev.driver->name)) {
- dev_err(&pdev->dev, "memory region already claimed\n");
- return -EBUSY;
- }
-
- dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
- if (!dma_rx) {
- ret = -EINVAL;
- goto err;
- }
-
- dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
- if (!dma_tx) {
- ret = -EINVAL;
- goto err;
- }
-
- up = kzalloc(sizeof(*up), GFP_KERNEL);
- if (up == NULL) {
- ret = -ENOMEM;
- goto do_release_region;
- }
- sprintf(up->name, "OMAP UART%d", pdev->id);
- up->pdev = pdev;
- up->port.dev = &pdev->dev;
- up->port.type = PORT_OMAP;
- up->port.iotype = UPIO_MEM;
- up->port.irq = irq->start;
-
- up->port.regshift = 2;
- up->port.fifosize = 64;
- up->port.ops = &serial_omap_pops;
- up->port.line = pdev->id;
-
- up->port.membase = omap_up_info->membase;
- up->port.mapbase = omap_up_info->mapbase;
- up->port.flags = omap_up_info->flags;
- up->port.irqflags = omap_up_info->irqflags;
- up->port.uartclk = omap_up_info->uartclk;
- up->uart_dma.uart_base = mem->start;
-
- if (omap_up_info->dma_enabled) {
- up->uart_dma.uart_dma_tx = dma_tx->start;
- up->uart_dma.uart_dma_rx = dma_rx->start;
- up->use_dma = 1;
- up->uart_dma.rx_buf_size = 4096;
- up->uart_dma.rx_timeout = 2;
- spin_lock_init(&(up->uart_dma.tx_lock));
- spin_lock_init(&(up->uart_dma.rx_lock));
- up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
- up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
- }
-
- ui[pdev->id] = up;
- serial_omap_add_console_port(up);
-
- ret = uart_add_one_port(&serial_omap_reg, &up->port);
- if (ret != 0)
- goto do_release_region;
-
- platform_set_drvdata(pdev, up);
- return 0;
-err:
- dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
- pdev->id, __func__, ret);
-do_release_region:
- release_mem_region(mem->start, (mem->end - mem->start) + 1);
- return ret;
-}
-
-static int serial_omap_remove(struct platform_device *dev)
-{
- struct uart_omap_port *up = platform_get_drvdata(dev);
-
- platform_set_drvdata(dev, NULL);
- if (up) {
- uart_remove_one_port(&serial_omap_reg, &up->port);
- kfree(up);
- }
- return 0;
-}
-
-static struct platform_driver serial_omap_driver = {
- .probe = serial_omap_probe,
- .remove = serial_omap_remove,
-
- .suspend = serial_omap_suspend,
- .resume = serial_omap_resume,
- .driver = {
- .name = DRIVER_NAME,
- },
-};
-
-static int __init serial_omap_init(void)
-{
- int ret;
-
- ret = uart_register_driver(&serial_omap_reg);
- if (ret != 0)
- return ret;
- ret = platform_driver_register(&serial_omap_driver);
- if (ret != 0)
- uart_unregister_driver(&serial_omap_reg);
- return ret;
-}
-
-static void __exit serial_omap_exit(void)
-{
- platform_driver_unregister(&serial_omap_driver);
- uart_unregister_driver(&serial_omap_reg);
-}
-
-module_init(serial_omap_init);
-module_exit(serial_omap_exit);
-
-MODULE_DESCRIPTION("OMAP High Speed UART driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/serial/pch_uart.c b/drivers/serial/pch_uart.c
deleted file mode 100644
index 70a61458ec42..000000000000
--- a/drivers/serial/pch_uart.c
+++ /dev/null
@@ -1,1451 +0,0 @@
-/*
- *Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
- *
- *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; version 2 of the License.
- *
- *This program is distributed in the hope that it will be useful,
- *but WITHOUT ANY WARRANTY; without even the implied warranty of
- *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *GNU General Public License for more details.
- *
- *You should have received a copy of the GNU General Public License
- *along with this program; if not, write to the Free Software
- *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <linux/serial_reg.h>
-#include <linux/pci.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/serial_core.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <linux/dmaengine.h>
-#include <linux/pch_dma.h>
-
-enum {
- PCH_UART_HANDLED_RX_INT_SHIFT,
- PCH_UART_HANDLED_TX_INT_SHIFT,
- PCH_UART_HANDLED_RX_ERR_INT_SHIFT,
- PCH_UART_HANDLED_RX_TRG_INT_SHIFT,
- PCH_UART_HANDLED_MS_INT_SHIFT,
-};
-
-enum {
- PCH_UART_8LINE,
- PCH_UART_2LINE,
-};
-
-#define PCH_UART_DRIVER_DEVICE "ttyPCH"
-
-#define PCH_UART_NR_GE_256FIFO 1
-#define PCH_UART_NR_GE_64FIFO 3
-#define PCH_UART_NR_GE (PCH_UART_NR_GE_256FIFO+PCH_UART_NR_GE_64FIFO)
-#define PCH_UART_NR PCH_UART_NR_GE
-
-#define PCH_UART_HANDLED_RX_INT (1<<((PCH_UART_HANDLED_RX_INT_SHIFT)<<1))
-#define PCH_UART_HANDLED_TX_INT (1<<((PCH_UART_HANDLED_TX_INT_SHIFT)<<1))
-#define PCH_UART_HANDLED_RX_ERR_INT (1<<((\
- PCH_UART_HANDLED_RX_ERR_INT_SHIFT)<<1))
-#define PCH_UART_HANDLED_RX_TRG_INT (1<<((\
- PCH_UART_HANDLED_RX_TRG_INT_SHIFT)<<1))
-#define PCH_UART_HANDLED_MS_INT (1<<((PCH_UART_HANDLED_MS_INT_SHIFT)<<1))
-
-#define PCH_UART_RBR 0x00
-#define PCH_UART_THR 0x00
-
-#define PCH_UART_IER_MASK (PCH_UART_IER_ERBFI|PCH_UART_IER_ETBEI|\
- PCH_UART_IER_ELSI|PCH_UART_IER_EDSSI)
-#define PCH_UART_IER_ERBFI 0x00000001
-#define PCH_UART_IER_ETBEI 0x00000002
-#define PCH_UART_IER_ELSI 0x00000004
-#define PCH_UART_IER_EDSSI 0x00000008
-
-#define PCH_UART_IIR_IP 0x00000001
-#define PCH_UART_IIR_IID 0x00000006
-#define PCH_UART_IIR_MSI 0x00000000
-#define PCH_UART_IIR_TRI 0x00000002
-#define PCH_UART_IIR_RRI 0x00000004
-#define PCH_UART_IIR_REI 0x00000006
-#define PCH_UART_IIR_TOI 0x00000008
-#define PCH_UART_IIR_FIFO256 0x00000020
-#define PCH_UART_IIR_FIFO64 PCH_UART_IIR_FIFO256
-#define PCH_UART_IIR_FE 0x000000C0
-
-#define PCH_UART_FCR_FIFOE 0x00000001
-#define PCH_UART_FCR_RFR 0x00000002
-#define PCH_UART_FCR_TFR 0x00000004
-#define PCH_UART_FCR_DMS 0x00000008
-#define PCH_UART_FCR_FIFO256 0x00000020
-#define PCH_UART_FCR_RFTL 0x000000C0
-
-#define PCH_UART_FCR_RFTL1 0x00000000
-#define PCH_UART_FCR_RFTL64 0x00000040
-#define PCH_UART_FCR_RFTL128 0x00000080
-#define PCH_UART_FCR_RFTL224 0x000000C0
-#define PCH_UART_FCR_RFTL16 PCH_UART_FCR_RFTL64
-#define PCH_UART_FCR_RFTL32 PCH_UART_FCR_RFTL128
-#define PCH_UART_FCR_RFTL56 PCH_UART_FCR_RFTL224
-#define PCH_UART_FCR_RFTL4 PCH_UART_FCR_RFTL64
-#define PCH_UART_FCR_RFTL8 PCH_UART_FCR_RFTL128
-#define PCH_UART_FCR_RFTL14 PCH_UART_FCR_RFTL224
-#define PCH_UART_FCR_RFTL_SHIFT 6
-
-#define PCH_UART_LCR_WLS 0x00000003
-#define PCH_UART_LCR_STB 0x00000004
-#define PCH_UART_LCR_PEN 0x00000008
-#define PCH_UART_LCR_EPS 0x00000010
-#define PCH_UART_LCR_SP 0x00000020
-#define PCH_UART_LCR_SB 0x00000040
-#define PCH_UART_LCR_DLAB 0x00000080
-#define PCH_UART_LCR_NP 0x00000000
-#define PCH_UART_LCR_OP PCH_UART_LCR_PEN
-#define PCH_UART_LCR_EP (PCH_UART_LCR_PEN | PCH_UART_LCR_EPS)
-#define PCH_UART_LCR_1P (PCH_UART_LCR_PEN | PCH_UART_LCR_SP)
-#define PCH_UART_LCR_0P (PCH_UART_LCR_PEN | PCH_UART_LCR_EPS |\
- PCH_UART_LCR_SP)
-
-#define PCH_UART_LCR_5BIT 0x00000000
-#define PCH_UART_LCR_6BIT 0x00000001
-#define PCH_UART_LCR_7BIT 0x00000002
-#define PCH_UART_LCR_8BIT 0x00000003
-
-#define PCH_UART_MCR_DTR 0x00000001
-#define PCH_UART_MCR_RTS 0x00000002
-#define PCH_UART_MCR_OUT 0x0000000C
-#define PCH_UART_MCR_LOOP 0x00000010
-#define PCH_UART_MCR_AFE 0x00000020
-
-#define PCH_UART_LSR_DR 0x00000001
-#define PCH_UART_LSR_ERR (1<<7)
-
-#define PCH_UART_MSR_DCTS 0x00000001
-#define PCH_UART_MSR_DDSR 0x00000002
-#define PCH_UART_MSR_TERI 0x00000004
-#define PCH_UART_MSR_DDCD 0x00000008
-#define PCH_UART_MSR_CTS 0x00000010
-#define PCH_UART_MSR_DSR 0x00000020
-#define PCH_UART_MSR_RI 0x00000040
-#define PCH_UART_MSR_DCD 0x00000080
-#define PCH_UART_MSR_DELTA (PCH_UART_MSR_DCTS | PCH_UART_MSR_DDSR |\
- PCH_UART_MSR_TERI | PCH_UART_MSR_DDCD)
-
-#define PCH_UART_DLL 0x00
-#define PCH_UART_DLM 0x01
-
-#define DIV_ROUND(a, b) (((a) + ((b)/2)) / (b))
-
-#define PCH_UART_IID_RLS (PCH_UART_IIR_REI)
-#define PCH_UART_IID_RDR (PCH_UART_IIR_RRI)
-#define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI)
-#define PCH_UART_IID_THRE (PCH_UART_IIR_TRI)
-#define PCH_UART_IID_MS (PCH_UART_IIR_MSI)
-
-#define PCH_UART_HAL_PARITY_NONE (PCH_UART_LCR_NP)
-#define PCH_UART_HAL_PARITY_ODD (PCH_UART_LCR_OP)
-#define PCH_UART_HAL_PARITY_EVEN (PCH_UART_LCR_EP)
-#define PCH_UART_HAL_PARITY_FIX1 (PCH_UART_LCR_1P)
-#define PCH_UART_HAL_PARITY_FIX0 (PCH_UART_LCR_0P)
-#define PCH_UART_HAL_5BIT (PCH_UART_LCR_5BIT)
-#define PCH_UART_HAL_6BIT (PCH_UART_LCR_6BIT)
-#define PCH_UART_HAL_7BIT (PCH_UART_LCR_7BIT)
-#define PCH_UART_HAL_8BIT (PCH_UART_LCR_8BIT)
-#define PCH_UART_HAL_STB1 0
-#define PCH_UART_HAL_STB2 (PCH_UART_LCR_STB)
-
-#define PCH_UART_HAL_CLR_TX_FIFO (PCH_UART_FCR_TFR)
-#define PCH_UART_HAL_CLR_RX_FIFO (PCH_UART_FCR_RFR)
-#define PCH_UART_HAL_CLR_ALL_FIFO (PCH_UART_HAL_CLR_TX_FIFO | \
- PCH_UART_HAL_CLR_RX_FIFO)
-
-#define PCH_UART_HAL_DMA_MODE0 0
-#define PCH_UART_HAL_FIFO_DIS 0
-#define PCH_UART_HAL_FIFO16 (PCH_UART_FCR_FIFOE)
-#define PCH_UART_HAL_FIFO256 (PCH_UART_FCR_FIFOE | \
- PCH_UART_FCR_FIFO256)
-#define PCH_UART_HAL_FIFO64 (PCH_UART_HAL_FIFO256)
-#define PCH_UART_HAL_TRIGGER1 (PCH_UART_FCR_RFTL1)
-#define PCH_UART_HAL_TRIGGER64 (PCH_UART_FCR_RFTL64)
-#define PCH_UART_HAL_TRIGGER128 (PCH_UART_FCR_RFTL128)
-#define PCH_UART_HAL_TRIGGER224 (PCH_UART_FCR_RFTL224)
-#define PCH_UART_HAL_TRIGGER16 (PCH_UART_FCR_RFTL16)
-#define PCH_UART_HAL_TRIGGER32 (PCH_UART_FCR_RFTL32)
-#define PCH_UART_HAL_TRIGGER56 (PCH_UART_FCR_RFTL56)
-#define PCH_UART_HAL_TRIGGER4 (PCH_UART_FCR_RFTL4)
-#define PCH_UART_HAL_TRIGGER8 (PCH_UART_FCR_RFTL8)
-#define PCH_UART_HAL_TRIGGER14 (PCH_UART_FCR_RFTL14)
-#define PCH_UART_HAL_TRIGGER_L (PCH_UART_FCR_RFTL64)
-#define PCH_UART_HAL_TRIGGER_M (PCH_UART_FCR_RFTL128)
-#define PCH_UART_HAL_TRIGGER_H (PCH_UART_FCR_RFTL224)
-
-#define PCH_UART_HAL_RX_INT (PCH_UART_IER_ERBFI)
-#define PCH_UART_HAL_TX_INT (PCH_UART_IER_ETBEI)
-#define PCH_UART_HAL_RX_ERR_INT (PCH_UART_IER_ELSI)
-#define PCH_UART_HAL_MS_INT (PCH_UART_IER_EDSSI)
-#define PCH_UART_HAL_ALL_INT (PCH_UART_IER_MASK)
-
-#define PCH_UART_HAL_DTR (PCH_UART_MCR_DTR)
-#define PCH_UART_HAL_RTS (PCH_UART_MCR_RTS)
-#define PCH_UART_HAL_OUT (PCH_UART_MCR_OUT)
-#define PCH_UART_HAL_LOOP (PCH_UART_MCR_LOOP)
-#define PCH_UART_HAL_AFE (PCH_UART_MCR_AFE)
-
-struct pch_uart_buffer {
- unsigned char *buf;
- int size;
-};
-
-struct eg20t_port {
- struct uart_port port;
- int port_type;
- void __iomem *membase;
- resource_size_t mapbase;
- unsigned int iobase;
- struct pci_dev *pdev;
- int fifo_size;
- int base_baud;
- int start_tx;
- int start_rx;
- int tx_empty;
- int int_dis_flag;
- int trigger;
- int trigger_level;
- struct pch_uart_buffer rxbuf;
- unsigned int dmsr;
- unsigned int fcr;
- unsigned int use_dma;
- unsigned int use_dma_flag;
- struct dma_async_tx_descriptor *desc_tx;
- struct dma_async_tx_descriptor *desc_rx;
- struct pch_dma_slave param_tx;
- struct pch_dma_slave param_rx;
- struct dma_chan *chan_tx;
- struct dma_chan *chan_rx;
- struct scatterlist sg_tx;
- struct scatterlist sg_rx;
- int tx_dma_use;
- void *rx_buf_virt;
- dma_addr_t rx_buf_dma;
-};
-
-static unsigned int default_baud = 9600;
-static const int trigger_level_256[4] = { 1, 64, 128, 224 };
-static const int trigger_level_64[4] = { 1, 16, 32, 56 };
-static const int trigger_level_16[4] = { 1, 4, 8, 14 };
-static const int trigger_level_1[4] = { 1, 1, 1, 1 };
-
-static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize,
- int base_baud)
-{
- struct eg20t_port *priv = pci_get_drvdata(pdev);
-
- priv->trigger_level = 1;
- priv->fcr = 0;
-}
-
-static unsigned int get_msr(struct eg20t_port *priv, void __iomem *base)
-{
- unsigned int msr = ioread8(base + UART_MSR);
- priv->dmsr |= msr & PCH_UART_MSR_DELTA;
-
- return msr;
-}
-
-static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv,
- unsigned int flag)
-{
- u8 ier = ioread8(priv->membase + UART_IER);
- ier |= flag & PCH_UART_IER_MASK;
- iowrite8(ier, priv->membase + UART_IER);
-}
-
-static void pch_uart_hal_disable_interrupt(struct eg20t_port *priv,
- unsigned int flag)
-{
- u8 ier = ioread8(priv->membase + UART_IER);
- ier &= ~(flag & PCH_UART_IER_MASK);
- iowrite8(ier, priv->membase + UART_IER);
-}
-
-static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
- unsigned int parity, unsigned int bits,
- unsigned int stb)
-{
- unsigned int dll, dlm, lcr;
- int div;
-
- div = DIV_ROUND(priv->base_baud / 16, baud);
- if (div < 0 || USHRT_MAX <= div) {
- pr_err("Invalid Baud(div=0x%x)\n", div);
- return -EINVAL;
- }
-
- dll = (unsigned int)div & 0x00FFU;
- dlm = ((unsigned int)div >> 8) & 0x00FFU;
-
- if (parity & ~(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS | PCH_UART_LCR_SP)) {
- pr_err("Invalid parity(0x%x)\n", parity);
- return -EINVAL;
- }
-
- if (bits & ~PCH_UART_LCR_WLS) {
- pr_err("Invalid bits(0x%x)\n", bits);
- return -EINVAL;
- }
-
- if (stb & ~PCH_UART_LCR_STB) {
- pr_err("Invalid STB(0x%x)\n", stb);
- return -EINVAL;
- }
-
- lcr = parity;
- lcr |= bits;
- lcr |= stb;
-
- pr_debug("%s:baud = %d, div = %04x, lcr = %02x (%lu)\n",
- __func__, baud, div, lcr, jiffies);
- iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
- iowrite8(dll, priv->membase + PCH_UART_DLL);
- iowrite8(dlm, priv->membase + PCH_UART_DLM);
- iowrite8(lcr, priv->membase + UART_LCR);
-
- return 0;
-}
-
-static int pch_uart_hal_fifo_reset(struct eg20t_port *priv,
- unsigned int flag)
-{
- if (flag & ~(PCH_UART_FCR_TFR | PCH_UART_FCR_RFR)) {
- pr_err("%s:Invalid flag(0x%x)\n", __func__, flag);
- return -EINVAL;
- }
-
- iowrite8(PCH_UART_FCR_FIFOE | priv->fcr, priv->membase + UART_FCR);
- iowrite8(PCH_UART_FCR_FIFOE | priv->fcr | flag,
- priv->membase + UART_FCR);
- iowrite8(priv->fcr, priv->membase + UART_FCR);
-
- return 0;
-}
-
-static int pch_uart_hal_set_fifo(struct eg20t_port *priv,
- unsigned int dmamode,
- unsigned int fifo_size, unsigned int trigger)
-{
- u8 fcr;
-
- if (dmamode & ~PCH_UART_FCR_DMS) {
- pr_err("%s:Invalid DMA Mode(0x%x)\n", __func__, dmamode);
- return -EINVAL;
- }
-
- if (fifo_size & ~(PCH_UART_FCR_FIFOE | PCH_UART_FCR_FIFO256)) {
- pr_err("%s:Invalid FIFO SIZE(0x%x)\n", __func__, fifo_size);
- return -EINVAL;
- }
-
- if (trigger & ~PCH_UART_FCR_RFTL) {
- pr_err("%s:Invalid TRIGGER(0x%x)\n", __func__, trigger);
- return -EINVAL;
- }
-
- switch (priv->fifo_size) {
- case 256:
- priv->trigger_level =
- trigger_level_256[trigger >> PCH_UART_FCR_RFTL_SHIFT];
- break;
- case 64:
- priv->trigger_level =
- trigger_level_64[trigger >> PCH_UART_FCR_RFTL_SHIFT];
- break;
- case 16:
- priv->trigger_level =
- trigger_level_16[trigger >> PCH_UART_FCR_RFTL_SHIFT];
- break;
- default:
- priv->trigger_level =
- trigger_level_1[trigger >> PCH_UART_FCR_RFTL_SHIFT];
- break;
- }
- fcr =
- dmamode | fifo_size | trigger | PCH_UART_FCR_RFR | PCH_UART_FCR_TFR;
- iowrite8(PCH_UART_FCR_FIFOE, priv->membase + UART_FCR);
- iowrite8(PCH_UART_FCR_FIFOE | PCH_UART_FCR_RFR | PCH_UART_FCR_TFR,
- priv->membase + UART_FCR);
- iowrite8(fcr, priv->membase + UART_FCR);
- priv->fcr = fcr;
-
- return 0;
-}
-
-static u8 pch_uart_hal_get_modem(struct eg20t_port *priv)
-{
- priv->dmsr = 0;
- return get_msr(priv, priv->membase);
-}
-
-static int pch_uart_hal_write(struct eg20t_port *priv,
- const unsigned char *buf, int tx_size)
-{
- int i;
- unsigned int thr;
-
- for (i = 0; i < tx_size;) {
- thr = buf[i++];
- iowrite8(thr, priv->membase + PCH_UART_THR);
- }
- return i;
-}
-
-static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
- int rx_size)
-{
- int i;
- u8 rbr, lsr;
-
- lsr = ioread8(priv->membase + UART_LSR);
- for (i = 0, lsr = ioread8(priv->membase + UART_LSR);
- i < rx_size && lsr & UART_LSR_DR;
- lsr = ioread8(priv->membase + UART_LSR)) {
- rbr = ioread8(priv->membase + PCH_UART_RBR);
- buf[i++] = rbr;
- }
- return i;
-}
-
-static unsigned int pch_uart_hal_get_iid(struct eg20t_port *priv)
-{
- unsigned int iir;
- int ret;
-
- iir = ioread8(priv->membase + UART_IIR);
- ret = (iir & (PCH_UART_IIR_IID | PCH_UART_IIR_TOI | PCH_UART_IIR_IP));
- return ret;
-}
-
-static u8 pch_uart_hal_get_line_status(struct eg20t_port *priv)
-{
- return ioread8(priv->membase + UART_LSR);
-}
-
-static void pch_uart_hal_set_break(struct eg20t_port *priv, int on)
-{
- unsigned int lcr;
-
- lcr = ioread8(priv->membase + UART_LCR);
- if (on)
- lcr |= PCH_UART_LCR_SB;
- else
- lcr &= ~PCH_UART_LCR_SB;
-
- iowrite8(lcr, priv->membase + UART_LCR);
-}
-
-static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
- int size)
-{
- struct uart_port *port;
- struct tty_struct *tty;
-
- port = &priv->port;
- tty = tty_port_tty_get(&port->state->port);
- if (!tty) {
- pr_debug("%s:tty is busy now", __func__);
- return -EBUSY;
- }
-
- tty_insert_flip_string(tty, buf, size);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
-
- return 0;
-}
-
-static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
-{
- int ret;
- struct uart_port *port = &priv->port;
-
- if (port->x_char) {
- pr_debug("%s:X character send %02x (%lu)\n", __func__,
- port->x_char, jiffies);
- buf[0] = port->x_char;
- port->x_char = 0;
- ret = 1;
- } else {
- ret = 0;
- }
-
- return ret;
-}
-
-static int dma_push_rx(struct eg20t_port *priv, int size)
-{
- struct tty_struct *tty;
- int room;
- struct uart_port *port = &priv->port;
-
- port = &priv->port;
- tty = tty_port_tty_get(&port->state->port);
- if (!tty) {
- pr_debug("%s:tty is busy now", __func__);
- return 0;
- }
-
- room = tty_buffer_request_room(tty, size);
-
- if (room < size)
- dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
- size - room);
- if (!room)
- return room;
-
- tty_insert_flip_string(tty, sg_virt(&priv->sg_rx), size);
-
- port->icount.rx += room;
- tty_kref_put(tty);
-
- return room;
-}
-
-static void pch_free_dma(struct uart_port *port)
-{
- struct eg20t_port *priv;
- priv = container_of(port, struct eg20t_port, port);
-
- if (priv->chan_tx) {
- dma_release_channel(priv->chan_tx);
- priv->chan_tx = NULL;
- }
- if (priv->chan_rx) {
- dma_release_channel(priv->chan_rx);
- priv->chan_rx = NULL;
- }
- if (sg_dma_address(&priv->sg_rx))
- dma_free_coherent(port->dev, port->fifosize,
- sg_virt(&priv->sg_rx),
- sg_dma_address(&priv->sg_rx));
-
- return;
-}
-
-static bool filter(struct dma_chan *chan, void *slave)
-{
- struct pch_dma_slave *param = slave;
-
- if ((chan->chan_id == param->chan_id) && (param->dma_dev ==
- chan->device->dev)) {
- chan->private = param;
- return true;
- } else {
- return false;
- }
-}
-
-static void pch_request_dma(struct uart_port *port)
-{
- dma_cap_mask_t mask;
- struct dma_chan *chan;
- struct pci_dev *dma_dev;
- struct pch_dma_slave *param;
- struct eg20t_port *priv =
- container_of(port, struct eg20t_port, port);
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(0xa, 0)); /* Get DMA's dev
- information */
- /* Set Tx DMA */
- param = &priv->param_tx;
- param->dma_dev = &dma_dev->dev;
- param->chan_id = priv->port.line;
- param->tx_reg = port->mapbase + UART_TX;
- chan = dma_request_channel(mask, filter, param);
- if (!chan) {
- pr_err("%s:dma_request_channel FAILS(Tx)\n", __func__);
- return;
- }
- priv->chan_tx = chan;
-
- /* Set Rx DMA */
- param = &priv->param_rx;
- param->dma_dev = &dma_dev->dev;
- param->chan_id = priv->port.line + 1; /* Rx = Tx + 1 */
- param->rx_reg = port->mapbase + UART_RX;
- chan = dma_request_channel(mask, filter, param);
- if (!chan) {
- pr_err("%s:dma_request_channel FAILS(Rx)\n", __func__);
- dma_release_channel(priv->chan_tx);
- return;
- }
-
- /* Get Consistent memory for DMA */
- priv->rx_buf_virt = dma_alloc_coherent(port->dev, port->fifosize,
- &priv->rx_buf_dma, GFP_KERNEL);
- priv->chan_rx = chan;
-}
-
-static void pch_dma_rx_complete(void *arg)
-{
- struct eg20t_port *priv = arg;
- struct uart_port *port = &priv->port;
- struct tty_struct *tty = tty_port_tty_get(&port->state->port);
-
- if (!tty) {
- pr_debug("%s:tty is busy now", __func__);
- return;
- }
-
- if (dma_push_rx(priv, priv->trigger_level))
- tty_flip_buffer_push(tty);
-
- tty_kref_put(tty);
-}
-
-static void pch_dma_tx_complete(void *arg)
-{
- struct eg20t_port *priv = arg;
- struct uart_port *port = &priv->port;
- struct circ_buf *xmit = &port->state->xmit;
-
- xmit->tail += sg_dma_len(&priv->sg_tx);
- xmit->tail &= UART_XMIT_SIZE - 1;
- port->icount.tx += sg_dma_len(&priv->sg_tx);
-
- async_tx_ack(priv->desc_tx);
- priv->tx_dma_use = 0;
-}
-
-static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size)
-{
- int count = 0;
- struct uart_port *port = &priv->port;
- struct circ_buf *xmit = &port->state->xmit;
-
- if (uart_tx_stopped(port) || uart_circ_empty(xmit) || count >= size)
- goto pop_tx_end;
-
- do {
- int cnt_to_end =
- CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- int sz = min(size - count, cnt_to_end);
- memcpy(&buf[count], &xmit->buf[xmit->tail], sz);
- xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1);
- count += sz;
- } while (!uart_circ_empty(xmit) && count < size);
-
-pop_tx_end:
- pr_debug("%d characters. Remained %d characters. (%lu)\n",
- count, size - count, jiffies);
-
- return count;
-}
-
-static int handle_rx_to(struct eg20t_port *priv)
-{
- struct pch_uart_buffer *buf;
- int rx_size;
- int ret;
- if (!priv->start_rx) {
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
- return 0;
- }
- buf = &priv->rxbuf;
- do {
- rx_size = pch_uart_hal_read(priv, buf->buf, buf->size);
- ret = push_rx(priv, buf->buf, rx_size);
- if (ret)
- return 0;
- } while (rx_size == buf->size);
-
- return PCH_UART_HANDLED_RX_INT;
-}
-
-static int handle_rx(struct eg20t_port *priv)
-{
- return handle_rx_to(priv);
-}
-
-static int dma_handle_rx(struct eg20t_port *priv)
-{
- struct uart_port *port = &priv->port;
- struct dma_async_tx_descriptor *desc;
- struct scatterlist *sg;
-
- priv = container_of(port, struct eg20t_port, port);
- sg = &priv->sg_rx;
-
- sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */
-
- sg_dma_len(sg) = priv->fifo_size;
-
- sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt),
- sg_dma_len(sg), (unsigned long)priv->rx_buf_virt &
- ~PAGE_MASK);
-
- sg_dma_address(sg) = priv->rx_buf_dma;
-
- desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx,
- sg, 1, DMA_FROM_DEVICE,
- DMA_PREP_INTERRUPT);
- if (!desc)
- return 0;
-
- priv->desc_rx = desc;
- desc->callback = pch_dma_rx_complete;
- desc->callback_param = priv;
- desc->tx_submit(desc);
- dma_async_issue_pending(priv->chan_rx);
-
- return PCH_UART_HANDLED_RX_INT;
-}
-
-static unsigned int handle_tx(struct eg20t_port *priv)
-{
- struct uart_port *port = &priv->port;
- struct circ_buf *xmit = &port->state->xmit;
- int ret;
- int fifo_size;
- int tx_size;
- int size;
- int tx_empty;
-
- if (!priv->start_tx) {
- pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies);
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
- priv->tx_empty = 1;
- return 0;
- }
-
- fifo_size = max(priv->fifo_size, 1);
- tx_empty = 1;
- if (pop_tx_x(priv, xmit->buf)) {
- pch_uart_hal_write(priv, xmit->buf, 1);
- port->icount.tx++;
- tx_empty = 0;
- fifo_size--;
- }
- size = min(xmit->head - xmit->tail, fifo_size);
- tx_size = pop_tx(priv, xmit->buf, size);
- if (tx_size > 0) {
- ret = pch_uart_hal_write(priv, xmit->buf, tx_size);
- port->icount.tx += ret;
- tx_empty = 0;
- }
-
- priv->tx_empty = tx_empty;
-
- if (tx_empty)
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
-
- return PCH_UART_HANDLED_TX_INT;
-}
-
-static unsigned int dma_handle_tx(struct eg20t_port *priv)
-{
- struct uart_port *port = &priv->port;
- struct circ_buf *xmit = &port->state->xmit;
- struct scatterlist *sg = &priv->sg_tx;
- int nent;
- int fifo_size;
- int tx_empty;
- struct dma_async_tx_descriptor *desc;
-
- if (!priv->start_tx) {
- pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies);
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
- priv->tx_empty = 1;
- return 0;
- }
-
- fifo_size = max(priv->fifo_size, 1);
- tx_empty = 1;
- if (pop_tx_x(priv, xmit->buf)) {
- pch_uart_hal_write(priv, xmit->buf, 1);
- port->icount.tx++;
- tx_empty = 0;
- fifo_size--;
- }
-
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
-
- priv->tx_dma_use = 1;
-
- sg_init_table(&priv->sg_tx, 1); /* Initialize SG table */
-
- sg_set_page(&priv->sg_tx, virt_to_page(xmit->buf),
- UART_XMIT_SIZE, (int)xmit->buf & ~PAGE_MASK);
-
- nent = dma_map_sg(port->dev, &priv->sg_tx, 1, DMA_TO_DEVICE);
- if (!nent) {
- pr_err("%s:dma_map_sg Failed\n", __func__);
- return 0;
- }
-
- sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
- sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
- sg->offset;
- sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail,
- UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
- xmit->tail, UART_XMIT_SIZE));
-
- desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx,
- sg, nent, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- pr_err("%s:device_prep_slave_sg Failed\n", __func__);
- return 0;
- }
-
- dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
-
- priv->desc_tx = desc;
- desc->callback = pch_dma_tx_complete;
- desc->callback_param = priv;
-
- desc->tx_submit(desc);
-
- dma_async_issue_pending(priv->chan_tx);
-
- return PCH_UART_HANDLED_TX_INT;
-}
-
-static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
-{
- u8 fcr = ioread8(priv->membase + UART_FCR);
-
- /* Reset FIFO */
- fcr |= UART_FCR_CLEAR_RCVR;
- iowrite8(fcr, priv->membase + UART_FCR);
-
- if (lsr & PCH_UART_LSR_ERR)
- dev_err(&priv->pdev->dev, "Error data in FIFO\n");
-
- if (lsr & UART_LSR_FE)
- dev_err(&priv->pdev->dev, "Framing Error\n");
-
- if (lsr & UART_LSR_PE)
- dev_err(&priv->pdev->dev, "Parity Error\n");
-
- if (lsr & UART_LSR_OE)
- dev_err(&priv->pdev->dev, "Overrun Error\n");
-}
-
-static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
-{
- struct eg20t_port *priv = dev_id;
- unsigned int handled;
- u8 lsr;
- int ret = 0;
- unsigned int iid;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->port.lock, flags);
- handled = 0;
- while ((iid = pch_uart_hal_get_iid(priv)) > 1) {
- switch (iid) {
- case PCH_UART_IID_RLS: /* Receiver Line Status */
- lsr = pch_uart_hal_get_line_status(priv);
- if (lsr & (PCH_UART_LSR_ERR | UART_LSR_FE |
- UART_LSR_PE | UART_LSR_OE)) {
- pch_uart_err_ir(priv, lsr);
- ret = PCH_UART_HANDLED_RX_ERR_INT;
- }
- break;
- case PCH_UART_IID_RDR: /* Received Data Ready */
- if (priv->use_dma)
- ret = dma_handle_rx(priv);
- else
- ret = handle_rx(priv);
- break;
- case PCH_UART_IID_RDR_TO: /* Received Data Ready
- (FIFO Timeout) */
- ret = handle_rx_to(priv);
- break;
- case PCH_UART_IID_THRE: /* Transmitter Holding Register
- Empty */
- if (priv->use_dma)
- ret = dma_handle_tx(priv);
- else
- ret = handle_tx(priv);
- break;
- case PCH_UART_IID_MS: /* Modem Status */
- ret = PCH_UART_HANDLED_MS_INT;
- break;
- default: /* Never junp to this label */
- pr_err("%s:iid=%d (%lu)\n", __func__, iid, jiffies);
- ret = -1;
- break;
- }
- handled |= (unsigned int)ret;
- }
- if (handled == 0 && iid <= 1) {
- if (priv->int_dis_flag)
- priv->int_dis_flag = 0;
- }
-
- spin_unlock_irqrestore(&priv->port.lock, flags);
- return IRQ_RETVAL(handled);
-}
-
-/* This function tests whether the transmitter fifo and shifter for the port
- described by 'port' is empty. */
-static unsigned int pch_uart_tx_empty(struct uart_port *port)
-{
- struct eg20t_port *priv;
- int ret;
- priv = container_of(port, struct eg20t_port, port);
- if (priv->tx_empty)
- ret = TIOCSER_TEMT;
- else
- ret = 0;
-
- return ret;
-}
-
-/* Returns the current state of modem control inputs. */
-static unsigned int pch_uart_get_mctrl(struct uart_port *port)
-{
- struct eg20t_port *priv;
- u8 modem;
- unsigned int ret = 0;
-
- priv = container_of(port, struct eg20t_port, port);
- modem = pch_uart_hal_get_modem(priv);
-
- if (modem & UART_MSR_DCD)
- ret |= TIOCM_CAR;
-
- if (modem & UART_MSR_RI)
- ret |= TIOCM_RNG;
-
- if (modem & UART_MSR_DSR)
- ret |= TIOCM_DSR;
-
- if (modem & UART_MSR_CTS)
- ret |= TIOCM_CTS;
-
- return ret;
-}
-
-static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- u32 mcr = 0;
- unsigned int dat;
- struct eg20t_port *priv = container_of(port, struct eg20t_port, port);
-
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- if (mctrl) {
- dat = pch_uart_get_mctrl(port);
- dat |= mcr;
- iowrite8(dat, priv->membase + UART_MCR);
- }
-}
-
-static void pch_uart_stop_tx(struct uart_port *port)
-{
- struct eg20t_port *priv;
- priv = container_of(port, struct eg20t_port, port);
- priv->start_tx = 0;
- priv->tx_dma_use = 0;
-}
-
-static void pch_uart_start_tx(struct uart_port *port)
-{
- struct eg20t_port *priv;
-
- priv = container_of(port, struct eg20t_port, port);
-
- if (priv->use_dma)
- if (priv->tx_dma_use)
- return;
-
- priv->start_tx = 1;
- pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
-}
-
-static void pch_uart_stop_rx(struct uart_port *port)
-{
- struct eg20t_port *priv;
- priv = container_of(port, struct eg20t_port, port);
- priv->start_rx = 0;
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
- priv->int_dis_flag = 1;
-}
-
-/* Enable the modem status interrupts. */
-static void pch_uart_enable_ms(struct uart_port *port)
-{
- struct eg20t_port *priv;
- priv = container_of(port, struct eg20t_port, port);
- pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_MS_INT);
-}
-
-/* Control the transmission of a break signal. */
-static void pch_uart_break_ctl(struct uart_port *port, int ctl)
-{
- struct eg20t_port *priv;
- unsigned long flags;
-
- priv = container_of(port, struct eg20t_port, port);
- spin_lock_irqsave(&port->lock, flags);
- pch_uart_hal_set_break(priv, ctl);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/* Grab any interrupt resources and initialise any low level driver state. */
-static int pch_uart_startup(struct uart_port *port)
-{
- struct eg20t_port *priv;
- int ret;
- int fifo_size;
- int trigger_level;
-
- priv = container_of(port, struct eg20t_port, port);
- priv->tx_empty = 1;
- port->uartclk = priv->base_baud;
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
- ret = pch_uart_hal_set_line(priv, default_baud,
- PCH_UART_HAL_PARITY_NONE, PCH_UART_HAL_8BIT,
- PCH_UART_HAL_STB1);
- if (ret)
- return ret;
-
- switch (priv->fifo_size) {
- case 256:
- fifo_size = PCH_UART_HAL_FIFO256;
- break;
- case 64:
- fifo_size = PCH_UART_HAL_FIFO64;
- break;
- case 16:
- fifo_size = PCH_UART_HAL_FIFO16;
- case 1:
- default:
- fifo_size = PCH_UART_HAL_FIFO_DIS;
- break;
- }
-
- switch (priv->trigger) {
- case PCH_UART_HAL_TRIGGER1:
- trigger_level = 1;
- break;
- case PCH_UART_HAL_TRIGGER_L:
- trigger_level = priv->fifo_size / 4;
- break;
- case PCH_UART_HAL_TRIGGER_M:
- trigger_level = priv->fifo_size / 2;
- break;
- case PCH_UART_HAL_TRIGGER_H:
- default:
- trigger_level = priv->fifo_size - (priv->fifo_size / 8);
- break;
- }
-
- priv->trigger_level = trigger_level;
- ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0,
- fifo_size, priv->trigger);
- if (ret < 0)
- return ret;
-
- ret = request_irq(priv->port.irq, pch_uart_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, priv);
- if (ret < 0)
- return ret;
-
- if (priv->use_dma)
- pch_request_dma(port);
-
- priv->start_rx = 1;
- pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT);
- uart_update_timeout(port, CS8, default_baud);
-
- return 0;
-}
-
-static void pch_uart_shutdown(struct uart_port *port)
-{
- struct eg20t_port *priv;
- int ret;
-
- priv = container_of(port, struct eg20t_port, port);
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
- pch_uart_hal_fifo_reset(priv, PCH_UART_HAL_CLR_ALL_FIFO);
- ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0,
- PCH_UART_HAL_FIFO_DIS, PCH_UART_HAL_TRIGGER1);
- if (ret)
- pr_err("pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
-
- if (priv->use_dma_flag)
- pch_free_dma(port);
-
- free_irq(priv->port.irq, priv);
-}
-
-/* Change the port parameters, including word length, parity, stop
- *bits. Update read_status_mask and ignore_status_mask to indicate
- *the types of events we are interested in receiving. */
-static void pch_uart_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- int baud;
- int rtn;
- unsigned int parity, bits, stb;
- struct eg20t_port *priv;
- unsigned long flags;
-
- priv = container_of(port, struct eg20t_port, port);
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- bits = PCH_UART_HAL_5BIT;
- break;
- case CS6:
- bits = PCH_UART_HAL_6BIT;
- break;
- case CS7:
- bits = PCH_UART_HAL_7BIT;
- break;
- default: /* CS8 */
- bits = PCH_UART_HAL_8BIT;
- break;
- }
- if (termios->c_cflag & CSTOPB)
- stb = PCH_UART_HAL_STB2;
- else
- stb = PCH_UART_HAL_STB1;
-
- if (termios->c_cflag & PARENB) {
- if (!(termios->c_cflag & PARODD))
- parity = PCH_UART_HAL_PARITY_ODD;
- else
- parity = PCH_UART_HAL_PARITY_EVEN;
-
- } else {
- parity = PCH_UART_HAL_PARITY_NONE;
- }
- termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
-
- spin_lock_irqsave(&port->lock, flags);
-
- uart_update_timeout(port, termios->c_cflag, baud);
- rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb);
- if (rtn)
- goto out;
-
- /* Don't rewrite B0 */
- if (tty_termios_baud_rate(termios))
- tty_termios_encode_baud_rate(termios, baud, baud);
-
-out:
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *pch_uart_type(struct uart_port *port)
-{
- return KBUILD_MODNAME;
-}
-
-static void pch_uart_release_port(struct uart_port *port)
-{
- struct eg20t_port *priv;
-
- priv = container_of(port, struct eg20t_port, port);
- pci_iounmap(priv->pdev, priv->membase);
- pci_release_regions(priv->pdev);
-}
-
-static int pch_uart_request_port(struct uart_port *port)
-{
- struct eg20t_port *priv;
- int ret;
- void __iomem *membase;
-
- priv = container_of(port, struct eg20t_port, port);
- ret = pci_request_regions(priv->pdev, KBUILD_MODNAME);
- if (ret < 0)
- return -EBUSY;
-
- membase = pci_iomap(priv->pdev, 1, 0);
- if (!membase) {
- pci_release_regions(priv->pdev);
- return -EBUSY;
- }
- priv->membase = port->membase = membase;
-
- return 0;
-}
-
-static void pch_uart_config_port(struct uart_port *port, int type)
-{
- struct eg20t_port *priv;
-
- priv = container_of(port, struct eg20t_port, port);
- if (type & UART_CONFIG_TYPE) {
- port->type = priv->port_type;
- pch_uart_request_port(port);
- }
-}
-
-static int pch_uart_verify_port(struct uart_port *port,
- struct serial_struct *serinfo)
-{
- struct eg20t_port *priv;
-
- priv = container_of(port, struct eg20t_port, port);
- if (serinfo->flags & UPF_LOW_LATENCY) {
- pr_info("PCH UART : Use PIO Mode (without DMA)\n");
- priv->use_dma = 0;
- serinfo->flags &= ~UPF_LOW_LATENCY;
- } else {
-#ifndef CONFIG_PCH_DMA
- pr_err("%s : PCH DMA is not Loaded.\n", __func__);
- return -EOPNOTSUPP;
-#endif
- priv->use_dma = 1;
- priv->use_dma_flag = 1;
- pr_info("PCH UART : Use DMA Mode\n");
- }
-
- return 0;
-}
-
-static struct uart_ops pch_uart_ops = {
- .tx_empty = pch_uart_tx_empty,
- .set_mctrl = pch_uart_set_mctrl,
- .get_mctrl = pch_uart_get_mctrl,
- .stop_tx = pch_uart_stop_tx,
- .start_tx = pch_uart_start_tx,
- .stop_rx = pch_uart_stop_rx,
- .enable_ms = pch_uart_enable_ms,
- .break_ctl = pch_uart_break_ctl,
- .startup = pch_uart_startup,
- .shutdown = pch_uart_shutdown,
- .set_termios = pch_uart_set_termios,
-/* .pm = pch_uart_pm, Not supported yet */
-/* .set_wake = pch_uart_set_wake, Not supported yet */
- .type = pch_uart_type,
- .release_port = pch_uart_release_port,
- .request_port = pch_uart_request_port,
- .config_port = pch_uart_config_port,
- .verify_port = pch_uart_verify_port
-};
-
-static struct uart_driver pch_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = KBUILD_MODNAME,
- .dev_name = PCH_UART_DRIVER_DEVICE,
- .major = 0,
- .minor = 0,
- .nr = PCH_UART_NR,
-};
-
-static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
- int port_type)
-{
- struct eg20t_port *priv;
- int ret;
- unsigned int iobase;
- unsigned int mapbase;
- unsigned char *rxbuf;
- int fifosize, base_baud;
- static int num;
-
- priv = kzalloc(sizeof(struct eg20t_port), GFP_KERNEL);
- if (priv == NULL)
- goto init_port_alloc_err;
-
- rxbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!rxbuf)
- goto init_port_free_txbuf;
-
- switch (port_type) {
- case PORT_UNKNOWN:
- fifosize = 256; /* UART0 */
- base_baud = 1843200; /* 1.8432MHz */
- break;
- case PORT_8250:
- fifosize = 64; /* UART1~3 */
- base_baud = 1843200; /* 1.8432MHz */
- break;
- default:
- dev_err(&pdev->dev, "Invalid Port Type(=%d)\n", port_type);
- goto init_port_hal_free;
- }
-
- iobase = pci_resource_start(pdev, 0);
- mapbase = pci_resource_start(pdev, 1);
- priv->mapbase = mapbase;
- priv->iobase = iobase;
- priv->pdev = pdev;
- priv->tx_empty = 1;
- priv->rxbuf.buf = rxbuf;
- priv->rxbuf.size = PAGE_SIZE;
-
- priv->fifo_size = fifosize;
- priv->base_baud = base_baud;
- priv->port_type = PORT_MAX_8250 + port_type + 1;
- priv->port.dev = &pdev->dev;
- priv->port.iobase = iobase;
- priv->port.membase = NULL;
- priv->port.mapbase = mapbase;
- priv->port.irq = pdev->irq;
- priv->port.iotype = UPIO_PORT;
- priv->port.ops = &pch_uart_ops;
- priv->port.flags = UPF_BOOT_AUTOCONF;
- priv->port.fifosize = fifosize;
- priv->port.line = num++;
- priv->trigger = PCH_UART_HAL_TRIGGER_M;
-
- pci_set_drvdata(pdev, priv);
- pch_uart_hal_request(pdev, fifosize, base_baud);
- ret = uart_add_one_port(&pch_uart_driver, &priv->port);
- if (ret < 0)
- goto init_port_hal_free;
-
- return priv;
-
-init_port_hal_free:
- free_page((unsigned long)rxbuf);
-init_port_free_txbuf:
- kfree(priv);
-init_port_alloc_err:
-
- return NULL;
-}
-
-static void pch_uart_exit_port(struct eg20t_port *priv)
-{
- uart_remove_one_port(&pch_uart_driver, &priv->port);
- pci_set_drvdata(priv->pdev, NULL);
- free_page((unsigned long)priv->rxbuf.buf);
-}
-
-static void pch_uart_pci_remove(struct pci_dev *pdev)
-{
- struct eg20t_port *priv;
-
- priv = (struct eg20t_port *)pci_get_drvdata(pdev);
- pch_uart_exit_port(priv);
- pci_disable_device(pdev);
- kfree(priv);
- return;
-}
-#ifdef CONFIG_PM
-static int pch_uart_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct eg20t_port *priv = pci_get_drvdata(pdev);
-
- uart_suspend_port(&pch_uart_driver, &priv->port);
-
- pci_save_state(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- return 0;
-}
-
-static int pch_uart_pci_resume(struct pci_dev *pdev)
-{
- struct eg20t_port *priv = pci_get_drvdata(pdev);
- int ret;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
-
- ret = pci_enable_device(pdev);
- if (ret) {
- dev_err(&pdev->dev,
- "%s-pci_enable_device failed(ret=%d) ", __func__, ret);
- return ret;
- }
-
- uart_resume_port(&pch_uart_driver, &priv->port);
-
- return 0;
-}
-#else
-#define pch_uart_pci_suspend NULL
-#define pch_uart_pci_resume NULL
-#endif
-
-static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
- .driver_data = PCH_UART_8LINE},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812),
- .driver_data = PCH_UART_2LINE},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8813),
- .driver_data = PCH_UART_2LINE},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8814),
- .driver_data = PCH_UART_2LINE},
- {0,},
-};
-
-static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- int ret;
- struct eg20t_port *priv;
-
- ret = pci_enable_device(pdev);
- if (ret < 0)
- goto probe_error;
-
- priv = pch_uart_init_port(pdev, id->driver_data);
- if (!priv) {
- ret = -EBUSY;
- goto probe_disable_device;
- }
- pci_set_drvdata(pdev, priv);
-
- return ret;
-
-probe_disable_device:
- pci_disable_device(pdev);
-probe_error:
- return ret;
-}
-
-static struct pci_driver pch_uart_pci_driver = {
- .name = "pch_uart",
- .id_table = pch_uart_pci_id,
- .probe = pch_uart_pci_probe,
- .remove = __devexit_p(pch_uart_pci_remove),
- .suspend = pch_uart_pci_suspend,
- .resume = pch_uart_pci_resume,
-};
-
-static int __init pch_uart_module_init(void)
-{
- int ret;
-
- /* register as UART driver */
- ret = uart_register_driver(&pch_uart_driver);
- if (ret < 0)
- return ret;
-
- /* register as PCI driver */
- ret = pci_register_driver(&pch_uart_pci_driver);
- if (ret < 0)
- uart_unregister_driver(&pch_uart_driver);
-
- return ret;
-}
-module_init(pch_uart_module_init);
-
-static void __exit pch_uart_module_exit(void)
-{
- pci_unregister_driver(&pch_uart_pci_driver);
- uart_unregister_driver(&pch_uart_driver);
-}
-module_exit(pch_uart_module_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver");
-module_param(default_baud, uint, S_IRUGO);
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
deleted file mode 100644
index 5b9cde79e4ea..000000000000
--- a/drivers/serial/pmac_zilog.c
+++ /dev/null
@@ -1,2208 +0,0 @@
-/*
- * linux/drivers/serial/pmac_zilog.c
- *
- * Driver for PowerMac Z85c30 based ESCC cell found in the
- * "macio" ASICs of various PowerMac models
- *
- * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org)
- *
- * Derived from drivers/macintosh/macserial.c by Paul Mackerras
- * and drivers/serial/sunzilog.c by David S. Miller
- *
- * Hrm... actually, I ripped most of sunzilog (Thanks David !) and
- * adapted special tweaks needed for us. I don't think it's worth
- * merging back those though. The DMA code still has to get in
- * and once done, I expect that driver to remain fairly stable in
- * the long term, unless we change the driver model again...
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * 2004-08-06 Harald Welte <laforge@gnumonks.org>
- * - Enable BREAK interrupt
- * - Add support for sysreq
- *
- * TODO: - Add DMA support
- * - Defer port shutdown to a few seconds after close
- * - maybe put something right into uap->clk_divisor
- */
-
-#undef DEBUG
-#undef DEBUG_HARD
-#undef USE_CTRL_O_SYSRQ
-
-#include <linux/module.h>
-#include <linux/tty.h>
-
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <linux/bitops.h>
-#include <linux/sysrq.h>
-#include <linux/mutex.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/dbdma.h>
-#include <asm/macio.h>
-#else
-#include <linux/platform_device.h>
-#define of_machine_is_compatible(x) (0)
-#endif
-
-#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-
-#include "pmac_zilog.h"
-
-/* Not yet implemented */
-#undef HAS_DBDMA
-
-static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
-MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
-MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports.");
-MODULE_LICENSE("GPL");
-
-#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
-#define PMACZILOG_MAJOR TTY_MAJOR
-#define PMACZILOG_MINOR 64
-#define PMACZILOG_NAME "ttyS"
-#else
-#define PMACZILOG_MAJOR 204
-#define PMACZILOG_MINOR 192
-#define PMACZILOG_NAME "ttyPZ"
-#endif
-
-
-/*
- * For the sake of early serial console, we can do a pre-probe
- * (optional) of the ports at rather early boot time.
- */
-static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS];
-static int pmz_ports_count;
-static DEFINE_MUTEX(pmz_irq_mutex);
-
-static struct uart_driver pmz_uart_reg = {
- .owner = THIS_MODULE,
- .driver_name = PMACZILOG_NAME,
- .dev_name = PMACZILOG_NAME,
- .major = PMACZILOG_MAJOR,
- .minor = PMACZILOG_MINOR,
-};
-
-
-/*
- * Load all registers to reprogram the port
- * This function must only be called when the TX is not busy. The UART
- * port lock must be held and local interrupts disabled.
- */
-static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs)
-{
- int i;
-
- if (ZS_IS_ASLEEP(uap))
- return;
-
- /* Let pending transmits finish. */
- for (i = 0; i < 1000; i++) {
- unsigned char stat = read_zsreg(uap, R1);
- if (stat & ALL_SNT)
- break;
- udelay(100);
- }
-
- ZS_CLEARERR(uap);
- zssync(uap);
- ZS_CLEARFIFO(uap);
- zssync(uap);
- ZS_CLEARERR(uap);
-
- /* Disable all interrupts. */
- write_zsreg(uap, R1,
- regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
-
- /* Set parity, sync config, stop bits, and clock divisor. */
- write_zsreg(uap, R4, regs[R4]);
-
- /* Set misc. TX/RX control bits. */
- write_zsreg(uap, R10, regs[R10]);
-
- /* Set TX/RX controls sans the enable bits. */
- write_zsreg(uap, R3, regs[R3] & ~RxENABLE);
- write_zsreg(uap, R5, regs[R5] & ~TxENABLE);
-
- /* now set R7 "prime" on ESCC */
- write_zsreg(uap, R15, regs[R15] | EN85C30);
- write_zsreg(uap, R7, regs[R7P]);
-
- /* make sure we use R7 "non-prime" on ESCC */
- write_zsreg(uap, R15, regs[R15] & ~EN85C30);
-
- /* Synchronous mode config. */
- write_zsreg(uap, R6, regs[R6]);
- write_zsreg(uap, R7, regs[R7]);
-
- /* Disable baud generator. */
- write_zsreg(uap, R14, regs[R14] & ~BRENAB);
-
- /* Clock mode control. */
- write_zsreg(uap, R11, regs[R11]);
-
- /* Lower and upper byte of baud rate generator divisor. */
- write_zsreg(uap, R12, regs[R12]);
- write_zsreg(uap, R13, regs[R13]);
-
- /* Now rewrite R14, with BRENAB (if set). */
- write_zsreg(uap, R14, regs[R14]);
-
- /* Reset external status interrupts. */
- write_zsreg(uap, R0, RES_EXT_INT);
- write_zsreg(uap, R0, RES_EXT_INT);
-
- /* Rewrite R3/R5, this time without enables masked. */
- write_zsreg(uap, R3, regs[R3]);
- write_zsreg(uap, R5, regs[R5]);
-
- /* Rewrite R1, this time without IRQ enabled masked. */
- write_zsreg(uap, R1, regs[R1]);
-
- /* Enable interrupts */
- write_zsreg(uap, R9, regs[R9]);
-}
-
-/*
- * We do like sunzilog to avoid disrupting pending Tx
- * Reprogram the Zilog channel HW registers with the copies found in the
- * software state struct. If the transmitter is busy, we defer this update
- * until the next TX complete interrupt. Else, we do it right now.
- *
- * The UART port lock must be held and local interrupts disabled.
- */
-static void pmz_maybe_update_regs(struct uart_pmac_port *uap)
-{
- if (!ZS_REGS_HELD(uap)) {
- if (ZS_TX_ACTIVE(uap)) {
- uap->flags |= PMACZILOG_FLAG_REGS_HELD;
- } else {
- pmz_debug("pmz: maybe_update_regs: updating\n");
- pmz_load_zsregs(uap, uap->curregs);
- }
- }
-}
-
-static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
-{
- struct tty_struct *tty = NULL;
- unsigned char ch, r1, drop, error, flag;
- int loops = 0;
-
- /* The interrupt can be enabled when the port isn't open, typically
- * that happens when using one port is open and the other closed (stale
- * interrupt) or when one port is used as a console.
- */
- if (!ZS_IS_OPEN(uap)) {
- pmz_debug("pmz: draining input\n");
- /* Port is closed, drain input data */
- for (;;) {
- if ((++loops) > 1000)
- goto flood;
- (void)read_zsreg(uap, R1);
- write_zsreg(uap, R0, ERR_RES);
- (void)read_zsdata(uap);
- ch = read_zsreg(uap, R0);
- if (!(ch & Rx_CH_AV))
- break;
- }
- return NULL;
- }
-
- /* Sanity check, make sure the old bug is no longer happening */
- if (uap->port.state == NULL || uap->port.state->port.tty == NULL) {
- WARN_ON(1);
- (void)read_zsdata(uap);
- return NULL;
- }
- tty = uap->port.state->port.tty;
-
- while (1) {
- error = 0;
- drop = 0;
-
- r1 = read_zsreg(uap, R1);
- ch = read_zsdata(uap);
-
- if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- write_zsreg(uap, R0, ERR_RES);
- zssync(uap);
- }
-
- ch &= uap->parity_mask;
- if (ch == 0 && uap->flags & PMACZILOG_FLAG_BREAK) {
- uap->flags &= ~PMACZILOG_FLAG_BREAK;
- }
-
-#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_SERIAL_CORE_CONSOLE)
-#ifdef USE_CTRL_O_SYSRQ
- /* Handle the SysRq ^O Hack */
- if (ch == '\x0f') {
- uap->port.sysrq = jiffies + HZ*5;
- goto next_char;
- }
-#endif /* USE_CTRL_O_SYSRQ */
- if (uap->port.sysrq) {
- int swallow;
- spin_unlock(&uap->port.lock);
- swallow = uart_handle_sysrq_char(&uap->port, ch);
- spin_lock(&uap->port.lock);
- if (swallow)
- goto next_char;
- }
-#endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */
-
- /* A real serial line, record the character and status. */
- if (drop)
- goto next_char;
-
- flag = TTY_NORMAL;
- uap->port.icount.rx++;
-
- if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
- error = 1;
- if (r1 & BRK_ABRT) {
- pmz_debug("pmz: got break !\n");
- r1 &= ~(PAR_ERR | CRC_ERR);
- uap->port.icount.brk++;
- if (uart_handle_break(&uap->port))
- goto next_char;
- }
- else if (r1 & PAR_ERR)
- uap->port.icount.parity++;
- else if (r1 & CRC_ERR)
- uap->port.icount.frame++;
- if (r1 & Rx_OVR)
- uap->port.icount.overrun++;
- r1 &= uap->port.read_status_mask;
- if (r1 & BRK_ABRT)
- flag = TTY_BREAK;
- else if (r1 & PAR_ERR)
- flag = TTY_PARITY;
- else if (r1 & CRC_ERR)
- flag = TTY_FRAME;
- }
-
- if (uap->port.ignore_status_mask == 0xff ||
- (r1 & uap->port.ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if (r1 & Rx_OVR)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- next_char:
- /* We can get stuck in an infinite loop getting char 0 when the
- * line is in a wrong HW state, we break that here.
- * When that happens, I disable the receive side of the driver.
- * Note that what I've been experiencing is a real irq loop where
- * I'm getting flooded regardless of the actual port speed.
- * Something stange is going on with the HW
- */
- if ((++loops) > 1000)
- goto flood;
- ch = read_zsreg(uap, R0);
- if (!(ch & Rx_CH_AV))
- break;
- }
-
- return tty;
- flood:
- uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
- write_zsreg(uap, R1, uap->curregs[R1]);
- zssync(uap);
- pmz_error("pmz: rx irq flood !\n");
- return tty;
-}
-
-static void pmz_status_handle(struct uart_pmac_port *uap)
-{
- unsigned char status;
-
- status = read_zsreg(uap, R0);
- write_zsreg(uap, R0, RES_EXT_INT);
- zssync(uap);
-
- if (ZS_IS_OPEN(uap) && ZS_WANTS_MODEM_STATUS(uap)) {
- if (status & SYNC_HUNT)
- uap->port.icount.dsr++;
-
- /* The Zilog just gives us an interrupt when DCD/CTS/etc. change.
- * But it does not tell us which bit has changed, we have to keep
- * track of this ourselves.
- * The CTS input is inverted for some reason. -- paulus
- */
- if ((status ^ uap->prev_status) & DCD)
- uart_handle_dcd_change(&uap->port,
- (status & DCD));
- if ((status ^ uap->prev_status) & CTS)
- uart_handle_cts_change(&uap->port,
- !(status & CTS));
-
- wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
- }
-
- if (status & BRK_ABRT)
- uap->flags |= PMACZILOG_FLAG_BREAK;
-
- uap->prev_status = status;
-}
-
-static void pmz_transmit_chars(struct uart_pmac_port *uap)
-{
- struct circ_buf *xmit;
-
- if (ZS_IS_ASLEEP(uap))
- return;
- if (ZS_IS_CONS(uap)) {
- unsigned char status = read_zsreg(uap, R0);
-
- /* TX still busy? Just wait for the next TX done interrupt.
- *
- * It can occur because of how we do serial console writes. It would
- * be nice to transmit console writes just like we normally would for
- * a TTY line. (ie. buffered and TX interrupt driven). That is not
- * easy because console writes cannot sleep. One solution might be
- * to poll on enough port->xmit space becomming free. -DaveM
- */
- if (!(status & Tx_BUF_EMP))
- return;
- }
-
- uap->flags &= ~PMACZILOG_FLAG_TX_ACTIVE;
-
- if (ZS_REGS_HELD(uap)) {
- pmz_load_zsregs(uap, uap->curregs);
- uap->flags &= ~PMACZILOG_FLAG_REGS_HELD;
- }
-
- if (ZS_TX_STOPPED(uap)) {
- uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
- goto ack_tx_int;
- }
-
- /* Under some circumstances, we see interrupts reported for
- * a closed channel. The interrupt mask in R1 is clear, but
- * R3 still signals the interrupts and we see them when taking
- * an interrupt for the other channel (this could be a qemu
- * bug but since the ESCC doc doesn't specify precsiely whether
- * R3 interrup status bits are masked by R1 interrupt enable
- * bits, better safe than sorry). --BenH.
- */
- if (!ZS_IS_OPEN(uap))
- goto ack_tx_int;
-
- if (uap->port.x_char) {
- uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
- write_zsdata(uap, uap->port.x_char);
- zssync(uap);
- uap->port.icount.tx++;
- uap->port.x_char = 0;
- return;
- }
-
- if (uap->port.state == NULL)
- goto ack_tx_int;
- xmit = &uap->port.state->xmit;
- if (uart_circ_empty(xmit)) {
- uart_write_wakeup(&uap->port);
- goto ack_tx_int;
- }
- if (uart_tx_stopped(&uap->port))
- goto ack_tx_int;
-
- uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
- write_zsdata(uap, xmit->buf[xmit->tail]);
- zssync(uap);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- uap->port.icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uap->port);
-
- return;
-
-ack_tx_int:
- write_zsreg(uap, R0, RES_Tx_P);
- zssync(uap);
-}
-
-/* Hrm... we register that twice, fixme later.... */
-static irqreturn_t pmz_interrupt(int irq, void *dev_id)
-{
- struct uart_pmac_port *uap = dev_id;
- struct uart_pmac_port *uap_a;
- struct uart_pmac_port *uap_b;
- int rc = IRQ_NONE;
- struct tty_struct *tty;
- u8 r3;
-
- uap_a = pmz_get_port_A(uap);
- uap_b = uap_a->mate;
-
- spin_lock(&uap_a->port.lock);
- r3 = read_zsreg(uap_a, R3);
-
-#ifdef DEBUG_HARD
- pmz_debug("irq, r3: %x\n", r3);
-#endif
- /* Channel A */
- tty = NULL;
- if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
- write_zsreg(uap_a, R0, RES_H_IUS);
- zssync(uap_a);
- if (r3 & CHAEXT)
- pmz_status_handle(uap_a);
- if (r3 & CHARxIP)
- tty = pmz_receive_chars(uap_a);
- if (r3 & CHATxIP)
- pmz_transmit_chars(uap_a);
- rc = IRQ_HANDLED;
- }
- spin_unlock(&uap_a->port.lock);
- if (tty != NULL)
- tty_flip_buffer_push(tty);
-
- if (uap_b->node == NULL)
- goto out;
-
- spin_lock(&uap_b->port.lock);
- tty = NULL;
- if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
- write_zsreg(uap_b, R0, RES_H_IUS);
- zssync(uap_b);
- if (r3 & CHBEXT)
- pmz_status_handle(uap_b);
- if (r3 & CHBRxIP)
- tty = pmz_receive_chars(uap_b);
- if (r3 & CHBTxIP)
- pmz_transmit_chars(uap_b);
- rc = IRQ_HANDLED;
- }
- spin_unlock(&uap_b->port.lock);
- if (tty != NULL)
- tty_flip_buffer_push(tty);
-
- out:
-#ifdef DEBUG_HARD
- pmz_debug("irq done.\n");
-#endif
- return rc;
-}
-
-/*
- * Peek the status register, lock not held by caller
- */
-static inline u8 pmz_peek_status(struct uart_pmac_port *uap)
-{
- unsigned long flags;
- u8 status;
-
- spin_lock_irqsave(&uap->port.lock, flags);
- status = read_zsreg(uap, R0);
- spin_unlock_irqrestore(&uap->port.lock, flags);
-
- return status;
-}
-
-/*
- * Check if transmitter is empty
- * The port lock is not held.
- */
-static unsigned int pmz_tx_empty(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned char status;
-
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return TIOCSER_TEMT;
-
- status = pmz_peek_status(to_pmz(port));
- if (status & Tx_BUF_EMP)
- return TIOCSER_TEMT;
- return 0;
-}
-
-/*
- * Set Modem Control (RTS & DTR) bits
- * The port lock is held and interrupts are disabled.
- * Note: Shall we really filter out RTS on external ports or
- * should that be dealt at higher level only ?
- */
-static void pmz_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned char set_bits, clear_bits;
-
- /* Do nothing for irda for now... */
- if (ZS_IS_IRDA(uap))
- return;
- /* We get called during boot with a port not up yet */
- if (ZS_IS_ASLEEP(uap) ||
- !(ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)))
- return;
-
- set_bits = clear_bits = 0;
-
- if (ZS_IS_INTMODEM(uap)) {
- if (mctrl & TIOCM_RTS)
- set_bits |= RTS;
- else
- clear_bits |= RTS;
- }
- if (mctrl & TIOCM_DTR)
- set_bits |= DTR;
- else
- clear_bits |= DTR;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- uap->curregs[R5] |= set_bits;
- uap->curregs[R5] &= ~clear_bits;
- if (ZS_IS_ASLEEP(uap))
- return;
- write_zsreg(uap, R5, uap->curregs[R5]);
- pmz_debug("pmz_set_mctrl: set bits: %x, clear bits: %x -> %x\n",
- set_bits, clear_bits, uap->curregs[R5]);
- zssync(uap);
-}
-
-/*
- * Get Modem Control bits (only the input ones, the core will
- * or that with a cached value of the control ones)
- * The port lock is held and interrupts are disabled.
- */
-static unsigned int pmz_get_mctrl(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned char status;
- unsigned int ret;
-
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return 0;
-
- status = read_zsreg(uap, R0);
-
- ret = 0;
- if (status & DCD)
- ret |= TIOCM_CAR;
- if (status & SYNC_HUNT)
- ret |= TIOCM_DSR;
- if (!(status & CTS))
- ret |= TIOCM_CTS;
-
- return ret;
-}
-
-/*
- * Stop TX side. Dealt like sunzilog at next Tx interrupt,
- * though for DMA, we will have to do a bit more.
- * The port lock is held and interrupts are disabled.
- */
-static void pmz_stop_tx(struct uart_port *port)
-{
- to_pmz(port)->flags |= PMACZILOG_FLAG_TX_STOPPED;
-}
-
-/*
- * Kick the Tx side.
- * The port lock is held and interrupts are disabled.
- */
-static void pmz_start_tx(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned char status;
-
- pmz_debug("pmz: start_tx()\n");
-
- uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
- uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
-
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return;
-
- status = read_zsreg(uap, R0);
-
- /* TX busy? Just wait for the TX done interrupt. */
- if (!(status & Tx_BUF_EMP))
- return;
-
- /* Send the first character to jump-start the TX done
- * IRQ sending engine.
- */
- if (port->x_char) {
- write_zsdata(uap, port->x_char);
- zssync(uap);
- port->icount.tx++;
- port->x_char = 0;
- } else {
- struct circ_buf *xmit = &port->state->xmit;
-
- write_zsdata(uap, xmit->buf[xmit->tail]);
- zssync(uap);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uap->port);
- }
- pmz_debug("pmz: start_tx() done.\n");
-}
-
-/*
- * Stop Rx side, basically disable emitting of
- * Rx interrupts on the port. We don't disable the rx
- * side of the chip proper though
- * The port lock is held.
- */
-static void pmz_stop_rx(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
-
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return;
-
- pmz_debug("pmz: stop_rx()()\n");
-
- /* Disable all RX interrupts. */
- uap->curregs[R1] &= ~RxINT_MASK;
- pmz_maybe_update_regs(uap);
-
- pmz_debug("pmz: stop_rx() done.\n");
-}
-
-/*
- * Enable modem status change interrupts
- * The port lock is held.
- */
-static void pmz_enable_ms(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned char new_reg;
-
- if (ZS_IS_IRDA(uap) || uap->node == NULL)
- return;
- new_reg = uap->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
- if (new_reg != uap->curregs[R15]) {
- uap->curregs[R15] = new_reg;
-
- if (ZS_IS_ASLEEP(uap))
- return;
- /* NOTE: Not subject to 'transmitter active' rule. */
- write_zsreg(uap, R15, uap->curregs[R15]);
- }
-}
-
-/*
- * Control break state emission
- * The port lock is not held.
- */
-static void pmz_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned char set_bits, clear_bits, new_reg;
- unsigned long flags;
-
- if (uap->node == NULL)
- return;
- set_bits = clear_bits = 0;
-
- if (break_state)
- set_bits |= SND_BRK;
- else
- clear_bits |= SND_BRK;
-
- spin_lock_irqsave(&port->lock, flags);
-
- new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits;
- if (new_reg != uap->curregs[R5]) {
- uap->curregs[R5] = new_reg;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- if (ZS_IS_ASLEEP(uap)) {
- spin_unlock_irqrestore(&port->lock, flags);
- return;
- }
- write_zsreg(uap, R5, uap->curregs[R5]);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-#ifdef CONFIG_PPC_PMAC
-
-/*
- * Turn power on or off to the SCC and associated stuff
- * (port drivers, modem, IR port, etc.)
- * Returns the number of milliseconds we should wait before
- * trying to use the port.
- */
-static int pmz_set_scc_power(struct uart_pmac_port *uap, int state)
-{
- int delay = 0;
- int rc;
-
- if (state) {
- rc = pmac_call_feature(
- PMAC_FTR_SCC_ENABLE, uap->node, uap->port_type, 1);
- pmz_debug("port power on result: %d\n", rc);
- if (ZS_IS_INTMODEM(uap)) {
- rc = pmac_call_feature(
- PMAC_FTR_MODEM_ENABLE, uap->node, 0, 1);
- delay = 2500; /* wait for 2.5s before using */
- pmz_debug("modem power result: %d\n", rc);
- }
- } else {
- /* TODO: Make that depend on a timer, don't power down
- * immediately
- */
- if (ZS_IS_INTMODEM(uap)) {
- rc = pmac_call_feature(
- PMAC_FTR_MODEM_ENABLE, uap->node, 0, 0);
- pmz_debug("port power off result: %d\n", rc);
- }
- pmac_call_feature(PMAC_FTR_SCC_ENABLE, uap->node, uap->port_type, 0);
- }
- return delay;
-}
-
-#else
-
-static int pmz_set_scc_power(struct uart_pmac_port *uap, int state)
-{
- return 0;
-}
-
-#endif /* !CONFIG_PPC_PMAC */
-
-/*
- * FixZeroBug....Works around a bug in the SCC receving channel.
- * Inspired from Darwin code, 15 Sept. 2000 -DanM
- *
- * The following sequence prevents a problem that is seen with O'Hare ASICs
- * (most versions -- also with some Heathrow and Hydra ASICs) where a zero
- * at the input to the receiver becomes 'stuck' and locks up the receiver.
- * This problem can occur as a result of a zero bit at the receiver input
- * coincident with any of the following events:
- *
- * The SCC is initialized (hardware or software).
- * A framing error is detected.
- * The clocking option changes from synchronous or X1 asynchronous
- * clocking to X16, X32, or X64 asynchronous clocking.
- * The decoding mode is changed among NRZ, NRZI, FM0, or FM1.
- *
- * This workaround attempts to recover from the lockup condition by placing
- * the SCC in synchronous loopback mode with a fast clock before programming
- * any of the asynchronous modes.
- */
-static void pmz_fix_zero_bug_scc(struct uart_pmac_port *uap)
-{
- write_zsreg(uap, 9, ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB);
- zssync(uap);
- udelay(10);
- write_zsreg(uap, 9, (ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB) | NV);
- zssync(uap);
-
- write_zsreg(uap, 4, X1CLK | MONSYNC);
- write_zsreg(uap, 3, Rx8);
- write_zsreg(uap, 5, Tx8 | RTS);
- write_zsreg(uap, 9, NV); /* Didn't we already do this? */
- write_zsreg(uap, 11, RCBR | TCBR);
- write_zsreg(uap, 12, 0);
- write_zsreg(uap, 13, 0);
- write_zsreg(uap, 14, (LOOPBAK | BRSRC));
- write_zsreg(uap, 14, (LOOPBAK | BRSRC | BRENAB));
- write_zsreg(uap, 3, Rx8 | RxENABLE);
- write_zsreg(uap, 0, RES_EXT_INT);
- write_zsreg(uap, 0, RES_EXT_INT);
- write_zsreg(uap, 0, RES_EXT_INT); /* to kill some time */
-
- /* The channel should be OK now, but it is probably receiving
- * loopback garbage.
- * Switch to asynchronous mode, disable the receiver,
- * and discard everything in the receive buffer.
- */
- write_zsreg(uap, 9, NV);
- write_zsreg(uap, 4, X16CLK | SB_MASK);
- write_zsreg(uap, 3, Rx8);
-
- while (read_zsreg(uap, 0) & Rx_CH_AV) {
- (void)read_zsreg(uap, 8);
- write_zsreg(uap, 0, RES_EXT_INT);
- write_zsreg(uap, 0, ERR_RES);
- }
-}
-
-/*
- * Real startup routine, powers up the hardware and sets up
- * the SCC. Returns a delay in ms where you need to wait before
- * actually using the port, this is typically the internal modem
- * powerup delay. This routine expect the lock to be taken.
- */
-static int __pmz_startup(struct uart_pmac_port *uap)
-{
- int pwr_delay = 0;
-
- memset(&uap->curregs, 0, sizeof(uap->curregs));
-
- /* Power up the SCC & underlying hardware (modem/irda) */
- pwr_delay = pmz_set_scc_power(uap, 1);
-
- /* Nice buggy HW ... */
- pmz_fix_zero_bug_scc(uap);
-
- /* Reset the channel */
- uap->curregs[R9] = 0;
- write_zsreg(uap, 9, ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB);
- zssync(uap);
- udelay(10);
- write_zsreg(uap, 9, 0);
- zssync(uap);
-
- /* Clear the interrupt registers */
- write_zsreg(uap, R1, 0);
- write_zsreg(uap, R0, ERR_RES);
- write_zsreg(uap, R0, ERR_RES);
- write_zsreg(uap, R0, RES_H_IUS);
- write_zsreg(uap, R0, RES_H_IUS);
-
- /* Setup some valid baud rate */
- uap->curregs[R4] = X16CLK | SB1;
- uap->curregs[R3] = Rx8;
- uap->curregs[R5] = Tx8 | RTS;
- if (!ZS_IS_IRDA(uap))
- uap->curregs[R5] |= DTR;
- uap->curregs[R12] = 0;
- uap->curregs[R13] = 0;
- uap->curregs[R14] = BRENAB;
-
- /* Clear handshaking, enable BREAK interrupts */
- uap->curregs[R15] = BRKIE;
-
- /* Master interrupt enable */
- uap->curregs[R9] |= NV | MIE;
-
- pmz_load_zsregs(uap, uap->curregs);
-
- /* Enable receiver and transmitter. */
- write_zsreg(uap, R3, uap->curregs[R3] |= RxENABLE);
- write_zsreg(uap, R5, uap->curregs[R5] |= TxENABLE);
-
- /* Remember status for DCD/CTS changes */
- uap->prev_status = read_zsreg(uap, R0);
-
- return pwr_delay;
-}
-
-static void pmz_irda_reset(struct uart_pmac_port *uap)
-{
- uap->curregs[R5] |= DTR;
- write_zsreg(uap, R5, uap->curregs[R5]);
- zssync(uap);
- mdelay(110);
- uap->curregs[R5] &= ~DTR;
- write_zsreg(uap, R5, uap->curregs[R5]);
- zssync(uap);
- mdelay(10);
-}
-
-/*
- * This is the "normal" startup routine, using the above one
- * wrapped with the lock and doing a schedule delay
- */
-static int pmz_startup(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned long flags;
- int pwr_delay = 0;
-
- pmz_debug("pmz: startup()\n");
-
- if (ZS_IS_ASLEEP(uap))
- return -EAGAIN;
- if (uap->node == NULL)
- return -ENODEV;
-
- mutex_lock(&pmz_irq_mutex);
-
- uap->flags |= PMACZILOG_FLAG_IS_OPEN;
-
- /* A console is never powered down. Else, power up and
- * initialize the chip
- */
- if (!ZS_IS_CONS(uap)) {
- spin_lock_irqsave(&port->lock, flags);
- pwr_delay = __pmz_startup(uap);
- spin_unlock_irqrestore(&port->lock, flags);
- }
-
- pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
- if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED,
- "SCC", uap)) {
- pmz_error("Unable to register zs interrupt handler.\n");
- pmz_set_scc_power(uap, 0);
- mutex_unlock(&pmz_irq_mutex);
- return -ENXIO;
- }
-
- mutex_unlock(&pmz_irq_mutex);
-
- /* Right now, we deal with delay by blocking here, I'll be
- * smarter later on
- */
- if (pwr_delay != 0) {
- pmz_debug("pmz: delaying %d ms\n", pwr_delay);
- msleep(pwr_delay);
- }
-
- /* IrDA reset is done now */
- if (ZS_IS_IRDA(uap))
- pmz_irda_reset(uap);
-
- /* Enable interrupts emission from the chip */
- spin_lock_irqsave(&port->lock, flags);
- uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB;
- if (!ZS_IS_EXTCLK(uap))
- uap->curregs[R1] |= EXT_INT_ENAB;
- write_zsreg(uap, R1, uap->curregs[R1]);
- spin_unlock_irqrestore(&port->lock, flags);
-
- pmz_debug("pmz: startup() done.\n");
-
- return 0;
-}
-
-static void pmz_shutdown(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned long flags;
-
- pmz_debug("pmz: shutdown()\n");
-
- if (uap->node == NULL)
- return;
-
- mutex_lock(&pmz_irq_mutex);
-
- /* Release interrupt handler */
- free_irq(uap->port.irq, uap);
-
- spin_lock_irqsave(&port->lock, flags);
-
- uap->flags &= ~PMACZILOG_FLAG_IS_OPEN;
-
- if (!ZS_IS_OPEN(uap->mate))
- pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON;
-
- /* Disable interrupts */
- if (!ZS_IS_ASLEEP(uap)) {
- uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
- write_zsreg(uap, R1, uap->curregs[R1]);
- zssync(uap);
- }
-
- if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) {
- spin_unlock_irqrestore(&port->lock, flags);
- mutex_unlock(&pmz_irq_mutex);
- return;
- }
-
- /* Disable receiver and transmitter. */
- uap->curregs[R3] &= ~RxENABLE;
- uap->curregs[R5] &= ~TxENABLE;
-
- /* Disable all interrupts and BRK assertion. */
- uap->curregs[R5] &= ~SND_BRK;
- pmz_maybe_update_regs(uap);
-
- /* Shut the chip down */
- pmz_set_scc_power(uap, 0);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- mutex_unlock(&pmz_irq_mutex);
-
- pmz_debug("pmz: shutdown() done.\n");
-}
-
-/* Shared by TTY driver and serial console setup. The port lock is held
- * and local interrupts are disabled.
- */
-static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag,
- unsigned int iflag, unsigned long baud)
-{
- int brg;
-
- /* Switch to external clocking for IrDA high clock rates. That
- * code could be re-used for Midi interfaces with different
- * multipliers
- */
- if (baud >= 115200 && ZS_IS_IRDA(uap)) {
- uap->curregs[R4] = X1CLK;
- uap->curregs[R11] = RCTRxCP | TCTRxCP;
- uap->curregs[R14] = 0; /* BRG off */
- uap->curregs[R12] = 0;
- uap->curregs[R13] = 0;
- uap->flags |= PMACZILOG_FLAG_IS_EXTCLK;
- } else {
- switch (baud) {
- case ZS_CLOCK/16: /* 230400 */
- uap->curregs[R4] = X16CLK;
- uap->curregs[R11] = 0;
- uap->curregs[R14] = 0;
- break;
- case ZS_CLOCK/32: /* 115200 */
- uap->curregs[R4] = X32CLK;
- uap->curregs[R11] = 0;
- uap->curregs[R14] = 0;
- break;
- default:
- uap->curregs[R4] = X16CLK;
- uap->curregs[R11] = TCBR | RCBR;
- brg = BPS_TO_BRG(baud, ZS_CLOCK / 16);
- uap->curregs[R12] = (brg & 255);
- uap->curregs[R13] = ((brg >> 8) & 255);
- uap->curregs[R14] = BRENAB;
- }
- uap->flags &= ~PMACZILOG_FLAG_IS_EXTCLK;
- }
-
- /* Character size, stop bits, and parity. */
- uap->curregs[3] &= ~RxN_MASK;
- uap->curregs[5] &= ~TxN_MASK;
-
- switch (cflag & CSIZE) {
- case CS5:
- uap->curregs[3] |= Rx5;
- uap->curregs[5] |= Tx5;
- uap->parity_mask = 0x1f;
- break;
- case CS6:
- uap->curregs[3] |= Rx6;
- uap->curregs[5] |= Tx6;
- uap->parity_mask = 0x3f;
- break;
- case CS7:
- uap->curregs[3] |= Rx7;
- uap->curregs[5] |= Tx7;
- uap->parity_mask = 0x7f;
- break;
- case CS8:
- default:
- uap->curregs[3] |= Rx8;
- uap->curregs[5] |= Tx8;
- uap->parity_mask = 0xff;
- break;
- };
- uap->curregs[4] &= ~(SB_MASK);
- if (cflag & CSTOPB)
- uap->curregs[4] |= SB2;
- else
- uap->curregs[4] |= SB1;
- if (cflag & PARENB)
- uap->curregs[4] |= PAR_ENAB;
- else
- uap->curregs[4] &= ~PAR_ENAB;
- if (!(cflag & PARODD))
- uap->curregs[4] |= PAR_EVEN;
- else
- uap->curregs[4] &= ~PAR_EVEN;
-
- uap->port.read_status_mask = Rx_OVR;
- if (iflag & INPCK)
- uap->port.read_status_mask |= CRC_ERR | PAR_ERR;
- if (iflag & (BRKINT | PARMRK))
- uap->port.read_status_mask |= BRK_ABRT;
-
- uap->port.ignore_status_mask = 0;
- if (iflag & IGNPAR)
- uap->port.ignore_status_mask |= CRC_ERR | PAR_ERR;
- if (iflag & IGNBRK) {
- uap->port.ignore_status_mask |= BRK_ABRT;
- if (iflag & IGNPAR)
- uap->port.ignore_status_mask |= Rx_OVR;
- }
-
- if ((cflag & CREAD) == 0)
- uap->port.ignore_status_mask = 0xff;
-}
-
-
-/*
- * Set the irda codec on the imac to the specified baud rate.
- */
-static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
-{
- u8 cmdbyte;
- int t, version;
-
- switch (*baud) {
- /* SIR modes */
- case 2400:
- cmdbyte = 0x53;
- break;
- case 4800:
- cmdbyte = 0x52;
- break;
- case 9600:
- cmdbyte = 0x51;
- break;
- case 19200:
- cmdbyte = 0x50;
- break;
- case 38400:
- cmdbyte = 0x4f;
- break;
- case 57600:
- cmdbyte = 0x4e;
- break;
- case 115200:
- cmdbyte = 0x4d;
- break;
- /* The FIR modes aren't really supported at this point, how
- * do we select the speed ? via the FCR on KeyLargo ?
- */
- case 1152000:
- cmdbyte = 0;
- break;
- case 4000000:
- cmdbyte = 0;
- break;
- default: /* 9600 */
- cmdbyte = 0x51;
- *baud = 9600;
- break;
- }
-
- /* Wait for transmitter to drain */
- t = 10000;
- while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0
- || (read_zsreg(uap, R1) & ALL_SNT) == 0) {
- if (--t <= 0) {
- pmz_error("transmitter didn't drain\n");
- return;
- }
- udelay(10);
- }
-
- /* Drain the receiver too */
- t = 100;
- (void)read_zsdata(uap);
- (void)read_zsdata(uap);
- (void)read_zsdata(uap);
- mdelay(10);
- while (read_zsreg(uap, R0) & Rx_CH_AV) {
- read_zsdata(uap);
- mdelay(10);
- if (--t <= 0) {
- pmz_error("receiver didn't drain\n");
- return;
- }
- }
-
- /* Switch to command mode */
- uap->curregs[R5] |= DTR;
- write_zsreg(uap, R5, uap->curregs[R5]);
- zssync(uap);
- mdelay(1);
-
- /* Switch SCC to 19200 */
- pmz_convert_to_zs(uap, CS8, 0, 19200);
- pmz_load_zsregs(uap, uap->curregs);
- mdelay(1);
-
- /* Write get_version command byte */
- write_zsdata(uap, 1);
- t = 5000;
- while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
- if (--t <= 0) {
- pmz_error("irda_setup timed out on get_version byte\n");
- goto out;
- }
- udelay(10);
- }
- version = read_zsdata(uap);
-
- if (version < 4) {
- pmz_info("IrDA: dongle version %d not supported\n", version);
- goto out;
- }
-
- /* Send speed mode */
- write_zsdata(uap, cmdbyte);
- t = 5000;
- while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
- if (--t <= 0) {
- pmz_error("irda_setup timed out on speed mode byte\n");
- goto out;
- }
- udelay(10);
- }
- t = read_zsdata(uap);
- if (t != cmdbyte)
- pmz_error("irda_setup speed mode byte = %x (%x)\n", t, cmdbyte);
-
- pmz_info("IrDA setup for %ld bps, dongle version: %d\n",
- *baud, version);
-
- (void)read_zsdata(uap);
- (void)read_zsdata(uap);
- (void)read_zsdata(uap);
-
- out:
- /* Switch back to data mode */
- uap->curregs[R5] &= ~DTR;
- write_zsreg(uap, R5, uap->curregs[R5]);
- zssync(uap);
-
- (void)read_zsdata(uap);
- (void)read_zsdata(uap);
- (void)read_zsdata(uap);
-}
-
-
-static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned long baud;
-
- pmz_debug("pmz: set_termios()\n");
-
- if (ZS_IS_ASLEEP(uap))
- return;
-
- memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
-
- /* XXX Check which revs of machines actually allow 1 and 4Mb speeds
- * on the IR dongle. Note that the IRTTY driver currently doesn't know
- * about the FIR mode and high speed modes. So these are unused. For
- * implementing proper support for these, we should probably add some
- * DMA as well, at least on the Rx side, which isn't a simple thing
- * at this point.
- */
- if (ZS_IS_IRDA(uap)) {
- /* Calc baud rate */
- baud = uart_get_baud_rate(port, termios, old, 1200, 4000000);
- pmz_debug("pmz: switch IRDA to %ld bauds\n", baud);
- /* Cet the irda codec to the right rate */
- pmz_irda_setup(uap, &baud);
- /* Set final baud rate */
- pmz_convert_to_zs(uap, termios->c_cflag, termios->c_iflag, baud);
- pmz_load_zsregs(uap, uap->curregs);
- zssync(uap);
- } else {
- baud = uart_get_baud_rate(port, termios, old, 1200, 230400);
- pmz_convert_to_zs(uap, termios->c_cflag, termios->c_iflag, baud);
- /* Make sure modem status interrupts are correctly configured */
- if (UART_ENABLE_MS(&uap->port, termios->c_cflag)) {
- uap->curregs[R15] |= DCDIE | SYNCIE | CTSIE;
- uap->flags |= PMACZILOG_FLAG_MODEM_STATUS;
- } else {
- uap->curregs[R15] &= ~(DCDIE | SYNCIE | CTSIE);
- uap->flags &= ~PMACZILOG_FLAG_MODEM_STATUS;
- }
-
- /* Load registers to the chip */
- pmz_maybe_update_regs(uap);
- }
- uart_update_timeout(port, termios->c_cflag, baud);
-
- pmz_debug("pmz: set_termios() done.\n");
-}
-
-/* The port lock is not held. */
-static void pmz_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_pmac_port *uap = to_pmz(port);
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* Disable IRQs on the port */
- uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
- write_zsreg(uap, R1, uap->curregs[R1]);
-
- /* Setup new port configuration */
- __pmz_set_termios(port, termios, old);
-
- /* Re-enable IRQs on the port */
- if (ZS_IS_OPEN(uap)) {
- uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB;
- if (!ZS_IS_EXTCLK(uap))
- uap->curregs[R1] |= EXT_INT_ENAB;
- write_zsreg(uap, R1, uap->curregs[R1]);
- }
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *pmz_type(struct uart_port *port)
-{
- struct uart_pmac_port *uap = to_pmz(port);
-
- if (ZS_IS_IRDA(uap))
- return "Z85c30 ESCC - Infrared port";
- else if (ZS_IS_INTMODEM(uap))
- return "Z85c30 ESCC - Internal modem";
- return "Z85c30 ESCC - Serial port";
-}
-
-/* We do not request/release mappings of the registers here, this
- * happens at early serial probe time.
- */
-static void pmz_release_port(struct uart_port *port)
-{
-}
-
-static int pmz_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/* These do not need to do anything interesting either. */
-static void pmz_config_port(struct uart_port *port, int flags)
-{
-}
-
-/* We do not support letting the user mess with the divisor, IRQ, etc. */
-static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-
-static int pmz_poll_get_char(struct uart_port *port)
-{
- struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
-
- while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0)
- udelay(5);
- return read_zsdata(uap);
-}
-
-static void pmz_poll_put_char(struct uart_port *port, unsigned char c)
-{
- struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
-
- /* Wait for the transmit buffer to empty. */
- while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
- udelay(5);
- write_zsdata(uap, c);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static struct uart_ops pmz_pops = {
- .tx_empty = pmz_tx_empty,
- .set_mctrl = pmz_set_mctrl,
- .get_mctrl = pmz_get_mctrl,
- .stop_tx = pmz_stop_tx,
- .start_tx = pmz_start_tx,
- .stop_rx = pmz_stop_rx,
- .enable_ms = pmz_enable_ms,
- .break_ctl = pmz_break_ctl,
- .startup = pmz_startup,
- .shutdown = pmz_shutdown,
- .set_termios = pmz_set_termios,
- .type = pmz_type,
- .release_port = pmz_release_port,
- .request_port = pmz_request_port,
- .config_port = pmz_config_port,
- .verify_port = pmz_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = pmz_poll_get_char,
- .poll_put_char = pmz_poll_put_char,
-#endif
-};
-
-#ifdef CONFIG_PPC_PMAC
-
-/*
- * Setup one port structure after probing, HW is down at this point,
- * Unlike sunzilog, we don't need to pre-init the spinlock as we don't
- * register our console before uart_add_one_port() is called
- */
-static int __init pmz_init_port(struct uart_pmac_port *uap)
-{
- struct device_node *np = uap->node;
- const char *conn;
- const struct slot_names_prop {
- int count;
- char name[1];
- } *slots;
- int len;
- struct resource r_ports, r_rxdma, r_txdma;
-
- /*
- * Request & map chip registers
- */
- if (of_address_to_resource(np, 0, &r_ports))
- return -ENODEV;
- uap->port.mapbase = r_ports.start;
- uap->port.membase = ioremap(uap->port.mapbase, 0x1000);
-
- uap->control_reg = uap->port.membase;
- uap->data_reg = uap->control_reg + 0x10;
-
- /*
- * Request & map DBDMA registers
- */
-#ifdef HAS_DBDMA
- if (of_address_to_resource(np, 1, &r_txdma) == 0 &&
- of_address_to_resource(np, 2, &r_rxdma) == 0)
- uap->flags |= PMACZILOG_FLAG_HAS_DMA;
-#else
- memset(&r_txdma, 0, sizeof(struct resource));
- memset(&r_rxdma, 0, sizeof(struct resource));
-#endif
- if (ZS_HAS_DMA(uap)) {
- uap->tx_dma_regs = ioremap(r_txdma.start, 0x100);
- if (uap->tx_dma_regs == NULL) {
- uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
- goto no_dma;
- }
- uap->rx_dma_regs = ioremap(r_rxdma.start, 0x100);
- if (uap->rx_dma_regs == NULL) {
- iounmap(uap->tx_dma_regs);
- uap->tx_dma_regs = NULL;
- uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
- goto no_dma;
- }
- uap->tx_dma_irq = irq_of_parse_and_map(np, 1);
- uap->rx_dma_irq = irq_of_parse_and_map(np, 2);
- }
-no_dma:
-
- /*
- * Detect port type
- */
- if (of_device_is_compatible(np, "cobalt"))
- uap->flags |= PMACZILOG_FLAG_IS_INTMODEM;
- conn = of_get_property(np, "AAPL,connector", &len);
- if (conn && (strcmp(conn, "infrared") == 0))
- uap->flags |= PMACZILOG_FLAG_IS_IRDA;
- uap->port_type = PMAC_SCC_ASYNC;
- /* 1999 Powerbook G3 has slot-names property instead */
- slots = of_get_property(np, "slot-names", &len);
- if (slots && slots->count > 0) {
- if (strcmp(slots->name, "IrDA") == 0)
- uap->flags |= PMACZILOG_FLAG_IS_IRDA;
- else if (strcmp(slots->name, "Modem") == 0)
- uap->flags |= PMACZILOG_FLAG_IS_INTMODEM;
- }
- if (ZS_IS_IRDA(uap))
- uap->port_type = PMAC_SCC_IRDA;
- if (ZS_IS_INTMODEM(uap)) {
- struct device_node* i2c_modem =
- of_find_node_by_name(NULL, "i2c-modem");
- if (i2c_modem) {
- const char* mid =
- of_get_property(i2c_modem, "modem-id", NULL);
- if (mid) switch(*mid) {
- case 0x04 :
- case 0x05 :
- case 0x07 :
- case 0x08 :
- case 0x0b :
- case 0x0c :
- uap->port_type = PMAC_SCC_I2S1;
- }
- printk(KERN_INFO "pmac_zilog: i2c-modem detected, id: %d\n",
- mid ? (*mid) : 0);
- of_node_put(i2c_modem);
- } else {
- printk(KERN_INFO "pmac_zilog: serial modem detected\n");
- }
- }
-
- /*
- * Init remaining bits of "port" structure
- */
- uap->port.iotype = UPIO_MEM;
- uap->port.irq = irq_of_parse_and_map(np, 0);
- uap->port.uartclk = ZS_CLOCK;
- uap->port.fifosize = 1;
- uap->port.ops = &pmz_pops;
- uap->port.type = PORT_PMAC_ZILOG;
- uap->port.flags = 0;
-
- /*
- * Fixup for the port on Gatwick for which the device-tree has
- * missing interrupts. Normally, the macio_dev would contain
- * fixed up interrupt info, but we use the device-tree directly
- * here due to early probing so we need the fixup too.
- */
- if (uap->port.irq == NO_IRQ &&
- np->parent && np->parent->parent &&
- of_device_is_compatible(np->parent->parent, "gatwick")) {
- /* IRQs on gatwick are offset by 64 */
- uap->port.irq = irq_create_mapping(NULL, 64 + 15);
- uap->tx_dma_irq = irq_create_mapping(NULL, 64 + 4);
- uap->rx_dma_irq = irq_create_mapping(NULL, 64 + 5);
- }
-
- /* Setup some valid baud rate information in the register
- * shadows so we don't write crap there before baud rate is
- * first initialized.
- */
- pmz_convert_to_zs(uap, CS8, 0, 9600);
-
- return 0;
-}
-
-/*
- * Get rid of a port on module removal
- */
-static void pmz_dispose_port(struct uart_pmac_port *uap)
-{
- struct device_node *np;
-
- np = uap->node;
- iounmap(uap->rx_dma_regs);
- iounmap(uap->tx_dma_regs);
- iounmap(uap->control_reg);
- uap->node = NULL;
- of_node_put(np);
- memset(uap, 0, sizeof(struct uart_pmac_port));
-}
-
-/*
- * Called upon match with an escc node in the device-tree.
- */
-static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match)
-{
- int i;
-
- /* Iterate the pmz_ports array to find a matching entry
- */
- for (i = 0; i < MAX_ZS_PORTS; i++)
- if (pmz_ports[i].node == mdev->ofdev.dev.of_node) {
- struct uart_pmac_port *uap = &pmz_ports[i];
-
- uap->dev = mdev;
- dev_set_drvdata(&mdev->ofdev.dev, uap);
- if (macio_request_resources(uap->dev, "pmac_zilog"))
- printk(KERN_WARNING "%s: Failed to request resource"
- ", port still active\n",
- uap->node->name);
- else
- uap->flags |= PMACZILOG_FLAG_RSRC_REQUESTED;
- return 0;
- }
- return -ENODEV;
-}
-
-/*
- * That one should not be called, macio isn't really a hotswap device,
- * we don't expect one of those serial ports to go away...
- */
-static int pmz_detach(struct macio_dev *mdev)
-{
- struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
-
- if (!uap)
- return -ENODEV;
-
- if (uap->flags & PMACZILOG_FLAG_RSRC_REQUESTED) {
- macio_release_resources(uap->dev);
- uap->flags &= ~PMACZILOG_FLAG_RSRC_REQUESTED;
- }
- dev_set_drvdata(&mdev->ofdev.dev, NULL);
- uap->dev = NULL;
-
- return 0;
-}
-
-
-static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
-{
- struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
- struct uart_state *state;
- unsigned long flags;
-
- if (uap == NULL) {
- printk("HRM... pmz_suspend with NULL uap\n");
- return 0;
- }
-
- if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
- return 0;
-
- pmz_debug("suspend, switching to state %d\n", pm_state.event);
-
- state = pmz_uart_reg.state + uap->port.line;
-
- mutex_lock(&pmz_irq_mutex);
- mutex_lock(&state->port.mutex);
-
- spin_lock_irqsave(&uap->port.lock, flags);
-
- if (ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)) {
- /* Disable receiver and transmitter. */
- uap->curregs[R3] &= ~RxENABLE;
- uap->curregs[R5] &= ~TxENABLE;
-
- /* Disable all interrupts and BRK assertion. */
- uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
- uap->curregs[R5] &= ~SND_BRK;
- pmz_load_zsregs(uap, uap->curregs);
- uap->flags |= PMACZILOG_FLAG_IS_ASLEEP;
- mb();
- }
-
- spin_unlock_irqrestore(&uap->port.lock, flags);
-
- if (ZS_IS_OPEN(uap) || ZS_IS_OPEN(uap->mate))
- if (ZS_IS_ASLEEP(uap->mate) && ZS_IS_IRQ_ON(pmz_get_port_A(uap))) {
- pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON;
- disable_irq(uap->port.irq);
- }
-
- if (ZS_IS_CONS(uap))
- uap->port.cons->flags &= ~CON_ENABLED;
-
- /* Shut the chip down */
- pmz_set_scc_power(uap, 0);
-
- mutex_unlock(&state->port.mutex);
- mutex_unlock(&pmz_irq_mutex);
-
- pmz_debug("suspend, switching complete\n");
-
- mdev->ofdev.dev.power.power_state = pm_state;
-
- return 0;
-}
-
-
-static int pmz_resume(struct macio_dev *mdev)
-{
- struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
- struct uart_state *state;
- unsigned long flags;
- int pwr_delay = 0;
-
- if (uap == NULL)
- return 0;
-
- if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
- return 0;
-
- pmz_debug("resume, switching to state 0\n");
-
- state = pmz_uart_reg.state + uap->port.line;
-
- mutex_lock(&pmz_irq_mutex);
- mutex_lock(&state->port.mutex);
-
- spin_lock_irqsave(&uap->port.lock, flags);
- if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) {
- spin_unlock_irqrestore(&uap->port.lock, flags);
- goto bail;
- }
- pwr_delay = __pmz_startup(uap);
-
- /* Take care of config that may have changed while asleep */
- __pmz_set_termios(&uap->port, &uap->termios_cache, NULL);
-
- if (ZS_IS_OPEN(uap)) {
- /* Enable interrupts */
- uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB;
- if (!ZS_IS_EXTCLK(uap))
- uap->curregs[R1] |= EXT_INT_ENAB;
- write_zsreg(uap, R1, uap->curregs[R1]);
- }
-
- spin_unlock_irqrestore(&uap->port.lock, flags);
-
- if (ZS_IS_CONS(uap))
- uap->port.cons->flags |= CON_ENABLED;
-
- /* Re-enable IRQ on the controller */
- if (ZS_IS_OPEN(uap) && !ZS_IS_IRQ_ON(pmz_get_port_A(uap))) {
- pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
- enable_irq(uap->port.irq);
- }
-
- bail:
- mutex_unlock(&state->port.mutex);
- mutex_unlock(&pmz_irq_mutex);
-
- /* Right now, we deal with delay by blocking here, I'll be
- * smarter later on
- */
- if (pwr_delay != 0) {
- pmz_debug("pmz: delaying %d ms\n", pwr_delay);
- msleep(pwr_delay);
- }
-
- pmz_debug("resume, switching complete\n");
-
- mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
-
- return 0;
-}
-
-/*
- * Probe all ports in the system and build the ports array, we register
- * with the serial layer at this point, the macio-type probing is only
- * used later to "attach" to the sysfs tree so we get power management
- * events
- */
-static int __init pmz_probe(void)
-{
- struct device_node *node_p, *node_a, *node_b, *np;
- int count = 0;
- int rc;
-
- /*
- * Find all escc chips in the system
- */
- node_p = of_find_node_by_name(NULL, "escc");
- while (node_p) {
- /*
- * First get channel A/B node pointers
- *
- * TODO: Add routines with proper locking to do that...
- */
- node_a = node_b = NULL;
- for (np = NULL; (np = of_get_next_child(node_p, np)) != NULL;) {
- if (strncmp(np->name, "ch-a", 4) == 0)
- node_a = of_node_get(np);
- else if (strncmp(np->name, "ch-b", 4) == 0)
- node_b = of_node_get(np);
- }
- if (!node_a && !node_b) {
- of_node_put(node_a);
- of_node_put(node_b);
- printk(KERN_ERR "pmac_zilog: missing node %c for escc %s\n",
- (!node_a) ? 'a' : 'b', node_p->full_name);
- goto next;
- }
-
- /*
- * Fill basic fields in the port structures
- */
- pmz_ports[count].mate = &pmz_ports[count+1];
- pmz_ports[count+1].mate = &pmz_ports[count];
- pmz_ports[count].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
- pmz_ports[count].node = node_a;
- pmz_ports[count+1].node = node_b;
- pmz_ports[count].port.line = count;
- pmz_ports[count+1].port.line = count+1;
-
- /*
- * Setup the ports for real
- */
- rc = pmz_init_port(&pmz_ports[count]);
- if (rc == 0 && node_b != NULL)
- rc = pmz_init_port(&pmz_ports[count+1]);
- if (rc != 0) {
- of_node_put(node_a);
- of_node_put(node_b);
- memset(&pmz_ports[count], 0, sizeof(struct uart_pmac_port));
- memset(&pmz_ports[count+1], 0, sizeof(struct uart_pmac_port));
- goto next;
- }
- count += 2;
-next:
- node_p = of_find_node_by_name(node_p, "escc");
- }
- pmz_ports_count = count;
-
- return 0;
-}
-
-#else
-
-extern struct platform_device scc_a_pdev, scc_b_pdev;
-
-static int __init pmz_init_port(struct uart_pmac_port *uap)
-{
- struct resource *r_ports;
- int irq;
-
- r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0);
- irq = platform_get_irq(uap->node, 0);
- if (!r_ports || !irq)
- return -ENODEV;
-
- uap->port.mapbase = r_ports->start;
- uap->port.membase = (unsigned char __iomem *) r_ports->start;
- uap->port.iotype = UPIO_MEM;
- uap->port.irq = irq;
- uap->port.uartclk = ZS_CLOCK;
- uap->port.fifosize = 1;
- uap->port.ops = &pmz_pops;
- uap->port.type = PORT_PMAC_ZILOG;
- uap->port.flags = 0;
-
- uap->control_reg = uap->port.membase;
- uap->data_reg = uap->control_reg + 4;
- uap->port_type = 0;
-
- pmz_convert_to_zs(uap, CS8, 0, 9600);
-
- return 0;
-}
-
-static int __init pmz_probe(void)
-{
- int err;
-
- pmz_ports_count = 0;
-
- pmz_ports[0].mate = &pmz_ports[1];
- pmz_ports[0].port.line = 0;
- pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
- pmz_ports[0].node = &scc_a_pdev;
- err = pmz_init_port(&pmz_ports[0]);
- if (err)
- return err;
- pmz_ports_count++;
-
- pmz_ports[1].mate = &pmz_ports[0];
- pmz_ports[1].port.line = 1;
- pmz_ports[1].flags = 0;
- pmz_ports[1].node = &scc_b_pdev;
- err = pmz_init_port(&pmz_ports[1]);
- if (err)
- return err;
- pmz_ports_count++;
-
- return 0;
-}
-
-static void pmz_dispose_port(struct uart_pmac_port *uap)
-{
- memset(uap, 0, sizeof(struct uart_pmac_port));
-}
-
-static int __init pmz_attach(struct platform_device *pdev)
-{
- int i;
-
- for (i = 0; i < pmz_ports_count; i++)
- if (pmz_ports[i].node == pdev)
- return 0;
- return -ENODEV;
-}
-
-static int __exit pmz_detach(struct platform_device *pdev)
-{
- return 0;
-}
-
-#endif /* !CONFIG_PPC_PMAC */
-
-#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
-
-static void pmz_console_write(struct console *con, const char *s, unsigned int count);
-static int __init pmz_console_setup(struct console *co, char *options);
-
-static struct console pmz_console = {
- .name = PMACZILOG_NAME,
- .write = pmz_console_write,
- .device = uart_console_device,
- .setup = pmz_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &pmz_uart_reg,
-};
-
-#define PMACZILOG_CONSOLE &pmz_console
-#else /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
-#define PMACZILOG_CONSOLE (NULL)
-#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
-
-/*
- * Register the driver, console driver and ports with the serial
- * core
- */
-static int __init pmz_register(void)
-{
- int i, rc;
-
- pmz_uart_reg.nr = pmz_ports_count;
- pmz_uart_reg.cons = PMACZILOG_CONSOLE;
-
- /*
- * Register this driver with the serial core
- */
- rc = uart_register_driver(&pmz_uart_reg);
- if (rc)
- return rc;
-
- /*
- * Register each port with the serial core
- */
- for (i = 0; i < pmz_ports_count; i++) {
- struct uart_pmac_port *uport = &pmz_ports[i];
- /* NULL node may happen on wallstreet */
- if (uport->node != NULL)
- rc = uart_add_one_port(&pmz_uart_reg, &uport->port);
- if (rc)
- goto err_out;
- }
-
- return 0;
-err_out:
- while (i-- > 0) {
- struct uart_pmac_port *uport = &pmz_ports[i];
- uart_remove_one_port(&pmz_uart_reg, &uport->port);
- }
- uart_unregister_driver(&pmz_uart_reg);
- return rc;
-}
-
-#ifdef CONFIG_PPC_PMAC
-
-static struct of_device_id pmz_match[] =
-{
- {
- .name = "ch-a",
- },
- {
- .name = "ch-b",
- },
- {},
-};
-MODULE_DEVICE_TABLE (of, pmz_match);
-
-static struct macio_driver pmz_driver = {
- .driver = {
- .name = "pmac_zilog",
- .owner = THIS_MODULE,
- .of_match_table = pmz_match,
- },
- .probe = pmz_attach,
- .remove = pmz_detach,
- .suspend = pmz_suspend,
- .resume = pmz_resume,
-};
-
-#else
-
-static struct platform_driver pmz_driver = {
- .remove = __exit_p(pmz_detach),
- .driver = {
- .name = "scc",
- .owner = THIS_MODULE,
- },
-};
-
-#endif /* !CONFIG_PPC_PMAC */
-
-static int __init init_pmz(void)
-{
- int rc, i;
- printk(KERN_INFO "%s\n", version);
-
- /*
- * First, we need to do a direct OF-based probe pass. We
- * do that because we want serial console up before the
- * macio stuffs calls us back, and since that makes it
- * easier to pass the proper number of channels to
- * uart_register_driver()
- */
- if (pmz_ports_count == 0)
- pmz_probe();
-
- /*
- * Bail early if no port found
- */
- if (pmz_ports_count == 0)
- return -ENODEV;
-
- /*
- * Now we register with the serial layer
- */
- rc = pmz_register();
- if (rc) {
- printk(KERN_ERR
- "pmac_zilog: Error registering serial device, disabling pmac_zilog.\n"
- "pmac_zilog: Did another serial driver already claim the minors?\n");
- /* effectively "pmz_unprobe()" */
- for (i=0; i < pmz_ports_count; i++)
- pmz_dispose_port(&pmz_ports[i]);
- return rc;
- }
-
- /*
- * Then we register the macio driver itself
- */
-#ifdef CONFIG_PPC_PMAC
- return macio_register_driver(&pmz_driver);
-#else
- return platform_driver_probe(&pmz_driver, pmz_attach);
-#endif
-}
-
-static void __exit exit_pmz(void)
-{
- int i;
-
-#ifdef CONFIG_PPC_PMAC
- /* Get rid of macio-driver (detach from macio) */
- macio_unregister_driver(&pmz_driver);
-#else
- platform_driver_unregister(&pmz_driver);
-#endif
-
- for (i = 0; i < pmz_ports_count; i++) {
- struct uart_pmac_port *uport = &pmz_ports[i];
- if (uport->node != NULL) {
- uart_remove_one_port(&pmz_uart_reg, &uport->port);
- pmz_dispose_port(uport);
- }
- }
- /* Unregister UART driver */
- uart_unregister_driver(&pmz_uart_reg);
-}
-
-#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
-
-static void pmz_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
-
- /* Wait for the transmit buffer to empty. */
- while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
- udelay(5);
- write_zsdata(uap, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- */
-static void pmz_console_write(struct console *con, const char *s, unsigned int count)
-{
- struct uart_pmac_port *uap = &pmz_ports[con->index];
- unsigned long flags;
-
- if (ZS_IS_ASLEEP(uap))
- return;
- spin_lock_irqsave(&uap->port.lock, flags);
-
- /* Turn of interrupts and enable the transmitter. */
- write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB);
- write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR);
-
- uart_console_write(&uap->port, s, count, pmz_console_putchar);
-
- /* Restore the values in the registers. */
- write_zsreg(uap, R1, uap->curregs[1]);
- /* Don't disable the transmitter. */
-
- spin_unlock_irqrestore(&uap->port.lock, flags);
-}
-
-/*
- * Setup the serial console
- */
-static int __init pmz_console_setup(struct console *co, char *options)
-{
- struct uart_pmac_port *uap;
- struct uart_port *port;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- unsigned long pwr_delay;
-
- /*
- * XServe's default to 57600 bps
- */
- if (of_machine_is_compatible("RackMac1,1")
- || of_machine_is_compatible("RackMac1,2")
- || of_machine_is_compatible("MacRISC4"))
- baud = 57600;
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= pmz_ports_count)
- co->index = 0;
- uap = &pmz_ports[co->index];
- if (uap->node == NULL)
- return -ENODEV;
- port = &uap->port;
-
- /*
- * Mark port as beeing a console
- */
- uap->flags |= PMACZILOG_FLAG_IS_CONS;
-
- /*
- * Temporary fix for uart layer who didn't setup the spinlock yet
- */
- spin_lock_init(&port->lock);
-
- /*
- * Enable the hardware
- */
- pwr_delay = __pmz_startup(uap);
- if (pwr_delay)
- mdelay(pwr_delay);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static int __init pmz_console_init(void)
-{
- /* Probe ports */
- pmz_probe();
-
- /* TODO: Autoprobe console based on OF */
- /* pmz_console.index = i; */
- register_console(&pmz_console);
-
- return 0;
-
-}
-console_initcall(pmz_console_init);
-#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
-
-module_init(init_pmz);
-module_exit(exit_pmz);
diff --git a/drivers/serial/pmac_zilog.h b/drivers/serial/pmac_zilog.h
deleted file mode 100644
index cbc34fbb1b20..000000000000
--- a/drivers/serial/pmac_zilog.h
+++ /dev/null
@@ -1,396 +0,0 @@
-#ifndef __PMAC_ZILOG_H__
-#define __PMAC_ZILOG_H__
-
-#ifdef CONFIG_PPC_PMAC
-#define pmz_debug(fmt, arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
-#define pmz_error(fmt, arg...) dev_err(&uap->dev->ofdev.dev, fmt, ## arg)
-#define pmz_info(fmt, arg...) dev_info(&uap->dev->ofdev.dev, fmt, ## arg)
-#else
-#define pmz_debug(fmt, arg...) dev_dbg(&uap->node->dev, fmt, ## arg)
-#define pmz_error(fmt, arg...) dev_err(&uap->node->dev, fmt, ## arg)
-#define pmz_info(fmt, arg...) dev_info(&uap->node->dev, fmt, ## arg)
-#endif
-
-/*
- * At most 2 ESCCs with 2 ports each
- */
-#define MAX_ZS_PORTS 4
-
-/*
- * We wrap our port structure around the generic uart_port.
- */
-#define NUM_ZSREGS 17
-
-struct uart_pmac_port {
- struct uart_port port;
- struct uart_pmac_port *mate;
-
-#ifdef CONFIG_PPC_PMAC
- /* macio_dev for the escc holding this port (maybe be null on
- * early inited port)
- */
- struct macio_dev *dev;
- /* device node to this port, this points to one of 2 childs
- * of "escc" node (ie. ch-a or ch-b)
- */
- struct device_node *node;
-#else
- struct platform_device *node;
-#endif
-
- /* Port type as obtained from device tree (IRDA, modem, ...) */
- int port_type;
- u8 curregs[NUM_ZSREGS];
-
- unsigned int flags;
-#define PMACZILOG_FLAG_IS_CONS 0x00000001
-#define PMACZILOG_FLAG_IS_KGDB 0x00000002
-#define PMACZILOG_FLAG_MODEM_STATUS 0x00000004
-#define PMACZILOG_FLAG_IS_CHANNEL_A 0x00000008
-#define PMACZILOG_FLAG_REGS_HELD 0x00000010
-#define PMACZILOG_FLAG_TX_STOPPED 0x00000020
-#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
-#define PMACZILOG_FLAG_ENABLED 0x00000080
-#define PMACZILOG_FLAG_IS_IRDA 0x00000100
-#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
-#define PMACZILOG_FLAG_HAS_DMA 0x00000400
-#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
-#define PMACZILOG_FLAG_IS_ASLEEP 0x00001000
-#define PMACZILOG_FLAG_IS_OPEN 0x00002000
-#define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000
-#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
-#define PMACZILOG_FLAG_BREAK 0x00010000
-
- unsigned char parity_mask;
- unsigned char prev_status;
-
- volatile u8 __iomem *control_reg;
- volatile u8 __iomem *data_reg;
-
-#ifdef CONFIG_PPC_PMAC
- unsigned int tx_dma_irq;
- unsigned int rx_dma_irq;
- volatile struct dbdma_regs __iomem *tx_dma_regs;
- volatile struct dbdma_regs __iomem *rx_dma_regs;
-#endif
-
- struct ktermios termios_cache;
-};
-
-#define to_pmz(p) ((struct uart_pmac_port *)(p))
-
-static inline struct uart_pmac_port *pmz_get_port_A(struct uart_pmac_port *uap)
-{
- if (uap->flags & PMACZILOG_FLAG_IS_CHANNEL_A)
- return uap;
- return uap->mate;
-}
-
-/*
- * Register accessors. Note that we don't need to enforce a recovery
- * delay on PCI PowerMac hardware, it's dealt in HW by the MacIO chip,
- * though if we try to use this driver on older machines, we might have
- * to add it back
- */
-static inline u8 read_zsreg(struct uart_pmac_port *port, u8 reg)
-{
- if (reg != 0)
- writeb(reg, port->control_reg);
- return readb(port->control_reg);
-}
-
-static inline void write_zsreg(struct uart_pmac_port *port, u8 reg, u8 value)
-{
- if (reg != 0)
- writeb(reg, port->control_reg);
- writeb(value, port->control_reg);
-}
-
-static inline u8 read_zsdata(struct uart_pmac_port *port)
-{
- return readb(port->data_reg);
-}
-
-static inline void write_zsdata(struct uart_pmac_port *port, u8 data)
-{
- writeb(data, port->data_reg);
-}
-
-static inline void zssync(struct uart_pmac_port *port)
-{
- (void)readb(port->control_reg);
-}
-
-/* Conversion routines to/from brg time constants from/to bits
- * per second.
- */
-#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
-#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
-
-#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */
-
-/* The Zilog register set */
-
-#define FLAG 0x7e
-
-/* Write Register 0 */
-#define R0 0 /* Register selects */
-#define R1 1
-#define R2 2
-#define R3 3
-#define R4 4
-#define R5 5
-#define R6 6
-#define R7 7
-#define R8 8
-#define R9 9
-#define R10 10
-#define R11 11
-#define R12 12
-#define R13 13
-#define R14 14
-#define R15 15
-#define R7P 16
-
-#define NULLCODE 0 /* Null Code */
-#define POINT_HIGH 0x8 /* Select upper half of registers */
-#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
-#define SEND_ABORT 0x18 /* HDLC Abort */
-#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
-#define RES_Tx_P 0x28 /* Reset TxINT Pending */
-#define ERR_RES 0x30 /* Error Reset */
-#define RES_H_IUS 0x38 /* Reset highest IUS */
-
-#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
-#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
-#define RES_EOM_L 0xC0 /* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
-#define TxINT_ENAB 0x2 /* Tx Int Enable */
-#define PAR_SPEC 0x4 /* Parity is special condition */
-
-#define RxINT_DISAB 0 /* Rx Int Disable */
-#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
-#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
-#define INT_ERR_Rx 0x18 /* Int on error only */
-#define RxINT_MASK 0x18
-
-#define WT_RDY_RT 0x20 /* W/Req reflects recv if 1, xmit if 0 */
-#define WT_FN_RDYFN 0x40 /* W/Req pin is DMA request if 1, wait if 0 */
-#define WT_RDY_ENAB 0x80 /* Enable W/Req pin */
-
-/* Write Register #2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define RxENABLE 0x1 /* Rx Enable */
-#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
-#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
-#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
-#define ENT_HM 0x10 /* Enter Hunt Mode */
-#define AUTO_ENAB 0x20 /* Auto Enables */
-#define Rx5 0x0 /* Rx 5 Bits/Character */
-#define Rx7 0x40 /* Rx 7 Bits/Character */
-#define Rx6 0x80 /* Rx 6 Bits/Character */
-#define Rx8 0xc0 /* Rx 8 Bits/Character */
-#define RxN_MASK 0xc0
-
-/* Write Register 4 */
-
-#define PAR_ENAB 0x1 /* Parity Enable */
-#define PAR_EVEN 0x2 /* Parity Even/Odd* */
-
-#define SYNC_ENAB 0 /* Sync Modes Enable */
-#define SB1 0x4 /* 1 stop bit/char */
-#define SB15 0x8 /* 1.5 stop bits/char */
-#define SB2 0xc /* 2 stop bits/char */
-#define SB_MASK 0xc
-
-#define MONSYNC 0 /* 8 Bit Sync character */
-#define BISYNC 0x10 /* 16 bit sync character */
-#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
-#define EXTSYNC 0x30 /* External Sync Mode */
-
-#define X1CLK 0x0 /* x1 clock mode */
-#define X16CLK 0x40 /* x16 clock mode */
-#define X32CLK 0x80 /* x32 clock mode */
-#define X64CLK 0xC0 /* x64 clock mode */
-#define XCLK_MASK 0xC0
-
-/* Write Register 5 */
-
-#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
-#define RTS 0x2 /* RTS */
-#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
-#define TxENABLE 0x8 /* Tx Enable */
-#define SND_BRK 0x10 /* Send Break */
-#define Tx5 0x0 /* Tx 5 bits (or less)/character */
-#define Tx7 0x20 /* Tx 7 bits/character */
-#define Tx6 0x40 /* Tx 6 bits/character */
-#define Tx8 0x60 /* Tx 8 bits/character */
-#define TxN_MASK 0x60
-#define DTR 0x80 /* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 7' (Some enhanced feature control) */
-#define ENEXREAD 0x40 /* Enable read of some write registers */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define VIS 1 /* Vector Includes Status */
-#define NV 2 /* No Vector */
-#define DLC 4 /* Disable Lower Chain */
-#define MIE 8 /* Master Interrupt Enable */
-#define STATHI 0x10 /* Status high */
-#define NORESET 0 /* No reset on write to R9 */
-#define CHRB 0x40 /* Reset channel B */
-#define CHRA 0x80 /* Reset channel A */
-#define FHWRES 0xc0 /* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define BIT6 1 /* 6 bit/8bit sync */
-#define LOOPMODE 2 /* SDLC Loop mode */
-#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
-#define MARKIDLE 8 /* Mark/flag on idle */
-#define GAOP 0x10 /* Go active on poll */
-#define NRZ 0 /* NRZ mode */
-#define NRZI 0x20 /* NRZI mode */
-#define FM1 0x40 /* FM1 (transition = 1) */
-#define FM0 0x60 /* FM0 (transition = 0) */
-#define CRCPS 0x80 /* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define TRxCXT 0 /* TRxC = Xtal output */
-#define TRxCTC 1 /* TRxC = Transmit clock */
-#define TRxCBR 2 /* TRxC = BR Generator Output */
-#define TRxCDP 3 /* TRxC = DPLL output */
-#define TRxCOI 4 /* TRxC O/I */
-#define TCRTxCP 0 /* Transmit clock = RTxC pin */
-#define TCTRxCP 8 /* Transmit clock = TRxC pin */
-#define TCBR 0x10 /* Transmit clock = BR Generator output */
-#define TCDPLL 0x18 /* Transmit clock = DPLL output */
-#define RCRTxCP 0 /* Receive clock = RTxC pin */
-#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
-#define RCBR 0x40 /* Receive clock = BR Generator output */
-#define RCDPLL 0x60 /* Receive clock = DPLL output */
-#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define BRENAB 1 /* Baud rate generator enable */
-#define BRSRC 2 /* Baud rate generator source */
-#define DTRREQ 4 /* DTR/Request function */
-#define AUTOECHO 8 /* Auto Echo */
-#define LOOPBAK 0x10 /* Local loopback */
-#define SEARCH 0x20 /* Enter search mode */
-#define RMC 0x40 /* Reset missing clock */
-#define DISDPLL 0x60 /* Disable DPLL */
-#define SSBR 0x80 /* Set DPLL source = BR generator */
-#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
-#define SFMM 0xc0 /* Set FM mode */
-#define SNRZI 0xe0 /* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define EN85C30 1 /* Enable some 85c30-enhanced registers */
-#define ZCIE 2 /* Zero count IE */
-#define ENSTFIFO 4 /* Enable status FIFO (SDLC) */
-#define DCDIE 8 /* DCD IE */
-#define SYNCIE 0x10 /* Sync/hunt IE */
-#define CTSIE 0x20 /* CTS IE */
-#define TxUIE 0x40 /* Tx Underrun/EOM IE */
-#define BRKIE 0x80 /* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define Rx_CH_AV 0x1 /* Rx Character Available */
-#define ZCOUNT 0x2 /* Zero count */
-#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
-#define DCD 0x8 /* DCD */
-#define SYNC_HUNT 0x10 /* Sync/hunt */
-#define CTS 0x20 /* CTS */
-#define TxEOM 0x40 /* Tx underrun */
-#define BRK_ABRT 0x80 /* Break/Abort */
-
-/* Read Register 1 */
-#define ALL_SNT 0x1 /* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define RES3 0x8 /* 0/3 */
-#define RES4 0x4 /* 0/4 */
-#define RES5 0xc /* 0/5 */
-#define RES6 0x2 /* 0/6 */
-#define RES7 0xa /* 0/7 */
-#define RES8 0x6 /* 0/8 */
-#define RES18 0xe /* 1/8 */
-#define RES28 0x0 /* 2/8 */
-/* Special Rx Condition Interrupts */
-#define PAR_ERR 0x10 /* Parity error */
-#define Rx_OVR 0x20 /* Rx Overrun Error */
-#define CRC_ERR 0x40 /* CRC/Framing Error */
-#define END_FR 0x80 /* End of Frame (SDLC) */
-
-/* Read Register 2 (channel b only) - Interrupt vector */
-#define CHB_Tx_EMPTY 0x00
-#define CHB_EXT_STAT 0x02
-#define CHB_Rx_AVAIL 0x04
-#define CHB_SPECIAL 0x06
-#define CHA_Tx_EMPTY 0x08
-#define CHA_EXT_STAT 0x0a
-#define CHA_Rx_AVAIL 0x0c
-#define CHA_SPECIAL 0x0e
-#define STATUS_MASK 0x06
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
-#define CHBTxIP 0x2 /* Channel B Tx IP */
-#define CHBRxIP 0x4 /* Channel B Rx IP */
-#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
-#define CHATxIP 0x10 /* Channel A Tx IP */
-#define CHARxIP 0x20 /* Channel A Rx IP */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10 (misc status bits) */
-#define ONLOOP 2 /* On loop */
-#define LOOPSEND 0x10 /* Loop sending */
-#define CLK2MIS 0x40 /* Two clocks missing */
-#define CLK1MIS 0x80 /* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
-
-/* Misc macros */
-#define ZS_CLEARERR(port) (write_zsreg(port, 0, ERR_RES))
-#define ZS_CLEARFIFO(port) do { volatile unsigned char garbage; \
- garbage = read_zsdata(port); \
- garbage = read_zsdata(port); \
- garbage = read_zsdata(port); \
- } while(0)
-
-#define ZS_IS_CONS(UP) ((UP)->flags & PMACZILOG_FLAG_IS_CONS)
-#define ZS_IS_KGDB(UP) ((UP)->flags & PMACZILOG_FLAG_IS_KGDB)
-#define ZS_IS_CHANNEL_A(UP) ((UP)->flags & PMACZILOG_FLAG_IS_CHANNEL_A)
-#define ZS_REGS_HELD(UP) ((UP)->flags & PMACZILOG_FLAG_REGS_HELD)
-#define ZS_TX_STOPPED(UP) ((UP)->flags & PMACZILOG_FLAG_TX_STOPPED)
-#define ZS_TX_ACTIVE(UP) ((UP)->flags & PMACZILOG_FLAG_TX_ACTIVE)
-#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & PMACZILOG_FLAG_MODEM_STATUS)
-#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
-#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
-#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
-#define ZS_IS_ASLEEP(UP) ((UP)->flags & PMACZILOG_FLAG_IS_ASLEEP)
-#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
-#define ZS_IS_IRQ_ON(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRQ_ON)
-#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
-
-#endif /* __PMAC_ZILOG_H__ */
diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c
deleted file mode 100644
index 0aa75a97531c..000000000000
--- a/drivers/serial/pnx8xxx_uart.c
+++ /dev/null
@@ -1,854 +0,0 @@
-/*
- * UART driver for PNX8XXX SoCs
- *
- * Author: Per Hallsmark per.hallsmark@mvista.com
- * Ported to 2.6 kernel by EmbeddedAlley
- * Reworked by Vitaly Wool <vitalywool@gmail.com>
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of
- * any kind, whether express or implied.
- *
- */
-
-#if defined(CONFIG_SERIAL_PNX8XXX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/serial_pnx8xxx.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-/* We'll be using StrongARM sa1100 serial port major/minor */
-#define SERIAL_PNX8XXX_MAJOR 204
-#define MINOR_START 5
-
-#define NR_PORTS 2
-
-#define PNX8XXX_ISR_PASS_LIMIT 256
-
-/*
- * Convert from ignore_status_mask or read_status_mask to FIFO
- * and interrupt status bits
- */
-#define SM_TO_FIFO(x) ((x) >> 10)
-#define SM_TO_ISTAT(x) ((x) & 0x000001ff)
-#define FIFO_TO_SM(x) ((x) << 10)
-#define ISTAT_TO_SM(x) ((x) & 0x000001ff)
-
-/*
- * This is the size of our serial port register set.
- */
-#define UART_PORT_SIZE 0x1000
-
-/*
- * This determines how often we check the modem status signals
- * for any change. They generally aren't connected to an IRQ
- * so we have to poll them. We also check immediately before
- * filling the TX fifo incase CTS has been dropped.
- */
-#define MCTRL_TIMEOUT (250*HZ/1000)
-
-extern struct pnx8xxx_port pnx8xxx_ports[];
-
-static inline int serial_in(struct pnx8xxx_port *sport, int offset)
-{
- return (__raw_readl(sport->port.membase + offset));
-}
-
-static inline void serial_out(struct pnx8xxx_port *sport, int offset, int value)
-{
- __raw_writel(value, sport->port.membase + offset);
-}
-
-/*
- * Handle any change of modem status signal since we were last called.
- */
-static void pnx8xxx_mctrl_check(struct pnx8xxx_port *sport)
-{
- unsigned int status, changed;
-
- status = sport->port.ops->get_mctrl(&sport->port);
- changed = status ^ sport->old_status;
-
- if (changed == 0)
- return;
-
- sport->old_status = status;
-
- if (changed & TIOCM_RI)
- sport->port.icount.rng++;
- if (changed & TIOCM_DSR)
- sport->port.icount.dsr++;
- if (changed & TIOCM_CAR)
- uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
- if (changed & TIOCM_CTS)
- uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
-
- wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
-}
-
-/*
- * This is our per-port timeout handler, for checking the
- * modem status signals.
- */
-static void pnx8xxx_timeout(unsigned long data)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)data;
- unsigned long flags;
-
- if (sport->port.state) {
- spin_lock_irqsave(&sport->port.lock, flags);
- pnx8xxx_mctrl_check(sport);
- spin_unlock_irqrestore(&sport->port.lock, flags);
-
- mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
- }
-}
-
-/*
- * interrupts disabled on entry
- */
-static void pnx8xxx_stop_tx(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- u32 ien;
-
- /* Disable TX intr */
- ien = serial_in(sport, PNX8XXX_IEN);
- serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLTX);
-
- /* Clear all pending TX intr */
- serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
-}
-
-/*
- * interrupts may not be disabled on entry
- */
-static void pnx8xxx_start_tx(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- u32 ien;
-
- /* Clear all pending TX intr */
- serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
-
- /* Enable TX intr */
- ien = serial_in(sport, PNX8XXX_IEN);
- serial_out(sport, PNX8XXX_IEN, ien | PNX8XXX_UART_INT_ALLTX);
-}
-
-/*
- * Interrupts enabled
- */
-static void pnx8xxx_stop_rx(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- u32 ien;
-
- /* Disable RX intr */
- ien = serial_in(sport, PNX8XXX_IEN);
- serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLRX);
-
- /* Clear all pending RX intr */
- serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX);
-}
-
-/*
- * Set the modem control timer to fire immediately.
- */
-static void pnx8xxx_enable_ms(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
-
- mod_timer(&sport->timer, jiffies);
-}
-
-static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
-{
- struct tty_struct *tty = sport->port.state->port.tty;
- unsigned int status, ch, flg;
-
- status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
- ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
- while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
- ch = serial_in(sport, PNX8XXX_FIFO) & 0xff;
-
- sport->port.icount.rx++;
-
- flg = TTY_NORMAL;
-
- /*
- * note that the error handling code is
- * out of the main execution path
- */
- if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
- PNX8XXX_UART_FIFO_RXPAR |
- PNX8XXX_UART_FIFO_RXBRK) |
- ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
- if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) {
- status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
- FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR));
- sport->port.icount.brk++;
- if (uart_handle_break(&sport->port))
- goto ignore_char;
- } else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
- sport->port.icount.parity++;
- else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
- sport->port.icount.frame++;
- if (status & ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))
- sport->port.icount.overrun++;
-
- status &= sport->port.read_status_mask;
-
- if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
- flg = TTY_PARITY;
- else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
- flg = TTY_FRAME;
-
-#ifdef SUPPORT_SYSRQ
- sport->port.sysrq = 0;
-#endif
- }
-
- if (uart_handle_sysrq_char(&sport->port, ch))
- goto ignore_char;
-
- uart_insert_char(&sport->port, status,
- ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN), ch, flg);
-
- ignore_char:
- serial_out(sport, PNX8XXX_LCR, serial_in(sport, PNX8XXX_LCR) |
- PNX8XXX_UART_LCR_RX_NEXT);
- status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
- ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
- }
- tty_flip_buffer_push(tty);
-}
-
-static void pnx8xxx_tx_chars(struct pnx8xxx_port *sport)
-{
- struct circ_buf *xmit = &sport->port.state->xmit;
-
- if (sport->port.x_char) {
- serial_out(sport, PNX8XXX_FIFO, sport->port.x_char);
- sport->port.icount.tx++;
- sport->port.x_char = 0;
- return;
- }
-
- /*
- * Check the modem control lines before
- * transmitting anything.
- */
- pnx8xxx_mctrl_check(sport);
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- pnx8xxx_stop_tx(&sport->port);
- return;
- }
-
- /*
- * TX while bytes available
- */
- while (((serial_in(sport, PNX8XXX_FIFO) &
- PNX8XXX_UART_FIFO_TXFIFO) >> 16) < 16) {
- serial_out(sport, PNX8XXX_FIFO, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- sport->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&sport->port);
-
- if (uart_circ_empty(xmit))
- pnx8xxx_stop_tx(&sport->port);
-}
-
-static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
-{
- struct pnx8xxx_port *sport = dev_id;
- unsigned int status;
-
- spin_lock(&sport->port.lock);
- /* Get the interrupts */
- status = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
-
- /* Byte or break signal received */
- if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK))
- pnx8xxx_rx_chars(sport);
-
- /* TX holding register empty - transmit a byte */
- if (status & PNX8XXX_UART_INT_TX)
- pnx8xxx_tx_chars(sport);
-
- /* Clear the ISTAT register */
- serial_out(sport, PNX8XXX_ICLR, status);
-
- spin_unlock(&sport->port.lock);
- return IRQ_HANDLED;
-}
-
-/*
- * Return TIOCSER_TEMT when transmitter is not busy.
- */
-static unsigned int pnx8xxx_tx_empty(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
-
- return serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA ? 0 : TIOCSER_TEMT;
-}
-
-static unsigned int pnx8xxx_get_mctrl(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- unsigned int mctrl = TIOCM_DSR;
- unsigned int msr;
-
- /* REVISIT */
-
- msr = serial_in(sport, PNX8XXX_MCR);
-
- mctrl |= msr & PNX8XXX_UART_MCR_CTS ? TIOCM_CTS : 0;
- mctrl |= msr & PNX8XXX_UART_MCR_DCD ? TIOCM_CAR : 0;
-
- return mctrl;
-}
-
-static void pnx8xxx_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-#if 0 /* FIXME */
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- unsigned int msr;
-#endif
-}
-
-/*
- * Interrupts always disabled.
- */
-static void pnx8xxx_break_ctl(struct uart_port *port, int break_state)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- unsigned long flags;
- unsigned int lcr;
-
- spin_lock_irqsave(&sport->port.lock, flags);
- lcr = serial_in(sport, PNX8XXX_LCR);
- if (break_state == -1)
- lcr |= PNX8XXX_UART_LCR_TXBREAK;
- else
- lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
- serial_out(sport, PNX8XXX_LCR, lcr);
- spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-static int pnx8xxx_startup(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- int retval;
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(sport->port.irq, pnx8xxx_int, 0,
- "pnx8xxx-uart", sport);
- if (retval)
- return retval;
-
- /*
- * Finally, clear and enable interrupts
- */
-
- serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
- PNX8XXX_UART_INT_ALLTX);
-
- serial_out(sport, PNX8XXX_IEN, serial_in(sport, PNX8XXX_IEN) |
- PNX8XXX_UART_INT_ALLRX |
- PNX8XXX_UART_INT_ALLTX);
-
- /*
- * Enable modem status interrupts
- */
- spin_lock_irq(&sport->port.lock);
- pnx8xxx_enable_ms(&sport->port);
- spin_unlock_irq(&sport->port.lock);
-
- return 0;
-}
-
-static void pnx8xxx_shutdown(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- int lcr;
-
- /*
- * Stop our timer.
- */
- del_timer_sync(&sport->timer);
-
- /*
- * Disable all interrupts
- */
- serial_out(sport, PNX8XXX_IEN, 0);
-
- /*
- * Reset the Tx and Rx FIFOS, disable the break condition
- */
- lcr = serial_in(sport, PNX8XXX_LCR);
- lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
- lcr |= PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST;
- serial_out(sport, PNX8XXX_LCR, lcr);
-
- /*
- * Clear all interrupts
- */
- serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
- PNX8XXX_UART_INT_ALLTX);
-
- /*
- * Free the interrupt
- */
- free_irq(sport->port.irq, sport);
-}
-
-static void
-pnx8xxx_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- unsigned long flags;
- unsigned int lcr_fcr, old_ien, baud, quot;
- unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
-
- /*
- * We only support CS7 and CS8.
- */
- while ((termios->c_cflag & CSIZE) != CS7 &&
- (termios->c_cflag & CSIZE) != CS8) {
- termios->c_cflag &= ~CSIZE;
- termios->c_cflag |= old_csize;
- old_csize = CS8;
- }
-
- if ((termios->c_cflag & CSIZE) == CS8)
- lcr_fcr = PNX8XXX_UART_LCR_8BIT;
- else
- lcr_fcr = 0;
-
- if (termios->c_cflag & CSTOPB)
- lcr_fcr |= PNX8XXX_UART_LCR_2STOPB;
- if (termios->c_cflag & PARENB) {
- lcr_fcr |= PNX8XXX_UART_LCR_PAREN;
- if (!(termios->c_cflag & PARODD))
- lcr_fcr |= PNX8XXX_UART_LCR_PAREVN;
- }
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- spin_lock_irqsave(&sport->port.lock, flags);
-
- sport->port.read_status_mask = ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN) |
- ISTAT_TO_SM(PNX8XXX_UART_INT_EMPTY) |
- ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
- if (termios->c_iflag & INPCK)
- sport->port.read_status_mask |=
- FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
- FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
- if (termios->c_iflag & (BRKINT | PARMRK))
- sport->port.read_status_mask |=
- ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
-
- /*
- * Characters to ignore
- */
- sport->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- sport->port.ignore_status_mask |=
- FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
- FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
- if (termios->c_iflag & IGNBRK) {
- sport->port.ignore_status_mask |=
- ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- sport->port.ignore_status_mask |=
- ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN);
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- sport->port.ignore_status_mask |=
- ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
-
- del_timer_sync(&sport->timer);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /*
- * disable interrupts and drain transmitter
- */
- old_ien = serial_in(sport, PNX8XXX_IEN);
- serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
- PNX8XXX_UART_INT_ALLRX));
-
- while (serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA)
- barrier();
-
- /* then, disable everything */
- serial_out(sport, PNX8XXX_IEN, 0);
-
- /* Reset the Rx and Tx FIFOs too */
- lcr_fcr |= PNX8XXX_UART_LCR_TX_RST;
- lcr_fcr |= PNX8XXX_UART_LCR_RX_RST;
-
- /* set the parity, stop bits and data size */
- serial_out(sport, PNX8XXX_LCR, lcr_fcr);
-
- /* set the baud rate */
- quot -= 1;
- serial_out(sport, PNX8XXX_BAUD, quot);
-
- serial_out(sport, PNX8XXX_ICLR, -1);
-
- serial_out(sport, PNX8XXX_IEN, old_ien);
-
- if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
- pnx8xxx_enable_ms(&sport->port);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-static const char *pnx8xxx_type(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
-
- return sport->port.type == PORT_PNX8XXX ? "PNX8XXX" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'.
- */
-static void pnx8xxx_release_port(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
-
- release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
-}
-
-/*
- * Request the memory region(s) being used by 'port'.
- */
-static int pnx8xxx_request_port(struct uart_port *port)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
- "pnx8xxx-uart") != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void pnx8xxx_config_port(struct uart_port *port, int flags)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
-
- if (flags & UART_CONFIG_TYPE &&
- pnx8xxx_request_port(&sport->port) == 0)
- sport->port.type = PORT_PNX8XXX;
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- * The only change we allow are to the flags and type, and
- * even then only between PORT_PNX8XXX and PORT_UNKNOWN
- */
-static int
-pnx8xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_PNX8XXX)
- ret = -EINVAL;
- if (sport->port.irq != ser->irq)
- ret = -EINVAL;
- if (ser->io_type != SERIAL_IO_MEM)
- ret = -EINVAL;
- if (sport->port.uartclk / 16 != ser->baud_base)
- ret = -EINVAL;
- if ((void *)sport->port.mapbase != ser->iomem_base)
- ret = -EINVAL;
- if (sport->port.iobase != ser->port)
- ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops pnx8xxx_pops = {
- .tx_empty = pnx8xxx_tx_empty,
- .set_mctrl = pnx8xxx_set_mctrl,
- .get_mctrl = pnx8xxx_get_mctrl,
- .stop_tx = pnx8xxx_stop_tx,
- .start_tx = pnx8xxx_start_tx,
- .stop_rx = pnx8xxx_stop_rx,
- .enable_ms = pnx8xxx_enable_ms,
- .break_ctl = pnx8xxx_break_ctl,
- .startup = pnx8xxx_startup,
- .shutdown = pnx8xxx_shutdown,
- .set_termios = pnx8xxx_set_termios,
- .type = pnx8xxx_type,
- .release_port = pnx8xxx_release_port,
- .request_port = pnx8xxx_request_port,
- .config_port = pnx8xxx_config_port,
- .verify_port = pnx8xxx_verify_port,
-};
-
-
-/*
- * Setup the PNX8XXX serial ports.
- *
- * Note also that we support "console=ttySx" where "x" is either 0 or 1.
- */
-static void __init pnx8xxx_init_ports(void)
-{
- static int first = 1;
- int i;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0; i < NR_PORTS; i++) {
- init_timer(&pnx8xxx_ports[i].timer);
- pnx8xxx_ports[i].timer.function = pnx8xxx_timeout;
- pnx8xxx_ports[i].timer.data = (unsigned long)&pnx8xxx_ports[i];
- pnx8xxx_ports[i].port.ops = &pnx8xxx_pops;
- }
-}
-
-#ifdef CONFIG_SERIAL_PNX8XXX_CONSOLE
-
-static void pnx8xxx_console_putchar(struct uart_port *port, int ch)
-{
- struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
- int status;
-
- do {
- /* Wait for UART_TX register to empty */
- status = serial_in(sport, PNX8XXX_FIFO);
- } while (status & PNX8XXX_UART_FIFO_TXFIFO);
- serial_out(sport, PNX8XXX_FIFO, ch);
-}
-
-/*
- * Interrupts are disabled on entering
- */static void
-pnx8xxx_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct pnx8xxx_port *sport = &pnx8xxx_ports[co->index];
- unsigned int old_ien, status;
-
- /*
- * First, save IEN and then disable interrupts
- */
- old_ien = serial_in(sport, PNX8XXX_IEN);
- serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
- PNX8XXX_UART_INT_ALLRX));
-
- uart_console_write(&sport->port, s, count, pnx8xxx_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore IEN
- */
- do {
- /* Wait for UART_TX register to empty */
- status = serial_in(sport, PNX8XXX_FIFO);
- } while (status & PNX8XXX_UART_FIFO_TXFIFO);
-
- /* Clear TX and EMPTY interrupt */
- serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX |
- PNX8XXX_UART_INT_EMPTY);
-
- serial_out(sport, PNX8XXX_IEN, old_ien);
-}
-
-static int __init
-pnx8xxx_console_setup(struct console *co, char *options)
-{
- struct pnx8xxx_port *sport;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index == -1 || co->index >= NR_PORTS)
- co->index = 0;
- sport = &pnx8xxx_ports[co->index];
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver pnx8xxx_reg;
-static struct console pnx8xxx_console = {
- .name = "ttyS",
- .write = pnx8xxx_console_write,
- .device = uart_console_device,
- .setup = pnx8xxx_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &pnx8xxx_reg,
-};
-
-static int __init pnx8xxx_rs_console_init(void)
-{
- pnx8xxx_init_ports();
- register_console(&pnx8xxx_console);
- return 0;
-}
-console_initcall(pnx8xxx_rs_console_init);
-
-#define PNX8XXX_CONSOLE &pnx8xxx_console
-#else
-#define PNX8XXX_CONSOLE NULL
-#endif
-
-static struct uart_driver pnx8xxx_reg = {
- .owner = THIS_MODULE,
- .driver_name = "ttyS",
- .dev_name = "ttyS",
- .major = SERIAL_PNX8XXX_MAJOR,
- .minor = MINOR_START,
- .nr = NR_PORTS,
- .cons = PNX8XXX_CONSOLE,
-};
-
-static int pnx8xxx_serial_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
-
- return uart_suspend_port(&pnx8xxx_reg, &sport->port);
-}
-
-static int pnx8xxx_serial_resume(struct platform_device *pdev)
-{
- struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
-
- return uart_resume_port(&pnx8xxx_reg, &sport->port);
-}
-
-static int pnx8xxx_serial_probe(struct platform_device *pdev)
-{
- struct resource *res = pdev->resource;
- int i;
-
- for (i = 0; i < pdev->num_resources; i++, res++) {
- if (!(res->flags & IORESOURCE_MEM))
- continue;
-
- for (i = 0; i < NR_PORTS; i++) {
- if (pnx8xxx_ports[i].port.mapbase != res->start)
- continue;
-
- pnx8xxx_ports[i].port.dev = &pdev->dev;
- uart_add_one_port(&pnx8xxx_reg, &pnx8xxx_ports[i].port);
- platform_set_drvdata(pdev, &pnx8xxx_ports[i]);
- break;
- }
- }
-
- return 0;
-}
-
-static int pnx8xxx_serial_remove(struct platform_device *pdev)
-{
- struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
-
- if (sport)
- uart_remove_one_port(&pnx8xxx_reg, &sport->port);
-
- return 0;
-}
-
-static struct platform_driver pnx8xxx_serial_driver = {
- .driver = {
- .name = "pnx8xxx-uart",
- .owner = THIS_MODULE,
- },
- .probe = pnx8xxx_serial_probe,
- .remove = pnx8xxx_serial_remove,
- .suspend = pnx8xxx_serial_suspend,
- .resume = pnx8xxx_serial_resume,
-};
-
-static int __init pnx8xxx_serial_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: PNX8XXX driver\n");
-
- pnx8xxx_init_ports();
-
- ret = uart_register_driver(&pnx8xxx_reg);
- if (ret == 0) {
- ret = platform_driver_register(&pnx8xxx_serial_driver);
- if (ret)
- uart_unregister_driver(&pnx8xxx_reg);
- }
- return ret;
-}
-
-static void __exit pnx8xxx_serial_exit(void)
-{
- platform_driver_unregister(&pnx8xxx_serial_driver);
- uart_unregister_driver(&pnx8xxx_reg);
-}
-
-module_init(pnx8xxx_serial_init);
-module_exit(pnx8xxx_serial_exit);
-
-MODULE_AUTHOR("Embedded Alley Solutions, Inc.");
-MODULE_DESCRIPTION("PNX8XXX SoCs serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8XXX_MAJOR);
-MODULE_ALIAS("platform:pnx8xxx-uart");
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
deleted file mode 100644
index 1102a39b44f5..000000000000
--- a/drivers/serial/pxa.c
+++ /dev/null
@@ -1,879 +0,0 @@
-/*
- * linux/drivers/serial/pxa.c
- *
- * Based on drivers/serial/8250.c by Russell King.
- *
- * Author: Nicolas Pitre
- * Created: Feb 20, 2003
- * Copyright: (C) 2003 Monta Vista Software, 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.
- *
- * Note 1: This driver is made separate from the already too overloaded
- * 8250.c because it needs some kirks of its own and that'll make it
- * easier to add DMA support.
- *
- * Note 2: I'm too sick of device allocation policies for serial ports.
- * If someone else wants to request an "official" allocation of major/minor
- * for this driver please be my guest. And don't forget that new hardware
- * to come from Intel might have more than 3 or 4 of those UARTs. Let's
- * hope for a better port registration and dynamic device allocation scheme
- * with the serial core maintainer satisfaction to appear soon.
- */
-
-
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-struct uart_pxa_port {
- struct uart_port port;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr;
- unsigned int lsr_break_flag;
- struct clk *clk;
- char *name;
-};
-
-static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
-{
- offset <<= 2;
- return readl(up->port.membase + offset);
-}
-
-static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
-{
- offset <<= 2;
- writel(value, up->port.membase + offset);
-}
-
-static void serial_pxa_enable_ms(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void serial_pxa_stop_tx(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial_pxa_stop_rx(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static inline void receive_chars(struct uart_pxa_port *up, int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned int ch, flag;
- int max_count = 256;
-
- do {
- ch = serial_in(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE))) {
- /*
- * For statistics only
- */
- if (*status & UART_LSR_BI) {
- *status &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (*status & UART_LSR_PE)
- up->port.icount.parity++;
- else if (*status & UART_LSR_FE)
- up->port.icount.frame++;
- if (*status & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- *status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- *status |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-#endif
- if (*status & UART_LSR_BI) {
- flag = TTY_BREAK;
- } else if (*status & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (*status & UART_LSR_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
-
- uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-
- ignore_char:
- *status = serial_in(up, UART_LSR);
- } while ((*status & UART_LSR_DR) && (max_count-- > 0));
- tty_flip_buffer_push(tty);
-}
-
-static void transmit_chars(struct uart_pxa_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_out(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_pxa_stop_tx(&up->port);
- return;
- }
-
- count = up->port.fifosize / 2;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
-
- if (uart_circ_empty(xmit))
- serial_pxa_stop_tx(&up->port);
-}
-
-static void serial_pxa_start_tx(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static inline void check_modem_status(struct uart_pxa_port *up)
-{
- int status;
-
- status = serial_in(up, UART_MSR);
-
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return;
-
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
-{
- struct uart_pxa_port *up = dev_id;
- unsigned int iir, lsr;
-
- iir = serial_in(up, UART_IIR);
- if (iir & UART_IIR_NO_INT)
- return IRQ_NONE;
- lsr = serial_in(up, UART_LSR);
- if (lsr & UART_LSR_DR)
- receive_chars(up, &lsr);
- check_modem_status(up);
- if (lsr & UART_LSR_THRE)
- transmit_chars(up);
- return IRQ_HANDLED;
-}
-
-static unsigned int serial_pxa_tx_empty(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- unsigned char status;
- unsigned int ret;
-
- status = serial_in(up, UART_MSR);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr |= up->mcr;
-
- serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-#if 0
-static void serial_pxa_dma_init(struct pxa_uart *up)
-{
- up->rxdma =
- pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_receive_dma, up);
- if (up->rxdma < 0)
- goto out;
- up->txdma =
- pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_transmit_dma, up);
- if (up->txdma < 0)
- goto err_txdma;
- up->dmadesc = kmalloc(4 * sizeof(pxa_dma_desc), GFP_KERNEL);
- if (!up->dmadesc)
- goto err_alloc;
-
- /* ... */
-err_alloc:
- pxa_free_dma(up->txdma);
-err_rxdma:
- pxa_free_dma(up->rxdma);
-out:
- return;
-}
-#endif
-
-static int serial_pxa_startup(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- unsigned long flags;
- int retval;
-
- if (port->line == 3) /* HWUART */
- up->mcr |= UART_MCR_AFE;
- else
- up->mcr = 0;
-
- up->port.uartclk = clk_get_rate(up->clk);
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
- if (retval)
- return retval;
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_out(up, UART_FCR, 0);
-
- /*
- * Clear the interrupt registers.
- */
- (void) serial_in(up, UART_LSR);
- (void) serial_in(up, UART_RX);
- (void) serial_in(up, UART_IIR);
- (void) serial_in(up, UART_MSR);
-
- /*
- * Now, initialize the UART
- */
- serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&up->port.lock, flags);
- up->port.mctrl |= TIOCM_OUT2;
- serial_pxa_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
- serial_out(up, UART_IER, up->ier);
-
- /*
- * And clear the interrupt registers again for luck.
- */
- (void) serial_in(up, UART_LSR);
- (void) serial_in(up, UART_RX);
- (void) serial_in(up, UART_IIR);
- (void) serial_in(up, UART_MSR);
-
- return 0;
-}
-
-static void serial_pxa_shutdown(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- unsigned long flags;
-
- free_irq(up->port.irq, up);
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_out(up, UART_IER, 0);
-
- spin_lock_irqsave(&up->port.lock, flags);
- up->port.mctrl &= ~TIOCM_OUT2;
- serial_pxa_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT);
- serial_out(up, UART_FCR, 0);
-}
-
-static void
-serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- unsigned char cval, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
- unsigned int dll;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- if ((up->port.uartclk / quot) < (2400 * 16))
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
- else if ((up->port.uartclk / quot) < (230400 * 16))
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
- else
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Ensure the port will be enabled.
- * This is required especially for serial console.
- */
- up->ier |= UART_IER_UUE;
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characters to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
-
- serial_out(up, UART_IER, up->ier);
-
- if (termios->c_cflag & CRTSCTS)
- up->mcr |= UART_MCR_AFE;
- else
- up->mcr &= ~UART_MCR_AFE;
-
- serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
- serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
-
- /*
- * work around Errata #75 according to Intel(R) PXA27x Processor Family
- * Specification Update (Nov 2005)
- */
- dll = serial_in(up, UART_DLL);
- WARN_ON(dll != (quot & 0xff));
-
- serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
- serial_out(up, UART_LCR, cval); /* reset DLAB */
- up->lcr = cval; /* Save LCR */
- serial_pxa_set_mctrl(&up->port, up->port.mctrl);
- serial_out(up, UART_FCR, fcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_pxa_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
- if (!state)
- clk_enable(up->clk);
- else
- clk_disable(up->clk);
-}
-
-static void serial_pxa_release_port(struct uart_port *port)
-{
-}
-
-static int serial_pxa_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void serial_pxa_config_port(struct uart_port *port, int flags)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- up->port.type = PORT_PXA;
-}
-
-static int
-serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- /* we don't want the core code to modify any port params */
- return -EINVAL;
-}
-
-static const char *
-serial_pxa_type(struct uart_port *port)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- return up->name;
-}
-
-static struct uart_pxa_port *serial_pxa_ports[4];
-static struct uart_driver serial_pxa_reg;
-
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_pxa_port *up)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = serial_in(up, UART_LSR);
-
- if (status & UART_LSR_BI)
- up->lsr_break_flag = UART_LSR_BI;
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
- udelay(1);
- }
-}
-
-static void serial_pxa_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-
- wait_for_xmitr(up);
- serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void
-serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_pxa_port *up = serial_pxa_ports[co->index];
- unsigned int ier;
-
- clk_enable(up->clk);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, UART_IER_UUE);
-
- uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- serial_out(up, UART_IER, ier);
-
- clk_disable(up->clk);
-}
-
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
-{
- struct uart_pxa_port *up;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (co->index == -1 || co->index >= serial_pxa_reg.nr)
- co->index = 0;
- up = serial_pxa_ports[co->index];
- if (!up)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_pxa_console = {
- .name = "ttyS",
- .write = serial_pxa_console_write,
- .device = uart_console_device,
- .setup = serial_pxa_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &serial_pxa_reg,
-};
-
-#define PXA_CONSOLE &serial_pxa_console
-#else
-#define PXA_CONSOLE NULL
-#endif
-
-struct uart_ops serial_pxa_pops = {
- .tx_empty = serial_pxa_tx_empty,
- .set_mctrl = serial_pxa_set_mctrl,
- .get_mctrl = serial_pxa_get_mctrl,
- .stop_tx = serial_pxa_stop_tx,
- .start_tx = serial_pxa_start_tx,
- .stop_rx = serial_pxa_stop_rx,
- .enable_ms = serial_pxa_enable_ms,
- .break_ctl = serial_pxa_break_ctl,
- .startup = serial_pxa_startup,
- .shutdown = serial_pxa_shutdown,
- .set_termios = serial_pxa_set_termios,
- .pm = serial_pxa_pm,
- .type = serial_pxa_type,
- .release_port = serial_pxa_release_port,
- .request_port = serial_pxa_request_port,
- .config_port = serial_pxa_config_port,
- .verify_port = serial_pxa_verify_port,
-};
-
-static struct uart_driver serial_pxa_reg = {
- .owner = THIS_MODULE,
- .driver_name = "PXA serial",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = 4,
- .cons = PXA_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_pxa_suspend(struct device *dev)
-{
- struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
- if (sport)
- uart_suspend_port(&serial_pxa_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_pxa_resume(struct device *dev)
-{
- struct uart_pxa_port *sport = dev_get_drvdata(dev);
-
- if (sport)
- uart_resume_port(&serial_pxa_reg, &sport->port);
-
- return 0;
-}
-
-static const struct dev_pm_ops serial_pxa_pm_ops = {
- .suspend = serial_pxa_suspend,
- .resume = serial_pxa_resume,
-};
-#endif
-
-static int serial_pxa_probe(struct platform_device *dev)
-{
- struct uart_pxa_port *sport;
- struct resource *mmres, *irqres;
- int ret;
-
- mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
- irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
- if (!mmres || !irqres)
- return -ENODEV;
-
- sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
- if (!sport)
- return -ENOMEM;
-
- sport->clk = clk_get(&dev->dev, NULL);
- if (IS_ERR(sport->clk)) {
- ret = PTR_ERR(sport->clk);
- goto err_free;
- }
-
- sport->port.type = PORT_PXA;
- sport->port.iotype = UPIO_MEM;
- sport->port.mapbase = mmres->start;
- sport->port.irq = irqres->start;
- sport->port.fifosize = 64;
- sport->port.ops = &serial_pxa_pops;
- sport->port.line = dev->id;
- sport->port.dev = &dev->dev;
- sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
- sport->port.uartclk = clk_get_rate(sport->clk);
-
- switch (dev->id) {
- case 0: sport->name = "FFUART"; break;
- case 1: sport->name = "BTUART"; break;
- case 2: sport->name = "STUART"; break;
- case 3: sport->name = "HWUART"; break;
- default:
- sport->name = "???";
- break;
- }
-
- sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1);
- if (!sport->port.membase) {
- ret = -ENOMEM;
- goto err_clk;
- }
-
- serial_pxa_ports[dev->id] = sport;
-
- uart_add_one_port(&serial_pxa_reg, &sport->port);
- platform_set_drvdata(dev, sport);
-
- return 0;
-
- err_clk:
- clk_put(sport->clk);
- err_free:
- kfree(sport);
- return ret;
-}
-
-static int serial_pxa_remove(struct platform_device *dev)
-{
- struct uart_pxa_port *sport = platform_get_drvdata(dev);
-
- platform_set_drvdata(dev, NULL);
-
- uart_remove_one_port(&serial_pxa_reg, &sport->port);
- clk_put(sport->clk);
- kfree(sport);
-
- return 0;
-}
-
-static struct platform_driver serial_pxa_driver = {
- .probe = serial_pxa_probe,
- .remove = serial_pxa_remove,
-
- .driver = {
- .name = "pxa2xx-uart",
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .pm = &serial_pxa_pm_ops,
-#endif
- },
-};
-
-int __init serial_pxa_init(void)
-{
- int ret;
-
- ret = uart_register_driver(&serial_pxa_reg);
- if (ret != 0)
- return ret;
-
- ret = platform_driver_register(&serial_pxa_driver);
- if (ret != 0)
- uart_unregister_driver(&serial_pxa_reg);
-
- return ret;
-}
-
-void __exit serial_pxa_exit(void)
-{
- platform_driver_unregister(&serial_pxa_driver);
- uart_unregister_driver(&serial_pxa_reg);
-}
-
-module_init(serial_pxa_init);
-module_exit(serial_pxa_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-uart");
diff --git a/drivers/serial/s3c2400.c b/drivers/serial/s3c2400.c
deleted file mode 100644
index fed1a9a1ffb4..000000000000
--- a/drivers/serial/s3c2400.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* linux/drivers/serial/s3c240.c
- *
- * Driver for Samsung SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c2400_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- clk->divisor = 1;
- clk->name = "pclk";
-
- return 0;
-}
-
-static int s3c2400_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- return 0;
-}
-
-static int s3c2400_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- wr_regl(port, S3C2410_UCON, cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c2400_uart_inf = {
- .name = "Samsung S3C2400 UART",
- .type = PORT_S3C2400,
- .fifosize = 16,
- .rx_fifomask = S3C2410_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2410_UFSTAT_RXFULL,
- .tx_fifofull = S3C2410_UFSTAT_TXFULL,
- .tx_fifomask = S3C2410_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
- .get_clksrc = s3c2400_serial_getsource,
- .set_clksrc = s3c2400_serial_setsource,
- .reset_port = s3c2400_serial_resetport,
-};
-
-static int s3c2400_serial_probe(struct platform_device *dev)
-{
- return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
-}
-
-static struct platform_driver s3c2400_serial_driver = {
- .probe = s3c2400_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c2400-uart",
- .owner = THIS_MODULE,
- },
-};
-
-s3c24xx_console_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
-
-static inline int s3c2400_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
-}
-
-static inline void s3c2400_serial_exit(void)
-{
- platform_driver_unregister(&s3c2400_serial_driver);
-}
-
-module_init(s3c2400_serial_init);
-module_exit(s3c2400_serial_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C2400 SoC Serial port driver");
-MODULE_ALIAS("platform:s3c2400-uart");
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
deleted file mode 100644
index 73f089d3efd6..000000000000
--- a/drivers/serial/s3c2410.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* linux/drivers/serial/s3c2410.c
- *
- * Driver for Samsung S3C2410 SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c2410_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- if (strcmp(clk->name, "uclk") == 0)
- ucon |= S3C2410_UCON_UCLK;
- else
- ucon &= ~S3C2410_UCON_UCLK;
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-static int s3c2410_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- clk->divisor = 1;
- clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
-
- return 0;
-}
-
-static int s3c2410_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- dbg("s3c2410_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- wr_regl(port, S3C2410_UCON, cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c2410_uart_inf = {
- .name = "Samsung S3C2410 UART",
- .type = PORT_S3C2410,
- .fifosize = 16,
- .rx_fifomask = S3C2410_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2410_UFSTAT_RXFULL,
- .tx_fifofull = S3C2410_UFSTAT_TXFULL,
- .tx_fifomask = S3C2410_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
- .get_clksrc = s3c2410_serial_getsource,
- .set_clksrc = s3c2410_serial_setsource,
- .reset_port = s3c2410_serial_resetport,
-};
-
-static int s3c2410_serial_probe(struct platform_device *dev)
-{
- return s3c24xx_serial_probe(dev, &s3c2410_uart_inf);
-}
-
-static struct platform_driver s3c2410_serial_driver = {
- .probe = s3c2410_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c2410-uart",
- .owner = THIS_MODULE,
- },
-};
-
-s3c24xx_console_init(&s3c2410_serial_driver, &s3c2410_uart_inf);
-
-static int __init s3c2410_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c2410_serial_driver, &s3c2410_uart_inf);
-}
-
-static void __exit s3c2410_serial_exit(void)
-{
- platform_driver_unregister(&s3c2410_serial_driver);
-}
-
-module_init(s3c2410_serial_init);
-module_exit(s3c2410_serial_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C2410 SoC Serial port driver");
-MODULE_ALIAS("platform:s3c2410-uart");
diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c
deleted file mode 100644
index 1700b1a2fb7e..000000000000
--- a/drivers/serial/s3c2412.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* linux/drivers/serial/s3c2412.c
- *
- * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c2412_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- ucon &= ~S3C2412_UCON_CLKMASK;
-
- if (strcmp(clk->name, "uclk") == 0)
- ucon |= S3C2440_UCON_UCLK;
- else if (strcmp(clk->name, "pclk") == 0)
- ucon |= S3C2440_UCON_PCLK;
- else if (strcmp(clk->name, "usysclk") == 0)
- ucon |= S3C2412_UCON_USYSCLK;
- else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s3c2412_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- switch (ucon & S3C2412_UCON_CLKMASK) {
- case S3C2412_UCON_UCLK:
- clk->divisor = 1;
- clk->name = "uclk";
- break;
-
- case S3C2412_UCON_PCLK:
- case S3C2412_UCON_PCLK2:
- clk->divisor = 1;
- clk->name = "pclk";
- break;
-
- case S3C2412_UCON_USYSCLK:
- clk->divisor = 1;
- clk->name = "usysclk";
- break;
- }
-
- return 0;
-}
-
-static int s3c2412_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- dbg("%s: port=%p (%08lx), cfg=%p\n",
- __func__, port, port->mapbase, cfg);
-
- /* ensure we don't change the clock settings... */
-
- ucon &= S3C2412_UCON_CLKMASK;
-
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c2412_uart_inf = {
- .name = "Samsung S3C2412 UART",
- .type = PORT_S3C2412,
- .fifosize = 64,
- .has_divslot = 1,
- .rx_fifomask = S3C2440_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2440_UFSTAT_RXFULL,
- .tx_fifofull = S3C2440_UFSTAT_TXFULL,
- .tx_fifomask = S3C2440_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
- .get_clksrc = s3c2412_serial_getsource,
- .set_clksrc = s3c2412_serial_setsource,
- .reset_port = s3c2412_serial_resetport,
-};
-
-/* device management */
-
-static int s3c2412_serial_probe(struct platform_device *dev)
-{
- dbg("s3c2440_serial_probe: dev=%p\n", dev);
- return s3c24xx_serial_probe(dev, &s3c2412_uart_inf);
-}
-
-static struct platform_driver s3c2412_serial_driver = {
- .probe = s3c2412_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c2412-uart",
- .owner = THIS_MODULE,
- },
-};
-
-s3c24xx_console_init(&s3c2412_serial_driver, &s3c2412_uart_inf);
-
-static inline int s3c2412_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c2412_serial_driver, &s3c2412_uart_inf);
-}
-
-static inline void s3c2412_serial_exit(void)
-{
- platform_driver_unregister(&s3c2412_serial_driver);
-}
-
-module_init(s3c2412_serial_init);
-module_exit(s3c2412_serial_exit);
-
-MODULE_DESCRIPTION("Samsung S3C2412,S3C2413 SoC Serial port driver");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:s3c2412-uart");
diff --git a/drivers/serial/s3c2440.c b/drivers/serial/s3c2440.c
deleted file mode 100644
index 094cc3904b13..000000000000
--- a/drivers/serial/s3c2440.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* linux/drivers/serial/s3c2440.c
- *
- * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-
-static int s3c2440_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- /* todo - proper fclk<>nonfclk switch. */
-
- ucon &= ~S3C2440_UCON_CLKMASK;
-
- if (strcmp(clk->name, "uclk") == 0)
- ucon |= S3C2440_UCON_UCLK;
- else if (strcmp(clk->name, "pclk") == 0)
- ucon |= S3C2440_UCON_PCLK;
- else if (strcmp(clk->name, "fclk") == 0)
- ucon |= S3C2440_UCON_FCLK;
- else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s3c2440_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
- unsigned long ucon0, ucon1, ucon2;
-
- switch (ucon & S3C2440_UCON_CLKMASK) {
- case S3C2440_UCON_UCLK:
- clk->divisor = 1;
- clk->name = "uclk";
- break;
-
- case S3C2440_UCON_PCLK:
- case S3C2440_UCON_PCLK2:
- clk->divisor = 1;
- clk->name = "pclk";
- break;
-
- case S3C2440_UCON_FCLK:
- /* the fun of calculating the uart divisors on
- * the s3c2440 */
-
- ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
- ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
- ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
-
- printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
-
- ucon0 &= S3C2440_UCON0_DIVMASK;
- ucon1 &= S3C2440_UCON1_DIVMASK;
- ucon2 &= S3C2440_UCON2_DIVMASK;
-
- if (ucon0 != 0) {
- clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT;
- clk->divisor += 6;
- } else if (ucon1 != 0) {
- clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT;
- clk->divisor += 21;
- } else if (ucon2 != 0) {
- clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT;
- clk->divisor += 36;
- } else {
- /* manual calims 44, seems to be 9 */
- clk->divisor = 9;
- }
-
- clk->name = "fclk";
- break;
- }
-
- return 0;
-}
-
-static int s3c2440_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- /* ensure we don't change the clock settings... */
-
- ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
-
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c2440_uart_inf = {
- .name = "Samsung S3C2440 UART",
- .type = PORT_S3C2440,
- .fifosize = 64,
- .rx_fifomask = S3C2440_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2440_UFSTAT_RXFULL,
- .tx_fifofull = S3C2440_UFSTAT_TXFULL,
- .tx_fifomask = S3C2440_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
- .get_clksrc = s3c2440_serial_getsource,
- .set_clksrc = s3c2440_serial_setsource,
- .reset_port = s3c2440_serial_resetport,
-};
-
-/* device management */
-
-static int s3c2440_serial_probe(struct platform_device *dev)
-{
- dbg("s3c2440_serial_probe: dev=%p\n", dev);
- return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
-}
-
-static struct platform_driver s3c2440_serial_driver = {
- .probe = s3c2440_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c2440-uart",
- .owner = THIS_MODULE,
- },
-};
-
-s3c24xx_console_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
-
-static int __init s3c2440_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
-}
-
-static void __exit s3c2440_serial_exit(void)
-{
- platform_driver_unregister(&s3c2440_serial_driver);
-}
-
-module_init(s3c2440_serial_init);
-module_exit(s3c2440_serial_exit);
-
-MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:s3c2440-uart");
diff --git a/drivers/serial/s3c24a0.c b/drivers/serial/s3c24a0.c
deleted file mode 100644
index fad6083ca427..000000000000
--- a/drivers/serial/s3c24a0.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* linux/drivers/serial/s3c24a0.c
- *
- * Driver for Samsung S3C24A0 SoC onboard UARTs.
- *
- * Based on drivers/serial/s3c2410.c
- *
- * Author: Sandeep Patil <sandeep.patil@azingo.com>
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c24a0_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- if (strcmp(clk->name, "uclk") == 0)
- ucon |= S3C2410_UCON_UCLK;
- else
- ucon &= ~S3C2410_UCON_UCLK;
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-static int s3c24a0_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- clk->divisor = 1;
- clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
-
- return 0;
-}
-
-static int s3c24a0_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- dbg("s3c24a0_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- wr_regl(port, S3C2410_UCON, cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c24a0_uart_inf = {
- .name = "Samsung S3C24A0 UART",
- .type = PORT_S3C2410,
- .fifosize = 16,
- .rx_fifomask = S3C24A0_UFSTAT_RXMASK,
- .rx_fifoshift = S3C24A0_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C24A0_UFSTAT_RXFULL,
- .tx_fifofull = S3C24A0_UFSTAT_TXFULL,
- .tx_fifomask = S3C24A0_UFSTAT_TXMASK,
- .tx_fifoshift = S3C24A0_UFSTAT_TXSHIFT,
- .get_clksrc = s3c24a0_serial_getsource,
- .set_clksrc = s3c24a0_serial_setsource,
- .reset_port = s3c24a0_serial_resetport,
-};
-
-static int s3c24a0_serial_probe(struct platform_device *dev)
-{
- return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf);
-}
-
-static struct platform_driver s3c24a0_serial_driver = {
- .probe = s3c24a0_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c24a0-uart",
- .owner = THIS_MODULE,
- },
-};
-
-s3c24xx_console_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
-
-static int __init s3c24a0_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
-}
-
-static void __exit s3c24a0_serial_exit(void)
-{
- platform_driver_unregister(&s3c24a0_serial_driver);
-}
-
-module_init(s3c24a0_serial_init);
-module_exit(s3c24a0_serial_exit);
-
diff --git a/drivers/serial/s3c6400.c b/drivers/serial/s3c6400.c
deleted file mode 100644
index 4be92ab50058..000000000000
--- a/drivers/serial/s3c6400.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* linux/drivers/serial/s3c6400.c
- *
- * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs.
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-
-#include "samsung.h"
-
-static int s3c6400_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- if (strcmp(clk->name, "uclk0") == 0) {
- ucon &= ~S3C6400_UCON_CLKMASK;
- ucon |= S3C6400_UCON_UCLK0;
- } else if (strcmp(clk->name, "uclk1") == 0)
- ucon |= S3C6400_UCON_UCLK1;
- else if (strcmp(clk->name, "pclk") == 0) {
- /* See notes about transitioning from UCLK to PCLK */
- ucon &= ~S3C6400_UCON_UCLK0;
- } else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s3c6400_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- u32 ucon = rd_regl(port, S3C2410_UCON);
-
- clk->divisor = 1;
-
- switch (ucon & S3C6400_UCON_CLKMASK) {
- case S3C6400_UCON_UCLK0:
- clk->name = "uclk0";
- break;
-
- case S3C6400_UCON_UCLK1:
- clk->name = "uclk1";
- break;
-
- case S3C6400_UCON_PCLK:
- case S3C6400_UCON_PCLK2:
- clk->name = "pclk";
- break;
- }
-
- return 0;
-}
-
-static int s3c6400_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- /* ensure we don't change the clock settings... */
-
- ucon &= S3C6400_UCON_CLKMASK;
-
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c6400_uart_inf = {
- .name = "Samsung S3C6400 UART",
- .type = PORT_S3C6400,
- .fifosize = 64,
- .has_divslot = 1,
- .rx_fifomask = S3C2440_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2440_UFSTAT_RXFULL,
- .tx_fifofull = S3C2440_UFSTAT_TXFULL,
- .tx_fifomask = S3C2440_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
- .get_clksrc = s3c6400_serial_getsource,
- .set_clksrc = s3c6400_serial_setsource,
- .reset_port = s3c6400_serial_resetport,
-};
-
-/* device management */
-
-static int s3c6400_serial_probe(struct platform_device *dev)
-{
- dbg("s3c6400_serial_probe: dev=%p\n", dev);
- return s3c24xx_serial_probe(dev, &s3c6400_uart_inf);
-}
-
-static struct platform_driver s3c6400_serial_driver = {
- .probe = s3c6400_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c6400-uart",
- .owner = THIS_MODULE,
- },
-};
-
-s3c24xx_console_init(&s3c6400_serial_driver, &s3c6400_uart_inf);
-
-static int __init s3c6400_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c6400_serial_driver, &s3c6400_uart_inf);
-}
-
-static void __exit s3c6400_serial_exit(void)
-{
- platform_driver_unregister(&s3c6400_serial_driver);
-}
-
-module_init(s3c6400_serial_init);
-module_exit(s3c6400_serial_exit);
-
-MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:s3c6400-uart");
diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c
deleted file mode 100644
index 6ebccd70a707..000000000000
--- a/drivers/serial/s5pv210.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* linux/drivers/serial/s5pv210.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Based on drivers/serial/s3c6400.c
- *
- * Driver for Samsung S5PV210 SoC UARTs.
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <plat/regs-serial.h>
-#include "samsung.h"
-
-static int s5pv210_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- struct s3c2410_uartcfg *cfg = port->dev->platform_data;
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- if ((cfg->clocks_size) == 1)
- return 0;
-
- if (strcmp(clk->name, "pclk") == 0)
- ucon &= ~S5PV210_UCON_CLKMASK;
- else if (strcmp(clk->name, "uclk1") == 0)
- ucon |= S5PV210_UCON_CLKMASK;
- else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s5pv210_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- struct s3c2410_uartcfg *cfg = port->dev->platform_data;
- u32 ucon = rd_regl(port, S3C2410_UCON);
-
- clk->divisor = 1;
-
- if ((cfg->clocks_size) == 1)
- return 0;
-
- switch (ucon & S5PV210_UCON_CLKMASK) {
- case S5PV210_UCON_PCLK:
- clk->name = "pclk";
- break;
- case S5PV210_UCON_UCLK:
- clk->name = "uclk1";
- break;
- }
-
- return 0;
-}
-
-static int s5pv210_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- ucon &= S5PV210_UCON_CLKMASK;
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-#define S5PV210_UART_DEFAULT_INFO(fifo_size) \
- .name = "Samsung S5PV210 UART0", \
- .type = PORT_S3C6400, \
- .fifosize = fifo_size, \
- .has_divslot = 1, \
- .rx_fifomask = S5PV210_UFSTAT_RXMASK, \
- .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \
- .rx_fifofull = S5PV210_UFSTAT_RXFULL, \
- .tx_fifofull = S5PV210_UFSTAT_TXFULL, \
- .tx_fifomask = S5PV210_UFSTAT_TXMASK, \
- .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, \
- .get_clksrc = s5pv210_serial_getsource, \
- .set_clksrc = s5pv210_serial_setsource, \
- .reset_port = s5pv210_serial_resetport
-
-static struct s3c24xx_uart_info s5p_port_fifo256 = {
- S5PV210_UART_DEFAULT_INFO(256),
-};
-
-static struct s3c24xx_uart_info s5p_port_fifo64 = {
- S5PV210_UART_DEFAULT_INFO(64),
-};
-
-static struct s3c24xx_uart_info s5p_port_fifo16 = {
- S5PV210_UART_DEFAULT_INFO(16),
-};
-
-static struct s3c24xx_uart_info *s5p_uart_inf[] = {
- [0] = &s5p_port_fifo256,
- [1] = &s5p_port_fifo64,
- [2] = &s5p_port_fifo16,
- [3] = &s5p_port_fifo16,
-};
-
-/* device management */
-static int s5p_serial_probe(struct platform_device *pdev)
-{
- return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]);
-}
-
-static struct platform_driver s5p_serial_driver = {
- .probe = s5p_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s5pv210-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s5pv210_serial_console_init(void)
-{
- return s3c24xx_serial_initconsole(&s5p_serial_driver, s5p_uart_inf);
-}
-
-console_initcall(s5pv210_serial_console_init);
-
-static int __init s5p_serial_init(void)
-{
- return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf);
-}
-
-static void __exit s5p_serial_exit(void)
-{
- platform_driver_unregister(&s5p_serial_driver);
-}
-
-module_init(s5p_serial_init);
-module_exit(s5p_serial_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s5pv210-uart");
-MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support");
-MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
deleted file mode 100644
index 2199d819a987..000000000000
--- a/drivers/serial/sa1100.c
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * linux/drivers/char/sa1100.c
- *
- * Driver for SA11x0 serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/mach/serial_sa1100.h>
-
-/* We've been assigned a range on the "Low-density serial ports" major */
-#define SERIAL_SA1100_MAJOR 204
-#define MINOR_START 5
-
-#define NR_PORTS 3
-
-#define SA1100_ISR_PASS_LIMIT 256
-
-/*
- * Convert from ignore_status_mask or read_status_mask to UTSR[01]
- */
-#define SM_TO_UTSR0(x) ((x) & 0xff)
-#define SM_TO_UTSR1(x) ((x) >> 8)
-#define UTSR0_TO_SM(x) ((x))
-#define UTSR1_TO_SM(x) ((x) << 8)
-
-#define UART_GET_UTCR0(sport) __raw_readl((sport)->port.membase + UTCR0)
-#define UART_GET_UTCR1(sport) __raw_readl((sport)->port.membase + UTCR1)
-#define UART_GET_UTCR2(sport) __raw_readl((sport)->port.membase + UTCR2)
-#define UART_GET_UTCR3(sport) __raw_readl((sport)->port.membase + UTCR3)
-#define UART_GET_UTSR0(sport) __raw_readl((sport)->port.membase + UTSR0)
-#define UART_GET_UTSR1(sport) __raw_readl((sport)->port.membase + UTSR1)
-#define UART_GET_CHAR(sport) __raw_readl((sport)->port.membase + UTDR)
-
-#define UART_PUT_UTCR0(sport,v) __raw_writel((v),(sport)->port.membase + UTCR0)
-#define UART_PUT_UTCR1(sport,v) __raw_writel((v),(sport)->port.membase + UTCR1)
-#define UART_PUT_UTCR2(sport,v) __raw_writel((v),(sport)->port.membase + UTCR2)
-#define UART_PUT_UTCR3(sport,v) __raw_writel((v),(sport)->port.membase + UTCR3)
-#define UART_PUT_UTSR0(sport,v) __raw_writel((v),(sport)->port.membase + UTSR0)
-#define UART_PUT_UTSR1(sport,v) __raw_writel((v),(sport)->port.membase + UTSR1)
-#define UART_PUT_CHAR(sport,v) __raw_writel((v),(sport)->port.membase + UTDR)
-
-/*
- * This is the size of our serial port register set.
- */
-#define UART_PORT_SIZE 0x24
-
-/*
- * This determines how often we check the modem status signals
- * for any change. They generally aren't connected to an IRQ
- * so we have to poll them. We also check immediately before
- * filling the TX fifo incase CTS has been dropped.
- */
-#define MCTRL_TIMEOUT (250*HZ/1000)
-
-struct sa1100_port {
- struct uart_port port;
- struct timer_list timer;
- unsigned int old_status;
-};
-
-/*
- * Handle any change of modem status signal since we were last called.
- */
-static void sa1100_mctrl_check(struct sa1100_port *sport)
-{
- unsigned int status, changed;
-
- status = sport->port.ops->get_mctrl(&sport->port);
- changed = status ^ sport->old_status;
-
- if (changed == 0)
- return;
-
- sport->old_status = status;
-
- if (changed & TIOCM_RI)
- sport->port.icount.rng++;
- if (changed & TIOCM_DSR)
- sport->port.icount.dsr++;
- if (changed & TIOCM_CAR)
- uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
- if (changed & TIOCM_CTS)
- uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
-
- wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
-}
-
-/*
- * This is our per-port timeout handler, for checking the
- * modem status signals.
- */
-static void sa1100_timeout(unsigned long data)
-{
- struct sa1100_port *sport = (struct sa1100_port *)data;
- unsigned long flags;
-
- if (sport->port.state) {
- spin_lock_irqsave(&sport->port.lock, flags);
- sa1100_mctrl_check(sport);
- spin_unlock_irqrestore(&sport->port.lock, flags);
-
- mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
- }
-}
-
-/*
- * interrupts disabled on entry
- */
-static void sa1100_stop_tx(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
- u32 utcr3;
-
- utcr3 = UART_GET_UTCR3(sport);
- UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE);
- sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
-}
-
-/*
- * port locked and interrupts disabled
- */
-static void sa1100_start_tx(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
- u32 utcr3;
-
- utcr3 = UART_GET_UTCR3(sport);
- sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
- UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
-}
-
-/*
- * Interrupts enabled
- */
-static void sa1100_stop_rx(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
- u32 utcr3;
-
- utcr3 = UART_GET_UTCR3(sport);
- UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
-}
-
-/*
- * Set the modem control timer to fire immediately.
- */
-static void sa1100_enable_ms(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- mod_timer(&sport->timer, jiffies);
-}
-
-static void
-sa1100_rx_chars(struct sa1100_port *sport)
-{
- struct tty_struct *tty = sport->port.state->port.tty;
- unsigned int status, ch, flg;
-
- status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
- UTSR0_TO_SM(UART_GET_UTSR0(sport));
- while (status & UTSR1_TO_SM(UTSR1_RNE)) {
- ch = UART_GET_CHAR(sport);
-
- sport->port.icount.rx++;
-
- flg = TTY_NORMAL;
-
- /*
- * note that the error handling code is
- * out of the main execution path
- */
- if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) {
- if (status & UTSR1_TO_SM(UTSR1_PRE))
- sport->port.icount.parity++;
- else if (status & UTSR1_TO_SM(UTSR1_FRE))
- sport->port.icount.frame++;
- if (status & UTSR1_TO_SM(UTSR1_ROR))
- sport->port.icount.overrun++;
-
- status &= sport->port.read_status_mask;
-
- if (status & UTSR1_TO_SM(UTSR1_PRE))
- flg = TTY_PARITY;
- else if (status & UTSR1_TO_SM(UTSR1_FRE))
- flg = TTY_FRAME;
-
-#ifdef SUPPORT_SYSRQ
- sport->port.sysrq = 0;
-#endif
- }
-
- if (uart_handle_sysrq_char(&sport->port, ch))
- goto ignore_char;
-
- uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg);
-
- ignore_char:
- status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
- UTSR0_TO_SM(UART_GET_UTSR0(sport));
- }
- tty_flip_buffer_push(tty);
-}
-
-static void sa1100_tx_chars(struct sa1100_port *sport)
-{
- struct circ_buf *xmit = &sport->port.state->xmit;
-
- if (sport->port.x_char) {
- UART_PUT_CHAR(sport, sport->port.x_char);
- sport->port.icount.tx++;
- sport->port.x_char = 0;
- return;
- }
-
- /*
- * Check the modem control lines before
- * transmitting anything.
- */
- sa1100_mctrl_check(sport);
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- sa1100_stop_tx(&sport->port);
- return;
- }
-
- /*
- * Tried using FIFO (not checking TNF) for fifo fill:
- * still had the '4 bytes repeated' problem.
- */
- while (UART_GET_UTSR1(sport) & UTSR1_TNF) {
- UART_PUT_CHAR(sport, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- sport->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&sport->port);
-
- if (uart_circ_empty(xmit))
- sa1100_stop_tx(&sport->port);
-}
-
-static irqreturn_t sa1100_int(int irq, void *dev_id)
-{
- struct sa1100_port *sport = dev_id;
- unsigned int status, pass_counter = 0;
-
- spin_lock(&sport->port.lock);
- status = UART_GET_UTSR0(sport);
- status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
- do {
- if (status & (UTSR0_RFS | UTSR0_RID)) {
- /* Clear the receiver idle bit, if set */
- if (status & UTSR0_RID)
- UART_PUT_UTSR0(sport, UTSR0_RID);
- sa1100_rx_chars(sport);
- }
-
- /* Clear the relevant break bits */
- if (status & (UTSR0_RBB | UTSR0_REB))
- UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB));
-
- if (status & UTSR0_RBB)
- sport->port.icount.brk++;
-
- if (status & UTSR0_REB)
- uart_handle_break(&sport->port);
-
- if (status & UTSR0_TFS)
- sa1100_tx_chars(sport);
- if (pass_counter++ > SA1100_ISR_PASS_LIMIT)
- break;
- status = UART_GET_UTSR0(sport);
- status &= SM_TO_UTSR0(sport->port.read_status_mask) |
- ~UTSR0_TFS;
- } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
- spin_unlock(&sport->port.lock);
-
- return IRQ_HANDLED;
-}
-
-/*
- * Return TIOCSER_TEMT when transmitter is not busy.
- */
-static unsigned int sa1100_tx_empty(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- return UART_GET_UTSR1(sport) & UTSR1_TBY ? 0 : TIOCSER_TEMT;
-}
-
-static unsigned int sa1100_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-}
-
-static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-/*
- * Interrupts always disabled.
- */
-static void sa1100_break_ctl(struct uart_port *port, int break_state)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
- unsigned long flags;
- unsigned int utcr3;
-
- spin_lock_irqsave(&sport->port.lock, flags);
- utcr3 = UART_GET_UTCR3(sport);
- if (break_state == -1)
- utcr3 |= UTCR3_BRK;
- else
- utcr3 &= ~UTCR3_BRK;
- UART_PUT_UTCR3(sport, utcr3);
- spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-static int sa1100_startup(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
- int retval;
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(sport->port.irq, sa1100_int, 0,
- "sa11x0-uart", sport);
- if (retval)
- return retval;
-
- /*
- * Finally, clear and enable interrupts
- */
- UART_PUT_UTSR0(sport, -1);
- UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);
-
- /*
- * Enable modem status interrupts
- */
- spin_lock_irq(&sport->port.lock);
- sa1100_enable_ms(&sport->port);
- spin_unlock_irq(&sport->port.lock);
-
- return 0;
-}
-
-static void sa1100_shutdown(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- /*
- * Stop our timer.
- */
- del_timer_sync(&sport->timer);
-
- /*
- * Free the interrupt
- */
- free_irq(sport->port.irq, sport);
-
- /*
- * Disable all interrupts, port and break condition.
- */
- UART_PUT_UTCR3(sport, 0);
-}
-
-static void
-sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
- unsigned long flags;
- unsigned int utcr0, old_utcr3, baud, quot;
- unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
-
- /*
- * We only support CS7 and CS8.
- */
- while ((termios->c_cflag & CSIZE) != CS7 &&
- (termios->c_cflag & CSIZE) != CS8) {
- termios->c_cflag &= ~CSIZE;
- termios->c_cflag |= old_csize;
- old_csize = CS8;
- }
-
- if ((termios->c_cflag & CSIZE) == CS8)
- utcr0 = UTCR0_DSS;
- else
- utcr0 = 0;
-
- if (termios->c_cflag & CSTOPB)
- utcr0 |= UTCR0_SBS;
- if (termios->c_cflag & PARENB) {
- utcr0 |= UTCR0_PE;
- if (!(termios->c_cflag & PARODD))
- utcr0 |= UTCR0_OES;
- }
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- spin_lock_irqsave(&sport->port.lock, flags);
-
- sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
- sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
- if (termios->c_iflag & INPCK)
- sport->port.read_status_mask |=
- UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
- if (termios->c_iflag & (BRKINT | PARMRK))
- sport->port.read_status_mask |=
- UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
-
- /*
- * Characters to ignore
- */
- sport->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- sport->port.ignore_status_mask |=
- UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
- if (termios->c_iflag & IGNBRK) {
- sport->port.ignore_status_mask |=
- UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- sport->port.ignore_status_mask |=
- UTSR1_TO_SM(UTSR1_ROR);
- }
-
- del_timer_sync(&sport->timer);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /*
- * disable interrupts and drain transmitter
- */
- old_utcr3 = UART_GET_UTCR3(sport);
- UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
-
- while (UART_GET_UTSR1(sport) & UTSR1_TBY)
- barrier();
-
- /* then, disable everything */
- UART_PUT_UTCR3(sport, 0);
-
- /* set the parity, stop bits and data size */
- UART_PUT_UTCR0(sport, utcr0);
-
- /* set the baud rate */
- quot -= 1;
- UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
- UART_PUT_UTCR2(sport, (quot & 0xff));
-
- UART_PUT_UTSR0(sport, -1);
-
- UART_PUT_UTCR3(sport, old_utcr3);
-
- if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
- sa1100_enable_ms(&sport->port);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-static const char *sa1100_type(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- return sport->port.type == PORT_SA1100 ? "SA1100" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'.
- */
-static void sa1100_release_port(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
-}
-
-/*
- * Request the memory region(s) being used by 'port'.
- */
-static int sa1100_request_port(struct uart_port *port)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
- "sa11x0-uart") != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void sa1100_config_port(struct uart_port *port, int flags)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- if (flags & UART_CONFIG_TYPE &&
- sa1100_request_port(&sport->port) == 0)
- sport->port.type = PORT_SA1100;
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- * The only change we allow are to the flags and type, and
- * even then only between PORT_SA1100 and PORT_UNKNOWN
- */
-static int
-sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_SA1100)
- ret = -EINVAL;
- if (sport->port.irq != ser->irq)
- ret = -EINVAL;
- if (ser->io_type != SERIAL_IO_MEM)
- ret = -EINVAL;
- if (sport->port.uartclk / 16 != ser->baud_base)
- ret = -EINVAL;
- if ((void *)sport->port.mapbase != ser->iomem_base)
- ret = -EINVAL;
- if (sport->port.iobase != ser->port)
- ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops sa1100_pops = {
- .tx_empty = sa1100_tx_empty,
- .set_mctrl = sa1100_set_mctrl,
- .get_mctrl = sa1100_get_mctrl,
- .stop_tx = sa1100_stop_tx,
- .start_tx = sa1100_start_tx,
- .stop_rx = sa1100_stop_rx,
- .enable_ms = sa1100_enable_ms,
- .break_ctl = sa1100_break_ctl,
- .startup = sa1100_startup,
- .shutdown = sa1100_shutdown,
- .set_termios = sa1100_set_termios,
- .type = sa1100_type,
- .release_port = sa1100_release_port,
- .request_port = sa1100_request_port,
- .config_port = sa1100_config_port,
- .verify_port = sa1100_verify_port,
-};
-
-static struct sa1100_port sa1100_ports[NR_PORTS];
-
-/*
- * Setup the SA1100 serial ports. Note that we don't include the IrDA
- * port here since we have our own SIR/FIR driver (see drivers/net/irda)
- *
- * Note also that we support "console=ttySAx" where "x" is either 0 or 1.
- * Which serial port this ends up being depends on the machine you're
- * running this kernel on. I'm not convinced that this is a good idea,
- * but that's the way it traditionally works.
- *
- * Note that NanoEngine UART3 becomes UART2, and UART2 is no longer
- * used here.
- */
-static void __init sa1100_init_ports(void)
-{
- static int first = 1;
- int i;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0; i < NR_PORTS; i++) {
- sa1100_ports[i].port.uartclk = 3686400;
- sa1100_ports[i].port.ops = &sa1100_pops;
- sa1100_ports[i].port.fifosize = 8;
- sa1100_ports[i].port.line = i;
- sa1100_ports[i].port.iotype = UPIO_MEM;
- init_timer(&sa1100_ports[i].timer);
- sa1100_ports[i].timer.function = sa1100_timeout;
- sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
- }
-
- /*
- * make transmit lines outputs, so that when the port
- * is closed, the output is in the MARK state.
- */
- PPDR |= PPC_TXD1 | PPC_TXD3;
- PPSR |= PPC_TXD1 | PPC_TXD3;
-}
-
-void __devinit sa1100_register_uart_fns(struct sa1100_port_fns *fns)
-{
- if (fns->get_mctrl)
- sa1100_pops.get_mctrl = fns->get_mctrl;
- if (fns->set_mctrl)
- sa1100_pops.set_mctrl = fns->set_mctrl;
-
- sa1100_pops.pm = fns->pm;
- sa1100_pops.set_wake = fns->set_wake;
-}
-
-void __init sa1100_register_uart(int idx, int port)
-{
- if (idx >= NR_PORTS) {
- printk(KERN_ERR "%s: bad index number %d\n", __func__, idx);
- return;
- }
-
- switch (port) {
- case 1:
- sa1100_ports[idx].port.membase = (void __iomem *)&Ser1UTCR0;
- sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
- sa1100_ports[idx].port.irq = IRQ_Ser1UART;
- sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF;
- break;
-
- case 2:
- sa1100_ports[idx].port.membase = (void __iomem *)&Ser2UTCR0;
- sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
- sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
- sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF;
- break;
-
- case 3:
- sa1100_ports[idx].port.membase = (void __iomem *)&Ser3UTCR0;
- sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
- sa1100_ports[idx].port.irq = IRQ_Ser3UART;
- sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF;
- break;
-
- default:
- printk(KERN_ERR "%s: bad port number %d\n", __func__, port);
- }
-}
-
-
-#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-static void sa1100_console_putchar(struct uart_port *port, int ch)
-{
- struct sa1100_port *sport = (struct sa1100_port *)port;
-
- while (!(UART_GET_UTSR1(sport) & UTSR1_TNF))
- barrier();
- UART_PUT_CHAR(sport, ch);
-}
-
-/*
- * Interrupts are disabled on entering
- */
-static void
-sa1100_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct sa1100_port *sport = &sa1100_ports[co->index];
- unsigned int old_utcr3, status;
-
- /*
- * First, save UTCR3 and then disable interrupts
- */
- old_utcr3 = UART_GET_UTCR3(sport);
- UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
- UTCR3_TXE);
-
- uart_console_write(&sport->port, s, count, sa1100_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore UTCR3
- */
- do {
- status = UART_GET_UTSR1(sport);
- } while (status & UTSR1_TBY);
- UART_PUT_UTCR3(sport, old_utcr3);
-}
-
-/*
- * If the port was already initialised (eg, by a boot loader),
- * try to determine the current setup.
- */
-static void __init
-sa1100_console_get_options(struct sa1100_port *sport, int *baud,
- int *parity, int *bits)
-{
- unsigned int utcr3;
-
- utcr3 = UART_GET_UTCR3(sport) & (UTCR3_RXE | UTCR3_TXE);
- if (utcr3 == (UTCR3_RXE | UTCR3_TXE)) {
- /* ok, the port was enabled */
- unsigned int utcr0, quot;
-
- utcr0 = UART_GET_UTCR0(sport);
-
- *parity = 'n';
- if (utcr0 & UTCR0_PE) {
- if (utcr0 & UTCR0_OES)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- if (utcr0 & UTCR0_DSS)
- *bits = 8;
- else
- *bits = 7;
-
- quot = UART_GET_UTCR2(sport) | UART_GET_UTCR1(sport) << 8;
- quot &= 0xfff;
- *baud = sport->port.uartclk / (16 * (quot + 1));
- }
-}
-
-static int __init
-sa1100_console_setup(struct console *co, char *options)
-{
- struct sa1100_port *sport;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index == -1 || co->index >= NR_PORTS)
- co->index = 0;
- sport = &sa1100_ports[co->index];
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- sa1100_console_get_options(sport, &baud, &parity, &bits);
-
- return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver sa1100_reg;
-static struct console sa1100_console = {
- .name = "ttySA",
- .write = sa1100_console_write,
- .device = uart_console_device,
- .setup = sa1100_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sa1100_reg,
-};
-
-static int __init sa1100_rs_console_init(void)
-{
- sa1100_init_ports();
- register_console(&sa1100_console);
- return 0;
-}
-console_initcall(sa1100_rs_console_init);
-
-#define SA1100_CONSOLE &sa1100_console
-#else
-#define SA1100_CONSOLE NULL
-#endif
-
-static struct uart_driver sa1100_reg = {
- .owner = THIS_MODULE,
- .driver_name = "ttySA",
- .dev_name = "ttySA",
- .major = SERIAL_SA1100_MAJOR,
- .minor = MINOR_START,
- .nr = NR_PORTS,
- .cons = SA1100_CONSOLE,
-};
-
-static int sa1100_serial_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct sa1100_port *sport = platform_get_drvdata(dev);
-
- if (sport)
- uart_suspend_port(&sa1100_reg, &sport->port);
-
- return 0;
-}
-
-static int sa1100_serial_resume(struct platform_device *dev)
-{
- struct sa1100_port *sport = platform_get_drvdata(dev);
-
- if (sport)
- uart_resume_port(&sa1100_reg, &sport->port);
-
- return 0;
-}
-
-static int sa1100_serial_probe(struct platform_device *dev)
-{
- struct resource *res = dev->resource;
- int i;
-
- for (i = 0; i < dev->num_resources; i++, res++)
- if (res->flags & IORESOURCE_MEM)
- break;
-
- if (i < dev->num_resources) {
- for (i = 0; i < NR_PORTS; i++) {
- if (sa1100_ports[i].port.mapbase != res->start)
- continue;
-
- sa1100_ports[i].port.dev = &dev->dev;
- uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
- platform_set_drvdata(dev, &sa1100_ports[i]);
- break;
- }
- }
-
- return 0;
-}
-
-static int sa1100_serial_remove(struct platform_device *pdev)
-{
- struct sa1100_port *sport = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
-
- if (sport)
- uart_remove_one_port(&sa1100_reg, &sport->port);
-
- return 0;
-}
-
-static struct platform_driver sa11x0_serial_driver = {
- .probe = sa1100_serial_probe,
- .remove = sa1100_serial_remove,
- .suspend = sa1100_serial_suspend,
- .resume = sa1100_serial_resume,
- .driver = {
- .name = "sa11x0-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init sa1100_serial_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Serial: SA11x0 driver\n");
-
- sa1100_init_ports();
-
- ret = uart_register_driver(&sa1100_reg);
- if (ret == 0) {
- ret = platform_driver_register(&sa11x0_serial_driver);
- if (ret)
- uart_unregister_driver(&sa1100_reg);
- }
- return ret;
-}
-
-static void __exit sa1100_serial_exit(void)
-{
- platform_driver_unregister(&sa11x0_serial_driver);
- uart_unregister_driver(&sa1100_reg);
-}
-
-module_init(sa1100_serial_init);
-module_exit(sa1100_serial_exit);
-
-MODULE_AUTHOR("Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("SA1100 generic serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_SA1100_MAJOR);
-MODULE_ALIAS("platform:sa11x0-uart");
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
deleted file mode 100644
index 7ac2bf5167cd..000000000000
--- a/drivers/serial/samsung.c
+++ /dev/null
@@ -1,1487 +0,0 @@
-/* linux/drivers/serial/samsuing.c
- *
- * Driver core for Samsung SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-/* Hote on 2410 error handling
- *
- * The s3c2410 manual has a love/hate affair with the contents of the
- * UERSTAT register in the UART blocks, and keeps marking some of the
- * error bits as reserved. Having checked with the s3c2410x01,
- * it copes with BREAKs properly, so I am happy to ignore the RESERVED
- * feature from the latter versions of the manual.
- *
- * If it becomes aparrent that latter versions of the 2410 remove these
- * bits, then action will have to be taken to differentiate the versions
- * and change the policy on BREAK
- *
- * BJD, 04-Nov-2004
-*/
-
-#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/regs-serial.h>
-
-#include "samsung.h"
-
-/* UART name and device definitions */
-
-#define S3C24XX_SERIAL_NAME "ttySAC"
-#define S3C24XX_SERIAL_MAJOR 204
-#define S3C24XX_SERIAL_MINOR 64
-
-/* macros to change one thing to another */
-
-#define tx_enabled(port) ((port)->unused[0])
-#define rx_enabled(port) ((port)->unused[1])
-
-/* flag to ignore all characters comming in */
-#define RXSTAT_DUMMY_READ (0x10000000)
-
-static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
-{
- return container_of(port, struct s3c24xx_uart_port, port);
-}
-
-/* translate a port to the device name */
-
-static inline const char *s3c24xx_serial_portname(struct uart_port *port)
-{
- return to_platform_device(port->dev)->name;
-}
-
-static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
-{
- return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE);
-}
-
-static void s3c24xx_serial_rx_enable(struct uart_port *port)
-{
- unsigned long flags;
- unsigned int ucon, ufcon;
- int count = 10000;
-
- spin_lock_irqsave(&port->lock, flags);
-
- while (--count && !s3c24xx_serial_txempty_nofifo(port))
- udelay(100);
-
- ufcon = rd_regl(port, S3C2410_UFCON);
- ufcon |= S3C2410_UFCON_RESETRX;
- wr_regl(port, S3C2410_UFCON, ufcon);
-
- ucon = rd_regl(port, S3C2410_UCON);
- ucon |= S3C2410_UCON_RXIRQMODE;
- wr_regl(port, S3C2410_UCON, ucon);
-
- rx_enabled(port) = 1;
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void s3c24xx_serial_rx_disable(struct uart_port *port)
-{
- unsigned long flags;
- unsigned int ucon;
-
- spin_lock_irqsave(&port->lock, flags);
-
- ucon = rd_regl(port, S3C2410_UCON);
- ucon &= ~S3C2410_UCON_RXIRQMODE;
- wr_regl(port, S3C2410_UCON, ucon);
-
- rx_enabled(port) = 0;
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void s3c24xx_serial_stop_tx(struct uart_port *port)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
-
- if (tx_enabled(port)) {
- disable_irq_nosync(ourport->tx_irq);
- tx_enabled(port) = 0;
- if (port->flags & UPF_CONS_FLOW)
- s3c24xx_serial_rx_enable(port);
- }
-}
-
-static void s3c24xx_serial_start_tx(struct uart_port *port)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
-
- if (!tx_enabled(port)) {
- if (port->flags & UPF_CONS_FLOW)
- s3c24xx_serial_rx_disable(port);
-
- enable_irq(ourport->tx_irq);
- tx_enabled(port) = 1;
- }
-}
-
-
-static void s3c24xx_serial_stop_rx(struct uart_port *port)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
-
- if (rx_enabled(port)) {
- dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
- disable_irq_nosync(ourport->rx_irq);
- rx_enabled(port) = 0;
- }
-}
-
-static void s3c24xx_serial_enable_ms(struct uart_port *port)
-{
-}
-
-static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
-{
- return to_ourport(port)->info;
-}
-
-static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port)
-{
- if (port->dev == NULL)
- return NULL;
-
- return (struct s3c2410_uartcfg *)port->dev->platform_data;
-}
-
-static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
- unsigned long ufstat)
-{
- struct s3c24xx_uart_info *info = ourport->info;
-
- if (ufstat & info->rx_fifofull)
- return info->fifosize;
-
- return (ufstat & info->rx_fifomask) >> info->rx_fifoshift;
-}
-
-
-/* ? - where has parity gone?? */
-#define S3C2410_UERSTAT_PARITY (0x1000)
-
-static irqreturn_t
-s3c24xx_serial_rx_chars(int irq, void *dev_id)
-{
- struct s3c24xx_uart_port *ourport = dev_id;
- struct uart_port *port = &ourport->port;
- struct tty_struct *tty = port->state->port.tty;
- unsigned int ufcon, ch, flag, ufstat, uerstat;
- int max_count = 64;
-
- while (max_count-- > 0) {
- ufcon = rd_regl(port, S3C2410_UFCON);
- ufstat = rd_regl(port, S3C2410_UFSTAT);
-
- if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
- break;
-
- uerstat = rd_regl(port, S3C2410_UERSTAT);
- ch = rd_regb(port, S3C2410_URXH);
-
- if (port->flags & UPF_CONS_FLOW) {
- int txe = s3c24xx_serial_txempty_nofifo(port);
-
- if (rx_enabled(port)) {
- if (!txe) {
- rx_enabled(port) = 0;
- continue;
- }
- } else {
- if (txe) {
- ufcon |= S3C2410_UFCON_RESETRX;
- wr_regl(port, S3C2410_UFCON, ufcon);
- rx_enabled(port) = 1;
- goto out;
- }
- continue;
- }
- }
-
- /* insert the character into the buffer */
-
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
- dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
- ch, uerstat);
-
- /* check for break */
- if (uerstat & S3C2410_UERSTAT_BREAK) {
- dbg("break!\n");
- port->icount.brk++;
- if (uart_handle_break(port))
- goto ignore_char;
- }
-
- if (uerstat & S3C2410_UERSTAT_FRAME)
- port->icount.frame++;
- if (uerstat & S3C2410_UERSTAT_OVERRUN)
- port->icount.overrun++;
-
- uerstat &= port->read_status_mask;
-
- if (uerstat & S3C2410_UERSTAT_BREAK)
- flag = TTY_BREAK;
- else if (uerstat & S3C2410_UERSTAT_PARITY)
- flag = TTY_PARITY;
- else if (uerstat & (S3C2410_UERSTAT_FRAME |
- S3C2410_UERSTAT_OVERRUN))
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
-
- uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
- ch, flag);
-
- ignore_char:
- continue;
- }
- tty_flip_buffer_push(tty);
-
- out:
- return IRQ_HANDLED;
-}
-
-static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
-{
- struct s3c24xx_uart_port *ourport = id;
- struct uart_port *port = &ourport->port;
- struct circ_buf *xmit = &port->state->xmit;
- int count = 256;
-
- if (port->x_char) {
- wr_regb(port, S3C2410_UTXH, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- goto out;
- }
-
- /* if there isnt anything more to transmit, or the uart is now
- * stopped, disable the uart and exit
- */
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- s3c24xx_serial_stop_tx(port);
- goto out;
- }
-
- /* try and drain the buffer... */
-
- while (!uart_circ_empty(xmit) && count-- > 0) {
- if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
- break;
-
- wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- s3c24xx_serial_stop_tx(port);
-
- out:
- return IRQ_HANDLED;
-}
-
-static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
- unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
- unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
-
- if (ufcon & S3C2410_UFCON_FIFOMODE) {
- if ((ufstat & info->tx_fifomask) != 0 ||
- (ufstat & info->tx_fifofull))
- return 0;
-
- return 1;
- }
-
- return s3c24xx_serial_txempty_nofifo(port);
-}
-
-/* no modem control lines */
-static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
-{
- unsigned int umstat = rd_regb(port, S3C2410_UMSTAT);
-
- if (umstat & S3C2410_UMSTAT_CTS)
- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
- else
- return TIOCM_CAR | TIOCM_DSR;
-}
-
-static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- /* todo - possibly remove AFC and do manual CTS */
-}
-
-static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned long flags;
- unsigned int ucon;
-
- spin_lock_irqsave(&port->lock, flags);
-
- ucon = rd_regl(port, S3C2410_UCON);
-
- if (break_state)
- ucon |= S3C2410_UCON_SBREAK;
- else
- ucon &= ~S3C2410_UCON_SBREAK;
-
- wr_regl(port, S3C2410_UCON, ucon);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void s3c24xx_serial_shutdown(struct uart_port *port)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
-
- if (ourport->tx_claimed) {
- free_irq(ourport->tx_irq, ourport);
- tx_enabled(port) = 0;
- ourport->tx_claimed = 0;
- }
-
- if (ourport->rx_claimed) {
- free_irq(ourport->rx_irq, ourport);
- ourport->rx_claimed = 0;
- rx_enabled(port) = 0;
- }
-}
-
-
-static int s3c24xx_serial_startup(struct uart_port *port)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
- int ret;
-
- dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
- port->mapbase, port->membase);
-
- rx_enabled(port) = 1;
-
- ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
- s3c24xx_serial_portname(port), ourport);
-
- if (ret != 0) {
- printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
- return ret;
- }
-
- ourport->rx_claimed = 1;
-
- dbg("requesting tx irq...\n");
-
- tx_enabled(port) = 1;
-
- ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
- s3c24xx_serial_portname(port), ourport);
-
- if (ret) {
- printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
- goto err;
- }
-
- ourport->tx_claimed = 1;
-
- dbg("s3c24xx_serial_startup ok\n");
-
- /* the port reset code should have done the correct
- * register setup for the port controls */
-
- return ret;
-
- err:
- s3c24xx_serial_shutdown(port);
- return ret;
-}
-
-/* power power management control */
-
-static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
- unsigned int old)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
-
- ourport->pm_level = level;
-
- switch (level) {
- case 3:
- if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
- clk_disable(ourport->baudclk);
-
- clk_disable(ourport->clk);
- break;
-
- case 0:
- clk_enable(ourport->clk);
-
- if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
- clk_enable(ourport->baudclk);
-
- break;
- default:
- printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level);
- }
-}
-
-/* baud rate calculation
- *
- * The UARTs on the S3C2410/S3C2440 can take their clocks from a number
- * of different sources, including the peripheral clock ("pclk") and an
- * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk")
- * with a programmable extra divisor.
- *
- * The following code goes through the clock sources, and calculates the
- * baud clocks (and the resultant actual baud rates) and then tries to
- * pick the closest one and select that.
- *
-*/
-
-
-#define MAX_CLKS (8)
-
-static struct s3c24xx_uart_clksrc tmp_clksrc = {
- .name = "pclk",
- .min_baud = 0,
- .max_baud = 0,
- .divisor = 1,
-};
-
-static inline int
-s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-
- return (info->get_clksrc)(port, c);
-}
-
-static inline int
-s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-
- return (info->set_clksrc)(port, c);
-}
-
-struct baud_calc {
- struct s3c24xx_uart_clksrc *clksrc;
- unsigned int calc;
- unsigned int divslot;
- unsigned int quot;
- struct clk *src;
-};
-
-static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
- struct uart_port *port,
- struct s3c24xx_uart_clksrc *clksrc,
- unsigned int baud)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
- unsigned long rate;
-
- calc->src = clk_get(port->dev, clksrc->name);
- if (calc->src == NULL || IS_ERR(calc->src))
- return 0;
-
- rate = clk_get_rate(calc->src);
- rate /= clksrc->divisor;
-
- calc->clksrc = clksrc;
-
- if (ourport->info->has_divslot) {
- unsigned long div = rate / baud;
-
- /* The UDIVSLOT register on the newer UARTs allows us to
- * get a divisor adjustment of 1/16th on the baud clock.
- *
- * We don't keep the UDIVSLOT value (the 16ths we calculated
- * by not multiplying the baud by 16) as it is easy enough
- * to recalculate.
- */
-
- calc->quot = div / 16;
- calc->calc = rate / div;
- } else {
- calc->quot = (rate + (8 * baud)) / (16 * baud);
- calc->calc = (rate / (calc->quot * 16));
- }
-
- calc->quot--;
- return 1;
-}
-
-static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
- struct s3c24xx_uart_clksrc **clksrc,
- struct clk **clk,
- unsigned int baud)
-{
- struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
- struct s3c24xx_uart_clksrc *clkp;
- struct baud_calc res[MAX_CLKS];
- struct baud_calc *resptr, *best, *sptr;
- int i;
-
- clkp = cfg->clocks;
- best = NULL;
-
- if (cfg->clocks_size < 2) {
- if (cfg->clocks_size == 0)
- clkp = &tmp_clksrc;
-
- /* check to see if we're sourcing fclk, and if so we're
- * going to have to update the clock source
- */
-
- if (strcmp(clkp->name, "fclk") == 0) {
- struct s3c24xx_uart_clksrc src;
-
- s3c24xx_serial_getsource(port, &src);
-
- /* check that the port already using fclk, and if
- * not, then re-select fclk
- */
-
- if (strcmp(src.name, clkp->name) == 0) {
- s3c24xx_serial_setsource(port, clkp);
- s3c24xx_serial_getsource(port, &src);
- }
-
- clkp->divisor = src.divisor;
- }
-
- s3c24xx_serial_calcbaud(res, port, clkp, baud);
- best = res;
- resptr = best + 1;
- } else {
- resptr = res;
-
- for (i = 0; i < cfg->clocks_size; i++, clkp++) {
- if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud))
- resptr++;
- }
- }
-
- /* ok, we now need to select the best clock we found */
-
- if (!best) {
- unsigned int deviation = (1<<30)|((1<<30)-1);
- int calc_deviation;
-
- for (sptr = res; sptr < resptr; sptr++) {
- calc_deviation = baud - sptr->calc;
- if (calc_deviation < 0)
- calc_deviation = -calc_deviation;
-
- if (calc_deviation < deviation) {
- best = sptr;
- deviation = calc_deviation;
- }
- }
- }
-
- /* store results to pass back */
-
- *clksrc = best->clksrc;
- *clk = best->src;
-
- return best->quot;
-}
-
-/* udivslot_table[]
- *
- * This table takes the fractional value of the baud divisor and gives
- * the recommended setting for the UDIVSLOT register.
- */
-static u16 udivslot_table[16] = {
- [0] = 0x0000,
- [1] = 0x0080,
- [2] = 0x0808,
- [3] = 0x0888,
- [4] = 0x2222,
- [5] = 0x4924,
- [6] = 0x4A52,
- [7] = 0x54AA,
- [8] = 0x5555,
- [9] = 0xD555,
- [10] = 0xD5D5,
- [11] = 0xDDD5,
- [12] = 0xDDDD,
- [13] = 0xDFDD,
- [14] = 0xDFDF,
- [15] = 0xFFDF,
-};
-
-static void s3c24xx_serial_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
- struct s3c24xx_uart_port *ourport = to_ourport(port);
- struct s3c24xx_uart_clksrc *clksrc = NULL;
- struct clk *clk = NULL;
- unsigned long flags;
- unsigned int baud, quot;
- unsigned int ulcon;
- unsigned int umcon;
- unsigned int udivslot = 0;
-
- /*
- * We don't support modem control lines.
- */
- termios->c_cflag &= ~(HUPCL | CMSPAR);
- termios->c_cflag |= CLOCAL;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
-
- baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
-
- if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
- quot = port->custom_divisor;
- else
- quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
-
- /* check to see if we need to change clock source */
-
- if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
- dbg("selecting clock %p\n", clk);
- s3c24xx_serial_setsource(port, clksrc);
-
- if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
- clk_disable(ourport->baudclk);
- ourport->baudclk = NULL;
- }
-
- clk_enable(clk);
-
- ourport->clksrc = clksrc;
- ourport->baudclk = clk;
- ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
- }
-
- if (ourport->info->has_divslot) {
- unsigned int div = ourport->baudclk_rate / baud;
-
- if (cfg->has_fracval) {
- udivslot = (div & 15);
- dbg("fracval = %04x\n", udivslot);
- } else {
- udivslot = udivslot_table[div & 15];
- dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
- }
- }
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- dbg("config: 5bits/char\n");
- ulcon = S3C2410_LCON_CS5;
- break;
- case CS6:
- dbg("config: 6bits/char\n");
- ulcon = S3C2410_LCON_CS6;
- break;
- case CS7:
- dbg("config: 7bits/char\n");
- ulcon = S3C2410_LCON_CS7;
- break;
- case CS8:
- default:
- dbg("config: 8bits/char\n");
- ulcon = S3C2410_LCON_CS8;
- break;
- }
-
- /* preserve original lcon IR settings */
- ulcon |= (cfg->ulcon & S3C2410_LCON_IRM);
-
- if (termios->c_cflag & CSTOPB)
- ulcon |= S3C2410_LCON_STOPB;
-
- umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;
-
- if (termios->c_cflag & PARENB) {
- if (termios->c_cflag & PARODD)
- ulcon |= S3C2410_LCON_PODD;
- else
- ulcon |= S3C2410_LCON_PEVEN;
- } else {
- ulcon |= S3C2410_LCON_PNONE;
- }
-
- spin_lock_irqsave(&port->lock, flags);
-
- dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
- ulcon, quot, udivslot);
-
- wr_regl(port, S3C2410_ULCON, ulcon);
- wr_regl(port, S3C2410_UBRDIV, quot);
- wr_regl(port, S3C2410_UMCON, umcon);
-
- if (ourport->info->has_divslot)
- wr_regl(port, S3C2443_DIVSLOT, udivslot);
-
- dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
- rd_regl(port, S3C2410_ULCON),
- rd_regl(port, S3C2410_UCON),
- rd_regl(port, S3C2410_UFCON));
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /*
- * Which character status flags are we interested in?
- */
- port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY;
-
- /*
- * Which character status flags should we ignore?
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;
- if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;
-
- /*
- * Ignore all characters if CREAD is not set.
- */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= RXSTAT_DUMMY_READ;
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *s3c24xx_serial_type(struct uart_port *port)
-{
- switch (port->type) {
- case PORT_S3C2410:
- return "S3C2410";
- case PORT_S3C2440:
- return "S3C2440";
- case PORT_S3C2412:
- return "S3C2412";
- case PORT_S3C6400:
- return "S3C6400/10";
- default:
- return NULL;
- }
-}
-
-#define MAP_SIZE (0x100)
-
-static void s3c24xx_serial_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, MAP_SIZE);
-}
-
-static int s3c24xx_serial_request_port(struct uart_port *port)
-{
- const char *name = s3c24xx_serial_portname(port);
- return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
-}
-
-static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-
- if (flags & UART_CONFIG_TYPE &&
- s3c24xx_serial_request_port(port) == 0)
- port->type = info->type;
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int
-s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-
- if (ser->type != PORT_UNKNOWN && ser->type != info->type)
- return -EINVAL;
-
- return 0;
-}
-
-
-#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
-
-static struct console s3c24xx_serial_console;
-
-#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
-#else
-#define S3C24XX_SERIAL_CONSOLE NULL
-#endif
-
-static struct uart_ops s3c24xx_serial_ops = {
- .pm = s3c24xx_serial_pm,
- .tx_empty = s3c24xx_serial_tx_empty,
- .get_mctrl = s3c24xx_serial_get_mctrl,
- .set_mctrl = s3c24xx_serial_set_mctrl,
- .stop_tx = s3c24xx_serial_stop_tx,
- .start_tx = s3c24xx_serial_start_tx,
- .stop_rx = s3c24xx_serial_stop_rx,
- .enable_ms = s3c24xx_serial_enable_ms,
- .break_ctl = s3c24xx_serial_break_ctl,
- .startup = s3c24xx_serial_startup,
- .shutdown = s3c24xx_serial_shutdown,
- .set_termios = s3c24xx_serial_set_termios,
- .type = s3c24xx_serial_type,
- .release_port = s3c24xx_serial_release_port,
- .request_port = s3c24xx_serial_request_port,
- .config_port = s3c24xx_serial_config_port,
- .verify_port = s3c24xx_serial_verify_port,
-};
-
-
-static struct uart_driver s3c24xx_uart_drv = {
- .owner = THIS_MODULE,
- .dev_name = "s3c2410_serial",
- .nr = CONFIG_SERIAL_SAMSUNG_UARTS,
- .cons = S3C24XX_SERIAL_CONSOLE,
- .driver_name = S3C24XX_SERIAL_NAME,
- .major = S3C24XX_SERIAL_MAJOR,
- .minor = S3C24XX_SERIAL_MINOR,
-};
-
-static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
- [0] = {
- .port = {
- .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
- .iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX0,
- .uartclk = 0,
- .fifosize = 16,
- .ops = &s3c24xx_serial_ops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 0,
- }
- },
- [1] = {
- .port = {
- .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
- .iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX1,
- .uartclk = 0,
- .fifosize = 16,
- .ops = &s3c24xx_serial_ops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 1,
- }
- },
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
-
- [2] = {
- .port = {
- .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
- .iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX2,
- .uartclk = 0,
- .fifosize = 16,
- .ops = &s3c24xx_serial_ops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 2,
- }
- },
-#endif
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
- [3] = {
- .port = {
- .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),
- .iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX3,
- .uartclk = 0,
- .fifosize = 16,
- .ops = &s3c24xx_serial_ops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 3,
- }
- }
-#endif
-};
-
-/* s3c24xx_serial_resetport
- *
- * wrapper to call the specific reset for this port (reset the fifos
- * and the settings)
-*/
-
-static inline int s3c24xx_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
-
- return (info->reset_port)(port, cfg);
-}
-
-
-#ifdef CONFIG_CPU_FREQ
-
-static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
- unsigned long val, void *data)
-{
- struct s3c24xx_uart_port *port;
- struct uart_port *uport;
-
- port = container_of(nb, struct s3c24xx_uart_port, freq_transition);
- uport = &port->port;
-
- /* check to see if port is enabled */
-
- if (port->pm_level != 0)
- return 0;
-
- /* try and work out if the baudrate is changing, we can detect
- * a change in rate, but we do not have support for detecting
- * a disturbance in the clock-rate over the change.
- */
-
- if (IS_ERR(port->clk))
- goto exit;
-
- if (port->baudclk_rate == clk_get_rate(port->clk))
- goto exit;
-
- if (val == CPUFREQ_PRECHANGE) {
- /* we should really shut the port down whilst the
- * frequency change is in progress. */
-
- } else if (val == CPUFREQ_POSTCHANGE) {
- struct ktermios *termios;
- struct tty_struct *tty;
-
- if (uport->state == NULL)
- goto exit;
-
- tty = uport->state->port.tty;
-
- if (tty == NULL)
- goto exit;
-
- termios = tty->termios;
-
- if (termios == NULL) {
- printk(KERN_WARNING "%s: no termios?\n", __func__);
- goto exit;
- }
-
- s3c24xx_serial_set_termios(uport, termios, NULL);
- }
-
- exit:
- return 0;
-}
-
-static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
-{
- port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
-
- return cpufreq_register_notifier(&port->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
-{
- cpufreq_unregister_notifier(&port->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-#else
-static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
-{
- return 0;
-}
-
-static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
-{
-}
-#endif
-
-/* s3c24xx_serial_init_port
- *
- * initialise a single serial port from the platform device given
- */
-
-static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
- struct s3c24xx_uart_info *info,
- struct platform_device *platdev)
-{
- struct uart_port *port = &ourport->port;
- struct s3c2410_uartcfg *cfg;
- struct resource *res;
- int ret;
-
- dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
-
- if (platdev == NULL)
- return -ENODEV;
-
- cfg = s3c24xx_dev_to_cfg(&platdev->dev);
-
- if (port->mapbase != 0)
- return 0;
-
- if (cfg->hwport > CONFIG_SERIAL_SAMSUNG_UARTS) {
- printk(KERN_ERR "%s: port %d bigger than %d\n", __func__,
- cfg->hwport, CONFIG_SERIAL_SAMSUNG_UARTS);
- return -ERANGE;
- }
-
- /* setup info for port */
- port->dev = &platdev->dev;
- ourport->info = info;
-
- /* copy the info in from provided structure */
- ourport->port.fifosize = info->fifosize;
-
- dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport);
-
- port->uartclk = 1;
-
- if (cfg->uart_flags & UPF_CONS_FLOW) {
- dbg("s3c24xx_serial_init_port: enabling flow control\n");
- port->flags |= UPF_CONS_FLOW;
- }
-
- /* sort our the physical and virtual addresses for each UART */
-
- res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- printk(KERN_ERR "failed to find memory resource for uart\n");
- return -EINVAL;
- }
-
- dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
-
- port->mapbase = res->start;
- port->membase = S3C_VA_UART + (res->start & 0xfffff);
- ret = platform_get_irq(platdev, 0);
- if (ret < 0)
- port->irq = 0;
- else {
- port->irq = ret;
- ourport->rx_irq = ret;
- ourport->tx_irq = ret + 1;
- }
-
- ret = platform_get_irq(platdev, 1);
- if (ret > 0)
- ourport->tx_irq = ret;
-
- ourport->clk = clk_get(&platdev->dev, "uart");
-
- dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n",
- port->mapbase, port->membase, port->irq,
- ourport->rx_irq, ourport->tx_irq, port->uartclk);
-
- /* reset the fifos (and setup the uart) */
- s3c24xx_serial_resetport(port, cfg);
- return 0;
-}
-
-static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct uart_port *port = s3c24xx_dev_to_port(dev);
- struct s3c24xx_uart_port *ourport = to_ourport(port);
-
- return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->clksrc->name);
-}
-
-static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
-
-/* Device driver serial port probe */
-
-static int probe_index;
-
-int s3c24xx_serial_probe(struct platform_device *dev,
- struct s3c24xx_uart_info *info)
-{
- struct s3c24xx_uart_port *ourport;
- int ret;
-
- dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index);
-
- ourport = &s3c24xx_serial_ports[probe_index];
- probe_index++;
-
- dbg("%s: initialising port %p...\n", __func__, ourport);
-
- ret = s3c24xx_serial_init_port(ourport, info, dev);
- if (ret < 0)
- goto probe_err;
-
- dbg("%s: adding port\n", __func__);
- uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
- platform_set_drvdata(dev, &ourport->port);
-
- ret = device_create_file(&dev->dev, &dev_attr_clock_source);
- if (ret < 0)
- printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__);
-
- ret = s3c24xx_serial_cpufreq_register(ourport);
- if (ret < 0)
- dev_err(&dev->dev, "failed to add cpufreq notifier\n");
-
- return 0;
-
- probe_err:
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(s3c24xx_serial_probe);
-
-int __devexit s3c24xx_serial_remove(struct platform_device *dev)
-{
- struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
-
- if (port) {
- s3c24xx_serial_cpufreq_deregister(to_ourport(port));
- device_remove_file(&dev->dev, &dev_attr_clock_source);
- uart_remove_one_port(&s3c24xx_uart_drv, port);
- }
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(s3c24xx_serial_remove);
-
-/* UART power management code */
-
-#ifdef CONFIG_PM
-
-static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
-
- if (port)
- uart_suspend_port(&s3c24xx_uart_drv, port);
-
- return 0;
-}
-
-static int s3c24xx_serial_resume(struct platform_device *dev)
-{
- struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
- struct s3c24xx_uart_port *ourport = to_ourport(port);
-
- if (port) {
- clk_enable(ourport->clk);
- s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
- clk_disable(ourport->clk);
-
- uart_resume_port(&s3c24xx_uart_drv, port);
- }
-
- return 0;
-}
-#endif
-
-int s3c24xx_serial_init(struct platform_driver *drv,
- struct s3c24xx_uart_info *info)
-{
- dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
-
-#ifdef CONFIG_PM
- drv->suspend = s3c24xx_serial_suspend;
- drv->resume = s3c24xx_serial_resume;
-#endif
-
- return platform_driver_register(drv);
-}
-
-EXPORT_SYMBOL_GPL(s3c24xx_serial_init);
-
-/* module initialisation code */
-
-static int __init s3c24xx_serial_modinit(void)
-{
- int ret;
-
- ret = uart_register_driver(&s3c24xx_uart_drv);
- if (ret < 0) {
- printk(KERN_ERR "failed to register UART driver\n");
- return -1;
- }
-
- return 0;
-}
-
-static void __exit s3c24xx_serial_modexit(void)
-{
- uart_unregister_driver(&s3c24xx_uart_drv);
-}
-
-module_init(s3c24xx_serial_modinit);
-module_exit(s3c24xx_serial_modexit);
-
-/* Console code */
-
-#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
-
-static struct uart_port *cons_uart;
-
-static int
-s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
- unsigned long ufstat, utrstat;
-
- if (ufcon & S3C2410_UFCON_FIFOMODE) {
- /* fifo mode - check amount of data in fifo registers... */
-
- ufstat = rd_regl(port, S3C2410_UFSTAT);
- return (ufstat & info->tx_fifofull) ? 0 : 1;
- }
-
- /* in non-fifo mode, we go and use the tx buffer empty */
-
- utrstat = rd_regl(port, S3C2410_UTRSTAT);
- return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
-}
-
-static void
-s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
-{
- unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
- while (!s3c24xx_serial_console_txrdy(port, ufcon))
- barrier();
- wr_regb(cons_uart, S3C2410_UTXH, ch);
-}
-
-static void
-s3c24xx_serial_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
-}
-
-static void __init
-s3c24xx_serial_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- struct s3c24xx_uart_clksrc clksrc;
- struct clk *clk;
- unsigned int ulcon;
- unsigned int ucon;
- unsigned int ubrdiv;
- unsigned long rate;
-
- ulcon = rd_regl(port, S3C2410_ULCON);
- ucon = rd_regl(port, S3C2410_UCON);
- ubrdiv = rd_regl(port, S3C2410_UBRDIV);
-
- dbg("s3c24xx_serial_get_options: port=%p\n"
- "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
- port, ulcon, ucon, ubrdiv);
-
- if ((ucon & 0xf) != 0) {
- /* consider the serial port configured if the tx/rx mode set */
-
- switch (ulcon & S3C2410_LCON_CSMASK) {
- case S3C2410_LCON_CS5:
- *bits = 5;
- break;
- case S3C2410_LCON_CS6:
- *bits = 6;
- break;
- case S3C2410_LCON_CS7:
- *bits = 7;
- break;
- default:
- case S3C2410_LCON_CS8:
- *bits = 8;
- break;
- }
-
- switch (ulcon & S3C2410_LCON_PMASK) {
- case S3C2410_LCON_PEVEN:
- *parity = 'e';
- break;
-
- case S3C2410_LCON_PODD:
- *parity = 'o';
- break;
-
- case S3C2410_LCON_PNONE:
- default:
- *parity = 'n';
- }
-
- /* now calculate the baud rate */
-
- s3c24xx_serial_getsource(port, &clksrc);
-
- clk = clk_get(port->dev, clksrc.name);
- if (!IS_ERR(clk) && clk != NULL)
- rate = clk_get_rate(clk) / clksrc.divisor;
- else
- rate = 1;
-
-
- *baud = rate / (16 * (ubrdiv + 1));
- dbg("calculated baud %d\n", *baud);
- }
-
-}
-
-/* s3c24xx_serial_init_ports
- *
- * initialise the serial ports from the machine provided initialisation
- * data.
-*/
-
-static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info)
-{
- struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports;
- struct platform_device **platdev_ptr;
- int i;
-
- dbg("s3c24xx_serial_init_ports: initialising ports...\n");
-
- platdev_ptr = s3c24xx_uart_devs;
-
- for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) {
- s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr);
- }
-
- return 0;
-}
-
-static int __init
-s3c24xx_serial_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
- co, co->index, options);
-
- /* is this a valid port */
-
- if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS)
- co->index = 0;
-
- port = &s3c24xx_serial_ports[co->index].port;
-
- /* is the port configured? */
-
- if (port->mapbase == 0x0) {
- co->index = 0;
- port = &s3c24xx_serial_ports[co->index].port;
- }
-
- cons_uart = port;
-
- dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- s3c24xx_serial_get_options(port, &baud, &parity, &bits);
-
- dbg("s3c24xx_serial_console_setup: baud %d\n", baud);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-/* s3c24xx_serial_initconsole
- *
- * initialise the console from one of the uart drivers
-*/
-
-static struct console s3c24xx_serial_console = {
- .name = S3C24XX_SERIAL_NAME,
- .device = uart_console_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .write = s3c24xx_serial_console_write,
- .setup = s3c24xx_serial_console_setup
-};
-
-int s3c24xx_serial_initconsole(struct platform_driver *drv,
- struct s3c24xx_uart_info **info)
-
-{
- struct platform_device *dev = s3c24xx_uart_devs[0];
-
- dbg("s3c24xx_serial_initconsole\n");
-
- /* select driver based on the cpu */
-
- if (dev == NULL) {
- printk(KERN_ERR "s3c24xx: no devices for console init\n");
- return 0;
- }
-
- if (strcmp(dev->name, drv->driver.name) != 0)
- return 0;
-
- s3c24xx_serial_console.data = &s3c24xx_uart_drv;
- s3c24xx_serial_init_ports(info);
-
- register_console(&s3c24xx_serial_console);
- return 0;
-}
-
-#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
-
-MODULE_DESCRIPTION("Samsung SoC Serial port driver");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h
deleted file mode 100644
index 0ac06a07d25f..000000000000
--- a/drivers/serial/samsung.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* linux/drivers/serial/samsung.h
- *
- * Driver for Samsung SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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.
-*/
-
-struct s3c24xx_uart_info {
- char *name;
- unsigned int type;
- unsigned int fifosize;
- unsigned long rx_fifomask;
- unsigned long rx_fifoshift;
- unsigned long rx_fifofull;
- unsigned long tx_fifomask;
- unsigned long tx_fifoshift;
- unsigned long tx_fifofull;
-
- /* uart port features */
-
- unsigned int has_divslot:1;
-
- /* clock source control */
-
- int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
- int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
-
- /* uart controls */
- int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *);
-};
-
-struct s3c24xx_uart_port {
- unsigned char rx_claimed;
- unsigned char tx_claimed;
- unsigned int pm_level;
- unsigned long baudclk_rate;
-
- unsigned int rx_irq;
- unsigned int tx_irq;
-
- struct s3c24xx_uart_info *info;
- struct s3c24xx_uart_clksrc *clksrc;
- struct clk *clk;
- struct clk *baudclk;
- struct uart_port port;
-
-#ifdef CONFIG_CPU_FREQ
- struct notifier_block freq_transition;
-#endif
-};
-
-/* conversion functions */
-
-#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
-#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data)
-
-/* register access controls */
-
-#define portaddr(port, reg) ((port)->membase + (reg))
-
-#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
-#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
-
-#define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
-#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
-
-extern int s3c24xx_serial_probe(struct platform_device *dev,
- struct s3c24xx_uart_info *uart);
-
-extern int __devexit s3c24xx_serial_remove(struct platform_device *dev);
-
-extern int s3c24xx_serial_initconsole(struct platform_driver *drv,
- struct s3c24xx_uart_info **uart);
-
-extern int s3c24xx_serial_init(struct platform_driver *drv,
- struct s3c24xx_uart_info *info);
-
-#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
-
-#define s3c24xx_console_init(__drv, __inf) \
-static int __init s3c_serial_console_init(void) \
-{ \
- struct s3c24xx_uart_info *uinfo[CONFIG_SERIAL_SAMSUNG_UARTS]; \
- int i; \
- \
- for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) \
- uinfo[i] = __inf; \
- return s3c24xx_serial_initconsole(__drv, uinfo); \
-} \
- \
-console_initcall(s3c_serial_console_init)
-
-#else
-#define s3c24xx_console_init(drv, inf) extern void no_console(void)
-#endif
-
-#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG
-
-extern void printascii(const char *);
-
-static void dbg(const char *fmt, ...)
-{
- va_list va;
- char buff[256];
-
- va_start(va, fmt);
- vsprintf(buff, fmt, va);
- va_end(va);
-
- printascii(buff);
-}
-
-#else
-#define dbg(x...) do { } while (0)
-#endif
diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c
deleted file mode 100644
index a2f2b3254499..000000000000
--- a/drivers/serial/sb1250-duart.c
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
- * drivers/serial/sb1250-duart.c
- *
- * Support for the asynchronous serial interface (DUART) included
- * in the BCM1250 and derived System-On-a-Chip (SOC) devices.
- *
- * Copyright (c) 2007 Maciej W. Rozycki
- *
- * Derived from drivers/char/sb1250_duart.c for which the following
- * copyright applies:
- *
- * Copyright (c) 2000, 2001, 2002, 2003, 2004 Broadcom Corporation
- *
- * 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.
- *
- * References:
- *
- * "BCM1250/BCM1125/BCM1125H User Manual", Broadcom Corporation
- */
-
-#if defined(CONFIG_SERIAL_SB1250_DUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/compiler.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/spinlock.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/types.h>
-
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/war.h>
-
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_uart.h>
-#include <asm/sibyte/swarm.h>
-
-
-#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
-#include <asm/sibyte/bcm1480_regs.h>
-#include <asm/sibyte/bcm1480_int.h>
-
-#define SBD_CHANREGS(line) A_BCM1480_DUART_CHANREG((line), 0)
-#define SBD_CTRLREGS(line) A_BCM1480_DUART_CTRLREG((line), 0)
-#define SBD_INT(line) (K_BCM1480_INT_UART_0 + (line))
-
-#define DUART_CHANREG_SPACING BCM1480_DUART_CHANREG_SPACING
-
-#define R_DUART_IMRREG(line) R_BCM1480_DUART_IMRREG(line)
-#define R_DUART_INCHREG(line) R_BCM1480_DUART_INCHREG(line)
-#define R_DUART_ISRREG(line) R_BCM1480_DUART_ISRREG(line)
-
-#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-
-#define SBD_CHANREGS(line) A_DUART_CHANREG((line), 0)
-#define SBD_CTRLREGS(line) A_DUART_CTRLREG(0)
-#define SBD_INT(line) (K_INT_UART_0 + (line))
-
-#else
-#error invalid SB1250 UART configuration
-
-#endif
-
-
-MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
-MODULE_DESCRIPTION("BCM1xxx on-chip DUART serial driver");
-MODULE_LICENSE("GPL");
-
-
-#define DUART_MAX_CHIP 2
-#define DUART_MAX_SIDE 2
-
-/*
- * Per-port state.
- */
-struct sbd_port {
- struct sbd_duart *duart;
- struct uart_port port;
- unsigned char __iomem *memctrl;
- int tx_stopped;
- int initialised;
-};
-
-/*
- * Per-DUART state for the shared register space.
- */
-struct sbd_duart {
- struct sbd_port sport[2];
- unsigned long mapctrl;
- atomic_t map_guard;
-};
-
-#define to_sport(uport) container_of(uport, struct sbd_port, port)
-
-static struct sbd_duart sbd_duarts[DUART_MAX_CHIP];
-
-
-/*
- * Reading and writing SB1250 DUART registers.
- *
- * There are three register spaces: two per-channel ones and
- * a shared one. We have to define accessors appropriately.
- * All registers are 64-bit and all but the Baud Rate Clock
- * registers only define 8 least significant bits. There is
- * also a workaround to take into account. Raw accessors use
- * the full register width, but cooked ones truncate it
- * intentionally so that the rest of the driver does not care.
- */
-static u64 __read_sbdchn(struct sbd_port *sport, int reg)
-{
- void __iomem *csr = sport->port.membase + reg;
-
- return __raw_readq(csr);
-}
-
-static u64 __read_sbdshr(struct sbd_port *sport, int reg)
-{
- void __iomem *csr = sport->memctrl + reg;
-
- return __raw_readq(csr);
-}
-
-static void __write_sbdchn(struct sbd_port *sport, int reg, u64 value)
-{
- void __iomem *csr = sport->port.membase + reg;
-
- __raw_writeq(value, csr);
-}
-
-static void __write_sbdshr(struct sbd_port *sport, int reg, u64 value)
-{
- void __iomem *csr = sport->memctrl + reg;
-
- __raw_writeq(value, csr);
-}
-
-/*
- * In bug 1956, we get glitches that can mess up uart registers. This
- * "read-mode-reg after any register access" is an accepted workaround.
- */
-static void __war_sbd1956(struct sbd_port *sport)
-{
- __read_sbdchn(sport, R_DUART_MODE_REG_1);
- __read_sbdchn(sport, R_DUART_MODE_REG_2);
-}
-
-static unsigned char read_sbdchn(struct sbd_port *sport, int reg)
-{
- unsigned char retval;
-
- retval = __read_sbdchn(sport, reg);
- if (SIBYTE_1956_WAR)
- __war_sbd1956(sport);
- return retval;
-}
-
-static unsigned char read_sbdshr(struct sbd_port *sport, int reg)
-{
- unsigned char retval;
-
- retval = __read_sbdshr(sport, reg);
- if (SIBYTE_1956_WAR)
- __war_sbd1956(sport);
- return retval;
-}
-
-static void write_sbdchn(struct sbd_port *sport, int reg, unsigned int value)
-{
- __write_sbdchn(sport, reg, value);
- if (SIBYTE_1956_WAR)
- __war_sbd1956(sport);
-}
-
-static void write_sbdshr(struct sbd_port *sport, int reg, unsigned int value)
-{
- __write_sbdshr(sport, reg, value);
- if (SIBYTE_1956_WAR)
- __war_sbd1956(sport);
-}
-
-
-static int sbd_receive_ready(struct sbd_port *sport)
-{
- return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_RX_RDY;
-}
-
-static int sbd_receive_drain(struct sbd_port *sport)
-{
- int loops = 10000;
-
- while (sbd_receive_ready(sport) && --loops)
- read_sbdchn(sport, R_DUART_RX_HOLD);
- return loops;
-}
-
-static int __maybe_unused sbd_transmit_ready(struct sbd_port *sport)
-{
- return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_RDY;
-}
-
-static int __maybe_unused sbd_transmit_drain(struct sbd_port *sport)
-{
- int loops = 10000;
-
- while (!sbd_transmit_ready(sport) && --loops)
- udelay(2);
- return loops;
-}
-
-static int sbd_transmit_empty(struct sbd_port *sport)
-{
- return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_EMT;
-}
-
-static int sbd_line_drain(struct sbd_port *sport)
-{
- int loops = 10000;
-
- while (!sbd_transmit_empty(sport) && --loops)
- udelay(2);
- return loops;
-}
-
-
-static unsigned int sbd_tx_empty(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
-
- return sbd_transmit_empty(sport) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int sbd_get_mctrl(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
- unsigned int mctrl, status;
-
- status = read_sbdshr(sport, R_DUART_IN_PORT);
- status >>= (uport->line) % 2;
- mctrl = (!(status & M_DUART_IN_PIN0_VAL) ? TIOCM_CTS : 0) |
- (!(status & M_DUART_IN_PIN4_VAL) ? TIOCM_CAR : 0) |
- (!(status & M_DUART_RIN0_PIN) ? TIOCM_RNG : 0) |
- (!(status & M_DUART_IN_PIN2_VAL) ? TIOCM_DSR : 0);
- return mctrl;
-}
-
-static void sbd_set_mctrl(struct uart_port *uport, unsigned int mctrl)
-{
- struct sbd_port *sport = to_sport(uport);
- unsigned int clr = 0, set = 0, mode2;
-
- if (mctrl & TIOCM_DTR)
- set |= M_DUART_SET_OPR2;
- else
- clr |= M_DUART_CLR_OPR2;
- if (mctrl & TIOCM_RTS)
- set |= M_DUART_SET_OPR0;
- else
- clr |= M_DUART_CLR_OPR0;
- clr <<= (uport->line) % 2;
- set <<= (uport->line) % 2;
-
- mode2 = read_sbdchn(sport, R_DUART_MODE_REG_2);
- mode2 &= ~M_DUART_CHAN_MODE;
- if (mctrl & TIOCM_LOOP)
- mode2 |= V_DUART_CHAN_MODE_LCL_LOOP;
- else
- mode2 |= V_DUART_CHAN_MODE_NORMAL;
-
- write_sbdshr(sport, R_DUART_CLEAR_OPR, clr);
- write_sbdshr(sport, R_DUART_SET_OPR, set);
- write_sbdchn(sport, R_DUART_MODE_REG_2, mode2);
-}
-
-static void sbd_stop_tx(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
-
- write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
- sport->tx_stopped = 1;
-};
-
-static void sbd_start_tx(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
- unsigned int mask;
-
- /* Enable tx interrupts. */
- mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
- mask |= M_DUART_IMR_TX;
- write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
-
- /* Go!, go!, go!... */
- write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
- sport->tx_stopped = 0;
-};
-
-static void sbd_stop_rx(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
-
- write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
-};
-
-static void sbd_enable_ms(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
-
- write_sbdchn(sport, R_DUART_AUXCTL_X,
- M_DUART_CIN_CHNG_ENA | M_DUART_CTS_CHNG_ENA);
-}
-
-static void sbd_break_ctl(struct uart_port *uport, int break_state)
-{
- struct sbd_port *sport = to_sport(uport);
-
- if (break_state == -1)
- write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_START_BREAK);
- else
- write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_STOP_BREAK);
-}
-
-
-static void sbd_receive_chars(struct sbd_port *sport)
-{
- struct uart_port *uport = &sport->port;
- struct uart_icount *icount;
- unsigned int status, ch, flag;
- int count;
-
- for (count = 16; count; count--) {
- status = read_sbdchn(sport, R_DUART_STATUS);
- if (!(status & M_DUART_RX_RDY))
- break;
-
- ch = read_sbdchn(sport, R_DUART_RX_HOLD);
-
- flag = TTY_NORMAL;
-
- icount = &uport->icount;
- icount->rx++;
-
- if (unlikely(status &
- (M_DUART_RCVD_BRK | M_DUART_FRM_ERR |
- M_DUART_PARITY_ERR | M_DUART_OVRUN_ERR))) {
- if (status & M_DUART_RCVD_BRK) {
- icount->brk++;
- if (uart_handle_break(uport))
- continue;
- } else if (status & M_DUART_FRM_ERR)
- icount->frame++;
- else if (status & M_DUART_PARITY_ERR)
- icount->parity++;
- if (status & M_DUART_OVRUN_ERR)
- icount->overrun++;
-
- status &= uport->read_status_mask;
- if (status & M_DUART_RCVD_BRK)
- flag = TTY_BREAK;
- else if (status & M_DUART_FRM_ERR)
- flag = TTY_FRAME;
- else if (status & M_DUART_PARITY_ERR)
- flag = TTY_PARITY;
- }
-
- if (uart_handle_sysrq_char(uport, ch))
- continue;
-
- uart_insert_char(uport, status, M_DUART_OVRUN_ERR, ch, flag);
- }
-
- tty_flip_buffer_push(uport->state->port.tty);
-}
-
-static void sbd_transmit_chars(struct sbd_port *sport)
-{
- struct uart_port *uport = &sport->port;
- struct circ_buf *xmit = &sport->port.state->xmit;
- unsigned int mask;
- int stop_tx;
-
- /* XON/XOFF chars. */
- if (sport->port.x_char) {
- write_sbdchn(sport, R_DUART_TX_HOLD, sport->port.x_char);
- sport->port.icount.tx++;
- sport->port.x_char = 0;
- return;
- }
-
- /* If nothing to do or stopped or hardware stopped. */
- stop_tx = (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port));
-
- /* Send char. */
- if (!stop_tx) {
- write_sbdchn(sport, R_DUART_TX_HOLD, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- sport->port.icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&sport->port);
- }
-
- /* Are we are done? */
- if (stop_tx || uart_circ_empty(xmit)) {
- /* Disable tx interrupts. */
- mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
- mask &= ~M_DUART_IMR_TX;
- write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
- }
-}
-
-static void sbd_status_handle(struct sbd_port *sport)
-{
- struct uart_port *uport = &sport->port;
- unsigned int delta;
-
- delta = read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
- delta >>= (uport->line) % 2;
-
- if (delta & (M_DUART_IN_PIN0_VAL << S_DUART_IN_PIN_CHNG))
- uart_handle_cts_change(uport, !(delta & M_DUART_IN_PIN0_VAL));
-
- if (delta & (M_DUART_IN_PIN2_VAL << S_DUART_IN_PIN_CHNG))
- uport->icount.dsr++;
-
- if (delta & ((M_DUART_IN_PIN2_VAL | M_DUART_IN_PIN0_VAL) <<
- S_DUART_IN_PIN_CHNG))
- wake_up_interruptible(&uport->state->port.delta_msr_wait);
-}
-
-static irqreturn_t sbd_interrupt(int irq, void *dev_id)
-{
- struct sbd_port *sport = dev_id;
- struct uart_port *uport = &sport->port;
- irqreturn_t status = IRQ_NONE;
- unsigned int intstat;
- int count;
-
- for (count = 16; count; count--) {
- intstat = read_sbdshr(sport,
- R_DUART_ISRREG((uport->line) % 2));
- intstat &= read_sbdshr(sport,
- R_DUART_IMRREG((uport->line) % 2));
- intstat &= M_DUART_ISR_ALL;
- if (!intstat)
- break;
-
- if (intstat & M_DUART_ISR_RX)
- sbd_receive_chars(sport);
- if (intstat & M_DUART_ISR_IN)
- sbd_status_handle(sport);
- if (intstat & M_DUART_ISR_TX)
- sbd_transmit_chars(sport);
-
- status = IRQ_HANDLED;
- }
-
- return status;
-}
-
-
-static int sbd_startup(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
- unsigned int mode1;
- int ret;
-
- ret = request_irq(sport->port.irq, sbd_interrupt,
- IRQF_SHARED, "sb1250-duart", sport);
- if (ret)
- return ret;
-
- /* Clear the receive FIFO. */
- sbd_receive_drain(sport);
-
- /* Clear the interrupt registers. */
- write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT);
- read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
-
- /* Set rx/tx interrupt to FIFO available. */
- mode1 = read_sbdchn(sport, R_DUART_MODE_REG_1);
- mode1 &= ~(M_DUART_RX_IRQ_SEL_RXFULL | M_DUART_TX_IRQ_SEL_TXEMPT);
- write_sbdchn(sport, R_DUART_MODE_REG_1, mode1);
-
- /* Disable tx, enable rx. */
- write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_EN);
- sport->tx_stopped = 1;
-
- /* Enable interrupts. */
- write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
- M_DUART_IMR_IN | M_DUART_IMR_RX);
-
- return 0;
-}
-
-static void sbd_shutdown(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
-
- write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
- sport->tx_stopped = 1;
- free_irq(sport->port.irq, sport);
-}
-
-
-static void sbd_init_port(struct sbd_port *sport)
-{
- struct uart_port *uport = &sport->port;
-
- if (sport->initialised)
- return;
-
- /* There is no DUART reset feature, so just set some sane defaults. */
- write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_TX);
- write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_RX);
- write_sbdchn(sport, R_DUART_MODE_REG_1, V_DUART_BITS_PER_CHAR_8);
- write_sbdchn(sport, R_DUART_MODE_REG_2, 0);
- write_sbdchn(sport, R_DUART_FULL_CTL,
- V_DUART_INT_TIME(0) | V_DUART_SIG_FULL(15));
- write_sbdchn(sport, R_DUART_OPCR_X, 0);
- write_sbdchn(sport, R_DUART_AUXCTL_X, 0);
- write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
-
- sport->initialised = 1;
-}
-
-static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios,
- struct ktermios *old_termios)
-{
- struct sbd_port *sport = to_sport(uport);
- unsigned int mode1 = 0, mode2 = 0, aux = 0;
- unsigned int mode1mask = 0, mode2mask = 0, auxmask = 0;
- unsigned int oldmode1, oldmode2, oldaux;
- unsigned int baud, brg;
- unsigned int command;
-
- mode1mask |= ~(M_DUART_PARITY_MODE | M_DUART_PARITY_TYPE_ODD |
- M_DUART_BITS_PER_CHAR);
- mode2mask |= ~M_DUART_STOP_BIT_LEN_2;
- auxmask |= ~M_DUART_CTS_CHNG_ENA;
-
- /* Byte size. */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- case CS6:
- /* Unsupported, leave unchanged. */
- mode1mask |= M_DUART_PARITY_MODE;
- break;
- case CS7:
- mode1 |= V_DUART_BITS_PER_CHAR_7;
- break;
- case CS8:
- default:
- mode1 |= V_DUART_BITS_PER_CHAR_8;
- break;
- }
-
- /* Parity and stop bits. */
- if (termios->c_cflag & CSTOPB)
- mode2 |= M_DUART_STOP_BIT_LEN_2;
- else
- mode2 |= M_DUART_STOP_BIT_LEN_1;
- if (termios->c_cflag & PARENB)
- mode1 |= V_DUART_PARITY_MODE_ADD;
- else
- mode1 |= V_DUART_PARITY_MODE_NONE;
- if (termios->c_cflag & PARODD)
- mode1 |= M_DUART_PARITY_TYPE_ODD;
- else
- mode1 |= M_DUART_PARITY_TYPE_EVEN;
-
- baud = uart_get_baud_rate(uport, termios, old_termios, 1200, 5000000);
- brg = V_DUART_BAUD_RATE(baud);
- /* The actual lower bound is 1221bps, so compensate. */
- if (brg > M_DUART_CLK_COUNTER)
- brg = M_DUART_CLK_COUNTER;
-
- uart_update_timeout(uport, termios->c_cflag, baud);
-
- uport->read_status_mask = M_DUART_OVRUN_ERR;
- if (termios->c_iflag & INPCK)
- uport->read_status_mask |= M_DUART_FRM_ERR |
- M_DUART_PARITY_ERR;
- if (termios->c_iflag & (BRKINT | PARMRK))
- uport->read_status_mask |= M_DUART_RCVD_BRK;
-
- uport->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- uport->ignore_status_mask |= M_DUART_FRM_ERR |
- M_DUART_PARITY_ERR;
- if (termios->c_iflag & IGNBRK) {
- uport->ignore_status_mask |= M_DUART_RCVD_BRK;
- if (termios->c_iflag & IGNPAR)
- uport->ignore_status_mask |= M_DUART_OVRUN_ERR;
- }
-
- if (termios->c_cflag & CREAD)
- command = M_DUART_RX_EN;
- else
- command = M_DUART_RX_DIS;
-
- if (termios->c_cflag & CRTSCTS)
- aux |= M_DUART_CTS_CHNG_ENA;
- else
- aux &= ~M_DUART_CTS_CHNG_ENA;
-
- spin_lock(&uport->lock);
-
- if (sport->tx_stopped)
- command |= M_DUART_TX_DIS;
- else
- command |= M_DUART_TX_EN;
-
- oldmode1 = read_sbdchn(sport, R_DUART_MODE_REG_1) & mode1mask;
- oldmode2 = read_sbdchn(sport, R_DUART_MODE_REG_2) & mode2mask;
- oldaux = read_sbdchn(sport, R_DUART_AUXCTL_X) & auxmask;
-
- if (!sport->tx_stopped)
- sbd_line_drain(sport);
- write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
-
- write_sbdchn(sport, R_DUART_MODE_REG_1, mode1 | oldmode1);
- write_sbdchn(sport, R_DUART_MODE_REG_2, mode2 | oldmode2);
- write_sbdchn(sport, R_DUART_CLK_SEL, brg);
- write_sbdchn(sport, R_DUART_AUXCTL_X, aux | oldaux);
-
- write_sbdchn(sport, R_DUART_CMD, command);
-
- spin_unlock(&uport->lock);
-}
-
-
-static const char *sbd_type(struct uart_port *uport)
-{
- return "SB1250 DUART";
-}
-
-static void sbd_release_port(struct uart_port *uport)
-{
- struct sbd_port *sport = to_sport(uport);
- struct sbd_duart *duart = sport->duart;
- int map_guard;
-
- iounmap(sport->memctrl);
- sport->memctrl = NULL;
- iounmap(uport->membase);
- uport->membase = NULL;
-
- map_guard = atomic_add_return(-1, &duart->map_guard);
- if (!map_guard)
- release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
- release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
-}
-
-static int sbd_map_port(struct uart_port *uport)
-{
- const char *err = KERN_ERR "sbd: Cannot map MMIO\n";
- struct sbd_port *sport = to_sport(uport);
- struct sbd_duart *duart = sport->duart;
-
- if (!uport->membase)
- uport->membase = ioremap_nocache(uport->mapbase,
- DUART_CHANREG_SPACING);
- if (!uport->membase) {
- printk(err);
- return -ENOMEM;
- }
-
- if (!sport->memctrl)
- sport->memctrl = ioremap_nocache(duart->mapctrl,
- DUART_CHANREG_SPACING);
- if (!sport->memctrl) {
- printk(err);
- iounmap(uport->membase);
- uport->membase = NULL;
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int sbd_request_port(struct uart_port *uport)
-{
- const char *err = KERN_ERR "sbd: Unable to reserve MMIO resource\n";
- struct sbd_duart *duart = to_sport(uport)->duart;
- int map_guard;
- int ret = 0;
-
- if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
- "sb1250-duart")) {
- printk(err);
- return -EBUSY;
- }
- map_guard = atomic_add_return(1, &duart->map_guard);
- if (map_guard == 1) {
- if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
- "sb1250-duart")) {
- atomic_add(-1, &duart->map_guard);
- printk(err);
- ret = -EBUSY;
- }
- }
- if (!ret) {
- ret = sbd_map_port(uport);
- if (ret) {
- map_guard = atomic_add_return(-1, &duart->map_guard);
- if (!map_guard)
- release_mem_region(duart->mapctrl,
- DUART_CHANREG_SPACING);
- }
- }
- if (ret) {
- release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
- return ret;
- }
- return 0;
-}
-
-static void sbd_config_port(struct uart_port *uport, int flags)
-{
- struct sbd_port *sport = to_sport(uport);
-
- if (flags & UART_CONFIG_TYPE) {
- if (sbd_request_port(uport))
- return;
-
- uport->type = PORT_SB1250_DUART;
-
- sbd_init_port(sport);
- }
-}
-
-static int sbd_verify_port(struct uart_port *uport, struct serial_struct *ser)
-{
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_SB1250_DUART)
- ret = -EINVAL;
- if (ser->irq != uport->irq)
- ret = -EINVAL;
- if (ser->baud_base != uport->uartclk / 16)
- ret = -EINVAL;
- return ret;
-}
-
-
-static const struct uart_ops sbd_ops = {
- .tx_empty = sbd_tx_empty,
- .set_mctrl = sbd_set_mctrl,
- .get_mctrl = sbd_get_mctrl,
- .stop_tx = sbd_stop_tx,
- .start_tx = sbd_start_tx,
- .stop_rx = sbd_stop_rx,
- .enable_ms = sbd_enable_ms,
- .break_ctl = sbd_break_ctl,
- .startup = sbd_startup,
- .shutdown = sbd_shutdown,
- .set_termios = sbd_set_termios,
- .type = sbd_type,
- .release_port = sbd_release_port,
- .request_port = sbd_request_port,
- .config_port = sbd_config_port,
- .verify_port = sbd_verify_port,
-};
-
-/* Initialize SB1250 DUART port structures. */
-static void __init sbd_probe_duarts(void)
-{
- static int probed;
- int chip, side;
- int max_lines, line;
-
- if (probed)
- return;
-
- /* Set the number of available units based on the SOC type. */
- switch (soc_type) {
- case K_SYS_SOC_TYPE_BCM1x55:
- case K_SYS_SOC_TYPE_BCM1x80:
- max_lines = 4;
- break;
- default:
- /* Assume at least two serial ports at the normal address. */
- max_lines = 2;
- break;
- }
-
- probed = 1;
-
- for (chip = 0, line = 0; chip < DUART_MAX_CHIP && line < max_lines;
- chip++) {
- sbd_duarts[chip].mapctrl = SBD_CTRLREGS(line);
-
- for (side = 0; side < DUART_MAX_SIDE && line < max_lines;
- side++, line++) {
- struct sbd_port *sport = &sbd_duarts[chip].sport[side];
- struct uart_port *uport = &sport->port;
-
- sport->duart = &sbd_duarts[chip];
-
- uport->irq = SBD_INT(line);
- uport->uartclk = 100000000 / 20 * 16;
- uport->fifosize = 16;
- uport->iotype = UPIO_MEM;
- uport->flags = UPF_BOOT_AUTOCONF;
- uport->ops = &sbd_ops;
- uport->line = line;
- uport->mapbase = SBD_CHANREGS(line);
- }
- }
-}
-
-
-#ifdef CONFIG_SERIAL_SB1250_DUART_CONSOLE
-/*
- * Serial console stuff. Very basic, polling driver for doing serial
- * console output. The console_sem is held by the caller, so we
- * shouldn't be interrupted for more console activity.
- */
-static void sbd_console_putchar(struct uart_port *uport, int ch)
-{
- struct sbd_port *sport = to_sport(uport);
-
- sbd_transmit_drain(sport);
- write_sbdchn(sport, R_DUART_TX_HOLD, ch);
-}
-
-static void sbd_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- int chip = co->index / DUART_MAX_SIDE;
- int side = co->index % DUART_MAX_SIDE;
- struct sbd_port *sport = &sbd_duarts[chip].sport[side];
- struct uart_port *uport = &sport->port;
- unsigned long flags;
- unsigned int mask;
-
- /* Disable transmit interrupts and enable the transmitter. */
- spin_lock_irqsave(&uport->lock, flags);
- mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
- write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
- mask & ~M_DUART_IMR_TX);
- write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
- spin_unlock_irqrestore(&uport->lock, flags);
-
- uart_console_write(&sport->port, s, count, sbd_console_putchar);
-
- /* Restore transmit interrupts and the transmitter enable. */
- spin_lock_irqsave(&uport->lock, flags);
- sbd_line_drain(sport);
- if (sport->tx_stopped)
- write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
- write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
- spin_unlock_irqrestore(&uport->lock, flags);
-}
-
-static int __init sbd_console_setup(struct console *co, char *options)
-{
- int chip = co->index / DUART_MAX_SIDE;
- int side = co->index % DUART_MAX_SIDE;
- struct sbd_port *sport = &sbd_duarts[chip].sport[side];
- struct uart_port *uport = &sport->port;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- int ret;
-
- if (!sport->duart)
- return -ENXIO;
-
- ret = sbd_map_port(uport);
- if (ret)
- return ret;
-
- sbd_init_port(sport);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- return uart_set_options(uport, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver sbd_reg;
-static struct console sbd_console = {
- .name = "duart",
- .write = sbd_console_write,
- .device = uart_console_device,
- .setup = sbd_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sbd_reg
-};
-
-static int __init sbd_serial_console_init(void)
-{
- sbd_probe_duarts();
- register_console(&sbd_console);
-
- return 0;
-}
-
-console_initcall(sbd_serial_console_init);
-
-#define SERIAL_SB1250_DUART_CONSOLE &sbd_console
-#else
-#define SERIAL_SB1250_DUART_CONSOLE NULL
-#endif /* CONFIG_SERIAL_SB1250_DUART_CONSOLE */
-
-
-static struct uart_driver sbd_reg = {
- .owner = THIS_MODULE,
- .driver_name = "sb1250_duart",
- .dev_name = "duart",
- .major = TTY_MAJOR,
- .minor = SB1250_DUART_MINOR_BASE,
- .nr = DUART_MAX_CHIP * DUART_MAX_SIDE,
- .cons = SERIAL_SB1250_DUART_CONSOLE,
-};
-
-/* Set up the driver and register it. */
-static int __init sbd_init(void)
-{
- int i, ret;
-
- sbd_probe_duarts();
-
- ret = uart_register_driver(&sbd_reg);
- if (ret)
- return ret;
-
- for (i = 0; i < DUART_MAX_CHIP * DUART_MAX_SIDE; i++) {
- struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
- struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
- struct uart_port *uport = &sport->port;
-
- if (sport->duart)
- uart_add_one_port(&sbd_reg, uport);
- }
-
- return 0;
-}
-
-/* Unload the driver. Unregister stuff, get ready to go away. */
-static void __exit sbd_exit(void)
-{
- int i;
-
- for (i = DUART_MAX_CHIP * DUART_MAX_SIDE - 1; i >= 0; i--) {
- struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
- struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
- struct uart_port *uport = &sport->port;
-
- if (sport->duart)
- uart_remove_one_port(&sbd_reg, uport);
- }
-
- uart_unregister_driver(&sbd_reg);
-}
-
-module_init(sbd_init);
-module_exit(sbd_exit);
diff --git a/drivers/serial/sc26xx.c b/drivers/serial/sc26xx.c
deleted file mode 100644
index 75038ad2b242..000000000000
--- a/drivers/serial/sc26xx.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * SC268xx.c: Serial driver for Philiphs SC2681/SC2692 devices.
- *
- * Copyright (C) 2006,2007 Thomas Bogendörfer (tsbogend@alpha.franken.de)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/circ_buf.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-
-#if defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#define SC26XX_MAJOR 204
-#define SC26XX_MINOR_START 205
-#define SC26XX_NR 2
-
-struct uart_sc26xx_port {
- struct uart_port port[2];
- u8 dsr_mask[2];
- u8 cts_mask[2];
- u8 dcd_mask[2];
- u8 ri_mask[2];
- u8 dtr_mask[2];
- u8 rts_mask[2];
- u8 imr;
-};
-
-/* register common to both ports */
-#define RD_ISR 0x14
-#define RD_IPR 0x34
-
-#define WR_ACR 0x10
-#define WR_IMR 0x14
-#define WR_OPCR 0x34
-#define WR_OPR_SET 0x38
-#define WR_OPR_CLR 0x3C
-
-/* access common register */
-#define READ_SC(p, r) readb((p)->membase + RD_##r)
-#define WRITE_SC(p, r, v) writeb((v), (p)->membase + WR_##r)
-
-/* register per port */
-#define RD_PORT_MRx 0x00
-#define RD_PORT_SR 0x04
-#define RD_PORT_RHR 0x0c
-
-#define WR_PORT_MRx 0x00
-#define WR_PORT_CSR 0x04
-#define WR_PORT_CR 0x08
-#define WR_PORT_THR 0x0c
-
-/* SR bits */
-#define SR_BREAK (1 << 7)
-#define SR_FRAME (1 << 6)
-#define SR_PARITY (1 << 5)
-#define SR_OVERRUN (1 << 4)
-#define SR_TXRDY (1 << 2)
-#define SR_RXRDY (1 << 0)
-
-#define CR_RES_MR (1 << 4)
-#define CR_RES_RX (2 << 4)
-#define CR_RES_TX (3 << 4)
-#define CR_STRT_BRK (6 << 4)
-#define CR_STOP_BRK (7 << 4)
-#define CR_DIS_TX (1 << 3)
-#define CR_ENA_TX (1 << 2)
-#define CR_DIS_RX (1 << 1)
-#define CR_ENA_RX (1 << 0)
-
-/* ISR bits */
-#define ISR_RXRDYB (1 << 5)
-#define ISR_TXRDYB (1 << 4)
-#define ISR_RXRDYA (1 << 1)
-#define ISR_TXRDYA (1 << 0)
-
-/* IMR bits */
-#define IMR_RXRDY (1 << 1)
-#define IMR_TXRDY (1 << 0)
-
-/* access port register */
-static inline u8 read_sc_port(struct uart_port *p, u8 reg)
-{
- return readb(p->membase + p->line * 0x20 + reg);
-}
-
-static inline void write_sc_port(struct uart_port *p, u8 reg, u8 val)
-{
- writeb(val, p->membase + p->line * 0x20 + reg);
-}
-
-#define READ_SC_PORT(p, r) read_sc_port(p, RD_PORT_##r)
-#define WRITE_SC_PORT(p, r, v) write_sc_port(p, WR_PORT_##r, v)
-
-static void sc26xx_enable_irq(struct uart_port *port, int mask)
-{
- struct uart_sc26xx_port *up;
- int line = port->line;
-
- port -= line;
- up = container_of(port, struct uart_sc26xx_port, port[0]);
-
- up->imr |= mask << (line * 4);
- WRITE_SC(port, IMR, up->imr);
-}
-
-static void sc26xx_disable_irq(struct uart_port *port, int mask)
-{
- struct uart_sc26xx_port *up;
- int line = port->line;
-
- port -= line;
- up = container_of(port, struct uart_sc26xx_port, port[0]);
-
- up->imr &= ~(mask << (line * 4));
- WRITE_SC(port, IMR, up->imr);
-}
-
-static struct tty_struct *receive_chars(struct uart_port *port)
-{
- struct tty_struct *tty = NULL;
- int limit = 10000;
- unsigned char ch;
- char flag;
- u8 status;
-
- if (port->state != NULL) /* Unopened serial console */
- tty = port->state->port.tty;
-
- while (limit-- > 0) {
- status = READ_SC_PORT(port, SR);
- if (!(status & SR_RXRDY))
- break;
- ch = READ_SC_PORT(port, RHR);
-
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- if (unlikely(status & (SR_BREAK | SR_FRAME |
- SR_PARITY | SR_OVERRUN))) {
- if (status & SR_BREAK) {
- status &= ~(SR_PARITY | SR_FRAME);
- port->icount.brk++;
- if (uart_handle_break(port))
- continue;
- } else if (status & SR_PARITY)
- port->icount.parity++;
- else if (status & SR_FRAME)
- port->icount.frame++;
- if (status & SR_OVERRUN)
- port->icount.overrun++;
-
- status &= port->read_status_mask;
- if (status & SR_BREAK)
- flag = TTY_BREAK;
- else if (status & SR_PARITY)
- flag = TTY_PARITY;
- else if (status & SR_FRAME)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, ch))
- continue;
-
- if (status & port->ignore_status_mask)
- continue;
-
- tty_insert_flip_char(tty, ch, flag);
- }
- return tty;
-}
-
-static void transmit_chars(struct uart_port *port)
-{
- struct circ_buf *xmit;
-
- if (!port->state)
- return;
-
- xmit = &port->state->xmit;
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- sc26xx_disable_irq(port, IMR_TXRDY);
- return;
- }
- while (!uart_circ_empty(xmit)) {
- if (!(READ_SC_PORT(port, SR) & SR_TXRDY))
- break;
-
- WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-}
-
-static irqreturn_t sc26xx_interrupt(int irq, void *dev_id)
-{
- struct uart_sc26xx_port *up = dev_id;
- struct tty_struct *tty;
- unsigned long flags;
- u8 isr;
-
- spin_lock_irqsave(&up->port[0].lock, flags);
-
- tty = NULL;
- isr = READ_SC(&up->port[0], ISR);
- if (isr & ISR_TXRDYA)
- transmit_chars(&up->port[0]);
- if (isr & ISR_RXRDYA)
- tty = receive_chars(&up->port[0]);
-
- spin_unlock(&up->port[0].lock);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- spin_lock(&up->port[1].lock);
-
- tty = NULL;
- if (isr & ISR_TXRDYB)
- transmit_chars(&up->port[1]);
- if (isr & ISR_RXRDYB)
- tty = receive_chars(&up->port[1]);
-
- spin_unlock_irqrestore(&up->port[1].lock, flags);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- return IRQ_HANDLED;
-}
-
-/* port->lock is not held. */
-static unsigned int sc26xx_tx_empty(struct uart_port *port)
-{
- return (READ_SC_PORT(port, SR) & SR_TXRDY) ? TIOCSER_TEMT : 0;
-}
-
-/* port->lock held by caller. */
-static void sc26xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_sc26xx_port *up;
- int line = port->line;
-
- port -= line;
- up = container_of(port, struct uart_sc26xx_port, port[0]);
-
- if (up->dtr_mask[line]) {
- if (mctrl & TIOCM_DTR)
- WRITE_SC(port, OPR_SET, up->dtr_mask[line]);
- else
- WRITE_SC(port, OPR_CLR, up->dtr_mask[line]);
- }
- if (up->rts_mask[line]) {
- if (mctrl & TIOCM_RTS)
- WRITE_SC(port, OPR_SET, up->rts_mask[line]);
- else
- WRITE_SC(port, OPR_CLR, up->rts_mask[line]);
- }
-}
-
-/* port->lock is held by caller and interrupts are disabled. */
-static unsigned int sc26xx_get_mctrl(struct uart_port *port)
-{
- struct uart_sc26xx_port *up;
- int line = port->line;
- unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
- u8 ipr;
-
- port -= line;
- up = container_of(port, struct uart_sc26xx_port, port[0]);
- ipr = READ_SC(port, IPR) ^ 0xff;
-
- if (up->dsr_mask[line]) {
- mctrl &= ~TIOCM_DSR;
- mctrl |= ipr & up->dsr_mask[line] ? TIOCM_DSR : 0;
- }
- if (up->cts_mask[line]) {
- mctrl &= ~TIOCM_CTS;
- mctrl |= ipr & up->cts_mask[line] ? TIOCM_CTS : 0;
- }
- if (up->dcd_mask[line]) {
- mctrl &= ~TIOCM_CAR;
- mctrl |= ipr & up->dcd_mask[line] ? TIOCM_CAR : 0;
- }
- if (up->ri_mask[line]) {
- mctrl &= ~TIOCM_RNG;
- mctrl |= ipr & up->ri_mask[line] ? TIOCM_RNG : 0;
- }
- return mctrl;
-}
-
-/* port->lock held by caller. */
-static void sc26xx_stop_tx(struct uart_port *port)
-{
- return;
-}
-
-/* port->lock held by caller. */
-static void sc26xx_start_tx(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- while (!uart_circ_empty(xmit)) {
- if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) {
- sc26xx_enable_irq(port, IMR_TXRDY);
- break;
- }
- WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
-}
-
-/* port->lock held by caller. */
-static void sc26xx_stop_rx(struct uart_port *port)
-{
-}
-
-/* port->lock held by caller. */
-static void sc26xx_enable_ms(struct uart_port *port)
-{
-}
-
-/* port->lock is not held. */
-static void sc26xx_break_ctl(struct uart_port *port, int break_state)
-{
- if (break_state == -1)
- WRITE_SC_PORT(port, CR, CR_STRT_BRK);
- else
- WRITE_SC_PORT(port, CR, CR_STOP_BRK);
-}
-
-/* port->lock is not held. */
-static int sc26xx_startup(struct uart_port *port)
-{
- sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
- WRITE_SC(port, OPCR, 0);
-
- /* reset tx and rx */
- WRITE_SC_PORT(port, CR, CR_RES_RX);
- WRITE_SC_PORT(port, CR, CR_RES_TX);
-
- /* start rx/tx */
- WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX);
-
- /* enable irqs */
- sc26xx_enable_irq(port, IMR_RXRDY);
- return 0;
-}
-
-/* port->lock is not held. */
-static void sc26xx_shutdown(struct uart_port *port)
-{
- /* disable interrupst */
- sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
-
- /* stop tx/rx */
- WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX);
-}
-
-/* port->lock is not held. */
-static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
- unsigned int quot = uart_get_divisor(port, baud);
- unsigned int iflag, cflag;
- unsigned long flags;
- u8 mr1, mr2, csr;
-
- spin_lock_irqsave(&port->lock, flags);
-
- while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc)
- udelay(2);
-
- WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX);
-
- iflag = termios->c_iflag;
- cflag = termios->c_cflag;
-
- port->read_status_mask = SR_OVERRUN;
- if (iflag & INPCK)
- port->read_status_mask |= SR_PARITY | SR_FRAME;
- if (iflag & (BRKINT | PARMRK))
- port->read_status_mask |= SR_BREAK;
-
- port->ignore_status_mask = 0;
- if (iflag & IGNBRK)
- port->ignore_status_mask |= SR_BREAK;
- if ((cflag & CREAD) == 0)
- port->ignore_status_mask |= SR_BREAK | SR_FRAME |
- SR_PARITY | SR_OVERRUN;
-
- switch (cflag & CSIZE) {
- case CS5:
- mr1 = 0x00;
- break;
- case CS6:
- mr1 = 0x01;
- break;
- case CS7:
- mr1 = 0x02;
- break;
- default:
- case CS8:
- mr1 = 0x03;
- break;
- }
- mr2 = 0x07;
- if (cflag & CSTOPB)
- mr2 = 0x0f;
- if (cflag & PARENB) {
- if (cflag & PARODD)
- mr1 |= (1 << 2);
- } else
- mr1 |= (2 << 3);
-
- switch (baud) {
- case 50:
- csr = 0x00;
- break;
- case 110:
- csr = 0x11;
- break;
- case 134:
- csr = 0x22;
- break;
- case 200:
- csr = 0x33;
- break;
- case 300:
- csr = 0x44;
- break;
- case 600:
- csr = 0x55;
- break;
- case 1200:
- csr = 0x66;
- break;
- case 2400:
- csr = 0x88;
- break;
- case 4800:
- csr = 0x99;
- break;
- default:
- case 9600:
- csr = 0xbb;
- break;
- case 19200:
- csr = 0xcc;
- break;
- }
-
- WRITE_SC_PORT(port, CR, CR_RES_MR);
- WRITE_SC_PORT(port, MRx, mr1);
- WRITE_SC_PORT(port, MRx, mr2);
-
- WRITE_SC(port, ACR, 0x80);
- WRITE_SC_PORT(port, CSR, csr);
-
- /* reset tx and rx */
- WRITE_SC_PORT(port, CR, CR_RES_RX);
- WRITE_SC_PORT(port, CR, CR_RES_TX);
-
- WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX);
- while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc)
- udelay(2);
-
- /* XXX */
- uart_update_timeout(port, cflag,
- (port->uartclk / (16 * quot)));
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *sc26xx_type(struct uart_port *port)
-{
- return "SC26XX";
-}
-
-static void sc26xx_release_port(struct uart_port *port)
-{
-}
-
-static int sc26xx_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void sc26xx_config_port(struct uart_port *port, int flags)
-{
-}
-
-static int sc26xx_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-static struct uart_ops sc26xx_ops = {
- .tx_empty = sc26xx_tx_empty,
- .set_mctrl = sc26xx_set_mctrl,
- .get_mctrl = sc26xx_get_mctrl,
- .stop_tx = sc26xx_stop_tx,
- .start_tx = sc26xx_start_tx,
- .stop_rx = sc26xx_stop_rx,
- .enable_ms = sc26xx_enable_ms,
- .break_ctl = sc26xx_break_ctl,
- .startup = sc26xx_startup,
- .shutdown = sc26xx_shutdown,
- .set_termios = sc26xx_set_termios,
- .type = sc26xx_type,
- .release_port = sc26xx_release_port,
- .request_port = sc26xx_request_port,
- .config_port = sc26xx_config_port,
- .verify_port = sc26xx_verify_port,
-};
-
-static struct uart_port *sc26xx_port;
-
-#ifdef CONFIG_SERIAL_SC26XX_CONSOLE
-static void sc26xx_console_putchar(struct uart_port *port, char c)
-{
- unsigned long flags;
- int limit = 1000000;
-
- spin_lock_irqsave(&port->lock, flags);
-
- while (limit-- > 0) {
- if (READ_SC_PORT(port, SR) & SR_TXRDY) {
- WRITE_SC_PORT(port, THR, c);
- break;
- }
- udelay(2);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void sc26xx_console_write(struct console *con, const char *s, unsigned n)
-{
- struct uart_port *port = sc26xx_port;
- int i;
-
- for (i = 0; i < n; i++) {
- if (*s == '\n')
- sc26xx_console_putchar(port, '\r');
- sc26xx_console_putchar(port, *s++);
- }
-}
-
-static int __init sc26xx_console_setup(struct console *con, char *options)
-{
- struct uart_port *port = sc26xx_port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (port->type != PORT_SC26XX)
- return -1;
-
- printk(KERN_INFO "Console: ttySC%d (SC26XX)\n", con->index);
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, con, baud, parity, bits, flow);
-}
-
-static struct uart_driver sc26xx_reg;
-static struct console sc26xx_console = {
- .name = "ttySC",
- .write = sc26xx_console_write,
- .device = uart_console_device,
- .setup = sc26xx_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sc26xx_reg,
-};
-#define SC26XX_CONSOLE &sc26xx_console
-#else
-#define SC26XX_CONSOLE NULL
-#endif
-
-static struct uart_driver sc26xx_reg = {
- .owner = THIS_MODULE,
- .driver_name = "SC26xx",
- .dev_name = "ttySC",
- .major = SC26XX_MAJOR,
- .minor = SC26XX_MINOR_START,
- .nr = SC26XX_NR,
- .cons = SC26XX_CONSOLE,
-};
-
-static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos)
-{
- unsigned int bit = (flags >> bitpos) & 15;
-
- return bit ? (1 << (bit - 1)) : 0;
-}
-
-static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
- int line, unsigned int data)
-{
- up->dtr_mask[line] = sc26xx_flags2mask(data, 0);
- up->rts_mask[line] = sc26xx_flags2mask(data, 4);
- up->dsr_mask[line] = sc26xx_flags2mask(data, 8);
- up->cts_mask[line] = sc26xx_flags2mask(data, 12);
- up->dcd_mask[line] = sc26xx_flags2mask(data, 16);
- up->ri_mask[line] = sc26xx_flags2mask(data, 20);
-}
-
-static int __devinit sc26xx_probe(struct platform_device *dev)
-{
- struct resource *res;
- struct uart_sc26xx_port *up;
- unsigned int *sc26xx_data = dev->dev.platform_data;
- int err;
-
- res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- up = kzalloc(sizeof *up, GFP_KERNEL);
- if (unlikely(!up))
- return -ENOMEM;
-
- up->port[0].line = 0;
- up->port[0].ops = &sc26xx_ops;
- up->port[0].type = PORT_SC26XX;
- up->port[0].uartclk = (29491200 / 16); /* arbitrary */
-
- up->port[0].mapbase = res->start;
- up->port[0].membase = ioremap_nocache(up->port[0].mapbase, 0x40);
- up->port[0].iotype = UPIO_MEM;
- up->port[0].irq = platform_get_irq(dev, 0);
-
- up->port[0].dev = &dev->dev;
-
- sc26xx_init_masks(up, 0, sc26xx_data[0]);
-
- sc26xx_port = &up->port[0];
-
- up->port[1].line = 1;
- up->port[1].ops = &sc26xx_ops;
- up->port[1].type = PORT_SC26XX;
- up->port[1].uartclk = (29491200 / 16); /* arbitrary */
-
- up->port[1].mapbase = up->port[0].mapbase;
- up->port[1].membase = up->port[0].membase;
- up->port[1].iotype = UPIO_MEM;
- up->port[1].irq = up->port[0].irq;
-
- up->port[1].dev = &dev->dev;
-
- sc26xx_init_masks(up, 1, sc26xx_data[1]);
-
- err = uart_register_driver(&sc26xx_reg);
- if (err)
- goto out_free_port;
-
- sc26xx_reg.tty_driver->name_base = sc26xx_reg.minor;
-
- err = uart_add_one_port(&sc26xx_reg, &up->port[0]);
- if (err)
- goto out_unregister_driver;
-
- err = uart_add_one_port(&sc26xx_reg, &up->port[1]);
- if (err)
- goto out_remove_port0;
-
- err = request_irq(up->port[0].irq, sc26xx_interrupt, 0, "sc26xx", up);
- if (err)
- goto out_remove_ports;
-
- dev_set_drvdata(&dev->dev, up);
- return 0;
-
-out_remove_ports:
- uart_remove_one_port(&sc26xx_reg, &up->port[1]);
-out_remove_port0:
- uart_remove_one_port(&sc26xx_reg, &up->port[0]);
-
-out_unregister_driver:
- uart_unregister_driver(&sc26xx_reg);
-
-out_free_port:
- kfree(up);
- sc26xx_port = NULL;
- return err;
-}
-
-
-static int __exit sc26xx_driver_remove(struct platform_device *dev)
-{
- struct uart_sc26xx_port *up = dev_get_drvdata(&dev->dev);
-
- free_irq(up->port[0].irq, up);
-
- uart_remove_one_port(&sc26xx_reg, &up->port[0]);
- uart_remove_one_port(&sc26xx_reg, &up->port[1]);
-
- uart_unregister_driver(&sc26xx_reg);
-
- kfree(up);
- sc26xx_port = NULL;
-
- dev_set_drvdata(&dev->dev, NULL);
- return 0;
-}
-
-static struct platform_driver sc26xx_driver = {
- .probe = sc26xx_probe,
- .remove = __devexit_p(sc26xx_driver_remove),
- .driver = {
- .name = "SC26xx",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init sc26xx_init(void)
-{
- return platform_driver_register(&sc26xx_driver);
-}
-
-static void __exit sc26xx_exit(void)
-{
- platform_driver_unregister(&sc26xx_driver);
-}
-
-module_init(sc26xx_init);
-module_exit(sc26xx_exit);
-
-
-MODULE_AUTHOR("Thomas Bogendörfer");
-MODULE_DESCRIPTION("SC681/SC2692 serial driver");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:SC26xx");
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
deleted file mode 100644
index 460a72d91bb7..000000000000
--- a/drivers/serial/serial_core.c
+++ /dev/null
@@ -1,2578 +0,0 @@
-/*
- * linux/drivers/char/core.c
- *
- * Driver core for serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright 1999 ARM Limited
- * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/device.h>
-#include <linux/serial.h> /* for serial_state and serial_icounter_struct */
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-/*
- * This is used to lock changes in serial line configuration.
- */
-static DEFINE_MUTEX(port_mutex);
-
-/*
- * lockdep: port->lock is initialized in two places, but we
- * want only one lock-class:
- */
-static struct lock_class_key port_lock_key;
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
-#else
-#define uart_console(port) (0)
-#endif
-
-static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
- struct ktermios *old_termios);
-static void __uart_wait_until_sent(struct uart_port *port, int timeout);
-static void uart_change_pm(struct uart_state *state, int pm_state);
-
-/*
- * This routine is used by the interrupt handler to schedule processing in
- * the software interrupt portion of the driver.
- */
-void uart_write_wakeup(struct uart_port *port)
-{
- struct uart_state *state = port->state;
- /*
- * This means you called this function _after_ the port was
- * closed. No cookie for you.
- */
- BUG_ON(!state);
- tasklet_schedule(&state->tlet);
-}
-
-static void uart_stop(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- port->ops->stop_tx(port);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void __uart_start(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
-
- if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&
- !tty->stopped && !tty->hw_stopped)
- port->ops->start_tx(port);
-}
-
-static void uart_start(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- __uart_start(tty);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void uart_tasklet_action(unsigned long data)
-{
- struct uart_state *state = (struct uart_state *)data;
- tty_wakeup(state->port.tty);
-}
-
-static inline void
-uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
-{
- unsigned long flags;
- unsigned int old;
-
- spin_lock_irqsave(&port->lock, flags);
- old = port->mctrl;
- port->mctrl = (old & ~clear) | set;
- if (old != port->mctrl)
- port->ops->set_mctrl(port, port->mctrl);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-#define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0)
-#define uart_clear_mctrl(port, clear) uart_update_mctrl(port, 0, clear)
-
-/*
- * Startup the port. This will be called once per open. All calls
- * will be serialised by the per-port mutex.
- */
-static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw)
-{
- struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
- unsigned long page;
- int retval = 0;
-
- if (port->flags & ASYNC_INITIALIZED)
- return 0;
-
- /*
- * Set the TTY IO error marker - we will only clear this
- * once we have successfully opened the port. Also set
- * up the tty->alt_speed kludge
- */
- set_bit(TTY_IO_ERROR, &tty->flags);
-
- if (uport->type == PORT_UNKNOWN)
- return 0;
-
- /*
- * Initialise and allocate the transmit and temporary
- * buffer.
- */
- if (!state->xmit.buf) {
- /* This is protected by the per port mutex */
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- state->xmit.buf = (unsigned char *) page;
- uart_circ_clear(&state->xmit);
- }
-
- retval = uport->ops->startup(uport);
- if (retval == 0) {
- if (init_hw) {
- /*
- * Initialise the hardware port settings.
- */
- uart_change_speed(tty, state, NULL);
-
- /*
- * Setup the RTS and DTR signals once the
- * port is open and ready to respond.
- */
- if (tty->termios->c_cflag & CBAUD)
- uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
- }
-
- if (port->flags & ASYNC_CTS_FLOW) {
- spin_lock_irq(&uport->lock);
- if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
- tty->hw_stopped = 1;
- spin_unlock_irq(&uport->lock);
- }
-
- set_bit(ASYNCB_INITIALIZED, &port->flags);
-
- clear_bit(TTY_IO_ERROR, &tty->flags);
- }
-
- if (retval && capable(CAP_SYS_ADMIN))
- retval = 0;
-
- return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on. Calls to
- * uart_shutdown are serialised by the per-port semaphore.
- */
-static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
-{
- struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
-
- /*
- * Set the TTY IO error marker
- */
- if (tty)
- set_bit(TTY_IO_ERROR, &tty->flags);
-
- if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) {
- /*
- * Turn off DTR and RTS early.
- */
- if (!tty || (tty->termios->c_cflag & HUPCL))
- uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
-
- /*
- * clear delta_msr_wait queue to avoid mem leaks: we may free
- * the irq here so the queue might never be woken up. Note
- * that we won't end up waiting on delta_msr_wait again since
- * any outstanding file descriptors should be pointing at
- * hung_up_tty_fops now.
- */
- wake_up_interruptible(&port->delta_msr_wait);
-
- /*
- * Free the IRQ and disable the port.
- */
- uport->ops->shutdown(uport);
-
- /*
- * Ensure that the IRQ handler isn't running on another CPU.
- */
- synchronize_irq(uport->irq);
- }
-
- /*
- * kill off our tasklet
- */
- tasklet_kill(&state->tlet);
-
- /*
- * Free the transmit buffer page.
- */
- if (state->xmit.buf) {
- free_page((unsigned long)state->xmit.buf);
- state->xmit.buf = NULL;
- }
-}
-
-/**
- * uart_update_timeout - update per-port FIFO timeout.
- * @port: uart_port structure describing the port
- * @cflag: termios cflag value
- * @baud: speed of the port
- *
- * Set the port FIFO timeout value. The @cflag value should
- * reflect the actual hardware settings.
- */
-void
-uart_update_timeout(struct uart_port *port, unsigned int cflag,
- unsigned int baud)
-{
- unsigned int bits;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5:
- bits = 7;
- break;
- case CS6:
- bits = 8;
- break;
- case CS7:
- bits = 9;
- break;
- default:
- bits = 10;
- break; /* CS8 */
- }
-
- if (cflag & CSTOPB)
- bits++;
- if (cflag & PARENB)
- bits++;
-
- /*
- * The total number of bits to be transmitted in the fifo.
- */
- bits = bits * port->fifosize;
-
- /*
- * Figure the timeout to send the above number of bits.
- * Add .02 seconds of slop
- */
- port->timeout = (HZ * bits) / baud + HZ/50;
-}
-
-EXPORT_SYMBOL(uart_update_timeout);
-
-/**
- * uart_get_baud_rate - return baud rate for a particular port
- * @port: uart_port structure describing the port in question.
- * @termios: desired termios settings.
- * @old: old termios (or NULL)
- * @min: minimum acceptable baud rate
- * @max: maximum acceptable baud rate
- *
- * Decode the termios structure into a numeric baud rate,
- * taking account of the magic 38400 baud rate (with spd_*
- * flags), and mapping the %B0 rate to 9600 baud.
- *
- * If the new baud rate is invalid, try the old termios setting.
- * If it's still invalid, we try 9600 baud.
- *
- * Update the @termios structure to reflect the baud rate
- * we're actually going to be using. Don't do this for the case
- * where B0 is requested ("hang up").
- */
-unsigned int
-uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old, unsigned int min, unsigned int max)
-{
- unsigned int try, baud, altbaud = 38400;
- int hung_up = 0;
- upf_t flags = port->flags & UPF_SPD_MASK;
-
- if (flags == UPF_SPD_HI)
- altbaud = 57600;
- else if (flags == UPF_SPD_VHI)
- altbaud = 115200;
- else if (flags == UPF_SPD_SHI)
- altbaud = 230400;
- else if (flags == UPF_SPD_WARP)
- altbaud = 460800;
-
- for (try = 0; try < 2; try++) {
- baud = tty_termios_baud_rate(termios);
-
- /*
- * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
- * Die! Die! Die!
- */
- if (baud == 38400)
- baud = altbaud;
-
- /*
- * Special case: B0 rate.
- */
- if (baud == 0) {
- hung_up = 1;
- baud = 9600;
- }
-
- if (baud >= min && baud <= max)
- return baud;
-
- /*
- * Oops, the quotient was zero. Try again with
- * the old baud rate if possible.
- */
- termios->c_cflag &= ~CBAUD;
- if (old) {
- baud = tty_termios_baud_rate(old);
- if (!hung_up)
- tty_termios_encode_baud_rate(termios,
- baud, baud);
- old = NULL;
- continue;
- }
-
- /*
- * As a last resort, if the range cannot be met then clip to
- * the nearest chip supported rate.
- */
- if (!hung_up) {
- if (baud <= min)
- tty_termios_encode_baud_rate(termios,
- min + 1, min + 1);
- else
- tty_termios_encode_baud_rate(termios,
- max - 1, max - 1);
- }
- }
- /* Should never happen */
- WARN_ON(1);
- return 0;
-}
-
-EXPORT_SYMBOL(uart_get_baud_rate);
-
-/**
- * uart_get_divisor - return uart clock divisor
- * @port: uart_port structure describing the port.
- * @baud: desired baud rate
- *
- * Calculate the uart clock divisor for the port.
- */
-unsigned int
-uart_get_divisor(struct uart_port *port, unsigned int baud)
-{
- unsigned int quot;
-
- /*
- * Old custom speed handling.
- */
- if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
- quot = port->custom_divisor;
- else
- quot = (port->uartclk + (8 * baud)) / (16 * baud);
-
- return quot;
-}
-
-EXPORT_SYMBOL(uart_get_divisor);
-
-/* FIXME: Consistent locking policy */
-static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
- struct ktermios *old_termios)
-{
- struct tty_port *port = &state->port;
- struct uart_port *uport = state->uart_port;
- struct ktermios *termios;
-
- /*
- * If we have no tty, termios, or the port does not exist,
- * then we can't set the parameters for this port.
- */
- if (!tty || !tty->termios || uport->type == PORT_UNKNOWN)
- return;
-
- termios = tty->termios;
-
- /*
- * Set flags based on termios cflag
- */
- if (termios->c_cflag & CRTSCTS)
- set_bit(ASYNCB_CTS_FLOW, &port->flags);
- else
- clear_bit(ASYNCB_CTS_FLOW, &port->flags);
-
- if (termios->c_cflag & CLOCAL)
- clear_bit(ASYNCB_CHECK_CD, &port->flags);
- else
- set_bit(ASYNCB_CHECK_CD, &port->flags);
-
- uport->ops->set_termios(uport, termios, old_termios);
-}
-
-static inline int __uart_put_char(struct uart_port *port,
- struct circ_buf *circ, unsigned char c)
-{
- unsigned long flags;
- int ret = 0;
-
- if (!circ->buf)
- return 0;
-
- spin_lock_irqsave(&port->lock, flags);
- if (uart_circ_chars_free(circ) != 0) {
- circ->buf[circ->head] = c;
- circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
- ret = 1;
- }
- spin_unlock_irqrestore(&port->lock, flags);
- return ret;
-}
-
-static int uart_put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct uart_state *state = tty->driver_data;
-
- return __uart_put_char(state->uart_port, &state->xmit, ch);
-}
-
-static void uart_flush_chars(struct tty_struct *tty)
-{
- uart_start(tty);
-}
-
-static int uart_write(struct tty_struct *tty,
- const unsigned char *buf, int count)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port;
- struct circ_buf *circ;
- unsigned long flags;
- int c, ret = 0;
-
- /*
- * This means you called this function _after_ the port was
- * closed. No cookie for you.
- */
- if (!state) {
- WARN_ON(1);
- return -EL3HLT;
- }
-
- port = state->uart_port;
- circ = &state->xmit;
-
- if (!circ->buf)
- return 0;
-
- spin_lock_irqsave(&port->lock, flags);
- while (1) {
- c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0)
- break;
- memcpy(circ->buf + circ->head, buf, c);
- circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
- buf += c;
- count -= c;
- ret += c;
- }
- spin_unlock_irqrestore(&port->lock, flags);
-
- uart_start(tty);
- return ret;
-}
-
-static int uart_write_room(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&state->uart_port->lock, flags);
- ret = uart_circ_chars_free(&state->xmit);
- spin_unlock_irqrestore(&state->uart_port->lock, flags);
- return ret;
-}
-
-static int uart_chars_in_buffer(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&state->uart_port->lock, flags);
- ret = uart_circ_chars_pending(&state->xmit);
- spin_unlock_irqrestore(&state->uart_port->lock, flags);
- return ret;
-}
-
-static void uart_flush_buffer(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port;
- unsigned long flags;
-
- /*
- * This means you called this function _after_ the port was
- * closed. No cookie for you.
- */
- if (!state) {
- WARN_ON(1);
- return;
- }
-
- port = state->uart_port;
- pr_debug("uart_flush_buffer(%d) called\n", tty->index);
-
- spin_lock_irqsave(&port->lock, flags);
- uart_circ_clear(&state->xmit);
- if (port->ops->flush_buffer)
- port->ops->flush_buffer(port);
- spin_unlock_irqrestore(&port->lock, flags);
- tty_wakeup(tty);
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void uart_send_xchar(struct tty_struct *tty, char ch)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
- unsigned long flags;
-
- if (port->ops->send_xchar)
- port->ops->send_xchar(port, ch);
- else {
- port->x_char = ch;
- if (ch) {
- spin_lock_irqsave(&port->lock, flags);
- port->ops->start_tx(port);
- spin_unlock_irqrestore(&port->lock, flags);
- }
- }
-}
-
-static void uart_throttle(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
-
- if (I_IXOFF(tty))
- uart_send_xchar(tty, STOP_CHAR(tty));
-
- if (tty->termios->c_cflag & CRTSCTS)
- uart_clear_mctrl(state->uart_port, TIOCM_RTS);
-}
-
-static void uart_unthrottle(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
-
- if (I_IXOFF(tty)) {
- if (port->x_char)
- port->x_char = 0;
- else
- uart_send_xchar(tty, START_CHAR(tty));
- }
-
- if (tty->termios->c_cflag & CRTSCTS)
- uart_set_mctrl(port, TIOCM_RTS);
-}
-
-static int uart_get_info(struct uart_state *state,
- struct serial_struct __user *retinfo)
-{
- struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
- struct serial_struct tmp;
-
- memset(&tmp, 0, sizeof(tmp));
-
- /* Ensure the state we copy is consistent and no hardware changes
- occur as we go */
- mutex_lock(&port->mutex);
-
- tmp.type = uport->type;
- tmp.line = uport->line;
- tmp.port = uport->iobase;
- if (HIGH_BITS_OFFSET)
- tmp.port_high = (long) uport->iobase >> HIGH_BITS_OFFSET;
- tmp.irq = uport->irq;
- tmp.flags = uport->flags;
- tmp.xmit_fifo_size = uport->fifosize;
- tmp.baud_base = uport->uartclk / 16;
- tmp.close_delay = port->close_delay / 10;
- tmp.closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
- ASYNC_CLOSING_WAIT_NONE :
- port->closing_wait / 10;
- tmp.custom_divisor = uport->custom_divisor;
- tmp.hub6 = uport->hub6;
- tmp.io_type = uport->iotype;
- tmp.iomem_reg_shift = uport->regshift;
- tmp.iomem_base = (void *)(unsigned long)uport->mapbase;
-
- mutex_unlock(&port->mutex);
-
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
- return 0;
-}
-
-static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
- struct serial_struct __user *newinfo)
-{
- struct serial_struct new_serial;
- struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
- unsigned long new_port;
- unsigned int change_irq, change_port, closing_wait;
- unsigned int old_custom_divisor, close_delay;
- upf_t old_flags, new_flags;
- int retval = 0;
-
- if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
- return -EFAULT;
-
- new_port = new_serial.port;
- if (HIGH_BITS_OFFSET)
- new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
-
- new_serial.irq = irq_canonicalize(new_serial.irq);
- close_delay = new_serial.close_delay * 10;
- closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
- ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
-
- /*
- * This semaphore protects port->count. It is also
- * very useful to prevent opens. Also, take the
- * port configuration semaphore to make sure that a
- * module insertion/removal doesn't change anything
- * under us.
- */
- mutex_lock(&port->mutex);
-
- change_irq = !(uport->flags & UPF_FIXED_PORT)
- && new_serial.irq != uport->irq;
-
- /*
- * Since changing the 'type' of the port changes its resource
- * allocations, we should treat type changes the same as
- * IO port changes.
- */
- change_port = !(uport->flags & UPF_FIXED_PORT)
- && (new_port != uport->iobase ||
- (unsigned long)new_serial.iomem_base != uport->mapbase ||
- new_serial.hub6 != uport->hub6 ||
- new_serial.io_type != uport->iotype ||
- new_serial.iomem_reg_shift != uport->regshift ||
- new_serial.type != uport->type);
-
- old_flags = uport->flags;
- new_flags = new_serial.flags;
- old_custom_divisor = uport->custom_divisor;
-
- if (!capable(CAP_SYS_ADMIN)) {
- retval = -EPERM;
- if (change_irq || change_port ||
- (new_serial.baud_base != uport->uartclk / 16) ||
- (close_delay != port->close_delay) ||
- (closing_wait != port->closing_wait) ||
- (new_serial.xmit_fifo_size &&
- new_serial.xmit_fifo_size != uport->fifosize) ||
- (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
- goto exit;
- uport->flags = ((uport->flags & ~UPF_USR_MASK) |
- (new_flags & UPF_USR_MASK));
- uport->custom_divisor = new_serial.custom_divisor;
- goto check_and_exit;
- }
-
- /*
- * Ask the low level driver to verify the settings.
- */
- if (uport->ops->verify_port)
- retval = uport->ops->verify_port(uport, &new_serial);
-
- if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
- (new_serial.baud_base < 9600))
- retval = -EINVAL;
-
- if (retval)
- goto exit;
-
- if (change_port || change_irq) {
- retval = -EBUSY;
-
- /*
- * Make sure that we are the sole user of this port.
- */
- if (tty_port_users(port) > 1)
- goto exit;
-
- /*
- * We need to shutdown the serial port at the old
- * port/type/irq combination.
- */
- uart_shutdown(tty, state);
- }
-
- if (change_port) {
- unsigned long old_iobase, old_mapbase;
- unsigned int old_type, old_iotype, old_hub6, old_shift;
-
- old_iobase = uport->iobase;
- old_mapbase = uport->mapbase;
- old_type = uport->type;
- old_hub6 = uport->hub6;
- old_iotype = uport->iotype;
- old_shift = uport->regshift;
-
- /*
- * Free and release old regions
- */
- if (old_type != PORT_UNKNOWN)
- uport->ops->release_port(uport);
-
- uport->iobase = new_port;
- uport->type = new_serial.type;
- uport->hub6 = new_serial.hub6;
- uport->iotype = new_serial.io_type;
- uport->regshift = new_serial.iomem_reg_shift;
- uport->mapbase = (unsigned long)new_serial.iomem_base;
-
- /*
- * Claim and map the new regions
- */
- if (uport->type != PORT_UNKNOWN) {
- retval = uport->ops->request_port(uport);
- } else {
- /* Always success - Jean II */
- retval = 0;
- }
-
- /*
- * If we fail to request resources for the
- * new port, try to restore the old settings.
- */
- if (retval && old_type != PORT_UNKNOWN) {
- uport->iobase = old_iobase;
- uport->type = old_type;
- uport->hub6 = old_hub6;
- uport->iotype = old_iotype;
- uport->regshift = old_shift;
- uport->mapbase = old_mapbase;
- retval = uport->ops->request_port(uport);
- /*
- * If we failed to restore the old settings,
- * we fail like this.
- */
- if (retval)
- uport->type = PORT_UNKNOWN;
-
- /*
- * We failed anyway.
- */
- retval = -EBUSY;
- /* Added to return the correct error -Ram Gupta */
- goto exit;
- }
- }
-
- if (change_irq)
- uport->irq = new_serial.irq;
- if (!(uport->flags & UPF_FIXED_PORT))
- uport->uartclk = new_serial.baud_base * 16;
- uport->flags = (uport->flags & ~UPF_CHANGE_MASK) |
- (new_flags & UPF_CHANGE_MASK);
- uport->custom_divisor = new_serial.custom_divisor;
- port->close_delay = close_delay;
- port->closing_wait = closing_wait;
- if (new_serial.xmit_fifo_size)
- uport->fifosize = new_serial.xmit_fifo_size;
- if (port->tty)
- port->tty->low_latency =
- (uport->flags & UPF_LOW_LATENCY) ? 1 : 0;
-
- check_and_exit:
- retval = 0;
- if (uport->type == PORT_UNKNOWN)
- goto exit;
- if (port->flags & ASYNC_INITIALIZED) {
- if (((old_flags ^ uport->flags) & UPF_SPD_MASK) ||
- old_custom_divisor != uport->custom_divisor) {
- /*
- * If they're setting up a custom divisor or speed,
- * instead of clearing it, then bitch about it. No
- * need to rate-limit; it's CAP_SYS_ADMIN only.
- */
- if (uport->flags & UPF_SPD_MASK) {
- char buf[64];
- printk(KERN_NOTICE
- "%s sets custom speed on %s. This "
- "is deprecated.\n", current->comm,
- tty_name(port->tty, buf));
- }
- uart_change_speed(tty, state, NULL);
- }
- } else
- retval = uart_startup(tty, state, 1);
- exit:
- mutex_unlock(&port->mutex);
- return retval;
-}
-
-/**
- * uart_get_lsr_info - get line status register info
- * @tty: tty associated with the UART
- * @state: UART being queried
- * @value: returned modem value
- *
- * Note: uart_ioctl protects us against hangups.
- */
-static int uart_get_lsr_info(struct tty_struct *tty,
- struct uart_state *state, unsigned int __user *value)
-{
- struct uart_port *uport = state->uart_port;
- unsigned int result;
-
- result = uport->ops->tx_empty(uport);
-
- /*
- * If we're about to load something into the transmit
- * register, we'll pretend the transmitter isn't empty to
- * avoid a race condition (depending on when the transmit
- * interrupt happens).
- */
- if (uport->x_char ||
- ((uart_circ_chars_pending(&state->xmit) > 0) &&
- !tty->stopped && !tty->hw_stopped))
- result &= ~TIOCSER_TEMT;
-
- return put_user(result, value);
-}
-
-static int uart_tiocmget(struct tty_struct *tty, struct file *file)
-{
- struct uart_state *state = tty->driver_data;
- struct tty_port *port = &state->port;
- struct uart_port *uport = state->uart_port;
- int result = -EIO;
-
- mutex_lock(&port->mutex);
- if ((!file || !tty_hung_up_p(file)) &&
- !(tty->flags & (1 << TTY_IO_ERROR))) {
- result = uport->mctrl;
-
- spin_lock_irq(&uport->lock);
- result |= uport->ops->get_mctrl(uport);
- spin_unlock_irq(&uport->lock);
- }
- mutex_unlock(&port->mutex);
-
- return result;
-}
-
-static int
-uart_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
- int ret = -EIO;
-
- mutex_lock(&port->mutex);
- if ((!file || !tty_hung_up_p(file)) &&
- !(tty->flags & (1 << TTY_IO_ERROR))) {
- uart_update_mctrl(uport, set, clear);
- ret = 0;
- }
- mutex_unlock(&port->mutex);
- return ret;
-}
-
-static int uart_break_ctl(struct tty_struct *tty, int break_state)
-{
- struct uart_state *state = tty->driver_data;
- struct tty_port *port = &state->port;
- struct uart_port *uport = state->uart_port;
-
- mutex_lock(&port->mutex);
-
- if (uport->type != PORT_UNKNOWN)
- uport->ops->break_ctl(uport, break_state);
-
- mutex_unlock(&port->mutex);
- return 0;
-}
-
-static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
-{
- struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
- int flags, ret;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- /*
- * Take the per-port semaphore. This prevents count from
- * changing, and hence any extra opens of the port while
- * we're auto-configuring.
- */
- if (mutex_lock_interruptible(&port->mutex))
- return -ERESTARTSYS;
-
- ret = -EBUSY;
- if (tty_port_users(port) == 1) {
- uart_shutdown(tty, state);
-
- /*
- * If we already have a port type configured,
- * we must release its resources.
- */
- if (uport->type != PORT_UNKNOWN)
- uport->ops->release_port(uport);
-
- flags = UART_CONFIG_TYPE;
- if (uport->flags & UPF_AUTO_IRQ)
- flags |= UART_CONFIG_IRQ;
-
- /*
- * This will claim the ports resources if
- * a port is found.
- */
- uport->ops->config_port(uport, flags);
-
- ret = uart_startup(tty, state, 1);
- }
- mutex_unlock(&port->mutex);
- return ret;
-}
-
-/*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- *
- * FIXME: This wants extracting into a common all driver implementation
- * of TIOCMWAIT using tty_port.
- */
-static int
-uart_wait_modem_status(struct uart_state *state, unsigned long arg)
-{
- struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
- DECLARE_WAITQUEUE(wait, current);
- struct uart_icount cprev, cnow;
- int ret;
-
- /*
- * note the counters on entry
- */
- spin_lock_irq(&uport->lock);
- memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
-
- /*
- * Force modem status interrupts on
- */
- uport->ops->enable_ms(uport);
- spin_unlock_irq(&uport->lock);
-
- add_wait_queue(&port->delta_msr_wait, &wait);
- for (;;) {
- spin_lock_irq(&uport->lock);
- memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
- spin_unlock_irq(&uport->lock);
-
- set_current_state(TASK_INTERRUPTIBLE);
-
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- ret = 0;
- break;
- }
-
- schedule();
-
- /* see if a signal did it */
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
-
- cprev = cnow;
- }
-
- current->state = TASK_RUNNING;
- remove_wait_queue(&port->delta_msr_wait, &wait);
-
- return ret;
-}
-
-/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
-static int uart_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_icount cnow;
- struct uart_port *uport = state->uart_port;
-
- spin_lock_irq(&uport->lock);
- memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
- spin_unlock_irq(&uport->lock);
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- return 0;
-}
-
-/*
- * Called via sys_ioctl. We can use spin_lock_irq() here.
- */
-static int
-uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- struct uart_state *state = tty->driver_data;
- struct tty_port *port = &state->port;
- void __user *uarg = (void __user *)arg;
- int ret = -ENOIOCTLCMD;
-
-
- /*
- * These ioctls don't rely on the hardware to be present.
- */
- switch (cmd) {
- case TIOCGSERIAL:
- ret = uart_get_info(state, uarg);
- break;
-
- case TIOCSSERIAL:
- ret = uart_set_info(tty, state, uarg);
- break;
-
- case TIOCSERCONFIG:
- ret = uart_do_autoconfig(tty, state);
- break;
-
- case TIOCSERGWILD: /* obsolete */
- case TIOCSERSWILD: /* obsolete */
- ret = 0;
- break;
- }
-
- if (ret != -ENOIOCTLCMD)
- goto out;
-
- if (tty->flags & (1 << TTY_IO_ERROR)) {
- ret = -EIO;
- goto out;
- }
-
- /*
- * The following should only be used when hardware is present.
- */
- switch (cmd) {
- case TIOCMIWAIT:
- ret = uart_wait_modem_status(state, arg);
- break;
- }
-
- if (ret != -ENOIOCTLCMD)
- goto out;
-
- mutex_lock(&port->mutex);
-
- if (tty_hung_up_p(filp)) {
- ret = -EIO;
- goto out_up;
- }
-
- /*
- * All these rely on hardware being present and need to be
- * protected against the tty being hung up.
- */
- switch (cmd) {
- case TIOCSERGETLSR: /* Get line status register */
- ret = uart_get_lsr_info(tty, state, uarg);
- break;
-
- default: {
- struct uart_port *uport = state->uart_port;
- if (uport->ops->ioctl)
- ret = uport->ops->ioctl(uport, cmd, arg);
- break;
- }
- }
-out_up:
- mutex_unlock(&port->mutex);
-out:
- return ret;
-}
-
-static void uart_set_ldisc(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *uport = state->uart_port;
-
- if (uport->ops->set_ldisc)
- uport->ops->set_ldisc(uport, tty->termios->c_line);
-}
-
-static void uart_set_termios(struct tty_struct *tty,
- struct ktermios *old_termios)
-{
- struct uart_state *state = tty->driver_data;
- unsigned long flags;
- unsigned int cflag = tty->termios->c_cflag;
-
-
- /*
- * These are the bits that are used to setup various
- * flags in the low level driver. We can ignore the Bfoo
- * bits in c_cflag; c_[io]speed will always be set
- * appropriately by set_termios() in tty_ioctl.c
- */
-#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
- if ((cflag ^ old_termios->c_cflag) == 0 &&
- tty->termios->c_ospeed == old_termios->c_ospeed &&
- tty->termios->c_ispeed == old_termios->c_ispeed &&
- RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) {
- return;
- }
-
- uart_change_speed(tty, state, old_termios);
-
- /* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
- uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
- /* Handle transition away from B0 status */
- else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
- unsigned int mask = TIOCM_DTR;
- if (!(cflag & CRTSCTS) ||
- !test_bit(TTY_THROTTLED, &tty->flags))
- mask |= TIOCM_RTS;
- uart_set_mctrl(state->uart_port, mask);
- }
-
- /* Handle turning off CRTSCTS */
- if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
- spin_lock_irqsave(&state->uart_port->lock, flags);
- tty->hw_stopped = 0;
- __uart_start(tty);
- spin_unlock_irqrestore(&state->uart_port->lock, flags);
- }
- /* Handle turning on CRTSCTS */
- else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
- spin_lock_irqsave(&state->uart_port->lock, flags);
- if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
- tty->hw_stopped = 1;
- state->uart_port->ops->stop_tx(state->uart_port);
- }
- 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
-}
-
-/*
- * In 2.4.5, calls to this will be serialized via the BKL in
- * linux/drivers/char/tty_io.c:tty_release()
- * linux/drivers/char/tty_io.c:do_tty_handup()
- */
-static void uart_close(struct tty_struct *tty, struct file *filp)
-{
- struct uart_state *state = tty->driver_data;
- struct tty_port *port;
- struct uart_port *uport;
- unsigned long flags;
-
- BUG_ON(!tty_locked());
-
- if (!state)
- return;
-
- uport = state->uart_port;
- port = &state->port;
-
- pr_debug("uart_close(%d) called\n", uport->line);
-
- mutex_lock(&port->mutex);
- spin_lock_irqsave(&port->lock, flags);
-
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&port->lock, flags);
- goto done;
- }
-
- if ((tty->count == 1) && (port->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. port->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, "
- "port->count is %d\n", port->count);
- port->count = 1;
- }
- if (--port->count < 0) {
- printk(KERN_ERR "uart_close: bad serial port count for %s: %d\n",
- tty->name, port->count);
- port->count = 0;
- }
- if (port->count) {
- spin_unlock_irqrestore(&port->lock, flags);
- goto done;
- }
-
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters by
- * setting tty->closing.
- */
- tty->closing = 1;
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
- /*
- * hack: open-coded tty_wait_until_sent to avoid
- * recursive tty_lock
- */
- long timeout = msecs_to_jiffies(port->closing_wait);
- if (wait_event_interruptible_timeout(tty->write_wait,
- !tty_chars_in_buffer(tty), timeout) >= 0)
- __uart_wait_until_sent(uport, timeout);
- }
-
- /*
- * At this point, we stop accepting input. To do this, we
- * disable the receive line status interrupts.
- */
- if (port->flags & ASYNC_INITIALIZED) {
- unsigned long flags;
- spin_lock_irqsave(&uport->lock, flags);
- uport->ops->stop_rx(uport);
- spin_unlock_irqrestore(&uport->lock, flags);
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- __uart_wait_until_sent(uport, uport->timeout);
- }
-
- uart_shutdown(tty, state);
- uart_flush_buffer(tty);
-
- tty_ldisc_flush(tty);
-
- tty_port_tty_set(port, NULL);
- spin_lock_irqsave(&port->lock, flags);
- tty->closing = 0;
-
- if (port->blocked_open) {
- spin_unlock_irqrestore(&port->lock, flags);
- if (port->close_delay)
- msleep_interruptible(port->close_delay);
- spin_lock_irqsave(&port->lock, flags);
- } else if (!uart_console(uport)) {
- spin_unlock_irqrestore(&port->lock, flags);
- uart_change_pm(state, 3);
- spin_lock_irqsave(&port->lock, flags);
- }
-
- /*
- * Wake up anyone trying to open this port.
- */
- clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
- spin_unlock_irqrestore(&port->lock, flags);
- wake_up_interruptible(&port->open_wait);
-
-done:
- mutex_unlock(&port->mutex);
-}
-
-static void __uart_wait_until_sent(struct uart_port *port, int timeout)
-{
- unsigned long char_time, expire;
-
- if (port->type == PORT_UNKNOWN || port->fifosize == 0)
- return;
-
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = (port->timeout - HZ/50) / port->fifosize;
- char_time = char_time / 5;
- if (char_time == 0)
- char_time = 1;
- if (timeout && timeout < char_time)
- char_time = timeout;
-
- /*
- * If the transmitter hasn't cleared in twice the approximate
- * amount of time to send the entire FIFO, it probably won't
- * ever clear. This assumes the UART isn't doing flow
- * control, which is currently the case. Hence, if it ever
- * takes longer than port->timeout, this is probably due to a
- * UART bug of some kind. So, we clamp the timeout parameter at
- * 2*port->timeout.
- */
- if (timeout == 0 || timeout > 2 * port->timeout)
- timeout = 2 * port->timeout;
-
- expire = jiffies + timeout;
-
- pr_debug("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
- port->line, jiffies, expire);
-
- /*
- * Check whether the transmitter is empty every 'char_time'.
- * 'timeout' / 'expire' give us the maximum amount of time
- * we wait.
- */
- while (!port->ops->tx_empty(port)) {
- msleep_interruptible(jiffies_to_msecs(char_time));
- if (signal_pending(current))
- break;
- 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)
-{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
-
- tty_lock();
- __uart_wait_until_sent(port, timeout);
- tty_unlock();
-}
-
-/*
- * This is called with the BKL held in
- * linux/drivers/char/tty_io.c:do_tty_hangup()
- * We're called from the eventd thread, so we can sleep for
- * a _short_ time only.
- */
-static void uart_hangup(struct tty_struct *tty)
-{
- struct uart_state *state = tty->driver_data;
- struct tty_port *port = &state->port;
- unsigned long flags;
-
- BUG_ON(!tty_locked());
- pr_debug("uart_hangup(%d)\n", state->uart_port->line);
-
- mutex_lock(&port->mutex);
- if (port->flags & ASYNC_NORMAL_ACTIVE) {
- uart_flush_buffer(tty);
- uart_shutdown(tty, state);
- spin_lock_irqsave(&port->lock, flags);
- port->count = 0;
- clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
- spin_unlock_irqrestore(&port->lock, flags);
- tty_port_tty_set(port, NULL);
- wake_up_interruptible(&port->open_wait);
- wake_up_interruptible(&port->delta_msr_wait);
- }
- 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);
- struct uart_port *uport = state->uart_port;
- int mctrl;
- spin_lock_irq(&uport->lock);
- uport->ops->enable_ms(uport);
- mctrl = uport->ops->get_mctrl(uport);
- spin_unlock_irq(&uport->lock);
- if (mctrl & TIOCM_CAR)
- return 1;
- return 0;
-}
-
-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) {
- 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);
-}
-
-static struct uart_state *uart_get(struct uart_driver *drv, int line)
-{
- struct uart_state *state;
- struct tty_port *port;
- int ret = 0;
-
- state = drv->state + line;
- port = &state->port;
- if (mutex_lock_interruptible(&port->mutex)) {
- ret = -ERESTARTSYS;
- goto err;
- }
-
- port->count++;
- if (!state->uart_port || state->uart_port->flags & UPF_DEAD) {
- ret = -ENXIO;
- goto err_unlock;
- }
- return state;
-
- err_unlock:
- port->count--;
- mutex_unlock(&port->mutex);
- err:
- return ERR_PTR(ret);
-}
-
-/*
- * calls to uart_open are serialised by the BKL in
- * fs/char_dev.c:chrdev_open()
- * Note that if this fails, then uart_close() _will_ be called.
- *
- * In time, we want to scrap the "opening nonpresent ports"
- * behaviour and implement an alternative way for setserial
- * to set base addresses/ports/types. This will allow us to
- * get rid of a certain amount of extra tests.
- */
-static int uart_open(struct tty_struct *tty, struct file *filp)
-{
- struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;
- struct uart_state *state;
- struct tty_port *port;
- int retval, line = tty->index;
-
- BUG_ON(!tty_locked());
- 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
- * side-effect that it delays the action of uart_hangup, so we can
- * guarantee that state->port.tty will always contain something
- * reasonable.
- */
- state = uart_get(drv, line);
- if (IS_ERR(state)) {
- retval = PTR_ERR(state);
- goto fail;
- }
- port = &state->port;
-
- /*
- * Once we set tty->driver_data here, we are guaranteed that
- * uart_close() will decrement the driver module use count.
- * Any failures from here onwards should not touch the count.
- */
- tty->driver_data = state;
- state->uart_port->state = state;
- tty->low_latency = (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
- tty->alt_speed = 0;
- tty_port_tty_set(port, tty);
-
- /*
- * If the port is in the middle of closing, bail out now.
- */
- if (tty_hung_up_p(filp)) {
- retval = -EAGAIN;
- port->count--;
- mutex_unlock(&port->mutex);
- goto fail;
- }
-
- /*
- * Make sure the device is in D0 state.
- */
- if (port->count == 1)
- uart_change_pm(state, 0);
-
- /*
- * Start up the serial port.
- */
- retval = uart_startup(tty, state, 0);
-
- /*
- * If we succeeded, wait until the port is ready.
- */
- mutex_unlock(&port->mutex);
- if (retval == 0)
- retval = tty_port_block_til_ready(port, tty, filp);
-
-fail:
- return retval;
-}
-
-static const char *uart_type(struct uart_port *port)
-{
- const char *str = NULL;
-
- if (port->ops->type)
- str = port->ops->type(port);
-
- if (!str)
- str = "unknown";
-
- return str;
-}
-
-#ifdef CONFIG_PROC_FS
-
-static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
-{
- struct uart_state *state = drv->state + i;
- struct tty_port *port = &state->port;
- int pm_state;
- struct uart_port *uport = state->uart_port;
- char stat_buf[32];
- unsigned int status;
- int mmio;
-
- if (!uport)
- return;
-
- mmio = uport->iotype >= UPIO_MEM;
- seq_printf(m, "%d: uart:%s %s%08llX irq:%d",
- uport->line, uart_type(uport),
- mmio ? "mmio:0x" : "port:",
- mmio ? (unsigned long long)uport->mapbase
- : (unsigned long long)uport->iobase,
- uport->irq);
-
- if (uport->type == PORT_UNKNOWN) {
- seq_putc(m, '\n');
- return;
- }
-
- if (capable(CAP_SYS_ADMIN)) {
- mutex_lock(&port->mutex);
- pm_state = state->pm_state;
- if (pm_state)
- uart_change_pm(state, 0);
- spin_lock_irq(&uport->lock);
- status = uport->ops->get_mctrl(uport);
- spin_unlock_irq(&uport->lock);
- if (pm_state)
- uart_change_pm(state, pm_state);
- mutex_unlock(&port->mutex);
-
- seq_printf(m, " tx:%d rx:%d",
- uport->icount.tx, uport->icount.rx);
- if (uport->icount.frame)
- seq_printf(m, " fe:%d",
- uport->icount.frame);
- if (uport->icount.parity)
- seq_printf(m, " pe:%d",
- uport->icount.parity);
- if (uport->icount.brk)
- seq_printf(m, " brk:%d",
- uport->icount.brk);
- if (uport->icount.overrun)
- seq_printf(m, " oe:%d",
- uport->icount.overrun);
-
-#define INFOBIT(bit, str) \
- if (uport->mctrl & (bit)) \
- strncat(stat_buf, (str), sizeof(stat_buf) - \
- strlen(stat_buf) - 2)
-#define STATBIT(bit, str) \
- if (status & (bit)) \
- strncat(stat_buf, (str), sizeof(stat_buf) - \
- strlen(stat_buf) - 2)
-
- stat_buf[0] = '\0';
- stat_buf[1] = '\0';
- INFOBIT(TIOCM_RTS, "|RTS");
- STATBIT(TIOCM_CTS, "|CTS");
- INFOBIT(TIOCM_DTR, "|DTR");
- STATBIT(TIOCM_DSR, "|DSR");
- STATBIT(TIOCM_CAR, "|CD");
- STATBIT(TIOCM_RNG, "|RI");
- if (stat_buf[0])
- stat_buf[0] = ' ';
-
- seq_puts(m, stat_buf);
- }
- seq_putc(m, '\n');
-#undef STATBIT
-#undef INFOBIT
-}
-
-static int uart_proc_show(struct seq_file *m, void *v)
-{
- struct tty_driver *ttydrv = m->private;
- struct uart_driver *drv = ttydrv->driver_state;
- int i;
-
- seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n",
- "", "", "");
- for (i = 0; i < drv->nr; i++)
- uart_line_info(m, drv, i);
- return 0;
-}
-
-static int uart_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, uart_proc_show, PDE(inode)->data);
-}
-
-static const struct file_operations uart_proc_fops = {
- .owner = THIS_MODULE,
- .open = uart_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
-/*
- * uart_console_write - write a console message to a serial port
- * @port: the port to write the message
- * @s: array of characters
- * @count: number of characters in string to write
- * @write: function to write character to port
- */
-void uart_console_write(struct uart_port *port, const char *s,
- unsigned int count,
- void (*putchar)(struct uart_port *, int))
-{
- unsigned int i;
-
- for (i = 0; i < count; i++, s++) {
- if (*s == '\n')
- putchar(port, '\r');
- putchar(port, *s);
- }
-}
-EXPORT_SYMBOL_GPL(uart_console_write);
-
-/*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
-struct uart_port * __init
-uart_get_console(struct uart_port *ports, int nr, struct console *co)
-{
- int idx = co->index;
-
- if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 &&
- ports[idx].membase == NULL))
- for (idx = 0; idx < nr; idx++)
- if (ports[idx].iobase != 0 ||
- ports[idx].membase != NULL)
- break;
-
- co->index = idx;
-
- return ports + idx;
-}
-
-/**
- * uart_parse_options - Parse serial port baud/parity/bits/flow contro.
- * @options: pointer to option string
- * @baud: pointer to an 'int' variable for the baud rate.
- * @parity: pointer to an 'int' variable for the parity.
- * @bits: pointer to an 'int' variable for the number of data bits.
- * @flow: pointer to an 'int' variable for the flow control character.
- *
- * uart_parse_options decodes a string containing the serial console
- * options. The format of the string is <baud><parity><bits><flow>,
- * eg: 115200n8r
- */
-void
-uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
-{
- char *s = options;
-
- *baud = simple_strtoul(s, NULL, 10);
- while (*s >= '0' && *s <= '9')
- s++;
- if (*s)
- *parity = *s++;
- if (*s)
- *bits = *s++ - '0';
- if (*s)
- *flow = *s;
-}
-EXPORT_SYMBOL_GPL(uart_parse_options);
-
-struct baud_rates {
- unsigned int rate;
- unsigned int cflag;
-};
-
-static const struct baud_rates baud_rates[] = {
- { 921600, B921600 },
- { 460800, B460800 },
- { 230400, B230400 },
- { 115200, B115200 },
- { 57600, B57600 },
- { 38400, B38400 },
- { 19200, B19200 },
- { 9600, B9600 },
- { 4800, B4800 },
- { 2400, B2400 },
- { 1200, B1200 },
- { 0, B38400 }
-};
-
-/**
- * uart_set_options - setup the serial console parameters
- * @port: pointer to the serial ports uart_port structure
- * @co: console pointer
- * @baud: baud rate
- * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
- * @bits: number of data bits
- * @flow: flow control character - 'r' (rts)
- */
-int
-uart_set_options(struct uart_port *port, struct console *co,
- int baud, int parity, int bits, int flow)
-{
- struct ktermios termios;
- static struct ktermios dummy;
- int i;
-
- /*
- * Ensure that the serial console lock is initialised
- * early.
- */
- spin_lock_init(&port->lock);
- lockdep_set_class(&port->lock, &port_lock_key);
-
- memset(&termios, 0, sizeof(struct ktermios));
-
- termios.c_cflag = CREAD | HUPCL | CLOCAL;
-
- /*
- * Construct a cflag setting.
- */
- for (i = 0; baud_rates[i].rate; i++)
- if (baud_rates[i].rate <= baud)
- break;
-
- termios.c_cflag |= baud_rates[i].cflag;
-
- if (bits == 7)
- termios.c_cflag |= CS7;
- else
- termios.c_cflag |= CS8;
-
- switch (parity) {
- case 'o': case 'O':
- termios.c_cflag |= PARODD;
- /*fall through*/
- case 'e': case 'E':
- termios.c_cflag |= PARENB;
- break;
- }
-
- if (flow == 'r')
- termios.c_cflag |= CRTSCTS;
-
- /*
- * some uarts on other side don't support no flow control.
- * So we set * DTR in host uart to make them happy
- */
- port->mctrl |= TIOCM_DTR;
-
- port->ops->set_termios(port, &termios, &dummy);
- /*
- * Allow the setting of the UART parameters with a NULL console
- * too:
- */
- if (co)
- co->cflag = termios.c_cflag;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(uart_set_options);
-#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-
-static void uart_change_pm(struct uart_state *state, int pm_state)
-{
- struct uart_port *port = state->uart_port;
-
- if (state->pm_state != pm_state) {
- if (port->ops->pm)
- port->ops->pm(port, pm_state, state->pm_state);
- state->pm_state = pm_state;
- }
-}
-
-struct uart_match {
- struct uart_port *port;
- struct uart_driver *driver;
-};
-
-static int serial_match_port(struct device *dev, void *data)
-{
- struct uart_match *match = data;
- struct tty_driver *tty_drv = match->driver->tty_driver;
- dev_t devt = MKDEV(tty_drv->major, tty_drv->minor_start) +
- match->port->line;
-
- return dev->devt == devt; /* Actually, only one tty per port */
-}
-
-int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
-{
- struct uart_state *state = drv->state + uport->line;
- 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))
- uport->irq_wake = 1;
- put_device(tty_dev);
- mutex_unlock(&port->mutex);
- return 0;
- }
- if (console_suspend_enabled || !uart_console(uport))
- uport->suspended = 1;
-
- if (port->flags & ASYNC_INITIALIZED) {
- const struct uart_ops *ops = uport->ops;
- int tries;
-
- if (console_suspend_enabled || !uart_console(uport)) {
- set_bit(ASYNCB_SUSPENDED, &port->flags);
- clear_bit(ASYNCB_INITIALIZED, &port->flags);
-
- spin_lock_irq(&uport->lock);
- ops->stop_tx(uport);
- ops->set_mctrl(uport, 0);
- ops->stop_rx(uport);
- spin_unlock_irq(&uport->lock);
- }
-
- /*
- * Wait for the transmitter to empty.
- */
- for (tries = 3; !ops->tx_empty(uport) && tries; tries--)
- msleep(10);
- if (!tries)
- printk(KERN_ERR "%s%s%s%d: Unable to drain "
- "transmitter\n",
- uport->dev ? dev_name(uport->dev) : "",
- uport->dev ? ": " : "",
- drv->dev_name,
- drv->tty_driver->name_base + uport->line);
-
- if (console_suspend_enabled || !uart_console(uport))
- ops->shutdown(uport);
- }
-
- /*
- * Disable the console device before suspending.
- */
- if (console_suspend_enabled && uart_console(uport))
- console_stop(uport->cons);
-
- if (console_suspend_enabled || !uart_console(uport))
- uart_change_pm(state, 3);
-
- mutex_unlock(&port->mutex);
-
- return 0;
-}
-
-int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
-{
- struct uart_state *state = drv->state + uport->line;
- struct tty_port *port = &state->port;
- struct device *tty_dev;
- struct uart_match match = {uport, drv};
- struct ktermios termios;
-
- mutex_lock(&port->mutex);
-
- tty_dev = device_find_child(uport->dev, &match, serial_match_port);
- if (!uport->suspended && device_may_wakeup(tty_dev)) {
- if (uport->irq_wake) {
- disable_irq_wake(uport->irq);
- uport->irq_wake = 0;
- }
- mutex_unlock(&port->mutex);
- return 0;
- }
- uport->suspended = 0;
-
- /*
- * Re-enable the console device after suspending.
- */
- if (console_suspend_enabled && uart_console(uport)) {
- /*
- * First try to use the console cflag setting.
- */
- memset(&termios, 0, sizeof(struct ktermios));
- termios.c_cflag = uport->cons->cflag;
-
- /*
- * If that's unset, use the tty termios setting.
- */
- if (port->tty && port->tty->termios && termios.c_cflag == 0)
- termios = *(port->tty->termios);
-
- uart_change_pm(state, 0);
- uport->ops->set_termios(uport, &termios, NULL);
- console_start(uport->cons);
- }
-
- if (port->flags & ASYNC_SUSPENDED) {
- const struct uart_ops *ops = uport->ops;
- int ret;
-
- uart_change_pm(state, 0);
- spin_lock_irq(&uport->lock);
- ops->set_mctrl(uport, 0);
- spin_unlock_irq(&uport->lock);
- if (console_suspend_enabled || !uart_console(uport)) {
- /* Protected by port mutex for now */
- struct tty_struct *tty = port->tty;
- ret = ops->startup(uport);
- if (ret == 0) {
- if (tty)
- uart_change_speed(tty, state, NULL);
- spin_lock_irq(&uport->lock);
- ops->set_mctrl(uport, uport->mctrl);
- ops->start_tx(uport);
- spin_unlock_irq(&uport->lock);
- set_bit(ASYNCB_INITIALIZED, &port->flags);
- } else {
- /*
- * Failed to resume - maybe hardware went away?
- * Clear the "initialized" flag so we won't try
- * to call the low level drivers shutdown method.
- */
- uart_shutdown(tty, state);
- }
- }
-
- clear_bit(ASYNCB_SUSPENDED, &port->flags);
- }
-
- mutex_unlock(&port->mutex);
-
- return 0;
-}
-
-static inline void
-uart_report_port(struct uart_driver *drv, struct uart_port *port)
-{
- char address[64];
-
- switch (port->iotype) {
- case UPIO_PORT:
- snprintf(address, sizeof(address), "I/O 0x%lx", port->iobase);
- break;
- case UPIO_HUB6:
- snprintf(address, sizeof(address),
- "I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
- break;
- case UPIO_MEM:
- case UPIO_MEM32:
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_DWAPB:
- case UPIO_DWAPB32:
- snprintf(address, sizeof(address),
- "MMIO 0x%llx", (unsigned long long)port->mapbase);
- break;
- default:
- strlcpy(address, "*unknown*", sizeof(address));
- break;
- }
-
- printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
- port->dev ? dev_name(port->dev) : "",
- port->dev ? ": " : "",
- drv->dev_name,
- drv->tty_driver->name_base + port->line,
- address, port->irq, uart_type(port));
-}
-
-static void
-uart_configure_port(struct uart_driver *drv, struct uart_state *state,
- struct uart_port *port)
-{
- unsigned int flags;
-
- /*
- * If there isn't a port here, don't do anything further.
- */
- if (!port->iobase && !port->mapbase && !port->membase)
- return;
-
- /*
- * Now do the auto configuration stuff. Note that config_port
- * is expected to claim the resources and map the port for us.
- */
- flags = 0;
- if (port->flags & UPF_AUTO_IRQ)
- flags |= UART_CONFIG_IRQ;
- if (port->flags & UPF_BOOT_AUTOCONF) {
- if (!(port->flags & UPF_FIXED_TYPE)) {
- port->type = PORT_UNKNOWN;
- flags |= UART_CONFIG_TYPE;
- }
- port->ops->config_port(port, flags);
- }
-
- if (port->type != PORT_UNKNOWN) {
- unsigned long flags;
-
- uart_report_port(drv, port);
-
- /* Power up port for set_mctrl() */
- uart_change_pm(state, 0);
-
- /*
- * Ensure that the modem control lines are de-activated.
- * keep the DTR setting that is set in uart_set_options()
- * We probably don't need a spinlock around this, but
- */
- spin_lock_irqsave(&port->lock, flags);
- port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);
- spin_unlock_irqrestore(&port->lock, flags);
-
- /*
- * If this driver supports console, and it hasn't been
- * successfully registered yet, try to re-register it.
- * It may be that the port was not available.
- */
- if (port->cons && !(port->cons->flags & CON_ENABLED))
- register_console(port->cons);
-
- /*
- * Power down all ports by default, except the
- * console if we have one.
- */
- if (!uart_console(port))
- uart_change_pm(state, 3);
- }
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-
-static int uart_poll_init(struct tty_driver *driver, int line, char *options)
-{
- struct uart_driver *drv = driver->driver_state;
- struct uart_state *state = drv->state + line;
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (!state || !state->uart_port)
- return -1;
-
- port = state->uart_port;
- if (!(port->ops->poll_get_char && port->ops->poll_put_char))
- return -1;
-
- if (options) {
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- return uart_set_options(port, NULL, baud, parity, bits, flow);
- }
-
- return 0;
-}
-
-static int uart_poll_get_char(struct tty_driver *driver, int line)
-{
- struct uart_driver *drv = driver->driver_state;
- struct uart_state *state = drv->state + line;
- struct uart_port *port;
-
- if (!state || !state->uart_port)
- return -1;
-
- port = state->uart_port;
- return port->ops->poll_get_char(port);
-}
-
-static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
-{
- struct uart_driver *drv = driver->driver_state;
- struct uart_state *state = drv->state + line;
- struct uart_port *port;
-
- if (!state || !state->uart_port)
- return;
-
- port = state->uart_port;
- port->ops->poll_put_char(port, ch);
-}
-#endif
-
-static const struct tty_operations uart_ops = {
- .open = uart_open,
- .close = uart_close,
- .write = uart_write,
- .put_char = uart_put_char,
- .flush_chars = uart_flush_chars,
- .write_room = uart_write_room,
- .chars_in_buffer= uart_chars_in_buffer,
- .flush_buffer = uart_flush_buffer,
- .ioctl = uart_ioctl,
- .throttle = uart_throttle,
- .unthrottle = uart_unthrottle,
- .send_xchar = uart_send_xchar,
- .set_termios = uart_set_termios,
- .set_ldisc = uart_set_ldisc,
- .stop = uart_stop,
- .start = uart_start,
- .hangup = uart_hangup,
- .break_ctl = uart_break_ctl,
- .wait_until_sent= uart_wait_until_sent,
-#ifdef CONFIG_PROC_FS
- .proc_fops = &uart_proc_fops,
-#endif
- .tiocmget = uart_tiocmget,
- .tiocmset = uart_tiocmset,
- .get_icount = uart_get_icount,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_init = uart_poll_init,
- .poll_get_char = uart_poll_get_char,
- .poll_put_char = uart_poll_put_char,
-#endif
-};
-
-static const struct tty_port_operations uart_port_ops = {
- .carrier_raised = uart_carrier_raised,
- .dtr_rts = uart_dtr_rts,
-};
-
-/**
- * uart_register_driver - register a driver with the uart core layer
- * @drv: low level driver structure
- *
- * Register a uart driver with the core driver. We in turn register
- * with the tty layer, and initialise the core driver per-port state.
- *
- * We have a proc file in /proc/tty/driver which is named after the
- * normal driver.
- *
- * drv->port should be NULL, and the per-port structures should be
- * registered using uart_add_one_port after this call has succeeded.
- */
-int uart_register_driver(struct uart_driver *drv)
-{
- struct tty_driver *normal;
- int i, retval;
-
- BUG_ON(drv->state);
-
- /*
- * Maybe we should be using a slab cache for this, especially if
- * we have a large number of ports to handle.
- */
- drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
- if (!drv->state)
- goto out;
-
- normal = alloc_tty_driver(drv->nr);
- if (!normal)
- goto out_kfree;
-
- drv->tty_driver = normal;
-
- normal->owner = drv->owner;
- normal->driver_name = drv->driver_name;
- normal->name = drv->dev_name;
- normal->major = drv->major;
- normal->minor_start = drv->minor;
- normal->type = TTY_DRIVER_TYPE_SERIAL;
- normal->subtype = SERIAL_TYPE_NORMAL;
- normal->init_termios = tty_std_termios;
- normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
- normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- normal->driver_state = drv;
- tty_set_operations(normal, &uart_ops);
-
- /*
- * Initialise the UART state(s).
- */
- for (i = 0; i < drv->nr; i++) {
- struct uart_state *state = drv->state + i;
- struct tty_port *port = &state->port;
-
- tty_port_init(port);
- port->ops = &uart_port_ops;
- port->close_delay = 500; /* .5 seconds */
- port->closing_wait = 30000; /* 30 seconds */
- tasklet_init(&state->tlet, uart_tasklet_action,
- (unsigned long)state);
- }
-
- retval = tty_register_driver(normal);
- if (retval >= 0)
- return retval;
-
- put_tty_driver(normal);
-out_kfree:
- kfree(drv->state);
-out:
- return -ENOMEM;
-}
-
-/**
- * uart_unregister_driver - remove a driver from the uart core layer
- * @drv: low level driver structure
- *
- * Remove all references to a driver from the core driver. The low
- * level driver must have removed all its ports via the
- * uart_remove_one_port() if it registered them with uart_add_one_port().
- * (ie, drv->port == NULL)
- */
-void uart_unregister_driver(struct uart_driver *drv)
-{
- struct tty_driver *p = drv->tty_driver;
- tty_unregister_driver(p);
- put_tty_driver(p);
- kfree(drv->state);
- drv->tty_driver = NULL;
-}
-
-struct tty_driver *uart_console_device(struct console *co, int *index)
-{
- struct uart_driver *p = co->data;
- *index = co->index;
- return p->tty_driver;
-}
-
-/**
- * uart_add_one_port - attach a driver-defined port structure
- * @drv: pointer to the uart low level driver structure for this port
- * @uport: uart port structure to use for this port.
- *
- * This allows the driver to register its own uart_port structure
- * with the core driver. The main purpose is to allow the low
- * level uart drivers to expand uart_port, rather than having yet
- * more levels of structures.
- */
-int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
-{
- struct uart_state *state;
- struct tty_port *port;
- int ret = 0;
- struct device *tty_dev;
-
- BUG_ON(in_interrupt());
-
- if (uport->line >= drv->nr)
- return -EINVAL;
-
- state = drv->state + uport->line;
- port = &state->port;
-
- mutex_lock(&port_mutex);
- mutex_lock(&port->mutex);
- if (state->uart_port) {
- ret = -EINVAL;
- goto out;
- }
-
- state->uart_port = uport;
- state->pm_state = -1;
-
- uport->cons = drv->cons;
- uport->state = state;
-
- /*
- * If this port is a console, then the spinlock is already
- * initialised.
- */
- if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
- spin_lock_init(&uport->lock);
- lockdep_set_class(&uport->lock, &port_lock_key);
- }
-
- uart_configure_port(drv, state, uport);
-
- /*
- * Register the port whether it's detected or not. This allows
- * setserial to be used to alter this ports parameters.
- */
- tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
- if (likely(!IS_ERR(tty_dev))) {
- device_init_wakeup(tty_dev, 1);
- device_set_wakeup_enable(tty_dev, 0);
- } else
- printk(KERN_ERR "Cannot register tty device on line %d\n",
- uport->line);
-
- /*
- * Ensure UPF_DEAD is not set.
- */
- uport->flags &= ~UPF_DEAD;
-
- out:
- mutex_unlock(&port->mutex);
- mutex_unlock(&port_mutex);
-
- return ret;
-}
-
-/**
- * uart_remove_one_port - detach a driver defined port structure
- * @drv: pointer to the uart low level driver structure for this port
- * @uport: uart port structure for this port
- *
- * This unhooks (and hangs up) the specified port structure from the
- * core driver. No further calls will be made to the low-level code
- * for this port.
- */
-int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
-{
- struct uart_state *state = drv->state + uport->line;
- struct tty_port *port = &state->port;
-
- BUG_ON(in_interrupt());
-
- if (state->uart_port != uport)
- printk(KERN_ALERT "Removing wrong port: %p != %p\n",
- state->uart_port, uport);
-
- mutex_lock(&port_mutex);
-
- /*
- * Mark the port "dead" - this prevents any opens from
- * succeeding while we shut down the port.
- */
- mutex_lock(&port->mutex);
- uport->flags |= UPF_DEAD;
- mutex_unlock(&port->mutex);
-
- /*
- * Remove the devices from the tty layer
- */
- tty_unregister_device(drv->tty_driver, uport->line);
-
- if (port->tty)
- tty_vhangup(port->tty);
-
- /*
- * Free the port IO and memory resources, if any.
- */
- if (uport->type != PORT_UNKNOWN)
- uport->ops->release_port(uport);
-
- /*
- * Indicate that there isn't a port here anymore.
- */
- uport->type = PORT_UNKNOWN;
-
- /*
- * Kill the tasklet, and free resources.
- */
- tasklet_kill(&state->tlet);
-
- state->uart_port = NULL;
- mutex_unlock(&port_mutex);
-
- return 0;
-}
-
-/*
- * Are the two ports equivalent?
- */
-int uart_match_port(struct uart_port *port1, struct uart_port *port2)
-{
- if (port1->iotype != port2->iotype)
- return 0;
-
- switch (port1->iotype) {
- case UPIO_PORT:
- return (port1->iobase == port2->iobase);
- case UPIO_HUB6:
- return (port1->iobase == port2->iobase) &&
- (port1->hub6 == port2->hub6);
- case UPIO_MEM:
- case UPIO_MEM32:
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_DWAPB:
- case UPIO_DWAPB32:
- return (port1->mapbase == port2->mapbase);
- }
- return 0;
-}
-EXPORT_SYMBOL(uart_match_port);
-
-EXPORT_SYMBOL(uart_write_wakeup);
-EXPORT_SYMBOL(uart_register_driver);
-EXPORT_SYMBOL(uart_unregister_driver);
-EXPORT_SYMBOL(uart_suspend_port);
-EXPORT_SYMBOL(uart_resume_port);
-EXPORT_SYMBOL(uart_add_one_port);
-EXPORT_SYMBOL(uart_remove_one_port);
-
-MODULE_DESCRIPTION("Serial driver core");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
deleted file mode 100644
index 93760b2ea172..000000000000
--- a/drivers/serial/serial_cs.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/*======================================================================
-
- A driver for PCMCIA serial devices
-
- serial_cs.c 1.134 2002/05/04 05:48:53
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-#include "8250.h"
-
-
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-/* Enable the speaker? */
-static int do_sound = 1;
-/* Skip strict UART tests? */
-static int buggy_uart;
-
-module_param(do_sound, int, 0444);
-module_param(buggy_uart, int, 0444);
-
-/*====================================================================*/
-
-/* Table of multi-port card ID's */
-
-struct serial_quirk {
- unsigned int manfid;
- unsigned int prodid;
- int multi; /* 1 = multifunction, > 1 = # ports */
- void (*config)(struct pcmcia_device *);
- void (*setup)(struct pcmcia_device *, struct uart_port *);
- void (*wakeup)(struct pcmcia_device *);
- int (*post)(struct pcmcia_device *);
-};
-
-struct serial_info {
- struct pcmcia_device *p_dev;
- int ndev;
- int multi;
- int slave;
- int manfid;
- int prodid;
- int c950ctrl;
- int line[4];
- const struct serial_quirk *quirk;
-};
-
-struct serial_cfg_mem {
- tuple_t tuple;
- cisparse_t parse;
- u_char buf[256];
-};
-
-/*
- * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6"
- * manfid 0x0160, 0x0104
- * This card appears to have a 14.7456MHz clock.
- */
-/* Generic Modem: MD55x (GPRS/EDGE) have
- * Elan VPU16551 UART with 14.7456MHz oscillator
- * manfid 0x015D, 0x4C45
- */
-static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
-{
- port->uartclk = 14745600;
-}
-
-static int quirk_post_ibm(struct pcmcia_device *link)
-{
- u8 val;
- int ret;
-
- ret = pcmcia_read_config_byte(link, 0x800, &val);
- if (ret)
- goto failed;
-
- ret = pcmcia_write_config_byte(link, 0x800, val | 1);
- if (ret)
- goto failed;
- return 0;
-
- failed:
- return -ENODEV;
-}
-
-/*
- * Nokia cards are not really multiport cards. Shouldn't this
- * be handled by setting the quirk entry .multi = 0 | 1 ?
- */
-static void quirk_config_nokia(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- if (info->multi > 1)
- info->multi = 1;
-}
-
-static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- if (info->c950ctrl)
- outb(12, info->c950ctrl + 1);
-}
-
-/* request_region? oxsemi branch does no request_region too... */
-/*
- * This sequence is needed to properly initialize MC45 attached to OXCF950.
- * I tried decreasing these msleep()s, but it worked properly (survived
- * 1000 stop/start operations) with these timeouts (or bigger).
- */
-static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- unsigned int ctrl = info->c950ctrl;
-
- outb(0xA, ctrl + 1);
- msleep(100);
- outb(0xE, ctrl + 1);
- msleep(300);
- outb(0xC, ctrl + 1);
- msleep(100);
- outb(0xE, ctrl + 1);
- msleep(200);
- outb(0xF, ctrl + 1);
- msleep(100);
- outb(0xE, ctrl + 1);
- msleep(100);
- outb(0xC, ctrl + 1);
-}
-
-/*
- * Socket Dual IO: this enables irq's for second port
- */
-static void quirk_config_socket(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- if (info->multi)
- link->config_flags |= CONF_ENABLE_ESR;
-}
-
-static const struct serial_quirk quirks[] = {
- {
- .manfid = 0x0160,
- .prodid = 0x0104,
- .multi = -1,
- .setup = quirk_setup_brainboxes_0104,
- }, {
- .manfid = 0x015D,
- .prodid = 0x4C45,
- .multi = -1,
- .setup = quirk_setup_brainboxes_0104,
- }, {
- .manfid = MANFID_IBM,
- .prodid = ~0,
- .multi = -1,
- .post = quirk_post_ibm,
- }, {
- .manfid = MANFID_INTEL,
- .prodid = PRODID_INTEL_DUAL_RS232,
- .multi = 2,
- }, {
- .manfid = MANFID_NATINST,
- .prodid = PRODID_NATINST_QUAD_RS232,
- .multi = 4,
- }, {
- .manfid = MANFID_NOKIA,
- .prodid = ~0,
- .multi = -1,
- .config = quirk_config_nokia,
- }, {
- .manfid = MANFID_OMEGA,
- .prodid = PRODID_OMEGA_QSP_100,
- .multi = 4,
- }, {
- .manfid = MANFID_OXSEMI,
- .prodid = ~0,
- .multi = -1,
- .wakeup = quirk_wakeup_oxsemi,
- }, {
- .manfid = MANFID_POSSIO,
- .prodid = PRODID_POSSIO_GCC,
- .multi = -1,
- .wakeup = quirk_wakeup_possio_gcc,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_DUAL_RS232,
- .multi = 2,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_DUAL_RS232_D1,
- .multi = 2,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_DUAL_RS232_G,
- .multi = 2,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_QUAD_RS232,
- .multi = 4,
- }, {
- .manfid = MANFID_SOCKET,
- .prodid = PRODID_SOCKET_DUAL_RS232,
- .multi = 2,
- .config = quirk_config_socket,
- }, {
- .manfid = MANFID_SOCKET,
- .prodid = ~0,
- .multi = -1,
- .config = quirk_config_socket,
- }
-};
-
-
-static int serial_config(struct pcmcia_device * link);
-
-
-static void serial_remove(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- dev_dbg(&link->dev, "serial_release\n");
-
- /*
- * Recheck to see if the device is still configured.
- */
- for (i = 0; i < info->ndev; i++)
- serial8250_unregister_port(info->line[i]);
-
- if (!info->slave)
- pcmcia_disable_device(link);
-}
-
-static int serial_suspend(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- for (i = 0; i < info->ndev; i++)
- serial8250_suspend_port(info->line[i]);
-
- return 0;
-}
-
-static int serial_resume(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- for (i = 0; i < info->ndev; i++)
- serial8250_resume_port(info->line[i]);
-
- if (info->quirk && info->quirk->wakeup)
- info->quirk->wakeup(link);
-
- return 0;
-}
-
-static int serial_probe(struct pcmcia_device *link)
-{
- struct serial_info *info;
-
- dev_dbg(&link->dev, "serial_attach()\n");
-
- /* Create new serial device */
- info = kzalloc(sizeof (*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
- info->p_dev = link;
- link->priv = info;
-
- link->config_flags |= CONF_ENABLE_IRQ;
- if (do_sound)
- link->config_flags |= CONF_ENABLE_SPKR;
-
- return serial_config(link);
-}
-
-static void serial_detach(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- dev_dbg(&link->dev, "serial_detach\n");
-
- /*
- * Ensure that the ports have been released.
- */
- serial_remove(link);
-
- /* free bits */
- kfree(info);
-}
-
-/*====================================================================*/
-
-static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
- unsigned int iobase, int irq)
-{
- struct uart_port port;
- int line;
-
- memset(&port, 0, sizeof (struct uart_port));
- port.iobase = iobase;
- port.irq = irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &handle->dev;
- if (buggy_uart)
- port.flags |= UPF_BUGGY_UART;
-
- if (info->quirk && info->quirk->setup)
- info->quirk->setup(handle, &port);
-
- line = serial8250_register_port(&port);
- if (line < 0) {
- printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
- "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
- return -EINVAL;
- }
-
- info->line[info->ndev] = line;
- info->ndev++;
-
- return 0;
-}
-
-/*====================================================================*/
-
-static int pfc_config(struct pcmcia_device *p_dev)
-{
- unsigned int port = 0;
- struct serial_info *info = p_dev->priv;
-
- if ((p_dev->resource[1]->end != 0) &&
- (resource_size(p_dev->resource[1]) == 8)) {
- port = p_dev->resource[1]->start;
- info->slave = 1;
- } else if ((info->manfid == MANFID_OSITECH) &&
- (resource_size(p_dev->resource[0]) == 0x40)) {
- port = p_dev->resource[0]->start + 0x28;
- info->slave = 1;
- }
- if (info->slave)
- return setup_serial(p_dev, info, port, p_dev->irq);
-
- dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
- return -ENODEV;
-}
-
-static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
-{
- static const int size_table[2] = { 8, 16 };
- int *try = priv_data;
-
- if (p_dev->resource[0]->start == 0)
- return -ENODEV;
-
- if ((*try & 0x1) == 0)
- p_dev->io_lines = 16;
-
- if (p_dev->resource[0]->end != size_table[(*try >> 1)])
- return -ENODEV;
-
- p_dev->resource[0]->end = 8;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
- return pcmcia_request_io(p_dev);
-}
-
-static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
- int j;
-
- if (p_dev->io_lines > 3)
- return -ENODEV;
-
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- p_dev->resource[0]->end = 8;
-
- for (j = 0; j < 5; j++) {
- p_dev->resource[0]->start = base[j];
- p_dev->io_lines = base[j] ? 16 : 3;
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
- return -ENODEV;
-}
-
-static int simple_config(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i = -ENODEV, try;
-
- /* First pass: look for a config entry that looks normal.
- * Two tries: without IO aliases, then with aliases */
- link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO;
- for (try = 0; try < 4; try++)
- if (!pcmcia_loop_config(link, simple_config_check, &try))
- goto found_port;
-
- /* Second pass: try to find an entry that isn't picky about
- its base address, then try to grab any standard serial port
- address, and finally try to get any free port. */
- if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
- goto found_port;
-
- dev_warn(&link->dev, "no usable port range found, giving up\n");
- return -1;
-
-found_port:
- if (info->multi && (info->manfid == MANFID_3COM))
- link->config_index &= ~(0x08);
-
- /*
- * Apply any configuration quirks.
- */
- if (info->quirk && info->quirk->config)
- info->quirk->config(link);
-
- i = pcmcia_enable_device(link);
- if (i != 0)
- return -1;
- return setup_serial(link, info, link->resource[0]->start, link->irq);
-}
-
-static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
-{
- int *multi = priv_data;
-
- if (p_dev->resource[1]->end)
- return -EINVAL;
-
- /* The quad port cards have bad CIS's, so just look for a
- window larger than 8 ports and assume it will be right */
- if (p_dev->resource[0]->end <= 8)
- return -EINVAL;
-
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- p_dev->resource[0]->end = *multi * 8;
-
- if (pcmcia_request_io(p_dev))
- return -ENODEV;
- return 0;
-}
-
-static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- int *base2 = priv_data;
-
- if (!p_dev->resource[0]->end || !p_dev->resource[1]->end)
- return -ENODEV;
-
- p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
- if (pcmcia_request_io(p_dev))
- return -ENODEV;
-
- *base2 = p_dev->resource[0]->start + 8;
- return 0;
-}
-
-static int multi_config(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i, base2 = 0;
-
- link->config_flags |= CONF_AUTO_SET_IO;
- /* First, look for a generic full-sized window */
- if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
- base2 = link->resource[0]->start + 8;
- else {
- /* If that didn't work, look for two windows */
- info->multi = 2;
- if (pcmcia_loop_config(link, multi_config_check_notpicky,
- &base2)) {
- dev_warn(&link->dev, "no usable port range "
- "found, giving up\n");
- return -ENODEV;
- }
- }
-
- if (!link->irq)
- dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
-
- /*
- * Apply any configuration quirks.
- */
- if (info->quirk && info->quirk->config)
- info->quirk->config(link);
-
- i = pcmcia_enable_device(link);
- if (i != 0)
- return -ENODEV;
-
- /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
- * 8 registers are for the UART, the others are extra registers.
- * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
- */
- if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
- info->prodid == PRODID_POSSIO_GCC)) {
- int err;
-
- if (link->config_index == 1 ||
- link->config_index == 3) {
- err = setup_serial(link, info, base2,
- link->irq);
- base2 = link->resource[0]->start;
- } else {
- err = setup_serial(link, info, link->resource[0]->start,
- link->irq);
- }
- info->c950ctrl = base2;
-
- /*
- * FIXME: We really should wake up the port prior to
- * handing it over to the serial layer.
- */
- if (info->quirk && info->quirk->wakeup)
- info->quirk->wakeup(link);
-
- return 0;
- }
-
- setup_serial(link, info, link->resource[0]->start, link->irq);
- for (i = 0; i < info->multi - 1; i++)
- setup_serial(link, info, base2 + (8 * i),
- link->irq);
- return 0;
-}
-
-static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data)
-{
- struct serial_info *info = p_dev->priv;
-
- if (!p_dev->resource[0]->end)
- return -EINVAL;
-
- if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
- info->multi = p_dev->resource[0]->end >> 3;
-
- if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
- && (p_dev->resource[1]->end == 8))
- info->multi = 2;
-
- return 0; /* break */
-}
-
-
-static int serial_config(struct pcmcia_device * link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- dev_dbg(&link->dev, "serial_config\n");
-
- /* Is this a compliant multifunction card? */
- info->multi = (link->socket->functions > 1);
-
- /* Is this a multiport card? */
- info->manfid = link->manf_id;
- info->prodid = link->card_id;
-
- for (i = 0; i < ARRAY_SIZE(quirks); i++)
- if ((quirks[i].manfid == ~0 ||
- quirks[i].manfid == info->manfid) &&
- (quirks[i].prodid == ~0 ||
- quirks[i].prodid == info->prodid)) {
- info->quirk = &quirks[i];
- break;
- }
-
- /* Another check for dual-serial cards: look for either serial or
- multifunction cards that ask for appropriate IO port ranges */
- if ((info->multi == 0) &&
- (link->has_func_id) &&
- (link->socket->pcmcia_pfc == 0) &&
- ((link->func_id == CISTPL_FUNCID_MULTI) ||
- (link->func_id == CISTPL_FUNCID_SERIAL)))
- pcmcia_loop_config(link, serial_check_for_multi, info);
-
- /*
- * Apply any multi-port quirk.
- */
- if (info->quirk && info->quirk->multi != -1)
- info->multi = info->quirk->multi;
-
- dev_info(&link->dev,
- "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
- link->manf_id, link->card_id,
- link->socket->pcmcia_pfc, info->multi, info->quirk);
- if (link->socket->pcmcia_pfc)
- i = pfc_config(link);
- else if (info->multi > 1)
- i = multi_config(link);
- else
- i = simple_config(link);
-
- if (i || info->ndev == 0)
- goto failed;
-
- /*
- * Apply any post-init quirk. FIXME: This should really happen
- * before we register the port, since it might already be in use.
- */
- if (info->quirk && info->quirk->post)
- if (info->quirk->post(link))
- goto failed;
-
- return 0;
-
-failed:
- dev_warn(&link->dev, "failed to initialize\n");
- serial_remove(link);
- return -ENODEV;
-}
-
-static struct pcmcia_device_id serial_ids[] = {
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
- PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
- PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
- PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
- PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
- PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
- PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
- PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
- PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
- PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
- PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
- PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
- PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
- PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
- PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
- PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
- PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
- PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
- PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
- PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
- PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
- PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
- PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
- PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
- PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
- PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
- PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
- PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
- PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
- PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
- PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
- PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
- PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
- PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
- PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
- PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
- PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
- PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
- PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
- PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
- PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
- PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
- PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
- PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
- PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
- PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC860", 0xd85f6206, 0x698f93db, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC860 3G Network Adapter R1 */
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
- PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b),
- /* too generic */
- /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
- /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
- PCMCIA_DEVICE_FUNC_ID(2),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, serial_ids);
-
-MODULE_FIRMWARE("cis/PCMLM28.cis");
-MODULE_FIRMWARE("cis/DP83903.cis");
-MODULE_FIRMWARE("cis/3CCFEM556.cis");
-MODULE_FIRMWARE("cis/3CXEM556.cis");
-MODULE_FIRMWARE("cis/SW_8xx_SER.cis");
-MODULE_FIRMWARE("cis/SW_7xx_SER.cis");
-MODULE_FIRMWARE("cis/SW_555_SER.cis");
-MODULE_FIRMWARE("cis/MT5634ZLX.cis");
-MODULE_FIRMWARE("cis/COMpad2.cis");
-MODULE_FIRMWARE("cis/COMpad4.cis");
-MODULE_FIRMWARE("cis/RS-COM-2P.cis");
-
-static struct pcmcia_driver serial_cs_driver = {
- .owner = THIS_MODULE,
- .name = "serial_cs",
- .probe = serial_probe,
- .remove = serial_detach,
- .id_table = serial_ids,
- .suspend = serial_suspend,
- .resume = serial_resume,
-};
-
-static int __init init_serial_cs(void)
-{
- return pcmcia_register_driver(&serial_cs_driver);
-}
-
-static void __exit exit_serial_cs(void)
-{
- pcmcia_unregister_driver(&serial_cs_driver);
-}
-
-module_init(init_serial_cs);
-module_exit(exit_serial_cs);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
deleted file mode 100644
index b1962025b1aa..000000000000
--- a/drivers/serial/serial_ks8695.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * drivers/serial/serial_ks8695.c
- *
- * Driver for KS8695 serial ports
- *
- * Based on drivers/serial/serial_amba.c, by Kam Lee.
- *
- * Copyright 2002-2005 Micrel 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/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <mach/regs-uart.h>
-#include <mach/regs-irq.h>
-
-#if defined(CONFIG_SERIAL_KS8695_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-
-#define SERIAL_KS8695_MAJOR 204
-#define SERIAL_KS8695_MINOR 16
-#define SERIAL_KS8695_DEVNAME "ttyAM"
-
-#define SERIAL_KS8695_NR 1
-
-/*
- * Access macros for the KS8695 UART
- */
-#define UART_GET_CHAR(p) (__raw_readl((p)->membase + KS8695_URRB) & 0xFF)
-#define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + KS8695_URTH)
-#define UART_GET_FCR(p) __raw_readl((p)->membase + KS8695_URFC)
-#define UART_PUT_FCR(p, c) __raw_writel((c), (p)->membase + KS8695_URFC)
-#define UART_GET_MSR(p) __raw_readl((p)->membase + KS8695_URMS)
-#define UART_GET_LSR(p) __raw_readl((p)->membase + KS8695_URLS)
-#define UART_GET_LCR(p) __raw_readl((p)->membase + KS8695_URLC)
-#define UART_PUT_LCR(p, c) __raw_writel((c), (p)->membase + KS8695_URLC)
-#define UART_GET_MCR(p) __raw_readl((p)->membase + KS8695_URMC)
-#define UART_PUT_MCR(p, c) __raw_writel((c), (p)->membase + KS8695_URMC)
-#define UART_GET_BRDR(p) __raw_readl((p)->membase + KS8695_URBD)
-#define UART_PUT_BRDR(p, c) __raw_writel((c), (p)->membase + KS8695_URBD)
-
-#define KS8695_CLR_TX_INT() __raw_writel(1 << KS8695_IRQ_UART_TX, KS8695_IRQ_VA + KS8695_INTST)
-
-#define UART_DUMMY_LSR_RX 0x100
-#define UART_PORT_SIZE (KS8695_USR - KS8695_URRB + 4)
-
-static inline int tx_enabled(struct uart_port *port)
-{
- return port->unused[0] & 1;
-}
-
-static inline int rx_enabled(struct uart_port *port)
-{
- return port->unused[0] & 2;
-}
-
-static inline int ms_enabled(struct uart_port *port)
-{
- return port->unused[0] & 4;
-}
-
-static inline void ms_enable(struct uart_port *port, int enabled)
-{
- if(enabled)
- port->unused[0] |= 4;
- else
- port->unused[0] &= ~4;
-}
-
-static inline void rx_enable(struct uart_port *port, int enabled)
-{
- if(enabled)
- port->unused[0] |= 2;
- else
- port->unused[0] &= ~2;
-}
-
-static inline void tx_enable(struct uart_port *port, int enabled)
-{
- if(enabled)
- port->unused[0] |= 1;
- else
- port->unused[0] &= ~1;
-}
-
-
-#ifdef SUPPORT_SYSRQ
-static struct console ks8695_console;
-#endif
-
-static void ks8695uart_stop_tx(struct uart_port *port)
-{
- if (tx_enabled(port)) {
- /* use disable_irq_nosync() and not disable_irq() to avoid self
- * imposed deadlock by not waiting for irq handler to end,
- * since this ks8695uart_stop_tx() is called from interrupt context.
- */
- disable_irq_nosync(KS8695_IRQ_UART_TX);
- tx_enable(port, 0);
- }
-}
-
-static void ks8695uart_start_tx(struct uart_port *port)
-{
- if (!tx_enabled(port)) {
- enable_irq(KS8695_IRQ_UART_TX);
- tx_enable(port, 1);
- }
-}
-
-static void ks8695uart_stop_rx(struct uart_port *port)
-{
- if (rx_enabled(port)) {
- disable_irq(KS8695_IRQ_UART_RX);
- rx_enable(port, 0);
- }
-}
-
-static void ks8695uart_enable_ms(struct uart_port *port)
-{
- if (!ms_enabled(port)) {
- enable_irq(KS8695_IRQ_UART_MODEM_STATUS);
- ms_enable(port,1);
- }
-}
-
-static void ks8695uart_disable_ms(struct uart_port *port)
-{
- if (ms_enabled(port)) {
- disable_irq(KS8695_IRQ_UART_MODEM_STATUS);
- ms_enable(port,0);
- }
-}
-
-static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- struct tty_struct *tty = port->state->port.tty;
- unsigned int status, ch, lsr, flg, max_count = 256;
-
- status = UART_GET_LSR(port); /* clears pending LSR interrupts */
- while ((status & URLS_URDR) && max_count--) {
- ch = UART_GET_CHAR(port);
- flg = TTY_NORMAL;
-
- port->icount.rx++;
-
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- lsr = UART_GET_LSR(port) | UART_DUMMY_LSR_RX;
- if (unlikely(lsr & (URLS_URBI | URLS_URPE | URLS_URFE | URLS_URROE))) {
- if (lsr & URLS_URBI) {
- lsr &= ~(URLS_URFE | URLS_URPE);
- port->icount.brk++;
- if (uart_handle_break(port))
- goto ignore_char;
- }
- if (lsr & URLS_URPE)
- port->icount.parity++;
- if (lsr & URLS_URFE)
- port->icount.frame++;
- if (lsr & URLS_URROE)
- port->icount.overrun++;
-
- lsr &= port->read_status_mask;
-
- if (lsr & URLS_URBI)
- flg = TTY_BREAK;
- else if (lsr & URLS_URPE)
- flg = TTY_PARITY;
- else if (lsr & URLS_URFE)
- flg = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
-
- uart_insert_char(port, lsr, URLS_URROE, ch, flg);
-
-ignore_char:
- status = UART_GET_LSR(port);
- }
- tty_flip_buffer_push(tty);
-
- return IRQ_HANDLED;
-}
-
-
-static irqreturn_t ks8695uart_tx_chars(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- struct circ_buf *xmit = &port->state->xmit;
- unsigned int count;
-
- if (port->x_char) {
- KS8695_CLR_TX_INT();
- UART_PUT_CHAR(port, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return IRQ_HANDLED;
- }
-
- if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
- ks8695uart_stop_tx(port);
- return IRQ_HANDLED;
- }
-
- count = 16; /* fifo size */
- while (!uart_circ_empty(xmit) && (count-- > 0)) {
- KS8695_CLR_TX_INT();
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- ks8695uart_stop_tx(port);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t ks8695uart_modem_status(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- unsigned int status;
-
- /*
- * clear modem interrupt by reading MSR
- */
- status = UART_GET_MSR(port);
-
- if (status & URMS_URDDCD)
- uart_handle_dcd_change(port, status & URMS_URDDCD);
-
- if (status & URMS_URDDST)
- port->icount.dsr++;
-
- if (status & URMS_URDCTS)
- uart_handle_cts_change(port, status & URMS_URDCTS);
-
- if (status & URMS_URTERI)
- port->icount.rng++;
-
- wake_up_interruptible(&port->state->port.delta_msr_wait);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int ks8695uart_tx_empty(struct uart_port *port)
-{
- return (UART_GET_LSR(port) & URLS_URTE) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int ks8695uart_get_mctrl(struct uart_port *port)
-{
- unsigned int result = 0;
- unsigned int status;
-
- status = UART_GET_MSR(port);
- if (status & URMS_URDCD)
- result |= TIOCM_CAR;
- if (status & URMS_URDSR)
- result |= TIOCM_DSR;
- if (status & URMS_URCTS)
- result |= TIOCM_CTS;
- if (status & URMS_URRI)
- result |= TIOCM_RI;
-
- return result;
-}
-
-static void ks8695uart_set_mctrl(struct uart_port *port, u_int mctrl)
-{
- unsigned int mcr;
-
- mcr = UART_GET_MCR(port);
- if (mctrl & TIOCM_RTS)
- mcr |= URMC_URRTS;
- else
- mcr &= ~URMC_URRTS;
-
- if (mctrl & TIOCM_DTR)
- mcr |= URMC_URDTR;
- else
- mcr &= ~URMC_URDTR;
-
- UART_PUT_MCR(port, mcr);
-}
-
-static void ks8695uart_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned int lcr;
-
- lcr = UART_GET_LCR(port);
-
- if (break_state == -1)
- lcr |= URLC_URSBC;
- else
- lcr &= ~URLC_URSBC;
-
- UART_PUT_LCR(port, lcr);
-}
-
-static int ks8695uart_startup(struct uart_port *port)
-{
- int retval;
-
- set_irq_flags(KS8695_IRQ_UART_TX, IRQF_VALID | IRQF_NOAUTOEN);
- tx_enable(port, 0);
- rx_enable(port, 1);
- ms_enable(port, 1);
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, IRQF_DISABLED, "UART TX", port);
- if (retval)
- goto err_tx;
-
- retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, IRQF_DISABLED, "UART RX", port);
- if (retval)
- goto err_rx;
-
- retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, IRQF_DISABLED, "UART LineStatus", port);
- if (retval)
- goto err_ls;
-
- retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, IRQF_DISABLED, "UART ModemStatus", port);
- if (retval)
- goto err_ms;
-
- return 0;
-
-err_ms:
- free_irq(KS8695_IRQ_UART_LINE_STATUS, port);
-err_ls:
- free_irq(KS8695_IRQ_UART_RX, port);
-err_rx:
- free_irq(KS8695_IRQ_UART_TX, port);
-err_tx:
- return retval;
-}
-
-static void ks8695uart_shutdown(struct uart_port *port)
-{
- /*
- * Free the interrupt
- */
- free_irq(KS8695_IRQ_UART_RX, port);
- free_irq(KS8695_IRQ_UART_TX, port);
- free_irq(KS8695_IRQ_UART_MODEM_STATUS, port);
- free_irq(KS8695_IRQ_UART_LINE_STATUS, port);
-
- /* disable break condition and fifos */
- UART_PUT_LCR(port, UART_GET_LCR(port) & ~URLC_URSBC);
- UART_PUT_FCR(port, UART_GET_FCR(port) & ~URFC_URFE);
-}
-
-static void ks8695uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
-{
- unsigned int lcr, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- lcr = URCL_5;
- break;
- case CS6:
- lcr = URCL_6;
- break;
- case CS7:
- lcr = URCL_7;
- break;
- default:
- lcr = URCL_8;
- break;
- }
-
- /* stop bits */
- if (termios->c_cflag & CSTOPB)
- lcr |= URLC_URSB;
-
- /* parity */
- if (termios->c_cflag & PARENB) {
- if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */
- if (termios->c_cflag & PARODD)
- lcr |= URPE_MARK;
- else
- lcr |= URPE_SPACE;
- }
- else if (termios->c_cflag & PARODD)
- lcr |= URPE_ODD;
- else
- lcr |= URPE_EVEN;
- }
-
- if (port->fifosize > 1)
- fcr = URFC_URFRT_8 | URFC_URTFR | URFC_URRFR | URFC_URFE;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- port->read_status_mask = URLS_URROE;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= (URLS_URFE | URLS_URPE);
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= URLS_URBI;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= (URLS_URFE | URLS_URPE);
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= URLS_URBI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= URLS_URROE;
- }
-
- /*
- * Ignore all characters if CREAD is not set.
- */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= UART_DUMMY_LSR_RX;
-
- /* first, disable everything */
- if (UART_ENABLE_MS(port, termios->c_cflag))
- ks8695uart_enable_ms(port);
- else
- ks8695uart_disable_ms(port);
-
- /* Set baud rate */
- UART_PUT_BRDR(port, quot);
-
- UART_PUT_LCR(port, lcr);
- UART_PUT_FCR(port, fcr);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *ks8695uart_type(struct uart_port *port)
-{
- return port->type == PORT_KS8695 ? "KS8695" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'
- */
-static void ks8695uart_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, UART_PORT_SIZE);
-}
-
-/*
- * Request the memory region(s) being used by 'port'
- */
-static int ks8695uart_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, UART_PORT_SIZE,
- "serial_ks8695") != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void ks8695uart_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_KS8695;
- ks8695uart_request_port(port);
- }
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int ks8695uart_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_KS8695)
- ret = -EINVAL;
- if (ser->irq != port->irq)
- ret = -EINVAL;
- if (ser->baud_base < 9600)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops ks8695uart_pops = {
- .tx_empty = ks8695uart_tx_empty,
- .set_mctrl = ks8695uart_set_mctrl,
- .get_mctrl = ks8695uart_get_mctrl,
- .stop_tx = ks8695uart_stop_tx,
- .start_tx = ks8695uart_start_tx,
- .stop_rx = ks8695uart_stop_rx,
- .enable_ms = ks8695uart_enable_ms,
- .break_ctl = ks8695uart_break_ctl,
- .startup = ks8695uart_startup,
- .shutdown = ks8695uart_shutdown,
- .set_termios = ks8695uart_set_termios,
- .type = ks8695uart_type,
- .release_port = ks8695uart_release_port,
- .request_port = ks8695uart_request_port,
- .config_port = ks8695uart_config_port,
- .verify_port = ks8695uart_verify_port,
-};
-
-static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = {
- {
- .membase = (void *) KS8695_UART_VA,
- .mapbase = KS8695_UART_VA,
- .iotype = SERIAL_IO_MEM,
- .irq = KS8695_IRQ_UART_TX,
- .uartclk = KS8695_CLOCK_RATE * 16,
- .fifosize = 16,
- .ops = &ks8695uart_pops,
- .flags = ASYNC_BOOT_AUTOCONF,
- .line = 0,
- }
-};
-
-#ifdef CONFIG_SERIAL_KS8695_CONSOLE
-static void ks8695_console_putchar(struct uart_port *port, int ch)
-{
- while (!(UART_GET_LSR(port) & URLS_URTHRE))
- barrier();
-
- UART_PUT_CHAR(port, ch);
-}
-
-static void ks8695_console_write(struct console *co, const char *s, u_int count)
-{
- struct uart_port *port = ks8695uart_ports + co->index;
-
- uart_console_write(port, s, count, ks8695_console_putchar);
-}
-
-static void __init ks8695_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-{
- unsigned int lcr;
-
- lcr = UART_GET_LCR(port);
-
- switch (lcr & URLC_PARITY) {
- case URPE_ODD:
- *parity = 'o';
- break;
- case URPE_EVEN:
- *parity = 'e';
- break;
- default:
- *parity = 'n';
- }
-
- switch (lcr & URLC_URCL) {
- case URCL_5:
- *bits = 5;
- break;
- case URCL_6:
- *bits = 6;
- break;
- case URCL_7:
- *bits = 7;
- break;
- default:
- *bits = 8;
- }
-
- *baud = port->uartclk / (UART_GET_BRDR(port) & 0x0FFF);
- *baud /= 16;
- *baud &= 0xFFFFFFF0;
-}
-
-static int __init ks8695_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- port = uart_get_console(ks8695uart_ports, SERIAL_KS8695_NR, co);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- ks8695_console_get_options(port, &baud, &parity, &bits);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver ks8695_reg;
-
-static struct console ks8695_console = {
- .name = SERIAL_KS8695_DEVNAME,
- .write = ks8695_console_write,
- .device = uart_console_device,
- .setup = ks8695_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &ks8695_reg,
-};
-
-static int __init ks8695_console_init(void)
-{
- add_preferred_console(SERIAL_KS8695_DEVNAME, 0, NULL);
- register_console(&ks8695_console);
- return 0;
-}
-
-console_initcall(ks8695_console_init);
-
-#define KS8695_CONSOLE &ks8695_console
-#else
-#define KS8695_CONSOLE NULL
-#endif
-
-static struct uart_driver ks8695_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial_ks8695",
- .dev_name = SERIAL_KS8695_DEVNAME,
- .major = SERIAL_KS8695_MAJOR,
- .minor = SERIAL_KS8695_MINOR,
- .nr = SERIAL_KS8695_NR,
- .cons = KS8695_CONSOLE,
-};
-
-static int __init ks8695uart_init(void)
-{
- int i, ret;
-
- printk(KERN_INFO "Serial: Micrel KS8695 UART driver\n");
-
- ret = uart_register_driver(&ks8695_reg);
- if (ret)
- return ret;
-
- for (i = 0; i < SERIAL_KS8695_NR; i++)
- uart_add_one_port(&ks8695_reg, &ks8695uart_ports[0]);
-
- return 0;
-}
-
-static void __exit ks8695uart_exit(void)
-{
- int i;
-
- for (i = 0; i < SERIAL_KS8695_NR; i++)
- uart_remove_one_port(&ks8695_reg, &ks8695uart_ports[0]);
- uart_unregister_driver(&ks8695_reg);
-}
-
-module_init(ks8695uart_init);
-module_exit(ks8695uart_exit);
-
-MODULE_DESCRIPTION("KS8695 serial port driver");
-MODULE_AUTHOR("Micrel Inc.");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
deleted file mode 100644
index ea744707c4d6..000000000000
--- a/drivers/serial/serial_lh7a40x.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/* drivers/serial/serial_lh7a40x.c
- *
- * Copyright (C) 2004 Coastal Environmental Systems
- *
- * 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.
- *
- */
-
-/* Driver for Sharp LH7A40X embedded serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- * Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd.
- *
- * ---
- *
- * This driver supports the embedded UARTs of the Sharp LH7A40X series
- * CPUs. While similar to the 16550 and other UART chips, there is
- * nothing close to register compatibility. Moreover, some of the
- * modem control lines are not available, either in the chip or they
- * are lacking in the board-level implementation.
- *
- * - Use of SIRDIS
- * For simplicity, we disable the IR functions of any UART whenever
- * we enable it.
- *
- */
-
-
-#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#define DEV_MAJOR 204
-#define DEV_MINOR 16
-#define DEV_NR 3
-
-#define ISR_LOOP_LIMIT 256
-
-#define UR(p,o) _UR ((p)->membase, o)
-#define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o))))
-#define BIT_CLR(p,o,m) UR(p,o) = UR(p,o) & (~(unsigned int)m)
-#define BIT_SET(p,o,m) UR(p,o) = UR(p,o) | ( (unsigned int)m)
-
-#define UART_REG_SIZE 32
-
-#define UART_R_DATA (0x00)
-#define UART_R_FCON (0x04)
-#define UART_R_BRCON (0x08)
-#define UART_R_CON (0x0c)
-#define UART_R_STATUS (0x10)
-#define UART_R_RAWISR (0x14)
-#define UART_R_INTEN (0x18)
-#define UART_R_ISR (0x1c)
-
-#define UARTEN (0x01) /* UART enable */
-#define SIRDIS (0x02) /* Serial IR disable (UART1 only) */
-
-#define RxEmpty (0x10)
-#define TxEmpty (0x80)
-#define TxFull (0x20)
-#define nRxRdy RxEmpty
-#define nTxRdy TxFull
-#define TxBusy (0x08)
-
-#define RxBreak (0x0800)
-#define RxOverrunError (0x0400)
-#define RxParityError (0x0200)
-#define RxFramingError (0x0100)
-#define RxError (RxBreak | RxOverrunError | RxParityError | RxFramingError)
-
-#define DCD (0x04)
-#define DSR (0x02)
-#define CTS (0x01)
-
-#define RxInt (0x01)
-#define TxInt (0x02)
-#define ModemInt (0x04)
-#define RxTimeoutInt (0x08)
-
-#define MSEOI (0x10)
-
-#define WLEN_8 (0x60)
-#define WLEN_7 (0x40)
-#define WLEN_6 (0x20)
-#define WLEN_5 (0x00)
-#define WLEN (0x60) /* Mask for all word-length bits */
-#define STP2 (0x08)
-#define PEN (0x02) /* Parity Enable */
-#define EPS (0x04) /* Even Parity Set */
-#define FEN (0x10) /* FIFO Enable */
-#define BRK (0x01) /* Send Break */
-
-
-struct uart_port_lh7a40x {
- struct uart_port port;
- unsigned int statusPrev; /* Most recently read modem status */
-};
-
-static void lh7a40xuart_stop_tx (struct uart_port* port)
-{
- BIT_CLR (port, UART_R_INTEN, TxInt);
-}
-
-static void lh7a40xuart_start_tx (struct uart_port* port)
-{
- BIT_SET (port, UART_R_INTEN, TxInt);
-
- /* *** FIXME: do I need to check for startup of the
- transmitter? The old driver did, but AMBA
- doesn't . */
-}
-
-static void lh7a40xuart_stop_rx (struct uart_port* port)
-{
- BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
-}
-
-static void lh7a40xuart_enable_ms (struct uart_port* port)
-{
- BIT_SET (port, UART_R_INTEN, ModemInt);
-}
-
-static void lh7a40xuart_rx_chars (struct uart_port* port)
-{
- struct tty_struct* tty = port->state->port.tty;
- int cbRxMax = 256; /* (Gross) limit on receive */
- unsigned int data; /* Received data and status */
- unsigned int flag;
-
- while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
- data = UR (port, UART_R_DATA);
- flag = TTY_NORMAL;
- ++port->icount.rx;
-
- if (unlikely(data & RxError)) {
- if (data & RxBreak) {
- data &= ~(RxFramingError | RxParityError);
- ++port->icount.brk;
- if (uart_handle_break (port))
- continue;
- }
- else if (data & RxParityError)
- ++port->icount.parity;
- else if (data & RxFramingError)
- ++port->icount.frame;
- if (data & RxOverrunError)
- ++port->icount.overrun;
-
- /* Mask by termios, leave Rx'd byte */
- data &= port->read_status_mask | 0xff;
-
- if (data & RxBreak)
- flag = TTY_BREAK;
- else if (data & RxParityError)
- flag = TTY_PARITY;
- else if (data & RxFramingError)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char (port, (unsigned char) data))
- continue;
-
- uart_insert_char(port, data, RxOverrunError, data, flag);
- }
- tty_flip_buffer_push (tty);
- return;
-}
-
-static void lh7a40xuart_tx_chars (struct uart_port* port)
-{
- struct circ_buf* xmit = &port->state->xmit;
- int cbTxMax = port->fifosize;
-
- if (port->x_char) {
- UR (port, UART_R_DATA) = port->x_char;
- ++port->icount.tx;
- port->x_char = 0;
- return;
- }
- if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
- lh7a40xuart_stop_tx (port);
- return;
- }
-
- /* Unlike the AMBA UART, the lh7a40x UART does not guarantee
- that at least half of the FIFO is empty. Instead, we check
- status for every character. Using the AMBA method causes
- the transmitter to drop characters. */
-
- do {
- UR (port, UART_R_DATA) = xmit->buf[xmit->tail];
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- ++port->icount.tx;
- if (uart_circ_empty(xmit))
- break;
- } while (!(UR (port, UART_R_STATUS) & nTxRdy)
- && cbTxMax--);
-
- if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
- uart_write_wakeup (port);
-
- if (uart_circ_empty (xmit))
- lh7a40xuart_stop_tx (port);
-}
-
-static void lh7a40xuart_modem_status (struct uart_port* port)
-{
- unsigned int status = UR (port, UART_R_STATUS);
- unsigned int delta
- = status ^ ((struct uart_port_lh7a40x*) port)->statusPrev;
-
- BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */
-
- if (!delta) /* Only happens if we missed 2 transitions */
- return;
-
- ((struct uart_port_lh7a40x*) port)->statusPrev = status;
-
- if (delta & DCD)
- uart_handle_dcd_change (port, status & DCD);
-
- if (delta & DSR)
- ++port->icount.dsr;
-
- if (delta & CTS)
- uart_handle_cts_change (port, status & CTS);
-
- wake_up_interruptible (&port->state->port.delta_msr_wait);
-}
-
-static irqreturn_t lh7a40xuart_int (int irq, void* dev_id)
-{
- struct uart_port* port = dev_id;
- unsigned int cLoopLimit = ISR_LOOP_LIMIT;
- unsigned int isr = UR (port, UART_R_ISR);
-
-
- do {
- if (isr & (RxInt | RxTimeoutInt))
- lh7a40xuart_rx_chars(port);
- if (isr & ModemInt)
- lh7a40xuart_modem_status (port);
- if (isr & TxInt)
- lh7a40xuart_tx_chars (port);
-
- if (--cLoopLimit == 0)
- break;
-
- isr = UR (port, UART_R_ISR);
- } while (isr & (RxInt | TxInt | RxTimeoutInt));
-
- return IRQ_HANDLED;
-}
-
-static unsigned int lh7a40xuart_tx_empty (struct uart_port* port)
-{
- return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port)
-{
- unsigned int result = 0;
- unsigned int status = UR (port, UART_R_STATUS);
-
- if (status & DCD)
- result |= TIOCM_CAR;
- if (status & DSR)
- result |= TIOCM_DSR;
- if (status & CTS)
- result |= TIOCM_CTS;
-
- return result;
-}
-
-static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl)
-{
- /* None of the ports supports DTR. UART1 supports RTS through GPIO. */
- /* Note, kernel appears to be setting DTR and RTS on console. */
-
- /* *** FIXME: this deserves more work. There's some work in
- tracing all of the IO pins. */
-#if 0
- if( port->mapbase == UART1_PHYS) {
- gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
-
- if (mctrl & TIOCM_RTS)
- gpio->pbdr &= ~GPIOB_UART1_RTS;
- else
- gpio->pbdr |= GPIOB_UART1_RTS;
- }
-#endif
-}
-
-static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- if (break_state == -1)
- BIT_SET (port, UART_R_FCON, BRK); /* Assert break */
- else
- BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int lh7a40xuart_startup (struct uart_port* port)
-{
- int retval;
-
- retval = request_irq (port->irq, lh7a40xuart_int, 0,
- "serial_lh7a40x", port);
- if (retval)
- return retval;
-
- /* Initial modem control-line settings */
- ((struct uart_port_lh7a40x*) port)->statusPrev
- = UR (port, UART_R_STATUS);
-
- /* There is presently no configuration option to enable IR.
- Thus, we always disable it. */
-
- BIT_SET (port, UART_R_CON, UARTEN | SIRDIS);
- BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
-
- return 0;
-}
-
-static void lh7a40xuart_shutdown (struct uart_port* port)
-{
- free_irq (port->irq, port);
- BIT_CLR (port, UART_R_FCON, BRK | FEN);
- BIT_CLR (port, UART_R_CON, UARTEN);
-}
-
-static void lh7a40xuart_set_termios (struct uart_port* port,
- struct ktermios* termios,
- struct ktermios* old)
-{
- unsigned int con;
- unsigned int inten;
- unsigned int fcon;
- unsigned long flags;
- unsigned int baud;
- unsigned int quot;
-
- baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16);
- quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- fcon = WLEN_5;
- break;
- case CS6:
- fcon = WLEN_6;
- break;
- case CS7:
- fcon = WLEN_7;
- break;
- case CS8:
- default:
- fcon = WLEN_8;
- break;
- }
- if (termios->c_cflag & CSTOPB)
- fcon |= STP2;
- if (termios->c_cflag & PARENB) {
- fcon |= PEN;
- if (!(termios->c_cflag & PARODD))
- fcon |= EPS;
- }
- if (port->fifosize > 1)
- fcon |= FEN;
-
- spin_lock_irqsave (&port->lock, flags);
-
- uart_update_timeout (port, termios->c_cflag, baud);
-
- port->read_status_mask = RxOverrunError;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= RxFramingError | RxParityError;
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= RxBreak;
-
- /* Figure mask for status we ignore */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= RxFramingError | RxParityError;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= RxBreak;
- /* Ignore overrun when ignorning parity */
- /* *** FIXME: is this in the right place? */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= RxOverrunError;
- }
-
- /* Ignore all receive errors when receive disabled */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= RxError;
-
- con = UR (port, UART_R_CON);
- inten = (UR (port, UART_R_INTEN) & ~ModemInt);
-
- if (UART_ENABLE_MS (port, termios->c_cflag))
- inten |= ModemInt;
-
- BIT_CLR (port, UART_R_CON, UARTEN); /* Disable UART */
- UR (port, UART_R_INTEN) = 0; /* Disable interrupts */
- UR (port, UART_R_BRCON) = quot - 1; /* Set baud rate divisor */
- UR (port, UART_R_FCON) = fcon; /* Set FIFO and frame ctrl */
- UR (port, UART_R_INTEN) = inten; /* Enable interrupts */
- UR (port, UART_R_CON) = con; /* Restore UART mode */
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char* lh7a40xuart_type (struct uart_port* port)
-{
- return port->type == PORT_LH7A40X ? "LH7A40X" : NULL;
-}
-
-static void lh7a40xuart_release_port (struct uart_port* port)
-{
- release_mem_region (port->mapbase, UART_REG_SIZE);
-}
-
-static int lh7a40xuart_request_port (struct uart_port* port)
-{
- return request_mem_region (port->mapbase, UART_REG_SIZE,
- "serial_lh7a40x") != NULL
- ? 0 : -EBUSY;
-}
-
-static void lh7a40xuart_config_port (struct uart_port* port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_LH7A40X;
- lh7a40xuart_request_port (port);
- }
-}
-
-static int lh7a40xuart_verify_port (struct uart_port* port,
- struct serial_struct* ser)
-{
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
- ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
- ret = -EINVAL;
- if (ser->baud_base < 9600) /* *** FIXME: is this true? */
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops lh7a40x_uart_ops = {
- .tx_empty = lh7a40xuart_tx_empty,
- .set_mctrl = lh7a40xuart_set_mctrl,
- .get_mctrl = lh7a40xuart_get_mctrl,
- .stop_tx = lh7a40xuart_stop_tx,
- .start_tx = lh7a40xuart_start_tx,
- .stop_rx = lh7a40xuart_stop_rx,
- .enable_ms = lh7a40xuart_enable_ms,
- .break_ctl = lh7a40xuart_break_ctl,
- .startup = lh7a40xuart_startup,
- .shutdown = lh7a40xuart_shutdown,
- .set_termios = lh7a40xuart_set_termios,
- .type = lh7a40xuart_type,
- .release_port = lh7a40xuart_release_port,
- .request_port = lh7a40xuart_request_port,
- .config_port = lh7a40xuart_config_port,
- .verify_port = lh7a40xuart_verify_port,
-};
-
-static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
- {
- .port = {
- .membase = (void*) io_p2v (UART1_PHYS),
- .mapbase = UART1_PHYS,
- .iotype = UPIO_MEM,
- .irq = IRQ_UART1INTR,
- .uartclk = 14745600/2,
- .fifosize = 16,
- .ops = &lh7a40x_uart_ops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 0,
- },
- },
- {
- .port = {
- .membase = (void*) io_p2v (UART2_PHYS),
- .mapbase = UART2_PHYS,
- .iotype = UPIO_MEM,
- .irq = IRQ_UART2INTR,
- .uartclk = 14745600/2,
- .fifosize = 16,
- .ops = &lh7a40x_uart_ops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 1,
- },
- },
- {
- .port = {
- .membase = (void*) io_p2v (UART3_PHYS),
- .mapbase = UART3_PHYS,
- .iotype = UPIO_MEM,
- .irq = IRQ_UART3INTR,
- .uartclk = 14745600/2,
- .fifosize = 16,
- .ops = &lh7a40x_uart_ops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 2,
- },
- },
-};
-
-#ifndef CONFIG_SERIAL_LH7A40X_CONSOLE
-# define LH7A40X_CONSOLE NULL
-#else
-# define LH7A40X_CONSOLE &lh7a40x_console
-
-static void lh7a40xuart_console_putchar(struct uart_port *port, int ch)
-{
- while (UR(port, UART_R_STATUS) & nTxRdy)
- ;
- UR(port, UART_R_DATA) = ch;
-}
-
-static void lh7a40xuart_console_write (struct console* co,
- const char* s,
- unsigned int count)
-{
- struct uart_port* port = &lh7a40x_ports[co->index].port;
- unsigned int con = UR (port, UART_R_CON);
- unsigned int inten = UR (port, UART_R_INTEN);
-
-
- UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */
- BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */
-
- uart_console_write(port, s, count, lh7a40xuart_console_putchar);
-
- /* Wait until all characters are sent */
- while (UR (port, UART_R_STATUS) & TxBusy)
- ;
-
- /* Restore control and interrupt mask */
- UR (port, UART_R_CON) = con;
- UR (port, UART_R_INTEN) = inten;
-}
-
-static void __init lh7a40xuart_console_get_options (struct uart_port* port,
- int* baud,
- int* parity,
- int* bits)
-{
- if (UR (port, UART_R_CON) & UARTEN) {
- unsigned int fcon = UR (port, UART_R_FCON);
- unsigned int quot = UR (port, UART_R_BRCON) + 1;
-
- switch (fcon & (PEN | EPS)) {
- default: *parity = 'n'; break;
- case PEN: *parity = 'o'; break;
- case PEN | EPS: *parity = 'e'; break;
- }
-
- switch (fcon & WLEN) {
- default:
- case WLEN_8: *bits = 8; break;
- case WLEN_7: *bits = 7; break;
- case WLEN_6: *bits = 6; break;
- case WLEN_5: *bits = 5; break;
- }
-
- *baud = port->uartclk/(16*quot);
- }
-}
-
-static int __init lh7a40xuart_console_setup (struct console* co, char* options)
-{
- struct uart_port* port;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (co->index >= DEV_NR) /* Bounds check on device number */
- co->index = 0;
- port = &lh7a40x_ports[co->index].port;
-
- if (options)
- uart_parse_options (options, &baud, &parity, &bits, &flow);
- else
- lh7a40xuart_console_get_options (port, &baud, &parity, &bits);
-
- return uart_set_options (port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver lh7a40x_reg;
-static struct console lh7a40x_console = {
- .name = "ttyAM",
- .write = lh7a40xuart_console_write,
- .device = uart_console_device,
- .setup = lh7a40xuart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &lh7a40x_reg,
-};
-
-static int __init lh7a40xuart_console_init(void)
-{
- register_console (&lh7a40x_console);
- return 0;
-}
-
-console_initcall (lh7a40xuart_console_init);
-
-#endif
-
-static struct uart_driver lh7a40x_reg = {
- .owner = THIS_MODULE,
- .driver_name = "ttyAM",
- .dev_name = "ttyAM",
- .major = DEV_MAJOR,
- .minor = DEV_MINOR,
- .nr = DEV_NR,
- .cons = LH7A40X_CONSOLE,
-};
-
-static int __init lh7a40xuart_init(void)
-{
- int ret;
-
- printk (KERN_INFO "serial: LH7A40X serial driver\n");
-
- ret = uart_register_driver (&lh7a40x_reg);
-
- if (ret == 0) {
- int i;
-
- for (i = 0; i < DEV_NR; i++) {
- /* UART3, when used, requires GPIO pin reallocation */
- if (lh7a40x_ports[i].port.mapbase == UART3_PHYS)
- GPIO_PINMUX |= 1<<3;
- uart_add_one_port (&lh7a40x_reg,
- &lh7a40x_ports[i].port);
- }
- }
- return ret;
-}
-
-static void __exit lh7a40xuart_exit(void)
-{
- int i;
-
- for (i = 0; i < DEV_NR; i++)
- uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port);
-
- uart_unregister_driver (&lh7a40x_reg);
-}
-
-module_init (lh7a40xuart_init);
-module_exit (lh7a40xuart_exit);
-
-MODULE_AUTHOR ("Marc Singer");
-MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver");
-MODULE_LICENSE ("GPL");
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
deleted file mode 100644
index c50e9fbbf743..000000000000
--- a/drivers/serial/serial_txx9.c
+++ /dev/null
@@ -1,1344 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 1999 Harald Koerfgen
- * Copyright (C) 2000 Jim Pick <jim@jimpick.com>
- * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
- * Copyright (C) 2000-2002 Toshiba Corporation
- *
- * 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.
- *
- * Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller
- */
-
-#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-
-static char *serial_version = "1.11";
-static char *serial_name = "TX39/49 Serial driver";
-
-#define PASS_LIMIT 256
-
-#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
-/* "ttyS" is used for standard serial driver */
-#define TXX9_TTY_NAME "ttyTX"
-#define TXX9_TTY_MINOR_START 196
-#define TXX9_TTY_MAJOR 204
-#else
-/* acts like standard serial driver */
-#define TXX9_TTY_NAME "ttyS"
-#define TXX9_TTY_MINOR_START 64
-#define TXX9_TTY_MAJOR TTY_MAJOR
-#endif
-
-/* flag aliases */
-#define UPF_TXX9_HAVE_CTS_LINE UPF_BUGGY_UART
-#define UPF_TXX9_USE_SCLK UPF_MAGIC_MULTIPLIER
-
-#ifdef CONFIG_PCI
-/* support for Toshiba TC86C001 SIO */
-#define ENABLE_SERIAL_TXX9_PCI
-#endif
-
-/*
- * Number of serial ports
- */
-#define UART_NR CONFIG_SERIAL_TXX9_NR_UARTS
-
-struct uart_txx9_port {
- struct uart_port port;
- /* No additional info for now */
-};
-
-#define TXX9_REGION_SIZE 0x24
-
-/* TXX9 Serial Registers */
-#define TXX9_SILCR 0x00
-#define TXX9_SIDICR 0x04
-#define TXX9_SIDISR 0x08
-#define TXX9_SICISR 0x0c
-#define TXX9_SIFCR 0x10
-#define TXX9_SIFLCR 0x14
-#define TXX9_SIBGR 0x18
-#define TXX9_SITFIFO 0x1c
-#define TXX9_SIRFIFO 0x20
-
-/* SILCR : Line Control */
-#define TXX9_SILCR_SCS_MASK 0x00000060
-#define TXX9_SILCR_SCS_IMCLK 0x00000000
-#define TXX9_SILCR_SCS_IMCLK_BG 0x00000020
-#define TXX9_SILCR_SCS_SCLK 0x00000040
-#define TXX9_SILCR_SCS_SCLK_BG 0x00000060
-#define TXX9_SILCR_UEPS 0x00000010
-#define TXX9_SILCR_UPEN 0x00000008
-#define TXX9_SILCR_USBL_MASK 0x00000004
-#define TXX9_SILCR_USBL_1BIT 0x00000000
-#define TXX9_SILCR_USBL_2BIT 0x00000004
-#define TXX9_SILCR_UMODE_MASK 0x00000003
-#define TXX9_SILCR_UMODE_8BIT 0x00000000
-#define TXX9_SILCR_UMODE_7BIT 0x00000001
-
-/* SIDICR : DMA/Int. Control */
-#define TXX9_SIDICR_TDE 0x00008000
-#define TXX9_SIDICR_RDE 0x00004000
-#define TXX9_SIDICR_TIE 0x00002000
-#define TXX9_SIDICR_RIE 0x00001000
-#define TXX9_SIDICR_SPIE 0x00000800
-#define TXX9_SIDICR_CTSAC 0x00000600
-#define TXX9_SIDICR_STIE_MASK 0x0000003f
-#define TXX9_SIDICR_STIE_OERS 0x00000020
-#define TXX9_SIDICR_STIE_CTSS 0x00000010
-#define TXX9_SIDICR_STIE_RBRKD 0x00000008
-#define TXX9_SIDICR_STIE_TRDY 0x00000004
-#define TXX9_SIDICR_STIE_TXALS 0x00000002
-#define TXX9_SIDICR_STIE_UBRKD 0x00000001
-
-/* SIDISR : DMA/Int. Status */
-#define TXX9_SIDISR_UBRK 0x00008000
-#define TXX9_SIDISR_UVALID 0x00004000
-#define TXX9_SIDISR_UFER 0x00002000
-#define TXX9_SIDISR_UPER 0x00001000
-#define TXX9_SIDISR_UOER 0x00000800
-#define TXX9_SIDISR_ERI 0x00000400
-#define TXX9_SIDISR_TOUT 0x00000200
-#define TXX9_SIDISR_TDIS 0x00000100
-#define TXX9_SIDISR_RDIS 0x00000080
-#define TXX9_SIDISR_STIS 0x00000040
-#define TXX9_SIDISR_RFDN_MASK 0x0000001f
-
-/* SICISR : Change Int. Status */
-#define TXX9_SICISR_OERS 0x00000020
-#define TXX9_SICISR_CTSS 0x00000010
-#define TXX9_SICISR_RBRKD 0x00000008
-#define TXX9_SICISR_TRDY 0x00000004
-#define TXX9_SICISR_TXALS 0x00000002
-#define TXX9_SICISR_UBRKD 0x00000001
-
-/* SIFCR : FIFO Control */
-#define TXX9_SIFCR_SWRST 0x00008000
-#define TXX9_SIFCR_RDIL_MASK 0x00000180
-#define TXX9_SIFCR_RDIL_1 0x00000000
-#define TXX9_SIFCR_RDIL_4 0x00000080
-#define TXX9_SIFCR_RDIL_8 0x00000100
-#define TXX9_SIFCR_RDIL_12 0x00000180
-#define TXX9_SIFCR_RDIL_MAX 0x00000180
-#define TXX9_SIFCR_TDIL_MASK 0x00000018
-#define TXX9_SIFCR_TDIL_MASK 0x00000018
-#define TXX9_SIFCR_TDIL_1 0x00000000
-#define TXX9_SIFCR_TDIL_4 0x00000001
-#define TXX9_SIFCR_TDIL_8 0x00000010
-#define TXX9_SIFCR_TDIL_MAX 0x00000010
-#define TXX9_SIFCR_TFRST 0x00000004
-#define TXX9_SIFCR_RFRST 0x00000002
-#define TXX9_SIFCR_FRSTE 0x00000001
-#define TXX9_SIO_TX_FIFO 8
-#define TXX9_SIO_RX_FIFO 16
-
-/* SIFLCR : Flow Control */
-#define TXX9_SIFLCR_RCS 0x00001000
-#define TXX9_SIFLCR_TES 0x00000800
-#define TXX9_SIFLCR_RTSSC 0x00000200
-#define TXX9_SIFLCR_RSDE 0x00000100
-#define TXX9_SIFLCR_TSDE 0x00000080
-#define TXX9_SIFLCR_RTSTL_MASK 0x0000001e
-#define TXX9_SIFLCR_RTSTL_MAX 0x0000001e
-#define TXX9_SIFLCR_TBRK 0x00000001
-
-/* SIBGR : Baudrate Control */
-#define TXX9_SIBGR_BCLK_MASK 0x00000300
-#define TXX9_SIBGR_BCLK_T0 0x00000000
-#define TXX9_SIBGR_BCLK_T2 0x00000100
-#define TXX9_SIBGR_BCLK_T4 0x00000200
-#define TXX9_SIBGR_BCLK_T6 0x00000300
-#define TXX9_SIBGR_BRD_MASK 0x000000ff
-
-static inline unsigned int sio_in(struct uart_txx9_port *up, int offset)
-{
- switch (up->port.iotype) {
- default:
- return __raw_readl(up->port.membase + offset);
- case UPIO_PORT:
- return inl(up->port.iobase + offset);
- }
-}
-
-static inline void
-sio_out(struct uart_txx9_port *up, int offset, int value)
-{
- switch (up->port.iotype) {
- default:
- __raw_writel(value, up->port.membase + offset);
- break;
- case UPIO_PORT:
- outl(value, up->port.iobase + offset);
- break;
- }
-}
-
-static inline void
-sio_mask(struct uart_txx9_port *up, int offset, unsigned int value)
-{
- sio_out(up, offset, sio_in(up, offset) & ~value);
-}
-static inline void
-sio_set(struct uart_txx9_port *up, int offset, unsigned int value)
-{
- sio_out(up, offset, sio_in(up, offset) | value);
-}
-
-static inline void
-sio_quot_set(struct uart_txx9_port *up, int quot)
-{
- quot >>= 1;
- if (quot < 256)
- sio_out(up, TXX9_SIBGR, quot | TXX9_SIBGR_BCLK_T0);
- else if (quot < (256 << 2))
- sio_out(up, TXX9_SIBGR, (quot >> 2) | TXX9_SIBGR_BCLK_T2);
- else if (quot < (256 << 4))
- sio_out(up, TXX9_SIBGR, (quot >> 4) | TXX9_SIBGR_BCLK_T4);
- else if (quot < (256 << 6))
- sio_out(up, TXX9_SIBGR, (quot >> 6) | TXX9_SIBGR_BCLK_T6);
- else
- sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
-}
-
-static struct uart_txx9_port *to_uart_txx9_port(struct uart_port *port)
-{
- return container_of(port, struct uart_txx9_port, port);
-}
-
-static void serial_txx9_stop_tx(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
-}
-
-static void serial_txx9_start_tx(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
-}
-
-static void serial_txx9_stop_rx(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
-}
-
-static void serial_txx9_enable_ms(struct uart_port *port)
-{
- /* TXX9-SIO can not control DTR... */
-}
-
-static void serial_txx9_initialize(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- unsigned int tmout = 10000;
-
- sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
- /* TX4925 BUG WORKAROUND. Accessing SIOC register
- * immediately after soft reset causes bus error. */
- mmiowb();
- udelay(1);
- while ((sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) && --tmout)
- udelay(1);
- /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
- sio_set(up, TXX9_SIFCR,
- TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
- /* initial settings */
- sio_out(up, TXX9_SILCR,
- TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
- ((up->port.flags & UPF_TXX9_USE_SCLK) ?
- TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
- sio_quot_set(up, uart_get_divisor(port, 9600));
- sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
- sio_out(up, TXX9_SIDICR, 0);
-}
-
-static inline void
-receive_chars(struct uart_txx9_port *up, unsigned int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned char ch;
- unsigned int disr = *status;
- int max_count = 256;
- char flag;
- unsigned int next_ignore_status_mask;
-
- do {
- ch = sio_in(up, TXX9_SIRFIFO);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- /* mask out RFDN_MASK bit added by previous overrun */
- next_ignore_status_mask =
- up->port.ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK;
- if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER |
- TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) {
- /*
- * For statistics only
- */
- if (disr & TXX9_SIDISR_UBRK) {
- disr &= ~(TXX9_SIDISR_UFER | TXX9_SIDISR_UPER);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (disr & TXX9_SIDISR_UPER)
- up->port.icount.parity++;
- else if (disr & TXX9_SIDISR_UFER)
- up->port.icount.frame++;
- if (disr & TXX9_SIDISR_UOER) {
- up->port.icount.overrun++;
- /*
- * The receiver read buffer still hold
- * a char which caused overrun.
- * Ignore next char by adding RFDN_MASK
- * to ignore_status_mask temporarily.
- */
- next_ignore_status_mask |=
- TXX9_SIDISR_RFDN_MASK;
- }
-
- /*
- * Mask off conditions which should be ingored.
- */
- disr &= up->port.read_status_mask;
-
- if (disr & TXX9_SIDISR_UBRK) {
- flag = TTY_BREAK;
- } else if (disr & TXX9_SIDISR_UPER)
- flag = TTY_PARITY;
- else if (disr & TXX9_SIDISR_UFER)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
-
- uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
-
- ignore_char:
- up->port.ignore_status_mask = next_ignore_status_mask;
- disr = sio_in(up, TXX9_SIDISR);
- } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
- *status = disr;
-}
-
-static inline void transmit_chars(struct uart_txx9_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
- sio_out(up, TXX9_SITFIFO, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_txx9_stop_tx(&up->port);
- return;
- }
-
- count = TXX9_SIO_TX_FIFO;
- do {
- sio_out(up, TXX9_SITFIFO, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit))
- serial_txx9_stop_tx(&up->port);
-}
-
-static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
-{
- int pass_counter = 0;
- struct uart_txx9_port *up = dev_id;
- unsigned int status;
-
- while (1) {
- spin_lock(&up->port.lock);
- status = sio_in(up, TXX9_SIDISR);
- if (!(sio_in(up, TXX9_SIDICR) & TXX9_SIDICR_TIE))
- status &= ~TXX9_SIDISR_TDIS;
- if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
- TXX9_SIDISR_TOUT))) {
- spin_unlock(&up->port.lock);
- break;
- }
-
- if (status & TXX9_SIDISR_RDIS)
- receive_chars(up, &status);
- if (status & TXX9_SIDISR_TDIS)
- transmit_chars(up);
- /* Clear TX/RX Int. Status */
- sio_mask(up, TXX9_SIDISR,
- TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
- TXX9_SIDISR_TOUT);
- spin_unlock(&up->port.lock);
-
- if (pass_counter++ > PASS_LIMIT)
- break;
- }
-
- return pass_counter ? IRQ_HANDLED : IRQ_NONE;
-}
-
-static unsigned int serial_txx9_tx_empty(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = (sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS) ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- unsigned int ret;
-
- /* no modem control lines */
- ret = TIOCM_CAR | TIOCM_DSR;
- ret |= (sio_in(up, TXX9_SIFLCR) & TXX9_SIFLCR_RTSSC) ? 0 : TIOCM_RTS;
- ret |= (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS) ? 0 : TIOCM_CTS;
-
- return ret;
-}
-
-static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
-
- if (mctrl & TIOCM_RTS)
- sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
- else
- sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
-}
-
-static void serial_txx9_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
- else
- sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-#if defined(CONFIG_SERIAL_TXX9_CONSOLE) || (CONFIG_CONSOLE_POLL)
-/*
- * Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_txx9_port *up)
-{
- unsigned int tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- while (--tmout &&
- !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS))
- udelay(1);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS))
- udelay(1);
- }
-}
-#endif
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial_txx9_get_poll_char(struct uart_port *port)
-{
- unsigned int ier;
- unsigned char c;
- struct uart_txx9_port *up = to_uart_txx9_port(port);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = sio_in(up, TXX9_SIDICR);
- sio_out(up, TXX9_SIDICR, 0);
-
- while (sio_in(up, TXX9_SIDISR) & TXX9_SIDISR_UVALID)
- ;
-
- c = sio_in(up, TXX9_SIRFIFO);
-
- /*
- * Finally, clear RX interrupt status
- * and restore the IER
- */
- sio_mask(up, TXX9_SIDISR, TXX9_SIDISR_RDIS);
- sio_out(up, TXX9_SIDICR, ier);
- return c;
-}
-
-
-static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
-{
- unsigned int ier;
- struct uart_txx9_port *up = to_uart_txx9_port(port);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = sio_in(up, TXX9_SIDICR);
- sio_out(up, TXX9_SIDICR, 0);
-
- wait_for_xmitr(up);
- /*
- * Send the character out.
- * If a LF, also do CR...
- */
- sio_out(up, TXX9_SITFIFO, c);
- if (c == 10) {
- wait_for_xmitr(up);
- sio_out(up, TXX9_SITFIFO, 13);
- }
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- sio_out(up, TXX9_SIDICR, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int serial_txx9_startup(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- unsigned long flags;
- int retval;
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- sio_set(up, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
- /* clear reset */
- sio_mask(up, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
- sio_out(up, TXX9_SIDICR, 0);
-
- /*
- * Clear the interrupt registers.
- */
- sio_out(up, TXX9_SIDISR, 0);
-
- retval = request_irq(up->port.irq, serial_txx9_interrupt,
- IRQF_SHARED, "serial_txx9", up);
- if (retval)
- return retval;
-
- /*
- * Now, initialize the UART
- */
- spin_lock_irqsave(&up->port.lock, flags);
- serial_txx9_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /* Enable RX/TX */
- sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
-
- /*
- * Finally, enable interrupts.
- */
- sio_set(up, TXX9_SIDICR, TXX9_SIDICR_RIE);
-
- return 0;
-}
-
-static void serial_txx9_shutdown(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- unsigned long flags;
-
- /*
- * Disable interrupts from this port
- */
- sio_out(up, TXX9_SIDICR, 0); /* disable all intrs */
-
- spin_lock_irqsave(&up->port.lock, flags);
- serial_txx9_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition
- */
- sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
-
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
- if (up->port.cons && up->port.line == up->port.cons->index) {
- free_irq(up->port.irq, up);
- return;
- }
-#endif
- /* reset FIFOs */
- sio_set(up, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
- /* clear reset */
- sio_mask(up, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
-
- /* Disable RX/TX */
- sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
-
- free_irq(up->port.irq, up);
-}
-
-static void
-serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- unsigned int cval, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- /*
- * We don't support modem control lines.
- */
- termios->c_cflag &= ~(HUPCL | CMSPAR);
- termios->c_cflag |= CLOCAL;
-
- cval = sio_in(up, TXX9_SILCR);
- /* byte size and parity */
- cval &= ~TXX9_SILCR_UMODE_MASK;
- switch (termios->c_cflag & CSIZE) {
- case CS7:
- cval |= TXX9_SILCR_UMODE_7BIT;
- break;
- default:
- case CS5: /* not supported */
- case CS6: /* not supported */
- case CS8:
- cval |= TXX9_SILCR_UMODE_8BIT;
- break;
- }
-
- cval &= ~TXX9_SILCR_USBL_MASK;
- if (termios->c_cflag & CSTOPB)
- cval |= TXX9_SILCR_USBL_2BIT;
- else
- cval |= TXX9_SILCR_USBL_1BIT;
- cval &= ~(TXX9_SILCR_UPEN | TXX9_SILCR_UEPS);
- if (termios->c_cflag & PARENB)
- cval |= TXX9_SILCR_UPEN;
- if (!(termios->c_cflag & PARODD))
- cval |= TXX9_SILCR_UEPS;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16/2);
- quot = uart_get_divisor(port, baud);
-
- /* Set up FIFOs */
- /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
- fcr = TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1;
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = TXX9_SIDISR_UOER |
- TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= TXX9_SIDISR_UFER | TXX9_SIDISR_UPER;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= TXX9_SIDISR_UBRK;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= TXX9_SIDISR_UPER | TXX9_SIDISR_UFER;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= TXX9_SIDISR_UBRK;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= TXX9_SIDISR_UOER;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= TXX9_SIDISR_RDIS;
-
- /* CTS flow control flag */
- if ((termios->c_cflag & CRTSCTS) &&
- (up->port.flags & UPF_TXX9_HAVE_CTS_LINE)) {
- sio_set(up, TXX9_SIFLCR,
- TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
- } else {
- sio_mask(up, TXX9_SIFLCR,
- TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
- }
-
- sio_out(up, TXX9_SILCR, cval);
- sio_quot_set(up, quot);
- sio_out(up, TXX9_SIFCR, fcr);
-
- serial_txx9_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_txx9_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- /*
- * If oldstate was -1 this is called from
- * uart_configure_port(). In this case do not initialize the
- * port now, because the port was already initialized (for
- * non-console port) or should not be initialized here (for
- * console port). If we initialized the port here we lose
- * serial console settings.
- */
- if (state == 0 && oldstate != -1)
- serial_txx9_initialize(port);
-}
-
-static int serial_txx9_request_resource(struct uart_txx9_port *up)
-{
- unsigned int size = TXX9_REGION_SIZE;
- int ret = 0;
-
- switch (up->port.iotype) {
- default:
- if (!up->port.mapbase)
- break;
-
- if (!request_mem_region(up->port.mapbase, size, "serial_txx9")) {
- ret = -EBUSY;
- break;
- }
-
- if (up->port.flags & UPF_IOREMAP) {
- up->port.membase = ioremap(up->port.mapbase, size);
- if (!up->port.membase) {
- release_mem_region(up->port.mapbase, size);
- ret = -ENOMEM;
- }
- }
- break;
-
- case UPIO_PORT:
- if (!request_region(up->port.iobase, size, "serial_txx9"))
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-static void serial_txx9_release_resource(struct uart_txx9_port *up)
-{
- unsigned int size = TXX9_REGION_SIZE;
-
- switch (up->port.iotype) {
- default:
- if (!up->port.mapbase)
- break;
-
- if (up->port.flags & UPF_IOREMAP) {
- iounmap(up->port.membase);
- up->port.membase = NULL;
- }
-
- release_mem_region(up->port.mapbase, size);
- break;
-
- case UPIO_PORT:
- release_region(up->port.iobase, size);
- break;
- }
-}
-
-static void serial_txx9_release_port(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- serial_txx9_release_resource(up);
-}
-
-static int serial_txx9_request_port(struct uart_port *port)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- return serial_txx9_request_resource(up);
-}
-
-static void serial_txx9_config_port(struct uart_port *port, int uflags)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
- int ret;
-
- /*
- * Find the region that we can probe for. This in turn
- * tells us whether we can probe for the type of port.
- */
- ret = serial_txx9_request_resource(up);
- if (ret < 0)
- return;
- port->type = PORT_TXX9;
- up->port.fifosize = TXX9_SIO_TX_FIFO;
-
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
- if (up->port.line == up->port.cons->index)
- return;
-#endif
- serial_txx9_initialize(port);
-}
-
-static const char *
-serial_txx9_type(struct uart_port *port)
-{
- return "txx9";
-}
-
-static struct uart_ops serial_txx9_pops = {
- .tx_empty = serial_txx9_tx_empty,
- .set_mctrl = serial_txx9_set_mctrl,
- .get_mctrl = serial_txx9_get_mctrl,
- .stop_tx = serial_txx9_stop_tx,
- .start_tx = serial_txx9_start_tx,
- .stop_rx = serial_txx9_stop_rx,
- .enable_ms = serial_txx9_enable_ms,
- .break_ctl = serial_txx9_break_ctl,
- .startup = serial_txx9_startup,
- .shutdown = serial_txx9_shutdown,
- .set_termios = serial_txx9_set_termios,
- .pm = serial_txx9_pm,
- .type = serial_txx9_type,
- .release_port = serial_txx9_release_port,
- .request_port = serial_txx9_request_port,
- .config_port = serial_txx9_config_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = serial_txx9_get_poll_char,
- .poll_put_char = serial_txx9_put_poll_char,
-#endif
-};
-
-static struct uart_txx9_port serial_txx9_ports[UART_NR];
-
-static void __init serial_txx9_register_ports(struct uart_driver *drv,
- struct device *dev)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_txx9_port *up = &serial_txx9_ports[i];
-
- up->port.line = i;
- up->port.ops = &serial_txx9_pops;
- up->port.dev = dev;
- if (up->port.iobase || up->port.mapbase)
- uart_add_one_port(drv, &up->port);
- }
-}
-
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
-
-static void serial_txx9_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_txx9_port *up = to_uart_txx9_port(port);
-
- wait_for_xmitr(up);
- sio_out(up, TXX9_SITFIFO, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void
-serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_txx9_port *up = &serial_txx9_ports[co->index];
- unsigned int ier, flcr;
-
- /*
- * First save the UER then disable the interrupts
- */
- ier = sio_in(up, TXX9_SIDICR);
- sio_out(up, TXX9_SIDICR, 0);
- /*
- * Disable flow-control if enabled (and unnecessary)
- */
- flcr = sio_in(up, TXX9_SIFLCR);
- if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
- sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
-
- uart_console_write(&up->port, s, count, serial_txx9_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- sio_out(up, TXX9_SIFLCR, flcr);
- sio_out(up, TXX9_SIDICR, ier);
-}
-
-static int __init serial_txx9_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- struct uart_txx9_port *up;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- up = &serial_txx9_ports[co->index];
- port = &up->port;
- if (!port->ops)
- return -ENODEV;
-
- serial_txx9_initialize(&up->port);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver serial_txx9_reg;
-static struct console serial_txx9_console = {
- .name = TXX9_TTY_NAME,
- .write = serial_txx9_console_write,
- .device = uart_console_device,
- .setup = serial_txx9_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &serial_txx9_reg,
-};
-
-static int __init serial_txx9_console_init(void)
-{
- register_console(&serial_txx9_console);
- return 0;
-}
-console_initcall(serial_txx9_console_init);
-
-#define SERIAL_TXX9_CONSOLE &serial_txx9_console
-#else
-#define SERIAL_TXX9_CONSOLE NULL
-#endif
-
-static struct uart_driver serial_txx9_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial_txx9",
- .dev_name = TXX9_TTY_NAME,
- .major = TXX9_TTY_MAJOR,
- .minor = TXX9_TTY_MINOR_START,
- .nr = UART_NR,
- .cons = SERIAL_TXX9_CONSOLE,
-};
-
-int __init early_serial_txx9_setup(struct uart_port *port)
-{
- if (port->line >= ARRAY_SIZE(serial_txx9_ports))
- return -ENODEV;
-
- serial_txx9_ports[port->line].port = *port;
- serial_txx9_ports[port->line].port.ops = &serial_txx9_pops;
- serial_txx9_ports[port->line].port.flags |=
- UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
- return 0;
-}
-
-static DEFINE_MUTEX(serial_txx9_mutex);
-
-/**
- * serial_txx9_register_port - register a serial port
- * @port: serial port template
- *
- * Configure the serial port specified by the request.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- */
-static int __devinit serial_txx9_register_port(struct uart_port *port)
-{
- int i;
- struct uart_txx9_port *uart;
- int ret = -ENOSPC;
-
- mutex_lock(&serial_txx9_mutex);
- for (i = 0; i < UART_NR; i++) {
- uart = &serial_txx9_ports[i];
- if (uart_match_port(&uart->port, port)) {
- uart_remove_one_port(&serial_txx9_reg, &uart->port);
- break;
- }
- }
- if (i == UART_NR) {
- /* Find unused port */
- for (i = 0; i < UART_NR; i++) {
- uart = &serial_txx9_ports[i];
- if (!(uart->port.iobase || uart->port.mapbase))
- break;
- }
- }
- if (i < UART_NR) {
- uart->port.iobase = port->iobase;
- uart->port.membase = port->membase;
- uart->port.irq = port->irq;
- uart->port.uartclk = port->uartclk;
- uart->port.iotype = port->iotype;
- uart->port.flags = port->flags
- | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
- uart->port.mapbase = port->mapbase;
- if (port->dev)
- uart->port.dev = port->dev;
- ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
- if (ret == 0)
- ret = uart->port.line;
- }
- mutex_unlock(&serial_txx9_mutex);
- return ret;
-}
-
-/**
- * serial_txx9_unregister_port - remove a txx9 serial port at runtime
- * @line: serial line number
- *
- * Remove one serial port. This may not be called from interrupt
- * context. We hand the port back to the our control.
- */
-static void __devexit serial_txx9_unregister_port(int line)
-{
- struct uart_txx9_port *uart = &serial_txx9_ports[line];
-
- mutex_lock(&serial_txx9_mutex);
- uart_remove_one_port(&serial_txx9_reg, &uart->port);
- uart->port.flags = 0;
- uart->port.type = PORT_UNKNOWN;
- uart->port.iobase = 0;
- uart->port.mapbase = 0;
- uart->port.membase = NULL;
- uart->port.dev = NULL;
- mutex_unlock(&serial_txx9_mutex);
-}
-
-/*
- * Register a set of serial devices attached to a platform device.
- */
-static int __devinit serial_txx9_probe(struct platform_device *dev)
-{
- struct uart_port *p = dev->dev.platform_data;
- struct uart_port port;
- int ret, i;
-
- memset(&port, 0, sizeof(struct uart_port));
- for (i = 0; p && p->uartclk != 0; p++, i++) {
- port.iobase = p->iobase;
- port.membase = p->membase;
- port.irq = p->irq;
- port.uartclk = p->uartclk;
- port.iotype = p->iotype;
- port.flags = p->flags;
- port.mapbase = p->mapbase;
- port.dev = &dev->dev;
- ret = serial_txx9_register_port(&port);
- if (ret < 0) {
- dev_err(&dev->dev, "unable to register port at index %d "
- "(IO%lx MEM%llx IRQ%d): %d\n", i,
- p->iobase, (unsigned long long)p->mapbase,
- p->irq, ret);
- }
- }
- return 0;
-}
-
-/*
- * Remove serial ports registered against a platform device.
- */
-static int __devexit serial_txx9_remove(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_txx9_port *up = &serial_txx9_ports[i];
-
- if (up->port.dev == &dev->dev)
- serial_txx9_unregister_port(i);
- }
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int serial_txx9_suspend(struct platform_device *dev, pm_message_t state)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_txx9_port *up = &serial_txx9_ports[i];
-
- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- uart_suspend_port(&serial_txx9_reg, &up->port);
- }
-
- return 0;
-}
-
-static int serial_txx9_resume(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_txx9_port *up = &serial_txx9_ports[i];
-
- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- uart_resume_port(&serial_txx9_reg, &up->port);
- }
-
- return 0;
-}
-#endif
-
-static struct platform_driver serial_txx9_plat_driver = {
- .probe = serial_txx9_probe,
- .remove = __devexit_p(serial_txx9_remove),
-#ifdef CONFIG_PM
- .suspend = serial_txx9_suspend,
- .resume = serial_txx9_resume,
-#endif
- .driver = {
- .name = "serial_txx9",
- .owner = THIS_MODULE,
- },
-};
-
-#ifdef ENABLE_SERIAL_TXX9_PCI
-/*
- * Probe one serial board. Unfortunately, there is no rhyme nor reason
- * to the arrangement of serial ports on a PCI card.
- */
-static int __devinit
-pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
-{
- struct uart_port port;
- int line;
- int rc;
-
- rc = pci_enable_device(dev);
- if (rc)
- return rc;
-
- memset(&port, 0, sizeof(port));
- port.ops = &serial_txx9_pops;
- port.flags |= UPF_TXX9_HAVE_CTS_LINE;
- port.uartclk = 66670000;
- port.irq = dev->irq;
- port.iotype = UPIO_PORT;
- port.iobase = pci_resource_start(dev, 1);
- port.dev = &dev->dev;
- line = serial_txx9_register_port(&port);
- if (line < 0) {
- printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
- pci_disable_device(dev);
- return line;
- }
- pci_set_drvdata(dev, &serial_txx9_ports[line]);
-
- return 0;
-}
-
-static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
-{
- struct uart_txx9_port *up = pci_get_drvdata(dev);
-
- pci_set_drvdata(dev, NULL);
-
- if (up) {
- serial_txx9_unregister_port(up->port.line);
- pci_disable_device(dev);
- }
-}
-
-#ifdef CONFIG_PM
-static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
-{
- struct uart_txx9_port *up = pci_get_drvdata(dev);
-
- if (up)
- uart_suspend_port(&serial_txx9_reg, &up->port);
- pci_save_state(dev);
- pci_set_power_state(dev, pci_choose_state(dev, state));
- return 0;
-}
-
-static int pciserial_txx9_resume_one(struct pci_dev *dev)
-{
- struct uart_txx9_port *up = pci_get_drvdata(dev);
-
- pci_set_power_state(dev, PCI_D0);
- pci_restore_state(dev);
- if (up)
- uart_resume_port(&serial_txx9_reg, &up->port);
- return 0;
-}
-#endif
-
-static const struct pci_device_id serial_txx9_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC) },
- { 0, }
-};
-
-static struct pci_driver serial_txx9_pci_driver = {
- .name = "serial_txx9",
- .probe = pciserial_txx9_init_one,
- .remove = __devexit_p(pciserial_txx9_remove_one),
-#ifdef CONFIG_PM
- .suspend = pciserial_txx9_suspend_one,
- .resume = pciserial_txx9_resume_one,
-#endif
- .id_table = serial_txx9_pci_tbl,
-};
-
-MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
-#endif /* ENABLE_SERIAL_TXX9_PCI */
-
-static struct platform_device *serial_txx9_plat_devs;
-
-static int __init serial_txx9_init(void)
-{
- int ret;
-
- printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-
- ret = uart_register_driver(&serial_txx9_reg);
- if (ret)
- goto out;
-
- serial_txx9_plat_devs = platform_device_alloc("serial_txx9", -1);
- if (!serial_txx9_plat_devs) {
- ret = -ENOMEM;
- goto unreg_uart_drv;
- }
-
- ret = platform_device_add(serial_txx9_plat_devs);
- if (ret)
- goto put_dev;
-
- serial_txx9_register_ports(&serial_txx9_reg,
- &serial_txx9_plat_devs->dev);
-
- ret = platform_driver_register(&serial_txx9_plat_driver);
- if (ret)
- goto del_dev;
-
-#ifdef ENABLE_SERIAL_TXX9_PCI
- ret = pci_register_driver(&serial_txx9_pci_driver);
-#endif
- if (ret == 0)
- goto out;
-
- del_dev:
- platform_device_del(serial_txx9_plat_devs);
- put_dev:
- platform_device_put(serial_txx9_plat_devs);
- unreg_uart_drv:
- uart_unregister_driver(&serial_txx9_reg);
- out:
- return ret;
-}
-
-static void __exit serial_txx9_exit(void)
-{
- int i;
-
-#ifdef ENABLE_SERIAL_TXX9_PCI
- pci_unregister_driver(&serial_txx9_pci_driver);
-#endif
- platform_driver_unregister(&serial_txx9_plat_driver);
- platform_device_unregister(serial_txx9_plat_devs);
- for (i = 0; i < UART_NR; i++) {
- struct uart_txx9_port *up = &serial_txx9_ports[i];
- if (up->port.iobase || up->port.mapbase)
- uart_remove_one_port(&serial_txx9_reg, &up->port);
- }
-
- uart_unregister_driver(&serial_txx9_reg);
-}
-
-module_init(serial_txx9_init);
-module_exit(serial_txx9_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("TX39/49 serial driver");
-
-MODULE_ALIAS_CHARDEV_MAJOR(TXX9_TTY_MAJOR);
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
deleted file mode 100644
index c291b3add1d2..000000000000
--- a/drivers/serial/sh-sci.c
+++ /dev/null
@@ -1,2027 +0,0 @@
-/*
- * drivers/serial/sh-sci.c
- *
- * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
- *
- * Copyright (C) 2002 - 2008 Paul Mundt
- * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
- *
- * based off of the old drivers/char/sh-sci.c by:
- *
- * Copyright (C) 1999, 2000 Niibe Yutaka
- * Copyright (C) 2000 Sugioka Toshinobu
- * Modified to support multiple serial ports. Stuart Menefy (May 2000).
- * Modified to support SecureEdge. David McCullough (2002)
- * Modified to support SH7300 SCIF. Takashi Kusuda (Jun 2003).
- * Removed SH7300 support (Jul 2007).
- *
- * 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.
- */
-#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/sysrq.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/platform_device.h>
-#include <linux/serial_sci.h>
-#include <linux/notifier.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/ctype.h>
-#include <linux/err.h>
-#include <linux/list.h>
-#include <linux/dmaengine.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_SUPERH
-#include <asm/sh_bios.h>
-#endif
-
-#ifdef CONFIG_H8300
-#include <asm/gpio.h>
-#endif
-
-#include "sh-sci.h"
-
-struct sci_port {
- struct uart_port port;
-
- /* Port type */
- unsigned int type;
-
- /* Port IRQs: ERI, RXI, TXI, BRI (optional) */
- unsigned int irqs[SCIx_NR_IRQS];
-
- /* Port enable callback */
- void (*enable)(struct uart_port *port);
-
- /* Port disable callback */
- void (*disable)(struct uart_port *port);
-
- /* Break timer */
- struct timer_list break_timer;
- int break_flag;
-
- /* Interface clock */
- struct clk *iclk;
- /* Function clock */
- struct clk *fclk;
-
- struct list_head node;
- struct dma_chan *chan_tx;
- struct dma_chan *chan_rx;
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- struct device *dma_dev;
- unsigned int slave_tx;
- unsigned int slave_rx;
- struct dma_async_tx_descriptor *desc_tx;
- struct dma_async_tx_descriptor *desc_rx[2];
- dma_cookie_t cookie_tx;
- dma_cookie_t cookie_rx[2];
- dma_cookie_t active_rx;
- struct scatterlist sg_tx;
- unsigned int sg_len_tx;
- struct scatterlist sg_rx[2];
- size_t buf_len_rx;
- struct sh_dmae_slave param_tx;
- struct sh_dmae_slave param_rx;
- struct work_struct work_tx;
- struct work_struct work_rx;
- struct timer_list rx_timer;
- unsigned int rx_timeout;
-#endif
-};
-
-struct sh_sci_priv {
- spinlock_t lock;
- struct list_head ports;
- struct notifier_block clk_nb;
-};
-
-/* Function prototypes */
-static void sci_stop_tx(struct uart_port *port);
-
-#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
-
-static struct sci_port sci_ports[SCI_NPORTS];
-static struct uart_driver sci_uart_driver;
-
-static inline struct sci_port *
-to_sci_port(struct uart_port *uart)
-{
- return container_of(uart, struct sci_port, port);
-}
-
-#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
-
-#ifdef CONFIG_CONSOLE_POLL
-static inline void handle_error(struct uart_port *port)
-{
- /* Clear error flags */
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
-}
-
-static int sci_poll_get_char(struct uart_port *port)
-{
- unsigned short status;
- int c;
-
- do {
- status = sci_in(port, SCxSR);
- if (status & SCxSR_ERRORS(port)) {
- handle_error(port);
- continue;
- }
- break;
- } while (1);
-
- if (!(status & SCxSR_RDxF(port)))
- return NO_POLL_CHAR;
-
- c = sci_in(port, SCxRDR);
-
- /* Dummy read */
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
-
- return c;
-}
-#endif
-
-static void sci_poll_put_char(struct uart_port *port, unsigned char c)
-{
- unsigned short status;
-
- do {
- status = sci_in(port, SCxSR);
- } while (!(status & SCxSR_TDxE(port)));
-
- sci_out(port, SCxTDR, c);
- sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
-}
-#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
-
-#if defined(__H8300H__) || defined(__H8300S__)
-static void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- int ch = (port->mapbase - SMR0) >> 3;
-
- /* set DDR regs */
- H8300_GPIO_DDR(h8300_sci_pins[ch].port,
- h8300_sci_pins[ch].rx,
- H8300_GPIO_INPUT);
- H8300_GPIO_DDR(h8300_sci_pins[ch].port,
- h8300_sci_pins[ch].tx,
- H8300_GPIO_OUTPUT);
-
- /* tx mark output*/
- H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- if (port->mapbase == 0xA4400000) {
- __raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
- __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
- } else if (port->mapbase == 0xA4410000)
- __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7721)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- unsigned short data;
-
- if (cflag & CRTSCTS) {
- /* enable RTS/CTS */
- if (port->mapbase == 0xa4430000) { /* SCIF0 */
- /* Clear PTCR bit 9-2; enable all scif pins but sck */
- data = __raw_readw(PORT_PTCR);
- __raw_writew((data & 0xfc03), PORT_PTCR);
- } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
- /* Clear PVCR bit 9-2 */
- data = __raw_readw(PORT_PVCR);
- __raw_writew((data & 0xfc03), PORT_PVCR);
- }
- } else {
- if (port->mapbase == 0xa4430000) { /* SCIF0 */
- /* Clear PTCR bit 5-2; enable only tx and rx */
- data = __raw_readw(PORT_PTCR);
- __raw_writew((data & 0xffc3), PORT_PTCR);
- } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
- /* Clear PVCR bit 5-2 */
- data = __raw_readw(PORT_PVCR);
- __raw_writew((data & 0xffc3), PORT_PVCR);
- }
- }
-}
-#elif defined(CONFIG_CPU_SH3)
-/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- unsigned short data;
-
- /* We need to set SCPCR to enable RTS/CTS */
- data = __raw_readw(SCPCR);
- /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
- __raw_writew(data & 0x0fcf, SCPCR);
-
- if (!(cflag & CRTSCTS)) {
- /* We need to set SCPCR to enable RTS/CTS */
- data = __raw_readw(SCPCR);
- /* Clear out SCP7MD1,0, SCP4MD1,0,
- Set SCP6MD1,0 = {01} (output) */
- __raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
-
- data = __raw_readb(SCPDR);
- /* Set /RTS2 (bit6) = 0 */
- __raw_writeb(data & 0xbf, SCPDR);
- }
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- unsigned short data;
-
- if (port->mapbase == 0xffe00000) {
- data = __raw_readw(PSCR);
- data &= ~0x03cf;
- if (!(cflag & CRTSCTS))
- data |= 0x0340;
-
- __raw_writew(data, PSCR);
- }
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
- defined(CONFIG_CPU_SUBTYPE_SH7763) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785) || \
- defined(CONFIG_CPU_SUBTYPE_SH7786) || \
- defined(CONFIG_CPU_SUBTYPE_SHX3)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- if (!(cflag & CRTSCTS))
- __raw_writew(0x0080, SCSPTR0); /* Set RTS = 1 */
-}
-#elif defined(CONFIG_CPU_SH4) && !defined(CONFIG_CPU_SH4A)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- if (!(cflag & CRTSCTS))
- __raw_writew(0x0080, SCSPTR2); /* Set RTS = 1 */
-}
-#else
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
- /* Nothing to do */
-}
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785) || \
- defined(CONFIG_CPU_SUBTYPE_SH7786)
-static int scif_txfill(struct uart_port *port)
-{
- return sci_in(port, SCTFDR) & 0xff;
-}
-
-static int scif_txroom(struct uart_port *port)
-{
- return SCIF_TXROOM_MAX - scif_txfill(port);
-}
-
-static int scif_rxfill(struct uart_port *port)
-{
- return sci_in(port, SCRFDR) & 0xff;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-static int scif_txfill(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000 ||
- port->mapbase == 0xffe08000)
- /* SCIF0/1*/
- return sci_in(port, SCTFDR) & 0xff;
- else
- /* SCIF2 */
- return sci_in(port, SCFDR) >> 8;
-}
-
-static int scif_txroom(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000 ||
- port->mapbase == 0xffe08000)
- /* SCIF0/1*/
- return SCIF_TXROOM_MAX - scif_txfill(port);
- else
- /* SCIF2 */
- return SCIF2_TXROOM_MAX - scif_txfill(port);
-}
-
-static int scif_rxfill(struct uart_port *port)
-{
- if ((port->mapbase == 0xffe00000) ||
- (port->mapbase == 0xffe08000)) {
- /* SCIF0/1*/
- return sci_in(port, SCRFDR) & 0xff;
- } else {
- /* SCIF2 */
- return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
- }
-}
-#elif defined(CONFIG_ARCH_SH7372)
-static int scif_txfill(struct uart_port *port)
-{
- if (port->type == PORT_SCIFA)
- return sci_in(port, SCFDR) >> 8;
- else
- return sci_in(port, SCTFDR);
-}
-
-static int scif_txroom(struct uart_port *port)
-{
- return port->fifosize - scif_txfill(port);
-}
-
-static int scif_rxfill(struct uart_port *port)
-{
- if (port->type == PORT_SCIFA)
- return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
- else
- return sci_in(port, SCRFDR);
-}
-#else
-static int scif_txfill(struct uart_port *port)
-{
- return sci_in(port, SCFDR) >> 8;
-}
-
-static int scif_txroom(struct uart_port *port)
-{
- return SCIF_TXROOM_MAX - scif_txfill(port);
-}
-
-static int scif_rxfill(struct uart_port *port)
-{
- return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
-}
-#endif
-
-static int sci_txfill(struct uart_port *port)
-{
- return !(sci_in(port, SCxSR) & SCI_TDRE);
-}
-
-static int sci_txroom(struct uart_port *port)
-{
- return !sci_txfill(port);
-}
-
-static int sci_rxfill(struct uart_port *port)
-{
- return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
-}
-
-/* ********************************************************************** *
- * the interrupt related routines *
- * ********************************************************************** */
-
-static void sci_transmit_chars(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
- unsigned int stopped = uart_tx_stopped(port);
- unsigned short status;
- unsigned short ctrl;
- int count;
-
- status = sci_in(port, SCxSR);
- if (!(status & SCxSR_TDxE(port))) {
- ctrl = sci_in(port, SCSCR);
- if (uart_circ_empty(xmit))
- ctrl &= ~SCI_CTRL_FLAGS_TIE;
- else
- ctrl |= SCI_CTRL_FLAGS_TIE;
- sci_out(port, SCSCR, ctrl);
- return;
- }
-
- if (port->type == PORT_SCI)
- count = sci_txroom(port);
- else
- count = scif_txroom(port);
-
- do {
- unsigned char c;
-
- if (port->x_char) {
- c = port->x_char;
- port->x_char = 0;
- } else if (!uart_circ_empty(xmit) && !stopped) {
- c = xmit->buf[xmit->tail];
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- } else {
- break;
- }
-
- sci_out(port, SCxTDR, c);
-
- port->icount.tx++;
- } while (--count > 0);
-
- sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
- if (uart_circ_empty(xmit)) {
- sci_stop_tx(port);
- } else {
- ctrl = sci_in(port, SCSCR);
-
- if (port->type != PORT_SCI) {
- sci_in(port, SCxSR); /* Dummy read */
- sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
- }
-
- ctrl |= SCI_CTRL_FLAGS_TIE;
- sci_out(port, SCSCR, ctrl);
- }
-}
-
-/* On SH3, SCIF may read end-of-break as a space->mark char */
-#define STEPFN(c) ({int __c = (c); (((__c-1)|(__c)) == -1); })
-
-static inline void sci_receive_chars(struct uart_port *port)
-{
- struct sci_port *sci_port = to_sci_port(port);
- struct tty_struct *tty = port->state->port.tty;
- int i, count, copied = 0;
- unsigned short status;
- unsigned char flag;
-
- status = sci_in(port, SCxSR);
- if (!(status & SCxSR_RDxF(port)))
- return;
-
- while (1) {
- if (port->type == PORT_SCI)
- count = sci_rxfill(port);
- else
- count = scif_rxfill(port);
-
- /* Don't copy more bytes than there is room for in the buffer */
- count = tty_buffer_request_room(tty, count);
-
- /* If for any reason we can't copy more data, we're done! */
- if (count == 0)
- break;
-
- if (port->type == PORT_SCI) {
- char c = sci_in(port, SCxRDR);
- if (uart_handle_sysrq_char(port, c) ||
- sci_port->break_flag)
- count = 0;
- else
- tty_insert_flip_char(tty, c, TTY_NORMAL);
- } else {
- for (i = 0; i < count; i++) {
- char c = sci_in(port, SCxRDR);
- status = sci_in(port, SCxSR);
-#if defined(CONFIG_CPU_SH3)
- /* Skip "chars" during break */
- if (sci_port->break_flag) {
- if ((c == 0) &&
- (status & SCxSR_FER(port))) {
- count--; i--;
- continue;
- }
-
- /* Nonzero => end-of-break */
- dev_dbg(port->dev, "debounce<%02x>\n", c);
- sci_port->break_flag = 0;
-
- if (STEPFN(c)) {
- count--; i--;
- continue;
- }
- }
-#endif /* CONFIG_CPU_SH3 */
- if (uart_handle_sysrq_char(port, c)) {
- count--; i--;
- continue;
- }
-
- /* Store data and status */
- if (status & SCxSR_FER(port)) {
- flag = TTY_FRAME;
- dev_notice(port->dev, "frame error\n");
- } else if (status & SCxSR_PER(port)) {
- flag = TTY_PARITY;
- dev_notice(port->dev, "parity error\n");
- } else
- flag = TTY_NORMAL;
-
- tty_insert_flip_char(tty, c, flag);
- }
- }
-
- sci_in(port, SCxSR); /* dummy read */
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
-
- copied += count;
- port->icount.rx += count;
- }
-
- if (copied) {
- /* Tell the rest of the system the news. New characters! */
- tty_flip_buffer_push(tty);
- } else {
- sci_in(port, SCxSR); /* dummy read */
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
- }
-}
-
-#define SCI_BREAK_JIFFIES (HZ/20)
-/* The sci generates interrupts during the break,
- * 1 per millisecond or so during the break period, for 9600 baud.
- * So dont bother disabling interrupts.
- * But dont want more than 1 break event.
- * Use a kernel timer to periodically poll the rx line until
- * the break is finished.
- */
-static void sci_schedule_break_timer(struct sci_port *port)
-{
- port->break_timer.expires = jiffies + SCI_BREAK_JIFFIES;
- add_timer(&port->break_timer);
-}
-/* Ensure that two consecutive samples find the break over. */
-static void sci_break_timer(unsigned long data)
-{
- struct sci_port *port = (struct sci_port *)data;
-
- if (sci_rxd_in(&port->port) == 0) {
- port->break_flag = 1;
- sci_schedule_break_timer(port);
- } else if (port->break_flag == 1) {
- /* break is over. */
- port->break_flag = 2;
- sci_schedule_break_timer(port);
- } else
- port->break_flag = 0;
-}
-
-static inline int sci_handle_errors(struct uart_port *port)
-{
- int copied = 0;
- unsigned short status = sci_in(port, SCxSR);
- struct tty_struct *tty = port->state->port.tty;
-
- if (status & SCxSR_ORER(port)) {
- /* overrun error */
- if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
- copied++;
-
- dev_notice(port->dev, "overrun error");
- }
-
- if (status & SCxSR_FER(port)) {
- if (sci_rxd_in(port) == 0) {
- /* Notify of BREAK */
- struct sci_port *sci_port = to_sci_port(port);
-
- if (!sci_port->break_flag) {
- sci_port->break_flag = 1;
- sci_schedule_break_timer(sci_port);
-
- /* Do sysrq handling. */
- if (uart_handle_break(port))
- return 0;
-
- dev_dbg(port->dev, "BREAK detected\n");
-
- if (tty_insert_flip_char(tty, 0, TTY_BREAK))
- copied++;
- }
-
- } else {
- /* frame error */
- if (tty_insert_flip_char(tty, 0, TTY_FRAME))
- copied++;
-
- dev_notice(port->dev, "frame error\n");
- }
- }
-
- if (status & SCxSR_PER(port)) {
- /* parity error */
- if (tty_insert_flip_char(tty, 0, TTY_PARITY))
- copied++;
-
- dev_notice(port->dev, "parity error");
- }
-
- if (copied)
- tty_flip_buffer_push(tty);
-
- return copied;
-}
-
-static inline int sci_handle_fifo_overrun(struct uart_port *port)
-{
- struct tty_struct *tty = port->state->port.tty;
- int copied = 0;
-
- if (port->type != PORT_SCIF)
- return 0;
-
- if ((sci_in(port, SCLSR) & SCIF_ORER) != 0) {
- sci_out(port, SCLSR, 0);
-
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- tty_flip_buffer_push(tty);
-
- dev_notice(port->dev, "overrun error\n");
- copied++;
- }
-
- return copied;
-}
-
-static inline int sci_handle_breaks(struct uart_port *port)
-{
- int copied = 0;
- unsigned short status = sci_in(port, SCxSR);
- struct tty_struct *tty = port->state->port.tty;
- struct sci_port *s = to_sci_port(port);
-
- if (uart_handle_break(port))
- return 0;
-
- if (!s->break_flag && status & SCxSR_BRK(port)) {
-#if defined(CONFIG_CPU_SH3)
- /* Debounce break */
- s->break_flag = 1;
-#endif
- /* Notify of BREAK */
- if (tty_insert_flip_char(tty, 0, TTY_BREAK))
- copied++;
-
- dev_dbg(port->dev, "BREAK detected\n");
- }
-
- if (copied)
- tty_flip_buffer_push(tty);
-
- copied += sci_handle_fifo_overrun(port);
-
- return copied;
-}
-
-static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
-{
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- struct uart_port *port = ptr;
- struct sci_port *s = to_sci_port(port);
-
- if (s->chan_rx) {
- u16 scr = sci_in(port, SCSCR);
- u16 ssr = sci_in(port, SCxSR);
-
- /* Disable future Rx interrupts */
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- disable_irq_nosync(irq);
- scr |= 0x4000;
- } else {
- scr &= ~SCI_CTRL_FLAGS_RIE;
- }
- sci_out(port, SCSCR, scr);
- /* Clear current interrupt */
- sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
- dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
- jiffies, s->rx_timeout);
- mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
-
- return IRQ_HANDLED;
- }
-#endif
-
- /* I think sci_receive_chars has to be called irrespective
- * of whether the I_IXOFF is set, otherwise, how is the interrupt
- * to be disabled?
- */
- sci_receive_chars(ptr);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
-{
- struct uart_port *port = ptr;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- sci_transmit_chars(port);
- spin_unlock_irqrestore(&port->lock, flags);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sci_er_interrupt(int irq, void *ptr)
-{
- struct uart_port *port = ptr;
-
- /* Handle errors */
- if (port->type == PORT_SCI) {
- if (sci_handle_errors(port)) {
- /* discard character in rx buffer */
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
- }
- } else {
- sci_handle_fifo_overrun(port);
- sci_rx_interrupt(irq, ptr);
- }
-
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
-
- /* Kick the transmission */
- sci_tx_interrupt(irq, ptr);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sci_br_interrupt(int irq, void *ptr)
-{
- struct uart_port *port = ptr;
-
- /* Handle BREAKs */
- sci_handle_breaks(port);
- sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
-{
- unsigned short ssr_status, scr_status, err_enabled;
- struct uart_port *port = ptr;
- struct sci_port *s = to_sci_port(port);
- irqreturn_t ret = IRQ_NONE;
-
- ssr_status = sci_in(port, SCxSR);
- scr_status = sci_in(port, SCSCR);
- err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE);
-
- /* Tx Interrupt */
- if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE) &&
- !s->chan_tx)
- ret = sci_tx_interrupt(irq, ptr);
- /*
- * Rx Interrupt: if we're using DMA, the DMA controller clears RDF /
- * DR flags
- */
- if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
- (scr_status & SCI_CTRL_FLAGS_RIE))
- ret = sci_rx_interrupt(irq, ptr);
- /* Error Interrupt */
- if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
- ret = sci_er_interrupt(irq, ptr);
- /* Break Interrupt */
- if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
- ret = sci_br_interrupt(irq, ptr);
-
- return ret;
-}
-
-/*
- * Here we define a transistion notifier so that we can update all of our
- * ports' baud rate when the peripheral clock changes.
- */
-static int sci_notifier(struct notifier_block *self,
- unsigned long phase, void *p)
-{
- struct sh_sci_priv *priv = container_of(self,
- struct sh_sci_priv, clk_nb);
- struct sci_port *sci_port;
- unsigned long flags;
-
- if ((phase == CPUFREQ_POSTCHANGE) ||
- (phase == CPUFREQ_RESUMECHANGE)) {
- spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry(sci_port, &priv->ports, node)
- sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- return NOTIFY_OK;
-}
-
-static void sci_clk_enable(struct uart_port *port)
-{
- struct sci_port *sci_port = to_sci_port(port);
-
- clk_enable(sci_port->iclk);
- sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
- clk_enable(sci_port->fclk);
-}
-
-static void sci_clk_disable(struct uart_port *port)
-{
- struct sci_port *sci_port = to_sci_port(port);
-
- clk_disable(sci_port->fclk);
- clk_disable(sci_port->iclk);
-}
-
-static int sci_request_irq(struct sci_port *port)
-{
- int i;
- irqreturn_t (*handlers[4])(int irq, void *ptr) = {
- sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt,
- sci_br_interrupt,
- };
- const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
- "SCI Transmit Data Empty", "SCI Break" };
-
- if (port->irqs[0] == port->irqs[1]) {
- if (unlikely(!port->irqs[0]))
- return -ENODEV;
-
- if (request_irq(port->irqs[0], sci_mpxed_interrupt,
- IRQF_DISABLED, "sci", port)) {
- dev_err(port->port.dev, "Can't allocate IRQ\n");
- return -ENODEV;
- }
- } else {
- for (i = 0; i < ARRAY_SIZE(handlers); i++) {
- if (unlikely(!port->irqs[i]))
- continue;
-
- if (request_irq(port->irqs[i], handlers[i],
- IRQF_DISABLED, desc[i], port)) {
- dev_err(port->port.dev, "Can't allocate IRQ\n");
- return -ENODEV;
- }
- }
- }
-
- return 0;
-}
-
-static void sci_free_irq(struct sci_port *port)
-{
- int i;
-
- if (port->irqs[0] == port->irqs[1])
- free_irq(port->irqs[0], port);
- else {
- for (i = 0; i < ARRAY_SIZE(port->irqs); i++) {
- if (!port->irqs[i])
- continue;
-
- free_irq(port->irqs[i], port);
- }
- }
-}
-
-static unsigned int sci_tx_empty(struct uart_port *port)
-{
- unsigned short status = sci_in(port, SCxSR);
- unsigned short in_tx_fifo = scif_txfill(port);
-
- return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
-}
-
-static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
- /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
- /* If you have signals for DTR and DCD, please implement here. */
-}
-
-static unsigned int sci_get_mctrl(struct uart_port *port)
-{
- /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
- and CTS/RTS */
-
- return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
-}
-
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-static void sci_dma_tx_complete(void *arg)
-{
- struct sci_port *s = arg;
- struct uart_port *port = &s->port;
- struct circ_buf *xmit = &port->state->xmit;
- unsigned long flags;
-
- dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
-
- spin_lock_irqsave(&port->lock, flags);
-
- xmit->tail += sg_dma_len(&s->sg_tx);
- xmit->tail &= UART_XMIT_SIZE - 1;
-
- port->icount.tx += sg_dma_len(&s->sg_tx);
-
- async_tx_ack(s->desc_tx);
- s->cookie_tx = -EINVAL;
- s->desc_tx = NULL;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (!uart_circ_empty(xmit)) {
- schedule_work(&s->work_tx);
- } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 ctrl = sci_in(port, SCSCR);
- sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/* Locking: called with port lock held */
-static int sci_dma_rx_push(struct sci_port *s, struct tty_struct *tty,
- size_t count)
-{
- struct uart_port *port = &s->port;
- int i, active, room;
-
- room = tty_buffer_request_room(tty, count);
-
- if (s->active_rx == s->cookie_rx[0]) {
- active = 0;
- } else if (s->active_rx == s->cookie_rx[1]) {
- active = 1;
- } else {
- dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
- return 0;
- }
-
- if (room < count)
- dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
- count - room);
- if (!room)
- return room;
-
- for (i = 0; i < room; i++)
- tty_insert_flip_char(tty, ((u8 *)sg_virt(&s->sg_rx[active]))[i],
- TTY_NORMAL);
-
- port->icount.rx += room;
-
- return room;
-}
-
-static void sci_dma_rx_complete(void *arg)
-{
- struct sci_port *s = arg;
- struct uart_port *port = &s->port;
- struct tty_struct *tty = port->state->port.tty;
- unsigned long flags;
- int count;
-
- dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx);
-
- spin_lock_irqsave(&port->lock, flags);
-
- count = sci_dma_rx_push(s, tty, s->buf_len_rx);
-
- mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (count)
- tty_flip_buffer_push(tty);
-
- schedule_work(&s->work_rx);
-}
-
-static void sci_start_rx(struct uart_port *port);
-static void sci_start_tx(struct uart_port *port);
-
-static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
-{
- struct dma_chan *chan = s->chan_rx;
- struct uart_port *port = &s->port;
-
- s->chan_rx = NULL;
- s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
- dma_release_channel(chan);
- if (sg_dma_address(&s->sg_rx[0]))
- dma_free_coherent(port->dev, s->buf_len_rx * 2,
- sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
- if (enable_pio)
- sci_start_rx(port);
-}
-
-static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
-{
- struct dma_chan *chan = s->chan_tx;
- struct uart_port *port = &s->port;
-
- s->chan_tx = NULL;
- s->cookie_tx = -EINVAL;
- dma_release_channel(chan);
- if (enable_pio)
- sci_start_tx(port);
-}
-
-static void sci_submit_rx(struct sci_port *s)
-{
- struct dma_chan *chan = s->chan_rx;
- int i;
-
- for (i = 0; i < 2; i++) {
- struct scatterlist *sg = &s->sg_rx[i];
- struct dma_async_tx_descriptor *desc;
-
- desc = chan->device->device_prep_slave_sg(chan,
- sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT);
-
- if (desc) {
- s->desc_rx[i] = desc;
- desc->callback = sci_dma_rx_complete;
- desc->callback_param = s;
- s->cookie_rx[i] = desc->tx_submit(desc);
- }
-
- if (!desc || s->cookie_rx[i] < 0) {
- if (i) {
- async_tx_ack(s->desc_rx[0]);
- s->cookie_rx[0] = -EINVAL;
- }
- if (desc) {
- async_tx_ack(desc);
- s->cookie_rx[i] = -EINVAL;
- }
- dev_warn(s->port.dev,
- "failed to re-start DMA, using PIO\n");
- sci_rx_dma_release(s, true);
- return;
- }
- dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
- s->cookie_rx[i], i);
- }
-
- s->active_rx = s->cookie_rx[0];
-
- dma_async_issue_pending(chan);
-}
-
-static void work_fn_rx(struct work_struct *work)
-{
- struct sci_port *s = container_of(work, struct sci_port, work_rx);
- struct uart_port *port = &s->port;
- struct dma_async_tx_descriptor *desc;
- int new;
-
- if (s->active_rx == s->cookie_rx[0]) {
- new = 0;
- } else if (s->active_rx == s->cookie_rx[1]) {
- new = 1;
- } else {
- dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
- return;
- }
- desc = s->desc_rx[new];
-
- if (dma_async_is_tx_complete(s->chan_rx, s->active_rx, NULL, NULL) !=
- DMA_SUCCESS) {
- /* Handle incomplete DMA receive */
- struct tty_struct *tty = port->state->port.tty;
- struct dma_chan *chan = s->chan_rx;
- struct sh_desc *sh_desc = container_of(desc, struct sh_desc,
- async_tx);
- unsigned long flags;
- int count;
-
- chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
- dev_dbg(port->dev, "Read %u bytes with cookie %d\n",
- sh_desc->partial, sh_desc->cookie);
-
- spin_lock_irqsave(&port->lock, flags);
- count = sci_dma_rx_push(s, tty, sh_desc->partial);
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (count)
- tty_flip_buffer_push(tty);
-
- sci_submit_rx(s);
-
- return;
- }
-
- s->cookie_rx[new] = desc->tx_submit(desc);
- if (s->cookie_rx[new] < 0) {
- dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
- sci_rx_dma_release(s, true);
- return;
- }
-
- s->active_rx = s->cookie_rx[!new];
-
- dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__,
- s->cookie_rx[new], new, s->active_rx);
-}
-
-static void work_fn_tx(struct work_struct *work)
-{
- struct sci_port *s = container_of(work, struct sci_port, work_tx);
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *chan = s->chan_tx;
- struct uart_port *port = &s->port;
- struct circ_buf *xmit = &port->state->xmit;
- struct scatterlist *sg = &s->sg_tx;
-
- /*
- * DMA is idle now.
- * Port xmit buffer is already mapped, and it is one page... Just adjust
- * offsets and lengths. Since it is a circular buffer, we have to
- * transmit till the end, and then the rest. Take the port lock to get a
- * consistent xmit buffer state.
- */
- spin_lock_irq(&port->lock);
- sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
- sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
- sg->offset;
- sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
- CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
- spin_unlock_irq(&port->lock);
-
- BUG_ON(!sg_dma_len(sg));
-
- desc = chan->device->device_prep_slave_sg(chan,
- sg, s->sg_len_tx, DMA_TO_DEVICE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- /* switch to PIO */
- sci_tx_dma_release(s, true);
- return;
- }
-
- dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
-
- spin_lock_irq(&port->lock);
- s->desc_tx = desc;
- desc->callback = sci_dma_tx_complete;
- desc->callback_param = s;
- spin_unlock_irq(&port->lock);
- s->cookie_tx = desc->tx_submit(desc);
- if (s->cookie_tx < 0) {
- dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
- /* switch to PIO */
- sci_tx_dma_release(s, true);
- return;
- }
-
- dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", __func__,
- xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
-
- dma_async_issue_pending(chan);
-}
-#endif
-
-static void sci_start_tx(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
- unsigned short ctrl;
-
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 new, scr = sci_in(port, SCSCR);
- if (s->chan_tx)
- new = scr | 0x8000;
- else
- new = scr & ~0x8000;
- if (new != scr)
- sci_out(port, SCSCR, new);
- }
- if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
- s->cookie_tx < 0)
- schedule_work(&s->work_tx);
-#endif
- if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
- ctrl = sci_in(port, SCSCR);
- sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE);
- }
-}
-
-static void sci_stop_tx(struct uart_port *port)
-{
- unsigned short ctrl;
-
- /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
- ctrl = sci_in(port, SCSCR);
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- ctrl &= ~0x8000;
- ctrl &= ~SCI_CTRL_FLAGS_TIE;
- sci_out(port, SCSCR, ctrl);
-}
-
-static void sci_start_rx(struct uart_port *port)
-{
- unsigned short ctrl = SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
-
- /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
- ctrl |= sci_in(port, SCSCR);
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- ctrl &= ~0x4000;
- sci_out(port, SCSCR, ctrl);
-}
-
-static void sci_stop_rx(struct uart_port *port)
-{
- unsigned short ctrl;
-
- /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
- ctrl = sci_in(port, SCSCR);
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- ctrl &= ~0x4000;
- ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
- sci_out(port, SCSCR, ctrl);
-}
-
-static void sci_enable_ms(struct uart_port *port)
-{
- /* Nothing here yet .. */
-}
-
-static void sci_break_ctl(struct uart_port *port, int break_state)
-{
- /* Nothing here yet .. */
-}
-
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-static bool filter(struct dma_chan *chan, void *slave)
-{
- struct sh_dmae_slave *param = slave;
-
- dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
- param->slave_id);
-
- if (param->dma_dev == chan->device->dev) {
- chan->private = param;
- return true;
- } else {
- return false;
- }
-}
-
-static void rx_timer_fn(unsigned long arg)
-{
- struct sci_port *s = (struct sci_port *)arg;
- struct uart_port *port = &s->port;
- u16 scr = sci_in(port, SCSCR);
-
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- scr &= ~0x4000;
- enable_irq(s->irqs[1]);
- }
- sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE);
- dev_dbg(port->dev, "DMA Rx timed out\n");
- schedule_work(&s->work_rx);
-}
-
-static void sci_request_dma(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
- struct sh_dmae_slave *param;
- struct dma_chan *chan;
- dma_cap_mask_t mask;
- int nent;
-
- dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__,
- port->line, s->dma_dev);
-
- if (!s->dma_dev)
- return;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- param = &s->param_tx;
-
- /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
- param->slave_id = s->slave_tx;
- param->dma_dev = s->dma_dev;
-
- s->cookie_tx = -EINVAL;
- chan = dma_request_channel(mask, filter, param);
- dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
- if (chan) {
- s->chan_tx = chan;
- sg_init_table(&s->sg_tx, 1);
- /* UART circular tx buffer is an aligned page. */
- BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
- sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
- UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK);
- nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
- if (!nent)
- sci_tx_dma_release(s, false);
- else
- dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
- sg_dma_len(&s->sg_tx),
- port->state->xmit.buf, sg_dma_address(&s->sg_tx));
-
- s->sg_len_tx = nent;
-
- INIT_WORK(&s->work_tx, work_fn_tx);
- }
-
- param = &s->param_rx;
-
- /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
- param->slave_id = s->slave_rx;
- param->dma_dev = s->dma_dev;
-
- chan = dma_request_channel(mask, filter, param);
- dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
- if (chan) {
- dma_addr_t dma[2];
- void *buf[2];
- int i;
-
- s->chan_rx = chan;
-
- s->buf_len_rx = 2 * max(16, (int)port->fifosize);
- buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2,
- &dma[0], GFP_KERNEL);
-
- if (!buf[0]) {
- dev_warn(port->dev,
- "failed to allocate dma buffer, using PIO\n");
- sci_rx_dma_release(s, true);
- return;
- }
-
- buf[1] = buf[0] + s->buf_len_rx;
- dma[1] = dma[0] + s->buf_len_rx;
-
- for (i = 0; i < 2; i++) {
- struct scatterlist *sg = &s->sg_rx[i];
-
- sg_init_table(sg, 1);
- sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
- (int)buf[i] & ~PAGE_MASK);
- sg_dma_address(sg) = dma[i];
- }
-
- INIT_WORK(&s->work_rx, work_fn_rx);
- setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
-
- sci_submit_rx(s);
- }
-}
-
-static void sci_free_dma(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
-
- if (!s->dma_dev)
- return;
-
- if (s->chan_tx)
- sci_tx_dma_release(s, false);
- if (s->chan_rx)
- sci_rx_dma_release(s, false);
-}
-#endif
-
-static int sci_startup(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
-
- dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
-
- if (s->enable)
- s->enable(port);
-
- sci_request_irq(s);
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- sci_request_dma(port);
-#endif
- sci_start_tx(port);
- sci_start_rx(port);
-
- return 0;
-}
-
-static void sci_shutdown(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
-
- dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
-
- sci_stop_rx(port);
- sci_stop_tx(port);
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- sci_free_dma(port);
-#endif
- sci_free_irq(s);
-
- if (s->disable)
- s->disable(port);
-}
-
-static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- struct sci_port *s = to_sci_port(port);
-#endif
- unsigned int status, baud, smr_val, max_baud;
- int t = -1;
- u16 scfcr = 0;
-
- /*
- * earlyprintk comes here early on with port->uartclk set to zero.
- * the clock framework is not up and running at this point so here
- * we assume that 115200 is the maximum baud rate. please note that
- * the baud rate is not programmed during earlyprintk - it is assumed
- * that the previous boot loader has enabled required clocks and
- * setup the baud rate generator hardware for us already.
- */
- max_baud = port->uartclk ? port->uartclk / 16 : 115200;
-
- baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
- if (likely(baud && port->uartclk))
- t = SCBRR_VALUE(baud, port->uartclk);
-
- do {
- status = sci_in(port, SCxSR);
- } while (!(status & SCxSR_TEND(port)));
-
- sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
-
- if (port->type != PORT_SCI)
- sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
-
- smr_val = sci_in(port, SCSMR) & 3;
- if ((termios->c_cflag & CSIZE) == CS7)
- smr_val |= 0x40;
- if (termios->c_cflag & PARENB)
- smr_val |= 0x20;
- if (termios->c_cflag & PARODD)
- smr_val |= 0x30;
- if (termios->c_cflag & CSTOPB)
- smr_val |= 0x08;
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- sci_out(port, SCSMR, smr_val);
-
- dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
- SCSCR_INIT(port));
-
- if (t > 0) {
- if (t >= 256) {
- sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
- t >>= 2;
- } else
- sci_out(port, SCSMR, sci_in(port, SCSMR) & ~3);
-
- sci_out(port, SCBRR, t);
- udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
- }
-
- sci_init_pins(port, termios->c_cflag);
- sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
-
- sci_out(port, SCSCR, SCSCR_INIT(port));
-
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- /*
- * Calculate delay for 1.5 DMA buffers: see
- * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits
- * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
- * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)."
- * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO
- * sizes), but it has been found out experimentally, that this is not
- * enough: the driver too often needlessly runs on a DMA timeout. 20ms
- * as a minimum seem to work perfectly.
- */
- if (s->chan_rx) {
- s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
- port->fifosize / 2;
- dev_dbg(port->dev,
- "DMA Rx t-out %ums, tty t-out %u jiffies\n",
- s->rx_timeout * 1000 / HZ, port->timeout);
- if (s->rx_timeout < msecs_to_jiffies(20))
- s->rx_timeout = msecs_to_jiffies(20);
- }
-#endif
-
- if ((termios->c_cflag & CREAD) != 0)
- sci_start_rx(port);
-}
-
-static const char *sci_type(struct uart_port *port)
-{
- switch (port->type) {
- case PORT_IRDA:
- return "irda";
- case PORT_SCI:
- return "sci";
- case PORT_SCIF:
- return "scif";
- case PORT_SCIFA:
- return "scifa";
- case PORT_SCIFB:
- return "scifb";
- }
-
- return NULL;
-}
-
-static void sci_release_port(struct uart_port *port)
-{
- /* Nothing here yet .. */
-}
-
-static int sci_request_port(struct uart_port *port)
-{
- /* Nothing here yet .. */
- return 0;
-}
-
-static void sci_config_port(struct uart_port *port, int flags)
-{
- struct sci_port *s = to_sci_port(port);
-
- port->type = s->type;
-
- if (port->membase)
- return;
-
- if (port->flags & UPF_IOREMAP) {
- port->membase = ioremap_nocache(port->mapbase, 0x40);
-
- if (IS_ERR(port->membase))
- dev_err(port->dev, "can't remap port#%d\n", port->line);
- } else {
- /*
- * For the simple (and majority of) cases where we don't
- * need to do any remapping, just cast the cookie
- * directly.
- */
- port->membase = (void __iomem *)port->mapbase;
- }
-}
-
-static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- struct sci_port *s = to_sci_port(port);
-
- if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
- return -EINVAL;
- if (ser->baud_base < 2400)
- /* No paper tape reader for Mitch.. */
- return -EINVAL;
-
- return 0;
-}
-
-static struct uart_ops sci_uart_ops = {
- .tx_empty = sci_tx_empty,
- .set_mctrl = sci_set_mctrl,
- .get_mctrl = sci_get_mctrl,
- .start_tx = sci_start_tx,
- .stop_tx = sci_stop_tx,
- .stop_rx = sci_stop_rx,
- .enable_ms = sci_enable_ms,
- .break_ctl = sci_break_ctl,
- .startup = sci_startup,
- .shutdown = sci_shutdown,
- .set_termios = sci_set_termios,
- .type = sci_type,
- .release_port = sci_release_port,
- .request_port = sci_request_port,
- .config_port = sci_config_port,
- .verify_port = sci_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = sci_poll_get_char,
- .poll_put_char = sci_poll_put_char,
-#endif
-};
-
-static int __devinit sci_init_single(struct platform_device *dev,
- struct sci_port *sci_port,
- unsigned int index,
- struct plat_sci_port *p)
-{
- struct uart_port *port = &sci_port->port;
-
- port->ops = &sci_uart_ops;
- port->iotype = UPIO_MEM;
- port->line = index;
-
- switch (p->type) {
- case PORT_SCIFB:
- port->fifosize = 256;
- break;
- case PORT_SCIFA:
- port->fifosize = 64;
- break;
- case PORT_SCIF:
- port->fifosize = 16;
- break;
- default:
- port->fifosize = 1;
- break;
- }
-
- if (dev) {
- sci_port->iclk = clk_get(&dev->dev, "sci_ick");
- if (IS_ERR(sci_port->iclk)) {
- sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
- if (IS_ERR(sci_port->iclk)) {
- dev_err(&dev->dev, "can't get iclk\n");
- return PTR_ERR(sci_port->iclk);
- }
- }
-
- /*
- * The function clock is optional, ignore it if we can't
- * find it.
- */
- sci_port->fclk = clk_get(&dev->dev, "sci_fck");
- if (IS_ERR(sci_port->fclk))
- sci_port->fclk = NULL;
-
- sci_port->enable = sci_clk_enable;
- sci_port->disable = sci_clk_disable;
- port->dev = &dev->dev;
- }
-
- sci_port->break_timer.data = (unsigned long)sci_port;
- sci_port->break_timer.function = sci_break_timer;
- init_timer(&sci_port->break_timer);
-
- port->mapbase = p->mapbase;
- port->membase = p->membase;
-
- port->irq = p->irqs[SCIx_TXI_IRQ];
- port->flags = p->flags;
- sci_port->type = port->type = p->type;
-
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- sci_port->dma_dev = p->dma_dev;
- sci_port->slave_tx = p->dma_slave_tx;
- sci_port->slave_rx = p->dma_slave_rx;
-
- dev_dbg(port->dev, "%s: DMA device %p, tx %d, rx %d\n", __func__,
- p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
-#endif
-
- memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
- return 0;
-}
-
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-static struct tty_driver *serial_console_device(struct console *co, int *index)
-{
- struct uart_driver *p = &sci_uart_driver;
- *index = co->index;
- return p->tty_driver;
-}
-
-static void serial_console_putchar(struct uart_port *port, int ch)
-{
- sci_poll_put_char(port, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- */
-static void serial_console_write(struct console *co, const char *s,
- unsigned count)
-{
- struct uart_port *port = co->data;
- struct sci_port *sci_port = to_sci_port(port);
- unsigned short bits;
-
- if (sci_port->enable)
- sci_port->enable(port);
-
- uart_console_write(port, s, count, serial_console_putchar);
-
- /* wait until fifo is empty and last bit has been transmitted */
- bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
- while ((sci_in(port, SCxSR) & bits) != bits)
- cpu_relax();
-
- if (sci_port->disable)
- sci_port->disable(port);
-}
-
-static int __devinit serial_console_setup(struct console *co, char *options)
-{
- struct sci_port *sci_port;
- struct uart_port *port;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- int ret;
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= SCI_NPORTS)
- co->index = 0;
-
- if (co->data) {
- port = co->data;
- sci_port = to_sci_port(port);
- } else {
- sci_port = &sci_ports[co->index];
- port = &sci_port->port;
- co->data = port;
- }
-
- /*
- * Also need to check port->type, we don't actually have any
- * UPIO_PORT ports, but uart_report_port() handily misreports
- * it anyways if we don't have a port available by the time this is
- * called.
- */
- if (!port->type)
- return -ENODEV;
-
- sci_config_port(port, 0);
-
- if (sci_port->enable)
- sci_port->enable(port);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- ret = uart_set_options(port, co, baud, parity, bits, flow);
-#if defined(__H8300H__) || defined(__H8300S__)
- /* disable rx interrupt */
- if (ret == 0)
- sci_stop_rx(port);
-#endif
- /* TODO: disable clock */
- return ret;
-}
-
-static struct console serial_console = {
- .name = "ttySC",
- .device = serial_console_device,
- .write = serial_console_write,
- .setup = serial_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-static int __init sci_console_init(void)
-{
- register_console(&serial_console);
- return 0;
-}
-console_initcall(sci_console_init);
-
-static struct sci_port early_serial_port;
-static struct console early_serial_console = {
- .name = "early_ttySC",
- .write = serial_console_write,
- .flags = CON_PRINTBUFFER,
-};
-static char early_serial_buf[32];
-
-#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
-
-#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
-#define SCI_CONSOLE (&serial_console)
-#else
-#define SCI_CONSOLE 0
-#endif
-
-static char banner[] __initdata =
- KERN_INFO "SuperH SCI(F) driver initialized\n";
-
-static struct uart_driver sci_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "sci",
- .dev_name = "ttySC",
- .major = SCI_MAJOR,
- .minor = SCI_MINOR_START,
- .nr = SCI_NPORTS,
- .cons = SCI_CONSOLE,
-};
-
-
-static int sci_remove(struct platform_device *dev)
-{
- struct sh_sci_priv *priv = platform_get_drvdata(dev);
- struct sci_port *p;
- unsigned long flags;
-
- cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
-
- spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry(p, &priv->ports, node) {
- uart_remove_one_port(&sci_uart_driver, &p->port);
- clk_put(p->iclk);
- clk_put(p->fclk);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
- kfree(priv);
- return 0;
-}
-
-static int __devinit sci_probe_single(struct platform_device *dev,
- unsigned int index,
- struct plat_sci_port *p,
- struct sci_port *sciport)
-{
- struct sh_sci_priv *priv = platform_get_drvdata(dev);
- unsigned long flags;
- int ret;
-
- /* Sanity check */
- if (unlikely(index >= SCI_NPORTS)) {
- dev_notice(&dev->dev, "Attempting to register port "
- "%d when only %d are available.\n",
- index+1, SCI_NPORTS);
- dev_notice(&dev->dev, "Consider bumping "
- "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
- return 0;
- }
-
- ret = sci_init_single(dev, sciport, index, p);
- if (ret)
- return ret;
-
- ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
- if (ret)
- return ret;
-
- INIT_LIST_HEAD(&sciport->node);
-
- spin_lock_irqsave(&priv->lock, flags);
- list_add(&sciport->node, &priv->ports);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-/*
- * Register a set of serial devices attached to a platform device. The
- * list is terminated with a zero flags entry, which means we expect
- * all entries to have at least UPF_BOOT_AUTOCONF set. Platforms that need
- * remapping (such as sh64) should also set UPF_IOREMAP.
- */
-static int __devinit sci_probe(struct platform_device *dev)
-{
- struct plat_sci_port *p = dev->dev.platform_data;
- struct sh_sci_priv *priv;
- int i, ret = -EINVAL;
-
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
- if (is_early_platform_device(dev)) {
- if (dev->id == -1)
- return -ENOTSUPP;
- early_serial_console.index = dev->id;
- early_serial_console.data = &early_serial_port.port;
- sci_init_single(NULL, &early_serial_port, dev->id, p);
- serial_console_setup(&early_serial_console, early_serial_buf);
- if (!strstr(early_serial_buf, "keep"))
- early_serial_console.flags |= CON_BOOT;
- register_console(&early_serial_console);
- return 0;
- }
-#endif
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&priv->ports);
- spin_lock_init(&priv->lock);
- platform_set_drvdata(dev, priv);
-
- priv->clk_nb.notifier_call = sci_notifier;
- cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
-
- if (dev->id != -1) {
- ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]);
- if (ret)
- goto err_unreg;
- } else {
- for (i = 0; p && p->flags != 0; p++, i++) {
- ret = sci_probe_single(dev, i, p, &sci_ports[i]);
- if (ret)
- goto err_unreg;
- }
- }
-
-#ifdef CONFIG_SH_STANDARD_BIOS
- sh_bios_gdb_detach();
-#endif
-
- return 0;
-
-err_unreg:
- sci_remove(dev);
- return ret;
-}
-
-static int sci_suspend(struct device *dev)
-{
- struct sh_sci_priv *priv = dev_get_drvdata(dev);
- struct sci_port *p;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry(p, &priv->ports, node)
- uart_suspend_port(&sci_uart_driver, &p->port);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static int sci_resume(struct device *dev)
-{
- struct sh_sci_priv *priv = dev_get_drvdata(dev);
- struct sci_port *p;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry(p, &priv->ports, node)
- uart_resume_port(&sci_uart_driver, &p->port);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static const struct dev_pm_ops sci_dev_pm_ops = {
- .suspend = sci_suspend,
- .resume = sci_resume,
-};
-
-static struct platform_driver sci_driver = {
- .probe = sci_probe,
- .remove = sci_remove,
- .driver = {
- .name = "sh-sci",
- .owner = THIS_MODULE,
- .pm = &sci_dev_pm_ops,
- },
-};
-
-static int __init sci_init(void)
-{
- int ret;
-
- printk(banner);
-
- ret = uart_register_driver(&sci_uart_driver);
- if (likely(ret == 0)) {
- ret = platform_driver_register(&sci_driver);
- if (unlikely(ret))
- uart_unregister_driver(&sci_uart_driver);
- }
-
- return ret;
-}
-
-static void __exit sci_exit(void)
-{
- platform_driver_unregister(&sci_driver);
- uart_unregister_driver(&sci_uart_driver);
-}
-
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-early_platform_init_buffer("earlyprintk", &sci_driver,
- early_serial_buf, ARRAY_SIZE(early_serial_buf));
-#endif
-module_init(sci_init);
-module_exit(sci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:sh-sci");
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
deleted file mode 100644
index 4bc614e4221c..000000000000
--- a/drivers/serial/sh-sci.h
+++ /dev/null
@@ -1,660 +0,0 @@
-#include <linux/serial_core.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-#endif
-#if defined(CONFIG_H8S2678)
-#include <asm/regs267x.h>
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
- defined(CONFIG_CPU_SUBTYPE_SH7707) || \
- defined(CONFIG_CPU_SUBTYPE_SH7708) || \
- defined(CONFIG_CPU_SUBTYPE_SH7709)
-# define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */
-# define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */
-# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-# define SCIF0 0xA4400000
-# define SCIF2 0xA4410000
-# define SCSMR_Ir 0xA44A0000
-# define IRDA_SCIF SCIF0
-# define SCPCR 0xA4000116
-# define SCPDR 0xA4000136
-
-/* Set the clock source,
- * SCIF2 (0xA4410000) -> External clock, SCK pin used as clock input
- * SCIF0 (0xA4400000) -> Internal clock, SCK pin as serial clock output
- */
-# define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_SH7367) || \
- defined(CONFIG_ARCH_SH7377) || \
- defined(CONFIG_ARCH_SH7372)
-# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
-# define PORT_PTCR 0xA405011EUL
-# define PORT_PVCR 0xA4050122UL
-# define SCIF_ORER 0x0200 /* overrun error bit */
-#elif defined(CONFIG_SH_RTS7751R2D)
-# define SCSPTR1 0xFFE0001C /* 8 bit SCIF */
-# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
- defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
- defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
- defined(CONFIG_CPU_SUBTYPE_SH7091) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751R)
-# define SCSPTR1 0xffe0001c /* 8 bit SCI */
-# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \
- 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \
- 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ )
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-# define SCSPTR0 0xfe600024 /* 16 bit SCIF */
-# define SCSPTR1 0xfe610024 /* 16 bit SCIF */
-# define SCSPTR2 0xfe620024 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-# define SCSPTR0 0xA4400000 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define PACR 0xa4050100
-# define PBCR 0xa4050102
-# define SCSCR_INIT(port) 0x3B
-#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
-# define SCSPTR0 0xffe00010 /* 16 bit SCIF */
-# define SCSPTR1 0xffe10010 /* 16 bit SCIF */
-# define SCSPTR2 0xffe20010 /* 16 bit SCIF */
-# define SCSPTR3 0xffe30010 /* 16 bit SCIF */
-# define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-# define PADR 0xA4050120
-# define PSDR 0xA405013e
-# define PWDR 0xA4050166
-# define PSCR 0xA405011E
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7366)
-# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */
-# define SCSPTR0 SCPDR0
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-# define SCSPTR0 0xa4050160
-# define SCSPTR1 0xa405013e
-# define SCSPTR2 0xa4050160
-# define SCSPTR3 0xa405013e
-# define SCSPTR4 0xa4050128
-# define SCSPTR5 0xa4050128
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) ((port)->type == PORT_SCIFA ? \
- 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \
- 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ )
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
-# define SCIF_BASE_ADDR 0x01030000
-# define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
-# define SCIF_PTR2_OFFS 0x0000020
-# define SCIF_LSR2_OFFS 0x0000024
-# define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
-# define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
-# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
-# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
-#elif defined(CONFIG_H8S2678)
-# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
-# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
-# define SCSPTR0 0xfe4b0020
-# define SCSPTR1 0xfe4b0020
-# define SCSPTR2 0xfe4b0020
-# define SCIF_ORER 0x0001
-# define SCSCR_INIT(port) 0x38
-# define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
-# define SCSPTR1 0xffe08024 /* 16 bit SCIF */
-# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-# define SCSPTR0 0xff923020 /* 16 bit SCIF */
-# define SCSPTR1 0xff924020 /* 16 bit SCIF */
-# define SCSPTR2 0xff925020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
-# define SCSPTR1 0xffe10024 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* Overrun error bit */
-
-#if defined(CONFIG_SH_SH2007)
-/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=0 */
-# define SCSCR_INIT(port) 0x38
-#else
-/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */
-# define SCSCR_INIT(port) 0x3a
-#endif
-
-#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
- defined(CONFIG_CPU_SUBTYPE_SH7786)
-# define SCSPTR0 0xffea0024 /* 16 bit SCIF */
-# define SCSPTR1 0xffeb0024 /* 16 bit SCIF */
-# define SCSPTR2 0xffec0024 /* 16 bit SCIF */
-# define SCSPTR3 0xffed0024 /* 16 bit SCIF */
-# define SCSPTR4 0xffee0024 /* 16 bit SCIF */
-# define SCSPTR5 0xffef0024 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* Overrun error bit */
-# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
- defined(CONFIG_CPU_SUBTYPE_SH7203) || \
- defined(CONFIG_CPU_SUBTYPE_SH7206) || \
- defined(CONFIG_CPU_SUBTYPE_SH7263)
-# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
-# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */
-# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */
-# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */
-# if defined(CONFIG_CPU_SUBTYPE_SH7201)
-# define SCSPTR4 0xfffeA020 /* 16 bit SCIF */
-# define SCSPTR5 0xfffeA820 /* 16 bit SCIF */
-# define SCSPTR6 0xfffeB020 /* 16 bit SCIF */
-# define SCSPTR7 0xfffeB820 /* 16 bit SCIF */
-# endif
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-# define SCSPTR0 0xf8400020 /* 16 bit SCIF */
-# define SCSPTR1 0xf8410020 /* 16 bit SCIF */
-# define SCSPTR2 0xf8420020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
-# define SCSPTR0 0xffc30020 /* 16 bit SCIF */
-# define SCSPTR1 0xffc40020 /* 16 bit SCIF */
-# define SCSPTR2 0xffc50020 /* 16 bit SCIF */
-# define SCSPTR3 0xffc60020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* Overrun error bit */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#else
-# error CPU subtype not defined
-#endif
-
-/* SCSCR */
-#define SCI_CTRL_FLAGS_TIE 0x80 /* all */
-#define SCI_CTRL_FLAGS_RIE 0x40 /* all */
-#define SCI_CTRL_FLAGS_TE 0x20 /* all */
-#define SCI_CTRL_FLAGS_RE 0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
- defined(CONFIG_CPU_SUBTYPE_SH7091) || \
- defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
- defined(CONFIG_CPU_SUBTYPE_SH7722) || \
- defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
- defined(CONFIG_CPU_SUBTYPE_SH7763) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785) || \
- defined(CONFIG_CPU_SUBTYPE_SH7786) || \
- defined(CONFIG_CPU_SUBTYPE_SHX3)
-#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
-#define SCI_CTRL_FLAGS_REIE ((port)->type == PORT_SCIFA ? 0 : 8)
-#else
-#define SCI_CTRL_FLAGS_REIE 0
-#endif
-/* SCI_CTRL_FLAGS_MPIE 0x08 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/* SCI_CTRL_FLAGS_TEIE 0x04 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/* SCI_CTRL_FLAGS_CKE1 0x02 * all */
-/* SCI_CTRL_FLAGS_CKE0 0x01 * 7707 SCI/SCIF, 7708 SCI, 7709 SCI/SCIF, 7750 SCI */
-
-/* SCxSR SCI */
-#define SCI_TDRE 0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_RDRF 0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_ORER 0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_FER 0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_PER 0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_TEND 0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/* SCI_MPB 0x02 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/* SCI_MPBT 0x01 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-
-#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
-
-/* SCxSR SCIF */
-#define SCIF_ER 0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_TEND 0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_TDFE 0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_BRK 0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_FER 0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_PER 0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_RDF 0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_DR 0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_SH7367) || \
- defined(CONFIG_ARCH_SH7377) || \
- defined(CONFIG_ARCH_SH7372)
-# define SCIF_ORER 0x0200
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
-# define SCIF_RFDC_MASK 0x007f
-# define SCIF_TXROOM_MAX 64
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK )
-# define SCIF_RFDC_MASK 0x007f
-# define SCIF_TXROOM_MAX 64
-/* SH7763 SCIF2 support */
-# define SCIF2_RFDC_MASK 0x001f
-# define SCIF2_TXROOM_MAX 16
-#else
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
-# define SCIF_RFDC_MASK 0x001f
-# define SCIF_TXROOM_MAX 16
-#endif
-
-#ifndef SCIF_ORER
-#define SCIF_ORER 0x0000
-#endif
-
-#define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
-#define SCxSR_ERRORS(port) (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS)
-#define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF)
-#define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE)
-#define SCxSR_FER(port) (((port)->type == PORT_SCI) ? SCI_FER : SCIF_FER)
-#define SCxSR_PER(port) (((port)->type == PORT_SCI) ? SCI_PER : SCIF_PER)
-#define SCxSR_BRK(port) (((port)->type == PORT_SCI) ? 0x00 : SCIF_BRK)
-#define SCxSR_ORER(port) (((port)->type == PORT_SCI) ? SCI_ORER : SCIF_ORER)
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_SH7367) || \
- defined(CONFIG_ARCH_SH7377) || \
- defined(CONFIG_ARCH_SH7372)
-# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc)
-# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
-# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf)
-# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3)
-#else
-# define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc)
-# define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073)
-# define SCxSR_TDxE_CLEAR(port) (((port)->type == PORT_SCI) ? 0x78 : 0x00df)
-# define SCxSR_BREAK_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x00e3)
-#endif
-
-/* SCFCR */
-#define SCFCR_RFRST 0x0002
-#define SCFCR_TFRST 0x0004
-#define SCFCR_TCRST 0x4000
-#define SCFCR_MCE 0x0008
-
-#define SCI_MAJOR 204
-#define SCI_MINOR_START 8
-
-/* Generic serial flags */
-#define SCI_RX_THROTTLE 0x0000001
-
-#define SCI_MAGIC 0xbabeface
-
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at rs interrupt time.
- */
-#define SCI_EVENT_WRITE_WAKEUP 0
-
-#define SCI_IN(size, offset) \
- if ((size) == 8) { \
- return ioread8(port->membase + (offset)); \
- } else { \
- return ioread16(port->membase + (offset)); \
- }
-#define SCI_OUT(size, offset, value) \
- if ((size) == 8) { \
- iowrite8(value, port->membase + (offset)); \
- } else if ((size) == 16) { \
- iowrite16(value, port->membase + (offset)); \
- }
-
-#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
- static inline unsigned int sci_##name##_in(struct uart_port *port) \
- { \
- if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \
- SCI_IN(scif_size, scif_offset) \
- } else { /* PORT_SCI or PORT_SCIFA */ \
- SCI_IN(sci_size, sci_offset); \
- } \
- } \
- static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
- { \
- if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \
- SCI_OUT(scif_size, scif_offset, value) \
- } else { /* PORT_SCI or PORT_SCIFA */ \
- SCI_OUT(sci_size, sci_offset, value); \
- } \
- }
-
-#ifdef CONFIG_H8300
-/* h8300 don't have SCIF */
-#define CPU_SCIF_FNS(name) \
- static inline unsigned int sci_##name##_in(struct uart_port *port) \
- { \
- return 0; \
- } \
- static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
- { \
- }
-#else
-#define CPU_SCIF_FNS(name, scif_offset, scif_size) \
- static inline unsigned int sci_##name##_in(struct uart_port *port) \
- { \
- SCI_IN(scif_size, scif_offset); \
- } \
- static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
- { \
- SCI_OUT(scif_size, scif_offset, value); \
- }
-#endif
-
-#define CPU_SCI_FNS(name, sci_offset, sci_size) \
- static inline unsigned int sci_##name##_in(struct uart_port* port) \
- { \
- SCI_IN(sci_size, sci_offset); \
- } \
- static inline void sci_##name##_out(struct uart_port* port, unsigned int value) \
- { \
- SCI_OUT(sci_size, sci_offset, value); \
- }
-
-#if defined(CONFIG_CPU_SH3) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_SH7367) || \
- defined(CONFIG_ARCH_SH7377) || \
- defined(CONFIG_ARCH_SH7372)
-#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
- sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
- h8_sci_offset, h8_sci_size) \
- CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
- CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_SH7367) || \
- defined(CONFIG_ARCH_SH7377)
-#define SCIF_FNS(name, scif_offset, scif_size) \
- CPU_SCIF_FNS(name, scif_offset, scif_size)
-#elif defined(CONFIG_ARCH_SH7372)
-#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \
- CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size)
-#define SCIF_FNS(name, scif_offset, scif_size) \
- CPU_SCIF_FNS(name, scif_offset, scif_size)
-#else
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
- sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
- h8_sci_offset, h8_sci_size) \
- CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh3_scif_offset, sh3_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
- CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size)
-#endif
-#elif defined(__H8300H__) || defined(__H8300S__)
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
- sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
- h8_sci_offset, h8_sci_size) \
- CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
- CPU_SCIF_FNS(name)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
- defined(CONFIG_CPU_SUBTYPE_SH7724)
- #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
- CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
- #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
- CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#else
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
- sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
- h8_sci_offset, h8_sci_size) \
- CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
- CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_SH7367) || \
- defined(CONFIG_ARCH_SH7377)
-
-SCIF_FNS(SCSMR, 0x00, 16)
-SCIF_FNS(SCBRR, 0x04, 8)
-SCIF_FNS(SCSCR, 0x08, 16)
-SCIF_FNS(SCTDSR, 0x0c, 8)
-SCIF_FNS(SCFER, 0x10, 16)
-SCIF_FNS(SCxSR, 0x14, 16)
-SCIF_FNS(SCFCR, 0x18, 16)
-SCIF_FNS(SCFDR, 0x1c, 16)
-SCIF_FNS(SCxTDR, 0x20, 8)
-SCIF_FNS(SCxRDR, 0x24, 8)
-SCIF_FNS(SCLSR, 0x00, 0)
-#elif defined(CONFIG_ARCH_SH7372)
-SCIF_FNS(SCSMR, 0x00, 16)
-SCIF_FNS(SCBRR, 0x04, 8)
-SCIF_FNS(SCSCR, 0x08, 16)
-SCIF_FNS(SCTDSR, 0x0c, 16)
-SCIF_FNS(SCFER, 0x10, 16)
-SCIF_FNS(SCxSR, 0x14, 16)
-SCIF_FNS(SCFCR, 0x18, 16)
-SCIF_FNS(SCFDR, 0x1c, 16)
-SCIF_FNS(SCTFDR, 0x38, 16)
-SCIF_FNS(SCRFDR, 0x3c, 16)
-SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8)
-SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8)
-SCIF_FNS(SCLSR, 0x00, 0)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
- defined(CONFIG_CPU_SUBTYPE_SH7724)
-SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
-SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8)
-SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16)
-SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8)
-SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16)
-SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8)
-SCIx_FNS(SCSPTR, 0, 0, 0, 0)
-SCIF_FNS(SCTDSR, 0x0c, 8)
-SCIF_FNS(SCFER, 0x10, 16)
-SCIF_FNS(SCFCR, 0x18, 16)
-SCIF_FNS(SCFDR, 0x1c, 16)
-SCIF_FNS(SCLSR, 0x24, 16)
-#else
-/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
-/* name off sz off sz off sz off sz off sz*/
-SCIx_FNS(SCSMR, 0x00, 8, 0x00, 8, 0x00, 8, 0x00, 16, 0x00, 8)
-SCIx_FNS(SCBRR, 0x02, 8, 0x04, 8, 0x02, 8, 0x04, 8, 0x01, 8)
-SCIx_FNS(SCSCR, 0x04, 8, 0x08, 8, 0x04, 8, 0x08, 16, 0x02, 8)
-SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8, 0x03, 8)
-SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8)
-SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8)
-SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16)
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785) || \
- defined(CONFIG_CPU_SUBTYPE_SH7786)
-SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
-SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
-SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-SCIF_FNS(SCFDR, 0, 0, 0x1C, 16)
-SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16)
-SCIF_FNS(SCLSR2, 0, 0, 0x24, 16)
-SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
-SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
-SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
-#else
-SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-SCIF_FNS(SCSPTR, 0, 0, 0, 0)
-#else
-SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
-#endif
-SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
-#endif
-#endif
-#define sci_in(port, reg) sci_##reg##_in(port)
-#define sci_out(port, reg, value) sci_##reg##_out(port, value)
-
-/* H8/300 series SCI pins assignment */
-#if defined(__H8300H__) || defined(__H8300S__)
-static const struct __attribute__((packed)) {
- int port; /* GPIO port no */
- unsigned short rx,tx; /* GPIO bit no */
-} h8300_sci_pins[] = {
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
- { /* SCI0 */
- .port = H8300_GPIO_P9,
- .rx = H8300_GPIO_B2,
- .tx = H8300_GPIO_B0,
- },
- { /* SCI1 */
- .port = H8300_GPIO_P9,
- .rx = H8300_GPIO_B3,
- .tx = H8300_GPIO_B1,
- },
- { /* SCI2 */
- .port = H8300_GPIO_PB,
- .rx = H8300_GPIO_B7,
- .tx = H8300_GPIO_B6,
- }
-#elif defined(CONFIG_H8S2678)
- { /* SCI0 */
- .port = H8300_GPIO_P3,
- .rx = H8300_GPIO_B2,
- .tx = H8300_GPIO_B0,
- },
- { /* SCI1 */
- .port = H8300_GPIO_P3,
- .rx = H8300_GPIO_B3,
- .tx = H8300_GPIO_B1,
- },
- { /* SCI2 */
- .port = H8300_GPIO_P5,
- .rx = H8300_GPIO_B1,
- .tx = H8300_GPIO_B0,
- }
-#endif
-};
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
- defined(CONFIG_CPU_SUBTYPE_SH7707) || \
- defined(CONFIG_CPU_SUBTYPE_SH7708) || \
- defined(CONFIG_CPU_SUBTYPE_SH7709)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xfffffe80)
- return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
- defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
- defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
- defined(CONFIG_CPU_SUBTYPE_SH7091)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
- return 1;
-}
-#elif defined(__H8300H__) || defined(__H8300S__)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- int ch = (port->mapbase - SMR0) >> 3;
- return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
-}
-#else /* default case for non-SCI processors */
-static inline int sci_rxd_in(struct uart_port *port)
-{
- return 1;
-}
-#endif
-
-/*
- * Values for the BitRate Register (SCBRR)
- *
- * The values are actually divisors for a frequency which can
- * be internal to the SH3 (14.7456MHz) or derived from an external
- * clock source. This driver assumes the internal clock is used;
- * to support using an external clock source, config options or
- * possibly command-line options would need to be added.
- *
- * Also, to support speeds below 2400 (why?) the lower 2 bits of
- * the SCSMR register would also need to be set to non-zero values.
- *
- * -- Greg Banks 27Feb2000
- *
- * Answer: The SCBRR register is only eight bits, and the value in
- * it gets larger with lower baud rates. At around 2400 (depending on
- * the peripherial module clock) you run out of bits. However the
- * lower two bits of SCSMR allow the module clock to be divided down,
- * scaling the value which is needed in SCBRR.
- *
- * -- Stuart Menefy - 23 May 2000
- *
- * I meant, why would anyone bother with bitrates below 2400.
- *
- * -- Greg Banks - 7Jul2000
- *
- * You "speedist"! How will I use my 110bps ASR-33 teletype with paper
- * tape reader as a console!
- *
- * -- Mitch Davis - 15 Jul 2000
- */
-
-#if (defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785) || \
- defined(CONFIG_CPU_SUBTYPE_SH7786)) && \
- !defined(CONFIG_SH_SH2007)
-#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_SH7367) || \
- defined(CONFIG_ARCH_SH7377) || \
- defined(CONFIG_ARCH_SH7372)
-#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
- defined(CONFIG_CPU_SUBTYPE_SH7724)
-static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
-{
- if (port->type == PORT_SCIF)
- return (clk+16*bps)/(32*bps)-1;
- else
- return ((clk*2)+16*bps)/(16*bps)-1;
-}
-#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
-#elif defined(__H8300H__) || defined(__H8300S__)
-#define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1)
-#else /* Generic SH */
-#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
-#endif
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
deleted file mode 100644
index cff9a306660f..000000000000
--- a/drivers/serial/sn_console.c
+++ /dev/null
@@ -1,1085 +0,0 @@
-/*
- * C-Brick Serial Port (and console) driver for SGI Altix machines.
- *
- * This driver is NOT suitable for talking to the l1-controller for
- * anything other than 'console activities' --- please use the l1
- * driver for that.
- *
- *
- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/module.h>
-#include <linux/sysrq.h>
-#include <linux/circ_buf.h>
-#include <linux/serial_reg.h>
-#include <linux/delay.h> /* for mdelay */
-#include <linux/miscdevice.h>
-#include <linux/serial_core.h>
-
-#include <asm/io.h>
-#include <asm/sn/simulator.h>
-#include <asm/sn/sn_sal.h>
-
-/* number of characters we can transmit to the SAL console at a time */
-#define SN_SAL_MAX_CHARS 120
-
-/* 64K, when we're asynch, it must be at least printk's LOG_BUF_LEN to
- * avoid losing chars, (always has to be a power of 2) */
-#define SN_SAL_BUFFER_SIZE (64 * (1 << 10))
-
-#define SN_SAL_UART_FIFO_DEPTH 16
-#define SN_SAL_UART_FIFO_SPEED_CPS (9600/10)
-
-/* sn_transmit_chars() calling args */
-#define TRANSMIT_BUFFERED 0
-#define TRANSMIT_RAW 1
-
-/* To use dynamic numbers only and not use the assigned major and minor,
- * define the following.. */
- /* #define USE_DYNAMIC_MINOR 1 *//* use dynamic minor number */
-#define USE_DYNAMIC_MINOR 0 /* Don't rely on misc_register dynamic minor */
-
-/* Device name we're using */
-#define DEVICE_NAME "ttySG"
-#define DEVICE_NAME_DYNAMIC "ttySG0" /* need full name for misc_register */
-/* The major/minor we are using, ignored for USE_DYNAMIC_MINOR */
-#define DEVICE_MAJOR 204
-#define DEVICE_MINOR 40
-
-#ifdef CONFIG_MAGIC_SYSRQ
-static char sysrq_serial_str[] = "\eSYS";
-static char *sysrq_serial_ptr = sysrq_serial_str;
-static unsigned long sysrq_requested;
-#endif /* CONFIG_MAGIC_SYSRQ */
-
-/*
- * Port definition - this kinda drives it all
- */
-struct sn_cons_port {
- struct timer_list sc_timer;
- struct uart_port sc_port;
- struct sn_sal_ops {
- int (*sal_puts_raw) (const char *s, int len);
- int (*sal_puts) (const char *s, int len);
- int (*sal_getc) (void);
- int (*sal_input_pending) (void);
- void (*sal_wakeup_transmit) (struct sn_cons_port *, int);
- } *sc_ops;
- unsigned long sc_interrupt_timeout;
- int sc_is_asynch;
-};
-
-static struct sn_cons_port sal_console_port;
-static int sn_process_input;
-
-/* Only used if USE_DYNAMIC_MINOR is set to 1 */
-static struct miscdevice misc; /* used with misc_register for dynamic */
-
-extern void early_sn_setup(void);
-
-#undef DEBUG
-#ifdef DEBUG
-static int sn_debug_printf(const char *fmt, ...);
-#define DPRINTF(x...) sn_debug_printf(x)
-#else
-#define DPRINTF(x...) do { } while (0)
-#endif
-
-/* Prototypes */
-static int snt_hw_puts_raw(const char *, int);
-static int snt_hw_puts_buffered(const char *, int);
-static int snt_poll_getc(void);
-static int snt_poll_input_pending(void);
-static int snt_intr_getc(void);
-static int snt_intr_input_pending(void);
-static void sn_transmit_chars(struct sn_cons_port *, int);
-
-/* A table for polling:
- */
-static struct sn_sal_ops poll_ops = {
- .sal_puts_raw = snt_hw_puts_raw,
- .sal_puts = snt_hw_puts_raw,
- .sal_getc = snt_poll_getc,
- .sal_input_pending = snt_poll_input_pending
-};
-
-/* A table for interrupts enabled */
-static struct sn_sal_ops intr_ops = {
- .sal_puts_raw = snt_hw_puts_raw,
- .sal_puts = snt_hw_puts_buffered,
- .sal_getc = snt_intr_getc,
- .sal_input_pending = snt_intr_input_pending,
- .sal_wakeup_transmit = sn_transmit_chars
-};
-
-/* the console does output in two distinctly different ways:
- * synchronous (raw) and asynchronous (buffered). initally, early_printk
- * does synchronous output. any data written goes directly to the SAL
- * to be output (incidentally, it is internally buffered by the SAL)
- * after interrupts and timers are initialized and available for use,
- * the console init code switches to asynchronous output. this is
- * also the earliest opportunity to begin polling for console input.
- * after console initialization, console output and tty (serial port)
- * output is buffered and sent to the SAL asynchronously (either by
- * timer callback or by UART interrupt) */
-
-/* routines for running the console in polling mode */
-
-/**
- * snt_poll_getc - Get a character from the console in polling mode
- *
- */
-static int snt_poll_getc(void)
-{
- int ch;
-
- ia64_sn_console_getc(&ch);
- return ch;
-}
-
-/**
- * snt_poll_input_pending - Check if any input is waiting - polling mode.
- *
- */
-static int snt_poll_input_pending(void)
-{
- int status, input;
-
- status = ia64_sn_console_check(&input);
- return !status && input;
-}
-
-/* routines for an interrupt driven console (normal) */
-
-/**
- * snt_intr_getc - Get a character from the console, interrupt mode
- *
- */
-static int snt_intr_getc(void)
-{
- return ia64_sn_console_readc();
-}
-
-/**
- * snt_intr_input_pending - Check if input is pending, interrupt mode
- *
- */
-static int snt_intr_input_pending(void)
-{
- return ia64_sn_console_intr_status() & SAL_CONSOLE_INTR_RECV;
-}
-
-/* these functions are polled and interrupt */
-
-/**
- * snt_hw_puts_raw - Send raw string to the console, polled or interrupt mode
- * @s: String
- * @len: Length
- *
- */
-static int snt_hw_puts_raw(const char *s, int len)
-{
- /* this will call the PROM and not return until this is done */
- return ia64_sn_console_putb(s, len);
-}
-
-/**
- * snt_hw_puts_buffered - Send string to console, polled or interrupt mode
- * @s: String
- * @len: Length
- *
- */
-static int snt_hw_puts_buffered(const char *s, int len)
-{
- /* queue data to the PROM */
- return ia64_sn_console_xmit_chars((char *)s, len);
-}
-
-/* uart interface structs
- * These functions are associated with the uart_port that the serial core
- * infrastructure calls.
- *
- * Note: Due to how the console works, many routines are no-ops.
- */
-
-/**
- * snp_type - What type of console are we?
- * @port: Port to operate with (we ignore since we only have one port)
- *
- */
-static const char *snp_type(struct uart_port *port)
-{
- return ("SGI SN L1");
-}
-
-/**
- * snp_tx_empty - Is the transmitter empty? We pretend we're always empty
- * @port: Port to operate on (we ignore since we only have one port)
- *
- */
-static unsigned int snp_tx_empty(struct uart_port *port)
-{
- return 1;
-}
-
-/**
- * snp_stop_tx - stop the transmitter - no-op for us
- * @port: Port to operat eon - we ignore - no-op function
- *
- */
-static void snp_stop_tx(struct uart_port *port)
-{
-}
-
-/**
- * snp_release_port - Free i/o and resources for port - no-op for us
- * @port: Port to operate on - we ignore - no-op function
- *
- */
-static void snp_release_port(struct uart_port *port)
-{
-}
-
-/**
- * snp_enable_ms - Force modem status interrupts on - no-op for us
- * @port: Port to operate on - we ignore - no-op function
- *
- */
-static void snp_enable_ms(struct uart_port *port)
-{
-}
-
-/**
- * snp_shutdown - shut down the port - free irq and disable - no-op for us
- * @port: Port to shut down - we ignore
- *
- */
-static void snp_shutdown(struct uart_port *port)
-{
-}
-
-/**
- * snp_set_mctrl - set control lines (dtr, rts, etc) - no-op for our console
- * @port: Port to operate on - we ignore
- * @mctrl: Lines to set/unset - we ignore
- *
- */
-static void snp_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-/**
- * snp_get_mctrl - get contorl line info, we just return a static value
- * @port: port to operate on - we only have one port so we ignore this
- *
- */
-static unsigned int snp_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS;
-}
-
-/**
- * snp_stop_rx - Stop the receiver - we ignor ethis
- * @port: Port to operate on - we ignore
- *
- */
-static void snp_stop_rx(struct uart_port *port)
-{
-}
-
-/**
- * snp_start_tx - Start transmitter
- * @port: Port to operate on
- *
- */
-static void snp_start_tx(struct uart_port *port)
-{
- if (sal_console_port.sc_ops->sal_wakeup_transmit)
- sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port,
- TRANSMIT_BUFFERED);
-
-}
-
-/**
- * snp_break_ctl - handle breaks - ignored by us
- * @port: Port to operate on
- * @break_state: Break state
- *
- */
-static void snp_break_ctl(struct uart_port *port, int break_state)
-{
-}
-
-/**
- * snp_startup - Start up the serial port - always return 0 (We're always on)
- * @port: Port to operate on
- *
- */
-static int snp_startup(struct uart_port *port)
-{
- return 0;
-}
-
-/**
- * snp_set_termios - set termios stuff - we ignore these
- * @port: port to operate on
- * @termios: New settings
- * @termios: Old
- *
- */
-static void
-snp_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
-}
-
-/**
- * snp_request_port - allocate resources for port - ignored by us
- * @port: port to operate on
- *
- */
-static int snp_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/**
- * snp_config_port - allocate resources, set up - we ignore, we're always on
- * @port: Port to operate on
- * @flags: flags used for port setup
- *
- */
-static void snp_config_port(struct uart_port *port, int flags)
-{
-}
-
-/* Associate the uart functions above - given to serial core */
-
-static struct uart_ops sn_console_ops = {
- .tx_empty = snp_tx_empty,
- .set_mctrl = snp_set_mctrl,
- .get_mctrl = snp_get_mctrl,
- .stop_tx = snp_stop_tx,
- .start_tx = snp_start_tx,
- .stop_rx = snp_stop_rx,
- .enable_ms = snp_enable_ms,
- .break_ctl = snp_break_ctl,
- .startup = snp_startup,
- .shutdown = snp_shutdown,
- .set_termios = snp_set_termios,
- .pm = NULL,
- .type = snp_type,
- .release_port = snp_release_port,
- .request_port = snp_request_port,
- .config_port = snp_config_port,
- .verify_port = NULL,
-};
-
-/* End of uart struct functions and defines */
-
-#ifdef DEBUG
-
-/**
- * sn_debug_printf - close to hardware debugging printf
- * @fmt: printf format
- *
- * This is as "close to the metal" as we can get, used when the driver
- * itself may be broken.
- *
- */
-static int sn_debug_printf(const char *fmt, ...)
-{
- static char printk_buf[1024];
- int printed_len;
- va_list args;
-
- va_start(args, fmt);
- printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
-
- if (!sal_console_port.sc_ops) {
- sal_console_port.sc_ops = &poll_ops;
- early_sn_setup();
- }
- sal_console_port.sc_ops->sal_puts_raw(printk_buf, printed_len);
-
- va_end(args);
- return printed_len;
-}
-#endif /* DEBUG */
-
-/*
- * Interrupt handling routines.
- */
-
-/**
- * sn_receive_chars - Grab characters, pass them to tty layer
- * @port: Port to operate on
- * @flags: irq flags
- *
- * Note: If we're not registered with the serial core infrastructure yet,
- * we don't try to send characters to it...
- *
- */
-static void
-sn_receive_chars(struct sn_cons_port *port, unsigned long flags)
-{
- int ch;
- struct tty_struct *tty;
-
- if (!port) {
- printk(KERN_ERR "sn_receive_chars - port NULL so can't receieve\n");
- return;
- }
-
- if (!port->sc_ops) {
- printk(KERN_ERR "sn_receive_chars - port->sc_ops NULL so can't receieve\n");
- return;
- }
-
- if (port->sc_port.state) {
- /* The serial_core stuffs are initialized, use them */
- tty = port->sc_port.state->port.tty;
- }
- else {
- /* Not registered yet - can't pass to tty layer. */
- tty = NULL;
- }
-
- while (port->sc_ops->sal_input_pending()) {
- ch = port->sc_ops->sal_getc();
- if (ch < 0) {
- printk(KERN_ERR "sn_console: An error occured while "
- "obtaining data from the console (0x%0x)\n", ch);
- break;
- }
-#ifdef CONFIG_MAGIC_SYSRQ
- if (sysrq_requested) {
- unsigned long sysrq_timeout = sysrq_requested + HZ*5;
-
- sysrq_requested = 0;
- if (ch && time_before(jiffies, sysrq_timeout)) {
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- handle_sysrq(ch);
- spin_lock_irqsave(&port->sc_port.lock, flags);
- /* ignore actual sysrq command char */
- continue;
- }
- }
- if (ch == *sysrq_serial_ptr) {
- if (!(*++sysrq_serial_ptr)) {
- sysrq_requested = jiffies;
- sysrq_serial_ptr = sysrq_serial_str;
- }
- /*
- * ignore the whole sysrq string except for the
- * leading escape
- */
- if (ch != '\e')
- continue;
- }
- else
- sysrq_serial_ptr = sysrq_serial_str;
-#endif /* CONFIG_MAGIC_SYSRQ */
-
- /* record the character to pass up to the tty layer */
- if (tty) {
- if(tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
- break;
- }
- port->sc_port.icount.rx++;
- }
-
- if (tty)
- tty_flip_buffer_push(tty);
-}
-
-/**
- * sn_transmit_chars - grab characters from serial core, send off
- * @port: Port to operate on
- * @raw: Transmit raw or buffered
- *
- * Note: If we're early, before we're registered with serial core, the
- * writes are going through sn_sal_console_write because that's how
- * register_console has been set up. We currently could have asynch
- * polls calling this function due to sn_sal_switch_to_asynch but we can
- * ignore them until we register with the serial core stuffs.
- *
- */
-static void sn_transmit_chars(struct sn_cons_port *port, int raw)
-{
- int xmit_count, tail, head, loops, ii;
- int result;
- char *start;
- struct circ_buf *xmit;
-
- if (!port)
- return;
-
- BUG_ON(!port->sc_is_asynch);
-
- if (port->sc_port.state) {
- /* We're initialized, using serial core infrastructure */
- xmit = &port->sc_port.state->xmit;
- } else {
- /* Probably sn_sal_switch_to_asynch has been run but serial core isn't
- * initialized yet. Just return. Writes are going through
- * sn_sal_console_write (due to register_console) at this time.
- */
- return;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&port->sc_port)) {
- /* Nothing to do. */
- ia64_sn_console_intr_disable(SAL_CONSOLE_INTR_XMIT);
- return;
- }
-
- head = xmit->head;
- tail = xmit->tail;
- start = &xmit->buf[tail];
-
- /* twice around gets the tail to the end of the buffer and
- * then to the head, if needed */
- loops = (head < tail) ? 2 : 1;
-
- for (ii = 0; ii < loops; ii++) {
- xmit_count = (head < tail) ?
- (UART_XMIT_SIZE - tail) : (head - tail);
-
- if (xmit_count > 0) {
- if (raw == TRANSMIT_RAW)
- result =
- port->sc_ops->sal_puts_raw(start,
- xmit_count);
- else
- result =
- port->sc_ops->sal_puts(start, xmit_count);
-#ifdef DEBUG
- if (!result)
- DPRINTF("`");
-#endif
- if (result > 0) {
- xmit_count -= result;
- port->sc_port.icount.tx += result;
- tail += result;
- tail &= UART_XMIT_SIZE - 1;
- xmit->tail = tail;
- start = &xmit->buf[tail];
- }
- }
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&port->sc_port);
-
- if (uart_circ_empty(xmit))
- snp_stop_tx(&port->sc_port); /* no-op for us */
-}
-
-/**
- * sn_sal_interrupt - Handle console interrupts
- * @irq: irq #, useful for debug statements
- * @dev_id: our pointer to our port (sn_cons_port which contains the uart port)
- *
- */
-static irqreturn_t sn_sal_interrupt(int irq, void *dev_id)
-{
- struct sn_cons_port *port = (struct sn_cons_port *)dev_id;
- unsigned long flags;
- int status = ia64_sn_console_intr_status();
-
- if (!port)
- return IRQ_NONE;
-
- spin_lock_irqsave(&port->sc_port.lock, flags);
- if (status & SAL_CONSOLE_INTR_RECV) {
- sn_receive_chars(port, flags);
- }
- if (status & SAL_CONSOLE_INTR_XMIT) {
- sn_transmit_chars(port, TRANSMIT_BUFFERED);
- }
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- return IRQ_HANDLED;
-}
-
-/**
- * sn_sal_timer_poll - this function handles polled console mode
- * @data: A pointer to our sn_cons_port (which contains the uart port)
- *
- * data is the pointer that init_timer will store for us. This function is
- * associated with init_timer to see if there is any console traffic.
- * Obviously not used in interrupt mode
- *
- */
-static void sn_sal_timer_poll(unsigned long data)
-{
- struct sn_cons_port *port = (struct sn_cons_port *)data;
- unsigned long flags;
-
- if (!port)
- return;
-
- if (!port->sc_port.irq) {
- spin_lock_irqsave(&port->sc_port.lock, flags);
- if (sn_process_input)
- sn_receive_chars(port, flags);
- sn_transmit_chars(port, TRANSMIT_RAW);
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- mod_timer(&port->sc_timer,
- jiffies + port->sc_interrupt_timeout);
- }
-}
-
-/*
- * Boot-time initialization code
- */
-
-/**
- * sn_sal_switch_to_asynch - Switch to async mode (as opposed to synch)
- * @port: Our sn_cons_port (which contains the uart port)
- *
- * So this is used by sn_sal_serial_console_init (early on, before we're
- * registered with serial core). It's also used by sn_sal_module_init
- * right after we've registered with serial core. The later only happens
- * if we didn't already come through here via sn_sal_serial_console_init.
- *
- */
-static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port)
-{
- unsigned long flags;
-
- if (!port)
- return;
-
- DPRINTF("sn_console: about to switch to asynchronous console\n");
-
- /* without early_printk, we may be invoked late enough to race
- * with other cpus doing console IO at this point, however
- * console interrupts will never be enabled */
- spin_lock_irqsave(&port->sc_port.lock, flags);
-
- /* early_printk invocation may have done this for us */
- if (!port->sc_ops)
- port->sc_ops = &poll_ops;
-
- /* we can't turn on the console interrupt (as request_irq
- * calls kmalloc, which isn't set up yet), so we rely on a
- * timer to poll for input and push data from the console
- * buffer.
- */
- init_timer(&port->sc_timer);
- port->sc_timer.function = sn_sal_timer_poll;
- port->sc_timer.data = (unsigned long)port;
-
- if (IS_RUNNING_ON_SIMULATOR())
- port->sc_interrupt_timeout = 6;
- else {
- /* 960cps / 16 char FIFO = 60HZ
- * HZ / (SN_SAL_FIFO_SPEED_CPS / SN_SAL_FIFO_DEPTH) */
- port->sc_interrupt_timeout =
- HZ * SN_SAL_UART_FIFO_DEPTH / SN_SAL_UART_FIFO_SPEED_CPS;
- }
- mod_timer(&port->sc_timer, jiffies + port->sc_interrupt_timeout);
-
- port->sc_is_asynch = 1;
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
-}
-
-/**
- * sn_sal_switch_to_interrupts - Switch to interrupt driven mode
- * @port: Our sn_cons_port (which contains the uart port)
- *
- * In sn_sal_module_init, after we're registered with serial core and
- * the port is added, this function is called to switch us to interrupt
- * mode. We were previously in asynch/polling mode (using init_timer).
- *
- * We attempt to switch to interrupt mode here by calling
- * request_irq. If that works out, we enable receive interrupts.
- */
-static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port)
-{
- unsigned long flags;
-
- if (port) {
- DPRINTF("sn_console: switching to interrupt driven console\n");
-
- if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
- IRQF_DISABLED | IRQF_SHARED,
- "SAL console driver", port) >= 0) {
- spin_lock_irqsave(&port->sc_port.lock, flags);
- port->sc_port.irq = SGI_UART_VECTOR;
- port->sc_ops = &intr_ops;
-
- /* turn on receive interrupts */
- ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- }
- else {
- printk(KERN_INFO
- "sn_console: console proceeding in polled mode\n");
- }
- }
-}
-
-/*
- * Kernel console definitions
- */
-
-static void sn_sal_console_write(struct console *, const char *, unsigned);
-static int sn_sal_console_setup(struct console *, char *);
-static struct uart_driver sal_console_uart;
-extern struct tty_driver *uart_console_device(struct console *, int *);
-
-static struct console sal_console = {
- .name = DEVICE_NAME,
- .write = sn_sal_console_write,
- .device = uart_console_device,
- .setup = sn_sal_console_setup,
- .index = -1, /* unspecified */
- .data = &sal_console_uart,
-};
-
-#define SAL_CONSOLE &sal_console
-
-static struct uart_driver sal_console_uart = {
- .owner = THIS_MODULE,
- .driver_name = "sn_console",
- .dev_name = DEVICE_NAME,
- .major = 0, /* major/minor set at registration time per USE_DYNAMIC_MINOR */
- .minor = 0,
- .nr = 1, /* one port */
- .cons = SAL_CONSOLE,
-};
-
-/**
- * sn_sal_module_init - When the kernel loads us, get us rolling w/ serial core
- *
- * Before this is called, we've been printing kernel messages in a special
- * early mode not making use of the serial core infrastructure. When our
- * driver is loaded for real, we register the driver and port with serial
- * core and try to enable interrupt driven mode.
- *
- */
-static int __init sn_sal_module_init(void)
-{
- int retval;
-
- if (!ia64_platform_is("sn2"))
- return 0;
-
- printk(KERN_INFO "sn_console: Console driver init\n");
-
- if (USE_DYNAMIC_MINOR == 1) {
- misc.minor = MISC_DYNAMIC_MINOR;
- misc.name = DEVICE_NAME_DYNAMIC;
- retval = misc_register(&misc);
- if (retval != 0) {
- printk(KERN_WARNING "Failed to register console "
- "device using misc_register.\n");
- return -ENODEV;
- }
- sal_console_uart.major = MISC_MAJOR;
- sal_console_uart.minor = misc.minor;
- } else {
- sal_console_uart.major = DEVICE_MAJOR;
- sal_console_uart.minor = DEVICE_MINOR;
- }
-
- /* We register the driver and the port before switching to interrupts
- * or async above so the proper uart structures are populated */
-
- if (uart_register_driver(&sal_console_uart) < 0) {
- printk
- ("ERROR sn_sal_module_init failed uart_register_driver, line %d\n",
- __LINE__);
- return -ENODEV;
- }
-
- spin_lock_init(&sal_console_port.sc_port.lock);
-
- /* Setup the port struct with the minimum needed */
- sal_console_port.sc_port.membase = (char *)1; /* just needs to be non-zero */
- sal_console_port.sc_port.type = PORT_16550A;
- sal_console_port.sc_port.fifosize = SN_SAL_MAX_CHARS;
- sal_console_port.sc_port.ops = &sn_console_ops;
- sal_console_port.sc_port.line = 0;
-
- if (uart_add_one_port(&sal_console_uart, &sal_console_port.sc_port) < 0) {
- /* error - not sure what I'd do - so I'll do nothing */
- printk(KERN_ERR "%s: unable to add port\n", __func__);
- }
-
- /* when this driver is compiled in, the console initialization
- * will have already switched us into asynchronous operation
- * before we get here through the module initcalls */
- if (!sal_console_port.sc_is_asynch) {
- sn_sal_switch_to_asynch(&sal_console_port);
- }
-
- /* at this point (module_init) we can try to turn on interrupts */
- if (!IS_RUNNING_ON_SIMULATOR()) {
- sn_sal_switch_to_interrupts(&sal_console_port);
- }
- sn_process_input = 1;
- return 0;
-}
-
-/**
- * sn_sal_module_exit - When we're unloaded, remove the driver/port
- *
- */
-static void __exit sn_sal_module_exit(void)
-{
- del_timer_sync(&sal_console_port.sc_timer);
- uart_remove_one_port(&sal_console_uart, &sal_console_port.sc_port);
- uart_unregister_driver(&sal_console_uart);
- misc_deregister(&misc);
-}
-
-module_init(sn_sal_module_init);
-module_exit(sn_sal_module_exit);
-
-/**
- * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
- * @puts_raw : puts function to do the writing
- * @s: input string
- * @count: length
- *
- * We need a \r ahead of every \n for direct writes through
- * ia64_sn_console_putb (what sal_puts_raw below actually does).
- *
- */
-
-static void puts_raw_fixed(int (*puts_raw) (const char *s, int len),
- const char *s, int count)
-{
- const char *s1;
-
- /* Output '\r' before each '\n' */
- while ((s1 = memchr(s, '\n', count)) != NULL) {
- puts_raw(s, s1 - s);
- puts_raw("\r\n", 2);
- count -= s1 + 1 - s;
- s = s1 + 1;
- }
- puts_raw(s, count);
-}
-
-/**
- * sn_sal_console_write - Print statements before serial core available
- * @console: Console to operate on - we ignore since we have just one
- * @s: String to send
- * @count: length
- *
- * This is referenced in the console struct. It is used for early
- * console printing before we register with serial core and for things
- * such as kdb. The console_lock must be held when we get here.
- *
- * This function has some code for trying to print output even if the lock
- * is held. We try to cover the case where a lock holder could have died.
- * We don't use this special case code if we're not registered with serial
- * core yet. After we're registered with serial core, the only time this
- * function would be used is for high level kernel output like magic sys req,
- * kdb, and printk's.
- */
-static void
-sn_sal_console_write(struct console *co, const char *s, unsigned count)
-{
- unsigned long flags = 0;
- struct sn_cons_port *port = &sal_console_port;
- static int stole_lock = 0;
-
- BUG_ON(!port->sc_is_asynch);
-
- /* We can't look at the xmit buffer if we're not registered with serial core
- * yet. So only do the fancy recovery after registering
- */
- if (!port->sc_port.state) {
- /* Not yet registered with serial core - simple case */
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- return;
- }
-
- /* somebody really wants this output, might be an
- * oops, kdb, panic, etc. make sure they get it. */
- if (spin_is_locked(&port->sc_port.lock)) {
- int lhead = port->sc_port.state->xmit.head;
- int ltail = port->sc_port.state->xmit.tail;
- int counter, got_lock = 0;
-
- /*
- * We attempt to determine if someone has died with the
- * lock. We wait ~20 secs after the head and tail ptrs
- * stop moving and assume the lock holder is not functional
- * and plow ahead. If the lock is freed within the time out
- * period we re-get the lock and go ahead normally. We also
- * remember if we have plowed ahead so that we don't have
- * to wait out the time out period again - the asumption
- * is that we will time out again.
- */
-
- for (counter = 0; counter < 150; mdelay(125), counter++) {
- if (!spin_is_locked(&port->sc_port.lock)
- || stole_lock) {
- if (!stole_lock) {
- spin_lock_irqsave(&port->sc_port.lock,
- flags);
- got_lock = 1;
- }
- break;
- } else {
- /* still locked */
- if ((lhead != port->sc_port.state->xmit.head)
- || (ltail !=
- port->sc_port.state->xmit.tail)) {
- lhead =
- port->sc_port.state->xmit.head;
- ltail =
- port->sc_port.state->xmit.tail;
- counter = 0;
- }
- }
- }
- /* flush anything in the serial core xmit buffer, raw */
- sn_transmit_chars(port, 1);
- if (got_lock) {
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
- stole_lock = 0;
- } else {
- /* fell thru */
- stole_lock = 1;
- }
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- } else {
- stole_lock = 0;
- spin_lock_irqsave(&port->sc_port.lock, flags);
- sn_transmit_chars(port, 1);
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
-
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- }
-}
-
-
-/**
- * sn_sal_console_setup - Set up console for early printing
- * @co: Console to work with
- * @options: Options to set
- *
- * Altix console doesn't do anything with baud rates, etc, anyway.
- *
- * This isn't required since not providing the setup function in the
- * console struct is ok. However, other patches like KDB plop something
- * here so providing it is easier.
- *
- */
-static int sn_sal_console_setup(struct console *co, char *options)
-{
- return 0;
-}
-
-/**
- * sn_sal_console_write_early - simple early output routine
- * @co - console struct
- * @s - string to print
- * @count - count
- *
- * Simple function to provide early output, before even
- * sn_sal_serial_console_init is called. Referenced in the
- * console struct registerd in sn_serial_console_early_setup.
- *
- */
-static void __init
-sn_sal_console_write_early(struct console *co, const char *s, unsigned count)
-{
- puts_raw_fixed(sal_console_port.sc_ops->sal_puts_raw, s, count);
-}
-
-/* Used for very early console printing - again, before
- * sn_sal_serial_console_init is run */
-static struct console sal_console_early __initdata = {
- .name = "sn_sal",
- .write = sn_sal_console_write_early,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/**
- * sn_serial_console_early_setup - Sets up early console output support
- *
- * Register a console early on... This is for output before even
- * sn_sal_serial_cosnole_init is called. This function is called from
- * setup.c. This allows us to do really early polled writes. When
- * sn_sal_serial_console_init is called, this console is unregistered
- * and a new one registered.
- */
-int __init sn_serial_console_early_setup(void)
-{
- if (!ia64_platform_is("sn2"))
- return -1;
-
- sal_console_port.sc_ops = &poll_ops;
- spin_lock_init(&sal_console_port.sc_port.lock);
- early_sn_setup(); /* Find SAL entry points */
- register_console(&sal_console_early);
-
- return 0;
-}
-
-/**
- * sn_sal_serial_console_init - Early console output - set up for register
- *
- * This function is called when regular console init happens. Because we
- * support even earlier console output with sn_serial_console_early_setup
- * (called from setup.c directly), this function unregisters the really
- * early console.
- *
- * Note: Even if setup.c doesn't register sal_console_early, unregistering
- * it here doesn't hurt anything.
- *
- */
-static int __init sn_sal_serial_console_init(void)
-{
- if (ia64_platform_is("sn2")) {
- sn_sal_switch_to_asynch(&sal_console_port);
- DPRINTF("sn_sal_serial_console_init : register console\n");
- register_console(&sal_console);
- unregister_console(&sal_console_early);
- }
- return 0;
-}
-
-console_initcall(sn_sal_serial_console_init);
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
deleted file mode 100644
index 6381a0282ee7..000000000000
--- a/drivers/serial/suncore.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/* suncore.c
- *
- * Common SUN serial routines. Based entirely
- * upon drivers/sbus/char/sunserial.c which is:
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- *
- * Adaptation to new UART layer is:
- *
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/serial_core.h>
-#include <linux/init.h>
-
-#include <asm/prom.h>
-
-#include "suncore.h"
-
-static int sunserial_current_minor = 64;
-
-int sunserial_register_minors(struct uart_driver *drv, int count)
-{
- int err = 0;
-
- drv->minor = sunserial_current_minor;
- drv->nr += count;
- /* Register the driver on the first call */
- if (drv->nr == count)
- err = uart_register_driver(drv);
- if (err == 0) {
- sunserial_current_minor += count;
- drv->tty_driver->name_base = drv->minor - 64;
- }
- return err;
-}
-EXPORT_SYMBOL(sunserial_register_minors);
-
-void sunserial_unregister_minors(struct uart_driver *drv, int count)
-{
- drv->nr -= count;
- sunserial_current_minor -= count;
-
- if (drv->nr == 0)
- uart_unregister_driver(drv);
-}
-EXPORT_SYMBOL(sunserial_unregister_minors);
-
-int sunserial_console_match(struct console *con, struct device_node *dp,
- struct uart_driver *drv, int line, bool ignore_line)
-{
- if (!con)
- return 0;
-
- drv->cons = con;
-
- if (of_console_device != dp)
- return 0;
-
- if (!ignore_line) {
- int off = 0;
-
- if (of_console_options &&
- *of_console_options == 'b')
- off = 1;
-
- if ((line & 1) != off)
- return 0;
- }
-
- if (!console_set_on_cmdline) {
- con->index = line;
- add_preferred_console(con->name, line, NULL);
- }
- return 1;
-}
-EXPORT_SYMBOL(sunserial_console_match);
-
-void sunserial_console_termios(struct console *con, struct device_node *uart_dp)
-{
- const char *mode, *s;
- char mode_prop[] = "ttyX-mode";
- int baud, bits, stop, cflag;
- char parity;
-
- if (!strcmp(uart_dp->name, "rsc") ||
- !strcmp(uart_dp->name, "rsc-console") ||
- !strcmp(uart_dp->name, "rsc-control")) {
- mode = of_get_property(uart_dp,
- "ssp-console-modes", NULL);
- if (!mode)
- mode = "115200,8,n,1,-";
- } else if (!strcmp(uart_dp->name, "lom-console")) {
- mode = "9600,8,n,1,-";
- } else {
- struct device_node *dp;
- char c;
-
- c = 'a';
- if (of_console_options)
- c = *of_console_options;
-
- mode_prop[3] = c;
-
- dp = of_find_node_by_path("/options");
- mode = of_get_property(dp, mode_prop, NULL);
- if (!mode)
- mode = "9600,8,n,1,-";
- }
-
- cflag = CREAD | HUPCL | CLOCAL;
-
- s = mode;
- baud = simple_strtoul(s, NULL, 0);
- s = strchr(s, ',');
- bits = simple_strtoul(++s, NULL, 0);
- s = strchr(s, ',');
- parity = *(++s);
- s = strchr(s, ',');
- stop = simple_strtoul(++s, NULL, 0);
- s = strchr(s, ',');
- /* XXX handshake is not handled here. */
-
- switch (baud) {
- case 150: cflag |= B150; break;
- case 300: cflag |= B300; break;
- case 600: cflag |= B600; break;
- case 1200: cflag |= B1200; break;
- case 2400: cflag |= B2400; break;
- case 4800: cflag |= B4800; break;
- case 9600: cflag |= B9600; break;
- case 19200: cflag |= B19200; break;
- case 38400: cflag |= B38400; break;
- case 57600: cflag |= B57600; break;
- case 115200: cflag |= B115200; break;
- case 230400: cflag |= B230400; break;
- case 460800: cflag |= B460800; break;
- default: baud = 9600; cflag |= B9600; break;
- }
-
- switch (bits) {
- case 5: cflag |= CS5; break;
- case 6: cflag |= CS6; break;
- case 7: cflag |= CS7; break;
- case 8: cflag |= CS8; break;
- default: cflag |= CS8; break;
- }
-
- switch (parity) {
- case 'o': cflag |= (PARENB | PARODD); break;
- case 'e': cflag |= PARENB; break;
- case 'n': default: break;
- }
-
- switch (stop) {
- case 2: cflag |= CSTOPB; break;
- case 1: default: break;
- }
-
- con->cflag = cflag;
-}
-
-/* Sun serial MOUSE auto baud rate detection. */
-static struct mouse_baud_cflag {
- int baud;
- unsigned int cflag;
-} mouse_baud_table[] = {
- { 1200, B1200 },
- { 2400, B2400 },
- { 4800, B4800 },
- { 9600, B9600 },
- { -1, ~0 },
- { -1, ~0 },
-};
-
-unsigned int suncore_mouse_baud_cflag_next(unsigned int cflag, int *new_baud)
-{
- int i;
-
- for (i = 0; mouse_baud_table[i].baud != -1; i++)
- if (mouse_baud_table[i].cflag == (cflag & CBAUD))
- break;
-
- i += 1;
- if (mouse_baud_table[i].baud == -1)
- i = 0;
-
- *new_baud = mouse_baud_table[i].baud;
- return mouse_baud_table[i].cflag;
-}
-
-EXPORT_SYMBOL(suncore_mouse_baud_cflag_next);
-
-/* Basically, when the baud rate is wrong the mouse spits out
- * breaks to us.
- */
-int suncore_mouse_baud_detection(unsigned char ch, int is_break)
-{
- static int mouse_got_break = 0;
- static int ctr = 0;
-
- if (is_break) {
- /* Let a few normal bytes go by before we jump the gun
- * and say we need to try another baud rate.
- */
- if (mouse_got_break && ctr < 8)
- return 1;
-
- /* Ok, we need to try another baud. */
- ctr = 0;
- mouse_got_break = 1;
- return 2;
- }
- if (mouse_got_break) {
- ctr++;
- if (ch == 0x87) {
- /* Correct baud rate determined. */
- mouse_got_break = 0;
- }
- return 1;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(suncore_mouse_baud_detection);
-
-static int __init suncore_init(void)
-{
- return 0;
-}
-
-static void __exit suncore_exit(void)
-{
-}
-
-module_init(suncore_init);
-module_exit(suncore_exit);
-
-MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
-MODULE_DESCRIPTION("Sun serial common layer");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/suncore.h b/drivers/serial/suncore.h
deleted file mode 100644
index db2057936c31..000000000000
--- a/drivers/serial/suncore.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* suncore.h
- *
- * Generic SUN serial/kbd/ms layer. Based entirely
- * upon drivers/sbus/char/sunserial.h which is:
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- *
- * Port to new UART layer is:
- *
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
- */
-
-#ifndef _SERIAL_SUN_H
-#define _SERIAL_SUN_H
-
-/* Serial keyboard defines for L1-A processing... */
-#define SUNKBD_RESET 0xff
-#define SUNKBD_L1 0x01
-#define SUNKBD_UP 0x80
-#define SUNKBD_A 0x4d
-
-extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
-extern int suncore_mouse_baud_detection(unsigned char, int);
-
-extern int sunserial_register_minors(struct uart_driver *, int);
-extern void sunserial_unregister_minors(struct uart_driver *, int);
-
-extern int sunserial_console_match(struct console *, struct device_node *,
- struct uart_driver *, int, bool);
-extern void sunserial_console_termios(struct console *,
- struct device_node *);
-
-#endif /* !(_SERIAL_SUN_H) */
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
deleted file mode 100644
index c9014868297d..000000000000
--- a/drivers/serial/sunhv.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/* sunhv.c: Serial driver for SUN4V hypervisor console.
- *
- * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/circ_buf.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/of_device.h>
-
-#include <asm/hypervisor.h>
-#include <asm/spitfire.h>
-#include <asm/prom.h>
-#include <asm/irq.h>
-
-#if defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#include "suncore.h"
-
-#define CON_BREAK ((long)-1)
-#define CON_HUP ((long)-2)
-
-#define IGNORE_BREAK 0x1
-#define IGNORE_ALL 0x2
-
-static char *con_write_page;
-static char *con_read_page;
-
-static int hung_up = 0;
-
-static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit)
-{
- while (!uart_circ_empty(xmit)) {
- long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
-
- if (status != HV_EOK)
- break;
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
-}
-
-static void transmit_chars_write(struct uart_port *port, struct circ_buf *xmit)
-{
- while (!uart_circ_empty(xmit)) {
- unsigned long ra = __pa(xmit->buf + xmit->tail);
- unsigned long len, status, sent;
-
- len = CIRC_CNT_TO_END(xmit->head, xmit->tail,
- UART_XMIT_SIZE);
- status = sun4v_con_write(ra, len, &sent);
- if (status != HV_EOK)
- break;
- xmit->tail = (xmit->tail + sent) & (UART_XMIT_SIZE - 1);
- port->icount.tx += sent;
- }
-}
-
-static int receive_chars_getchar(struct uart_port *port, struct tty_struct *tty)
-{
- int saw_console_brk = 0;
- int limit = 10000;
-
- while (limit-- > 0) {
- long status;
- long c = sun4v_con_getchar(&status);
-
- if (status == HV_EWOULDBLOCK)
- break;
-
- if (c == CON_BREAK) {
- if (uart_handle_break(port))
- continue;
- saw_console_brk = 1;
- c = 0;
- }
-
- if (c == CON_HUP) {
- hung_up = 1;
- uart_handle_dcd_change(port, 0);
- } else if (hung_up) {
- hung_up = 0;
- uart_handle_dcd_change(port, 1);
- }
-
- if (tty == NULL) {
- uart_handle_sysrq_char(port, c);
- continue;
- }
-
- port->icount.rx++;
-
- if (uart_handle_sysrq_char(port, c))
- continue;
-
- tty_insert_flip_char(tty, c, TTY_NORMAL);
- }
-
- return saw_console_brk;
-}
-
-static int receive_chars_read(struct uart_port *port, struct tty_struct *tty)
-{
- int saw_console_brk = 0;
- int limit = 10000;
-
- while (limit-- > 0) {
- unsigned long ra = __pa(con_read_page);
- unsigned long bytes_read, i;
- long stat = sun4v_con_read(ra, PAGE_SIZE, &bytes_read);
-
- if (stat != HV_EOK) {
- bytes_read = 0;
-
- if (stat == CON_BREAK) {
- if (uart_handle_break(port))
- continue;
- saw_console_brk = 1;
- *con_read_page = 0;
- bytes_read = 1;
- } else if (stat == CON_HUP) {
- hung_up = 1;
- uart_handle_dcd_change(port, 0);
- continue;
- } else {
- /* HV_EWOULDBLOCK, etc. */
- break;
- }
- }
-
- if (hung_up) {
- hung_up = 0;
- uart_handle_dcd_change(port, 1);
- }
-
- for (i = 0; i < bytes_read; i++)
- uart_handle_sysrq_char(port, con_read_page[i]);
-
- if (tty == NULL)
- continue;
-
- port->icount.rx += bytes_read;
-
- tty_insert_flip_string(tty, con_read_page, bytes_read);
- }
-
- return saw_console_brk;
-}
-
-struct sunhv_ops {
- void (*transmit_chars)(struct uart_port *port, struct circ_buf *xmit);
- int (*receive_chars)(struct uart_port *port, struct tty_struct *tty);
-};
-
-static struct sunhv_ops bychar_ops = {
- .transmit_chars = transmit_chars_putchar,
- .receive_chars = receive_chars_getchar,
-};
-
-static struct sunhv_ops bywrite_ops = {
- .transmit_chars = transmit_chars_write,
- .receive_chars = receive_chars_read,
-};
-
-static struct sunhv_ops *sunhv_ops = &bychar_ops;
-
-static struct tty_struct *receive_chars(struct uart_port *port)
-{
- struct tty_struct *tty = NULL;
-
- if (port->state != NULL) /* Unopened serial console */
- tty = port->state->port.tty;
-
- if (sunhv_ops->receive_chars(port, tty))
- sun_do_break();
-
- return tty;
-}
-
-static void transmit_chars(struct uart_port *port)
-{
- struct circ_buf *xmit;
-
- if (!port->state)
- return;
-
- xmit = &port->state->xmit;
- if (uart_circ_empty(xmit) || uart_tx_stopped(port))
- return;
-
- sunhv_ops->transmit_chars(port, xmit);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-}
-
-static irqreturn_t sunhv_interrupt(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- struct tty_struct *tty;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- tty = receive_chars(port);
- transmit_chars(port);
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- return IRQ_HANDLED;
-}
-
-/* port->lock is not held. */
-static unsigned int sunhv_tx_empty(struct uart_port *port)
-{
- /* Transmitter is always empty for us. If the circ buffer
- * is non-empty or there is an x_char pending, our caller
- * will do the right thing and ignore what we return here.
- */
- return TIOCSER_TEMT;
-}
-
-/* port->lock held by caller. */
-static void sunhv_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- return;
-}
-
-/* port->lock is held by caller and interrupts are disabled. */
-static unsigned int sunhv_get_mctrl(struct uart_port *port)
-{
- return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
-}
-
-/* port->lock held by caller. */
-static void sunhv_stop_tx(struct uart_port *port)
-{
- return;
-}
-
-/* port->lock held by caller. */
-static void sunhv_start_tx(struct uart_port *port)
-{
- transmit_chars(port);
-}
-
-/* port->lock is not held. */
-static void sunhv_send_xchar(struct uart_port *port, char ch)
-{
- unsigned long flags;
- int limit = 10000;
-
- spin_lock_irqsave(&port->lock, flags);
-
- while (limit-- > 0) {
- long status = sun4v_con_putchar(ch);
- if (status == HV_EOK)
- break;
- udelay(1);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/* port->lock held by caller. */
-static void sunhv_stop_rx(struct uart_port *port)
-{
-}
-
-/* port->lock held by caller. */
-static void sunhv_enable_ms(struct uart_port *port)
-{
-}
-
-/* port->lock is not held. */
-static void sunhv_break_ctl(struct uart_port *port, int break_state)
-{
- if (break_state) {
- unsigned long flags;
- int limit = 10000;
-
- spin_lock_irqsave(&port->lock, flags);
-
- while (limit-- > 0) {
- long status = sun4v_con_putchar(CON_BREAK);
- if (status == HV_EOK)
- break;
- udelay(1);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
- }
-}
-
-/* port->lock is not held. */
-static int sunhv_startup(struct uart_port *port)
-{
- return 0;
-}
-
-/* port->lock is not held. */
-static void sunhv_shutdown(struct uart_port *port)
-{
-}
-
-/* port->lock is not held. */
-static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
- unsigned int quot = uart_get_divisor(port, baud);
- unsigned int iflag, cflag;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
-
- iflag = termios->c_iflag;
- cflag = termios->c_cflag;
-
- port->ignore_status_mask = 0;
- if (iflag & IGNBRK)
- port->ignore_status_mask |= IGNORE_BREAK;
- if ((cflag & CREAD) == 0)
- port->ignore_status_mask |= IGNORE_ALL;
-
- /* XXX */
- uart_update_timeout(port, cflag,
- (port->uartclk / (16 * quot)));
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *sunhv_type(struct uart_port *port)
-{
- return "SUN4V HCONS";
-}
-
-static void sunhv_release_port(struct uart_port *port)
-{
-}
-
-static int sunhv_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void sunhv_config_port(struct uart_port *port, int flags)
-{
-}
-
-static int sunhv_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-static struct uart_ops sunhv_pops = {
- .tx_empty = sunhv_tx_empty,
- .set_mctrl = sunhv_set_mctrl,
- .get_mctrl = sunhv_get_mctrl,
- .stop_tx = sunhv_stop_tx,
- .start_tx = sunhv_start_tx,
- .send_xchar = sunhv_send_xchar,
- .stop_rx = sunhv_stop_rx,
- .enable_ms = sunhv_enable_ms,
- .break_ctl = sunhv_break_ctl,
- .startup = sunhv_startup,
- .shutdown = sunhv_shutdown,
- .set_termios = sunhv_set_termios,
- .type = sunhv_type,
- .release_port = sunhv_release_port,
- .request_port = sunhv_request_port,
- .config_port = sunhv_config_port,
- .verify_port = sunhv_verify_port,
-};
-
-static struct uart_driver sunhv_reg = {
- .owner = THIS_MODULE,
- .driver_name = "sunhv",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
-};
-
-static struct uart_port *sunhv_port;
-
-/* Copy 's' into the con_write_page, decoding "\n" into
- * "\r\n" along the way. We have to return two lengths
- * because the caller needs to know how much to advance
- * 's' and also how many bytes to output via con_write_page.
- */
-static int fill_con_write_page(const char *s, unsigned int n,
- unsigned long *page_bytes)
-{
- const char *orig_s = s;
- char *p = con_write_page;
- int left = PAGE_SIZE;
-
- while (n--) {
- if (*s == '\n') {
- if (left < 2)
- break;
- *p++ = '\r';
- left--;
- } else if (left < 1)
- break;
- *p++ = *s++;
- left--;
- }
- *page_bytes = p - con_write_page;
- return s - orig_s;
-}
-
-static void sunhv_console_write_paged(struct console *con, const char *s, unsigned n)
-{
- struct uart_port *port = sunhv_port;
- unsigned long flags;
- int locked = 1;
-
- local_irq_save(flags);
- if (port->sysrq) {
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&port->lock);
- } else
- spin_lock(&port->lock);
-
- while (n > 0) {
- unsigned long ra = __pa(con_write_page);
- unsigned long page_bytes;
- unsigned int cpy = fill_con_write_page(s, n,
- &page_bytes);
-
- n -= cpy;
- s += cpy;
- while (page_bytes > 0) {
- unsigned long written;
- int limit = 1000000;
-
- while (limit--) {
- unsigned long stat;
-
- stat = sun4v_con_write(ra, page_bytes,
- &written);
- if (stat == HV_EOK)
- break;
- udelay(1);
- }
- if (limit < 0)
- break;
- page_bytes -= written;
- ra += written;
- }
- }
-
- if (locked)
- spin_unlock(&port->lock);
- local_irq_restore(flags);
-}
-
-static inline void sunhv_console_putchar(struct uart_port *port, char c)
-{
- int limit = 1000000;
-
- while (limit-- > 0) {
- long status = sun4v_con_putchar(c);
- if (status == HV_EOK)
- break;
- udelay(1);
- }
-}
-
-static void sunhv_console_write_bychar(struct console *con, const char *s, unsigned n)
-{
- struct uart_port *port = sunhv_port;
- unsigned long flags;
- int i, locked = 1;
-
- local_irq_save(flags);
- if (port->sysrq) {
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&port->lock);
- } else
- spin_lock(&port->lock);
-
- for (i = 0; i < n; i++) {
- if (*s == '\n')
- sunhv_console_putchar(port, '\r');
- sunhv_console_putchar(port, *s++);
- }
-
- if (locked)
- spin_unlock(&port->lock);
- local_irq_restore(flags);
-}
-
-static struct console sunhv_console = {
- .name = "ttyHV",
- .write = sunhv_console_write_bychar,
- .device = uart_console_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sunhv_reg,
-};
-
-static int __devinit hv_probe(struct platform_device *op, const struct of_device_id *match)
-{
- struct uart_port *port;
- unsigned long minor;
- int err;
-
- if (op->archdata.irqs[0] == 0xffffffff)
- return -ENODEV;
-
- port = kzalloc(sizeof(struct uart_port), GFP_KERNEL);
- if (unlikely(!port))
- return -ENOMEM;
-
- minor = 1;
- if (sun4v_hvapi_register(HV_GRP_CORE, 1, &minor) == 0 &&
- minor >= 1) {
- err = -ENOMEM;
- con_write_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!con_write_page)
- goto out_free_port;
-
- con_read_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!con_read_page)
- goto out_free_con_write_page;
-
- sunhv_console.write = sunhv_console_write_paged;
- sunhv_ops = &bywrite_ops;
- }
-
- sunhv_port = port;
-
- port->line = 0;
- port->ops = &sunhv_pops;
- port->type = PORT_SUNHV;
- port->uartclk = ( 29491200 / 16 ); /* arbitrary */
-
- port->membase = (unsigned char __iomem *) __pa(port);
-
- port->irq = op->archdata.irqs[0];
-
- port->dev = &op->dev;
-
- err = sunserial_register_minors(&sunhv_reg, 1);
- if (err)
- goto out_free_con_read_page;
-
- sunserial_console_match(&sunhv_console, op->dev.of_node,
- &sunhv_reg, port->line, false);
-
- err = uart_add_one_port(&sunhv_reg, port);
- if (err)
- goto out_unregister_driver;
-
- err = request_irq(port->irq, sunhv_interrupt, 0, "hvcons", port);
- if (err)
- goto out_remove_port;
-
- dev_set_drvdata(&op->dev, port);
-
- return 0;
-
-out_remove_port:
- uart_remove_one_port(&sunhv_reg, port);
-
-out_unregister_driver:
- sunserial_unregister_minors(&sunhv_reg, 1);
-
-out_free_con_read_page:
- kfree(con_read_page);
-
-out_free_con_write_page:
- kfree(con_write_page);
-
-out_free_port:
- kfree(port);
- sunhv_port = NULL;
- return err;
-}
-
-static int __devexit hv_remove(struct platform_device *dev)
-{
- struct uart_port *port = dev_get_drvdata(&dev->dev);
-
- free_irq(port->irq, port);
-
- uart_remove_one_port(&sunhv_reg, port);
-
- sunserial_unregister_minors(&sunhv_reg, 1);
-
- kfree(port);
- sunhv_port = NULL;
-
- dev_set_drvdata(&dev->dev, NULL);
-
- return 0;
-}
-
-static const struct of_device_id hv_match[] = {
- {
- .name = "console",
- .compatible = "qcn",
- },
- {
- .name = "console",
- .compatible = "SUNW,sun4v-console",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, hv_match);
-
-static struct of_platform_driver hv_driver = {
- .driver = {
- .name = "hv",
- .owner = THIS_MODULE,
- .of_match_table = hv_match,
- },
- .probe = hv_probe,
- .remove = __devexit_p(hv_remove),
-};
-
-static int __init sunhv_init(void)
-{
- if (tlb_type != hypervisor)
- return -ENODEV;
-
- return of_register_platform_driver(&hv_driver);
-}
-
-static void __exit sunhv_exit(void)
-{
- of_unregister_platform_driver(&hv_driver);
-}
-
-module_init(sunhv_init);
-module_exit(sunhv_exit);
-
-MODULE_AUTHOR("David S. Miller");
-MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
deleted file mode 100644
index 5b246b18f42f..000000000000
--- a/drivers/serial/sunsab.c
+++ /dev/null
@@ -1,1152 +0,0 @@
-/* sunsab.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
- *
- * Rewrote buffer handling to use CIRC(Circular Buffer) macros.
- * Maxim Krasnyanskiy <maxk@qualcomm.com>
- *
- * Fixed to use tty_get_baud_rate, and to allow for arbitrary baud
- * rates to be programmed into the UART. Also eliminated a lot of
- * duplicated code in the console setup.
- * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
- *
- * Ported to new 2.5.x UART layer.
- * David S. Miller <davem@davemloft.net>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/circ_buf.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-
-#if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#include "suncore.h"
-#include "sunsab.h"
-
-struct uart_sunsab_port {
- struct uart_port port; /* Generic UART port */
- union sab82532_async_regs __iomem *regs; /* Chip registers */
- unsigned long irqflags; /* IRQ state flags */
- int dsr; /* Current DSR state */
- unsigned int cec_timeout; /* Chip poll timeout... */
- unsigned int tec_timeout; /* likewise */
- unsigned char interrupt_mask0;/* ISR0 masking */
- unsigned char interrupt_mask1;/* ISR1 masking */
- unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */
- unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */
- unsigned int gis_shift;
- int type; /* SAB82532 version */
-
- /* Setting configuration bits while the transmitter is active
- * can cause garbage characters to get emitted by the chip.
- * Therefore, we cache such writes here and do the real register
- * write the next time the transmitter becomes idle.
- */
- unsigned int cached_ebrg;
- unsigned char cached_mode;
- unsigned char cached_pvr;
- unsigned char cached_dafo;
-};
-
-/*
- * This assumes you have a 29.4912 MHz clock for your UART.
- */
-#define SAB_BASE_BAUD ( 29491200 / 16 )
-
-static char *sab82532_version[16] = {
- "V1.0", "V2.0", "V3.2", "V(0x03)",
- "V(0x04)", "V(0x05)", "V(0x06)", "V(0x07)",
- "V(0x08)", "V(0x09)", "V(0x0a)", "V(0x0b)",
- "V(0x0c)", "V(0x0d)", "V(0x0e)", "V(0x0f)"
-};
-
-#define SAB82532_MAX_TEC_TIMEOUT 200000 /* 1 character time (at 50 baud) */
-#define SAB82532_MAX_CEC_TIMEOUT 50000 /* 2.5 TX CLKs (at 50 baud) */
-
-#define SAB82532_RECV_FIFO_SIZE 32 /* Standard async fifo sizes */
-#define SAB82532_XMIT_FIFO_SIZE 32
-
-static __inline__ void sunsab_tec_wait(struct uart_sunsab_port *up)
-{
- int timeout = up->tec_timeout;
-
- while ((readb(&up->regs->r.star) & SAB82532_STAR_TEC) && --timeout)
- udelay(1);
-}
-
-static __inline__ void sunsab_cec_wait(struct uart_sunsab_port *up)
-{
- int timeout = up->cec_timeout;
-
- while ((readb(&up->regs->r.star) & SAB82532_STAR_CEC) && --timeout)
- udelay(1);
-}
-
-static struct tty_struct *
-receive_chars(struct uart_sunsab_port *up,
- union sab82532_irq_status *stat)
-{
- struct tty_struct *tty = NULL;
- unsigned char buf[32];
- int saw_console_brk = 0;
- int free_fifo = 0;
- int count = 0;
- int i;
-
- if (up->port.state != NULL) /* Unopened serial console */
- tty = up->port.state->port.tty;
-
- /* Read number of BYTES (Character + Status) available. */
- if (stat->sreg.isr0 & SAB82532_ISR0_RPF) {
- count = SAB82532_RECV_FIFO_SIZE;
- free_fifo++;
- }
-
- if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
- count = readb(&up->regs->r.rbcl) & (SAB82532_RECV_FIFO_SIZE - 1);
- free_fifo++;
- }
-
- /* Issue a FIFO read command in case we where idle. */
- if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
- sunsab_cec_wait(up);
- writeb(SAB82532_CMDR_RFRD, &up->regs->w.cmdr);
- return tty;
- }
-
- if (stat->sreg.isr0 & SAB82532_ISR0_RFO)
- free_fifo++;
-
- /* Read the FIFO. */
- for (i = 0; i < count; i++)
- buf[i] = readb(&up->regs->r.rfifo[i]);
-
- /* Issue Receive Message Complete command. */
- if (free_fifo) {
- sunsab_cec_wait(up);
- writeb(SAB82532_CMDR_RMC, &up->regs->w.cmdr);
- }
-
- /* Count may be zero for BRK, so we check for it here */
- if ((stat->sreg.isr1 & SAB82532_ISR1_BRK) &&
- (up->port.line == up->port.cons->index))
- saw_console_brk = 1;
-
- for (i = 0; i < count; i++) {
- unsigned char ch = buf[i], flag;
-
- if (tty == NULL) {
- uart_handle_sysrq_char(&up->port, ch);
- continue;
- }
-
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(stat->sreg.isr0 & (SAB82532_ISR0_PERR |
- SAB82532_ISR0_FERR |
- SAB82532_ISR0_RFO)) ||
- unlikely(stat->sreg.isr1 & SAB82532_ISR1_BRK)) {
- /*
- * For statistics only
- */
- if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
- stat->sreg.isr0 &= ~(SAB82532_ISR0_PERR |
- SAB82532_ISR0_FERR);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- continue;
- } else if (stat->sreg.isr0 & SAB82532_ISR0_PERR)
- up->port.icount.parity++;
- else if (stat->sreg.isr0 & SAB82532_ISR0_FERR)
- up->port.icount.frame++;
- if (stat->sreg.isr0 & SAB82532_ISR0_RFO)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ingored.
- */
- stat->sreg.isr0 &= (up->port.read_status_mask & 0xff);
- stat->sreg.isr1 &= ((up->port.read_status_mask >> 8) & 0xff);
-
- if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
- flag = TTY_BREAK;
- } else if (stat->sreg.isr0 & SAB82532_ISR0_PERR)
- flag = TTY_PARITY;
- else if (stat->sreg.isr0 & SAB82532_ISR0_FERR)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&up->port, ch))
- continue;
-
- if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
- (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0)
- tty_insert_flip_char(tty, ch, flag);
- if (stat->sreg.isr0 & SAB82532_ISR0_RFO)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
-
- if (saw_console_brk)
- sun_do_break();
-
- return tty;
-}
-
-static void sunsab_stop_tx(struct uart_port *);
-static void sunsab_tx_idle(struct uart_sunsab_port *);
-
-static void transmit_chars(struct uart_sunsab_port *up,
- union sab82532_irq_status *stat)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int i;
-
- if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) {
- up->interrupt_mask1 |= SAB82532_IMR1_ALLS;
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
- set_bit(SAB82532_ALLS, &up->irqflags);
- }
-
-#if 0 /* bde@nwlink.com says this check causes problems */
- if (!(stat->sreg.isr1 & SAB82532_ISR1_XPR))
- return;
-#endif
-
- if (!(readb(&up->regs->r.star) & SAB82532_STAR_XFW))
- return;
-
- set_bit(SAB82532_XPR, &up->irqflags);
- sunsab_tx_idle(up);
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- up->interrupt_mask1 |= SAB82532_IMR1_XPR;
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
- return;
- }
-
- up->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS|SAB82532_IMR1_XPR);
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
- clear_bit(SAB82532_ALLS, &up->irqflags);
-
- /* Stuff 32 bytes into Transmit FIFO. */
- clear_bit(SAB82532_XPR, &up->irqflags);
- for (i = 0; i < up->port.fifosize; i++) {
- writeb(xmit->buf[xmit->tail],
- &up->regs->w.xfifo[i]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- }
-
- /* Issue a Transmit Frame command. */
- sunsab_cec_wait(up);
- writeb(SAB82532_CMDR_XF, &up->regs->w.cmdr);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit))
- sunsab_stop_tx(&up->port);
-}
-
-static void check_status(struct uart_sunsab_port *up,
- union sab82532_irq_status *stat)
-{
- if (stat->sreg.isr0 & SAB82532_ISR0_CDSC)
- uart_handle_dcd_change(&up->port,
- !(readb(&up->regs->r.vstr) & SAB82532_VSTR_CD));
-
- if (stat->sreg.isr1 & SAB82532_ISR1_CSC)
- uart_handle_cts_change(&up->port,
- (readb(&up->regs->r.star) & SAB82532_STAR_CTS));
-
- if ((readb(&up->regs->r.pvr) & up->pvr_dsr_bit) ^ up->dsr) {
- up->dsr = (readb(&up->regs->r.pvr) & up->pvr_dsr_bit) ? 0 : 1;
- up->port.icount.dsr++;
- }
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-static irqreturn_t sunsab_interrupt(int irq, void *dev_id)
-{
- struct uart_sunsab_port *up = dev_id;
- struct tty_struct *tty;
- union sab82532_irq_status status;
- unsigned long flags;
- unsigned char gis;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- status.stat = 0;
- gis = readb(&up->regs->r.gis) >> up->gis_shift;
- if (gis & 1)
- status.sreg.isr0 = readb(&up->regs->r.isr0);
- if (gis & 2)
- status.sreg.isr1 = readb(&up->regs->r.isr1);
-
- tty = NULL;
- if (status.stat) {
- if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
- SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) ||
- (status.sreg.isr1 & SAB82532_ISR1_BRK))
- tty = receive_chars(up, &status);
- if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
- (status.sreg.isr1 & SAB82532_ISR1_CSC))
- check_status(up, &status);
- if (status.sreg.isr1 & (SAB82532_ISR1_ALLS | SAB82532_ISR1_XPR))
- transmit_chars(up, &status);
- }
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- return IRQ_HANDLED;
-}
-
-/* port->lock is not held. */
-static unsigned int sunsab_tx_empty(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- int ret;
-
- /* Do not need a lock for a state test like this. */
- if (test_bit(SAB82532_ALLS, &up->irqflags))
- ret = TIOCSER_TEMT;
- else
- ret = 0;
-
- return ret;
-}
-
-/* port->lock held by caller. */
-static void sunsab_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
-
- if (mctrl & TIOCM_RTS) {
- up->cached_mode &= ~SAB82532_MODE_FRTS;
- up->cached_mode |= SAB82532_MODE_RTS;
- } else {
- up->cached_mode |= (SAB82532_MODE_FRTS |
- SAB82532_MODE_RTS);
- }
- if (mctrl & TIOCM_DTR) {
- up->cached_pvr &= ~(up->pvr_dtr_bit);
- } else {
- up->cached_pvr |= up->pvr_dtr_bit;
- }
-
- set_bit(SAB82532_REGS_PENDING, &up->irqflags);
- if (test_bit(SAB82532_XPR, &up->irqflags))
- sunsab_tx_idle(up);
-}
-
-/* port->lock is held by caller and interrupts are disabled. */
-static unsigned int sunsab_get_mctrl(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- unsigned char val;
- unsigned int result;
-
- result = 0;
-
- val = readb(&up->regs->r.pvr);
- result |= (val & up->pvr_dsr_bit) ? 0 : TIOCM_DSR;
-
- val = readb(&up->regs->r.vstr);
- result |= (val & SAB82532_VSTR_CD) ? 0 : TIOCM_CAR;
-
- val = readb(&up->regs->r.star);
- result |= (val & SAB82532_STAR_CTS) ? TIOCM_CTS : 0;
-
- return result;
-}
-
-/* port->lock held by caller. */
-static void sunsab_stop_tx(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
-
- up->interrupt_mask1 |= SAB82532_IMR1_XPR;
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
-}
-
-/* port->lock held by caller. */
-static void sunsab_tx_idle(struct uart_sunsab_port *up)
-{
- if (test_bit(SAB82532_REGS_PENDING, &up->irqflags)) {
- u8 tmp;
-
- clear_bit(SAB82532_REGS_PENDING, &up->irqflags);
- writeb(up->cached_mode, &up->regs->rw.mode);
- writeb(up->cached_pvr, &up->regs->rw.pvr);
- writeb(up->cached_dafo, &up->regs->w.dafo);
-
- writeb(up->cached_ebrg & 0xff, &up->regs->w.bgr);
- tmp = readb(&up->regs->rw.ccr2);
- tmp &= ~0xc0;
- tmp |= (up->cached_ebrg >> 2) & 0xc0;
- writeb(tmp, &up->regs->rw.ccr2);
- }
-}
-
-/* port->lock held by caller. */
-static void sunsab_start_tx(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- struct circ_buf *xmit = &up->port.state->xmit;
- int i;
-
- up->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS|SAB82532_IMR1_XPR);
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
-
- if (!test_bit(SAB82532_XPR, &up->irqflags))
- return;
-
- clear_bit(SAB82532_ALLS, &up->irqflags);
- clear_bit(SAB82532_XPR, &up->irqflags);
-
- for (i = 0; i < up->port.fifosize; i++) {
- writeb(xmit->buf[xmit->tail],
- &up->regs->w.xfifo[i]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- }
-
- /* Issue a Transmit Frame command. */
- sunsab_cec_wait(up);
- writeb(SAB82532_CMDR_XF, &up->regs->w.cmdr);
-}
-
-/* port->lock is not held. */
-static void sunsab_send_xchar(struct uart_port *port, char ch)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- sunsab_tec_wait(up);
- writeb(ch, &up->regs->w.tic);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/* port->lock held by caller. */
-static void sunsab_stop_rx(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
-
- up->interrupt_mask0 |= SAB82532_IMR0_TCD;
- writeb(up->interrupt_mask1, &up->regs->w.imr0);
-}
-
-/* port->lock held by caller. */
-static void sunsab_enable_ms(struct uart_port *port)
-{
- /* For now we always receive these interrupts. */
-}
-
-/* port->lock is not held. */
-static void sunsab_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- unsigned long flags;
- unsigned char val;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- val = up->cached_dafo;
- if (break_state)
- val |= SAB82532_DAFO_XBRK;
- else
- val &= ~SAB82532_DAFO_XBRK;
- up->cached_dafo = val;
-
- set_bit(SAB82532_REGS_PENDING, &up->irqflags);
- if (test_bit(SAB82532_XPR, &up->irqflags))
- sunsab_tx_idle(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/* port->lock is not held. */
-static int sunsab_startup(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- unsigned long flags;
- unsigned char tmp;
- int err = request_irq(up->port.irq, sunsab_interrupt,
- IRQF_SHARED, "sab", up);
- if (err)
- return err;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Wait for any commands or immediate characters
- */
- sunsab_cec_wait(up);
- sunsab_tec_wait(up);
-
- /*
- * Clear the FIFO buffers.
- */
- writeb(SAB82532_CMDR_RRES, &up->regs->w.cmdr);
- sunsab_cec_wait(up);
- writeb(SAB82532_CMDR_XRES, &up->regs->w.cmdr);
-
- /*
- * Clear the interrupt registers.
- */
- (void) readb(&up->regs->r.isr0);
- (void) readb(&up->regs->r.isr1);
-
- /*
- * Now, initialize the UART
- */
- writeb(0, &up->regs->w.ccr0); /* power-down */
- writeb(SAB82532_CCR0_MCE | SAB82532_CCR0_SC_NRZ |
- SAB82532_CCR0_SM_ASYNC, &up->regs->w.ccr0);
- writeb(SAB82532_CCR1_ODS | SAB82532_CCR1_BCR | 7, &up->regs->w.ccr1);
- writeb(SAB82532_CCR2_BDF | SAB82532_CCR2_SSEL |
- SAB82532_CCR2_TOE, &up->regs->w.ccr2);
- writeb(0, &up->regs->w.ccr3);
- writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &up->regs->w.ccr4);
- up->cached_mode = (SAB82532_MODE_RTS | SAB82532_MODE_FCTS |
- SAB82532_MODE_RAC);
- writeb(up->cached_mode, &up->regs->w.mode);
- writeb(SAB82532_RFC_DPS|SAB82532_RFC_RFTH_32, &up->regs->w.rfc);
-
- tmp = readb(&up->regs->rw.ccr0);
- tmp |= SAB82532_CCR0_PU; /* power-up */
- writeb(tmp, &up->regs->rw.ccr0);
-
- /*
- * Finally, enable interrupts
- */
- up->interrupt_mask0 = (SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
- SAB82532_IMR0_PLLA);
- writeb(up->interrupt_mask0, &up->regs->w.imr0);
- up->interrupt_mask1 = (SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
- SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
- SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
- SAB82532_IMR1_XPR);
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
- set_bit(SAB82532_ALLS, &up->irqflags);
- set_bit(SAB82532_XPR, &up->irqflags);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return 0;
-}
-
-/* port->lock is not held. */
-static void sunsab_shutdown(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- /* Disable Interrupts */
- up->interrupt_mask0 = 0xff;
- writeb(up->interrupt_mask0, &up->regs->w.imr0);
- up->interrupt_mask1 = 0xff;
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
-
- /* Disable break condition */
- up->cached_dafo = readb(&up->regs->rw.dafo);
- up->cached_dafo &= ~SAB82532_DAFO_XBRK;
- writeb(up->cached_dafo, &up->regs->rw.dafo);
-
- /* Disable Receiver */
- up->cached_mode &= ~SAB82532_MODE_RAC;
- writeb(up->cached_mode, &up->regs->rw.mode);
-
- /*
- * XXX FIXME
- *
- * If the chip is powered down here the system hangs/crashes during
- * reboot or shutdown. This needs to be investigated further,
- * similar behaviour occurs in 2.4 when the driver is configured
- * as a module only. One hint may be that data is sometimes
- * transmitted at 9600 baud during shutdown (regardless of the
- * speed the chip was configured for when the port was open).
- */
-#if 0
- /* Power Down */
- tmp = readb(&up->regs->rw.ccr0);
- tmp &= ~SAB82532_CCR0_PU;
- writeb(tmp, &up->regs->rw.ccr0);
-#endif
-
- spin_unlock_irqrestore(&up->port.lock, flags);
- free_irq(up->port.irq, up);
-}
-
-/*
- * This is used to figure out the divisor speeds.
- *
- * The formula is: Baud = SAB_BASE_BAUD / ((N + 1) * (1 << M)),
- *
- * with 0 <= N < 64 and 0 <= M < 16
- */
-
-static void calc_ebrg(int baud, int *n_ret, int *m_ret)
-{
- int n, m;
-
- if (baud == 0) {
- *n_ret = 0;
- *m_ret = 0;
- return;
- }
-
- /*
- * We scale numbers by 10 so that we get better accuracy
- * without having to use floating point. Here we increment m
- * until n is within the valid range.
- */
- n = (SAB_BASE_BAUD * 10) / baud;
- m = 0;
- while (n >= 640) {
- n = n / 2;
- m++;
- }
- n = (n+5) / 10;
- /*
- * We try very hard to avoid speeds with M == 0 since they may
- * not work correctly for XTAL frequences above 10 MHz.
- */
- if ((m == 0) && ((n & 1) == 0)) {
- n = n / 2;
- m++;
- }
- *n_ret = n - 1;
- *m_ret = m;
-}
-
-/* Internal routine, port->lock is held and local interrupts are disabled. */
-static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cflag,
- unsigned int iflag, unsigned int baud,
- unsigned int quot)
-{
- unsigned char dafo;
- int bits, n, m;
-
- /* Byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
- case CS6: dafo = SAB82532_DAFO_CHL6; bits = 8; break;
- case CS7: dafo = SAB82532_DAFO_CHL7; bits = 9; break;
- case CS8: dafo = SAB82532_DAFO_CHL8; bits = 10; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
- }
-
- if (cflag & CSTOPB) {
- dafo |= SAB82532_DAFO_STOP;
- bits++;
- }
-
- if (cflag & PARENB) {
- dafo |= SAB82532_DAFO_PARE;
- bits++;
- }
-
- if (cflag & PARODD) {
- dafo |= SAB82532_DAFO_PAR_ODD;
- } else {
- dafo |= SAB82532_DAFO_PAR_EVEN;
- }
- up->cached_dafo = dafo;
-
- calc_ebrg(baud, &n, &m);
-
- up->cached_ebrg = n | (m << 6);
-
- up->tec_timeout = (10 * 1000000) / baud;
- up->cec_timeout = up->tec_timeout >> 2;
-
- /* CTS flow control flags */
- /* We encode read_status_mask and ignore_status_mask like so:
- *
- * ---------------------
- * | ... | ISR1 | ISR0 |
- * ---------------------
- * .. 15 8 7 0
- */
-
- up->port.read_status_mask = (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
- SAB82532_ISR0_RFO | SAB82532_ISR0_RPF |
- SAB82532_ISR0_CDSC);
- up->port.read_status_mask |= (SAB82532_ISR1_CSC |
- SAB82532_ISR1_ALLS |
- SAB82532_ISR1_XPR) << 8;
- if (iflag & INPCK)
- up->port.read_status_mask |= (SAB82532_ISR0_PERR |
- SAB82532_ISR0_FERR);
- if (iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= (SAB82532_ISR1_BRK << 8);
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= (SAB82532_ISR0_PERR |
- SAB82532_ISR0_FERR);
- if (iflag & IGNBRK) {
- up->port.ignore_status_mask |= (SAB82532_ISR1_BRK << 8);
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= SAB82532_ISR0_RFO;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((cflag & CREAD) == 0)
- up->port.ignore_status_mask |= (SAB82532_ISR0_RPF |
- SAB82532_ISR0_TCD);
-
- uart_update_timeout(&up->port, cflag,
- (up->port.uartclk / (16 * quot)));
-
- /* Now schedule a register update when the chip's
- * transmitter is idle.
- */
- up->cached_mode |= SAB82532_MODE_RAC;
- set_bit(SAB82532_REGS_PENDING, &up->irqflags);
- if (test_bit(SAB82532_XPR, &up->irqflags))
- sunsab_tx_idle(up);
-}
-
-/* port->lock is not held. */
-static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
- unsigned long flags;
- unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
- unsigned int quot = uart_get_divisor(port, baud);
-
- spin_lock_irqsave(&up->port.lock, flags);
- sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud, quot);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static const char *sunsab_type(struct uart_port *port)
-{
- struct uart_sunsab_port *up = (void *)port;
- static char buf[36];
-
- sprintf(buf, "SAB82532 %s", sab82532_version[up->type]);
- return buf;
-}
-
-static void sunsab_release_port(struct uart_port *port)
-{
-}
-
-static int sunsab_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void sunsab_config_port(struct uart_port *port, int flags)
-{
-}
-
-static int sunsab_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-static struct uart_ops sunsab_pops = {
- .tx_empty = sunsab_tx_empty,
- .set_mctrl = sunsab_set_mctrl,
- .get_mctrl = sunsab_get_mctrl,
- .stop_tx = sunsab_stop_tx,
- .start_tx = sunsab_start_tx,
- .send_xchar = sunsab_send_xchar,
- .stop_rx = sunsab_stop_rx,
- .enable_ms = sunsab_enable_ms,
- .break_ctl = sunsab_break_ctl,
- .startup = sunsab_startup,
- .shutdown = sunsab_shutdown,
- .set_termios = sunsab_set_termios,
- .type = sunsab_type,
- .release_port = sunsab_release_port,
- .request_port = sunsab_request_port,
- .config_port = sunsab_config_port,
- .verify_port = sunsab_verify_port,
-};
-
-static struct uart_driver sunsab_reg = {
- .owner = THIS_MODULE,
- .driver_name = "sunsab",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
-};
-
-static struct uart_sunsab_port *sunsab_ports;
-
-#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE
-
-static void sunsab_console_putchar(struct uart_port *port, int c)
-{
- struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
-
- sunsab_tec_wait(up);
- writeb(c, &up->regs->w.tic);
-}
-
-static void sunsab_console_write(struct console *con, const char *s, unsigned n)
-{
- struct uart_sunsab_port *up = &sunsab_ports[con->index];
- unsigned long flags;
- int locked = 1;
-
- local_irq_save(flags);
- if (up->port.sysrq) {
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&up->port.lock);
- } else
- spin_lock(&up->port.lock);
-
- uart_console_write(&up->port, s, n, sunsab_console_putchar);
- sunsab_tec_wait(up);
-
- if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
-}
-
-static int sunsab_console_setup(struct console *con, char *options)
-{
- struct uart_sunsab_port *up = &sunsab_ports[con->index];
- unsigned long flags;
- unsigned int baud, quot;
-
- /*
- * The console framework calls us for each and every port
- * registered. Defer the console setup until the requested
- * port has been properly discovered. A bit of a hack,
- * though...
- */
- if (up->port.type != PORT_SUNSAB)
- return -1;
-
- printk("Console: ttyS%d (SAB82532)\n",
- (sunsab_reg.minor - 64) + con->index);
-
- sunserial_console_termios(con, up->port.dev->of_node);
-
- switch (con->cflag & CBAUD) {
- case B150: baud = 150; break;
- case B300: baud = 300; break;
- case B600: baud = 600; break;
- case B1200: baud = 1200; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- default: case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- case B57600: baud = 57600; break;
- case B115200: baud = 115200; break;
- case B230400: baud = 230400; break;
- case B460800: baud = 460800; break;
- };
-
- /*
- * Temporary fix.
- */
- spin_lock_init(&up->port.lock);
-
- /*
- * Initialize the hardware
- */
- sunsab_startup(&up->port);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Finally, enable interrupts
- */
- up->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
- SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
- writeb(up->interrupt_mask0, &up->regs->w.imr0);
- up->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
- SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
- SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
- SAB82532_IMR1_XPR;
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
-
- quot = uart_get_divisor(&up->port, baud);
- sunsab_convert_to_sab(up, con->cflag, 0, baud, quot);
- sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return 0;
-}
-
-static struct console sunsab_console = {
- .name = "ttyS",
- .write = sunsab_console_write,
- .device = uart_console_device,
- .setup = sunsab_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sunsab_reg,
-};
-
-static inline struct console *SUNSAB_CONSOLE(void)
-{
- return &sunsab_console;
-}
-#else
-#define SUNSAB_CONSOLE() (NULL)
-#define sunsab_console_init() do { } while (0)
-#endif
-
-static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
- struct platform_device *op,
- unsigned long offset,
- int line)
-{
- up->port.line = line;
- up->port.dev = &op->dev;
-
- up->port.mapbase = op->resource[0].start + offset;
- up->port.membase = of_ioremap(&op->resource[0], offset,
- sizeof(union sab82532_async_regs),
- "sab");
- if (!up->port.membase)
- return -ENOMEM;
- up->regs = (union sab82532_async_regs __iomem *) up->port.membase;
-
- up->port.irq = op->archdata.irqs[0];
-
- up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
- up->port.iotype = UPIO_MEM;
-
- writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
-
- up->port.ops = &sunsab_pops;
- up->port.type = PORT_SUNSAB;
- up->port.uartclk = SAB_BASE_BAUD;
-
- up->type = readb(&up->regs->r.vstr) & 0x0f;
- writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &up->regs->w.pcr);
- writeb(0xff, &up->regs->w.pim);
- if ((up->port.line & 0x1) == 0) {
- up->pvr_dsr_bit = (1 << 0);
- up->pvr_dtr_bit = (1 << 1);
- up->gis_shift = 2;
- } else {
- up->pvr_dsr_bit = (1 << 3);
- up->pvr_dtr_bit = (1 << 2);
- up->gis_shift = 0;
- }
- up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
- writeb(up->cached_pvr, &up->regs->w.pvr);
- up->cached_mode = readb(&up->regs->rw.mode);
- up->cached_mode |= SAB82532_MODE_FRTS;
- writeb(up->cached_mode, &up->regs->rw.mode);
- up->cached_mode |= SAB82532_MODE_RTS;
- writeb(up->cached_mode, &up->regs->rw.mode);
-
- up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
- up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
-
- return 0;
-}
-
-static int __devinit sab_probe(struct platform_device *op, const struct of_device_id *match)
-{
- static int inst;
- struct uart_sunsab_port *up;
- int err;
-
- up = &sunsab_ports[inst * 2];
-
- err = sunsab_init_one(&up[0], op,
- 0,
- (inst * 2) + 0);
- if (err)
- goto out;
-
- err = sunsab_init_one(&up[1], op,
- sizeof(union sab82532_async_regs),
- (inst * 2) + 1);
- if (err)
- goto out1;
-
- sunserial_console_match(SUNSAB_CONSOLE(), op->dev.of_node,
- &sunsab_reg, up[0].port.line,
- false);
-
- sunserial_console_match(SUNSAB_CONSOLE(), op->dev.of_node,
- &sunsab_reg, up[1].port.line,
- false);
-
- err = uart_add_one_port(&sunsab_reg, &up[0].port);
- if (err)
- goto out2;
-
- err = uart_add_one_port(&sunsab_reg, &up[1].port);
- if (err)
- goto out3;
-
- dev_set_drvdata(&op->dev, &up[0]);
-
- inst++;
-
- return 0;
-
-out3:
- uart_remove_one_port(&sunsab_reg, &up[0].port);
-out2:
- of_iounmap(&op->resource[0],
- up[1].port.membase,
- sizeof(union sab82532_async_regs));
-out1:
- of_iounmap(&op->resource[0],
- up[0].port.membase,
- sizeof(union sab82532_async_regs));
-out:
- return err;
-}
-
-static int __devexit sab_remove(struct platform_device *op)
-{
- struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
-
- uart_remove_one_port(&sunsab_reg, &up[1].port);
- uart_remove_one_port(&sunsab_reg, &up[0].port);
- of_iounmap(&op->resource[0],
- up[1].port.membase,
- sizeof(union sab82532_async_regs));
- of_iounmap(&op->resource[0],
- up[0].port.membase,
- sizeof(union sab82532_async_regs));
-
- dev_set_drvdata(&op->dev, NULL);
-
- return 0;
-}
-
-static const struct of_device_id sab_match[] = {
- {
- .name = "se",
- },
- {
- .name = "serial",
- .compatible = "sab82532",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, sab_match);
-
-static struct of_platform_driver sab_driver = {
- .driver = {
- .name = "sab",
- .owner = THIS_MODULE,
- .of_match_table = sab_match,
- },
- .probe = sab_probe,
- .remove = __devexit_p(sab_remove),
-};
-
-static int __init sunsab_init(void)
-{
- struct device_node *dp;
- int err;
- int num_channels = 0;
-
- for_each_node_by_name(dp, "se")
- num_channels += 2;
- for_each_node_by_name(dp, "serial") {
- if (of_device_is_compatible(dp, "sab82532"))
- num_channels += 2;
- }
-
- if (num_channels) {
- sunsab_ports = kzalloc(sizeof(struct uart_sunsab_port) *
- num_channels, GFP_KERNEL);
- if (!sunsab_ports)
- return -ENOMEM;
-
- err = sunserial_register_minors(&sunsab_reg, num_channels);
- if (err) {
- kfree(sunsab_ports);
- sunsab_ports = NULL;
-
- return err;
- }
- }
-
- return of_register_platform_driver(&sab_driver);
-}
-
-static void __exit sunsab_exit(void)
-{
- of_unregister_platform_driver(&sab_driver);
- if (sunsab_reg.nr) {
- sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr);
- }
-
- kfree(sunsab_ports);
- sunsab_ports = NULL;
-}
-
-module_init(sunsab_init);
-module_exit(sunsab_exit);
-
-MODULE_AUTHOR("Eddie C. Dost and David S. Miller");
-MODULE_DESCRIPTION("Sun SAB82532 serial port driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunsab.h b/drivers/serial/sunsab.h
deleted file mode 100644
index b78e1f7b8050..000000000000
--- a/drivers/serial/sunsab.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/* sunsab.h: Register Definitions for the Siemens SAB82532 DUSCC
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- */
-
-#ifndef _SUNSAB_H
-#define _SUNSAB_H
-
-struct sab82532_async_rd_regs {
- u8 rfifo[0x20]; /* Receive FIFO */
- u8 star; /* Status Register */
- u8 __pad1;
- u8 mode; /* Mode Register */
- u8 timr; /* Timer Register */
- u8 xon; /* XON Character */
- u8 xoff; /* XOFF Character */
- u8 tcr; /* Termination Character Register */
- u8 dafo; /* Data Format */
- u8 rfc; /* RFIFO Control Register */
- u8 __pad2;
- u8 rbcl; /* Receive Byte Count Low */
- u8 rbch; /* Receive Byte Count High */
- u8 ccr0; /* Channel Configuration Register 0 */
- u8 ccr1; /* Channel Configuration Register 1 */
- u8 ccr2; /* Channel Configuration Register 2 */
- u8 ccr3; /* Channel Configuration Register 3 */
- u8 __pad3[4];
- u8 vstr; /* Version Status Register */
- u8 __pad4[3];
- u8 gis; /* Global Interrupt Status */
- u8 ipc; /* Interrupt Port Configuration */
- u8 isr0; /* Interrupt Status 0 */
- u8 isr1; /* Interrupt Status 1 */
- u8 pvr; /* Port Value Register */
- u8 pis; /* Port Interrupt Status */
- u8 pcr; /* Port Configuration Register */
- u8 ccr4; /* Channel Configuration Register 4 */
-};
-
-struct sab82532_async_wr_regs {
- u8 xfifo[0x20]; /* Transmit FIFO */
- u8 cmdr; /* Command Register */
- u8 __pad1;
- u8 mode;
- u8 timr;
- u8 xon;
- u8 xoff;
- u8 tcr;
- u8 dafo;
- u8 rfc;
- u8 __pad2;
- u8 xbcl; /* Transmit Byte Count Low */
- u8 xbch; /* Transmit Byte Count High */
- u8 ccr0;
- u8 ccr1;
- u8 ccr2;
- u8 ccr3;
- u8 tsax; /* Time-Slot Assignment Reg. Transmit */
- u8 tsar; /* Time-Slot Assignment Reg. Receive */
- u8 xccr; /* Transmit Channel Capacity Register */
- u8 rccr; /* Receive Channel Capacity Register */
- u8 bgr; /* Baud Rate Generator Register */
- u8 tic; /* Transmit Immediate Character */
- u8 mxn; /* Mask XON Character */
- u8 mxf; /* Mask XOFF Character */
- u8 iva; /* Interrupt Vector Address */
- u8 ipc;
- u8 imr0; /* Interrupt Mask Register 0 */
- u8 imr1; /* Interrupt Mask Register 1 */
- u8 pvr;
- u8 pim; /* Port Interrupt Mask */
- u8 pcr;
- u8 ccr4;
-};
-
-struct sab82532_async_rw_regs { /* Read/Write registers */
- u8 __pad1[0x20];
- u8 __pad2;
- u8 __pad3;
- u8 mode;
- u8 timr;
- u8 xon;
- u8 xoff;
- u8 tcr;
- u8 dafo;
- u8 rfc;
- u8 __pad4;
- u8 __pad5;
- u8 __pad6;
- u8 ccr0;
- u8 ccr1;
- u8 ccr2;
- u8 ccr3;
- u8 __pad7;
- u8 __pad8;
- u8 __pad9;
- u8 __pad10;
- u8 __pad11;
- u8 __pad12;
- u8 __pad13;
- u8 __pad14;
- u8 __pad15;
- u8 ipc;
- u8 __pad16;
- u8 __pad17;
- u8 pvr;
- u8 __pad18;
- u8 pcr;
- u8 ccr4;
-};
-
-union sab82532_async_regs {
- __volatile__ struct sab82532_async_rd_regs r;
- __volatile__ struct sab82532_async_wr_regs w;
- __volatile__ struct sab82532_async_rw_regs rw;
-};
-
-union sab82532_irq_status {
- unsigned short stat;
- struct {
- unsigned char isr0;
- unsigned char isr1;
- } sreg;
-};
-
-/* irqflags bits */
-#define SAB82532_ALLS 0x00000001
-#define SAB82532_XPR 0x00000002
-#define SAB82532_REGS_PENDING 0x00000004
-
-/* RFIFO Status Byte */
-#define SAB82532_RSTAT_PE 0x80
-#define SAB82532_RSTAT_FE 0x40
-#define SAB82532_RSTAT_PARITY 0x01
-
-/* Status Register (STAR) */
-#define SAB82532_STAR_XDOV 0x80
-#define SAB82532_STAR_XFW 0x40
-#define SAB82532_STAR_RFNE 0x20
-#define SAB82532_STAR_FCS 0x10
-#define SAB82532_STAR_TEC 0x08
-#define SAB82532_STAR_CEC 0x04
-#define SAB82532_STAR_CTS 0x02
-
-/* Command Register (CMDR) */
-#define SAB82532_CMDR_RMC 0x80
-#define SAB82532_CMDR_RRES 0x40
-#define SAB82532_CMDR_RFRD 0x20
-#define SAB82532_CMDR_STI 0x10
-#define SAB82532_CMDR_XF 0x08
-#define SAB82532_CMDR_XRES 0x01
-
-/* Mode Register (MODE) */
-#define SAB82532_MODE_FRTS 0x40
-#define SAB82532_MODE_FCTS 0x20
-#define SAB82532_MODE_FLON 0x10
-#define SAB82532_MODE_RAC 0x08
-#define SAB82532_MODE_RTS 0x04
-#define SAB82532_MODE_TRS 0x02
-#define SAB82532_MODE_TLP 0x01
-
-/* Timer Register (TIMR) */
-#define SAB82532_TIMR_CNT_MASK 0xe0
-#define SAB82532_TIMR_VALUE_MASK 0x1f
-
-/* Data Format (DAFO) */
-#define SAB82532_DAFO_XBRK 0x40
-#define SAB82532_DAFO_STOP 0x20
-#define SAB82532_DAFO_PAR_SPACE 0x00
-#define SAB82532_DAFO_PAR_ODD 0x08
-#define SAB82532_DAFO_PAR_EVEN 0x10
-#define SAB82532_DAFO_PAR_MARK 0x18
-#define SAB82532_DAFO_PARE 0x04
-#define SAB82532_DAFO_CHL8 0x00
-#define SAB82532_DAFO_CHL7 0x01
-#define SAB82532_DAFO_CHL6 0x02
-#define SAB82532_DAFO_CHL5 0x03
-
-/* RFIFO Control Register (RFC) */
-#define SAB82532_RFC_DPS 0x40
-#define SAB82532_RFC_DXS 0x20
-#define SAB82532_RFC_RFDF 0x10
-#define SAB82532_RFC_RFTH_1 0x00
-#define SAB82532_RFC_RFTH_4 0x04
-#define SAB82532_RFC_RFTH_16 0x08
-#define SAB82532_RFC_RFTH_32 0x0c
-#define SAB82532_RFC_TCDE 0x01
-
-/* Received Byte Count High (RBCH) */
-#define SAB82532_RBCH_DMA 0x80
-#define SAB82532_RBCH_CAS 0x20
-
-/* Transmit Byte Count High (XBCH) */
-#define SAB82532_XBCH_DMA 0x80
-#define SAB82532_XBCH_CAS 0x20
-#define SAB82532_XBCH_XC 0x10
-
-/* Channel Configuration Register 0 (CCR0) */
-#define SAB82532_CCR0_PU 0x80
-#define SAB82532_CCR0_MCE 0x40
-#define SAB82532_CCR0_SC_NRZ 0x00
-#define SAB82532_CCR0_SC_NRZI 0x08
-#define SAB82532_CCR0_SC_FM0 0x10
-#define SAB82532_CCR0_SC_FM1 0x14
-#define SAB82532_CCR0_SC_MANCH 0x18
-#define SAB82532_CCR0_SM_HDLC 0x00
-#define SAB82532_CCR0_SM_SDLC_LOOP 0x01
-#define SAB82532_CCR0_SM_BISYNC 0x02
-#define SAB82532_CCR0_SM_ASYNC 0x03
-
-/* Channel Configuration Register 1 (CCR1) */
-#define SAB82532_CCR1_ODS 0x10
-#define SAB82532_CCR1_BCR 0x08
-#define SAB82532_CCR1_CM_MASK 0x07
-
-/* Channel Configuration Register 2 (CCR2) */
-#define SAB82532_CCR2_SOC1 0x80
-#define SAB82532_CCR2_SOC0 0x40
-#define SAB82532_CCR2_BR9 0x80
-#define SAB82532_CCR2_BR8 0x40
-#define SAB82532_CCR2_BDF 0x20
-#define SAB82532_CCR2_SSEL 0x10
-#define SAB82532_CCR2_XCS0 0x20
-#define SAB82532_CCR2_RCS0 0x10
-#define SAB82532_CCR2_TOE 0x08
-#define SAB82532_CCR2_RWX 0x04
-#define SAB82532_CCR2_DIV 0x01
-
-/* Channel Configuration Register 3 (CCR3) */
-#define SAB82532_CCR3_PSD 0x01
-
-/* Time Slot Assignment Register Transmit (TSAX) */
-#define SAB82532_TSAX_TSNX_MASK 0xfc
-#define SAB82532_TSAX_XCS2 0x02 /* see also CCR2 */
-#define SAB82532_TSAX_XCS1 0x01
-
-/* Time Slot Assignment Register Receive (TSAR) */
-#define SAB82532_TSAR_TSNR_MASK 0xfc
-#define SAB82532_TSAR_RCS2 0x02 /* see also CCR2 */
-#define SAB82532_TSAR_RCS1 0x01
-
-/* Version Status Register (VSTR) */
-#define SAB82532_VSTR_CD 0x80
-#define SAB82532_VSTR_DPLA 0x40
-#define SAB82532_VSTR_VN_MASK 0x0f
-#define SAB82532_VSTR_VN_1 0x00
-#define SAB82532_VSTR_VN_2 0x01
-#define SAB82532_VSTR_VN_3_2 0x02
-
-/* Global Interrupt Status Register (GIS) */
-#define SAB82532_GIS_PI 0x80
-#define SAB82532_GIS_ISA1 0x08
-#define SAB82532_GIS_ISA0 0x04
-#define SAB82532_GIS_ISB1 0x02
-#define SAB82532_GIS_ISB0 0x01
-
-/* Interrupt Vector Address (IVA) */
-#define SAB82532_IVA_MASK 0xf1
-
-/* Interrupt Port Configuration (IPC) */
-#define SAB82532_IPC_VIS 0x80
-#define SAB82532_IPC_SLA1 0x10
-#define SAB82532_IPC_SLA0 0x08
-#define SAB82532_IPC_CASM 0x04
-#define SAB82532_IPC_IC_OPEN_DRAIN 0x00
-#define SAB82532_IPC_IC_ACT_LOW 0x01
-#define SAB82532_IPC_IC_ACT_HIGH 0x03
-
-/* Interrupt Status Register 0 (ISR0) */
-#define SAB82532_ISR0_TCD 0x80
-#define SAB82532_ISR0_TIME 0x40
-#define SAB82532_ISR0_PERR 0x20
-#define SAB82532_ISR0_FERR 0x10
-#define SAB82532_ISR0_PLLA 0x08
-#define SAB82532_ISR0_CDSC 0x04
-#define SAB82532_ISR0_RFO 0x02
-#define SAB82532_ISR0_RPF 0x01
-
-/* Interrupt Status Register 1 (ISR1) */
-#define SAB82532_ISR1_BRK 0x80
-#define SAB82532_ISR1_BRKT 0x40
-#define SAB82532_ISR1_ALLS 0x20
-#define SAB82532_ISR1_XOFF 0x10
-#define SAB82532_ISR1_TIN 0x08
-#define SAB82532_ISR1_CSC 0x04
-#define SAB82532_ISR1_XON 0x02
-#define SAB82532_ISR1_XPR 0x01
-
-/* Interrupt Mask Register 0 (IMR0) */
-#define SAB82532_IMR0_TCD 0x80
-#define SAB82532_IMR0_TIME 0x40
-#define SAB82532_IMR0_PERR 0x20
-#define SAB82532_IMR0_FERR 0x10
-#define SAB82532_IMR0_PLLA 0x08
-#define SAB82532_IMR0_CDSC 0x04
-#define SAB82532_IMR0_RFO 0x02
-#define SAB82532_IMR0_RPF 0x01
-
-/* Interrupt Mask Register 1 (IMR1) */
-#define SAB82532_IMR1_BRK 0x80
-#define SAB82532_IMR1_BRKT 0x40
-#define SAB82532_IMR1_ALLS 0x20
-#define SAB82532_IMR1_XOFF 0x10
-#define SAB82532_IMR1_TIN 0x08
-#define SAB82532_IMR1_CSC 0x04
-#define SAB82532_IMR1_XON 0x02
-#define SAB82532_IMR1_XPR 0x01
-
-/* Port Interrupt Status Register (PIS) */
-#define SAB82532_PIS_SYNC_B 0x08
-#define SAB82532_PIS_DTR_B 0x04
-#define SAB82532_PIS_DTR_A 0x02
-#define SAB82532_PIS_SYNC_A 0x01
-
-/* Channel Configuration Register 4 (CCR4) */
-#define SAB82532_CCR4_MCK4 0x80
-#define SAB82532_CCR4_EBRG 0x40
-#define SAB82532_CCR4_TST1 0x20
-#define SAB82532_CCR4_ICD 0x10
-
-
-#endif /* !(_SUNSAB_H) */
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
deleted file mode 100644
index 551ebfe3ccbb..000000000000
--- a/drivers/serial/sunsu.c
+++ /dev/null
@@ -1,1608 +0,0 @@
-/*
- * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 1998-1999 Pete Zaitcev (zaitcev@yahoo.com)
- *
- * This is mainly a variation of 8250.c, credits go to authors mentioned
- * therein. In fact this driver should be merged into the generic 8250.c
- * infrastructure perhaps using a 8250_sparc.c module.
- *
- * Fixed to use tty_get_baud_rate().
- * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
- *
- * Converted to new 2.5.x UART layer.
- * David S. Miller (davem@davemloft.net), 2002-Jul-29
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/circ_buf.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/slab.h>
-#ifdef CONFIG_SERIO
-#include <linux/serio.h>
-#endif
-#include <linux/serial_reg.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-
-#if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#include "suncore.h"
-
-/* We are on a NS PC87303 clocked with 24.0 MHz, which results
- * in a UART clock of 1.8462 MHz.
- */
-#define SU_BASE_BAUD (1846200 / 16)
-
-enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT };
-static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" };
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
- { "unknown", 1, 0 },
- { "8250", 1, 0 },
- { "16450", 1, 0 },
- { "16550", 1, 0 },
- { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
- { "Cirrus", 1, 0 },
- { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
- { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
- { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO },
- { "Startech", 1, 0 },
- { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO },
- { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
- { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
- { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }
-};
-
-struct uart_sunsu_port {
- struct uart_port port;
- unsigned char acr;
- unsigned char ier;
- unsigned short rev;
- unsigned char lcr;
- unsigned int lsr_break_flag;
- unsigned int cflag;
-
- /* Probing information. */
- enum su_type su_type;
- unsigned int type_probed; /* XXX Stupid */
- unsigned long reg_size;
-
-#ifdef CONFIG_SERIO
- struct serio serio;
- int serio_open;
-#endif
-};
-
-static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
-{
- offset <<= up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- return inb(up->port.iobase + 1);
-
- case UPIO_MEM:
- return readb(up->port.membase + offset);
-
- default:
- return inb(up->port.iobase + offset);
- }
-}
-
-static void serial_out(struct uart_sunsu_port *up, int offset, int value)
-{
-#ifndef CONFIG_SPARC64
- /*
- * MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are
- * connected with a gate then go to SlavIO. When IRQ4 goes tristated
- * gate outputs a logical one. Since we use level triggered interrupts
- * we have lockup and watchdog reset. We cannot mask IRQ because
- * keyboard shares IRQ with us (Word has it as Bob Smelik's design).
- * This problem is similar to what Alpha people suffer, see serial.c.
- */
- if (offset == UART_MCR)
- value |= UART_MCR_OUT2;
-#endif
- offset <<= up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- outb(value, up->port.iobase + 1);
- break;
-
- case UPIO_MEM:
- writeb(value, up->port.membase + offset);
- break;
-
- default:
- outb(value, up->port.iobase + offset);
- }
-}
-
-/*
- * We used to support using pause I/O for certain machines. We
- * haven't supported this for a while, but just in case it's badly
- * needed for certain old 386 machines, I've left these #define's
- * in....
- */
-#define serial_inp(up, offset) serial_in(up, offset)
-#define serial_outp(up, offset, value) serial_out(up, offset, value)
-
-
-/*
- * For the 16C950
- */
-static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value)
-{
- serial_out(up, UART_SCR, offset);
- serial_out(up, UART_ICR, value);
-}
-
-#if 0 /* Unused currently */
-static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset)
-{
- unsigned int value;
-
- serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
- serial_out(up, UART_SCR, offset);
- value = serial_in(up, UART_ICR);
- serial_icr_write(up, UART_ACR, up->acr);
-
- return value;
-}
-#endif
-
-#ifdef CONFIG_SERIAL_8250_RSA
-/*
- * Attempts to turn on the RSA FIFO. Returns zero on failure.
- * We set the port uart clock rate if we succeed.
- */
-static int __enable_rsa(struct uart_sunsu_port *up)
-{
- unsigned char mode;
- int result;
-
- mode = serial_inp(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
-
- if (!result) {
- serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
- mode = serial_inp(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-
- return result;
-}
-
-static void enable_rsa(struct uart_sunsu_port *up)
-{
- if (up->port.type == PORT_RSA) {
- if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
- __enable_rsa(up);
- spin_unlock_irq(&up->port.lock);
- }
- if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
- serial_outp(up, UART_RSA_FRR, 0);
- }
-}
-
-/*
- * Attempts to turn off the RSA FIFO. Returns zero on failure.
- * It is unknown why interrupts were disabled in here. However,
- * the caller is expected to preserve this behaviour by grabbing
- * the spinlock before calling this function.
- */
-static void disable_rsa(struct uart_sunsu_port *up)
-{
- unsigned char mode;
- int result;
-
- if (up->port.type == PORT_RSA &&
- up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
-
- mode = serial_inp(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
-
- if (!result) {
- serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
- mode = serial_inp(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
- spin_unlock_irq(&up->port.lock);
- }
-}
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-static inline void __stop_tx(struct uart_sunsu_port *p)
-{
- if (p->ier & UART_IER_THRI) {
- p->ier &= ~UART_IER_THRI;
- serial_out(p, UART_IER, p->ier);
- }
-}
-
-static void sunsu_stop_tx(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
-
- __stop_tx(up);
-
- /*
- * We really want to stop the transmitter from sending.
- */
- if (up->port.type == PORT_16C950) {
- up->acr |= UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
-}
-
-static void sunsu_start_tx(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-
- /*
- * Re-enable the transmitter if we disabled it.
- */
- if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
- up->acr &= ~UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
-}
-
-static void sunsu_stop_rx(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void sunsu_enable_ms(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static struct tty_struct *
-receive_chars(struct uart_sunsu_port *up, unsigned char *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned char ch, flag;
- int max_count = 256;
- int saw_console_brk = 0;
-
- do {
- ch = serial_inp(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE))) {
- /*
- * For statistics only
- */
- if (*status & UART_LSR_BI) {
- *status &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- if (up->port.cons != NULL &&
- up->port.line == up->port.cons->index)
- saw_console_brk = 1;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (*status & UART_LSR_PE)
- up->port.icount.parity++;
- else if (*status & UART_LSR_FE)
- up->port.icount.frame++;
- if (*status & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ingored.
- */
- *status &= up->port.read_status_mask;
-
- if (up->port.cons != NULL &&
- up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- *status |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-
- if (*status & UART_LSR_BI) {
- flag = TTY_BREAK;
- } else if (*status & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (*status & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0)
- tty_insert_flip_char(tty, ch, flag);
- if (*status & UART_LSR_OE)
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- ignore_char:
- *status = serial_inp(up, UART_LSR);
- } while ((*status & UART_LSR_DR) && (max_count-- > 0));
-
- if (saw_console_brk)
- sun_do_break();
-
- return tty;
-}
-
-static void transmit_chars(struct uart_sunsu_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_outp(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_tx_stopped(&up->port)) {
- sunsu_stop_tx(&up->port);
- return;
- }
- if (uart_circ_empty(xmit)) {
- __stop_tx(up);
- return;
- }
-
- count = up->port.fifosize;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit))
- __stop_tx(up);
-}
-
-static void check_modem_status(struct uart_sunsu_port *up)
-{
- int status;
-
- status = serial_in(up, UART_MSR);
-
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return;
-
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id)
-{
- struct uart_sunsu_port *up = dev_id;
- unsigned long flags;
- unsigned char status;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- do {
- struct tty_struct *tty;
-
- status = serial_inp(up, UART_LSR);
- tty = NULL;
- if (status & UART_LSR_DR)
- tty = receive_chars(up, &status);
- check_modem_status(up);
- if (status & UART_LSR_THRE)
- transmit_chars(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- } while (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT));
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return IRQ_HANDLED;
-}
-
-/* Separate interrupt handling path for keyboard/mouse ports. */
-
-static void
-sunsu_change_speed(struct uart_port *port, unsigned int cflag,
- unsigned int iflag, unsigned int quot);
-
-static void sunsu_change_mouse_baud(struct uart_sunsu_port *up)
-{
- unsigned int cur_cflag = up->cflag;
- int quot, new_baud;
-
- up->cflag &= ~CBAUD;
- up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud);
-
- quot = up->port.uartclk / (16 * new_baud);
-
- sunsu_change_speed(&up->port, up->cflag, 0, quot);
-}
-
-static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break)
-{
- do {
- unsigned char ch = serial_inp(up, UART_RX);
-
- /* Stop-A is handled by drivers/char/keyboard.c now. */
- if (up->su_type == SU_PORT_KBD) {
-#ifdef CONFIG_SERIO
- serio_interrupt(&up->serio, ch, 0);
-#endif
- } else if (up->su_type == SU_PORT_MS) {
- int ret = suncore_mouse_baud_detection(ch, is_break);
-
- switch (ret) {
- case 2:
- sunsu_change_mouse_baud(up);
- /* fallthru */
- case 1:
- break;
-
- case 0:
-#ifdef CONFIG_SERIO
- serio_interrupt(&up->serio, ch, 0);
-#endif
- break;
- };
- }
- } while (serial_in(up, UART_LSR) & UART_LSR_DR);
-}
-
-static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id)
-{
- struct uart_sunsu_port *up = dev_id;
-
- if (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)) {
- unsigned char status = serial_inp(up, UART_LSR);
-
- if ((status & UART_LSR_DR) || (status & UART_LSR_BI))
- receive_kbd_ms_chars(up, (status & UART_LSR_BI) != 0);
- }
-
- return IRQ_HANDLED;
-}
-
-static unsigned int sunsu_tx_empty(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int sunsu_get_mctrl(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned char status;
- unsigned int ret;
-
- status = serial_in(up, UART_MSR);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void sunsu_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- serial_out(up, UART_MCR, mcr);
-}
-
-static void sunsu_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int sunsu_startup(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned long flags;
- int retval;
-
- if (up->port.type == PORT_16C950) {
- /* Wake up and initialize UART */
- up->acr = 0;
- serial_outp(up, UART_LCR, 0xBF);
- serial_outp(up, UART_EFR, UART_EFR_ECB);
- serial_outp(up, UART_IER, 0);
- serial_outp(up, UART_LCR, 0);
- serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
- serial_outp(up, UART_LCR, 0xBF);
- serial_outp(up, UART_EFR, UART_EFR_ECB);
- serial_outp(up, UART_LCR, 0);
- }
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * If this is an RSA port, see if we can kick it up to the
- * higher speed clock.
- */
- enable_rsa(up);
-#endif
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_FCR, 0);
- }
-
- /*
- * Clear the interrupt registers.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- /*
- * At this point, there's no way the LSR could still be 0xff;
- * if it is, then bail out, because there's likely no UART
- * here.
- */
- if (!(up->port.flags & UPF_BUGGY_UART) &&
- (serial_inp(up, UART_LSR) == 0xff)) {
- printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
- return -ENODEV;
- }
-
- if (up->su_type != SU_PORT_PORT) {
- retval = request_irq(up->port.irq, sunsu_kbd_ms_interrupt,
- IRQF_SHARED, su_typev[up->su_type], up);
- } else {
- retval = request_irq(up->port.irq, sunsu_serial_interrupt,
- IRQF_SHARED, su_typev[up->su_type], up);
- }
- if (retval) {
- printk("su: Cannot register IRQ %d\n", up->port.irq);
- return retval;
- }
-
- /*
- * Now, initialize the UART
- */
- serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->port.mctrl |= TIOCM_OUT2;
-
- sunsu_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI;
- serial_outp(up, UART_IER, up->ier);
-
- if (up->port.flags & UPF_FOURPORT) {
- unsigned int icp;
- /*
- * Enable interrupts on the AST Fourport board
- */
- icp = (up->port.iobase & 0xfe0) | 0x01f;
- outb_p(0x80, icp);
- (void) inb_p(icp);
- }
-
- /*
- * And clear the interrupt registers again for luck.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- return 0;
-}
-
-static void sunsu_shutdown(struct uart_port *port)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned long flags;
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_outp(up, UART_IER, 0);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- /* reset interrupts on the AST Fourport board */
- inb((up->port.iobase & 0xfe0) | 0x1f);
- up->port.mctrl |= TIOCM_OUT1;
- } else
- up->port.mctrl &= ~TIOCM_OUT2;
-
- sunsu_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_FCR, 0);
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * Reset the RSA board back to 115kbps compat mode.
- */
- disable_rsa(up);
-#endif
-
- /*
- * Read data port to reset things.
- */
- (void) serial_in(up, UART_RX);
-
- free_irq(up->port.irq, up);
-}
-
-static void
-sunsu_change_speed(struct uart_port *port, unsigned int cflag,
- unsigned int iflag, unsigned int quot)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned char cval, fcr = 0;
- unsigned long flags;
-
- switch (cflag & CSIZE) {
- case CS5:
- cval = 0x00;
- break;
- case CS6:
- cval = 0x01;
- break;
- case CS7:
- cval = 0x02;
- break;
- default:
- case CS8:
- cval = 0x03;
- break;
- }
-
- if (cflag & CSTOPB)
- cval |= 0x04;
- if (cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- /*
- * Work around a bug in the Oxford Semiconductor 952 rev B
- * chip which causes it to seriously miscalculate baud rates
- * when DLL is 0.
- */
- if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
- up->rev == 0x5201)
- quot ++;
-
- if (uart_config[up->port.type].flags & UART_USE_FIFO) {
- if ((up->port.uartclk / quot) < (2400 * 16))
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-#ifdef CONFIG_SERIAL_8250_RSA
- else if (up->port.type == PORT_RSA)
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
-#endif
- else
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
- }
- if (up->port.type == PORT_16750)
- fcr |= UART_FCR7_64BYTE;
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, cflag, (port->uartclk / (16 * quot)));
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, cflag))
- up->ier |= UART_IER_MSI;
-
- serial_out(up, UART_IER, up->ier);
-
- if (uart_config[up->port.type].flags & UART_STARTECH) {
- serial_outp(up, UART_LCR, 0xBF);
- serial_outp(up, UART_EFR, cflag & CRTSCTS ? UART_EFR_CTS :0);
- }
- serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
- serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */
- serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */
- if (up->port.type == PORT_16750)
- serial_outp(up, UART_FCR, fcr); /* set fcr */
- serial_outp(up, UART_LCR, cval); /* reset DLAB */
- up->lcr = cval; /* Save LCR */
- if (up->port.type != PORT_16750) {
- if (fcr & UART_FCR_ENABLE_FIFO) {
- /* emulated UARTs (Lucent Venus 167x) need two steps */
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- }
- serial_outp(up, UART_FCR, fcr); /* set fcr */
- }
-
- up->cflag = cflag;
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-sunsu_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int baud, quot;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- sunsu_change_speed(port, termios->c_cflag, termios->c_iflag, quot);
-}
-
-static void sunsu_release_port(struct uart_port *port)
-{
-}
-
-static int sunsu_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void sunsu_config_port(struct uart_port *port, int flags)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
-
- if (flags & UART_CONFIG_TYPE) {
- /*
- * We are supposed to call autoconfig here, but this requires
- * splitting all the OBP probing crap from the UART probing.
- * We'll do it when we kill sunsu.c altogether.
- */
- port->type = up->type_probed; /* XXX */
- }
-}
-
-static int
-sunsu_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-static const char *
-sunsu_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static struct uart_ops sunsu_pops = {
- .tx_empty = sunsu_tx_empty,
- .set_mctrl = sunsu_set_mctrl,
- .get_mctrl = sunsu_get_mctrl,
- .stop_tx = sunsu_stop_tx,
- .start_tx = sunsu_start_tx,
- .stop_rx = sunsu_stop_rx,
- .enable_ms = sunsu_enable_ms,
- .break_ctl = sunsu_break_ctl,
- .startup = sunsu_startup,
- .shutdown = sunsu_shutdown,
- .set_termios = sunsu_set_termios,
- .type = sunsu_type,
- .release_port = sunsu_release_port,
- .request_port = sunsu_request_port,
- .config_port = sunsu_config_port,
- .verify_port = sunsu_verify_port,
-};
-
-#define UART_NR 4
-
-static struct uart_sunsu_port sunsu_ports[UART_NR];
-
-#ifdef CONFIG_SERIO
-
-static DEFINE_SPINLOCK(sunsu_serio_lock);
-
-static int sunsu_serio_write(struct serio *serio, unsigned char ch)
-{
- struct uart_sunsu_port *up = serio->port_data;
- unsigned long flags;
- int lsr;
-
- spin_lock_irqsave(&sunsu_serio_lock, flags);
-
- do {
- lsr = serial_in(up, UART_LSR);
- } while (!(lsr & UART_LSR_THRE));
-
- /* Send the character out. */
- serial_out(up, UART_TX, ch);
-
- spin_unlock_irqrestore(&sunsu_serio_lock, flags);
-
- return 0;
-}
-
-static int sunsu_serio_open(struct serio *serio)
-{
- struct uart_sunsu_port *up = serio->port_data;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&sunsu_serio_lock, flags);
- if (!up->serio_open) {
- up->serio_open = 1;
- ret = 0;
- } else
- ret = -EBUSY;
- spin_unlock_irqrestore(&sunsu_serio_lock, flags);
-
- return ret;
-}
-
-static void sunsu_serio_close(struct serio *serio)
-{
- struct uart_sunsu_port *up = serio->port_data;
- unsigned long flags;
-
- spin_lock_irqsave(&sunsu_serio_lock, flags);
- up->serio_open = 0;
- spin_unlock_irqrestore(&sunsu_serio_lock, flags);
-}
-
-#endif /* CONFIG_SERIO */
-
-static void sunsu_autoconfig(struct uart_sunsu_port *up)
-{
- unsigned char status1, status2, scratch, scratch2, scratch3;
- unsigned char save_lcr, save_mcr;
- unsigned long flags;
-
- if (up->su_type == SU_PORT_NONE)
- return;
-
- up->type_probed = PORT_UNKNOWN;
- up->port.iotype = UPIO_MEM;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- if (!(up->port.flags & UPF_BUGGY_UART)) {
- /*
- * Do a simple existence test first; if we fail this, there's
- * no point trying anything else.
- *
- * 0x80 is used as a nonsense port to prevent against false
- * positives due to ISA bus float. The assumption is that
- * 0x80 is a non-existent port; which should be safe since
- * include/asm/io.h also makes this assumption.
- */
- scratch = serial_inp(up, UART_IER);
- serial_outp(up, UART_IER, 0);
-#ifdef __i386__
- outb(0xff, 0x080);
-#endif
- scratch2 = serial_inp(up, UART_IER);
- serial_outp(up, UART_IER, 0x0f);
-#ifdef __i386__
- outb(0, 0x080);
-#endif
- scratch3 = serial_inp(up, UART_IER);
- serial_outp(up, UART_IER, scratch);
- if (scratch2 != 0 || scratch3 != 0x0F)
- goto out; /* We failed; there's nothing here */
- }
-
- save_mcr = serial_in(up, UART_MCR);
- save_lcr = serial_in(up, UART_LCR);
-
- /*
- * Check to see if a UART is really there. Certain broken
- * internal modems based on the Rockwell chipset fail this
- * test, because they apparently don't implement the loopback
- * test mode. So this test is skipped on the COM 1 through
- * COM 4 ports. This *should* be safe, since no board
- * manufacturer would be stupid enough to design a board
- * that conflicts with COM 1-4 --- we hope!
- */
- if (!(up->port.flags & UPF_SKIP_TEST)) {
- serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
- status1 = serial_inp(up, UART_MSR) & 0xF0;
- serial_outp(up, UART_MCR, save_mcr);
- if (status1 != 0x90)
- goto out; /* We failed loopback test */
- }
- serial_outp(up, UART_LCR, 0xBF); /* set up for StarTech test */
- serial_outp(up, UART_EFR, 0); /* EFR is the same as FCR */
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- scratch = serial_in(up, UART_IIR) >> 6;
- switch (scratch) {
- case 0:
- up->port.type = PORT_16450;
- break;
- case 1:
- up->port.type = PORT_UNKNOWN;
- break;
- case 2:
- up->port.type = PORT_16550;
- break;
- case 3:
- up->port.type = PORT_16550A;
- break;
- }
- if (up->port.type == PORT_16550A) {
- /* Check for Startech UART's */
- serial_outp(up, UART_LCR, UART_LCR_DLAB);
- if (serial_in(up, UART_EFR) == 0) {
- up->port.type = PORT_16650;
- } else {
- serial_outp(up, UART_LCR, 0xBF);
- if (serial_in(up, UART_EFR) == 0)
- up->port.type = PORT_16650V2;
- }
- }
- if (up->port.type == PORT_16550A) {
- /* Check for TI 16750 */
- serial_outp(up, UART_LCR, save_lcr | UART_LCR_DLAB);
- serial_outp(up, UART_FCR,
- UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- scratch = serial_in(up, UART_IIR) >> 5;
- if (scratch == 7) {
- /*
- * If this is a 16750, and not a cheap UART
- * clone, then it should only go into 64 byte
- * mode if the UART_FCR7_64BYTE bit was set
- * while UART_LCR_DLAB was latched.
- */
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_FCR,
- UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- scratch = serial_in(up, UART_IIR) >> 5;
- if (scratch == 6)
- up->port.type = PORT_16750;
- }
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- }
- serial_outp(up, UART_LCR, save_lcr);
- if (up->port.type == PORT_16450) {
- scratch = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, 0xa5);
- status1 = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, 0x5a);
- status2 = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, scratch);
-
- if ((status1 != 0xa5) || (status2 != 0x5a))
- up->port.type = PORT_8250;
- }
-
- up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
-
- if (up->port.type == PORT_UNKNOWN)
- goto out;
- up->type_probed = up->port.type; /* XXX */
-
- /*
- * Reset the UART.
- */
-#ifdef CONFIG_SERIAL_8250_RSA
- if (up->port.type == PORT_RSA)
- serial_outp(up, UART_RSA_FRR, 0);
-#endif
- serial_outp(up, UART_MCR, save_mcr);
- serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT));
- serial_outp(up, UART_FCR, 0);
- (void)serial_in(up, UART_RX);
- serial_outp(up, UART_IER, 0);
-
-out:
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static struct uart_driver sunsu_reg = {
- .owner = THIS_MODULE,
- .driver_name = "sunsu",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
-};
-
-static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
-{
- int quot, baud;
-#ifdef CONFIG_SERIO
- struct serio *serio;
-#endif
-
- if (up->su_type == SU_PORT_KBD) {
- up->cflag = B1200 | CS8 | CLOCAL | CREAD;
- baud = 1200;
- } else {
- up->cflag = B4800 | CS8 | CLOCAL | CREAD;
- baud = 4800;
- }
- quot = up->port.uartclk / (16 * baud);
-
- sunsu_autoconfig(up);
- if (up->port.type == PORT_UNKNOWN)
- return -ENODEV;
-
- printk("%s: %s port at %llx, irq %u\n",
- up->port.dev->of_node->full_name,
- (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse",
- (unsigned long long) up->port.mapbase,
- up->port.irq);
-
-#ifdef CONFIG_SERIO
- serio = &up->serio;
- serio->port_data = up;
-
- serio->id.type = SERIO_RS232;
- if (up->su_type == SU_PORT_KBD) {
- serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "sukbd", sizeof(serio->name));
- } else {
- serio->id.proto = SERIO_SUN;
- serio->id.extra = 1;
- strlcpy(serio->name, "sums", sizeof(serio->name));
- }
- strlcpy(serio->phys,
- (!(up->port.line & 1) ? "su/serio0" : "su/serio1"),
- sizeof(serio->phys));
-
- serio->write = sunsu_serio_write;
- serio->open = sunsu_serio_open;
- serio->close = sunsu_serio_close;
- serio->dev.parent = up->port.dev;
-
- serio_register_port(serio);
-#endif
-
- sunsu_change_speed(&up->port, up->cflag, 0, quot);
-
- sunsu_startup(&up->port);
- return 0;
-}
-
-/*
- * ------------------------------------------------------------
- * Serial console driver
- * ------------------------------------------------------------
- */
-
-#ifdef CONFIG_SERIAL_SUNSU_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = serial_in(up, UART_LSR);
-
- if (status & UART_LSR_BI)
- up->lsr_break_flag = UART_LSR_BI;
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
- udelay(1);
- }
-}
-
-static void sunsu_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_sunsu_port *up = (struct uart_sunsu_port *)port;
-
- wait_for_xmitr(up);
- serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- */
-static void sunsu_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_sunsu_port *up = &sunsu_ports[co->index];
- unsigned long flags;
- unsigned int ier;
- int locked = 1;
-
- local_irq_save(flags);
- if (up->port.sysrq) {
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&up->port.lock);
- } else
- spin_lock(&up->port.lock);
-
- /*
- * First save the UER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
-
- uart_console_write(&up->port, s, count, sunsu_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- serial_out(up, UART_IER, ier);
-
- if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
-}
-
-/*
- * Setup initial baud/bits/parity. We do two things here:
- * - construct a cflag setting for the first su_open()
- * - initialize the serial port
- * Return non-zero if we didn't find a serial port.
- */
-static int __init sunsu_console_setup(struct console *co, char *options)
-{
- static struct ktermios dummy;
- struct ktermios termios;
- struct uart_port *port;
-
- printk("Console: ttyS%d (SU)\n",
- (sunsu_reg.minor - 64) + co->index);
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- port = &sunsu_ports[co->index].port;
-
- /*
- * Temporary fix.
- */
- spin_lock_init(&port->lock);
-
- /* Get firmware console settings. */
- sunserial_console_termios(co, port->dev->of_node);
-
- memset(&termios, 0, sizeof(struct ktermios));
- termios.c_cflag = co->cflag;
- port->mctrl |= TIOCM_DTR;
- port->ops->set_termios(port, &termios, &dummy);
-
- return 0;
-}
-
-static struct console sunsu_console = {
- .name = "ttyS",
- .write = sunsu_console_write,
- .device = uart_console_device,
- .setup = sunsu_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sunsu_reg,
-};
-
-/*
- * Register console.
- */
-
-static inline struct console *SUNSU_CONSOLE(void)
-{
- return &sunsu_console;
-}
-#else
-#define SUNSU_CONSOLE() (NULL)
-#define sunsu_serial_console_init() do { } while (0)
-#endif
-
-static enum su_type __devinit su_get_type(struct device_node *dp)
-{
- struct device_node *ap = of_find_node_by_path("/aliases");
-
- if (ap) {
- const char *keyb = of_get_property(ap, "keyboard", NULL);
- const char *ms = of_get_property(ap, "mouse", NULL);
-
- if (keyb) {
- if (dp == of_find_node_by_path(keyb))
- return SU_PORT_KBD;
- }
- if (ms) {
- if (dp == of_find_node_by_path(ms))
- return SU_PORT_MS;
- }
- }
-
- return SU_PORT_PORT;
-}
-
-static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match)
-{
- static int inst;
- struct device_node *dp = op->dev.of_node;
- struct uart_sunsu_port *up;
- struct resource *rp;
- enum su_type type;
- bool ignore_line;
- int err;
-
- type = su_get_type(dp);
- if (type == SU_PORT_PORT) {
- if (inst >= UART_NR)
- return -EINVAL;
- up = &sunsu_ports[inst];
- } else {
- up = kzalloc(sizeof(*up), GFP_KERNEL);
- if (!up)
- return -ENOMEM;
- }
-
- up->port.line = inst;
-
- spin_lock_init(&up->port.lock);
-
- up->su_type = type;
-
- rp = &op->resource[0];
- up->port.mapbase = rp->start;
- up->reg_size = (rp->end - rp->start) + 1;
- up->port.membase = of_ioremap(rp, 0, up->reg_size, "su");
- if (!up->port.membase) {
- if (type != SU_PORT_PORT)
- kfree(up);
- return -ENOMEM;
- }
-
- up->port.irq = op->archdata.irqs[0];
-
- up->port.dev = &op->dev;
-
- up->port.type = PORT_UNKNOWN;
- up->port.uartclk = (SU_BASE_BAUD * 16);
-
- err = 0;
- if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
- err = sunsu_kbd_ms_init(up);
- if (err) {
- of_iounmap(&op->resource[0],
- up->port.membase, up->reg_size);
- kfree(up);
- return err;
- }
- dev_set_drvdata(&op->dev, up);
-
- return 0;
- }
-
- up->port.flags |= UPF_BOOT_AUTOCONF;
-
- sunsu_autoconfig(up);
-
- err = -ENODEV;
- if (up->port.type == PORT_UNKNOWN)
- goto out_unmap;
-
- up->port.ops = &sunsu_pops;
-
- ignore_line = false;
- if (!strcmp(dp->name, "rsc-console") ||
- !strcmp(dp->name, "lom-console"))
- ignore_line = true;
-
- sunserial_console_match(SUNSU_CONSOLE(), dp,
- &sunsu_reg, up->port.line,
- ignore_line);
- err = uart_add_one_port(&sunsu_reg, &up->port);
- if (err)
- goto out_unmap;
-
- dev_set_drvdata(&op->dev, up);
-
- inst++;
-
- return 0;
-
-out_unmap:
- of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
- return err;
-}
-
-static int __devexit su_remove(struct platform_device *op)
-{
- struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
- bool kbdms = false;
-
- if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD)
- kbdms = true;
-
- if (kbdms) {
-#ifdef CONFIG_SERIO
- serio_unregister_port(&up->serio);
-#endif
- } else if (up->port.type != PORT_UNKNOWN)
- uart_remove_one_port(&sunsu_reg, &up->port);
-
- if (up->port.membase)
- of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
-
- if (kbdms)
- kfree(up);
-
- dev_set_drvdata(&op->dev, NULL);
-
- return 0;
-}
-
-static const struct of_device_id su_match[] = {
- {
- .name = "su",
- },
- {
- .name = "su_pnp",
- },
- {
- .name = "serial",
- .compatible = "su",
- },
- {
- .type = "serial",
- .compatible = "su",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, su_match);
-
-static struct of_platform_driver su_driver = {
- .driver = {
- .name = "su",
- .owner = THIS_MODULE,
- .of_match_table = su_match,
- },
- .probe = su_probe,
- .remove = __devexit_p(su_remove),
-};
-
-static int __init sunsu_init(void)
-{
- struct device_node *dp;
- int err;
- int num_uart = 0;
-
- for_each_node_by_name(dp, "su") {
- if (su_get_type(dp) == SU_PORT_PORT)
- num_uart++;
- }
- for_each_node_by_name(dp, "su_pnp") {
- if (su_get_type(dp) == SU_PORT_PORT)
- num_uart++;
- }
- for_each_node_by_name(dp, "serial") {
- if (of_device_is_compatible(dp, "su")) {
- if (su_get_type(dp) == SU_PORT_PORT)
- num_uart++;
- }
- }
- for_each_node_by_type(dp, "serial") {
- if (of_device_is_compatible(dp, "su")) {
- if (su_get_type(dp) == SU_PORT_PORT)
- num_uart++;
- }
- }
-
- if (num_uart) {
- err = sunserial_register_minors(&sunsu_reg, num_uart);
- if (err)
- return err;
- }
-
- err = of_register_platform_driver(&su_driver);
- if (err && num_uart)
- sunserial_unregister_minors(&sunsu_reg, num_uart);
-
- return err;
-}
-
-static void __exit sunsu_exit(void)
-{
- if (sunsu_reg.nr)
- sunserial_unregister_minors(&sunsu_reg, sunsu_reg.nr);
-}
-
-module_init(sunsu_init);
-module_exit(sunsu_exit);
-
-MODULE_AUTHOR("Eddie C. Dost, Peter Zaitcev, and David S. Miller");
-MODULE_DESCRIPTION("Sun SU serial port driver");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
deleted file mode 100644
index c1967ac1c07f..000000000000
--- a/drivers/serial/sunzilog.c
+++ /dev/null
@@ -1,1655 +0,0 @@
-/* sunzilog.c: Zilog serial driver for Sparc systems.
- *
- * Driver for Zilog serial chips found on Sun workstations and
- * servers. This driver could actually be made more generic.
- *
- * This is based on the old drivers/sbus/char/zs.c code. A lot
- * of code has been simply moved over directly from there but
- * much has been rewritten. Credits therefore go out to Eddie
- * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
- * work there.
- *
- * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/circ_buf.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/spinlock.h>
-#ifdef CONFIG_SERIO
-#include <linux/serio.h>
-#endif
-#include <linux/init.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-
-#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#include "suncore.h"
-#include "sunzilog.h"
-
-/* On 32-bit sparcs we need to delay after register accesses
- * to accommodate sun4 systems, but we do not need to flush writes.
- * On 64-bit sparc we only need to flush single writes to ensure
- * completion.
- */
-#ifndef CONFIG_SPARC64
-#define ZSDELAY() udelay(5)
-#define ZSDELAY_LONG() udelay(20)
-#define ZS_WSYNC(channel) do { } while (0)
-#else
-#define ZSDELAY()
-#define ZSDELAY_LONG()
-#define ZS_WSYNC(__channel) \
- readb(&((__channel)->control))
-#endif
-
-#define ZS_CLOCK 4915200 /* Zilog input clock rate. */
-#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
-
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct uart_sunzilog_port {
- struct uart_port port;
-
- /* IRQ servicing chain. */
- struct uart_sunzilog_port *next;
-
- /* Current values of Zilog write registers. */
- unsigned char curregs[NUM_ZSREGS];
-
- unsigned int flags;
-#define SUNZILOG_FLAG_CONS_KEYB 0x00000001
-#define SUNZILOG_FLAG_CONS_MOUSE 0x00000002
-#define SUNZILOG_FLAG_IS_CONS 0x00000004
-#define SUNZILOG_FLAG_IS_KGDB 0x00000008
-#define SUNZILOG_FLAG_MODEM_STATUS 0x00000010
-#define SUNZILOG_FLAG_IS_CHANNEL_A 0x00000020
-#define SUNZILOG_FLAG_REGS_HELD 0x00000040
-#define SUNZILOG_FLAG_TX_STOPPED 0x00000080
-#define SUNZILOG_FLAG_TX_ACTIVE 0x00000100
-#define SUNZILOG_FLAG_ESCC 0x00000200
-#define SUNZILOG_FLAG_ISR_HANDLER 0x00000400
-
- unsigned int cflag;
-
- unsigned char parity_mask;
- unsigned char prev_status;
-
-#ifdef CONFIG_SERIO
- struct serio serio;
- int serio_open;
-#endif
-};
-
-static void sunzilog_putchar(struct uart_port *port, int ch);
-
-#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase))
-#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
-
-#define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB)
-#define ZS_IS_MOUSE(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE)
-#define ZS_IS_CONS(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CONS)
-#define ZS_IS_KGDB(UP) ((UP)->flags & SUNZILOG_FLAG_IS_KGDB)
-#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & SUNZILOG_FLAG_MODEM_STATUS)
-#define ZS_IS_CHANNEL_A(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CHANNEL_A)
-#define ZS_REGS_HELD(UP) ((UP)->flags & SUNZILOG_FLAG_REGS_HELD)
-#define ZS_TX_STOPPED(UP) ((UP)->flags & SUNZILOG_FLAG_TX_STOPPED)
-#define ZS_TX_ACTIVE(UP) ((UP)->flags & SUNZILOG_FLAG_TX_ACTIVE)
-
-/* Reading and writing Zilog8530 registers. The delays are to make this
- * driver work on the Sun4 which needs a settling delay after each chip
- * register access, other machines handle this in hardware via auxiliary
- * flip-flops which implement the settle time we do in software.
- *
- * The port lock must be held and local IRQs must be disabled
- * when {read,write}_zsreg is invoked.
- */
-static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
- unsigned char reg)
-{
- unsigned char retval;
-
- writeb(reg, &channel->control);
- ZSDELAY();
- retval = readb(&channel->control);
- ZSDELAY();
-
- return retval;
-}
-
-static void write_zsreg(struct zilog_channel __iomem *channel,
- unsigned char reg, unsigned char value)
-{
- writeb(reg, &channel->control);
- ZSDELAY();
- writeb(value, &channel->control);
- ZSDELAY();
-}
-
-static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
-{
- int i;
-
- for (i = 0; i < 32; i++) {
- unsigned char regval;
-
- regval = readb(&channel->control);
- ZSDELAY();
- if (regval & Rx_CH_AV)
- break;
-
- regval = read_zsreg(channel, R1);
- readb(&channel->data);
- ZSDELAY();
-
- if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- writeb(ERR_RES, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
- }
- }
-}
-
-/* This function must only be called when the TX is not busy. The UART
- * port lock must be held and local interrupts disabled.
- */
-static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
-{
- int i;
- int escc;
- unsigned char r15;
-
- /* Let pending transmits finish. */
- for (i = 0; i < 1000; i++) {
- unsigned char stat = read_zsreg(channel, R1);
- if (stat & ALL_SNT)
- break;
- udelay(100);
- }
-
- writeb(ERR_RES, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- sunzilog_clear_fifo(channel);
-
- /* Disable all interrupts. */
- write_zsreg(channel, R1,
- regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
-
- /* Set parity, sync config, stop bits, and clock divisor. */
- write_zsreg(channel, R4, regs[R4]);
-
- /* Set misc. TX/RX control bits. */
- write_zsreg(channel, R10, regs[R10]);
-
- /* Set TX/RX controls sans the enable bits. */
- write_zsreg(channel, R3, regs[R3] & ~RxENAB);
- write_zsreg(channel, R5, regs[R5] & ~TxENAB);
-
- /* Synchronous mode config. */
- write_zsreg(channel, R6, regs[R6]);
- write_zsreg(channel, R7, regs[R7]);
-
- /* Don't mess with the interrupt vector (R2, unused by us) and
- * master interrupt control (R9). We make sure this is setup
- * properly at probe time then never touch it again.
- */
-
- /* Disable baud generator. */
- write_zsreg(channel, R14, regs[R14] & ~BRENAB);
-
- /* Clock mode control. */
- write_zsreg(channel, R11, regs[R11]);
-
- /* Lower and upper byte of baud rate generator divisor. */
- write_zsreg(channel, R12, regs[R12]);
- write_zsreg(channel, R13, regs[R13]);
-
- /* Now rewrite R14, with BRENAB (if set). */
- write_zsreg(channel, R14, regs[R14]);
-
- /* External status interrupt control. */
- write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN);
-
- /* ESCC Extension Register */
- r15 = read_zsreg(channel, R15);
- if (r15 & 0x01) {
- write_zsreg(channel, R7, regs[R7p]);
-
- /* External status interrupt and FIFO control. */
- write_zsreg(channel, R15, regs[R15] & ~WR7pEN);
- escc = 1;
- } else {
- /* Clear FIFO bit case it is an issue */
- regs[R15] &= ~FIFOEN;
- escc = 0;
- }
-
- /* Reset external status interrupts. */
- write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */
- write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */
-
- /* Rewrite R3/R5, this time without enables masked. */
- write_zsreg(channel, R3, regs[R3]);
- write_zsreg(channel, R5, regs[R5]);
-
- /* Rewrite R1, this time without IRQ enabled masked. */
- write_zsreg(channel, R1, regs[R1]);
-
- return escc;
-}
-
-/* Reprogram the Zilog channel HW registers with the copies found in the
- * software state struct. If the transmitter is busy, we defer this update
- * until the next TX complete interrupt. Else, we do it right now.
- *
- * The UART port lock must be held and local interrupts disabled.
- */
-static void sunzilog_maybe_update_regs(struct uart_sunzilog_port *up,
- struct zilog_channel __iomem *channel)
-{
- if (!ZS_REGS_HELD(up)) {
- if (ZS_TX_ACTIVE(up)) {
- up->flags |= SUNZILOG_FLAG_REGS_HELD;
- } else {
- __load_zsregs(channel, up->curregs);
- }
- }
-}
-
-static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up)
-{
- unsigned int cur_cflag = up->cflag;
- int brg, new_baud;
-
- up->cflag &= ~CBAUD;
- up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud);
-
- brg = BPS_TO_BRG(new_baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
- up->curregs[R12] = (brg & 0xff);
- up->curregs[R13] = (brg >> 8) & 0xff;
- sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(&up->port));
-}
-
-static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
- unsigned char ch, int is_break)
-{
- if (ZS_IS_KEYB(up)) {
- /* Stop-A is handled by drivers/char/keyboard.c now. */
-#ifdef CONFIG_SERIO
- if (up->serio_open)
- serio_interrupt(&up->serio, ch, 0);
-#endif
- } else if (ZS_IS_MOUSE(up)) {
- int ret = suncore_mouse_baud_detection(ch, is_break);
-
- switch (ret) {
- case 2:
- sunzilog_change_mouse_baud(up);
- /* fallthru */
- case 1:
- break;
-
- case 0:
-#ifdef CONFIG_SERIO
- if (up->serio_open)
- serio_interrupt(&up->serio, ch, 0);
-#endif
- break;
- };
- }
-}
-
-static struct tty_struct *
-sunzilog_receive_chars(struct uart_sunzilog_port *up,
- struct zilog_channel __iomem *channel)
-{
- struct tty_struct *tty;
- unsigned char ch, r1, flag;
-
- tty = NULL;
- if (up->port.state != NULL && /* Unopened serial console */
- up->port.state->port.tty != NULL) /* Keyboard || mouse */
- tty = up->port.state->port.tty;
-
- for (;;) {
-
- r1 = read_zsreg(channel, R1);
- if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- writeb(ERR_RES, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
- }
-
- ch = readb(&channel->control);
- ZSDELAY();
-
- /* This funny hack depends upon BRK_ABRT not interfering
- * with the other bits we care about in R1.
- */
- if (ch & BRK_ABRT)
- r1 |= BRK_ABRT;
-
- if (!(ch & Rx_CH_AV))
- break;
-
- ch = readb(&channel->data);
- ZSDELAY();
-
- ch &= up->parity_mask;
-
- if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) {
- sunzilog_kbdms_receive_chars(up, ch, 0);
- continue;
- }
-
- if (tty == NULL) {
- uart_handle_sysrq_char(&up->port, ch);
- continue;
- }
-
- /* A real serial line, record the character and status. */
- flag = TTY_NORMAL;
- up->port.icount.rx++;
- if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
- if (r1 & BRK_ABRT) {
- r1 &= ~(PAR_ERR | CRC_ERR);
- up->port.icount.brk++;
- if (uart_handle_break(&up->port))
- continue;
- }
- else if (r1 & PAR_ERR)
- up->port.icount.parity++;
- else if (r1 & CRC_ERR)
- up->port.icount.frame++;
- if (r1 & Rx_OVR)
- up->port.icount.overrun++;
- r1 &= up->port.read_status_mask;
- if (r1 & BRK_ABRT)
- flag = TTY_BREAK;
- else if (r1 & PAR_ERR)
- flag = TTY_PARITY;
- else if (r1 & CRC_ERR)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch))
- continue;
-
- if (up->port.ignore_status_mask == 0xff ||
- (r1 & up->port.ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if (r1 & Rx_OVR)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
-
- return tty;
-}
-
-static void sunzilog_status_handle(struct uart_sunzilog_port *up,
- struct zilog_channel __iomem *channel)
-{
- unsigned char status;
-
- status = readb(&channel->control);
- ZSDELAY();
-
- writeb(RES_EXT_INT, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- if (status & BRK_ABRT) {
- if (ZS_IS_MOUSE(up))
- sunzilog_kbdms_receive_chars(up, 0, 1);
- if (ZS_IS_CONS(up)) {
- /* Wait for BREAK to deassert to avoid potentially
- * confusing the PROM.
- */
- while (1) {
- status = readb(&channel->control);
- ZSDELAY();
- if (!(status & BRK_ABRT))
- break;
- }
- sun_do_break();
- return;
- }
- }
-
- if (ZS_WANTS_MODEM_STATUS(up)) {
- if (status & SYNC)
- up->port.icount.dsr++;
-
- /* The Zilog just gives us an interrupt when DCD/CTS/etc. change.
- * But it does not tell us which bit has changed, we have to keep
- * track of this ourselves.
- */
- if ((status ^ up->prev_status) ^ DCD)
- uart_handle_dcd_change(&up->port,
- (status & DCD));
- if ((status ^ up->prev_status) ^ CTS)
- uart_handle_cts_change(&up->port,
- (status & CTS));
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
- }
-
- up->prev_status = status;
-}
-
-static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
- struct zilog_channel __iomem *channel)
-{
- struct circ_buf *xmit;
-
- if (ZS_IS_CONS(up)) {
- unsigned char status = readb(&channel->control);
- ZSDELAY();
-
- /* TX still busy? Just wait for the next TX done interrupt.
- *
- * It can occur because of how we do serial console writes. It would
- * be nice to transmit console writes just like we normally would for
- * a TTY line. (ie. buffered and TX interrupt driven). That is not
- * easy because console writes cannot sleep. One solution might be
- * to poll on enough port->xmit space becomming free. -DaveM
- */
- if (!(status & Tx_BUF_EMP))
- return;
- }
-
- up->flags &= ~SUNZILOG_FLAG_TX_ACTIVE;
-
- if (ZS_REGS_HELD(up)) {
- __load_zsregs(channel, up->curregs);
- up->flags &= ~SUNZILOG_FLAG_REGS_HELD;
- }
-
- if (ZS_TX_STOPPED(up)) {
- up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
- goto ack_tx_int;
- }
-
- if (up->port.x_char) {
- up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
- writeb(up->port.x_char, &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
-
- if (up->port.state == NULL)
- goto ack_tx_int;
- xmit = &up->port.state->xmit;
- if (uart_circ_empty(xmit))
- goto ack_tx_int;
-
- if (uart_tx_stopped(&up->port))
- goto ack_tx_int;
-
- up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
- writeb(xmit->buf[xmit->tail], &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- return;
-
-ack_tx_int:
- writeb(RES_Tx_P, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-}
-
-static irqreturn_t sunzilog_interrupt(int irq, void *dev_id)
-{
- struct uart_sunzilog_port *up = dev_id;
-
- while (up) {
- struct zilog_channel __iomem *channel
- = ZILOG_CHANNEL_FROM_PORT(&up->port);
- struct tty_struct *tty;
- unsigned char r3;
-
- spin_lock(&up->port.lock);
- r3 = read_zsreg(channel, R3);
-
- /* Channel A */
- tty = NULL;
- if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
- writeb(RES_H_IUS, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- if (r3 & CHARxIP)
- tty = sunzilog_receive_chars(up, channel);
- if (r3 & CHAEXT)
- sunzilog_status_handle(up, channel);
- if (r3 & CHATxIP)
- sunzilog_transmit_chars(up, channel);
- }
- spin_unlock(&up->port.lock);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- /* Channel B */
- up = up->next;
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
-
- spin_lock(&up->port.lock);
- tty = NULL;
- if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
- writeb(RES_H_IUS, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- if (r3 & CHBRxIP)
- tty = sunzilog_receive_chars(up, channel);
- if (r3 & CHBEXT)
- sunzilog_status_handle(up, channel);
- if (r3 & CHBTxIP)
- sunzilog_transmit_chars(up, channel);
- }
- spin_unlock(&up->port.lock);
-
- if (tty)
- tty_flip_buffer_push(tty);
-
- up = up->next;
- }
-
- return IRQ_HANDLED;
-}
-
-/* A convenient way to quickly get R0 status. The caller must _not_ hold the
- * port lock, it is acquired here.
- */
-static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *port)
-{
- struct zilog_channel __iomem *channel;
- unsigned char status;
-
- channel = ZILOG_CHANNEL_FROM_PORT(port);
- status = readb(&channel->control);
- ZSDELAY();
-
- return status;
-}
-
-/* The port lock is not held. */
-static unsigned int sunzilog_tx_empty(struct uart_port *port)
-{
- unsigned long flags;
- unsigned char status;
- unsigned int ret;
-
- spin_lock_irqsave(&port->lock, flags);
-
- status = sunzilog_read_channel_status(port);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (status & Tx_BUF_EMP)
- ret = TIOCSER_TEMT;
- else
- ret = 0;
-
- return ret;
-}
-
-/* The port lock is held and interrupts are disabled. */
-static unsigned int sunzilog_get_mctrl(struct uart_port *port)
-{
- unsigned char status;
- unsigned int ret;
-
- status = sunzilog_read_channel_status(port);
-
- ret = 0;
- if (status & DCD)
- ret |= TIOCM_CAR;
- if (status & SYNC)
- ret |= TIOCM_DSR;
- if (status & CTS)
- ret |= TIOCM_CTS;
-
- return ret;
-}
-
-/* The port lock is held and interrupts are disabled. */
-static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char set_bits, clear_bits;
-
- set_bits = clear_bits = 0;
-
- if (mctrl & TIOCM_RTS)
- set_bits |= RTS;
- else
- clear_bits |= RTS;
- if (mctrl & TIOCM_DTR)
- set_bits |= DTR;
- else
- clear_bits |= DTR;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- up->curregs[R5] |= set_bits;
- up->curregs[R5] &= ~clear_bits;
- write_zsreg(channel, R5, up->curregs[R5]);
-}
-
-/* The port lock is held and interrupts are disabled. */
-static void sunzilog_stop_tx(struct uart_port *port)
-{
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
-
- up->flags |= SUNZILOG_FLAG_TX_STOPPED;
-}
-
-/* The port lock is held and interrupts are disabled. */
-static void sunzilog_start_tx(struct uart_port *port)
-{
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char status;
-
- up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
- up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
-
- status = readb(&channel->control);
- ZSDELAY();
-
- /* TX busy? Just wait for the TX done interrupt. */
- if (!(status & Tx_BUF_EMP))
- return;
-
- /* Send the first character to jump-start the TX done
- * IRQ sending engine.
- */
- if (port->x_char) {
- writeb(port->x_char, &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- port->icount.tx++;
- port->x_char = 0;
- } else {
- struct circ_buf *xmit = &port->state->xmit;
-
- writeb(xmit->buf[xmit->tail], &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
- }
-}
-
-/* The port lock is held. */
-static void sunzilog_stop_rx(struct uart_port *port)
-{
- struct uart_sunzilog_port *up = UART_ZILOG(port);
- struct zilog_channel __iomem *channel;
-
- if (ZS_IS_CONS(up))
- return;
-
- channel = ZILOG_CHANNEL_FROM_PORT(port);
-
- /* Disable all RX interrupts. */
- up->curregs[R1] &= ~RxINT_MASK;
- sunzilog_maybe_update_regs(up, channel);
-}
-
-/* The port lock is held. */
-static void sunzilog_enable_ms(struct uart_port *port)
-{
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char new_reg;
-
- new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
- if (new_reg != up->curregs[R15]) {
- up->curregs[R15] = new_reg;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN);
- }
-}
-
-/* The port lock is not held. */
-static void sunzilog_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
- unsigned char set_bits, clear_bits, new_reg;
- unsigned long flags;
-
- set_bits = clear_bits = 0;
-
- if (break_state)
- set_bits |= SND_BRK;
- else
- clear_bits |= SND_BRK;
-
- spin_lock_irqsave(&port->lock, flags);
-
- new_reg = (up->curregs[R5] | set_bits) & ~clear_bits;
- if (new_reg != up->curregs[R5]) {
- up->curregs[R5] = new_reg;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- write_zsreg(channel, R5, up->curregs[R5]);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void __sunzilog_startup(struct uart_sunzilog_port *up)
-{
- struct zilog_channel __iomem *channel;
-
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- up->prev_status = readb(&channel->control);
-
- /* Enable receiver and transmitter. */
- up->curregs[R3] |= RxENAB;
- up->curregs[R5] |= TxENAB;
-
- up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- sunzilog_maybe_update_regs(up, channel);
-}
-
-static int sunzilog_startup(struct uart_port *port)
-{
- struct uart_sunzilog_port *up = UART_ZILOG(port);
- unsigned long flags;
-
- if (ZS_IS_CONS(up))
- return 0;
-
- spin_lock_irqsave(&port->lock, flags);
- __sunzilog_startup(up);
- spin_unlock_irqrestore(&port->lock, flags);
- return 0;
-}
-
-/*
- * The test for ZS_IS_CONS is explained by the following e-mail:
- *****
- * From: Russell King <rmk@arm.linux.org.uk>
- * Date: Sun, 8 Dec 2002 10:18:38 +0000
- *
- * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote:
- * > I boot my 2.5 boxes using "console=ttyS0,9600" argument,
- * > and I noticed that something is not right with reference
- * > counting in this case. It seems that when the console
- * > is open by kernel initially, this is not accounted
- * > as an open, and uart_startup is not called.
- *
- * That is correct. We are unable to call uart_startup when the serial
- * console is initialised because it may need to allocate memory (as
- * request_irq does) and the memory allocators may not have been
- * initialised.
- *
- * 1. initialise the port into a state where it can send characters in the
- * console write method.
- *
- * 2. don't do the actual hardware shutdown in your shutdown() method (but
- * do the normal software shutdown - ie, free irqs etc)
- *****
- */
-static void sunzilog_shutdown(struct uart_port *port)
-{
- struct uart_sunzilog_port *up = UART_ZILOG(port);
- struct zilog_channel __iomem *channel;
- unsigned long flags;
-
- if (ZS_IS_CONS(up))
- return;
-
- spin_lock_irqsave(&port->lock, flags);
-
- channel = ZILOG_CHANNEL_FROM_PORT(port);
-
- /* Disable receiver and transmitter. */
- up->curregs[R3] &= ~RxENAB;
- up->curregs[R5] &= ~TxENAB;
-
- /* Disable all interrupts and BRK assertion. */
- up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
- up->curregs[R5] &= ~SND_BRK;
- sunzilog_maybe_update_regs(up, channel);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/* Shared by TTY driver and serial console setup. The port lock is held
- * and local interrupts are disabled.
- */
-static void
-sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
- unsigned int iflag, int brg)
-{
-
- up->curregs[R10] = NRZ;
- up->curregs[R11] = TCBR | RCBR;
-
- /* Program BAUD and clock source. */
- up->curregs[R4] &= ~XCLK_MASK;
- up->curregs[R4] |= X16CLK;
- up->curregs[R12] = brg & 0xff;
- up->curregs[R13] = (brg >> 8) & 0xff;
- up->curregs[R14] = BRSRC | BRENAB;
-
- /* Character size, stop bits, and parity. */
- up->curregs[R3] &= ~RxN_MASK;
- up->curregs[R5] &= ~TxN_MASK;
- switch (cflag & CSIZE) {
- case CS5:
- up->curregs[R3] |= Rx5;
- up->curregs[R5] |= Tx5;
- up->parity_mask = 0x1f;
- break;
- case CS6:
- up->curregs[R3] |= Rx6;
- up->curregs[R5] |= Tx6;
- up->parity_mask = 0x3f;
- break;
- case CS7:
- up->curregs[R3] |= Rx7;
- up->curregs[R5] |= Tx7;
- up->parity_mask = 0x7f;
- break;
- case CS8:
- default:
- up->curregs[R3] |= Rx8;
- up->curregs[R5] |= Tx8;
- up->parity_mask = 0xff;
- break;
- };
- up->curregs[R4] &= ~0x0c;
- if (cflag & CSTOPB)
- up->curregs[R4] |= SB2;
- else
- up->curregs[R4] |= SB1;
- if (cflag & PARENB)
- up->curregs[R4] |= PAR_ENAB;
- else
- up->curregs[R4] &= ~PAR_ENAB;
- if (!(cflag & PARODD))
- up->curregs[R4] |= PAR_EVEN;
- else
- up->curregs[R4] &= ~PAR_EVEN;
-
- up->port.read_status_mask = Rx_OVR;
- if (iflag & INPCK)
- up->port.read_status_mask |= CRC_ERR | PAR_ERR;
- if (iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= BRK_ABRT;
-
- up->port.ignore_status_mask = 0;
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= CRC_ERR | PAR_ERR;
- if (iflag & IGNBRK) {
- up->port.ignore_status_mask |= BRK_ABRT;
- if (iflag & IGNPAR)
- up->port.ignore_status_mask |= Rx_OVR;
- }
-
- if ((cflag & CREAD) == 0)
- up->port.ignore_status_mask = 0xff;
-}
-
-/* The port lock is not held. */
-static void
-sunzilog_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- unsigned long flags;
- int baud, brg;
-
- baud = uart_get_baud_rate(port, termios, old, 1200, 76800);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
-
- sunzilog_convert_to_zs(up, termios->c_cflag, termios->c_iflag, brg);
-
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->flags |= SUNZILOG_FLAG_MODEM_STATUS;
- else
- up->flags &= ~SUNZILOG_FLAG_MODEM_STATUS;
-
- up->cflag = termios->c_cflag;
-
- sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static const char *sunzilog_type(struct uart_port *port)
-{
- struct uart_sunzilog_port *up = UART_ZILOG(port);
-
- return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs";
-}
-
-/* We do not request/release mappings of the registers here, this
- * happens at early serial probe time.
- */
-static void sunzilog_release_port(struct uart_port *port)
-{
-}
-
-static int sunzilog_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-/* These do not need to do anything interesting either. */
-static void sunzilog_config_port(struct uart_port *port, int flags)
-{
-}
-
-/* We do not support letting the user mess with the divisor, IRQ, etc. */
-static int sunzilog_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- return -EINVAL;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-static int sunzilog_get_poll_char(struct uart_port *port)
-{
- unsigned char ch, r1;
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel __iomem *channel
- = ZILOG_CHANNEL_FROM_PORT(&up->port);
-
-
- r1 = read_zsreg(channel, R1);
- if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- writeb(ERR_RES, &channel->control);
- ZSDELAY();
- ZS_WSYNC(channel);
- }
-
- ch = readb(&channel->control);
- ZSDELAY();
-
- /* This funny hack depends upon BRK_ABRT not interfering
- * with the other bits we care about in R1.
- */
- if (ch & BRK_ABRT)
- r1 |= BRK_ABRT;
-
- if (!(ch & Rx_CH_AV))
- return NO_POLL_CHAR;
-
- ch = readb(&channel->data);
- ZSDELAY();
-
- ch &= up->parity_mask;
- return ch;
-}
-
-static void sunzilog_put_poll_char(struct uart_port *port,
- unsigned char ch)
-{
- struct uart_sunzilog_port *up = (struct uart_sunzilog_port *)port;
-
- sunzilog_putchar(&up->port, ch);
-}
-#endif /* CONFIG_CONSOLE_POLL */
-
-static struct uart_ops sunzilog_pops = {
- .tx_empty = sunzilog_tx_empty,
- .set_mctrl = sunzilog_set_mctrl,
- .get_mctrl = sunzilog_get_mctrl,
- .stop_tx = sunzilog_stop_tx,
- .start_tx = sunzilog_start_tx,
- .stop_rx = sunzilog_stop_rx,
- .enable_ms = sunzilog_enable_ms,
- .break_ctl = sunzilog_break_ctl,
- .startup = sunzilog_startup,
- .shutdown = sunzilog_shutdown,
- .set_termios = sunzilog_set_termios,
- .type = sunzilog_type,
- .release_port = sunzilog_release_port,
- .request_port = sunzilog_request_port,
- .config_port = sunzilog_config_port,
- .verify_port = sunzilog_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = sunzilog_get_poll_char,
- .poll_put_char = sunzilog_put_poll_char,
-#endif
-};
-
-static int uart_chip_count;
-static struct uart_sunzilog_port *sunzilog_port_table;
-static struct zilog_layout __iomem **sunzilog_chip_regs;
-
-static struct uart_sunzilog_port *sunzilog_irq_chain;
-
-static struct uart_driver sunzilog_reg = {
- .owner = THIS_MODULE,
- .driver_name = "sunzilog",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
-};
-
-static int __init sunzilog_alloc_tables(int num_sunzilog)
-{
- struct uart_sunzilog_port *up;
- unsigned long size;
- int num_channels = num_sunzilog * 2;
- int i;
-
- size = num_channels * sizeof(struct uart_sunzilog_port);
- sunzilog_port_table = kzalloc(size, GFP_KERNEL);
- if (!sunzilog_port_table)
- return -ENOMEM;
-
- for (i = 0; i < num_channels; i++) {
- up = &sunzilog_port_table[i];
-
- spin_lock_init(&up->port.lock);
-
- if (i == 0)
- sunzilog_irq_chain = up;
-
- if (i < num_channels - 1)
- up->next = up + 1;
- else
- up->next = NULL;
- }
-
- size = num_sunzilog * sizeof(struct zilog_layout __iomem *);
- sunzilog_chip_regs = kzalloc(size, GFP_KERNEL);
- if (!sunzilog_chip_regs) {
- kfree(sunzilog_port_table);
- sunzilog_irq_chain = NULL;
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void sunzilog_free_tables(void)
-{
- kfree(sunzilog_port_table);
- sunzilog_irq_chain = NULL;
- kfree(sunzilog_chip_regs);
-}
-
-#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
-
-static void sunzilog_putchar(struct uart_port *port, int ch)
-{
- struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
- int loops = ZS_PUT_CHAR_MAX_DELAY;
-
- /* This is a timed polling loop so do not switch the explicit
- * udelay with ZSDELAY as that is a NOP on some platforms. -DaveM
- */
- do {
- unsigned char val = readb(&channel->control);
- if (val & Tx_BUF_EMP) {
- ZSDELAY();
- break;
- }
- udelay(5);
- } while (--loops);
-
- writeb(ch, &channel->data);
- ZSDELAY();
- ZS_WSYNC(channel);
-}
-
-#ifdef CONFIG_SERIO
-
-static DEFINE_SPINLOCK(sunzilog_serio_lock);
-
-static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
-{
- struct uart_sunzilog_port *up = serio->port_data;
- unsigned long flags;
-
- spin_lock_irqsave(&sunzilog_serio_lock, flags);
-
- sunzilog_putchar(&up->port, ch);
-
- spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
-
- return 0;
-}
-
-static int sunzilog_serio_open(struct serio *serio)
-{
- struct uart_sunzilog_port *up = serio->port_data;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&sunzilog_serio_lock, flags);
- if (!up->serio_open) {
- up->serio_open = 1;
- ret = 0;
- } else
- ret = -EBUSY;
- spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
-
- return ret;
-}
-
-static void sunzilog_serio_close(struct serio *serio)
-{
- struct uart_sunzilog_port *up = serio->port_data;
- unsigned long flags;
-
- spin_lock_irqsave(&sunzilog_serio_lock, flags);
- up->serio_open = 0;
- spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
-}
-
-#endif /* CONFIG_SERIO */
-
-#ifdef CONFIG_SERIAL_SUNZILOG_CONSOLE
-static void
-sunzilog_console_write(struct console *con, const char *s, unsigned int count)
-{
- struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
- unsigned long flags;
- int locked = 1;
-
- local_irq_save(flags);
- if (up->port.sysrq) {
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&up->port.lock);
- } else
- spin_lock(&up->port.lock);
-
- uart_console_write(&up->port, s, count, sunzilog_putchar);
- udelay(2);
-
- if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
-}
-
-static int __init sunzilog_console_setup(struct console *con, char *options)
-{
- struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
- unsigned long flags;
- int baud, brg;
-
- if (up->port.type != PORT_SUNZILOG)
- return -1;
-
- printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n",
- (sunzilog_reg.minor - 64) + con->index, con->index);
-
- /* Get firmware console settings. */
- sunserial_console_termios(con, up->port.dev->of_node);
-
- /* Firmware console speed is limited to 150-->38400 baud so
- * this hackish cflag thing is OK.
- */
- switch (con->cflag & CBAUD) {
- case B150: baud = 150; break;
- case B300: baud = 300; break;
- case B600: baud = 600; break;
- case B1200: baud = 1200; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- default: case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- };
-
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->curregs[R15] |= BRKIE;
- sunzilog_convert_to_zs(up, con->cflag, 0, brg);
-
- sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
- __sunzilog_startup(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return 0;
-}
-
-static struct console sunzilog_console_ops = {
- .name = "ttyS",
- .write = sunzilog_console_write,
- .device = uart_console_device,
- .setup = sunzilog_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &sunzilog_reg,
-};
-
-static inline struct console *SUNZILOG_CONSOLE(void)
-{
- return &sunzilog_console_ops;
-}
-
-#else
-#define SUNZILOG_CONSOLE() (NULL)
-#endif
-
-static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
-{
- int baud, brg;
-
- if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
- up->cflag = B1200 | CS8 | CLOCAL | CREAD;
- baud = 1200;
- } else {
- up->cflag = B4800 | CS8 | CLOCAL | CREAD;
- baud = 4800;
- }
-
- up->curregs[R15] |= BRKIE;
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
- sunzilog_convert_to_zs(up, up->cflag, 0, brg);
- sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
- __sunzilog_startup(up);
-}
-
-#ifdef CONFIG_SERIO
-static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
-{
- struct serio *serio = &up->serio;
-
- serio->port_data = up;
-
- serio->id.type = SERIO_RS232;
- if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
- serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "zskbd", sizeof(serio->name));
- } else {
- serio->id.proto = SERIO_SUN;
- serio->id.extra = 1;
- strlcpy(serio->name, "zsms", sizeof(serio->name));
- }
- strlcpy(serio->phys,
- ((up->flags & SUNZILOG_FLAG_CONS_KEYB) ?
- "zs/serio0" : "zs/serio1"),
- sizeof(serio->phys));
-
- serio->write = sunzilog_serio_write;
- serio->open = sunzilog_serio_open;
- serio->close = sunzilog_serio_close;
- serio->dev.parent = up->port.dev;
-
- serio_register_port(serio);
-}
-#endif
-
-static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
-{
- struct zilog_channel __iomem *channel;
- unsigned long flags;
- int baud, brg;
-
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (ZS_IS_CHANNEL_A(up)) {
- write_zsreg(channel, R9, FHWRES);
- ZSDELAY_LONG();
- (void) read_zsreg(channel, R0);
- }
-
- if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
- SUNZILOG_FLAG_CONS_MOUSE)) {
- up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
- up->curregs[R3] = RxENAB | Rx8;
- up->curregs[R5] = TxENAB | Tx8;
- up->curregs[R6] = 0x00; /* SDLC Address */
- up->curregs[R7] = 0x7E; /* SDLC Flag */
- up->curregs[R9] = NV;
- up->curregs[R7p] = 0x00;
- sunzilog_init_kbdms(up);
- /* Only enable interrupts if an ISR handler available */
- if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
- up->curregs[R9] |= MIE;
- write_zsreg(channel, R9, up->curregs[R9]);
- } else {
- /* Normal serial TTY. */
- up->parity_mask = 0xff;
- up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
- up->curregs[R3] = RxENAB | Rx8;
- up->curregs[R5] = TxENAB | Tx8;
- up->curregs[R6] = 0x00; /* SDLC Address */
- up->curregs[R7] = 0x7E; /* SDLC Flag */
- up->curregs[R9] = NV;
- up->curregs[R10] = NRZ;
- up->curregs[R11] = TCBR | RCBR;
- baud = 9600;
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
- up->curregs[R12] = (brg & 0xff);
- up->curregs[R13] = (brg >> 8) & 0xff;
- up->curregs[R14] = BRSRC | BRENAB;
- up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */
- up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL;
- if (__load_zsregs(channel, up->curregs)) {
- up->flags |= SUNZILOG_FLAG_ESCC;
- }
- /* Only enable interrupts if an ISR handler available */
- if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
- up->curregs[R9] |= MIE;
- write_zsreg(channel, R9, up->curregs[R9]);
- }
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
-#ifdef CONFIG_SERIO
- if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
- SUNZILOG_FLAG_CONS_MOUSE))
- sunzilog_register_serio(up);
-#endif
-}
-
-static int zilog_irq = -1;
-
-static int __devinit zs_probe(struct platform_device *op, const struct of_device_id *match)
-{
- static int kbm_inst, uart_inst;
- int inst;
- struct uart_sunzilog_port *up;
- struct zilog_layout __iomem *rp;
- int keyboard_mouse = 0;
- int err;
-
- if (of_find_property(op->dev.of_node, "keyboard", NULL))
- keyboard_mouse = 1;
-
- /* uarts must come before keyboards/mice */
- if (keyboard_mouse)
- inst = uart_chip_count + kbm_inst;
- else
- inst = uart_inst;
-
- sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
- sizeof(struct zilog_layout),
- "zs");
- if (!sunzilog_chip_regs[inst])
- return -ENOMEM;
-
- rp = sunzilog_chip_regs[inst];
-
- if (zilog_irq == -1)
- zilog_irq = op->archdata.irqs[0];
-
- up = &sunzilog_port_table[inst * 2];
-
- /* Channel A */
- up[0].port.mapbase = op->resource[0].start + 0x00;
- up[0].port.membase = (void __iomem *) &rp->channelA;
- up[0].port.iotype = UPIO_MEM;
- up[0].port.irq = op->archdata.irqs[0];
- up[0].port.uartclk = ZS_CLOCK;
- up[0].port.fifosize = 1;
- up[0].port.ops = &sunzilog_pops;
- up[0].port.type = PORT_SUNZILOG;
- up[0].port.flags = 0;
- up[0].port.line = (inst * 2) + 0;
- up[0].port.dev = &op->dev;
- up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
- if (keyboard_mouse)
- up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
- sunzilog_init_hw(&up[0]);
-
- /* Channel B */
- up[1].port.mapbase = op->resource[0].start + 0x04;
- up[1].port.membase = (void __iomem *) &rp->channelB;
- up[1].port.iotype = UPIO_MEM;
- up[1].port.irq = op->archdata.irqs[0];
- up[1].port.uartclk = ZS_CLOCK;
- up[1].port.fifosize = 1;
- up[1].port.ops = &sunzilog_pops;
- up[1].port.type = PORT_SUNZILOG;
- up[1].port.flags = 0;
- up[1].port.line = (inst * 2) + 1;
- up[1].port.dev = &op->dev;
- up[1].flags |= 0;
- if (keyboard_mouse)
- up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
- sunzilog_init_hw(&up[1]);
-
- if (!keyboard_mouse) {
- if (sunserial_console_match(SUNZILOG_CONSOLE(), op->dev.of_node,
- &sunzilog_reg, up[0].port.line,
- false))
- up->flags |= SUNZILOG_FLAG_IS_CONS;
- err = uart_add_one_port(&sunzilog_reg, &up[0].port);
- if (err) {
- of_iounmap(&op->resource[0],
- rp, sizeof(struct zilog_layout));
- return err;
- }
- if (sunserial_console_match(SUNZILOG_CONSOLE(), op->dev.of_node,
- &sunzilog_reg, up[1].port.line,
- false))
- up->flags |= SUNZILOG_FLAG_IS_CONS;
- err = uart_add_one_port(&sunzilog_reg, &up[1].port);
- if (err) {
- uart_remove_one_port(&sunzilog_reg, &up[0].port);
- of_iounmap(&op->resource[0],
- rp, sizeof(struct zilog_layout));
- return err;
- }
- uart_inst++;
- } else {
- printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) "
- "is a %s\n",
- dev_name(&op->dev),
- (unsigned long long) up[0].port.mapbase,
- op->archdata.irqs[0], sunzilog_type(&up[0].port));
- printk(KERN_INFO "%s: Mouse at MMIO 0x%llx (irq = %d) "
- "is a %s\n",
- dev_name(&op->dev),
- (unsigned long long) up[1].port.mapbase,
- op->archdata.irqs[0], sunzilog_type(&up[1].port));
- kbm_inst++;
- }
-
- dev_set_drvdata(&op->dev, &up[0]);
-
- return 0;
-}
-
-static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
-{
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
-#ifdef CONFIG_SERIO
- serio_unregister_port(&up->serio);
-#endif
- } else
- uart_remove_one_port(&sunzilog_reg, &up->port);
-}
-
-static int __devexit zs_remove(struct platform_device *op)
-{
- struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev);
- struct zilog_layout __iomem *regs;
-
- zs_remove_one(&up[0]);
- zs_remove_one(&up[1]);
-
- regs = sunzilog_chip_regs[up[0].port.line / 2];
- of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout));
-
- dev_set_drvdata(&op->dev, NULL);
-
- return 0;
-}
-
-static const struct of_device_id zs_match[] = {
- {
- .name = "zs",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, zs_match);
-
-static struct of_platform_driver zs_driver = {
- .driver = {
- .name = "zs",
- .owner = THIS_MODULE,
- .of_match_table = zs_match,
- },
- .probe = zs_probe,
- .remove = __devexit_p(zs_remove),
-};
-
-static int __init sunzilog_init(void)
-{
- struct device_node *dp;
- int err;
- int num_keybms = 0;
- int num_sunzilog = 0;
-
- for_each_node_by_name(dp, "zs") {
- num_sunzilog++;
- if (of_find_property(dp, "keyboard", NULL))
- num_keybms++;
- }
-
- if (num_sunzilog) {
- err = sunzilog_alloc_tables(num_sunzilog);
- if (err)
- goto out;
-
- uart_chip_count = num_sunzilog - num_keybms;
-
- err = sunserial_register_minors(&sunzilog_reg,
- uart_chip_count * 2);
- if (err)
- goto out_free_tables;
- }
-
- err = of_register_platform_driver(&zs_driver);
- if (err)
- goto out_unregister_uart;
-
- if (zilog_irq != -1) {
- struct uart_sunzilog_port *up = sunzilog_irq_chain;
- err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
- "zs", sunzilog_irq_chain);
- if (err)
- goto out_unregister_driver;
-
- /* Enable Interrupts */
- while (up) {
- struct zilog_channel __iomem *channel;
-
- /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- up->flags |= SUNZILOG_FLAG_ISR_HANDLER;
- up->curregs[R9] |= MIE;
- write_zsreg(channel, R9, up->curregs[R9]);
- up = up->next;
- }
- }
-
-out:
- return err;
-
-out_unregister_driver:
- of_unregister_platform_driver(&zs_driver);
-
-out_unregister_uart:
- if (num_sunzilog) {
- sunserial_unregister_minors(&sunzilog_reg, num_sunzilog);
- sunzilog_reg.cons = NULL;
- }
-
-out_free_tables:
- sunzilog_free_tables();
- goto out;
-}
-
-static void __exit sunzilog_exit(void)
-{
- of_unregister_platform_driver(&zs_driver);
-
- if (zilog_irq != -1) {
- struct uart_sunzilog_port *up = sunzilog_irq_chain;
-
- /* Disable Interrupts */
- while (up) {
- struct zilog_channel __iomem *channel;
-
- /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER;
- up->curregs[R9] &= ~MIE;
- write_zsreg(channel, R9, up->curregs[R9]);
- up = up->next;
- }
-
- free_irq(zilog_irq, sunzilog_irq_chain);
- zilog_irq = -1;
- }
-
- if (sunzilog_reg.nr) {
- sunserial_unregister_minors(&sunzilog_reg, sunzilog_reg.nr);
- sunzilog_free_tables();
- }
-}
-
-module_init(sunzilog_init);
-module_exit(sunzilog_exit);
-
-MODULE_AUTHOR("David S. Miller");
-MODULE_DESCRIPTION("Sun Zilog serial port driver");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunzilog.h b/drivers/serial/sunzilog.h
deleted file mode 100644
index 5dec7b47cc38..000000000000
--- a/drivers/serial/sunzilog.h
+++ /dev/null
@@ -1,289 +0,0 @@
-#ifndef _SUNZILOG_H
-#define _SUNZILOG_H
-
-struct zilog_channel {
- volatile unsigned char control;
- volatile unsigned char __pad1;
- volatile unsigned char data;
- volatile unsigned char __pad2;
-};
-
-struct zilog_layout {
- struct zilog_channel channelB;
- struct zilog_channel channelA;
-};
-
-#define NUM_ZSREGS 17
-#define R7p 16 /* Written as R7 with P15 bit 0 set */
-
-/* Conversion routines to/from brg time constants from/to bits
- * per second.
- */
-#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
-#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
-
-/* The Zilog register set */
-
-#define FLAG 0x7e
-
-/* Write Register 0 */
-#define R0 0 /* Register selects */
-#define R1 1
-#define R2 2
-#define R3 3
-#define R4 4
-#define R5 5
-#define R6 6
-#define R7 7
-#define R8 8
-#define R9 9
-#define R10 10
-#define R11 11
-#define R12 12
-#define R13 13
-#define R14 14
-#define R15 15
-
-#define NULLCODE 0 /* Null Code */
-#define POINT_HIGH 0x8 /* Select upper half of registers */
-#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
-#define SEND_ABORT 0x18 /* HDLC Abort */
-#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
-#define RES_Tx_P 0x28 /* Reset TxINT Pending */
-#define ERR_RES 0x30 /* Error Reset */
-#define RES_H_IUS 0x38 /* Reset highest IUS */
-
-#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
-#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
-#define RES_EOM_L 0xC0 /* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
-#define TxINT_ENAB 0x2 /* Tx Int Enable */
-#define PAR_SPEC 0x4 /* Parity is special condition */
-
-#define RxINT_DISAB 0 /* Rx Int Disable */
-#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
-#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
-#define INT_ERR_Rx 0x18 /* Int on error only */
-#define RxINT_MASK 0x18
-
-#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
-#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
-#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
-
-/* Write Register #2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define RxENAB 0x1 /* Rx Enable */
-#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
-#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
-#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
-#define ENT_HM 0x10 /* Enter Hunt Mode */
-#define AUTO_ENAB 0x20 /* Auto Enables */
-#define Rx5 0x0 /* Rx 5 Bits/Character */
-#define Rx7 0x40 /* Rx 7 Bits/Character */
-#define Rx6 0x80 /* Rx 6 Bits/Character */
-#define Rx8 0xc0 /* Rx 8 Bits/Character */
-#define RxN_MASK 0xc0
-
-/* Write Register 4 */
-
-#define PAR_ENAB 0x1 /* Parity Enable */
-#define PAR_EVEN 0x2 /* Parity Even/Odd* */
-
-#define SYNC_ENAB 0 /* Sync Modes Enable */
-#define SB1 0x4 /* 1 stop bit/char */
-#define SB15 0x8 /* 1.5 stop bits/char */
-#define SB2 0xc /* 2 stop bits/char */
-
-#define MONSYNC 0 /* 8 Bit Sync character */
-#define BISYNC 0x10 /* 16 bit sync character */
-#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
-#define EXTSYNC 0x30 /* External Sync Mode */
-
-#define X1CLK 0x0 /* x1 clock mode */
-#define X16CLK 0x40 /* x16 clock mode */
-#define X32CLK 0x80 /* x32 clock mode */
-#define X64CLK 0xC0 /* x64 clock mode */
-#define XCLK_MASK 0xC0
-
-/* Write Register 5 */
-
-#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
-#define RTS 0x2 /* RTS */
-#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
-#define TxENAB 0x8 /* Tx Enable */
-#define SND_BRK 0x10 /* Send Break */
-#define Tx5 0x0 /* Tx 5 bits (or less)/character */
-#define Tx7 0x20 /* Tx 7 bits/character */
-#define Tx6 0x40 /* Tx 6 bits/character */
-#define Tx8 0x60 /* Tx 8 bits/character */
-#define TxN_MASK 0x60
-#define DTR 0x80 /* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 7' (ESCC Only) */
-#define AUTO_TxFLAG 1 /* Automatic Tx SDLC Flag */
-#define AUTO_EOM_RST 2 /* Automatic EOM Reset */
-#define AUTOnRTS 4 /* Automatic /RTS pin deactivation */
-#define RxFIFO_LVL 8 /* Receive FIFO interrupt level */
-#define nDTRnREQ 0x10 /* /DTR/REQ timing */
-#define TxFIFO_LVL 0x20 /* Transmit FIFO interrupt level */
-#define EXT_RD_EN 0x40 /* Extended read register enable */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define VIS 1 /* Vector Includes Status */
-#define NV 2 /* No Vector */
-#define DLC 4 /* Disable Lower Chain */
-#define MIE 8 /* Master Interrupt Enable */
-#define STATHI 0x10 /* Status high */
-#define SWIACK 0x20 /* Software Interrupt Ack (not on NMOS) */
-#define NORESET 0 /* No reset on write to R9 */
-#define CHRB 0x40 /* Reset channel B */
-#define CHRA 0x80 /* Reset channel A */
-#define FHWRES 0xc0 /* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define BIT6 1 /* 6 bit/8bit sync */
-#define LOOPMODE 2 /* SDLC Loop mode */
-#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
-#define MARKIDLE 8 /* Mark/flag on idle */
-#define GAOP 0x10 /* Go active on poll */
-#define NRZ 0 /* NRZ mode */
-#define NRZI 0x20 /* NRZI mode */
-#define FM1 0x40 /* FM1 (transition = 1) */
-#define FM0 0x60 /* FM0 (transition = 0) */
-#define CRCPS 0x80 /* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define TRxCXT 0 /* TRxC = Xtal output */
-#define TRxCTC 1 /* TRxC = Transmit clock */
-#define TRxCBR 2 /* TRxC = BR Generator Output */
-#define TRxCDP 3 /* TRxC = DPLL output */
-#define TRxCOI 4 /* TRxC O/I */
-#define TCRTxCP 0 /* Transmit clock = RTxC pin */
-#define TCTRxCP 8 /* Transmit clock = TRxC pin */
-#define TCBR 0x10 /* Transmit clock = BR Generator output */
-#define TCDPLL 0x18 /* Transmit clock = DPLL output */
-#define RCRTxCP 0 /* Receive clock = RTxC pin */
-#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
-#define RCBR 0x40 /* Receive clock = BR Generator output */
-#define RCDPLL 0x60 /* Receive clock = DPLL output */
-#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define BRENAB 1 /* Baud rate generator enable */
-#define BRSRC 2 /* Baud rate generator source */
-#define DTRREQ 4 /* DTR/Request function */
-#define AUTOECHO 8 /* Auto Echo */
-#define LOOPBAK 0x10 /* Local loopback */
-#define SEARCH 0x20 /* Enter search mode */
-#define RMC 0x40 /* Reset missing clock */
-#define DISDPLL 0x60 /* Disable DPLL */
-#define SSBR 0x80 /* Set DPLL source = BR generator */
-#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
-#define SFMM 0xc0 /* Set FM mode */
-#define SNRZI 0xe0 /* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define WR7pEN 1 /* WR7' Enable (ESCC only) */
-#define ZCIE 2 /* Zero count IE */
-#define FIFOEN 4 /* FIFO Enable (ESCC only) */
-#define DCDIE 8 /* DCD IE */
-#define SYNCIE 0x10 /* Sync/hunt IE */
-#define CTSIE 0x20 /* CTS IE */
-#define TxUIE 0x40 /* Tx Underrun/EOM IE */
-#define BRKIE 0x80 /* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define Rx_CH_AV 0x1 /* Rx Character Available */
-#define ZCOUNT 0x2 /* Zero count */
-#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
-#define DCD 0x8 /* DCD */
-#define SYNC 0x10 /* Sync/hunt */
-#define CTS 0x20 /* CTS */
-#define TxEOM 0x40 /* Tx underrun */
-#define BRK_ABRT 0x80 /* Break/Abort */
-
-/* Read Register 1 */
-#define ALL_SNT 0x1 /* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define RES3 0x8 /* 0/3 */
-#define RES4 0x4 /* 0/4 */
-#define RES5 0xc /* 0/5 */
-#define RES6 0x2 /* 0/6 */
-#define RES7 0xa /* 0/7 */
-#define RES8 0x6 /* 0/8 */
-#define RES18 0xe /* 1/8 */
-#define RES28 0x0 /* 2/8 */
-/* Special Rx Condition Interrupts */
-#define PAR_ERR 0x10 /* Parity error */
-#define Rx_OVR 0x20 /* Rx Overrun Error */
-#define CRC_ERR 0x40 /* CRC/Framing Error */
-#define END_FR 0x80 /* End of Frame (SDLC) */
-
-/* Read Register 2 (channel b only) - Interrupt vector */
-#define CHB_Tx_EMPTY 0x00
-#define CHB_EXT_STAT 0x02
-#define CHB_Rx_AVAIL 0x04
-#define CHB_SPECIAL 0x06
-#define CHA_Tx_EMPTY 0x08
-#define CHA_EXT_STAT 0x0a
-#define CHA_Rx_AVAIL 0x0c
-#define CHA_SPECIAL 0x0e
-#define STATUS_MASK 0x0e
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
-#define CHBTxIP 0x2 /* Channel B Tx IP */
-#define CHBRxIP 0x4 /* Channel B Rx IP */
-#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
-#define CHATxIP 0x10 /* Channel A Tx IP */
-#define CHARxIP 0x20 /* Channel A Rx IP */
-
-/* Read Register 6 (LSB frame byte count [Not on NMOS]) */
-
-/* Read Register 7 (MSB frame byte count and FIFO status [Not on NMOS]) */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10 (misc status bits) */
-#define ONLOOP 2 /* On loop */
-#define LOOPSEND 0x10 /* Loop sending */
-#define CLK2MIS 0x40 /* Two clocks missing */
-#define CLK1MIS 0x80 /* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
-
-/* Misc macros */
-#define ZS_CLEARERR(channel) do { sbus_writeb(ERR_RES, &channel->control); \
- udelay(5); } while(0)
-
-#define ZS_CLEARSTAT(channel) do { sbus_writeb(RES_EXT_INT, &channel->control); \
- udelay(5); } while(0)
-
-#define ZS_CLEARFIFO(channel) do { sbus_readb(&channel->data); \
- udelay(2); \
- sbus_readb(&channel->data); \
- udelay(2); \
- sbus_readb(&channel->data); \
- udelay(2); } while(0)
-
-#endif /* _SUNZILOG_H */
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c
deleted file mode 100644
index 1f36b7eb7351..000000000000
--- a/drivers/serial/timbuart.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * timbuart.c timberdale FPGA UART driver
- * Copyright (c) 2009 Intel Corporation
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Supports:
- * Timberdale FPGA UART
- */
-
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/serial_core.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-
-#include "timbuart.h"
-
-struct timbuart_port {
- struct uart_port port;
- struct tasklet_struct tasklet;
- int usedma;
- u32 last_ier;
- struct platform_device *dev;
-};
-
-static int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800,
- 921600, 1843200, 3250000};
-
-static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier);
-
-static irqreturn_t timbuart_handleinterrupt(int irq, void *devid);
-
-static void timbuart_stop_rx(struct uart_port *port)
-{
- /* spin lock held by upper layer, disable all RX interrupts */
- u32 ier = ioread32(port->membase + TIMBUART_IER) & ~RXFLAGS;
- iowrite32(ier, port->membase + TIMBUART_IER);
-}
-
-static void timbuart_stop_tx(struct uart_port *port)
-{
- /* spinlock held by upper layer, disable TX interrupt */
- u32 ier = ioread32(port->membase + TIMBUART_IER) & ~TXBAE;
- iowrite32(ier, port->membase + TIMBUART_IER);
-}
-
-static void timbuart_start_tx(struct uart_port *port)
-{
- struct timbuart_port *uart =
- container_of(port, struct timbuart_port, port);
-
- /* do not transfer anything here -> fire off the tasklet */
- tasklet_schedule(&uart->tasklet);
-}
-
-static unsigned int timbuart_tx_empty(struct uart_port *port)
-{
- u32 isr = ioread32(port->membase + TIMBUART_ISR);
-
- return (isr & TXBE) ? TIOCSER_TEMT : 0;
-}
-
-static void timbuart_flush_buffer(struct uart_port *port)
-{
- if (!timbuart_tx_empty(port)) {
- u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
- TIMBUART_CTRL_FLSHTX;
-
- iowrite8(ctl, port->membase + TIMBUART_CTRL);
- iowrite32(TXBF, port->membase + TIMBUART_ISR);
- }
-}
-
-static void timbuart_rx_chars(struct uart_port *port)
-{
- struct tty_struct *tty = port->state->port.tty;
-
- while (ioread32(port->membase + TIMBUART_ISR) & RXDP) {
- u8 ch = ioread8(port->membase + TIMBUART_RXFIFO);
- port->icount.rx++;
- tty_insert_flip_char(tty, ch, TTY_NORMAL);
- }
-
- spin_unlock(&port->lock);
- tty_flip_buffer_push(port->state->port.tty);
- spin_lock(&port->lock);
-
- dev_dbg(port->dev, "%s - total read %d bytes\n",
- __func__, port->icount.rx);
-}
-
-static void timbuart_tx_chars(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) &&
- !uart_circ_empty(xmit)) {
- iowrite8(xmit->buf[xmit->tail],
- port->membase + TIMBUART_TXFIFO);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
-
- dev_dbg(port->dev,
- "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n",
- __func__,
- port->icount.tx,
- ioread8(port->membase + TIMBUART_CTRL),
- port->mctrl & TIOCM_RTS,
- ioread8(port->membase + TIMBUART_BAUDRATE));
-}
-
-static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier)
-{
- struct timbuart_port *uart =
- container_of(port, struct timbuart_port, port);
- struct circ_buf *xmit = &port->state->xmit;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port))
- return;
-
- if (port->x_char)
- return;
-
- if (isr & TXFLAGS) {
- timbuart_tx_chars(port);
- /* clear all TX interrupts */
- iowrite32(TXFLAGS, port->membase + TIMBUART_ISR);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
- } else
- /* Re-enable any tx interrupt */
- *ier |= uart->last_ier & TXFLAGS;
-
- /* enable interrupts if there are chars in the transmit buffer,
- * Or if we delivered some bytes and want the almost empty interrupt
- * we wake up the upper layer later when we got the interrupt
- * to give it some time to go out...
- */
- if (!uart_circ_empty(xmit))
- *ier |= TXBAE;
-
- dev_dbg(port->dev, "%s - leaving\n", __func__);
-}
-
-void timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier)
-{
- if (isr & RXFLAGS) {
- /* Some RX status is set */
- if (isr & RXBF) {
- u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
- TIMBUART_CTRL_FLSHRX;
- iowrite8(ctl, port->membase + TIMBUART_CTRL);
- port->icount.overrun++;
- } else if (isr & (RXDP))
- timbuart_rx_chars(port);
-
- /* ack all RX interrupts */
- iowrite32(RXFLAGS, port->membase + TIMBUART_ISR);
- }
-
- /* always have the RX interrupts enabled */
- *ier |= RXBAF | RXBF | RXTT;
-
- dev_dbg(port->dev, "%s - leaving\n", __func__);
-}
-
-void timbuart_tasklet(unsigned long arg)
-{
- struct timbuart_port *uart = (struct timbuart_port *)arg;
- u32 isr, ier = 0;
-
- spin_lock(&uart->port.lock);
-
- isr = ioread32(uart->port.membase + TIMBUART_ISR);
- dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr);
-
- if (!uart->usedma)
- timbuart_handle_tx_port(&uart->port, isr, &ier);
-
- timbuart_mctrl_check(&uart->port, isr, &ier);
-
- if (!uart->usedma)
- timbuart_handle_rx_port(&uart->port, isr, &ier);
-
- iowrite32(ier, uart->port.membase + TIMBUART_IER);
-
- spin_unlock(&uart->port.lock);
- dev_dbg(uart->port.dev, "%s leaving\n", __func__);
-}
-
-static unsigned int timbuart_get_mctrl(struct uart_port *port)
-{
- u8 cts = ioread8(port->membase + TIMBUART_CTRL);
- dev_dbg(port->dev, "%s - cts %x\n", __func__, cts);
-
- if (cts & TIMBUART_CTRL_CTS)
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
- else
- return TIOCM_DSR | TIOCM_CAR;
-}
-
-static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- dev_dbg(port->dev, "%s - %x\n", __func__, mctrl);
-
- if (mctrl & TIOCM_RTS)
- iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
- else
- iowrite8(0, port->membase + TIMBUART_CTRL);
-}
-
-static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
-{
- unsigned int cts;
-
- if (isr & CTS_DELTA) {
- /* ack */
- iowrite32(CTS_DELTA, port->membase + TIMBUART_ISR);
- cts = timbuart_get_mctrl(port);
- uart_handle_cts_change(port, cts & TIOCM_CTS);
- wake_up_interruptible(&port->state->port.delta_msr_wait);
- }
-
- *ier |= CTS_DELTA;
-}
-
-static void timbuart_enable_ms(struct uart_port *port)
-{
- /* N/A */
-}
-
-static void timbuart_break_ctl(struct uart_port *port, int ctl)
-{
- /* N/A */
-}
-
-static int timbuart_startup(struct uart_port *port)
-{
- struct timbuart_port *uart =
- container_of(port, struct timbuart_port, port);
-
- dev_dbg(port->dev, "%s\n", __func__);
-
- iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL);
- iowrite32(0x1ff, port->membase + TIMBUART_ISR);
- /* Enable all but TX interrupts */
- iowrite32(RXBAF | RXBF | RXTT | CTS_DELTA,
- port->membase + TIMBUART_IER);
-
- return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED,
- "timb-uart", uart);
-}
-
-static void timbuart_shutdown(struct uart_port *port)
-{
- struct timbuart_port *uart =
- container_of(port, struct timbuart_port, port);
- dev_dbg(port->dev, "%s\n", __func__);
- free_irq(port->irq, uart);
- iowrite32(0, port->membase + TIMBUART_IER);
-}
-
-static int get_bindex(int baud)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(baudrates); i++)
- if (baud <= baudrates[i])
- return i;
-
- return -1;
-}
-
-static void timbuart_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int baud;
- short bindex;
- unsigned long flags;
-
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
- bindex = get_bindex(baud);
- dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex);
-
- if (bindex < 0)
- bindex = 0;
- baud = baudrates[bindex];
-
- /* The serial layer calls into this once with old = NULL when setting
- up initially */
- if (old)
- tty_termios_copy_hw(termios, old);
- tty_termios_encode_baud_rate(termios, baud, baud);
-
- spin_lock_irqsave(&port->lock, flags);
- iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE);
- uart_update_timeout(port, termios->c_cflag, baud);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *timbuart_type(struct uart_port *port)
-{
- return port->type == PORT_UNKNOWN ? "timbuart" : NULL;
-}
-
-/* We do not request/release mappings of the registers here,
- * currently it's done in the proble function.
- */
-static void timbuart_release_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- int size =
- resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
-
- if (port->flags & UPF_IOREMAP) {
- iounmap(port->membase);
- port->membase = NULL;
- }
-
- release_mem_region(port->mapbase, size);
-}
-
-static int timbuart_request_port(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- int size =
- resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
-
- if (!request_mem_region(port->mapbase, size, "timb-uart"))
- return -EBUSY;
-
- if (port->flags & UPF_IOREMAP) {
- port->membase = ioremap(port->mapbase, size);
- if (port->membase == NULL) {
- release_mem_region(port->mapbase, size);
- return -ENOMEM;
- }
- }
-
- return 0;
-}
-
-static irqreturn_t timbuart_handleinterrupt(int irq, void *devid)
-{
- struct timbuart_port *uart = (struct timbuart_port *)devid;
-
- if (ioread8(uart->port.membase + TIMBUART_IPR)) {
- uart->last_ier = ioread32(uart->port.membase + TIMBUART_IER);
-
- /* disable interrupts, the tasklet enables them again */
- iowrite32(0, uart->port.membase + TIMBUART_IER);
-
- /* fire off bottom half */
- tasklet_schedule(&uart->tasklet);
-
- return IRQ_HANDLED;
- } else
- return IRQ_NONE;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void timbuart_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_TIMBUART;
- timbuart_request_port(port);
- }
-}
-
-static int timbuart_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- /* we don't want the core code to modify any port params */
- return -EINVAL;
-}
-
-static struct uart_ops timbuart_ops = {
- .tx_empty = timbuart_tx_empty,
- .set_mctrl = timbuart_set_mctrl,
- .get_mctrl = timbuart_get_mctrl,
- .stop_tx = timbuart_stop_tx,
- .start_tx = timbuart_start_tx,
- .flush_buffer = timbuart_flush_buffer,
- .stop_rx = timbuart_stop_rx,
- .enable_ms = timbuart_enable_ms,
- .break_ctl = timbuart_break_ctl,
- .startup = timbuart_startup,
- .shutdown = timbuart_shutdown,
- .set_termios = timbuart_set_termios,
- .type = timbuart_type,
- .release_port = timbuart_release_port,
- .request_port = timbuart_request_port,
- .config_port = timbuart_config_port,
- .verify_port = timbuart_verify_port
-};
-
-static struct uart_driver timbuart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "timberdale_uart",
- .dev_name = "ttyTU",
- .major = TIMBUART_MAJOR,
- .minor = TIMBUART_MINOR,
- .nr = 1
-};
-
-static int __devinit timbuart_probe(struct platform_device *dev)
-{
- int err, irq;
- struct timbuart_port *uart;
- struct resource *iomem;
-
- dev_dbg(&dev->dev, "%s\n", __func__);
-
- uart = kzalloc(sizeof(*uart), GFP_KERNEL);
- if (!uart) {
- err = -EINVAL;
- goto err_mem;
- }
-
- uart->usedma = 0;
-
- uart->port.uartclk = 3250000 * 16;
- uart->port.fifosize = TIMBUART_FIFO_SIZE;
- uart->port.regshift = 2;
- uart->port.iotype = UPIO_MEM;
- uart->port.ops = &timbuart_ops;
- uart->port.irq = 0;
- uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
- uart->port.line = 0;
- uart->port.dev = &dev->dev;
-
- iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!iomem) {
- err = -ENOMEM;
- goto err_register;
- }
- uart->port.mapbase = iomem->start;
- uart->port.membase = NULL;
-
- irq = platform_get_irq(dev, 0);
- if (irq < 0) {
- err = -EINVAL;
- goto err_register;
- }
- uart->port.irq = irq;
-
- tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart);
-
- err = uart_register_driver(&timbuart_driver);
- if (err)
- goto err_register;
-
- err = uart_add_one_port(&timbuart_driver, &uart->port);
- if (err)
- goto err_add_port;
-
- platform_set_drvdata(dev, uart);
-
- return 0;
-
-err_add_port:
- uart_unregister_driver(&timbuart_driver);
-err_register:
- kfree(uart);
-err_mem:
- printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n",
- err);
-
- return err;
-}
-
-static int __devexit timbuart_remove(struct platform_device *dev)
-{
- struct timbuart_port *uart = platform_get_drvdata(dev);
-
- tasklet_kill(&uart->tasklet);
- uart_remove_one_port(&timbuart_driver, &uart->port);
- uart_unregister_driver(&timbuart_driver);
- kfree(uart);
-
- return 0;
-}
-
-static struct platform_driver timbuart_platform_driver = {
- .driver = {
- .name = "timb-uart",
- .owner = THIS_MODULE,
- },
- .probe = timbuart_probe,
- .remove = __devexit_p(timbuart_remove),
-};
-
-/*--------------------------------------------------------------------------*/
-
-static int __init timbuart_init(void)
-{
- return platform_driver_register(&timbuart_platform_driver);
-}
-
-static void __exit timbuart_exit(void)
-{
- platform_driver_unregister(&timbuart_platform_driver);
-}
-
-module_init(timbuart_init);
-module_exit(timbuart_exit);
-
-MODULE_DESCRIPTION("Timberdale UART driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:timb-uart");
-
diff --git a/drivers/serial/timbuart.h b/drivers/serial/timbuart.h
deleted file mode 100644
index 7e566766bc43..000000000000
--- a/drivers/serial/timbuart.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * timbuart.c timberdale FPGA GPIO driver
- * Copyright (c) 2009 Intel Corporation
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Supports:
- * Timberdale FPGA UART
- */
-
-#ifndef _TIMBUART_H
-#define _TIMBUART_H
-
-#define TIMBUART_FIFO_SIZE 2048
-
-#define TIMBUART_RXFIFO 0x08
-#define TIMBUART_TXFIFO 0x0c
-#define TIMBUART_IER 0x10
-#define TIMBUART_IPR 0x14
-#define TIMBUART_ISR 0x18
-#define TIMBUART_CTRL 0x1c
-#define TIMBUART_BAUDRATE 0x20
-
-#define TIMBUART_CTRL_RTS 0x01
-#define TIMBUART_CTRL_CTS 0x02
-#define TIMBUART_CTRL_FLSHTX 0x40
-#define TIMBUART_CTRL_FLSHRX 0x80
-
-#define TXBF 0x01
-#define TXBAE 0x02
-#define CTS_DELTA 0x04
-#define RXDP 0x08
-#define RXBAF 0x10
-#define RXBF 0x20
-#define RXTT 0x40
-#define RXBNAE 0x80
-#define TXBE 0x100
-
-#define RXFLAGS (RXDP | RXBAF | RXBF | RXTT | RXBNAE)
-#define TXFLAGS (TXBF | TXBAE)
-
-#define TIMBUART_MAJOR 204
-#define TIMBUART_MINOR 192
-
-#endif /* _TIMBUART_H */
-
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
deleted file mode 100644
index d2fce865b731..000000000000
--- a/drivers/serial/uartlite.c
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * uartlite.c: Serial driver for Xilinx uartlite serial controller
- *
- * Copyright (C) 2006 Peter Korsgaard <jacmet@sunsite.dk>
- * Copyright (C) 2007 Secret Lab Technologies Ltd.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE))
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-
-/* Match table for of_platform binding */
-static struct of_device_id ulite_of_match[] __devinitdata = {
- { .compatible = "xlnx,opb-uartlite-1.00.b", },
- { .compatible = "xlnx,xps-uartlite-1.00.a", },
- {}
-};
-MODULE_DEVICE_TABLE(of, ulite_of_match);
-
-#endif
-
-#define ULITE_NAME "ttyUL"
-#define ULITE_MAJOR 204
-#define ULITE_MINOR 187
-#define ULITE_NR_UARTS 4
-
-/* ---------------------------------------------------------------------
- * Register definitions
- *
- * For register details see datasheet:
- * http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf
- */
-
-#define ULITE_RX 0x00
-#define ULITE_TX 0x04
-#define ULITE_STATUS 0x08
-#define ULITE_CONTROL 0x0c
-
-#define ULITE_REGION 16
-
-#define ULITE_STATUS_RXVALID 0x01
-#define ULITE_STATUS_RXFULL 0x02
-#define ULITE_STATUS_TXEMPTY 0x04
-#define ULITE_STATUS_TXFULL 0x08
-#define ULITE_STATUS_IE 0x10
-#define ULITE_STATUS_OVERRUN 0x20
-#define ULITE_STATUS_FRAME 0x40
-#define ULITE_STATUS_PARITY 0x80
-
-#define ULITE_CONTROL_RST_TX 0x01
-#define ULITE_CONTROL_RST_RX 0x02
-#define ULITE_CONTROL_IE 0x10
-
-
-static struct uart_port ulite_ports[ULITE_NR_UARTS];
-
-/* ---------------------------------------------------------------------
- * Core UART driver operations
- */
-
-static int ulite_receive(struct uart_port *port, int stat)
-{
- struct tty_struct *tty = port->state->port.tty;
- unsigned char ch = 0;
- char flag = TTY_NORMAL;
-
- if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
- | ULITE_STATUS_FRAME)) == 0)
- return 0;
-
- /* stats */
- if (stat & ULITE_STATUS_RXVALID) {
- port->icount.rx++;
- ch = ioread32be(port->membase + ULITE_RX);
-
- if (stat & ULITE_STATUS_PARITY)
- port->icount.parity++;
- }
-
- if (stat & ULITE_STATUS_OVERRUN)
- port->icount.overrun++;
-
- if (stat & ULITE_STATUS_FRAME)
- port->icount.frame++;
-
-
- /* drop byte with parity error if IGNPAR specificed */
- if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
- stat &= ~ULITE_STATUS_RXVALID;
-
- stat &= port->read_status_mask;
-
- if (stat & ULITE_STATUS_PARITY)
- flag = TTY_PARITY;
-
-
- stat &= ~port->ignore_status_mask;
-
- if (stat & ULITE_STATUS_RXVALID)
- tty_insert_flip_char(tty, ch, flag);
-
- if (stat & ULITE_STATUS_FRAME)
- tty_insert_flip_char(tty, 0, TTY_FRAME);
-
- if (stat & ULITE_STATUS_OVERRUN)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-
- return 1;
-}
-
-static int ulite_transmit(struct uart_port *port, int stat)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- if (stat & ULITE_STATUS_TXFULL)
- return 0;
-
- if (port->x_char) {
- iowrite32be(port->x_char, port->membase + ULITE_TX);
- port->x_char = 0;
- port->icount.tx++;
- return 1;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port))
- return 0;
-
- iowrite32be(xmit->buf[xmit->tail], port->membase + ULITE_TX);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
- port->icount.tx++;
-
- /* wake up */
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- return 1;
-}
-
-static irqreturn_t ulite_isr(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- int busy, n = 0;
-
- do {
- int stat = ioread32be(port->membase + ULITE_STATUS);
- busy = ulite_receive(port, stat);
- busy |= ulite_transmit(port, stat);
- n++;
- } while (busy);
-
- /* work done? */
- if (n > 1) {
- tty_flip_buffer_push(port->state->port.tty);
- return IRQ_HANDLED;
- } else {
- return IRQ_NONE;
- }
-}
-
-static unsigned int ulite_tx_empty(struct uart_port *port)
-{
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&port->lock, flags);
- ret = ioread32be(port->membase + ULITE_STATUS);
- spin_unlock_irqrestore(&port->lock, flags);
-
- return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int ulite_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-}
-
-static void ulite_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- /* N/A */
-}
-
-static void ulite_stop_tx(struct uart_port *port)
-{
- /* N/A */
-}
-
-static void ulite_start_tx(struct uart_port *port)
-{
- ulite_transmit(port, ioread32be(port->membase + ULITE_STATUS));
-}
-
-static void ulite_stop_rx(struct uart_port *port)
-{
- /* don't forward any more data (like !CREAD) */
- port->ignore_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
- | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
-}
-
-static void ulite_enable_ms(struct uart_port *port)
-{
- /* N/A */
-}
-
-static void ulite_break_ctl(struct uart_port *port, int ctl)
-{
- /* N/A */
-}
-
-static int ulite_startup(struct uart_port *port)
-{
- int ret;
-
- ret = request_irq(port->irq, ulite_isr,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM, "uartlite", port);
- if (ret)
- return ret;
-
- iowrite32be(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX,
- port->membase + ULITE_CONTROL);
- iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
-
- return 0;
-}
-
-static void ulite_shutdown(struct uart_port *port)
-{
- iowrite32be(0, port->membase + ULITE_CONTROL);
- ioread32be(port->membase + ULITE_CONTROL); /* dummy */
- free_irq(port->irq, port);
-}
-
-static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned long flags;
- unsigned int baud;
-
- spin_lock_irqsave(&port->lock, flags);
-
- port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
- | ULITE_STATUS_TXFULL;
-
- if (termios->c_iflag & INPCK)
- port->read_status_mask |=
- ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
-
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= ULITE_STATUS_PARITY
- | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
-
- /* ignore all characters if CREAD is not set */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |=
- ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
- | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
-
- /* update timeout */
- baud = uart_get_baud_rate(port, termios, old, 0, 460800);
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *ulite_type(struct uart_port *port)
-{
- return port->type == PORT_UARTLITE ? "uartlite" : NULL;
-}
-
-static void ulite_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, ULITE_REGION);
- iounmap(port->membase);
- port->membase = NULL;
-}
-
-static int ulite_request_port(struct uart_port *port)
-{
- pr_debug("ulite console: port=%p; port->mapbase=%llx\n",
- port, (unsigned long long) port->mapbase);
-
- if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {
- dev_err(port->dev, "Memory region busy\n");
- return -EBUSY;
- }
-
- port->membase = ioremap(port->mapbase, ULITE_REGION);
- if (!port->membase) {
- dev_err(port->dev, "Unable to map registers\n");
- release_mem_region(port->mapbase, ULITE_REGION);
- return -EBUSY;
- }
-
- return 0;
-}
-
-static void ulite_config_port(struct uart_port *port, int flags)
-{
- if (!ulite_request_port(port))
- port->type = PORT_UARTLITE;
-}
-
-static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- /* we don't want the core code to modify any port params */
- return -EINVAL;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-static int ulite_get_poll_char(struct uart_port *port)
-{
- if (!(ioread32be(port->membase + ULITE_STATUS)
- & ULITE_STATUS_RXVALID))
- return NO_POLL_CHAR;
-
- return ioread32be(port->membase + ULITE_RX);
-}
-
-static void ulite_put_poll_char(struct uart_port *port, unsigned char ch)
-{
- while (ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL)
- cpu_relax();
-
- /* write char to device */
- iowrite32be(ch, port->membase + ULITE_TX);
-}
-#endif
-
-static struct uart_ops ulite_ops = {
- .tx_empty = ulite_tx_empty,
- .set_mctrl = ulite_set_mctrl,
- .get_mctrl = ulite_get_mctrl,
- .stop_tx = ulite_stop_tx,
- .start_tx = ulite_start_tx,
- .stop_rx = ulite_stop_rx,
- .enable_ms = ulite_enable_ms,
- .break_ctl = ulite_break_ctl,
- .startup = ulite_startup,
- .shutdown = ulite_shutdown,
- .set_termios = ulite_set_termios,
- .type = ulite_type,
- .release_port = ulite_release_port,
- .request_port = ulite_request_port,
- .config_port = ulite_config_port,
- .verify_port = ulite_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = ulite_get_poll_char,
- .poll_put_char = ulite_put_poll_char,
-#endif
-};
-
-/* ---------------------------------------------------------------------
- * Console driver operations
- */
-
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
-static void ulite_console_wait_tx(struct uart_port *port)
-{
- int i;
- u8 val;
-
- /* Spin waiting for TX fifo to have space available */
- for (i = 0; i < 100000; i++) {
- val = ioread32be(port->membase + ULITE_STATUS);
- if ((val & ULITE_STATUS_TXFULL) == 0)
- break;
- cpu_relax();
- }
-}
-
-static void ulite_console_putchar(struct uart_port *port, int ch)
-{
- ulite_console_wait_tx(port);
- iowrite32be(ch, port->membase + ULITE_TX);
-}
-
-static void ulite_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_port *port = &ulite_ports[co->index];
- unsigned long flags;
- unsigned int ier;
- 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 */
- ier = ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_IE;
- iowrite32be(0, port->membase + ULITE_CONTROL);
-
- uart_console_write(port, s, count, ulite_console_putchar);
-
- ulite_console_wait_tx(port);
-
- /* restore interrupt state */
- if (ier)
- iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
-
- if (locked)
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int __devinit ulite_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (co->index < 0 || co->index >= ULITE_NR_UARTS)
- return -EINVAL;
-
- port = &ulite_ports[co->index];
-
- /* Has the device been initialized yet? */
- if (!port->mapbase) {
- pr_debug("console on ttyUL%i not present\n", co->index);
- return -ENODEV;
- }
-
- /* not initialized yet? */
- if (!port->membase) {
- if (ulite_request_port(port))
- 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 ulite_uart_driver;
-
-static struct console ulite_console = {
- .name = ULITE_NAME,
- .write = ulite_console_write,
- .device = uart_console_device,
- .setup = ulite_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */
- .data = &ulite_uart_driver,
-};
-
-static int __init ulite_console_init(void)
-{
- register_console(&ulite_console);
- return 0;
-}
-
-console_initcall(ulite_console_init);
-
-#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
-
-static struct uart_driver ulite_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "uartlite",
- .dev_name = ULITE_NAME,
- .major = ULITE_MAJOR,
- .minor = ULITE_MINOR,
- .nr = ULITE_NR_UARTS,
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
- .cons = &ulite_console,
-#endif
-};
-
-/* ---------------------------------------------------------------------
- * Port assignment functions (mapping devices to uart_port structures)
- */
-
-/** ulite_assign: register a uartlite device with the driver
- *
- * @dev: pointer to device structure
- * @id: requested id number. Pass -1 for automatic port assignment
- * @base: base address of uartlite registers
- * @irq: irq number for uartlite
- *
- * Returns: 0 on success, <0 otherwise
- */
-static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
-{
- struct uart_port *port;
- int rc;
-
- /* if id = -1; then scan for a free id and use that */
- if (id < 0) {
- for (id = 0; id < ULITE_NR_UARTS; id++)
- if (ulite_ports[id].mapbase == 0)
- break;
- }
- if (id < 0 || id >= ULITE_NR_UARTS) {
- dev_err(dev, "%s%i too large\n", ULITE_NAME, id);
- return -EINVAL;
- }
-
- if ((ulite_ports[id].mapbase) && (ulite_ports[id].mapbase != base)) {
- dev_err(dev, "cannot assign to %s%i; it is already in use\n",
- ULITE_NAME, id);
- return -EBUSY;
- }
-
- port = &ulite_ports[id];
-
- spin_lock_init(&port->lock);
- port->fifosize = 16;
- port->regshift = 2;
- port->iotype = UPIO_MEM;
- port->iobase = 1; /* mark port in use */
- port->mapbase = base;
- port->membase = NULL;
- port->ops = &ulite_ops;
- port->irq = irq;
- port->flags = UPF_BOOT_AUTOCONF;
- port->dev = dev;
- port->type = PORT_UNKNOWN;
- port->line = id;
-
- dev_set_drvdata(dev, port);
-
- /* Register the port */
- rc = uart_add_one_port(&ulite_uart_driver, port);
- if (rc) {
- dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
- port->mapbase = 0;
- dev_set_drvdata(dev, NULL);
- return rc;
- }
-
- return 0;
-}
-
-/** ulite_release: register a uartlite device with the driver
- *
- * @dev: pointer to device structure
- */
-static int __devexit ulite_release(struct device *dev)
-{
- struct uart_port *port = dev_get_drvdata(dev);
- int rc = 0;
-
- if (port) {
- rc = uart_remove_one_port(&ulite_uart_driver, port);
- dev_set_drvdata(dev, NULL);
- port->mapbase = 0;
- }
-
- return rc;
-}
-
-/* ---------------------------------------------------------------------
- * Platform bus binding
- */
-
-static int __devinit ulite_probe(struct platform_device *pdev)
-{
- struct resource *res, *res2;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res2)
- return -ENODEV;
-
- return ulite_assign(&pdev->dev, pdev->id, res->start, res2->start);
-}
-
-static int __devexit ulite_remove(struct platform_device *pdev)
-{
- return ulite_release(&pdev->dev);
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:uartlite");
-
-static struct platform_driver ulite_platform_driver = {
- .probe = ulite_probe,
- .remove = __devexit_p(ulite_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "uartlite",
- },
-};
-
-/* ---------------------------------------------------------------------
- * OF bus bindings
- */
-#if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE))
-static int __devinit
-ulite_of_probe(struct platform_device *op, const struct of_device_id *match)
-{
- struct resource res;
- const unsigned int *id;
- int irq, rc;
-
- dev_dbg(&op->dev, "%s(%p, %p)\n", __func__, op, match);
-
- rc = of_address_to_resource(op->dev.of_node, 0, &res);
- if (rc) {
- dev_err(&op->dev, "invalid address\n");
- return rc;
- }
-
- irq = irq_of_parse_and_map(op->dev.of_node, 0);
-
- id = of_get_property(op->dev.of_node, "port-number", NULL);
-
- return ulite_assign(&op->dev, id ? *id : -1, res.start, irq);
-}
-
-static int __devexit ulite_of_remove(struct platform_device *op)
-{
- return ulite_release(&op->dev);
-}
-
-static struct of_platform_driver ulite_of_driver = {
- .probe = ulite_of_probe,
- .remove = __devexit_p(ulite_of_remove),
- .driver = {
- .name = "uartlite",
- .owner = THIS_MODULE,
- .of_match_table = ulite_of_match,
- },
-};
-
-/* Registration helpers to keep the number of #ifdefs to a minimum */
-static inline int __init ulite_of_register(void)
-{
- pr_debug("uartlite: calling of_register_platform_driver()\n");
- return of_register_platform_driver(&ulite_of_driver);
-}
-
-static inline void __exit ulite_of_unregister(void)
-{
- of_unregister_platform_driver(&ulite_of_driver);
-}
-#else /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */
-/* Appropriate config not enabled; do nothing helpers */
-static inline int __init ulite_of_register(void) { return 0; }
-static inline void __exit ulite_of_unregister(void) { }
-#endif /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */
-
-/* ---------------------------------------------------------------------
- * Module setup/teardown
- */
-
-int __init ulite_init(void)
-{
- int ret;
-
- pr_debug("uartlite: calling uart_register_driver()\n");
- ret = uart_register_driver(&ulite_uart_driver);
- if (ret)
- goto err_uart;
-
- ret = ulite_of_register();
- if (ret)
- goto err_of;
-
- pr_debug("uartlite: calling platform_driver_register()\n");
- ret = platform_driver_register(&ulite_platform_driver);
- if (ret)
- goto err_plat;
-
- return 0;
-
-err_plat:
- ulite_of_unregister();
-err_of:
- uart_unregister_driver(&ulite_uart_driver);
-err_uart:
- printk(KERN_ERR "registering uartlite driver failed: err=%i", ret);
- return ret;
-}
-
-void __exit ulite_exit(void)
-{
- platform_driver_unregister(&ulite_platform_driver);
- ulite_of_unregister();
- uart_unregister_driver(&ulite_uart_driver);
-}
-
-module_init(ulite_init);
-module_exit(ulite_exit);
-
-MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
-MODULE_DESCRIPTION("Xilinx uartlite serial driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
deleted file mode 100644
index 3f4848e2174a..000000000000
--- a/drivers/serial/ucc_uart.c
+++ /dev/null
@@ -1,1537 +0,0 @@
-/*
- * Freescale QUICC Engine UART device driver
- *
- * Author: Timur Tabi <timur@freescale.com>
- *
- * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * This driver adds support for UART devices via Freescale's QUICC Engine
- * found on some Freescale SOCs.
- *
- * If Soft-UART support is needed but not already present, then this driver
- * will request and upload the "Soft-UART" microcode upon probe. The
- * filename of the microcode should be fsl_qe_ucode_uart_X_YZ.bin, where "X"
- * is the name of the SOC (e.g. 8323), and YZ is the revision of the SOC,
- * (e.g. "11" for 1.1).
- */
-
-#include <linux/module.h>
-#include <linux/serial.h>
-#include <linux/slab.h>
-#include <linux/serial_core.h>
-#include <linux/io.h>
-#include <linux/of_platform.h>
-#include <linux/dma-mapping.h>
-
-#include <linux/fs_uart_pd.h>
-#include <asm/ucc_slow.h>
-
-#include <linux/firmware.h>
-#include <asm/reg.h>
-
-/*
- * The GUMR flag for Soft UART. This would normally be defined in qe.h,
- * but Soft-UART is a hack and we want to keep everything related to it in
- * this file.
- */
-#define UCC_SLOW_GUMR_H_SUART 0x00004000 /* Soft-UART */
-
-/*
- * soft_uart is 1 if we need to use Soft-UART mode
- */
-static int soft_uart;
-/*
- * firmware_loaded is 1 if the firmware has been loaded, 0 otherwise.
- */
-static int firmware_loaded;
-
-/* Enable this macro to configure all serial ports in internal loopback
- mode */
-/* #define LOOPBACK */
-
-/* The major and minor device numbers are defined in
- * http://www.lanana.org/docs/device-list/devices-2.6+.txt. For the QE
- * UART, we have major number 204 and minor numbers 46 - 49, which are the
- * same as for the CPM2. This decision was made because no Freescale part
- * has both a CPM and a QE.
- */
-#define SERIAL_QE_MAJOR 204
-#define SERIAL_QE_MINOR 46
-
-/* Since we only have minor numbers 46 - 49, there is a hard limit of 4 ports */
-#define UCC_MAX_UART 4
-
-/* The number of buffer descriptors for receiving characters. */
-#define RX_NUM_FIFO 4
-
-/* The number of buffer descriptors for transmitting characters. */
-#define TX_NUM_FIFO 4
-
-/* The maximum size of the character buffer for a single RX BD. */
-#define RX_BUF_SIZE 32
-
-/* The maximum size of the character buffer for a single TX BD. */
-#define TX_BUF_SIZE 32
-
-/*
- * The number of jiffies to wait after receiving a close command before the
- * device is actually closed. This allows the last few characters to be
- * sent over the wire.
- */
-#define UCC_WAIT_CLOSING 100
-
-struct ucc_uart_pram {
- struct ucc_slow_pram common;
- u8 res1[8]; /* reserved */
- __be16 maxidl; /* Maximum idle chars */
- __be16 idlc; /* temp idle counter */
- __be16 brkcr; /* Break count register */
- __be16 parec; /* receive parity error counter */
- __be16 frmec; /* receive framing error counter */
- __be16 nosec; /* receive noise counter */
- __be16 brkec; /* receive break condition counter */
- __be16 brkln; /* last received break length */
- __be16 uaddr[2]; /* UART address character 1 & 2 */
- __be16 rtemp; /* Temp storage */
- __be16 toseq; /* Transmit out of sequence char */
- __be16 cchars[8]; /* control characters 1-8 */
- __be16 rccm; /* receive control character mask */
- __be16 rccr; /* receive control character register */
- __be16 rlbc; /* receive last break character */
- __be16 res2; /* reserved */
- __be32 res3; /* reserved, should be cleared */
- u8 res4; /* reserved, should be cleared */
- u8 res5[3]; /* reserved, should be cleared */
- __be32 res6; /* reserved, should be cleared */
- __be32 res7; /* reserved, should be cleared */
- __be32 res8; /* reserved, should be cleared */
- __be32 res9; /* reserved, should be cleared */
- __be32 res10; /* reserved, should be cleared */
- __be32 res11; /* reserved, should be cleared */
- __be32 res12; /* reserved, should be cleared */
- __be32 res13; /* reserved, should be cleared */
-/* The rest is for Soft-UART only */
- __be16 supsmr; /* 0x90, Shadow UPSMR */
- __be16 res92; /* 0x92, reserved, initialize to 0 */
- __be32 rx_state; /* 0x94, RX state, initialize to 0 */
- __be32 rx_cnt; /* 0x98, RX count, initialize to 0 */
- u8 rx_length; /* 0x9C, Char length, set to 1+CL+PEN+1+SL */
- u8 rx_bitmark; /* 0x9D, reserved, initialize to 0 */
- u8 rx_temp_dlst_qe; /* 0x9E, reserved, initialize to 0 */
- u8 res14[0xBC - 0x9F]; /* reserved */
- __be32 dump_ptr; /* 0xBC, Dump pointer */
- __be32 rx_frame_rem; /* 0xC0, reserved, initialize to 0 */
- u8 rx_frame_rem_size; /* 0xC4, reserved, initialize to 0 */
- u8 tx_mode; /* 0xC5, mode, 0=AHDLC, 1=UART */
- __be16 tx_state; /* 0xC6, TX state */
- u8 res15[0xD0 - 0xC8]; /* reserved */
- __be32 resD0; /* 0xD0, reserved, initialize to 0 */
- u8 resD4; /* 0xD4, reserved, initialize to 0 */
- __be16 resD5; /* 0xD5, reserved, initialize to 0 */
-} __attribute__ ((packed));
-
-/* SUPSMR definitions, for Soft-UART only */
-#define UCC_UART_SUPSMR_SL 0x8000
-#define UCC_UART_SUPSMR_RPM_MASK 0x6000
-#define UCC_UART_SUPSMR_RPM_ODD 0x0000
-#define UCC_UART_SUPSMR_RPM_LOW 0x2000
-#define UCC_UART_SUPSMR_RPM_EVEN 0x4000
-#define UCC_UART_SUPSMR_RPM_HIGH 0x6000
-#define UCC_UART_SUPSMR_PEN 0x1000
-#define UCC_UART_SUPSMR_TPM_MASK 0x0C00
-#define UCC_UART_SUPSMR_TPM_ODD 0x0000
-#define UCC_UART_SUPSMR_TPM_LOW 0x0400
-#define UCC_UART_SUPSMR_TPM_EVEN 0x0800
-#define UCC_UART_SUPSMR_TPM_HIGH 0x0C00
-#define UCC_UART_SUPSMR_FRZ 0x0100
-#define UCC_UART_SUPSMR_UM_MASK 0x00c0
-#define UCC_UART_SUPSMR_UM_NORMAL 0x0000
-#define UCC_UART_SUPSMR_UM_MAN_MULTI 0x0040
-#define UCC_UART_SUPSMR_UM_AUTO_MULTI 0x00c0
-#define UCC_UART_SUPSMR_CL_MASK 0x0030
-#define UCC_UART_SUPSMR_CL_8 0x0030
-#define UCC_UART_SUPSMR_CL_7 0x0020
-#define UCC_UART_SUPSMR_CL_6 0x0010
-#define UCC_UART_SUPSMR_CL_5 0x0000
-
-#define UCC_UART_TX_STATE_AHDLC 0x00
-#define UCC_UART_TX_STATE_UART 0x01
-#define UCC_UART_TX_STATE_X1 0x00
-#define UCC_UART_TX_STATE_X16 0x80
-
-#define UCC_UART_PRAM_ALIGNMENT 0x100
-
-#define UCC_UART_SIZE_OF_BD UCC_SLOW_SIZE_OF_BD
-#define NUM_CONTROL_CHARS 8
-
-/* Private per-port data structure */
-struct uart_qe_port {
- struct uart_port port;
- struct ucc_slow __iomem *uccp;
- struct ucc_uart_pram __iomem *uccup;
- struct ucc_slow_info us_info;
- struct ucc_slow_private *us_private;
- struct device_node *np;
- unsigned int ucc_num; /* First ucc is 0, not 1 */
-
- u16 rx_nrfifos;
- u16 rx_fifosize;
- u16 tx_nrfifos;
- u16 tx_fifosize;
- int wait_closing;
- u32 flags;
- struct qe_bd *rx_bd_base;
- struct qe_bd *rx_cur;
- struct qe_bd *tx_bd_base;
- struct qe_bd *tx_cur;
- unsigned char *tx_buf;
- unsigned char *rx_buf;
- void *bd_virt; /* virtual address of the BD buffers */
- dma_addr_t bd_dma_addr; /* bus address of the BD buffers */
- unsigned int bd_size; /* size of BD buffer space */
-};
-
-static struct uart_driver ucc_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "ucc_uart",
- .dev_name = "ttyQE",
- .major = SERIAL_QE_MAJOR,
- .minor = SERIAL_QE_MINOR,
- .nr = UCC_MAX_UART,
-};
-
-/*
- * Virtual to physical address translation.
- *
- * Given the virtual address for a character buffer, this function returns
- * the physical (DMA) equivalent.
- */
-static inline dma_addr_t cpu2qe_addr(void *addr, struct uart_qe_port *qe_port)
-{
- if (likely((addr >= qe_port->bd_virt)) &&
- (addr < (qe_port->bd_virt + qe_port->bd_size)))
- return qe_port->bd_dma_addr + (addr - qe_port->bd_virt);
-
- /* something nasty happened */
- printk(KERN_ERR "%s: addr=%p\n", __func__, addr);
- BUG();
- return 0;
-}
-
-/*
- * Physical to virtual address translation.
- *
- * Given the physical (DMA) address for a character buffer, this function
- * returns the virtual equivalent.
- */
-static inline void *qe2cpu_addr(dma_addr_t addr, struct uart_qe_port *qe_port)
-{
- /* sanity check */
- if (likely((addr >= qe_port->bd_dma_addr) &&
- (addr < (qe_port->bd_dma_addr + qe_port->bd_size))))
- return qe_port->bd_virt + (addr - qe_port->bd_dma_addr);
-
- /* something nasty happened */
- printk(KERN_ERR "%s: addr=%x\n", __func__, addr);
- BUG();
- return NULL;
-}
-
-/*
- * Return 1 if the QE is done transmitting all buffers for this port
- *
- * This function scans each BD in sequence. If we find a BD that is not
- * ready (READY=1), then we return 0 indicating that the QE is still sending
- * data. If we reach the last BD (WRAP=1), then we know we've scanned
- * the entire list, and all BDs are done.
- */
-static unsigned int qe_uart_tx_empty(struct uart_port *port)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
- struct qe_bd *bdp = qe_port->tx_bd_base;
-
- while (1) {
- if (in_be16(&bdp->status) & BD_SC_READY)
- /* This BD is not done, so return "not done" */
- return 0;
-
- if (in_be16(&bdp->status) & BD_SC_WRAP)
- /*
- * This BD is done and it's the last one, so return
- * "done"
- */
- return 1;
-
- bdp++;
- };
-}
-
-/*
- * Set the modem control lines
- *
- * Although the QE can control the modem control lines (e.g. CTS), we
- * don't need that support. This function must exist, however, otherwise
- * the kernel will panic.
- */
-void qe_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-/*
- * Get the current modem control line status
- *
- * Although the QE can control the modem control lines (e.g. CTS), this
- * driver currently doesn't support that, so we always return Carrier
- * Detect, Data Set Ready, and Clear To Send.
- */
-static unsigned int qe_uart_get_mctrl(struct uart_port *port)
-{
- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-}
-
-/*
- * Disable the transmit interrupt.
- *
- * Although this function is called "stop_tx", it does not actually stop
- * transmission of data. Instead, it tells the QE to not generate an
- * interrupt when the UCC is finished sending characters.
- */
-static void qe_uart_stop_tx(struct uart_port *port)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
-
- clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX);
-}
-
-/*
- * Transmit as many characters to the HW as possible.
- *
- * This function will attempt to stuff of all the characters from the
- * kernel's transmit buffer into TX BDs.
- *
- * A return value of non-zero indicates that it successfully stuffed all
- * characters from the kernel buffer.
- *
- * A return value of zero indicates that there are still characters in the
- * kernel's buffer that have not been transmitted, but there are no more BDs
- * available. This function should be called again after a BD has been made
- * available.
- */
-static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
-{
- struct qe_bd *bdp;
- unsigned char *p;
- unsigned int count;
- struct uart_port *port = &qe_port->port;
- struct circ_buf *xmit = &port->state->xmit;
-
- bdp = qe_port->rx_cur;
-
- /* Handle xon/xoff */
- if (port->x_char) {
- /* Pick next descriptor and fill from buffer */
- bdp = qe_port->tx_cur;
-
- p = qe2cpu_addr(bdp->buf, qe_port);
-
- *p++ = port->x_char;
- out_be16(&bdp->length, 1);
- setbits16(&bdp->status, BD_SC_READY);
- /* Get next BD. */
- if (in_be16(&bdp->status) & BD_SC_WRAP)
- bdp = qe_port->tx_bd_base;
- else
- bdp++;
- qe_port->tx_cur = bdp;
-
- port->icount.tx++;
- port->x_char = 0;
- return 1;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- qe_uart_stop_tx(port);
- return 0;
- }
-
- /* Pick next descriptor and fill from buffer */
- bdp = qe_port->tx_cur;
-
- while (!(in_be16(&bdp->status) & BD_SC_READY) &&
- (xmit->tail != xmit->head)) {
- count = 0;
- p = qe2cpu_addr(bdp->buf, qe_port);
- while (count < qe_port->tx_fifosize) {
- *p++ = xmit->buf[xmit->tail];
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- count++;
- if (xmit->head == xmit->tail)
- break;
- }
-
- out_be16(&bdp->length, count);
- setbits16(&bdp->status, BD_SC_READY);
-
- /* Get next BD. */
- if (in_be16(&bdp->status) & BD_SC_WRAP)
- bdp = qe_port->tx_bd_base;
- else
- bdp++;
- }
- qe_port->tx_cur = bdp;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit)) {
- /* The kernel buffer is empty, so turn off TX interrupts. We
- don't need to be told when the QE is finished transmitting
- the data. */
- qe_uart_stop_tx(port);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Start transmitting data
- *
- * This function will start transmitting any available data, if the port
- * isn't already transmitting data.
- */
-static void qe_uart_start_tx(struct uart_port *port)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
-
- /* If we currently are transmitting, then just return */
- if (in_be16(&qe_port->uccp->uccm) & UCC_UART_UCCE_TX)
- return;
-
- /* Otherwise, pump the port and start transmission */
- if (qe_uart_tx_pump(qe_port))
- setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX);
-}
-
-/*
- * Stop transmitting data
- */
-static void qe_uart_stop_rx(struct uart_port *port)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
-
- clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
-}
-
-/*
- * Enable status change interrupts
- *
- * We don't support status change interrupts, but we need to define this
- * function otherwise the kernel will panic.
- */
-static void qe_uart_enable_ms(struct uart_port *port)
-{
-}
-
-/* Start or stop sending break signal
- *
- * This function controls the sending of a break signal. If break_state=1,
- * then we start sending a break signal. If break_state=0, then we stop
- * sending the break signal.
- */
-static void qe_uart_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
-
- if (break_state)
- ucc_slow_stop_tx(qe_port->us_private);
- else
- ucc_slow_restart_tx(qe_port->us_private);
-}
-
-/* ISR helper function for receiving character.
- *
- * This function is called by the ISR to handling receiving characters
- */
-static void qe_uart_int_rx(struct uart_qe_port *qe_port)
-{
- int i;
- unsigned char ch, *cp;
- struct uart_port *port = &qe_port->port;
- struct tty_struct *tty = port->state->port.tty;
- struct qe_bd *bdp;
- u16 status;
- unsigned int flg;
-
- /* Just loop through the closed BDs and copy the characters into
- * the buffer.
- */
- bdp = qe_port->rx_cur;
- while (1) {
- status = in_be16(&bdp->status);
-
- /* If this one is empty, then we assume we've read them all */
- if (status & BD_SC_EMPTY)
- break;
-
- /* get number of characters, and check space in RX buffer */
- i = in_be16(&bdp->length);
-
- /* If we don't have enough room in RX buffer for the entire BD,
- * then we try later, which will be the next RX interrupt.
- */
- if (tty_buffer_request_room(tty, i) < i) {
- dev_dbg(port->dev, "ucc-uart: no room in RX buffer\n");
- return;
- }
-
- /* get pointer */
- cp = qe2cpu_addr(bdp->buf, qe_port);
-
- /* loop through the buffer */
- while (i-- > 0) {
- ch = *cp++;
- port->icount.rx++;
- flg = TTY_NORMAL;
-
- if (!i && status &
- (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
- goto handle_error;
- if (uart_handle_sysrq_char(port, ch))
- continue;
-
-error_return:
- tty_insert_flip_char(tty, ch, flg);
-
- }
-
- /* This BD is ready to be used again. Clear status. get next */
- clrsetbits_be16(&bdp->status, BD_SC_BR | BD_SC_FR | BD_SC_PR |
- BD_SC_OV | BD_SC_ID, BD_SC_EMPTY);
- if (in_be16(&bdp->status) & BD_SC_WRAP)
- bdp = qe_port->rx_bd_base;
- else
- bdp++;
-
- }
-
- /* Write back buffer pointer */
- qe_port->rx_cur = bdp;
-
- /* Activate BH processing */
- tty_flip_buffer_push(tty);
-
- return;
-
- /* Error processing */
-
-handle_error:
- /* Statistics */
- if (status & BD_SC_BR)
- port->icount.brk++;
- if (status & BD_SC_PR)
- port->icount.parity++;
- if (status & BD_SC_FR)
- port->icount.frame++;
- if (status & BD_SC_OV)
- port->icount.overrun++;
-
- /* Mask out ignored conditions */
- status &= port->read_status_mask;
-
- /* Handle the remaining ones */
- if (status & BD_SC_BR)
- flg = TTY_BREAK;
- else if (status & BD_SC_PR)
- flg = TTY_PARITY;
- else if (status & BD_SC_FR)
- flg = TTY_FRAME;
-
- /* Overrun does not affect the current character ! */
- if (status & BD_SC_OV)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-#ifdef SUPPORT_SYSRQ
- port->sysrq = 0;
-#endif
- goto error_return;
-}
-
-/* Interrupt handler
- *
- * This interrupt handler is called after a BD is processed.
- */
-static irqreturn_t qe_uart_int(int irq, void *data)
-{
- struct uart_qe_port *qe_port = (struct uart_qe_port *) data;
- struct ucc_slow __iomem *uccp = qe_port->uccp;
- u16 events;
-
- /* Clear the interrupts */
- events = in_be16(&uccp->ucce);
- out_be16(&uccp->ucce, events);
-
- if (events & UCC_UART_UCCE_BRKE)
- uart_handle_break(&qe_port->port);
-
- if (events & UCC_UART_UCCE_RX)
- qe_uart_int_rx(qe_port);
-
- if (events & UCC_UART_UCCE_TX)
- qe_uart_tx_pump(qe_port);
-
- return events ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/* Initialize buffer descriptors
- *
- * This function initializes all of the RX and TX buffer descriptors.
- */
-static void qe_uart_initbd(struct uart_qe_port *qe_port)
-{
- int i;
- void *bd_virt;
- struct qe_bd *bdp;
-
- /* Set the physical address of the host memory buffers in the buffer
- * descriptors, and the virtual address for us to work with.
- */
- bd_virt = qe_port->bd_virt;
- bdp = qe_port->rx_bd_base;
- qe_port->rx_cur = qe_port->rx_bd_base;
- for (i = 0; i < (qe_port->rx_nrfifos - 1); i++) {
- out_be16(&bdp->status, BD_SC_EMPTY | BD_SC_INTRPT);
- out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
- out_be16(&bdp->length, 0);
- bd_virt += qe_port->rx_fifosize;
- bdp++;
- }
-
- /* */
- out_be16(&bdp->status, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT);
- out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
- out_be16(&bdp->length, 0);
-
- /* Set the physical address of the host memory
- * buffers in the buffer descriptors, and the
- * virtual address for us to work with.
- */
- bd_virt = qe_port->bd_virt +
- L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
- qe_port->tx_cur = qe_port->tx_bd_base;
- bdp = qe_port->tx_bd_base;
- for (i = 0; i < (qe_port->tx_nrfifos - 1); i++) {
- out_be16(&bdp->status, BD_SC_INTRPT);
- out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
- out_be16(&bdp->length, 0);
- bd_virt += qe_port->tx_fifosize;
- bdp++;
- }
-
- /* Loopback requires the preamble bit to be set on the first TX BD */
-#ifdef LOOPBACK
- setbits16(&qe_port->tx_cur->status, BD_SC_P);
-#endif
-
- out_be16(&bdp->status, BD_SC_WRAP | BD_SC_INTRPT);
- out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
- out_be16(&bdp->length, 0);
-}
-
-/*
- * Initialize a UCC for UART.
- *
- * This function configures a given UCC to be used as a UART device. Basic
- * UCC initialization is handled in qe_uart_request_port(). This function
- * does all the UART-specific stuff.
- */
-static void qe_uart_init_ucc(struct uart_qe_port *qe_port)
-{
- u32 cecr_subblock;
- struct ucc_slow __iomem *uccp = qe_port->uccp;
- struct ucc_uart_pram *uccup = qe_port->uccup;
-
- unsigned int i;
-
- /* First, disable TX and RX in the UCC */
- ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX);
-
- /* Program the UCC UART parameter RAM */
- out_8(&uccup->common.rbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
- out_8(&uccup->common.tbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
- out_be16(&uccup->common.mrblr, qe_port->rx_fifosize);
- out_be16(&uccup->maxidl, 0x10);
- out_be16(&uccup->brkcr, 1);
- out_be16(&uccup->parec, 0);
- out_be16(&uccup->frmec, 0);
- out_be16(&uccup->nosec, 0);
- out_be16(&uccup->brkec, 0);
- out_be16(&uccup->uaddr[0], 0);
- out_be16(&uccup->uaddr[1], 0);
- out_be16(&uccup->toseq, 0);
- for (i = 0; i < 8; i++)
- out_be16(&uccup->cchars[i], 0xC000);
- out_be16(&uccup->rccm, 0xc0ff);
-
- /* Configure the GUMR registers for UART */
- if (soft_uart) {
- /* Soft-UART requires a 1X multiplier for TX */
- clrsetbits_be32(&uccp->gumr_l,
- UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
- UCC_SLOW_GUMR_L_RDCR_MASK,
- UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_1 |
- UCC_SLOW_GUMR_L_RDCR_16);
-
- clrsetbits_be32(&uccp->gumr_h, UCC_SLOW_GUMR_H_RFW,
- UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX);
- } else {
- clrsetbits_be32(&uccp->gumr_l,
- UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
- UCC_SLOW_GUMR_L_RDCR_MASK,
- UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_16 |
- UCC_SLOW_GUMR_L_RDCR_16);
-
- clrsetbits_be32(&uccp->gumr_h,
- UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX,
- UCC_SLOW_GUMR_H_RFW);
- }
-
-#ifdef LOOPBACK
- clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK,
- UCC_SLOW_GUMR_L_DIAG_LOOP);
- clrsetbits_be32(&uccp->gumr_h,
- UCC_SLOW_GUMR_H_CTSP | UCC_SLOW_GUMR_H_RSYN,
- UCC_SLOW_GUMR_H_CDS);
-#endif
-
- /* Disable rx interrupts and clear all pending events. */
- out_be16(&uccp->uccm, 0);
- out_be16(&uccp->ucce, 0xffff);
- out_be16(&uccp->udsr, 0x7e7e);
-
- /* Initialize UPSMR */
- out_be16(&uccp->upsmr, 0);
-
- if (soft_uart) {
- out_be16(&uccup->supsmr, 0x30);
- out_be16(&uccup->res92, 0);
- out_be32(&uccup->rx_state, 0);
- out_be32(&uccup->rx_cnt, 0);
- out_8(&uccup->rx_bitmark, 0);
- out_8(&uccup->rx_length, 10);
- out_be32(&uccup->dump_ptr, 0x4000);
- out_8(&uccup->rx_temp_dlst_qe, 0);
- out_be32(&uccup->rx_frame_rem, 0);
- out_8(&uccup->rx_frame_rem_size, 0);
- /* Soft-UART requires TX to be 1X */
- out_8(&uccup->tx_mode,
- UCC_UART_TX_STATE_UART | UCC_UART_TX_STATE_X1);
- out_be16(&uccup->tx_state, 0);
- out_8(&uccup->resD4, 0);
- out_be16(&uccup->resD5, 0);
-
- /* Set UART mode.
- * Enable receive and transmit.
- */
-
- /* From the microcode errata:
- * 1.GUMR_L register, set mode=0010 (QMC).
- * 2.Set GUMR_H[17] bit. (UART/AHDLC mode).
- * 3.Set GUMR_H[19:20] (Transparent mode)
- * 4.Clear GUMR_H[26] (RFW)
- * ...
- * 6.Receiver must use 16x over sampling
- */
- clrsetbits_be32(&uccp->gumr_l,
- UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
- UCC_SLOW_GUMR_L_RDCR_MASK,
- UCC_SLOW_GUMR_L_MODE_QMC | UCC_SLOW_GUMR_L_TDCR_16 |
- UCC_SLOW_GUMR_L_RDCR_16);
-
- clrsetbits_be32(&uccp->gumr_h,
- UCC_SLOW_GUMR_H_RFW | UCC_SLOW_GUMR_H_RSYN,
- UCC_SLOW_GUMR_H_SUART | UCC_SLOW_GUMR_H_TRX |
- UCC_SLOW_GUMR_H_TTX | UCC_SLOW_GUMR_H_TFL);
-
-#ifdef LOOPBACK
- clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK,
- UCC_SLOW_GUMR_L_DIAG_LOOP);
- clrbits32(&uccp->gumr_h, UCC_SLOW_GUMR_H_CTSP |
- UCC_SLOW_GUMR_H_CDS);
-#endif
-
- cecr_subblock = ucc_slow_get_qe_cr_subblock(qe_port->ucc_num);
- qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
- QE_CR_PROTOCOL_UNSPECIFIED, 0);
- } else {
- cecr_subblock = ucc_slow_get_qe_cr_subblock(qe_port->ucc_num);
- qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
- QE_CR_PROTOCOL_UART, 0);
- }
-}
-
-/*
- * Initialize the port.
- */
-static int qe_uart_startup(struct uart_port *port)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
- int ret;
-
- /*
- * If we're using Soft-UART mode, then we need to make sure the
- * firmware has been uploaded first.
- */
- if (soft_uart && !firmware_loaded) {
- dev_err(port->dev, "Soft-UART firmware not uploaded\n");
- return -ENODEV;
- }
-
- qe_uart_initbd(qe_port);
- qe_uart_init_ucc(qe_port);
-
- /* Install interrupt handler. */
- ret = request_irq(port->irq, qe_uart_int, IRQF_SHARED, "ucc-uart",
- qe_port);
- if (ret) {
- dev_err(port->dev, "could not claim IRQ %u\n", port->irq);
- return ret;
- }
-
- /* Startup rx-int */
- setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
- ucc_slow_enable(qe_port->us_private, COMM_DIR_RX_AND_TX);
-
- return 0;
-}
-
-/*
- * Shutdown the port.
- */
-static void qe_uart_shutdown(struct uart_port *port)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
- struct ucc_slow __iomem *uccp = qe_port->uccp;
- unsigned int timeout = 20;
-
- /* Disable RX and TX */
-
- /* Wait for all the BDs marked sent */
- while (!qe_uart_tx_empty(port)) {
- if (!--timeout) {
- dev_warn(port->dev, "shutdown timeout\n");
- break;
- }
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(2);
- }
-
- if (qe_port->wait_closing) {
- /* Wait a bit longer */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(qe_port->wait_closing);
- }
-
- /* Stop uarts */
- ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX);
- clrbits16(&uccp->uccm, UCC_UART_UCCE_TX | UCC_UART_UCCE_RX);
-
- /* Shut them really down and reinit buffer descriptors */
- ucc_slow_graceful_stop_tx(qe_port->us_private);
- qe_uart_initbd(qe_port);
-
- free_irq(port->irq, qe_port);
-}
-
-/*
- * Set the serial port parameters.
- */
-static void qe_uart_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
- struct ucc_slow __iomem *uccp = qe_port->uccp;
- unsigned int baud;
- unsigned long flags;
- u16 upsmr = in_be16(&uccp->upsmr);
- struct ucc_uart_pram __iomem *uccup = qe_port->uccup;
- u16 supsmr = in_be16(&uccup->supsmr);
- u8 char_length = 2; /* 1 + CL + PEN + 1 + SL */
-
- /* Character length programmed into the mode register is the
- * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
- * 1 or 2 stop bits, minus 1.
- * The value 'bits' counts this for us.
- */
-
- /* byte size */
- upsmr &= UCC_UART_UPSMR_CL_MASK;
- supsmr &= UCC_UART_SUPSMR_CL_MASK;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- upsmr |= UCC_UART_UPSMR_CL_5;
- supsmr |= UCC_UART_SUPSMR_CL_5;
- char_length += 5;
- break;
- case CS6:
- upsmr |= UCC_UART_UPSMR_CL_6;
- supsmr |= UCC_UART_SUPSMR_CL_6;
- char_length += 6;
- break;
- case CS7:
- upsmr |= UCC_UART_UPSMR_CL_7;
- supsmr |= UCC_UART_SUPSMR_CL_7;
- char_length += 7;
- break;
- default: /* case CS8 */
- upsmr |= UCC_UART_UPSMR_CL_8;
- supsmr |= UCC_UART_SUPSMR_CL_8;
- char_length += 8;
- break;
- }
-
- /* If CSTOPB is set, we want two stop bits */
- if (termios->c_cflag & CSTOPB) {
- upsmr |= UCC_UART_UPSMR_SL;
- supsmr |= UCC_UART_SUPSMR_SL;
- char_length++; /* + SL */
- }
-
- if (termios->c_cflag & PARENB) {
- upsmr |= UCC_UART_UPSMR_PEN;
- supsmr |= UCC_UART_SUPSMR_PEN;
- char_length++; /* + PEN */
-
- if (!(termios->c_cflag & PARODD)) {
- upsmr &= ~(UCC_UART_UPSMR_RPM_MASK |
- UCC_UART_UPSMR_TPM_MASK);
- upsmr |= UCC_UART_UPSMR_RPM_EVEN |
- UCC_UART_UPSMR_TPM_EVEN;
- supsmr &= ~(UCC_UART_SUPSMR_RPM_MASK |
- UCC_UART_SUPSMR_TPM_MASK);
- supsmr |= UCC_UART_SUPSMR_RPM_EVEN |
- UCC_UART_SUPSMR_TPM_EVEN;
- }
- }
-
- /*
- * Set up parity check flag
- */
- port->read_status_mask = BD_SC_EMPTY | BD_SC_OV;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= BD_SC_FR | BD_SC_PR;
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= BD_SC_BR;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= BD_SC_BR;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= BD_SC_OV;
- }
- /*
- * !!! ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- port->read_status_mask &= ~BD_SC_EMPTY;
-
- baud = uart_get_baud_rate(port, termios, old, 0, 115200);
-
- /* Do we really need a spinlock here? */
- spin_lock_irqsave(&port->lock, flags);
-
- out_be16(&uccp->upsmr, upsmr);
- if (soft_uart) {
- out_be16(&uccup->supsmr, supsmr);
- out_8(&uccup->rx_length, char_length);
-
- /* Soft-UART requires a 1X multiplier for TX */
- qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
- qe_setbrg(qe_port->us_info.tx_clock, baud, 1);
- } else {
- qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
- qe_setbrg(qe_port->us_info.tx_clock, baud, 16);
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/*
- * Return a pointer to a string that describes what kind of port this is.
- */
-static const char *qe_uart_type(struct uart_port *port)
-{
- return "QE";
-}
-
-/*
- * Allocate any memory and I/O resources required by the port.
- */
-static int qe_uart_request_port(struct uart_port *port)
-{
- int ret;
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
- struct ucc_slow_info *us_info = &qe_port->us_info;
- struct ucc_slow_private *uccs;
- unsigned int rx_size, tx_size;
- void *bd_virt;
- dma_addr_t bd_dma_addr = 0;
-
- ret = ucc_slow_init(us_info, &uccs);
- if (ret) {
- dev_err(port->dev, "could not initialize UCC%u\n",
- qe_port->ucc_num);
- return ret;
- }
-
- qe_port->us_private = uccs;
- qe_port->uccp = uccs->us_regs;
- qe_port->uccup = (struct ucc_uart_pram *) uccs->us_pram;
- qe_port->rx_bd_base = uccs->rx_bd;
- qe_port->tx_bd_base = uccs->tx_bd;
-
- /*
- * Allocate the transmit and receive data buffers.
- */
-
- rx_size = L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
- tx_size = L1_CACHE_ALIGN(qe_port->tx_nrfifos * qe_port->tx_fifosize);
-
- bd_virt = dma_alloc_coherent(port->dev, rx_size + tx_size, &bd_dma_addr,
- GFP_KERNEL);
- if (!bd_virt) {
- dev_err(port->dev, "could not allocate buffer descriptors\n");
- return -ENOMEM;
- }
-
- qe_port->bd_virt = bd_virt;
- qe_port->bd_dma_addr = bd_dma_addr;
- qe_port->bd_size = rx_size + tx_size;
-
- qe_port->rx_buf = bd_virt;
- qe_port->tx_buf = qe_port->rx_buf + rx_size;
-
- return 0;
-}
-
-/*
- * Configure the port.
- *
- * We say we're a CPM-type port because that's mostly true. Once the device
- * is configured, this driver operates almost identically to the CPM serial
- * driver.
- */
-static void qe_uart_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_CPM;
- qe_uart_request_port(port);
- }
-}
-
-/*
- * Release any memory and I/O resources that were allocated in
- * qe_uart_request_port().
- */
-static void qe_uart_release_port(struct uart_port *port)
-{
- struct uart_qe_port *qe_port =
- container_of(port, struct uart_qe_port, port);
- struct ucc_slow_private *uccs = qe_port->us_private;
-
- dma_free_coherent(port->dev, qe_port->bd_size, qe_port->bd_virt,
- qe_port->bd_dma_addr);
-
- ucc_slow_free(uccs);
-}
-
-/*
- * Verify that the data in serial_struct is suitable for this device.
- */
-static int qe_uart_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
- return -EINVAL;
-
- if (ser->irq < 0 || ser->irq >= nr_irqs)
- return -EINVAL;
-
- if (ser->baud_base < 9600)
- return -EINVAL;
-
- return 0;
-}
-/* UART operations
- *
- * Details on these functions can be found in Documentation/serial/driver
- */
-static struct uart_ops qe_uart_pops = {
- .tx_empty = qe_uart_tx_empty,
- .set_mctrl = qe_uart_set_mctrl,
- .get_mctrl = qe_uart_get_mctrl,
- .stop_tx = qe_uart_stop_tx,
- .start_tx = qe_uart_start_tx,
- .stop_rx = qe_uart_stop_rx,
- .enable_ms = qe_uart_enable_ms,
- .break_ctl = qe_uart_break_ctl,
- .startup = qe_uart_startup,
- .shutdown = qe_uart_shutdown,
- .set_termios = qe_uart_set_termios,
- .type = qe_uart_type,
- .release_port = qe_uart_release_port,
- .request_port = qe_uart_request_port,
- .config_port = qe_uart_config_port,
- .verify_port = qe_uart_verify_port,
-};
-
-/*
- * Obtain the SOC model number and revision level
- *
- * This function parses the device tree to obtain the SOC model. It then
- * reads the SVR register to the revision.
- *
- * The device tree stores the SOC model two different ways.
- *
- * The new way is:
- *
- * cpu@0 {
- * compatible = "PowerPC,8323";
- * device_type = "cpu";
- * ...
- *
- *
- * The old way is:
- * PowerPC,8323@0 {
- * device_type = "cpu";
- * ...
- *
- * This code first checks the new way, and then the old way.
- */
-static unsigned int soc_info(unsigned int *rev_h, unsigned int *rev_l)
-{
- struct device_node *np;
- const char *soc_string;
- unsigned int svr;
- unsigned int soc;
-
- /* Find the CPU node */
- np = of_find_node_by_type(NULL, "cpu");
- if (!np)
- return 0;
- /* Find the compatible property */
- soc_string = of_get_property(np, "compatible", NULL);
- if (!soc_string)
- /* No compatible property, so try the name. */
- soc_string = np->name;
-
- /* Extract the SOC number from the "PowerPC," string */
- if ((sscanf(soc_string, "PowerPC,%u", &soc) != 1) || !soc)
- return 0;
-
- /* Get the revision from the SVR */
- svr = mfspr(SPRN_SVR);
- *rev_h = (svr >> 4) & 0xf;
- *rev_l = svr & 0xf;
-
- return soc;
-}
-
-/*
- * requst_firmware_nowait() callback function
- *
- * This function is called by the kernel when a firmware is made available,
- * or if it times out waiting for the firmware.
- */
-static void uart_firmware_cont(const struct firmware *fw, void *context)
-{
- struct qe_firmware *firmware;
- struct device *dev = context;
- int ret;
-
- if (!fw) {
- dev_err(dev, "firmware not found\n");
- return;
- }
-
- firmware = (struct qe_firmware *) fw->data;
-
- if (firmware->header.length != fw->size) {
- dev_err(dev, "invalid firmware\n");
- goto out;
- }
-
- ret = qe_upload_firmware(firmware);
- if (ret) {
- dev_err(dev, "could not load firmware\n");
- goto out;
- }
-
- firmware_loaded = 1;
- out:
- release_firmware(fw);
-}
-
-static int ucc_uart_probe(struct platform_device *ofdev,
- const struct of_device_id *match)
-{
- struct device_node *np = ofdev->dev.of_node;
- const unsigned int *iprop; /* Integer OF properties */
- const char *sprop; /* String OF properties */
- struct uart_qe_port *qe_port = NULL;
- struct resource res;
- int ret;
-
- /*
- * Determine if we need Soft-UART mode
- */
- if (of_find_property(np, "soft-uart", NULL)) {
- dev_dbg(&ofdev->dev, "using Soft-UART mode\n");
- soft_uart = 1;
- }
-
- /*
- * If we are using Soft-UART, determine if we need to upload the
- * firmware, too.
- */
- if (soft_uart) {
- struct qe_firmware_info *qe_fw_info;
-
- qe_fw_info = qe_get_firmware_info();
-
- /* Check if the firmware has been uploaded. */
- if (qe_fw_info && strstr(qe_fw_info->id, "Soft-UART")) {
- firmware_loaded = 1;
- } else {
- char filename[32];
- unsigned int soc;
- unsigned int rev_h;
- unsigned int rev_l;
-
- soc = soc_info(&rev_h, &rev_l);
- if (!soc) {
- dev_err(&ofdev->dev, "unknown CPU model\n");
- return -ENXIO;
- }
- sprintf(filename, "fsl_qe_ucode_uart_%u_%u%u.bin",
- soc, rev_h, rev_l);
-
- dev_info(&ofdev->dev, "waiting for firmware %s\n",
- filename);
-
- /*
- * We call request_firmware_nowait instead of
- * request_firmware so that the driver can load and
- * initialize the ports without holding up the rest of
- * the kernel. If hotplug support is enabled in the
- * kernel, then we use it.
- */
- ret = request_firmware_nowait(THIS_MODULE,
- FW_ACTION_HOTPLUG, filename, &ofdev->dev,
- GFP_KERNEL, &ofdev->dev, uart_firmware_cont);
- if (ret) {
- dev_err(&ofdev->dev,
- "could not load firmware %s\n",
- filename);
- return ret;
- }
- }
- }
-
- qe_port = kzalloc(sizeof(struct uart_qe_port), GFP_KERNEL);
- if (!qe_port) {
- dev_err(&ofdev->dev, "can't allocate QE port structure\n");
- return -ENOMEM;
- }
-
- /* Search for IRQ and mapbase */
- ret = of_address_to_resource(np, 0, &res);
- if (ret) {
- dev_err(&ofdev->dev, "missing 'reg' property in device tree\n");
- kfree(qe_port);
- return ret;
- }
- if (!res.start) {
- dev_err(&ofdev->dev, "invalid 'reg' property in device tree\n");
- kfree(qe_port);
- return -EINVAL;
- }
- qe_port->port.mapbase = res.start;
-
- /* Get the UCC number (device ID) */
- /* UCCs are numbered 1-7 */
- iprop = of_get_property(np, "cell-index", NULL);
- if (!iprop) {
- iprop = of_get_property(np, "device-id", NULL);
- if (!iprop) {
- kfree(qe_port);
- dev_err(&ofdev->dev, "UCC is unspecified in "
- "device tree\n");
- return -EINVAL;
- }
- }
-
- if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
- dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop);
- kfree(qe_port);
- return -ENODEV;
- }
- qe_port->ucc_num = *iprop - 1;
-
- /*
- * In the future, we should not require the BRG to be specified in the
- * device tree. If no clock-source is specified, then just pick a BRG
- * to use. This requires a new QE library function that manages BRG
- * assignments.
- */
-
- sprop = of_get_property(np, "rx-clock-name", NULL);
- if (!sprop) {
- dev_err(&ofdev->dev, "missing rx-clock-name in device tree\n");
- kfree(qe_port);
- return -ENODEV;
- }
-
- qe_port->us_info.rx_clock = qe_clock_source(sprop);
- if ((qe_port->us_info.rx_clock < QE_BRG1) ||
- (qe_port->us_info.rx_clock > QE_BRG16)) {
- dev_err(&ofdev->dev, "rx-clock-name must be a BRG for UART\n");
- kfree(qe_port);
- return -ENODEV;
- }
-
-#ifdef LOOPBACK
- /* In internal loopback mode, TX and RX must use the same clock */
- qe_port->us_info.tx_clock = qe_port->us_info.rx_clock;
-#else
- sprop = of_get_property(np, "tx-clock-name", NULL);
- if (!sprop) {
- dev_err(&ofdev->dev, "missing tx-clock-name in device tree\n");
- kfree(qe_port);
- return -ENODEV;
- }
- qe_port->us_info.tx_clock = qe_clock_source(sprop);
-#endif
- if ((qe_port->us_info.tx_clock < QE_BRG1) ||
- (qe_port->us_info.tx_clock > QE_BRG16)) {
- dev_err(&ofdev->dev, "tx-clock-name must be a BRG for UART\n");
- kfree(qe_port);
- return -ENODEV;
- }
-
- /* Get the port number, numbered 0-3 */
- iprop = of_get_property(np, "port-number", NULL);
- if (!iprop) {
- dev_err(&ofdev->dev, "missing port-number in device tree\n");
- kfree(qe_port);
- return -EINVAL;
- }
- qe_port->port.line = *iprop;
- if (qe_port->port.line >= UCC_MAX_UART) {
- dev_err(&ofdev->dev, "port-number must be 0-%u\n",
- UCC_MAX_UART - 1);
- kfree(qe_port);
- return -EINVAL;
- }
-
- qe_port->port.irq = irq_of_parse_and_map(np, 0);
- if (qe_port->port.irq == NO_IRQ) {
- dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n",
- qe_port->ucc_num + 1);
- kfree(qe_port);
- return -EINVAL;
- }
-
- /*
- * Newer device trees have an "fsl,qe" compatible property for the QE
- * node, but we still need to support older device trees.
- */
- np = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!np) {
- np = of_find_node_by_type(NULL, "qe");
- if (!np) {
- dev_err(&ofdev->dev, "could not find 'qe' node\n");
- kfree(qe_port);
- return -EINVAL;
- }
- }
-
- iprop = of_get_property(np, "brg-frequency", NULL);
- if (!iprop) {
- dev_err(&ofdev->dev,
- "missing brg-frequency in device tree\n");
- kfree(qe_port);
- return -EINVAL;
- }
-
- if (*iprop)
- qe_port->port.uartclk = *iprop;
- else {
- /*
- * Older versions of U-Boot do not initialize the brg-frequency
- * property, so in this case we assume the BRG frequency is
- * half the QE bus frequency.
- */
- iprop = of_get_property(np, "bus-frequency", NULL);
- if (!iprop) {
- dev_err(&ofdev->dev,
- "missing QE bus-frequency in device tree\n");
- kfree(qe_port);
- return -EINVAL;
- }
- if (*iprop)
- qe_port->port.uartclk = *iprop / 2;
- else {
- dev_err(&ofdev->dev,
- "invalid QE bus-frequency in device tree\n");
- kfree(qe_port);
- return -EINVAL;
- }
- }
-
- spin_lock_init(&qe_port->port.lock);
- qe_port->np = np;
- qe_port->port.dev = &ofdev->dev;
- qe_port->port.ops = &qe_uart_pops;
- qe_port->port.iotype = UPIO_MEM;
-
- qe_port->tx_nrfifos = TX_NUM_FIFO;
- qe_port->tx_fifosize = TX_BUF_SIZE;
- qe_port->rx_nrfifos = RX_NUM_FIFO;
- qe_port->rx_fifosize = RX_BUF_SIZE;
-
- qe_port->wait_closing = UCC_WAIT_CLOSING;
- qe_port->port.fifosize = 512;
- qe_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
-
- qe_port->us_info.ucc_num = qe_port->ucc_num;
- qe_port->us_info.regs = (phys_addr_t) res.start;
- qe_port->us_info.irq = qe_port->port.irq;
-
- qe_port->us_info.rx_bd_ring_len = qe_port->rx_nrfifos;
- qe_port->us_info.tx_bd_ring_len = qe_port->tx_nrfifos;
-
- /* Make sure ucc_slow_init() initializes both TX and RX */
- qe_port->us_info.init_tx = 1;
- qe_port->us_info.init_rx = 1;
-
- /* Add the port to the uart sub-system. This will cause
- * qe_uart_config_port() to be called, so the us_info structure must
- * be initialized.
- */
- ret = uart_add_one_port(&ucc_uart_driver, &qe_port->port);
- if (ret) {
- dev_err(&ofdev->dev, "could not add /dev/ttyQE%u\n",
- qe_port->port.line);
- kfree(qe_port);
- return ret;
- }
-
- dev_set_drvdata(&ofdev->dev, qe_port);
-
- dev_info(&ofdev->dev, "UCC%u assigned to /dev/ttyQE%u\n",
- qe_port->ucc_num + 1, qe_port->port.line);
-
- /* Display the mknod command for this device */
- dev_dbg(&ofdev->dev, "mknod command is 'mknod /dev/ttyQE%u c %u %u'\n",
- qe_port->port.line, SERIAL_QE_MAJOR,
- SERIAL_QE_MINOR + qe_port->port.line);
-
- return 0;
-}
-
-static int ucc_uart_remove(struct platform_device *ofdev)
-{
- struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev);
-
- dev_info(&ofdev->dev, "removing /dev/ttyQE%u\n", qe_port->port.line);
-
- uart_remove_one_port(&ucc_uart_driver, &qe_port->port);
-
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(qe_port);
-
- return 0;
-}
-
-static struct of_device_id ucc_uart_match[] = {
- {
- .type = "serial",
- .compatible = "ucc_uart",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, ucc_uart_match);
-
-static struct of_platform_driver ucc_uart_of_driver = {
- .driver = {
- .name = "ucc_uart",
- .owner = THIS_MODULE,
- .of_match_table = ucc_uart_match,
- },
- .probe = ucc_uart_probe,
- .remove = ucc_uart_remove,
-};
-
-static int __init ucc_uart_init(void)
-{
- int ret;
-
- printk(KERN_INFO "Freescale QUICC Engine UART device driver\n");
-#ifdef LOOPBACK
- printk(KERN_INFO "ucc-uart: Using loopback mode\n");
-#endif
-
- ret = uart_register_driver(&ucc_uart_driver);
- if (ret) {
- printk(KERN_ERR "ucc-uart: could not register UART driver\n");
- return ret;
- }
-
- ret = of_register_platform_driver(&ucc_uart_of_driver);
- if (ret)
- printk(KERN_ERR
- "ucc-uart: could not register platform driver\n");
-
- return ret;
-}
-
-static void __exit ucc_uart_exit(void)
-{
- printk(KERN_INFO
- "Freescale QUICC Engine UART device driver unloading\n");
-
- of_unregister_platform_driver(&ucc_uart_of_driver);
- uart_unregister_driver(&ucc_uart_driver);
-}
-
-module_init(ucc_uart_init);
-module_exit(ucc_uart_exit);
-
-MODULE_DESCRIPTION("Freescale QUICC Engine (QE) UART");
-MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_QE_MAJOR);
-
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
deleted file mode 100644
index 3beb6ab4fa68..000000000000
--- a/drivers/serial/vr41xx_siu.c
+++ /dev/null
@@ -1,978 +0,0 @@
-/*
- * Driver for NEC VR4100 series Serial Interface Unit.
- *
- * Copyright (C) 2004-2008 Yoichi Yuasa <yuasa@linux-mips.org>
- *
- * Based on drivers/serial/8250.c, by Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#if defined(CONFIG_SERIAL_VR41XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/console.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-
-#include <asm/io.h>
-#include <asm/vr41xx/siu.h>
-#include <asm/vr41xx/vr41xx.h>
-
-#define SIU_BAUD_BASE 1152000
-#define SIU_MAJOR 204
-#define SIU_MINOR_BASE 82
-
-#define RX_MAX_COUNT 256
-#define TX_MAX_COUNT 15
-
-#define SIUIRSEL 0x08
- #define TMICMODE 0x20
- #define TMICTX 0x10
- #define IRMSEL 0x0c
- #define IRMSEL_HP 0x08
- #define IRMSEL_TEMIC 0x04
- #define IRMSEL_SHARP 0x00
- #define IRUSESEL 0x02
- #define SIRSEL 0x01
-
-static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
- [0 ... SIU_PORTS_MAX-1] = {
- .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
- .irq = -1,
- },
-};
-
-#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
-static uint8_t lsr_break_flag[SIU_PORTS_MAX];
-#endif
-
-#define siu_read(port, offset) readb((port)->membase + (offset))
-#define siu_write(port, offset, value) writeb((value), (port)->membase + (offset))
-
-void vr41xx_select_siu_interface(siu_interface_t interface)
-{
- struct uart_port *port;
- unsigned long flags;
- uint8_t irsel;
-
- port = &siu_uart_ports[0];
-
- spin_lock_irqsave(&port->lock, flags);
-
- irsel = siu_read(port, SIUIRSEL);
- if (interface == SIU_INTERFACE_IRDA)
- irsel |= SIRSEL;
- else
- irsel &= ~SIRSEL;
- siu_write(port, SIUIRSEL, irsel);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
-
-void vr41xx_use_irda(irda_use_t use)
-{
- struct uart_port *port;
- unsigned long flags;
- uint8_t irsel;
-
- port = &siu_uart_ports[0];
-
- spin_lock_irqsave(&port->lock, flags);
-
- irsel = siu_read(port, SIUIRSEL);
- if (use == FIR_USE_IRDA)
- irsel |= IRUSESEL;
- else
- irsel &= ~IRUSESEL;
- siu_write(port, SIUIRSEL, irsel);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-EXPORT_SYMBOL_GPL(vr41xx_use_irda);
-
-void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
-{
- struct uart_port *port;
- unsigned long flags;
- uint8_t irsel;
-
- port = &siu_uart_ports[0];
-
- spin_lock_irqsave(&port->lock, flags);
-
- irsel = siu_read(port, SIUIRSEL);
- irsel &= ~(IRMSEL | TMICTX | TMICMODE);
- switch (module) {
- case SHARP_IRDA:
- irsel |= IRMSEL_SHARP;
- break;
- case TEMIC_IRDA:
- irsel |= IRMSEL_TEMIC | TMICMODE;
- if (speed == IRDA_TX_4MBPS)
- irsel |= TMICTX;
- break;
- case HP_IRDA:
- irsel |= IRMSEL_HP;
- break;
- default:
- break;
- }
- siu_write(port, SIUIRSEL, irsel);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
-
-static inline void siu_clear_fifo(struct uart_port *port)
-{
- siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO);
- siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT);
- siu_write(port, UART_FCR, 0);
-}
-
-static inline unsigned long siu_port_size(struct uart_port *port)
-{
- switch (port->type) {
- case PORT_VR41XX_SIU:
- return 11UL;
- case PORT_VR41XX_DSIU:
- return 8UL;
- }
-
- return 0;
-}
-
-static inline unsigned int siu_check_type(struct uart_port *port)
-{
- if (port->line == 0)
- return PORT_VR41XX_SIU;
- if (port->line == 1 && port->irq != -1)
- return PORT_VR41XX_DSIU;
-
- return PORT_UNKNOWN;
-}
-
-static inline const char *siu_type_name(struct uart_port *port)
-{
- switch (port->type) {
- case PORT_VR41XX_SIU:
- return "SIU";
- case PORT_VR41XX_DSIU:
- return "DSIU";
- }
-
- return NULL;
-}
-
-static unsigned int siu_tx_empty(struct uart_port *port)
-{
- uint8_t lsr;
-
- lsr = siu_read(port, UART_LSR);
- if (lsr & UART_LSR_TEMT)
- return TIOCSER_TEMT;
-
- return 0;
-}
-
-static void siu_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- uint8_t mcr = 0;
-
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- siu_write(port, UART_MCR, mcr);
-}
-
-static unsigned int siu_get_mctrl(struct uart_port *port)
-{
- uint8_t msr;
- unsigned int mctrl = 0;
-
- msr = siu_read(port, UART_MSR);
- if (msr & UART_MSR_DCD)
- mctrl |= TIOCM_CAR;
- if (msr & UART_MSR_RI)
- mctrl |= TIOCM_RNG;
- if (msr & UART_MSR_DSR)
- mctrl |= TIOCM_DSR;
- if (msr & UART_MSR_CTS)
- mctrl |= TIOCM_CTS;
-
- return mctrl;
-}
-
-static void siu_stop_tx(struct uart_port *port)
-{
- unsigned long flags;
- uint8_t ier;
-
- spin_lock_irqsave(&port->lock, flags);
-
- ier = siu_read(port, UART_IER);
- ier &= ~UART_IER_THRI;
- siu_write(port, UART_IER, ier);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void siu_start_tx(struct uart_port *port)
-{
- unsigned long flags;
- uint8_t ier;
-
- spin_lock_irqsave(&port->lock, flags);
-
- ier = siu_read(port, UART_IER);
- ier |= UART_IER_THRI;
- siu_write(port, UART_IER, ier);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void siu_stop_rx(struct uart_port *port)
-{
- unsigned long flags;
- uint8_t ier;
-
- spin_lock_irqsave(&port->lock, flags);
-
- ier = siu_read(port, UART_IER);
- ier &= ~UART_IER_RLSI;
- siu_write(port, UART_IER, ier);
-
- port->read_status_mask &= ~UART_LSR_DR;
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void siu_enable_ms(struct uart_port *port)
-{
- unsigned long flags;
- uint8_t ier;
-
- spin_lock_irqsave(&port->lock, flags);
-
- ier = siu_read(port, UART_IER);
- ier |= UART_IER_MSI;
- siu_write(port, UART_IER, ier);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void siu_break_ctl(struct uart_port *port, int ctl)
-{
- unsigned long flags;
- uint8_t lcr;
-
- spin_lock_irqsave(&port->lock, flags);
-
- lcr = siu_read(port, UART_LCR);
- if (ctl == -1)
- lcr |= UART_LCR_SBC;
- else
- lcr &= ~UART_LCR_SBC;
- siu_write(port, UART_LCR, lcr);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static inline void receive_chars(struct uart_port *port, uint8_t *status)
-{
- struct tty_struct *tty;
- uint8_t lsr, ch;
- char flag;
- int max_count = RX_MAX_COUNT;
-
- tty = port->state->port.tty;
- lsr = *status;
-
- do {
- ch = siu_read(port, UART_RX);
- port->icount.rx++;
- flag = TTY_NORMAL;
-
-#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
- lsr |= lsr_break_flag[port->line];
- lsr_break_flag[port->line] = 0;
-#endif
- if (unlikely(lsr & (UART_LSR_BI | UART_LSR_FE |
- UART_LSR_PE | UART_LSR_OE))) {
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- port->icount.brk++;
-
- if (uart_handle_break(port))
- goto ignore_char;
- }
-
- if (lsr & UART_LSR_FE)
- port->icount.frame++;
- if (lsr & UART_LSR_PE)
- port->icount.parity++;
- if (lsr & UART_LSR_OE)
- port->icount.overrun++;
-
- lsr &= port->read_status_mask;
- if (lsr & UART_LSR_BI)
- flag = TTY_BREAK;
- if (lsr & UART_LSR_FE)
- flag = TTY_FRAME;
- if (lsr & UART_LSR_PE)
- flag = TTY_PARITY;
- }
-
- if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
-
- uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
-
- ignore_char:
- lsr = siu_read(port, UART_LSR);
- } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
-
- tty_flip_buffer_push(tty);
-
- *status = lsr;
-}
-
-static inline void check_modem_status(struct uart_port *port)
-{
- uint8_t msr;
-
- msr = siu_read(port, UART_MSR);
- if ((msr & UART_MSR_ANY_DELTA) == 0)
- return;
- if (msr & UART_MSR_DDCD)
- uart_handle_dcd_change(port, msr & UART_MSR_DCD);
- if (msr & UART_MSR_TERI)
- port->icount.rng++;
- if (msr & UART_MSR_DDSR)
- port->icount.dsr++;
- if (msr & UART_MSR_DCTS)
- uart_handle_cts_change(port, msr & UART_MSR_CTS);
-
- wake_up_interruptible(&port->state->port.delta_msr_wait);
-}
-
-static inline void transmit_chars(struct uart_port *port)
-{
- struct circ_buf *xmit;
- int max_count = TX_MAX_COUNT;
-
- xmit = &port->state->xmit;
-
- if (port->x_char) {
- siu_write(port, UART_TX, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- siu_stop_tx(port);
- return;
- }
-
- do {
- siu_write(port, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (max_count-- > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- siu_stop_tx(port);
-}
-
-static irqreturn_t siu_interrupt(int irq, void *dev_id)
-{
- struct uart_port *port;
- uint8_t iir, lsr;
-
- port = (struct uart_port *)dev_id;
-
- iir = siu_read(port, UART_IIR);
- if (iir & UART_IIR_NO_INT)
- return IRQ_NONE;
-
- lsr = siu_read(port, UART_LSR);
- if (lsr & UART_LSR_DR)
- receive_chars(port, &lsr);
-
- check_modem_status(port);
-
- if (lsr & UART_LSR_THRE)
- transmit_chars(port);
-
- return IRQ_HANDLED;
-}
-
-static int siu_startup(struct uart_port *port)
-{
- int retval;
-
- if (port->membase == NULL)
- return -ENODEV;
-
- siu_clear_fifo(port);
-
- (void)siu_read(port, UART_LSR);
- (void)siu_read(port, UART_RX);
- (void)siu_read(port, UART_IIR);
- (void)siu_read(port, UART_MSR);
-
- if (siu_read(port, UART_LSR) == 0xff)
- return -ENODEV;
-
- retval = request_irq(port->irq, siu_interrupt, 0, siu_type_name(port), port);
- if (retval)
- return retval;
-
- if (port->type == PORT_VR41XX_DSIU)
- vr41xx_enable_dsiuint(DSIUINT_ALL);
-
- siu_write(port, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irq(&port->lock);
- siu_set_mctrl(port, port->mctrl);
- spin_unlock_irq(&port->lock);
-
- siu_write(port, UART_IER, UART_IER_RLSI | UART_IER_RDI);
-
- (void)siu_read(port, UART_LSR);
- (void)siu_read(port, UART_RX);
- (void)siu_read(port, UART_IIR);
- (void)siu_read(port, UART_MSR);
-
- return 0;
-}
-
-static void siu_shutdown(struct uart_port *port)
-{
- unsigned long flags;
- uint8_t lcr;
-
- siu_write(port, UART_IER, 0);
-
- spin_lock_irqsave(&port->lock, flags);
-
- port->mctrl &= ~TIOCM_OUT2;
- siu_set_mctrl(port, port->mctrl);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- lcr = siu_read(port, UART_LCR);
- lcr &= ~UART_LCR_SBC;
- siu_write(port, UART_LCR, lcr);
-
- siu_clear_fifo(port);
-
- (void)siu_read(port, UART_RX);
-
- if (port->type == PORT_VR41XX_DSIU)
- vr41xx_disable_dsiuint(DSIUINT_ALL);
-
- free_irq(port->irq, port);
-}
-
-static void siu_set_termios(struct uart_port *port, struct ktermios *new,
- struct ktermios *old)
-{
- tcflag_t c_cflag, c_iflag;
- uint8_t lcr, fcr, ier;
- unsigned int baud, quot;
- unsigned long flags;
-
- c_cflag = new->c_cflag;
- switch (c_cflag & CSIZE) {
- case CS5:
- lcr = UART_LCR_WLEN5;
- break;
- case CS6:
- lcr = UART_LCR_WLEN6;
- break;
- case CS7:
- lcr = UART_LCR_WLEN7;
- break;
- default:
- lcr = UART_LCR_WLEN8;
- break;
- }
-
- if (c_cflag & CSTOPB)
- lcr |= UART_LCR_STOP;
- if (c_cflag & PARENB)
- lcr |= UART_LCR_PARITY;
- if ((c_cflag & PARODD) != PARODD)
- lcr |= UART_LCR_EPAR;
- if (c_cflag & CMSPAR)
- lcr |= UART_LCR_SPAR;
-
- baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
-
- spin_lock_irqsave(&port->lock, flags);
-
- uart_update_timeout(port, c_cflag, baud);
-
- c_iflag = new->c_iflag;
-
- port->read_status_mask = UART_LSR_THRE | UART_LSR_OE | UART_LSR_DR;
- if (c_iflag & INPCK)
- port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= UART_LSR_BI;
-
- port->ignore_status_mask = 0;
- if (c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (c_iflag & IGNBRK) {
- port->ignore_status_mask |= UART_LSR_BI;
- if (c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_LSR_OE;
- }
-
- if ((c_cflag & CREAD) == 0)
- port->ignore_status_mask |= UART_LSR_DR;
-
- ier = siu_read(port, UART_IER);
- ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(port, c_cflag))
- ier |= UART_IER_MSI;
- siu_write(port, UART_IER, ier);
-
- siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
-
- siu_write(port, UART_DLL, (uint8_t)quot);
- siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
-
- siu_write(port, UART_LCR, lcr);
-
- siu_write(port, UART_FCR, fcr);
-
- siu_set_mctrl(port, port->mctrl);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void siu_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
-{
- switch (state) {
- case 0:
- switch (port->type) {
- case PORT_VR41XX_SIU:
- vr41xx_supply_clock(SIU_CLOCK);
- break;
- case PORT_VR41XX_DSIU:
- vr41xx_supply_clock(DSIU_CLOCK);
- break;
- }
- break;
- case 3:
- switch (port->type) {
- case PORT_VR41XX_SIU:
- vr41xx_mask_clock(SIU_CLOCK);
- break;
- case PORT_VR41XX_DSIU:
- vr41xx_mask_clock(DSIU_CLOCK);
- break;
- }
- break;
- }
-}
-
-static const char *siu_type(struct uart_port *port)
-{
- return siu_type_name(port);
-}
-
-static void siu_release_port(struct uart_port *port)
-{
- unsigned long size;
-
- if (port->flags & UPF_IOREMAP) {
- iounmap(port->membase);
- port->membase = NULL;
- }
-
- size = siu_port_size(port);
- release_mem_region(port->mapbase, size);
-}
-
-static int siu_request_port(struct uart_port *port)
-{
- unsigned long size;
- struct resource *res;
-
- size = siu_port_size(port);
- res = request_mem_region(port->mapbase, size, siu_type_name(port));
- if (res == NULL)
- return -EBUSY;
-
- if (port->flags & UPF_IOREMAP) {
- port->membase = ioremap(port->mapbase, size);
- if (port->membase == NULL) {
- release_resource(res);
- return -ENOMEM;
- }
- }
-
- return 0;
-}
-
-static void siu_config_port(struct uart_port *port, int flags)
-{
- if (flags & UART_CONFIG_TYPE) {
- port->type = siu_check_type(port);
- (void)siu_request_port(port);
- }
-}
-
-static int siu_verify_port(struct uart_port *port, struct serial_struct *serial)
-{
- if (port->type != PORT_VR41XX_SIU && port->type != PORT_VR41XX_DSIU)
- return -EINVAL;
- if (port->irq != serial->irq)
- return -EINVAL;
- if (port->iotype != serial->io_type)
- return -EINVAL;
- if (port->mapbase != (unsigned long)serial->iomem_base)
- return -EINVAL;
-
- return 0;
-}
-
-static struct uart_ops siu_uart_ops = {
- .tx_empty = siu_tx_empty,
- .set_mctrl = siu_set_mctrl,
- .get_mctrl = siu_get_mctrl,
- .stop_tx = siu_stop_tx,
- .start_tx = siu_start_tx,
- .stop_rx = siu_stop_rx,
- .enable_ms = siu_enable_ms,
- .break_ctl = siu_break_ctl,
- .startup = siu_startup,
- .shutdown = siu_shutdown,
- .set_termios = siu_set_termios,
- .pm = siu_pm,
- .type = siu_type,
- .release_port = siu_release_port,
- .request_port = siu_request_port,
- .config_port = siu_config_port,
- .verify_port = siu_verify_port,
-};
-
-static int siu_init_ports(struct platform_device *pdev)
-{
- struct uart_port *port;
- struct resource *res;
- int *type = pdev->dev.platform_data;
- int i;
-
- if (!type)
- return 0;
-
- port = siu_uart_ports;
- for (i = 0; i < SIU_PORTS_MAX; i++) {
- port->type = type[i];
- if (port->type == PORT_UNKNOWN)
- continue;
- port->irq = platform_get_irq(pdev, i);
- port->uartclk = SIU_BAUD_BASE * 16;
- port->fifosize = 16;
- port->regshift = 0;
- port->iotype = UPIO_MEM;
- port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
- port->line = i;
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- port->mapbase = res->start;
- port++;
- }
-
- return i;
-}
-
-#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static void wait_for_xmitr(struct uart_port *port)
-{
- int timeout = 10000;
- uint8_t lsr, msr;
-
- do {
- lsr = siu_read(port, UART_LSR);
- if (lsr & UART_LSR_BI)
- lsr_break_flag[port->line] = UART_LSR_BI;
-
- if ((lsr & BOTH_EMPTY) == BOTH_EMPTY)
- break;
- } while (timeout-- > 0);
-
- if (port->flags & UPF_CONS_FLOW) {
- timeout = 1000000;
-
- do {
- msr = siu_read(port, UART_MSR);
- if ((msr & UART_MSR_CTS) != 0)
- break;
- } while (timeout-- > 0);
- }
-}
-
-static void siu_console_putchar(struct uart_port *port, int ch)
-{
- wait_for_xmitr(port);
- siu_write(port, UART_TX, ch);
-}
-
-static void siu_console_write(struct console *con, const char *s, unsigned count)
-{
- struct uart_port *port;
- uint8_t ier;
-
- port = &siu_uart_ports[con->index];
-
- ier = siu_read(port, UART_IER);
- siu_write(port, UART_IER, 0);
-
- uart_console_write(port, s, count, siu_console_putchar);
-
- wait_for_xmitr(port);
- siu_write(port, UART_IER, ier);
-}
-
-static int __init siu_console_setup(struct console *con, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int parity = 'n';
- int bits = 8;
- int flow = 'n';
-
- if (con->index >= SIU_PORTS_MAX)
- con->index = 0;
-
- port = &siu_uart_ports[con->index];
- if (port->membase == NULL) {
- if (port->mapbase == 0)
- return -ENODEV;
- port->membase = ioremap(port->mapbase, siu_port_size(port));
- }
-
- if (port->type == PORT_VR41XX_SIU)
- vr41xx_select_siu_interface(SIU_INTERFACE_RS232C);
-
- if (options != NULL)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, con, baud, parity, bits, flow);
-}
-
-static struct uart_driver siu_uart_driver;
-
-static struct console siu_console = {
- .name = "ttyVR",
- .write = siu_console_write,
- .device = uart_console_device,
- .setup = siu_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &siu_uart_driver,
-};
-
-static int __devinit siu_console_init(void)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; i < SIU_PORTS_MAX; i++) {
- port = &siu_uart_ports[i];
- port->ops = &siu_uart_ops;
- }
-
- register_console(&siu_console);
-
- return 0;
-}
-
-console_initcall(siu_console_init);
-
-void __init vr41xx_siu_early_setup(struct uart_port *port)
-{
- if (port->type == PORT_UNKNOWN)
- return;
-
- siu_uart_ports[port->line].line = port->line;
- siu_uart_ports[port->line].type = port->type;
- siu_uart_ports[port->line].uartclk = SIU_BAUD_BASE * 16;
- siu_uart_ports[port->line].mapbase = port->mapbase;
- siu_uart_ports[port->line].mapbase = port->mapbase;
- siu_uart_ports[port->line].ops = &siu_uart_ops;
-}
-
-#define SERIAL_VR41XX_CONSOLE &siu_console
-#else
-#define SERIAL_VR41XX_CONSOLE NULL
-#endif
-
-static struct uart_driver siu_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "SIU",
- .dev_name = "ttyVR",
- .major = SIU_MAJOR,
- .minor = SIU_MINOR_BASE,
- .cons = SERIAL_VR41XX_CONSOLE,
-};
-
-static int __devinit siu_probe(struct platform_device *dev)
-{
- struct uart_port *port;
- int num, i, retval;
-
- num = siu_init_ports(dev);
- if (num <= 0)
- return -ENODEV;
-
- siu_uart_driver.nr = num;
- retval = uart_register_driver(&siu_uart_driver);
- if (retval)
- return retval;
-
- for (i = 0; i < num; i++) {
- port = &siu_uart_ports[i];
- port->ops = &siu_uart_ops;
- port->dev = &dev->dev;
-
- retval = uart_add_one_port(&siu_uart_driver, port);
- if (retval < 0) {
- port->dev = NULL;
- break;
- }
- }
-
- if (i == 0 && retval < 0) {
- uart_unregister_driver(&siu_uart_driver);
- return retval;
- }
-
- return 0;
-}
-
-static int __devexit siu_remove(struct platform_device *dev)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; i < siu_uart_driver.nr; i++) {
- port = &siu_uart_ports[i];
- if (port->dev == &dev->dev) {
- uart_remove_one_port(&siu_uart_driver, port);
- port->dev = NULL;
- }
- }
-
- uart_unregister_driver(&siu_uart_driver);
-
- return 0;
-}
-
-static int siu_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; i < siu_uart_driver.nr; i++) {
- port = &siu_uart_ports[i];
- if ((port->type == PORT_VR41XX_SIU ||
- port->type == PORT_VR41XX_DSIU) && port->dev == &dev->dev)
- uart_suspend_port(&siu_uart_driver, port);
-
- }
-
- return 0;
-}
-
-static int siu_resume(struct platform_device *dev)
-{
- struct uart_port *port;
- int i;
-
- for (i = 0; i < siu_uart_driver.nr; i++) {
- port = &siu_uart_ports[i];
- if ((port->type == PORT_VR41XX_SIU ||
- port->type == PORT_VR41XX_DSIU) && port->dev == &dev->dev)
- uart_resume_port(&siu_uart_driver, port);
- }
-
- return 0;
-}
-
-static struct platform_driver siu_device_driver = {
- .probe = siu_probe,
- .remove = __devexit_p(siu_remove),
- .suspend = siu_suspend,
- .resume = siu_resume,
- .driver = {
- .name = "SIU",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init vr41xx_siu_init(void)
-{
- return platform_driver_register(&siu_device_driver);
-}
-
-static void __exit vr41xx_siu_exit(void)
-{
- platform_driver_unregister(&siu_device_driver);
-}
-
-module_init(vr41xx_siu_init);
-module_exit(vr41xx_siu_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:SIU");
diff --git a/drivers/serial/vt8500_serial.c b/drivers/serial/vt8500_serial.c
deleted file mode 100644
index 322bf56c0d89..000000000000
--- a/drivers/serial/vt8500_serial.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * drivers/serial/vt8500_serial.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * Based on msm_serial.c, which is:
- * Copyright (C) 2007 Google, Inc.
- * Author: Robert Love <rlove@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#if defined(CONFIG_SERIAL_VT8500_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-# define SUPPORT_SYSRQ
-#endif
-
-#include <linux/hrtimer.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-/*
- * UART Register offsets
- */
-
-#define VT8500_URTDR 0x0000 /* Transmit data */
-#define VT8500_URRDR 0x0004 /* Receive data */
-#define VT8500_URDIV 0x0008 /* Clock/Baud rate divisor */
-#define VT8500_URLCR 0x000C /* Line control */
-#define VT8500_URICR 0x0010 /* IrDA control */
-#define VT8500_URIER 0x0014 /* Interrupt enable */
-#define VT8500_URISR 0x0018 /* Interrupt status */
-#define VT8500_URUSR 0x001c /* UART status */
-#define VT8500_URFCR 0x0020 /* FIFO control */
-#define VT8500_URFIDX 0x0024 /* FIFO index */
-#define VT8500_URBKR 0x0028 /* Break signal count */
-#define VT8500_URTOD 0x002c /* Time out divisor */
-#define VT8500_TXFIFO 0x1000 /* Transmit FIFO (16x8) */
-#define VT8500_RXFIFO 0x1020 /* Receive FIFO (16x10) */
-
-/*
- * Interrupt enable and status bits
- */
-
-#define TXDE (1 << 0) /* Tx Data empty */
-#define RXDF (1 << 1) /* Rx Data full */
-#define TXFAE (1 << 2) /* Tx FIFO almost empty */
-#define TXFE (1 << 3) /* Tx FIFO empty */
-#define RXFAF (1 << 4) /* Rx FIFO almost full */
-#define RXFF (1 << 5) /* Rx FIFO full */
-#define TXUDR (1 << 6) /* Tx underrun */
-#define RXOVER (1 << 7) /* Rx overrun */
-#define PER (1 << 8) /* Parity error */
-#define FER (1 << 9) /* Frame error */
-#define TCTS (1 << 10) /* Toggle of CTS */
-#define RXTOUT (1 << 11) /* Rx timeout */
-#define BKDONE (1 << 12) /* Break signal done */
-#define ERR (1 << 13) /* AHB error response */
-
-#define RX_FIFO_INTS (RXFAF | RXFF | RXOVER | PER | FER | RXTOUT)
-#define TX_FIFO_INTS (TXFAE | TXFE | TXUDR)
-
-struct vt8500_port {
- struct uart_port uart;
- char name[16];
- struct clk *clk;
- unsigned int ier;
-};
-
-static inline void vt8500_write(struct uart_port *port, unsigned int val,
- unsigned int off)
-{
- writel(val, port->membase + off);
-}
-
-static inline unsigned int vt8500_read(struct uart_port *port, unsigned int off)
-{
- return readl(port->membase + off);
-}
-
-static void vt8500_stop_tx(struct uart_port *port)
-{
- struct vt8500_port *vt8500_port = container_of(port,
- struct vt8500_port,
- uart);
-
- vt8500_port->ier &= ~TX_FIFO_INTS;
- vt8500_write(port, vt8500_port->ier, VT8500_URIER);
-}
-
-static void vt8500_stop_rx(struct uart_port *port)
-{
- struct vt8500_port *vt8500_port = container_of(port,
- struct vt8500_port,
- uart);
-
- vt8500_port->ier &= ~RX_FIFO_INTS;
- vt8500_write(port, vt8500_port->ier, VT8500_URIER);
-}
-
-static void vt8500_enable_ms(struct uart_port *port)
-{
- struct vt8500_port *vt8500_port = container_of(port,
- struct vt8500_port,
- uart);
-
- vt8500_port->ier |= TCTS;
- vt8500_write(port, vt8500_port->ier, VT8500_URIER);
-}
-
-static void handle_rx(struct uart_port *port)
-{
- struct tty_struct *tty = tty_port_tty_get(&port->state->port);
- if (!tty) {
- /* Discard data: no tty available */
- int count = (vt8500_read(port, VT8500_URFIDX) & 0x1f00) >> 8;
- u16 ch;
- while (count--)
- ch = readw(port->membase + VT8500_RXFIFO);
- return;
- }
-
- /*
- * Handle overrun
- */
- if ((vt8500_read(port, VT8500_URISR) & RXOVER)) {
- port->icount.overrun++;
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
-
- /* and now the main RX loop */
- while (vt8500_read(port, VT8500_URFIDX) & 0x1f00) {
- unsigned int c;
- char flag = TTY_NORMAL;
-
- c = readw(port->membase + VT8500_RXFIFO) & 0x3ff;
-
- /* Mask conditions we're ignorning. */
- c &= ~port->read_status_mask;
-
- if (c & FER) {
- port->icount.frame++;
- flag = TTY_FRAME;
- } else if (c & PER) {
- port->icount.parity++;
- flag = TTY_PARITY;
- }
- port->icount.rx++;
-
- if (!uart_handle_sysrq_char(port, c))
- tty_insert_flip_char(tty, c, flag);
- }
-
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
-}
-
-static void handle_tx(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->state->xmit;
-
- if (port->x_char) {
- writeb(port->x_char, port->membase + VT8500_TXFIFO);
- port->icount.tx++;
- port->x_char = 0;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- vt8500_stop_tx(port);
- return;
- }
-
- while ((vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16) {
- if (uart_circ_empty(xmit))
- break;
-
- writeb(xmit->buf[xmit->tail], port->membase + VT8500_TXFIFO);
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- vt8500_stop_tx(port);
-}
-
-static void vt8500_start_tx(struct uart_port *port)
-{
- struct vt8500_port *vt8500_port = container_of(port,
- struct vt8500_port,
- uart);
-
- vt8500_port->ier &= ~TX_FIFO_INTS;
- vt8500_write(port, vt8500_port->ier, VT8500_URIER);
- handle_tx(port);
- vt8500_port->ier |= TX_FIFO_INTS;
- vt8500_write(port, vt8500_port->ier, VT8500_URIER);
-}
-
-static void handle_delta_cts(struct uart_port *port)
-{
- port->icount.cts++;
- wake_up_interruptible(&port->state->port.delta_msr_wait);
-}
-
-static irqreturn_t vt8500_irq(int irq, void *dev_id)
-{
- struct uart_port *port = dev_id;
- unsigned long isr;
-
- spin_lock(&port->lock);
- isr = vt8500_read(port, VT8500_URISR);
-
- /* Acknowledge active status bits */
- vt8500_write(port, isr, VT8500_URISR);
-
- if (isr & RX_FIFO_INTS)
- handle_rx(port);
- if (isr & TX_FIFO_INTS)
- handle_tx(port);
- if (isr & TCTS)
- handle_delta_cts(port);
-
- spin_unlock(&port->lock);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int vt8500_tx_empty(struct uart_port *port)
-{
- return (vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16 ?
- TIOCSER_TEMT : 0;
-}
-
-static unsigned int vt8500_get_mctrl(struct uart_port *port)
-{
- unsigned int usr;
-
- usr = vt8500_read(port, VT8500_URUSR);
- if (usr & (1 << 4))
- return TIOCM_CTS;
- else
- return 0;
-}
-
-static void vt8500_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-static void vt8500_break_ctl(struct uart_port *port, int break_ctl)
-{
- if (break_ctl)
- vt8500_write(port, vt8500_read(port, VT8500_URLCR) | (1 << 9),
- VT8500_URLCR);
-}
-
-static int vt8500_set_baud_rate(struct uart_port *port, unsigned int baud)
-{
- unsigned long div;
- unsigned int loops = 1000;
-
- div = vt8500_read(port, VT8500_URDIV) & ~(0x3ff);
-
- if (unlikely((baud < 900) || (baud > 921600)))
- div |= 7;
- else
- div |= (921600 / baud) - 1;
-
- while ((vt8500_read(port, VT8500_URUSR) & (1 << 5)) && --loops)
- cpu_relax();
- vt8500_write(port, div, VT8500_URDIV);
-
- return baud;
-}
-
-static int vt8500_startup(struct uart_port *port)
-{
- struct vt8500_port *vt8500_port =
- container_of(port, struct vt8500_port, uart);
- int ret;
-
- snprintf(vt8500_port->name, sizeof(vt8500_port->name),
- "vt8500_serial%d", port->line);
-
- ret = request_irq(port->irq, vt8500_irq, IRQF_TRIGGER_HIGH,
- vt8500_port->name, port);
- if (unlikely(ret))
- return ret;
-
- vt8500_write(port, 0x03, VT8500_URLCR); /* enable TX & RX */
-
- return 0;
-}
-
-static void vt8500_shutdown(struct uart_port *port)
-{
- struct vt8500_port *vt8500_port =
- container_of(port, struct vt8500_port, uart);
-
- vt8500_port->ier = 0;
-
- /* disable interrupts and FIFOs */
- vt8500_write(&vt8500_port->uart, 0, VT8500_URIER);
- vt8500_write(&vt8500_port->uart, 0x880, VT8500_URFCR);
- free_irq(port->irq, port);
-}
-
-static void vt8500_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- struct vt8500_port *vt8500_port =
- container_of(port, struct vt8500_port, uart);
- unsigned long flags;
- unsigned int baud, lcr;
- unsigned int loops = 1000;
-
- spin_lock_irqsave(&port->lock, flags);
-
- /* calculate and set baud rate */
- baud = uart_get_baud_rate(port, termios, old, 900, 921600);
- baud = vt8500_set_baud_rate(port, baud);
- if (tty_termios_baud_rate(termios))
- tty_termios_encode_baud_rate(termios, baud, baud);
-
- /* calculate parity */
- lcr = vt8500_read(&vt8500_port->uart, VT8500_URLCR);
- lcr &= ~((1 << 5) | (1 << 4));
- if (termios->c_cflag & PARENB) {
- lcr |= (1 << 4);
- termios->c_cflag &= ~CMSPAR;
- if (termios->c_cflag & PARODD)
- lcr |= (1 << 5);
- }
-
- /* calculate bits per char */
- lcr &= ~(1 << 2);
- switch (termios->c_cflag & CSIZE) {
- case CS7:
- break;
- case CS8:
- default:
- lcr |= (1 << 2);
- termios->c_cflag &= ~CSIZE;
- termios->c_cflag |= CS8;
- break;
- }
-
- /* calculate stop bits */
- lcr &= ~(1 << 3);
- if (termios->c_cflag & CSTOPB)
- lcr |= (1 << 3);
-
- /* set parity, bits per char, and stop bit */
- vt8500_write(&vt8500_port->uart, lcr, VT8500_URLCR);
-
- /* Configure status bits to ignore based on termio flags. */
- port->read_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->read_status_mask = FER | PER;
-
- uart_update_timeout(port, termios->c_cflag, baud);
-
- /* Reset FIFOs */
- vt8500_write(&vt8500_port->uart, 0x88c, VT8500_URFCR);
- while ((vt8500_read(&vt8500_port->uart, VT8500_URFCR) & 0xc)
- && --loops)
- cpu_relax();
-
- /* Every possible FIFO-related interrupt */
- vt8500_port->ier = RX_FIFO_INTS | TX_FIFO_INTS;
-
- /*
- * CTS flow control
- */
- if (UART_ENABLE_MS(&vt8500_port->uart, termios->c_cflag))
- vt8500_port->ier |= TCTS;
-
- vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR);
- vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *vt8500_type(struct uart_port *port)
-{
- struct vt8500_port *vt8500_port =
- container_of(port, struct vt8500_port, uart);
- return vt8500_port->name;
-}
-
-static void vt8500_release_port(struct uart_port *port)
-{
-}
-
-static int vt8500_request_port(struct uart_port *port)
-{
- return 0;
-}
-
-static void vt8500_config_port(struct uart_port *port, int flags)
-{
- port->type = PORT_VT8500;
-}
-
-static int vt8500_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_VT8500))
- return -EINVAL;
- if (unlikely(port->irq != ser->irq))
- return -EINVAL;
- return 0;
-}
-
-static struct vt8500_port *vt8500_uart_ports[4];
-static struct uart_driver vt8500_uart_driver;
-
-#ifdef CONFIG_SERIAL_VT8500_CONSOLE
-
-static inline void wait_for_xmitr(struct uart_port *port)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = vt8500_read(port, VT8500_URFIDX);
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while (status & 0x10);
-}
-
-static void vt8500_console_putchar(struct uart_port *port, int c)
-{
- wait_for_xmitr(port);
- writeb(c, port->membase + VT8500_TXFIFO);
-}
-
-static void vt8500_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct vt8500_port *vt8500_port = vt8500_uart_ports[co->index];
- unsigned long ier;
-
- BUG_ON(co->index < 0 || co->index >= vt8500_uart_driver.nr);
-
- ier = vt8500_read(&vt8500_port->uart, VT8500_URIER);
- vt8500_write(&vt8500_port->uart, VT8500_URIER, 0);
-
- uart_console_write(&vt8500_port->uart, s, count,
- vt8500_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and switch back to FIFO
- */
- wait_for_xmitr(&vt8500_port->uart);
- vt8500_write(&vt8500_port->uart, VT8500_URIER, ier);
-}
-
-static int __init vt8500_console_setup(struct console *co, char *options)
-{
- struct vt8500_port *vt8500_port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (unlikely(co->index >= vt8500_uart_driver.nr || co->index < 0))
- return -ENXIO;
-
- vt8500_port = vt8500_uart_ports[co->index];
-
- if (!vt8500_port)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(&vt8500_port->uart,
- co, baud, parity, bits, flow);
-}
-
-static struct console vt8500_console = {
- .name = "ttyWMT",
- .write = vt8500_console_write,
- .device = uart_console_device,
- .setup = vt8500_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &vt8500_uart_driver,
-};
-
-#define VT8500_CONSOLE (&vt8500_console)
-
-#else
-#define VT8500_CONSOLE NULL
-#endif
-
-static struct uart_ops vt8500_uart_pops = {
- .tx_empty = vt8500_tx_empty,
- .set_mctrl = vt8500_set_mctrl,
- .get_mctrl = vt8500_get_mctrl,
- .stop_tx = vt8500_stop_tx,
- .start_tx = vt8500_start_tx,
- .stop_rx = vt8500_stop_rx,
- .enable_ms = vt8500_enable_ms,
- .break_ctl = vt8500_break_ctl,
- .startup = vt8500_startup,
- .shutdown = vt8500_shutdown,
- .set_termios = vt8500_set_termios,
- .type = vt8500_type,
- .release_port = vt8500_release_port,
- .request_port = vt8500_request_port,
- .config_port = vt8500_config_port,
- .verify_port = vt8500_verify_port,
-};
-
-static struct uart_driver vt8500_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "vt8500_serial",
- .dev_name = "ttyWMT",
- .nr = 6,
- .cons = VT8500_CONSOLE,
-};
-
-static int __init vt8500_serial_probe(struct platform_device *pdev)
-{
- struct vt8500_port *vt8500_port;
- struct resource *mmres, *irqres;
- int ret;
-
- mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!mmres || !irqres)
- return -ENODEV;
-
- vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
- if (!vt8500_port)
- return -ENOMEM;
-
- vt8500_port->uart.type = PORT_VT8500;
- vt8500_port->uart.iotype = UPIO_MEM;
- vt8500_port->uart.mapbase = mmres->start;
- vt8500_port->uart.irq = irqres->start;
- vt8500_port->uart.fifosize = 16;
- vt8500_port->uart.ops = &vt8500_uart_pops;
- vt8500_port->uart.line = pdev->id;
- vt8500_port->uart.dev = &pdev->dev;
- vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
- vt8500_port->uart.uartclk = 24000000;
-
- snprintf(vt8500_port->name, sizeof(vt8500_port->name),
- "VT8500 UART%d", pdev->id);
-
- vt8500_port->uart.membase = ioremap(mmres->start,
- mmres->end - mmres->start + 1);
- if (!vt8500_port->uart.membase) {
- ret = -ENOMEM;
- goto err;
- }
-
- vt8500_uart_ports[pdev->id] = vt8500_port;
-
- uart_add_one_port(&vt8500_uart_driver, &vt8500_port->uart);
-
- platform_set_drvdata(pdev, vt8500_port);
-
- return 0;
-
-err:
- kfree(vt8500_port);
- return ret;
-}
-
-static int __devexit vt8500_serial_remove(struct platform_device *pdev)
-{
- struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
- uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart);
- kfree(vt8500_port);
-
- return 0;
-}
-
-static struct platform_driver vt8500_platform_driver = {
- .probe = vt8500_serial_probe,
- .remove = vt8500_serial_remove,
- .driver = {
- .name = "vt8500_serial",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init vt8500_serial_init(void)
-{
- int ret;
-
- ret = uart_register_driver(&vt8500_uart_driver);
- if (unlikely(ret))
- return ret;
-
- ret = platform_driver_register(&vt8500_platform_driver);
-
- if (unlikely(ret))
- uart_unregister_driver(&vt8500_uart_driver);
-
- return ret;
-}
-
-static void __exit vt8500_serial_exit(void)
-{
-#ifdef CONFIG_SERIAL_VT8500_CONSOLE
- unregister_console(&vt8500_console);
-#endif
- platform_driver_unregister(&vt8500_platform_driver);
- uart_unregister_driver(&vt8500_uart_driver);
-}
-
-module_init(vt8500_serial_init);
-module_exit(vt8500_serial_exit);
-
-MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
-MODULE_DESCRIPTION("Driver for vt8500 serial device");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/zs.c b/drivers/serial/zs.c
deleted file mode 100644
index 1a7fd3e70315..000000000000
--- a/drivers/serial/zs.c
+++ /dev/null
@@ -1,1304 +0,0 @@
-/*
- * zs.c: Serial port driver for IOASIC DECstations.
- *
- * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras.
- * Derived from drivers/macintosh/macserial.c by Harald Koerfgen.
- *
- * DECstation changes
- * Copyright (C) 1998-2000 Harald Koerfgen
- * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki
- *
- * For the rest of the code the original Copyright applies:
- * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- *
- * Note: for IOASIC systems the wiring is as follows:
- *
- * mouse/keyboard:
- * DIN-7 MJ-4 signal SCC
- * 2 1 TxD <- A.TxD
- * 3 4 RxD -> A.RxD
- *
- * EIA-232/EIA-423:
- * DB-25 MMJ-6 signal SCC
- * 2 2 TxD <- B.TxD
- * 3 5 RxD -> B.RxD
- * 4 RTS <- ~A.RTS
- * 5 CTS -> ~B.CTS
- * 6 6 DSR -> ~A.SYNC
- * 8 CD -> ~B.DCD
- * 12 DSRS(DCE) -> ~A.CTS (*)
- * 15 TxC -> B.TxC
- * 17 RxC -> B.RxC
- * 20 1 DTR <- ~A.DTR
- * 22 RI -> ~A.DCD
- * 23 DSRS(DTE) <- ~B.RTS
- *
- * (*) EIA-232 defines the signal at this pin to be SCD, while DSRS(DCE)
- * is shared with DSRS(DTE) at pin 23.
- *
- * As you can immediately notice the wiring of the RTS, DTR and DSR signals
- * is a bit odd. This makes the handling of port B unnecessarily
- * complicated and prevents the use of some automatic modes of operation.
- */
-
-#if defined(CONFIG_SERIAL_ZS_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/bug.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irqflags.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/spinlock.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/types.h>
-
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-#include <asm/dec/interrupts.h>
-#include <asm/dec/ioasic_addrs.h>
-#include <asm/dec/system.h>
-
-#include "zs.h"
-
-
-MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
-MODULE_DESCRIPTION("DECstation Z85C30 serial driver");
-MODULE_LICENSE("GPL");
-
-
-static char zs_name[] __initdata = "DECstation Z85C30 serial driver version ";
-static char zs_version[] __initdata = "0.10";
-
-/*
- * It would be nice to dynamically allocate everything that
- * depends on ZS_NUM_SCCS, so we could support any number of
- * Z85C30s, but for now...
- */
-#define ZS_NUM_SCCS 2 /* Max # of ZS chips supported. */
-#define ZS_NUM_CHAN 2 /* 2 channels per chip. */
-#define ZS_CHAN_A 0 /* Index of the channel A. */
-#define ZS_CHAN_B 1 /* Index of the channel B. */
-#define ZS_CHAN_IO_SIZE 8 /* IOMEM space size. */
-#define ZS_CHAN_IO_STRIDE 4 /* Register alignment. */
-#define ZS_CHAN_IO_OFFSET 1 /* The SCC resides on the high byte
- of the 16-bit IOBUS. */
-#define ZS_CLOCK 7372800 /* Z85C30 PCLK input clock rate. */
-
-#define to_zport(uport) container_of(uport, struct zs_port, port)
-
-struct zs_parms {
- resource_size_t scc[ZS_NUM_SCCS];
- int irq[ZS_NUM_SCCS];
-};
-
-static struct zs_scc zs_sccs[ZS_NUM_SCCS];
-
-static u8 zs_init_regs[ZS_NUM_REGS] __initdata = {
- 0, /* write 0 */
- PAR_SPEC, /* write 1 */
- 0, /* write 2 */
- 0, /* write 3 */
- X16CLK | SB1, /* write 4 */
- 0, /* write 5 */
- 0, 0, 0, /* write 6, 7, 8 */
- MIE | DLC | NV, /* write 9 */
- NRZ, /* write 10 */
- TCBR | RCBR, /* write 11 */
- 0, 0, /* BRG time constant, write 12 + 13 */
- BRSRC | BRENABL, /* write 14 */
- 0, /* write 15 */
-};
-
-/*
- * Debugging.
- */
-#undef ZS_DEBUG_REGS
-
-
-/*
- * Reading and writing Z85C30 registers.
- */
-static void recovery_delay(void)
-{
- udelay(2);
-}
-
-static u8 read_zsreg(struct zs_port *zport, int reg)
-{
- void __iomem *control = zport->port.membase + ZS_CHAN_IO_OFFSET;
- u8 retval;
-
- if (reg != 0) {
- writeb(reg & 0xf, control);
- fast_iob();
- recovery_delay();
- }
- retval = readb(control);
- recovery_delay();
- return retval;
-}
-
-static void write_zsreg(struct zs_port *zport, int reg, u8 value)
-{
- void __iomem *control = zport->port.membase + ZS_CHAN_IO_OFFSET;
-
- if (reg != 0) {
- writeb(reg & 0xf, control);
- fast_iob(); recovery_delay();
- }
- writeb(value, control);
- fast_iob();
- recovery_delay();
- return;
-}
-
-static u8 read_zsdata(struct zs_port *zport)
-{
- void __iomem *data = zport->port.membase +
- ZS_CHAN_IO_STRIDE + ZS_CHAN_IO_OFFSET;
- u8 retval;
-
- retval = readb(data);
- recovery_delay();
- return retval;
-}
-
-static void write_zsdata(struct zs_port *zport, u8 value)
-{
- void __iomem *data = zport->port.membase +
- ZS_CHAN_IO_STRIDE + ZS_CHAN_IO_OFFSET;
-
- writeb(value, data);
- fast_iob();
- recovery_delay();
- return;
-}
-
-#ifdef ZS_DEBUG_REGS
-void zs_dump(void)
-{
- struct zs_port *zport;
- int i, j;
-
- for (i = 0; i < ZS_NUM_SCCS * ZS_NUM_CHAN; i++) {
- zport = &zs_sccs[i / ZS_NUM_CHAN].zport[i % ZS_NUM_CHAN];
-
- if (!zport->scc)
- continue;
-
- for (j = 0; j < 16; j++)
- printk("W%-2d = 0x%02x\t", j, zport->regs[j]);
- printk("\n");
- for (j = 0; j < 16; j++)
- printk("R%-2d = 0x%02x\t", j, read_zsreg(zport, j));
- printk("\n\n");
- }
-}
-#endif
-
-
-static void zs_spin_lock_cond_irq(spinlock_t *lock, int irq)
-{
- if (irq)
- spin_lock_irq(lock);
- else
- spin_lock(lock);
-}
-
-static void zs_spin_unlock_cond_irq(spinlock_t *lock, int irq)
-{
- if (irq)
- spin_unlock_irq(lock);
- else
- spin_unlock(lock);
-}
-
-static int zs_receive_drain(struct zs_port *zport)
-{
- int loops = 10000;
-
- while ((read_zsreg(zport, R0) & Rx_CH_AV) && --loops)
- read_zsdata(zport);
- return loops;
-}
-
-static int zs_transmit_drain(struct zs_port *zport, int irq)
-{
- struct zs_scc *scc = zport->scc;
- int loops = 10000;
-
- while (!(read_zsreg(zport, R0) & Tx_BUF_EMP) && --loops) {
- zs_spin_unlock_cond_irq(&scc->zlock, irq);
- udelay(2);
- zs_spin_lock_cond_irq(&scc->zlock, irq);
- }
- return loops;
-}
-
-static int zs_line_drain(struct zs_port *zport, int irq)
-{
- struct zs_scc *scc = zport->scc;
- int loops = 10000;
-
- while (!(read_zsreg(zport, R1) & ALL_SNT) && --loops) {
- zs_spin_unlock_cond_irq(&scc->zlock, irq);
- udelay(2);
- zs_spin_lock_cond_irq(&scc->zlock, irq);
- }
- return loops;
-}
-
-
-static void load_zsregs(struct zs_port *zport, u8 *regs, int irq)
-{
- /* Let the current transmission finish. */
- zs_line_drain(zport, irq);
- /* Load 'em up. */
- write_zsreg(zport, R3, regs[3] & ~RxENABLE);
- write_zsreg(zport, R5, regs[5] & ~TxENAB);
- write_zsreg(zport, R4, regs[4]);
- write_zsreg(zport, R9, regs[9]);
- write_zsreg(zport, R1, regs[1]);
- write_zsreg(zport, R2, regs[2]);
- write_zsreg(zport, R10, regs[10]);
- write_zsreg(zport, R14, regs[14] & ~BRENABL);
- write_zsreg(zport, R11, regs[11]);
- write_zsreg(zport, R12, regs[12]);
- write_zsreg(zport, R13, regs[13]);
- write_zsreg(zport, R14, regs[14]);
- write_zsreg(zport, R15, regs[15]);
- if (regs[3] & RxENABLE)
- write_zsreg(zport, R3, regs[3]);
- if (regs[5] & TxENAB)
- write_zsreg(zport, R5, regs[5]);
- return;
-}
-
-
-/*
- * Status handling routines.
- */
-
-/*
- * zs_tx_empty() -- get the transmitter empty status
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static unsigned int zs_tx_empty(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- unsigned long flags;
- u8 status;
-
- spin_lock_irqsave(&scc->zlock, flags);
- status = read_zsreg(zport, R1);
- spin_unlock_irqrestore(&scc->zlock, flags);
-
- return status & ALL_SNT ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int zs_raw_get_ab_mctrl(struct zs_port *zport_a,
- struct zs_port *zport_b)
-{
- u8 status_a, status_b;
- unsigned int mctrl;
-
- status_a = read_zsreg(zport_a, R0);
- status_b = read_zsreg(zport_b, R0);
-
- mctrl = ((status_b & CTS) ? TIOCM_CTS : 0) |
- ((status_b & DCD) ? TIOCM_CAR : 0) |
- ((status_a & DCD) ? TIOCM_RNG : 0) |
- ((status_a & SYNC_HUNT) ? TIOCM_DSR : 0);
-
- return mctrl;
-}
-
-static unsigned int zs_raw_get_mctrl(struct zs_port *zport)
-{
- struct zs_port *zport_a = &zport->scc->zport[ZS_CHAN_A];
-
- return zport != zport_a ? zs_raw_get_ab_mctrl(zport_a, zport) : 0;
-}
-
-static unsigned int zs_raw_xor_mctrl(struct zs_port *zport)
-{
- struct zs_port *zport_a = &zport->scc->zport[ZS_CHAN_A];
- unsigned int mmask, mctrl, delta;
- u8 mask_a, mask_b;
-
- if (zport == zport_a)
- return 0;
-
- mask_a = zport_a->regs[15];
- mask_b = zport->regs[15];
-
- mmask = ((mask_b & CTSIE) ? TIOCM_CTS : 0) |
- ((mask_b & DCDIE) ? TIOCM_CAR : 0) |
- ((mask_a & DCDIE) ? TIOCM_RNG : 0) |
- ((mask_a & SYNCIE) ? TIOCM_DSR : 0);
-
- mctrl = zport->mctrl;
- if (mmask) {
- mctrl &= ~mmask;
- mctrl |= zs_raw_get_ab_mctrl(zport_a, zport) & mmask;
- }
-
- delta = mctrl ^ zport->mctrl;
- if (delta)
- zport->mctrl = mctrl;
-
- return delta;
-}
-
-static unsigned int zs_get_mctrl(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- unsigned int mctrl;
-
- spin_lock(&scc->zlock);
- mctrl = zs_raw_get_mctrl(zport);
- spin_unlock(&scc->zlock);
-
- return mctrl;
-}
-
-static void zs_set_mctrl(struct uart_port *uport, unsigned int mctrl)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- struct zs_port *zport_a = &scc->zport[ZS_CHAN_A];
- u8 oldloop, newloop;
-
- spin_lock(&scc->zlock);
- if (zport != zport_a) {
- if (mctrl & TIOCM_DTR)
- zport_a->regs[5] |= DTR;
- else
- zport_a->regs[5] &= ~DTR;
- if (mctrl & TIOCM_RTS)
- zport_a->regs[5] |= RTS;
- else
- zport_a->regs[5] &= ~RTS;
- write_zsreg(zport_a, R5, zport_a->regs[5]);
- }
-
- /* Rarely modified, so don't poke at hardware unless necessary. */
- oldloop = zport->regs[14];
- newloop = oldloop;
- if (mctrl & TIOCM_LOOP)
- newloop |= LOOPBAK;
- else
- newloop &= ~LOOPBAK;
- if (newloop != oldloop) {
- zport->regs[14] = newloop;
- write_zsreg(zport, R14, zport->regs[14]);
- }
- spin_unlock(&scc->zlock);
-}
-
-static void zs_raw_stop_tx(struct zs_port *zport)
-{
- write_zsreg(zport, R0, RES_Tx_P);
- zport->tx_stopped = 1;
-}
-
-static void zs_stop_tx(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
-
- spin_lock(&scc->zlock);
- zs_raw_stop_tx(zport);
- spin_unlock(&scc->zlock);
-}
-
-static void zs_raw_transmit_chars(struct zs_port *);
-
-static void zs_start_tx(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
-
- spin_lock(&scc->zlock);
- if (zport->tx_stopped) {
- zs_transmit_drain(zport, 0);
- zport->tx_stopped = 0;
- zs_raw_transmit_chars(zport);
- }
- spin_unlock(&scc->zlock);
-}
-
-static void zs_stop_rx(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- struct zs_port *zport_a = &scc->zport[ZS_CHAN_A];
-
- spin_lock(&scc->zlock);
- zport->regs[15] &= ~BRKIE;
- zport->regs[1] &= ~(RxINT_MASK | TxINT_ENAB);
- zport->regs[1] |= RxINT_DISAB;
-
- if (zport != zport_a) {
- /* A-side DCD tracks RI and SYNC tracks DSR. */
- zport_a->regs[15] &= ~(DCDIE | SYNCIE);
- write_zsreg(zport_a, R15, zport_a->regs[15]);
- if (!(zport_a->regs[15] & BRKIE)) {
- zport_a->regs[1] &= ~EXT_INT_ENAB;
- write_zsreg(zport_a, R1, zport_a->regs[1]);
- }
-
- /* This-side DCD tracks DCD and CTS tracks CTS. */
- zport->regs[15] &= ~(DCDIE | CTSIE);
- zport->regs[1] &= ~EXT_INT_ENAB;
- } else {
- /* DCD tracks RI and SYNC tracks DSR for the B side. */
- if (!(zport->regs[15] & (DCDIE | SYNCIE)))
- zport->regs[1] &= ~EXT_INT_ENAB;
- }
-
- write_zsreg(zport, R15, zport->regs[15]);
- write_zsreg(zport, R1, zport->regs[1]);
- spin_unlock(&scc->zlock);
-}
-
-static void zs_enable_ms(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- struct zs_port *zport_a = &scc->zport[ZS_CHAN_A];
-
- if (zport == zport_a)
- return;
-
- spin_lock(&scc->zlock);
-
- /* Clear Ext interrupts if not being handled already. */
- if (!(zport_a->regs[1] & EXT_INT_ENAB))
- write_zsreg(zport_a, R0, RES_EXT_INT);
-
- /* A-side DCD tracks RI and SYNC tracks DSR. */
- zport_a->regs[1] |= EXT_INT_ENAB;
- zport_a->regs[15] |= DCDIE | SYNCIE;
-
- /* This-side DCD tracks DCD and CTS tracks CTS. */
- zport->regs[15] |= DCDIE | CTSIE;
-
- zs_raw_xor_mctrl(zport);
-
- write_zsreg(zport_a, R1, zport_a->regs[1]);
- write_zsreg(zport_a, R15, zport_a->regs[15]);
- write_zsreg(zport, R15, zport->regs[15]);
- spin_unlock(&scc->zlock);
-}
-
-static void zs_break_ctl(struct uart_port *uport, int break_state)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- unsigned long flags;
-
- spin_lock_irqsave(&scc->zlock, flags);
- if (break_state == -1)
- zport->regs[5] |= SND_BRK;
- else
- zport->regs[5] &= ~SND_BRK;
- write_zsreg(zport, R5, zport->regs[5]);
- spin_unlock_irqrestore(&scc->zlock, flags);
-}
-
-
-/*
- * Interrupt handling routines.
- */
-#define Rx_BRK 0x0100 /* BREAK event software flag. */
-#define Rx_SYS 0x0200 /* SysRq event software flag. */
-
-static void zs_receive_chars(struct zs_port *zport)
-{
- struct uart_port *uport = &zport->port;
- struct zs_scc *scc = zport->scc;
- struct uart_icount *icount;
- unsigned int avail, status, ch, flag;
- int count;
-
- for (count = 16; count; count--) {
- spin_lock(&scc->zlock);
- avail = read_zsreg(zport, R0) & Rx_CH_AV;
- spin_unlock(&scc->zlock);
- if (!avail)
- break;
-
- spin_lock(&scc->zlock);
- status = read_zsreg(zport, R1) & (Rx_OVR | FRM_ERR | PAR_ERR);
- ch = read_zsdata(zport);
- spin_unlock(&scc->zlock);
-
- flag = TTY_NORMAL;
-
- icount = &uport->icount;
- icount->rx++;
-
- /* Handle the null char got when BREAK is removed. */
- if (!ch)
- status |= zport->tty_break;
- if (unlikely(status &
- (Rx_OVR | FRM_ERR | PAR_ERR | Rx_SYS | Rx_BRK))) {
- zport->tty_break = 0;
-
- /* Reset the error indication. */
- if (status & (Rx_OVR | FRM_ERR | PAR_ERR)) {
- spin_lock(&scc->zlock);
- write_zsreg(zport, R0, ERR_RES);
- spin_unlock(&scc->zlock);
- }
-
- if (status & (Rx_SYS | Rx_BRK)) {
- icount->brk++;
- /* SysRq discards the null char. */
- if (status & Rx_SYS)
- continue;
- } else if (status & FRM_ERR)
- icount->frame++;
- else if (status & PAR_ERR)
- icount->parity++;
- if (status & Rx_OVR)
- icount->overrun++;
-
- status &= uport->read_status_mask;
- if (status & Rx_BRK)
- flag = TTY_BREAK;
- else if (status & FRM_ERR)
- flag = TTY_FRAME;
- else if (status & PAR_ERR)
- flag = TTY_PARITY;
- }
-
- if (uart_handle_sysrq_char(uport, ch))
- continue;
-
- uart_insert_char(uport, status, Rx_OVR, ch, flag);
- }
-
- tty_flip_buffer_push(uport->state->port.tty);
-}
-
-static void zs_raw_transmit_chars(struct zs_port *zport)
-{
- struct circ_buf *xmit = &zport->port.state->xmit;
-
- /* XON/XOFF chars. */
- if (zport->port.x_char) {
- write_zsdata(zport, zport->port.x_char);
- zport->port.icount.tx++;
- zport->port.x_char = 0;
- return;
- }
-
- /* If nothing to do or stopped or hardware stopped. */
- if (uart_circ_empty(xmit) || uart_tx_stopped(&zport->port)) {
- zs_raw_stop_tx(zport);
- return;
- }
-
- /* Send char. */
- write_zsdata(zport, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- zport->port.icount.tx++;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&zport->port);
-
- /* Are we are done? */
- if (uart_circ_empty(xmit))
- zs_raw_stop_tx(zport);
-}
-
-static void zs_transmit_chars(struct zs_port *zport)
-{
- struct zs_scc *scc = zport->scc;
-
- spin_lock(&scc->zlock);
- zs_raw_transmit_chars(zport);
- spin_unlock(&scc->zlock);
-}
-
-static void zs_status_handle(struct zs_port *zport, struct zs_port *zport_a)
-{
- struct uart_port *uport = &zport->port;
- struct zs_scc *scc = zport->scc;
- unsigned int delta;
- u8 status, brk;
-
- spin_lock(&scc->zlock);
-
- /* Get status from Read Register 0. */
- status = read_zsreg(zport, R0);
-
- if (zport->regs[15] & BRKIE) {
- brk = status & BRK_ABRT;
- if (brk && !zport->brk) {
- spin_unlock(&scc->zlock);
- if (uart_handle_break(uport))
- zport->tty_break = Rx_SYS;
- else
- zport->tty_break = Rx_BRK;
- spin_lock(&scc->zlock);
- }
- zport->brk = brk;
- }
-
- if (zport != zport_a) {
- delta = zs_raw_xor_mctrl(zport);
- spin_unlock(&scc->zlock);
-
- if (delta & TIOCM_CTS)
- uart_handle_cts_change(uport,
- zport->mctrl & TIOCM_CTS);
- if (delta & TIOCM_CAR)
- uart_handle_dcd_change(uport,
- zport->mctrl & TIOCM_CAR);
- if (delta & TIOCM_RNG)
- uport->icount.dsr++;
- if (delta & TIOCM_DSR)
- uport->icount.rng++;
-
- if (delta)
- wake_up_interruptible(&uport->state->port.delta_msr_wait);
-
- spin_lock(&scc->zlock);
- }
-
- /* Clear the status condition... */
- write_zsreg(zport, R0, RES_EXT_INT);
-
- spin_unlock(&scc->zlock);
-}
-
-/*
- * This is the Z85C30 driver's generic interrupt routine.
- */
-static irqreturn_t zs_interrupt(int irq, void *dev_id)
-{
- struct zs_scc *scc = dev_id;
- struct zs_port *zport_a = &scc->zport[ZS_CHAN_A];
- struct zs_port *zport_b = &scc->zport[ZS_CHAN_B];
- irqreturn_t status = IRQ_NONE;
- u8 zs_intreg;
- int count;
-
- /*
- * NOTE: The read register 3, which holds the irq status,
- * does so for both channels on each chip. Although
- * the status value itself must be read from the A
- * channel and is only valid when read from channel A.
- * Yes... broken hardware...
- */
- for (count = 16; count; count--) {
- spin_lock(&scc->zlock);
- zs_intreg = read_zsreg(zport_a, R3);
- spin_unlock(&scc->zlock);
- if (!zs_intreg)
- break;
-
- /*
- * We do not like losing characters, so we prioritise
- * interrupt sources a little bit differently than
- * the SCC would, was it allowed to.
- */
- if (zs_intreg & CHBRxIP)
- zs_receive_chars(zport_b);
- if (zs_intreg & CHARxIP)
- zs_receive_chars(zport_a);
- if (zs_intreg & CHBEXT)
- zs_status_handle(zport_b, zport_a);
- if (zs_intreg & CHAEXT)
- zs_status_handle(zport_a, zport_a);
- if (zs_intreg & CHBTxIP)
- zs_transmit_chars(zport_b);
- if (zs_intreg & CHATxIP)
- zs_transmit_chars(zport_a);
-
- status = IRQ_HANDLED;
- }
-
- return status;
-}
-
-
-/*
- * Finally, routines used to initialize the serial port.
- */
-static int zs_startup(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- unsigned long flags;
- int irq_guard;
- int ret;
-
- irq_guard = atomic_add_return(1, &scc->irq_guard);
- if (irq_guard == 1) {
- ret = request_irq(zport->port.irq, zs_interrupt,
- IRQF_SHARED, "scc", scc);
- if (ret) {
- atomic_add(-1, &scc->irq_guard);
- printk(KERN_ERR "zs: can't get irq %d\n",
- zport->port.irq);
- return ret;
- }
- }
-
- spin_lock_irqsave(&scc->zlock, flags);
-
- /* Clear the receive FIFO. */
- zs_receive_drain(zport);
-
- /* Clear the interrupt registers. */
- write_zsreg(zport, R0, ERR_RES);
- write_zsreg(zport, R0, RES_Tx_P);
- /* But Ext only if not being handled already. */
- if (!(zport->regs[1] & EXT_INT_ENAB))
- write_zsreg(zport, R0, RES_EXT_INT);
-
- /* Finally, enable sequencing and interrupts. */
- zport->regs[1] &= ~RxINT_MASK;
- zport->regs[1] |= RxINT_ALL | TxINT_ENAB | EXT_INT_ENAB;
- zport->regs[3] |= RxENABLE;
- zport->regs[15] |= BRKIE;
- write_zsreg(zport, R1, zport->regs[1]);
- write_zsreg(zport, R3, zport->regs[3]);
- write_zsreg(zport, R5, zport->regs[5]);
- write_zsreg(zport, R15, zport->regs[15]);
-
- /* Record the current state of RR0. */
- zport->mctrl = zs_raw_get_mctrl(zport);
- zport->brk = read_zsreg(zport, R0) & BRK_ABRT;
-
- zport->tx_stopped = 1;
-
- spin_unlock_irqrestore(&scc->zlock, flags);
-
- return 0;
-}
-
-static void zs_shutdown(struct uart_port *uport)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- unsigned long flags;
- int irq_guard;
-
- spin_lock_irqsave(&scc->zlock, flags);
-
- zport->regs[3] &= ~RxENABLE;
- write_zsreg(zport, R5, zport->regs[5]);
- write_zsreg(zport, R3, zport->regs[3]);
-
- spin_unlock_irqrestore(&scc->zlock, flags);
-
- irq_guard = atomic_add_return(-1, &scc->irq_guard);
- if (!irq_guard)
- free_irq(zport->port.irq, scc);
-}
-
-
-static void zs_reset(struct zs_port *zport)
-{
- struct zs_scc *scc = zport->scc;
- int irq;
- unsigned long flags;
-
- spin_lock_irqsave(&scc->zlock, flags);
- irq = !irqs_disabled_flags(flags);
- if (!scc->initialised) {
- /* Reset the pointer first, just in case... */
- read_zsreg(zport, R0);
- /* And let the current transmission finish. */
- zs_line_drain(zport, irq);
- write_zsreg(zport, R9, FHWRES);
- udelay(10);
- write_zsreg(zport, R9, 0);
- scc->initialised = 1;
- }
- load_zsregs(zport, zport->regs, irq);
- spin_unlock_irqrestore(&scc->zlock, flags);
-}
-
-static void zs_set_termios(struct uart_port *uport, struct ktermios *termios,
- struct ktermios *old_termios)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- struct zs_port *zport_a = &scc->zport[ZS_CHAN_A];
- int irq;
- unsigned int baud, brg;
- unsigned long flags;
-
- spin_lock_irqsave(&scc->zlock, flags);
- irq = !irqs_disabled_flags(flags);
-
- /* Byte size. */
- zport->regs[3] &= ~RxNBITS_MASK;
- zport->regs[5] &= ~TxNBITS_MASK;
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- zport->regs[3] |= Rx5;
- zport->regs[5] |= Tx5;
- break;
- case CS6:
- zport->regs[3] |= Rx6;
- zport->regs[5] |= Tx6;
- break;
- case CS7:
- zport->regs[3] |= Rx7;
- zport->regs[5] |= Tx7;
- break;
- case CS8:
- default:
- zport->regs[3] |= Rx8;
- zport->regs[5] |= Tx8;
- break;
- }
-
- /* Parity and stop bits. */
- zport->regs[4] &= ~(XCLK_MASK | SB_MASK | PAR_ENA | PAR_EVEN);
- if (termios->c_cflag & CSTOPB)
- zport->regs[4] |= SB2;
- else
- zport->regs[4] |= SB1;
- if (termios->c_cflag & PARENB)
- zport->regs[4] |= PAR_ENA;
- if (!(termios->c_cflag & PARODD))
- zport->regs[4] |= PAR_EVEN;
- switch (zport->clk_mode) {
- case 64:
- zport->regs[4] |= X64CLK;
- break;
- case 32:
- zport->regs[4] |= X32CLK;
- break;
- case 16:
- zport->regs[4] |= X16CLK;
- break;
- case 1:
- zport->regs[4] |= X1CLK;
- break;
- default:
- BUG();
- }
-
- baud = uart_get_baud_rate(uport, termios, old_termios, 0,
- uport->uartclk / zport->clk_mode / 4);
-
- brg = ZS_BPS_TO_BRG(baud, uport->uartclk / zport->clk_mode);
- zport->regs[12] = brg & 0xff;
- zport->regs[13] = (brg >> 8) & 0xff;
-
- uart_update_timeout(uport, termios->c_cflag, baud);
-
- uport->read_status_mask = Rx_OVR;
- if (termios->c_iflag & INPCK)
- uport->read_status_mask |= FRM_ERR | PAR_ERR;
- if (termios->c_iflag & (BRKINT | PARMRK))
- uport->read_status_mask |= Rx_BRK;
-
- uport->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- uport->ignore_status_mask |= FRM_ERR | PAR_ERR;
- if (termios->c_iflag & IGNBRK) {
- uport->ignore_status_mask |= Rx_BRK;
- if (termios->c_iflag & IGNPAR)
- uport->ignore_status_mask |= Rx_OVR;
- }
-
- if (termios->c_cflag & CREAD)
- zport->regs[3] |= RxENABLE;
- else
- zport->regs[3] &= ~RxENABLE;
-
- if (zport != zport_a) {
- if (!(termios->c_cflag & CLOCAL)) {
- zport->regs[15] |= DCDIE;
- } else
- zport->regs[15] &= ~DCDIE;
- if (termios->c_cflag & CRTSCTS) {
- zport->regs[15] |= CTSIE;
- } else
- zport->regs[15] &= ~CTSIE;
- zs_raw_xor_mctrl(zport);
- }
-
- /* Load up the new values. */
- load_zsregs(zport, zport->regs, irq);
-
- spin_unlock_irqrestore(&scc->zlock, flags);
-}
-
-/*
- * Hack alert!
- * Required solely so that the initial PROM-based console
- * works undisturbed in parallel with this one.
- */
-static void zs_pm(struct uart_port *uport, unsigned int state,
- unsigned int oldstate)
-{
- struct zs_port *zport = to_zport(uport);
-
- if (state < 3)
- zport->regs[5] |= TxENAB;
- else
- zport->regs[5] &= ~TxENAB;
- write_zsreg(zport, R5, zport->regs[5]);
-}
-
-
-static const char *zs_type(struct uart_port *uport)
-{
- return "Z85C30 SCC";
-}
-
-static void zs_release_port(struct uart_port *uport)
-{
- iounmap(uport->membase);
- uport->membase = 0;
- release_mem_region(uport->mapbase, ZS_CHAN_IO_SIZE);
-}
-
-static int zs_map_port(struct uart_port *uport)
-{
- if (!uport->membase)
- uport->membase = ioremap_nocache(uport->mapbase,
- ZS_CHAN_IO_SIZE);
- if (!uport->membase) {
- printk(KERN_ERR "zs: Cannot map MMIO\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-static int zs_request_port(struct uart_port *uport)
-{
- int ret;
-
- if (!request_mem_region(uport->mapbase, ZS_CHAN_IO_SIZE, "scc")) {
- printk(KERN_ERR "zs: Unable to reserve MMIO resource\n");
- return -EBUSY;
- }
- ret = zs_map_port(uport);
- if (ret) {
- release_mem_region(uport->mapbase, ZS_CHAN_IO_SIZE);
- return ret;
- }
- return 0;
-}
-
-static void zs_config_port(struct uart_port *uport, int flags)
-{
- struct zs_port *zport = to_zport(uport);
-
- if (flags & UART_CONFIG_TYPE) {
- if (zs_request_port(uport))
- return;
-
- uport->type = PORT_ZS;
-
- zs_reset(zport);
- }
-}
-
-static int zs_verify_port(struct uart_port *uport, struct serial_struct *ser)
-{
- struct zs_port *zport = to_zport(uport);
- int ret = 0;
-
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_ZS)
- ret = -EINVAL;
- if (ser->irq != uport->irq)
- ret = -EINVAL;
- if (ser->baud_base != uport->uartclk / zport->clk_mode / 4)
- ret = -EINVAL;
- return ret;
-}
-
-
-static struct uart_ops zs_ops = {
- .tx_empty = zs_tx_empty,
- .set_mctrl = zs_set_mctrl,
- .get_mctrl = zs_get_mctrl,
- .stop_tx = zs_stop_tx,
- .start_tx = zs_start_tx,
- .stop_rx = zs_stop_rx,
- .enable_ms = zs_enable_ms,
- .break_ctl = zs_break_ctl,
- .startup = zs_startup,
- .shutdown = zs_shutdown,
- .set_termios = zs_set_termios,
- .pm = zs_pm,
- .type = zs_type,
- .release_port = zs_release_port,
- .request_port = zs_request_port,
- .config_port = zs_config_port,
- .verify_port = zs_verify_port,
-};
-
-/*
- * Initialize Z85C30 port structures.
- */
-static int __init zs_probe_sccs(void)
-{
- static int probed;
- struct zs_parms zs_parms;
- int chip, side, irq;
- int n_chips = 0;
- int i;
-
- if (probed)
- return 0;
-
- irq = dec_interrupt[DEC_IRQ_SCC0];
- if (irq >= 0) {
- zs_parms.scc[n_chips] = IOASIC_SCC0;
- zs_parms.irq[n_chips] = dec_interrupt[DEC_IRQ_SCC0];
- n_chips++;
- }
- irq = dec_interrupt[DEC_IRQ_SCC1];
- if (irq >= 0) {
- zs_parms.scc[n_chips] = IOASIC_SCC1;
- zs_parms.irq[n_chips] = dec_interrupt[DEC_IRQ_SCC1];
- n_chips++;
- }
- if (!n_chips)
- return -ENXIO;
-
- probed = 1;
-
- for (chip = 0; chip < n_chips; chip++) {
- spin_lock_init(&zs_sccs[chip].zlock);
- for (side = 0; side < ZS_NUM_CHAN; side++) {
- struct zs_port *zport = &zs_sccs[chip].zport[side];
- struct uart_port *uport = &zport->port;
-
- zport->scc = &zs_sccs[chip];
- zport->clk_mode = 16;
-
- uport->irq = zs_parms.irq[chip];
- uport->uartclk = ZS_CLOCK;
- uport->fifosize = 1;
- uport->iotype = UPIO_MEM;
- uport->flags = UPF_BOOT_AUTOCONF;
- uport->ops = &zs_ops;
- uport->line = chip * ZS_NUM_CHAN + side;
- uport->mapbase = dec_kn_slot_base +
- zs_parms.scc[chip] +
- (side ^ ZS_CHAN_B) * ZS_CHAN_IO_SIZE;
-
- for (i = 0; i < ZS_NUM_REGS; i++)
- zport->regs[i] = zs_init_regs[i];
- }
- }
-
- return 0;
-}
-
-
-#ifdef CONFIG_SERIAL_ZS_CONSOLE
-static void zs_console_putchar(struct uart_port *uport, int ch)
-{
- struct zs_port *zport = to_zport(uport);
- struct zs_scc *scc = zport->scc;
- int irq;
- unsigned long flags;
-
- spin_lock_irqsave(&scc->zlock, flags);
- irq = !irqs_disabled_flags(flags);
- if (zs_transmit_drain(zport, irq))
- write_zsdata(zport, ch);
- spin_unlock_irqrestore(&scc->zlock, flags);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- */
-static void zs_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- int chip = co->index / ZS_NUM_CHAN, side = co->index % ZS_NUM_CHAN;
- struct zs_port *zport = &zs_sccs[chip].zport[side];
- struct zs_scc *scc = zport->scc;
- unsigned long flags;
- u8 txint, txenb;
- int irq;
-
- /* Disable transmit interrupts and enable the transmitter. */
- spin_lock_irqsave(&scc->zlock, flags);
- txint = zport->regs[1];
- txenb = zport->regs[5];
- if (txint & TxINT_ENAB) {
- zport->regs[1] = txint & ~TxINT_ENAB;
- write_zsreg(zport, R1, zport->regs[1]);
- }
- if (!(txenb & TxENAB)) {
- zport->regs[5] = txenb | TxENAB;
- write_zsreg(zport, R5, zport->regs[5]);
- }
- spin_unlock_irqrestore(&scc->zlock, flags);
-
- uart_console_write(&zport->port, s, count, zs_console_putchar);
-
- /* Restore transmit interrupts and the transmitter enable. */
- spin_lock_irqsave(&scc->zlock, flags);
- irq = !irqs_disabled_flags(flags);
- zs_line_drain(zport, irq);
- if (!(txenb & TxENAB)) {
- zport->regs[5] &= ~TxENAB;
- write_zsreg(zport, R5, zport->regs[5]);
- }
- if (txint & TxINT_ENAB) {
- zport->regs[1] |= TxINT_ENAB;
- write_zsreg(zport, R1, zport->regs[1]);
- }
- spin_unlock_irqrestore(&scc->zlock, flags);
-}
-
-/*
- * Setup serial console baud/bits/parity. We do two things here:
- * - construct a cflag setting for the first uart_open()
- * - initialise the serial port
- * Return non-zero if we didn't find a serial port.
- */
-static int __init zs_console_setup(struct console *co, char *options)
-{
- int chip = co->index / ZS_NUM_CHAN, side = co->index % ZS_NUM_CHAN;
- struct zs_port *zport = &zs_sccs[chip].zport[side];
- struct uart_port *uport = &zport->port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- int ret;
-
- ret = zs_map_port(uport);
- if (ret)
- return ret;
-
- zs_reset(zport);
- zs_pm(uport, 0, -1);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- return uart_set_options(uport, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver zs_reg;
-static struct console zs_console = {
- .name = "ttyS",
- .write = zs_console_write,
- .device = uart_console_device,
- .setup = zs_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &zs_reg,
-};
-
-/*
- * Register console.
- */
-static int __init zs_serial_console_init(void)
-{
- int ret;
-
- ret = zs_probe_sccs();
- if (ret)
- return ret;
- register_console(&zs_console);
-
- return 0;
-}
-
-console_initcall(zs_serial_console_init);
-
-#define SERIAL_ZS_CONSOLE &zs_console
-#else
-#define SERIAL_ZS_CONSOLE NULL
-#endif /* CONFIG_SERIAL_ZS_CONSOLE */
-
-static struct uart_driver zs_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = ZS_NUM_SCCS * ZS_NUM_CHAN,
- .cons = SERIAL_ZS_CONSOLE,
-};
-
-/* zs_init inits the driver. */
-static int __init zs_init(void)
-{
- int i, ret;
-
- pr_info("%s%s\n", zs_name, zs_version);
-
- /* Find out how many Z85C30 SCCs we have. */
- ret = zs_probe_sccs();
- if (ret)
- return ret;
-
- ret = uart_register_driver(&zs_reg);
- if (ret)
- return ret;
-
- for (i = 0; i < ZS_NUM_SCCS * ZS_NUM_CHAN; i++) {
- struct zs_scc *scc = &zs_sccs[i / ZS_NUM_CHAN];
- struct zs_port *zport = &scc->zport[i % ZS_NUM_CHAN];
- struct uart_port *uport = &zport->port;
-
- if (zport->scc)
- uart_add_one_port(&zs_reg, uport);
- }
-
- return 0;
-}
-
-static void __exit zs_exit(void)
-{
- int i;
-
- for (i = ZS_NUM_SCCS * ZS_NUM_CHAN - 1; i >= 0; i--) {
- struct zs_scc *scc = &zs_sccs[i / ZS_NUM_CHAN];
- struct zs_port *zport = &scc->zport[i % ZS_NUM_CHAN];
- struct uart_port *uport = &zport->port;
-
- if (zport->scc)
- uart_remove_one_port(&zs_reg, uport);
- }
-
- uart_unregister_driver(&zs_reg);
-}
-
-module_init(zs_init);
-module_exit(zs_exit);
diff --git a/drivers/serial/zs.h b/drivers/serial/zs.h
deleted file mode 100644
index aa921b57d827..000000000000
--- a/drivers/serial/zs.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * zs.h: Definitions for the DECstation Z85C30 serial driver.
- *
- * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras.
- * Adapted from drivers/macintosh/macserial.h by Harald Koerfgen.
- *
- * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 2004, 2005, 2007 Maciej W. Rozycki
- */
-#ifndef _SERIAL_ZS_H
-#define _SERIAL_ZS_H
-
-#ifdef __KERNEL__
-
-#define ZS_NUM_REGS 16
-
-/*
- * This is our internal structure for each serial port's state.
- */
-struct zs_port {
- struct zs_scc *scc; /* Containing SCC. */
- struct uart_port port; /* Underlying UART. */
-
- int clk_mode; /* May be 1, 16, 32, or 64. */
-
- unsigned int tty_break; /* Set on BREAK condition. */
- int tx_stopped; /* Output is suspended. */
-
- unsigned int mctrl; /* State of modem lines. */
- u8 brk; /* BREAK state from RR0. */
-
- u8 regs[ZS_NUM_REGS]; /* Channel write registers. */
-};
-
-/*
- * Per-SCC state for locking and the interrupt handler.
- */
-struct zs_scc {
- struct zs_port zport[2];
- spinlock_t zlock;
- atomic_t irq_guard;
- int initialised;
-};
-
-#endif /* __KERNEL__ */
-
-/*
- * Conversion routines to/from brg time constants from/to bits per second.
- */
-#define ZS_BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
-#define ZS_BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
-
-/*
- * The Zilog register set.
- */
-
-/* Write Register 0 (Command) */
-#define R0 0 /* Register selects */
-#define R1 1
-#define R2 2
-#define R3 3
-#define R4 4
-#define R5 5
-#define R6 6
-#define R7 7
-#define R8 8
-#define R9 9
-#define R10 10
-#define R11 11
-#define R12 12
-#define R13 13
-#define R14 14
-#define R15 15
-
-#define NULLCODE 0 /* Null Code */
-#define POINT_HIGH 0x8 /* Select upper half of registers */
-#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
-#define SEND_ABORT 0x18 /* HDLC Abort */
-#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
-#define RES_Tx_P 0x28 /* Reset TxINT Pending */
-#define ERR_RES 0x30 /* Error Reset */
-#define RES_H_IUS 0x38 /* Reset highest IUS */
-
-#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
-#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
-#define RES_EOM_L 0xC0 /* Reset EOM latch */
-
-/* Write Register 1 (Tx/Rx/Ext Int Enable and WAIT/DMA Commands) */
-#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
-#define TxINT_ENAB 0x2 /* Tx Int Enable */
-#define PAR_SPEC 0x4 /* Parity is special condition */
-
-#define RxINT_DISAB 0 /* Rx Int Disable */
-#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
-#define RxINT_ALL 0x10 /* Int on all Rx Characters or error */
-#define RxINT_ERR 0x18 /* Int on error only */
-#define RxINT_MASK 0x18
-
-#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
-#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
-#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
-
-/* Write Register 2 (Interrupt Vector) */
-
-/* Write Register 3 (Receive Parameters and Control) */
-#define RxENABLE 0x1 /* Rx Enable */
-#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
-#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
-#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
-#define ENT_HM 0x10 /* Enter Hunt Mode */
-#define AUTO_ENAB 0x20 /* Auto Enables */
-#define Rx5 0x0 /* Rx 5 Bits/Character */
-#define Rx7 0x40 /* Rx 7 Bits/Character */
-#define Rx6 0x80 /* Rx 6 Bits/Character */
-#define Rx8 0xc0 /* Rx 8 Bits/Character */
-#define RxNBITS_MASK 0xc0
-
-/* Write Register 4 (Transmit/Receive Miscellaneous Parameters and Modes) */
-#define PAR_ENA 0x1 /* Parity Enable */
-#define PAR_EVEN 0x2 /* Parity Even/Odd* */
-
-#define SYNC_ENAB 0 /* Sync Modes Enable */
-#define SB1 0x4 /* 1 stop bit/char */
-#define SB15 0x8 /* 1.5 stop bits/char */
-#define SB2 0xc /* 2 stop bits/char */
-#define SB_MASK 0xc
-
-#define MONSYNC 0 /* 8 Bit Sync character */
-#define BISYNC 0x10 /* 16 bit sync character */
-#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
-#define EXTSYNC 0x30 /* External Sync Mode */
-
-#define X1CLK 0x0 /* x1 clock mode */
-#define X16CLK 0x40 /* x16 clock mode */
-#define X32CLK 0x80 /* x32 clock mode */
-#define X64CLK 0xc0 /* x64 clock mode */
-#define XCLK_MASK 0xc0
-
-/* Write Register 5 (Transmit Parameters and Controls) */
-#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
-#define RTS 0x2 /* RTS */
-#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
-#define TxENAB 0x8 /* Tx Enable */
-#define SND_BRK 0x10 /* Send Break */
-#define Tx5 0x0 /* Tx 5 bits (or less)/character */
-#define Tx7 0x20 /* Tx 7 bits/character */
-#define Tx6 0x40 /* Tx 6 bits/character */
-#define Tx8 0x60 /* Tx 8 bits/character */
-#define TxNBITS_MASK 0x60
-#define DTR 0x80 /* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 8 (Transmit Buffer) */
-
-/* Write Register 9 (Master Interrupt Control) */
-#define VIS 1 /* Vector Includes Status */
-#define NV 2 /* No Vector */
-#define DLC 4 /* Disable Lower Chain */
-#define MIE 8 /* Master Interrupt Enable */
-#define STATHI 0x10 /* Status high */
-#define SOFTACK 0x20 /* Software Interrupt Acknowledge */
-#define NORESET 0 /* No reset on write to R9 */
-#define CHRB 0x40 /* Reset channel B */
-#define CHRA 0x80 /* Reset channel A */
-#define FHWRES 0xc0 /* Force hardware reset */
-
-/* Write Register 10 (Miscellaneous Transmitter/Receiver Control Bits) */
-#define BIT6 1 /* 6 bit/8bit sync */
-#define LOOPMODE 2 /* SDLC Loop mode */
-#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
-#define MARKIDLE 8 /* Mark/flag on idle */
-#define GAOP 0x10 /* Go active on poll */
-#define NRZ 0 /* NRZ mode */
-#define NRZI 0x20 /* NRZI mode */
-#define FM1 0x40 /* FM1 (transition = 1) */
-#define FM0 0x60 /* FM0 (transition = 0) */
-#define CRCPS 0x80 /* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode Control) */
-#define TRxCXT 0 /* TRxC = Xtal output */
-#define TRxCTC 1 /* TRxC = Transmit clock */
-#define TRxCBR 2 /* TRxC = BR Generator Output */
-#define TRxCDP 3 /* TRxC = DPLL output */
-#define TRxCOI 4 /* TRxC O/I */
-#define TCRTxCP 0 /* Transmit clock = RTxC pin */
-#define TCTRxCP 8 /* Transmit clock = TRxC pin */
-#define TCBR 0x10 /* Transmit clock = BR Generator output */
-#define TCDPLL 0x18 /* Transmit clock = DPLL output */
-#define RCRTxCP 0 /* Receive clock = RTxC pin */
-#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
-#define RCBR 0x40 /* Receive clock = BR Generator output */
-#define RCDPLL 0x60 /* Receive clock = DPLL output */
-#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (Lower Byte of Baud Rate Generator Time Constant) */
-
-/* Write Register 13 (Upper Byte of Baud Rate Generator Time Constant) */
-
-/* Write Register 14 (Miscellaneous Control Bits) */
-#define BRENABL 1 /* Baud rate generator enable */
-#define BRSRC 2 /* Baud rate generator source */
-#define DTRREQ 4 /* DTR/Request function */
-#define AUTOECHO 8 /* Auto Echo */
-#define LOOPBAK 0x10 /* Local loopback */
-#define SEARCH 0x20 /* Enter search mode */
-#define RMC 0x40 /* Reset missing clock */
-#define DISDPLL 0x60 /* Disable DPLL */
-#define SSBR 0x80 /* Set DPLL source = BR generator */
-#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
-#define SFMM 0xc0 /* Set FM mode */
-#define SNRZI 0xe0 /* Set NRZI mode */
-
-/* Write Register 15 (External/Status Interrupt Control) */
-#define WR7P_EN 1 /* WR7 Prime SDLC Feature Enable */
-#define ZCIE 2 /* Zero count IE */
-#define DCDIE 8 /* DCD IE */
-#define SYNCIE 0x10 /* Sync/hunt IE */
-#define CTSIE 0x20 /* CTS IE */
-#define TxUIE 0x40 /* Tx Underrun/EOM IE */
-#define BRKIE 0x80 /* Break/Abort IE */
-
-
-/* Read Register 0 (Transmit/Receive Buffer Status and External Status) */
-#define Rx_CH_AV 0x1 /* Rx Character Available */
-#define ZCOUNT 0x2 /* Zero count */
-#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
-#define DCD 0x8 /* DCD */
-#define SYNC_HUNT 0x10 /* Sync/hunt */
-#define CTS 0x20 /* CTS */
-#define TxEOM 0x40 /* Tx underrun */
-#define BRK_ABRT 0x80 /* Break/Abort */
-
-/* Read Register 1 (Special Receive Condition Status) */
-#define ALL_SNT 0x1 /* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define RES3 0x8 /* 0/3 */
-#define RES4 0x4 /* 0/4 */
-#define RES5 0xc /* 0/5 */
-#define RES6 0x2 /* 0/6 */
-#define RES7 0xa /* 0/7 */
-#define RES8 0x6 /* 0/8 */
-#define RES18 0xe /* 1/8 */
-#define RES28 0x0 /* 2/8 */
-/* Special Rx Condition Interrupts */
-#define PAR_ERR 0x10 /* Parity Error */
-#define Rx_OVR 0x20 /* Rx Overrun Error */
-#define FRM_ERR 0x40 /* CRC/Framing Error */
-#define END_FR 0x80 /* End of Frame (SDLC) */
-
-/* Read Register 2 (Interrupt Vector (WR2) -- channel A). */
-
-/* Read Register 2 (Modified Interrupt Vector -- channel B). */
-
-/* Read Register 3 (Interrupt Pending Bits -- channel A only). */
-#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
-#define CHBTxIP 0x2 /* Channel B Tx IP */
-#define CHBRxIP 0x4 /* Channel B Rx IP */
-#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
-#define CHATxIP 0x10 /* Channel A Tx IP */
-#define CHARxIP 0x20 /* Channel A Rx IP */
-
-/* Read Register 6 (SDLC FIFO Status and Byte Count LSB) */
-
-/* Read Register 7 (SDLC FIFO Status and Byte Count MSB) */
-
-/* Read Register 8 (Receive Data) */
-
-/* Read Register 10 (Miscellaneous Status Bits) */
-#define ONLOOP 2 /* On loop */
-#define LOOPSEND 0x10 /* Loop sending */
-#define CLK2MIS 0x40 /* Two clocks missing */
-#define CLK1MIS 0x80 /* One clock missing */
-
-/* Read Register 12 (Lower Byte of Baud Rate Generator Constant (WR12)) */
-
-/* Read Register 13 (Upper Byte of Baud Rate Generator Constant (WR13) */
-
-/* Read Register 15 (External/Status Interrupt Control (WR15)) */
-
-#endif /* _SERIAL_ZS_H */