diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/8250.c | 2 | ||||
-rw-r--r-- | drivers/serial/8250_acpi.c | 183 | ||||
-rw-r--r-- | drivers/serial/8250_au1x00.c | 2 | ||||
-rw-r--r-- | drivers/serial/8250_hp300.c | 10 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 25 | ||||
-rw-r--r-- | drivers/serial/Makefile | 2 | ||||
-rw-r--r-- | drivers/serial/amba-pl010.c | 270 | ||||
-rw-r--r-- | drivers/serial/au1x00_uart.c | 1287 | ||||
-rw-r--r-- | drivers/serial/ioc4_serial.c | 387 | ||||
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 2 | ||||
-rw-r--r-- | drivers/serial/mpsc.c | 260 | ||||
-rw-r--r-- | drivers/serial/mpsc.h | 289 | ||||
-rw-r--r-- | drivers/serial/serial_txx9.c | 2 | ||||
-rw-r--r-- | drivers/serial/sunsu.c | 2 |
14 files changed, 632 insertions, 2091 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 5996d3cd0ed..674b15c78f6 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1528,7 +1528,7 @@ static int serial8250_startup(struct uart_port *port) /* * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) + * (they will be reenabled in set_termios()) */ serial8250_clear_fifos(up); diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c deleted file mode 100644 index 809f89ab965..00000000000 --- a/drivers/serial/8250_acpi.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard - * Copyright (C) 2004 Hewlett-Packard Co - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include <linux/acpi.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/serial_core.h> - -#include <acpi/acpi_bus.h> - -#include <asm/io.h> - -#include "8250.h" - -struct serial_private { - int line; -}; - -static acpi_status acpi_serial_mmio(struct uart_port *port, - struct acpi_resource_address64 *addr) -{ - port->mapbase = addr->minimum; - port->iotype = UPIO_MEM; - port->flags |= UPF_IOREMAP; - return AE_OK; -} - -static acpi_status acpi_serial_port(struct uart_port *port, - struct acpi_resource_io *io) -{ - if (io->address_length) { - port->iobase = io->minimum; - port->iotype = UPIO_PORT; - } else - printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__); - return AE_OK; -} - -static acpi_status acpi_serial_ext_irq(struct uart_port *port, - struct acpi_resource_extended_irq *ext_irq) -{ - int rc; - - if (ext_irq->interrupt_count > 0) { - rc = acpi_register_gsi(ext_irq->interrupts[0], - ext_irq->triggering, ext_irq->polarity); - if (rc < 0) - return AE_ERROR; - port->irq = rc; - } - return AE_OK; -} - -static acpi_status acpi_serial_irq(struct uart_port *port, - struct acpi_resource_irq *irq) -{ - int rc; - - if (irq->interrupt_count > 0) { - rc = acpi_register_gsi(irq->interrupts[0], - irq->triggering, irq->polarity); - if (rc < 0) - return AE_ERROR; - port->irq = rc; - } - return AE_OK; -} - -static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data) -{ - struct uart_port *port = (struct uart_port *) data; - struct acpi_resource_address64 addr; - acpi_status status; - - status = acpi_resource_to_address64(res, &addr); - if (ACPI_SUCCESS(status)) - return acpi_serial_mmio(port, &addr); - else if (res->type == ACPI_RESOURCE_TYPE_IO) - return acpi_serial_port(port, &res->data.io); - else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) - return acpi_serial_ext_irq(port, &res->data.extended_irq); - else if (res->type == ACPI_RESOURCE_TYPE_IRQ) - return acpi_serial_irq(port, &res->data.irq); - return AE_OK; -} - -static int acpi_serial_add(struct acpi_device *device) -{ - struct serial_private *priv; - acpi_status status; - struct uart_port port; - int result; - - memset(&port, 0, sizeof(struct uart_port)); - - port.uartclk = 1843200; - port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - - priv = kmalloc(sizeof(struct serial_private), GFP_KERNEL); - if (!priv) { - result = -ENOMEM; - goto fail; - } - memset(priv, 0, sizeof(*priv)); - - status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, - acpi_serial_resource, &port); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto fail; - } - - if (!port.mapbase && !port.iobase) { - printk(KERN_ERR "%s: no iomem or port address in %s _CRS\n", - __FUNCTION__, device->pnp.bus_id); - result = -ENODEV; - goto fail; - } - - priv->line = serial8250_register_port(&port); - if (priv->line < 0) { - printk(KERN_WARNING "Couldn't register serial port %s: %d\n", - device->pnp.bus_id, priv->line); - result = -ENODEV; - goto fail; - } - - acpi_driver_data(device) = priv; - return 0; - -fail: - kfree(priv); - - return result; -} - -static int acpi_serial_remove(struct acpi_device *device, int type) -{ - struct serial_private *priv; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - priv = acpi_driver_data(device); - serial8250_unregister_port(priv->line); - kfree(priv); - - return 0; -} - -static struct acpi_driver acpi_serial_driver = { - .name = "serial", - .class = "", - .ids = "PNP0501", - .ops = { - .add = acpi_serial_add, - .remove = acpi_serial_remove, - }, -}; - -static int __init acpi_serial_init(void) -{ - return acpi_bus_register_driver(&acpi_serial_driver); -} - -static void __exit acpi_serial_exit(void) -{ - acpi_bus_unregister_driver(&acpi_serial_driver); -} - -module_init(acpi_serial_init); -module_exit(acpi_serial_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic 8250/16x50 ACPI serial driver"); diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c index 8d8d7a70d03..3d1bfd07208 100644 --- a/drivers/serial/8250_au1x00.c +++ b/drivers/serial/8250_au1x00.c @@ -51,7 +51,7 @@ static struct plat_serial8250_port au1x00_data[] = { #elif defined(CONFIG_SOC_AU1100) PORT(UART0_ADDR, AU1100_UART0_INT), PORT(UART1_ADDR, AU1100_UART1_INT), - PORT(UART2_ADDR, AU1100_UART2_INT), + /* The internal UART2 does not exist on the AU1100 processor. */ PORT(UART3_ADDR, AU1100_UART3_INT), #elif defined(CONFIG_SOC_AU1550) PORT(UART0_ADDR, AU1550_UART0_INT), diff --git a/drivers/serial/8250_hp300.c b/drivers/serial/8250_hp300.c index 4315afe9c08..53e81a44c1a 100644 --- a/drivers/serial/8250_hp300.c +++ b/drivers/serial/8250_hp300.c @@ -55,6 +55,8 @@ static struct dio_driver hpdca_driver = { #endif +static unsigned int num_ports; + extern int hp300_uart_scode; /* Offset to UART registers from base of DCA */ @@ -199,6 +201,8 @@ static int __devinit hpdca_init_one(struct dio_dev *d, out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff); udelay(100); + num_ports++; + return 0; } #endif @@ -206,7 +210,6 @@ static int __devinit hpdca_init_one(struct dio_dev *d, static int __init hp300_8250_init(void) { static int called = 0; - int num_ports; #ifdef CONFIG_HPAPCI int line; unsigned long base; @@ -221,11 +224,8 @@ static int __init hp300_8250_init(void) if (!MACH_IS_HP300) return -ENODEV; - num_ports = 0; - #ifdef CONFIG_HPDCA - if (dio_module_init(&hpdca_driver) == 0) - num_ports++; + dio_register_driver(&hpdca_driver); #endif #ifdef CONFIG_HPAPCI if (hp300_model < HP_400) { diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index c66ef96c71b..fe0d8b8e91c 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -77,14 +77,6 @@ config SERIAL_8250_CS If unsure, say N. -config SERIAL_8250_ACPI - bool "8250/16550 device discovery via ACPI namespace" - default y if IA64 - depends on ACPI && SERIAL_8250 - ---help--- - If you wish to enable serial port discovery via the ACPI - namespace, say Y here. If unsure, say N. - config SERIAL_8250_NR_UARTS int "Maximum number of 8250/16550 serial ports" depends on SERIAL_8250 @@ -628,22 +620,6 @@ config SERIAL_SH_SCI_CONSOLE depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE -config SERIAL_AU1X00 - bool "Enable Au1x00 UART Support" - depends on MIPS && SOC_AU1X00 - select SERIAL_CORE - help - If you have an Alchemy AU1X00 processor (MIPS based) and you want - to use serial ports, say Y. Otherwise, say N. - -config SERIAL_AU1X00_CONSOLE - bool "Enable Au1x00 serial console" - depends on SERIAL_AU1X00 - select SERIAL_CORE_CONSOLE - help - If you have an Alchemy AU1X00 processor (MIPS based) and you want - to use a console on a serial port, say Y. Otherwise, say N. - config SERIAL_CORE tristate @@ -827,6 +803,7 @@ 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 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 50c221af9e6..d2b4c214876 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -5,7 +5,6 @@ # serial-8250-y := -serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o serial-8250-$(CONFIG_PNP) += 8250_pnp.o serial-8250-$(CONFIG_GSC) += 8250_gsc.o serial-8250-$(CONFIG_PCI) += 8250_pci.o @@ -42,7 +41,6 @@ obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_V850E_UART) += v850e_uart.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o -obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o obj-$(CONFIG_SERIAL_DZ) += dz.o obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index e04d5e82d9a..1631414000a 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -51,8 +51,6 @@ #include <linux/amba/serial.h> #include <asm/io.h> -#include <asm/irq.h> -#include <asm/hardware.h> #define UART_NR 2 @@ -62,47 +60,19 @@ #define AMBA_ISR_PASS_LIMIT 256 -/* - * Access macros for the AMBA UARTs - */ -#define UART_GET_INT_STATUS(p) readb((p)->membase + UART010_IIR) -#define UART_PUT_ICR(p, c) writel((c), (p)->membase + UART010_ICR) -#define UART_GET_FR(p) readb((p)->membase + UART01x_FR) -#define UART_GET_CHAR(p) readb((p)->membase + UART01x_DR) -#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + UART01x_DR) -#define UART_GET_RSR(p) readb((p)->membase + UART01x_RSR) -#define UART_GET_CR(p) readb((p)->membase + UART010_CR) -#define UART_PUT_CR(p,c) writel((c), (p)->membase + UART010_CR) -#define UART_GET_LCRL(p) readb((p)->membase + UART010_LCRL) -#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + UART010_LCRL) -#define UART_GET_LCRM(p) readb((p)->membase + UART010_LCRM) -#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + UART010_LCRM) -#define UART_GET_LCRH(p) readb((p)->membase + UART010_LCRH) -#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + UART010_LCRH) #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) -#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0) -#define UART_DUMMY_RSR_RX /*256*/0 +#define UART_DUMMY_RSR_RX 256 #define UART_PORT_SIZE 64 /* - * On the Integrator platform, the port RTS and DTR are provided by - * bits in the following SC_CTRLS register bits: - * RTS DTR - * UART0 7 6 - * UART1 5 4 - */ -#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) -#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) - -/* * We wrap our port structure around the generic uart_port. */ struct uart_amba_port { struct uart_port port; - unsigned int dtr_mask; - unsigned int rts_mask; + struct amba_device *dev; + struct amba_pl010_data *data; unsigned int old_status; }; @@ -110,36 +80,36 @@ static void pl010_stop_tx(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr &= ~UART010_CR_TIE; - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void pl010_start_tx(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr |= UART010_CR_TIE; - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void pl010_stop_rx(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void pl010_enable_ms(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr |= UART010_CR_MSIE; - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void @@ -152,9 +122,9 @@ pl010_rx_chars(struct uart_port *port) struct tty_struct *tty = port->info->tty; unsigned int status, ch, flag, rsr, max_count = 256; - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); while (UART_RX_DATA(status) && max_count--) { - ch = UART_GET_CHAR(port); + ch = readb(port->membase + UART01x_DR); flag = TTY_NORMAL; port->icount.rx++; @@ -163,7 +133,7 @@ pl010_rx_chars(struct uart_port *port) * Note that the error handling code is * out of the main execution path */ - rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; + rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); @@ -193,7 +163,7 @@ pl010_rx_chars(struct uart_port *port) uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); ignore_char: - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); } tty_flip_buffer_push(tty); return; @@ -205,7 +175,7 @@ static void pl010_tx_chars(struct uart_port *port) int count; if (port->x_char) { - UART_PUT_CHAR(port, port->x_char); + writel(port->x_char, port->membase + UART01x_DR); port->icount.tx++; port->x_char = 0; return; @@ -217,7 +187,7 @@ static void pl010_tx_chars(struct uart_port *port) count = port->fifosize >> 1; do { - UART_PUT_CHAR(port, xmit->buf[xmit->tail]); + writel(xmit->buf[xmit->tail], port->membase + UART01x_DR); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; if (uart_circ_empty(xmit)) @@ -236,9 +206,9 @@ static void pl010_modem_status(struct uart_port *port) struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status, delta; - UART_PUT_ICR(&uap->port, 0); + writel(0, uap->port.membase + UART010_ICR); - status = UART_GET_FR(&uap->port) & UART01x_FR_MODEM_ANY; + status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -266,7 +236,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) spin_lock(&port->lock); - status = UART_GET_INT_STATUS(port); + status = readb(port->membase + UART010_IIR); if (status) { do { if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) @@ -283,7 +253,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) if (pass_counter-- == 0) break; - status = UART_GET_INT_STATUS(port); + status = readb(port->membase + UART010_IIR); } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | UART010_IIR_TIS)); handled = 1; @@ -296,7 +266,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) static unsigned int pl010_tx_empty(struct uart_port *port) { - return UART_GET_FR(port) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; + return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; } static unsigned int pl010_get_mctrl(struct uart_port *port) @@ -304,7 +274,7 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) unsigned int result = 0; unsigned int status; - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); if (status & UART01x_FR_DCD) result |= TIOCM_CAR; if (status & UART01x_FR_DSR) @@ -318,20 +288,9 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned int ctrls = 0, ctrlc = 0; - - if (mctrl & TIOCM_RTS) - ctrlc |= uap->rts_mask; - else - ctrls |= uap->rts_mask; - - if (mctrl & TIOCM_DTR) - ctrlc |= uap->dtr_mask; - else - ctrls |= uap->dtr_mask; - __raw_writel(ctrls, SC_CTRLS); - __raw_writel(ctrlc, SC_CTRLC); + 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) @@ -340,12 +299,12 @@ static void pl010_break_ctl(struct uart_port *port, int break_state) unsigned int lcr_h; spin_lock_irqsave(&port->lock, flags); - lcr_h = UART_GET_LCRH(port); + lcr_h = readb(port->membase + UART010_LCRH); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - UART_PUT_LCRH(port, lcr_h); + writel(lcr_h, port->membase + UART010_LCRH); spin_unlock_irqrestore(&port->lock, flags); } @@ -364,13 +323,13 @@ static int pl010_startup(struct uart_port *port) /* * initialise the old status of the modem signals */ - uap->old_status = UART_GET_FR(port) & UART01x_FR_MODEM_ANY; + uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY; /* * Finally, enable interrupts */ - UART_PUT_CR(port, UART01x_CR_UARTEN | UART010_CR_RIE | - UART010_CR_RTIE); + writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, + port->membase + UART010_CR); return 0; } @@ -385,11 +344,12 @@ static void pl010_shutdown(struct uart_port *port) /* * disable all interrupts, disable the port */ - UART_PUT_CR(port, 0); + writel(0, port->membase + UART010_CR); /* disable break condition and fifos */ - UART_PUT_LCRH(port, UART_GET_LCRH(port) & - ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN)); + writel(readb(port->membase + UART010_LCRH) & + ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), + port->membase + UART010_LCRH); } static void @@ -466,25 +426,25 @@ pl010_set_termios(struct uart_port *port, struct termios *termios, port->ignore_status_mask |= UART_DUMMY_RSR_RX; /* first, disable everything */ - old_cr = UART_GET_CR(port) & ~UART010_CR_MSIE; + old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE; if (UART_ENABLE_MS(port, termios->c_cflag)) old_cr |= UART010_CR_MSIE; - UART_PUT_CR(port, 0); + writel(0, port->membase + UART010_CR); /* Set baud rate */ quot -= 1; - UART_PUT_LCRM(port, ((quot & 0xf00) >> 8)); - UART_PUT_LCRL(port, (quot & 0xff)); + writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM); + writel(quot & 0xff, port->membase + UART010_LCRL); /* * ----------v----------v----------v----------v----- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ - UART_PUT_LCRH(port, lcr_h); - UART_PUT_CR(port, old_cr); + writel(lcr_h, port->membase + UART010_LCRH); + writel(old_cr, port->membase + UART010_CR); spin_unlock_irqrestore(&port->lock, flags); } @@ -556,59 +516,32 @@ static struct uart_ops amba_pl010_pops = { .verify_port = pl010_verify_port, }; -static struct uart_amba_port amba_ports[UART_NR] = { - { - .port = { - .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), - .mapbase = INTEGRATOR_UART0_BASE, - .iotype = UPIO_MEM, - .irq = IRQ_UARTINT0, - .uartclk = 14745600, - .fifosize = 16, - .ops = &amba_pl010_pops, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - }, - .dtr_mask = 1 << 5, - .rts_mask = 1 << 4, - }, - { - .port = { - .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), - .mapbase = INTEGRATOR_UART1_BASE, - .iotype = UPIO_MEM, - .irq = IRQ_UARTINT1, - .uartclk = 14745600, - .fifosize = 16, - .ops = &amba_pl010_pops, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - }, - .dtr_mask = 1 << 7, - .rts_mask = 1 << 6, - } -}; +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) { - while (!UART_TX_READY(UART_GET_FR(port))) + unsigned int status; + + do { + status = readb(port->membase + UART01x_FR); barrier(); - UART_PUT_CHAR(port, ch); + } while (!UART_TX_READY(status)); + writel(ch, port->membase + UART01x_DR); } static void pl010_console_write(struct console *co, const char *s, unsigned int count) { - struct uart_port *port = &amba_ports[co->index].port; + struct uart_port *port = &amba_ports[co->index]->port; unsigned int status, old_cr; /* * First save the CR then disable the interrupts */ - old_cr = UART_GET_CR(port); - UART_PUT_CR(port, UART01x_CR_UARTEN); + old_cr = readb(port->membase + UART010_CR); + writel(UART01x_CR_UARTEN, port->membase + UART010_CR); uart_console_write(port, s, count, pl010_console_putchar); @@ -617,18 +550,19 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) * and restore the TCR */ do { - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); + barrier(); } while (status & UART01x_FR_BUSY); - UART_PUT_CR(port, old_cr); + writel(old_cr, port->membase + UART010_CR); } static void __init pl010_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { - if (UART_GET_CR(port) & UART01x_CR_UARTEN) { + if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, quot; - lcr_h = UART_GET_LCRH(port); + lcr_h = readb(port->membase + UART010_LCRH); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -643,7 +577,7 @@ pl010_console_get_options(struct uart_port *port, int *baud, else *bits = 8; - quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8; + quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8; *baud = port->uartclk / (16 * (quot + 1)); } } @@ -663,7 +597,7 @@ static int __init pl010_console_setup(struct console *co, char *options) */ if (co->index >= UART_NR) co->index = 0; - port = &amba_ports[co->index].port; + port = &amba_ports[co->index]->port; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -684,24 +618,6 @@ static struct console amba_console = { .data = &amba_reg, }; -static int __init amba_console_init(void) -{ - /* - * All port initializations are done statically - */ - register_console(&amba_console); - return 0; -} -console_initcall(amba_console_init); - -static int __init amba_late_console_init(void) -{ - if (!(amba_console.flags & CON_ENABLED)) - register_console(&amba_console); - return 0; -} -late_initcall(amba_late_console_init); - #define AMBA_CONSOLE &amba_console #else #define AMBA_CONSOLE NULL @@ -719,30 +635,76 @@ static struct uart_driver amba_reg = { static int pl010_probe(struct amba_device *dev, void *id) { - int i; + struct uart_amba_port *port; + void __iomem *base; + int i, ret; - for (i = 0; i < UART_NR; i++) { - if (amba_ports[i].port.mapbase != dev->res.start) - continue; + for (i = 0; i < ARRAY_SIZE(amba_ports); i++) + if (amba_ports[i] == NULL) + break; - amba_ports[i].port.dev = &dev->dev; - uart_add_one_port(&amba_reg, &amba_ports[i].port); - amba_set_drvdata(dev, &amba_ports[i]); - break; + if (i == ARRAY_SIZE(amba_ports)) { + ret = -EBUSY; + goto out; } - return 0; + port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); + if (!port) { + ret = -ENOMEM; + goto out; + } + + base = ioremap(dev->res.start, PAGE_SIZE); + if (!base) { + ret = -ENOMEM; + goto free; + } + + port->port.dev = &dev->dev; + port->port.mapbase = dev->res.start; + port->port.membase = base; + port->port.iotype = UPIO_MEM; + port->port.irq = dev->irq[0]; + port->port.uartclk = 14745600; + port->port.fifosize = 16; + port->port.ops = &amba_pl010_pops; + port->port.flags = UPF_BOOT_AUTOCONF; + port->port.line = i; + port->dev = dev; + port->data = dev->dev.platform_data; + + amba_ports[i] = port; + + amba_set_drvdata(dev, port); + ret = uart_add_one_port(&amba_reg, &port->port); + if (ret) { + amba_set_drvdata(dev, NULL); + amba_ports[i] = NULL; + iounmap(base); + free: + kfree(port); + } + + out: + return ret; } static int pl010_remove(struct amba_device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); - - if (uap) - uart_remove_one_port(&amba_reg, &uap->port); + struct uart_amba_port *port = amba_get_drvdata(dev); + int i; amba_set_drvdata(dev, NULL); + uart_remove_one_port(&amba_reg, &port->port); + + for (i = 0; i < ARRAY_SIZE(amba_ports); i++) + if (amba_ports[i] == port) + amba_ports[i] = NULL; + + iounmap(port->port.membase); + kfree(port); + return 0; } diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c deleted file mode 100644 index 948880ac587..00000000000 --- a/drivers/serial/au1x00_uart.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* - * 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. 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. - */ -#include <linux/config.h> -#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/serial.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/mach-au1x00/au1000.h> - -#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/serial_core.h> -#include "8250.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) - -static struct old_serial_port old_serial_port[] = { - { .baud_base = 0, - .iomem_base = (u8 *)UART0_ADDR, - .irq = AU1000_UART0_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2, - }, { - .baud_base = 0, - .iomem_base = (u8 *)UART1_ADDR, - .irq = AU1000_UART1_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2 - }, { - .baud_base = 0, - .iomem_base = (u8 *)UART2_ADDR, - .irq = AU1000_UART2_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2 - }, { - .baud_base = 0, - .iomem_base = (u8 *)UART3_ADDR, - .irq = AU1000_UART3_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2 - } -}; - -#define UART_NR ARRAY_SIZE(old_serial_port) - -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 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_MAX_8250+1] = { - { "unknown", 1, 0 }, - { "8250", 1, 0 }, - { "16450", 1, 0 }, - { "16550", 1, 0 }, - /* PORT_16550A */ - { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO }, -}; - -static unsigned int serial_in(struct uart_8250_port *up, int offset) -{ - return au_readl((unsigned long)up->port.membase + offset); -} - -static void serial_out(struct uart_8250_port *up, int offset, int value) -{ - au_writel(value, (unsigned long)up->port.membase + offset); -} - -#define serial_inp(up, offset) serial_in(up, offset) -#define serial_outp(up, offset, value) serial_out(up, offset, value) - -/* - * 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 save_lcr, save_mcr; - unsigned long flags; - - if (!up->port.iobase && !up->port.mapbase && !up->port.membase) - return; - - DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ", - up->port.line, 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); -// save_flags(flags); cli(); - - save_mcr = serial_in(up, UART_MCR); - save_lcr = serial_in(up, UART_LCR); - - up->port.type = PORT_16550A; - serial_outp(up, UART_LCR, save_lcr); - - up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; - - if (up->port.type == PORT_UNKNOWN) - goto out; - - /* - * Reset the UART. - */ - 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); -// restore_flags(flags); - DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); -} - -static void serial8250_stop_tx(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - - if (up->ier & UART_IER_THRI) { - up->ier &= ~UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - } -} - -static void serial8250_start_tx(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - - if (!(up->ier & UART_IER_THRI)) { - up->ier |= UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - } -} - -static void serial8250_stop_rx(struct uart_port *port) -{ - struct uart_8250_port *up = (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 = (struct uart_8250_port *)port; - - up->ier |= UART_IER_MSI; - serial_out(up, UART_IER, up->ier); -} - -static void -receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) -{ - struct tty_struct *tty = up->port.info->tty; - unsigned char ch, flag; - int max_count = 256; - - 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++; - /* - * 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; - -#ifdef CONFIG_SERIAL_AU1X00_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) { - 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, regs)) - 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)); - spin_unlock(&up->port.lock); - tty_flip_buffer_push(tty); - spin_lock(&up->port.lock); -} - -static void transmit_chars(struct uart_8250_port *up) -{ - struct circ_buf *xmit = &up->port.info->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_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - serial8250_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 (--count > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); - - DEBUG_INTR("THRE..."); - - if (uart_circ_empty(xmit)) - serial8250_stop_tx(&up->port); -} - -static void check_modem_status(struct uart_8250_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.info->delta_msr_wait); -} - -/* - * This handles the interrupt from one port. - */ -static inline void -serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) -{ - unsigned int status = serial_inp(up, UART_LSR); - - DEBUG_INTR("status = %x...", status); - - if (status & UART_LSR_DR) - receive_chars(up, &status, regs); - check_modem_status(up); - if (status & UART_LSR_THRE) - 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 serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct irq_info *i = dev_id; - struct list_head *l, *end = NULL; - int pass_counter = 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)) { - spin_lock(&up->port.lock); - serial8250_handle_port(up, regs); - 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 we hit this, we're dead. */ - printk(KERN_ERR "serial8250: too much work for " - "irq%d\n", irq); - break; - } - } while (l != end); - - spin_unlock(&i->lock); - - DEBUG_INTR("end.\n"); - /* FIXME! Was it really ours? */ - 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_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); -} - -static int serial_link_irq_chain(struct uart_8250_port *up) -{ - struct irq_info *i = irq_lists + up->port.irq; - int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 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, 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 = irq_lists + up->port.irq; - - BUG_ON(i->head == NULL); - - if (list_empty(i->head)) - free_irq(up->port.irq, i); - - serial_do_unlink(i, up); -} - -/* - * 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 timeout; - unsigned int iir; - - iir = serial_in(up, UART_IIR); - if (!(iir & UART_IIR_NO_INT)) { - spin_lock(&up->port.lock); - serial8250_handle_port(up, NULL); - 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 serial8250_tx_empty(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_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 serial8250_get_mctrl(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_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 serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - struct uart_8250_port *up = (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; - - serial_out(up, UART_MCR, mcr); -} - -static void serial8250_break_ctl(struct uart_port *port, int break_state) -{ - struct uart_8250_port *up = (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); -} - -static int serial8250_startup(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long flags; - int retval; - - /* - * Clear the FIFO buffers and disable them. - * (they will be reeanbled 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; - } - - 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); - 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 serial8250_shutdown(struct uart_port *port) -{ - struct uart_8250_port *up = (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); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_FCR, 0); - - /* - * Read data port to reset things, and then unlink from - * the IRQ chain. - */ - (void) serial_in(up, UART_RX); - - if (!is_real_interrupt(up->port.irq)) - del_timer_sync(&up->timer); - else - 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; -} - -static void -serial8250_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) -{ - struct uart_8250_port *up = (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, 0, port->uartclk/16); - quot = serial8250_get_divisor(port, baud); - quot = 0x35; /* FIXME */ - - /* - * 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 (baud < 2400) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1; - else - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8; - } - - /* - * 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 (UART_ENABLE_MS(&up->port, termios->c_cflag)) - up->ier |= UART_IER_MSI; - - serial_out(up, UART_IER, up->ier); - serial_outp(up, 0x28, quot & 0xffff); - 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 */ - } - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static void -serial8250_pm(struct uart_port *port, unsigned int state, - unsigned int oldstate) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - if (state) { - /* sleep */ - if (up->pm) - up->pm(port, state, oldstate); - } else { - /* wake */ - 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 -serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res) -{ - unsigned int size = 8 << up->port.regshift; - int ret = 0; - - switch (up->port.iotype) { - case UPIO_MEM: - if (up->port.mapbase) { - *res = request_mem_region(up->port.mapbase, size, "serial"); - if (!*res) - ret = -EBUSY; - } - break; - - case UPIO_HUB6: - case UPIO_PORT: - *res = request_region(up->port.iobase, size, "serial"); - if (!*res) - ret = -EBUSY; - break; - } - return ret; -} - - -static void serial8250_release_port(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_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_HUB6: - 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 serial8250_request_port(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - struct resource *res = NULL, *res_rsa = NULL; - int ret = 0; - - ret = serial8250_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_rsa) - release_resource(res_rsa); - if (res) - release_resource(res); - } - return ret; -} - -static void serial8250_config_port(struct uart_port *port, int flags) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - struct resource *res_std = NULL, *res_rsa = NULL; - int probeflags = PROBE_ANY; - - probeflags &= ~PROBE_RSA; - - if (flags & UART_CONFIG_TYPE) - autoconfig(up, probeflags); - - /* - * If the port wasn't an RSA port, release the resource. - */ - if (up->port.type != PORT_RSA && res_rsa) - release_resource(res_rsa); - - if (up->port.type == PORT_UNKNOWN && res_std) - release_resource(res_std); -} - -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 > PORT_MAX_8250 || 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, - .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, -}; - -static struct uart_8250_port serial8250_ports[UART_NR]; - -static void __init serial8250_isa_init_ports(void) -{ - struct uart_8250_port *up; - static int first = 1; - int i; - - if (!first) - return; - first = 0; - - for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port); - i++, up++) { - up->port.iobase = old_serial_port[i].port; - up->port.irq = old_serial_port[i].irq; - up->port.uartclk = get_au1x00_uart_baud_base(); - 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; - up->port.ops = &serial8250_pops; - } -} - -static void __init serial8250_register_ports(struct uart_driver *drv) -{ - int i; - - serial8250_isa_init_ports(); - - for (i = 0; i < UART_NR; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; - - up->port.line = i; - up->port.ops = &serial8250_pops; - 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; - - uart_add_one_port(drv, &up->port); - } -} - -#ifdef CONFIG_SERIAL_AU1X00_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_8250_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 au1x00_console_putchar(struct uart_port *port, int ch) -{ - struct uart_8250_port *up = (struct uart_8250_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 -serial8250_console_write(struct console *co, const char *s, unsigned int count) -{ - struct uart_8250_port *up = &serial8250_ports[co->index]; - unsigned int ier; - - /* - * 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, au1x00_console_putchar); - - /* - * Finally, wait for transmitter to become empty - * and restore the IER - */ - wait_for_xmitr(up); - serial_out(up, UART_IER, ier); -} - -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 >= UART_NR) - co->index = 0; - port = &serial8250_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); -} - -extern struct uart_driver serial8250_reg; -static struct console serial8250_console = { - .name = "ttyS", - .write = serial8250_console_write, - .device = uart_console_device, - .setup = serial8250_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &serial8250_reg, -}; - -static int __init serial8250_console_init(void) -{ - serial8250_isa_init_ports(); - register_console(&serial8250_console); - return 0; -} -console_initcall(serial8250_console_init); - -#define SERIAL8250_CONSOLE &serial8250_console -#else -#define SERIAL8250_CONSOLE NULL -#endif - -static struct uart_driver serial8250_reg = { - .owner = THIS_MODULE, - .driver_name = "serial", - .devfs_name = "tts/", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = 64, - .nr = UART_NR, - .cons = SERIAL8250_CONSOLE, -}; - -int __init early_serial_setup(struct uart_port *port) -{ - serial8250_isa_init_ports(); - serial8250_ports[port->line].port = *port; - serial8250_ports[port->line].port.ops = &serial8250_pops; - return 0; -} - -/** - * serial8250_suspend_port - suspend one serial port - * @line: serial line number - * @level: the level of port suspension, as per uart_suspend_port - * - * 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 - * @level: the level of port resumption, as per uart_resume_port - * - * Resume one serial port. - */ -void serial8250_resume_port(int line) -{ - uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); -} - -static int __init serial8250_init(void) -{ - int ret, i; - - printk(KERN_INFO "Serial: Au1x00 driver\n"); - - for (i = 0; i < NR_IRQS; i++) - spin_lock_init(&irq_lists[i].lock); - - ret = uart_register_driver(&serial8250_reg); - if (ret >= 0) - serial8250_register_ports(&serial8250_reg); - - return ret; -} - -static void __exit serial8250_exit(void) -{ - int i; - - for (i = 0; i < UART_NR; i++) - uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port); - - uart_unregister_driver(&serial8250_reg); -} - -module_init(serial8250_init); -module_exit(serial8250_exit); - -EXPORT_SYMBOL(serial8250_suspend_port); -EXPORT_SYMBOL(serial8250_resume_port); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au1x00 serial driver\n"); diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index a37579ce6d7..c620209d7b9 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. */ @@ -323,9 +323,12 @@ static unsigned int Num_of_ioc4_cards; #define IOC4_FIFO_CHARS 255 /* Device name we're using */ -#define DEVICE_NAME "ttyIOC" -#define DEVICE_MAJOR 204 -#define DEVICE_MINOR 50 +#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 @@ -341,10 +344,8 @@ static unsigned int Num_of_ioc4_cards; #define MAX_BAUD_SUPPORTED 115200 /* protocol types supported */ -enum sio_proto { - PROTO_RS232, - PROTO_RS422 -}; +#define PROTO_RS232 3 +#define PROTO_RS422 7 /* Notification types */ #define N_DATA_READY 0x01 @@ -395,11 +396,17 @@ enum sio_proto { /* * 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 */ - struct uart_port icp_uart_port; + /* 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]; @@ -443,7 +450,9 @@ struct ioc4_soft { /* Local port info for each IOC4 serial ports */ struct ioc4_port { - struct uart_port *ip_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; @@ -502,6 +511,9 @@ struct ioc4_port { #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 @@ -623,6 +635,23 @@ struct ring_buffer { 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 @@ -708,19 +737,33 @@ static int set_baud(struct ioc4_port *port, int baud) /** * 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) +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; - int ii; + struct ioc4_port *port; + int port_num, port_type; if (control) { - for ( ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++ ) { - if (!control->ic_port[ii].icp_port) + for ( port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; + port_num++ ) { + port = control->ic_port[port_num].icp_port; + if (!port) continue; - if (the_port == control->ic_port[ii].icp_port->ip_port) - return control->ic_port[ii].icp_port; + 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; @@ -946,6 +989,7 @@ intr_connect(struct ioc4_soft *soft, int type, * @arg: handler arg * @regs: registers */ + static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) { struct ioc4_soft *soft; @@ -953,7 +997,7 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) int xx, num_intrs = 0; int intr_type; int handled = 0; - struct ioc4_intr_info *ii; + struct ioc4_intr_info *intr_info; soft = arg; for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) { @@ -966,13 +1010,13 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) * which interrupt bits are set. */ for (xx = 0; xx < num_intrs; xx++) { - ii = &soft->is_intr_type[intr_type].is_intr_info[xx]; - if ((this_mir = this_ir & ii->sd_bits)) { + 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, ii->sd_bits, IOC4_W_IEC, + write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC, intr_type); - ii->sd_intr(ii->sd_info, this_mir); + intr_info->sd_intr(intr_info->sd_info, this_mir); this_ir &= ~this_mir; } } @@ -980,7 +1024,6 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) #ifdef DEBUG_INTERRUPTS { struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr; - spinlock_t *lp = &soft->is_ir_lock; unsigned long flag; spin_lock_irqsave(&soft->is_ir_lock, flag); @@ -1177,7 +1220,7 @@ static inline int local_open(struct ioc4_port *port) { int spiniter = 0; - port->ip_flags = 0; + port->ip_flags = PORT_ACTIVE; /* Pause the DMA interface if necessary */ if (port->ip_sscr & IOC4_SSCR_DMA_EN) { @@ -1187,6 +1230,7 @@ static inline int local_open(struct ioc4_port *port) & IOC4_SSCR_PAUSE_STATE) == 0) { spiniter++; if (spiniter > MAXITER) { + port->ip_flags = PORT_INACTIVE; return -1; } } @@ -1506,14 +1550,13 @@ static int set_notification(struct ioc4_port *port, int mask, int set_on) /** * set_mcr - set the master control reg * @the_port: port to use - * @set: set ? * @mask1: mcr mask * @mask2: shadow mask */ -static inline int set_mcr(struct uart_port *the_port, int set, +static inline int set_mcr(struct uart_port *the_port, int mask1, int mask2) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); uint32_t shadow; int spiniter = 0; char mcr; @@ -1536,13 +1579,9 @@ static inline int set_mcr(struct uart_port *the_port, int set, mcr = (shadow & 0xff000000) >> 24; /* Set new value */ - if (set) { - mcr |= mask1; - shadow |= mask2; - } else { - mcr &= ~mask1; - shadow &= ~mask2; - } + mcr |= mask1; + shadow |= mask2; + writeb(mcr, &port->ip_uart_regs->i4u_mcr); writel(shadow, &port->ip_serial_regs->shadow); @@ -1558,7 +1597,7 @@ static inline int set_mcr(struct uart_port *the_port, int set, * @port: port to use * @proto: protocol to use */ -static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto) +static int ioc4_set_proto(struct ioc4_port *port, int proto) { struct hooks *hooks = port->ip_hooks; @@ -1589,7 +1628,7 @@ static void transmit_chars(struct uart_port *the_port) int result; char *start; struct tty_struct *tty; - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); struct uart_info *info; if (!the_port) @@ -1645,7 +1684,7 @@ static void ioc4_change_speed(struct uart_port *the_port, struct termios *new_termios, struct termios *old_termios) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); int baud, bits; unsigned cflag; int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; @@ -1752,7 +1791,7 @@ static inline int ic4_startup_local(struct uart_port *the_port) if (!the_port) return -1; - port = get_ioc4_port(the_port); + port = get_ioc4_port(the_port, 0); if (!port) return -1; @@ -1760,6 +1799,9 @@ static inline int ic4_startup_local(struct uart_port *the_port) 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, info->tty->termios, (struct termios *)0); @@ -1768,17 +1810,17 @@ static inline int ic4_startup_local(struct uart_port *the_port) /* * ioc4_cb_output_lowat - called when the output low water mark is hit - * @port: port to output + * @the_port: port to output */ -static void ioc4_cb_output_lowat(struct ioc4_port *port) +static void ioc4_cb_output_lowat(struct uart_port *the_port) { unsigned long pflags; /* ip_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); + if (the_port) { + spin_lock_irqsave(&the_port->lock, pflags); + transmit_chars(the_port); + spin_unlock_irqrestore(&the_port->lock, pflags); } } @@ -1923,7 +1965,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) &port->ip_mem->sio_ir.raw); if (port->ip_notify & N_OUTPUT_LOWAT) - ioc4_cb_output_lowat(port); + ioc4_cb_output_lowat(port->ip_port); } /* Handle tx_mt. Must come after tx_explicit. */ @@ -1936,7 +1978,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) * So send the notification now. */ if (port->ip_notify & N_OUTPUT_LOWAT) { - ioc4_cb_output_lowat(port); + 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, @@ -2023,7 +2065,7 @@ 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); + struct ioc4_port *port = get_ioc4_port(the_port, 0); struct ring *inring; struct ring_entry *entry; struct hooks *hooks = port->ip_hooks; @@ -2335,17 +2377,27 @@ static void receive_chars(struct uart_port *the_port) */ static const char *ic4_type(struct uart_port *the_port) { - return "SGI IOC4 Serial"; + if (the_port->mapbase == PROTO_RS232) + return "SGI IOC4 Serial [rs232]"; + else + return "SGI IOC4 Serial [rs422]"; } /** - * ic4_tx_empty - Is the transmitter empty? We pretend we're always empty - * @port: Port to operate on (we ignore since we always return 1) + * ic4_tx_empty - Is the transmitter empty? + * @port: Port to operate on * */ static unsigned int ic4_tx_empty(struct uart_port *the_port) { - return 1; + 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; } /** @@ -2355,6 +2407,10 @@ static unsigned int ic4_tx_empty(struct uart_port *the_port) */ 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); } /** @@ -2377,11 +2433,12 @@ static void ic4_shutdown(struct uart_port *the_port) struct ioc4_port *port; struct uart_info *info; - port = get_ioc4_port(the_port); + port = get_ioc4_port(the_port, 0); if (!port) return; info = the_port->info; + port->ip_port = NULL; wake_up_interruptible(&info->delta_msr_wait); @@ -2390,6 +2447,7 @@ static void ic4_shutdown(struct uart_port *the_port) 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); } @@ -2402,6 +2460,11 @@ static void ic4_shutdown(struct uart_port *the_port) 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; @@ -2414,7 +2477,7 @@ static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl) if (mctrl & TIOCM_LOOP) mcr |= UART_MCR_LOOP; - set_mcr(the_port, 1, mcr, IOC4_SHADOW_DTR); + set_mcr(the_port, mcr, IOC4_SHADOW_DTR); } /** @@ -2424,11 +2487,11 @@ static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl) */ static unsigned int ic4_get_mctrl(struct uart_port *the_port) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); uint32_t shadow; unsigned int ret = 0; - if (!port) + if (!port_is_active(port, the_port)) return 0; shadow = readl(&port->ip_serial_regs->shadow); @@ -2448,9 +2511,9 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port) */ static void ic4_start_tx(struct uart_port *the_port) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); - if (port) { + if (port_is_active(port, the_port)) { set_notification(port, N_OUTPUT_LOWAT, 1); enable_intrs(port, port->ip_hooks->intr_tx_mt); } @@ -2467,7 +2530,7 @@ static void ic4_break_ctl(struct uart_port *the_port, int break_state) } /** - * ic4_startup - Start up the serial port - always return 0 (We're always on) + * ic4_startup - Start up the serial port * @port: Port to operate on * */ @@ -2479,17 +2542,16 @@ static int ic4_startup(struct uart_port *the_port) struct uart_info *info; unsigned long port_flags; - if (!the_port) { + if (!the_port) return -ENODEV; - } - port = get_ioc4_port(the_port); - if (!port) { + port = get_ioc4_port(the_port, 1); + if (!port) return -ENODEV; - } info = the_port->info; control = port->ip_control; if (!control) { + port->ip_port = NULL; return -ENODEV; } @@ -2551,28 +2613,104 @@ static struct uart_ops ioc4_ops = { * Boot-time initialization code */ -static struct uart_driver ioc4_uart = { +static struct uart_driver ioc4_uart_rs232 = { .owner = THIS_MODULE, - .driver_name = "ioc4_serial", - .dev_name = DEVICE_NAME, + .driver_name = "ioc4_serial_rs232", + .dev_name = DEVICE_NAME_RS232, .major = DEVICE_MAJOR, - .minor = DEVICE_MINOR, + .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_core_attach - register with serial core + * 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; + + control = idd->idd_serial_data; + + 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) { + release_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) +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 ii; + int port_num; + int port_type_idx; + struct uart_driver *u_driver; + DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n", __FUNCTION__, pdev, (void *)control)); @@ -2580,28 +2718,36 @@ ioc4_serial_core_attach(struct pci_dev *pdev) 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 (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) { - the_port = &control->ic_port[ii].icp_uart_port; - port = control->ic_port[ii].icp_port; - port->ip_port = the_port; + 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\n", + DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n", __FUNCTION__, (void *)the_port, - (void *)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) | ii; - the_port->line = (Num_of_ioc4_cards << 2) | ii; - the_port->mapbase = 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(&ioc4_uart, the_port) < 0) { + if (uart_add_one_port(u_driver, the_port) < 0) { printk(KERN_WARNING "%s: unable to add port %d bus %d\n", __FUNCTION__, the_port->line, pdev->bus->number); @@ -2610,8 +2756,6 @@ ioc4_serial_core_attach(struct pci_dev *pdev) ("IOC4 serial port %d irq = %d, bus %d\n", the_port->line, the_port->irq, pdev->bus->number)); } - /* all ports are rs232 for now */ - ioc4_set_proto(port, PROTO_RS232); } return 0; } @@ -2631,7 +2775,8 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) int ret = 0; - DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id)); + DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, + idd->idd_pci_id)); /* request serial registers */ tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET; @@ -2653,11 +2798,11 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) goto out2; } DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n", - __FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial)); + __FUNCTION__, (void *)idd->idd_misc_regs, + (void *)serial)); /* Get memory for the new card */ - control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS, - GFP_KERNEL); + control = kmalloc(sizeof(struct ioc4_control), GFP_KERNEL); if (!control) { printk(KERN_WARNING "ioc4_attach_one" @@ -2702,7 +2847,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) /* Hook up interrupt handler */ if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ, - "sgi-ioc4serial", (void *)soft)) { + "sgi-ioc4serial", soft)) { control->ic_irq = idd->idd_pdev->irq; } else { printk(KERN_WARNING @@ -2713,16 +2858,21 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) if (ret) goto out4; - /* register port with the serial core */ + /* register port with the serial core - 1 rs232, 1 rs422 */ - if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) + 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: @@ -2735,52 +2885,6 @@ out1: } -/** - * ioc4_serial_remove_one - detach function - * - * @idd: IOC4 master module data for this IOC4 - */ - -int ioc4_serial_remove_one(struct ioc4_driver_data *idd) -{ - int ii; - struct ioc4_control *control; - struct uart_port *the_port; - struct ioc4_port *port; - struct ioc4_soft *soft; - - control = idd->idd_serial_data; - - for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) { - the_port = &control->ic_port[ii].icp_uart_port; - if (the_port) { - uart_remove_one_port(&ioc4_uart, the_port); - } - port = control->ic_port[ii].icp_port; - if (!(ii & 1) && port) { - pci_free_consistent(port->ip_pdev, - TOTAL_RING_BUF_SIZE, - (void *)port->ip_cpu_ringbuf, - port->ip_dma_ringbuf); - kfree(port); - } - } - soft = control->ic_soft; - if (soft) { - free_irq(control->ic_irq, (void *)soft); - if (soft->is_ioc4_serial_addr) { - release_region((unsigned long) - soft->is_ioc4_serial_addr, - sizeof(struct ioc4_serial)); - } - kfree(soft); - } - kfree(control); - idd->idd_serial_data = NULL; - - return 0; -} - static struct ioc4_submodule ioc4_serial_submodule = { .is_name = "IOC4_serial", .is_owner = THIS_MODULE, @@ -2796,9 +2900,15 @@ int ioc4_serial_init(void) int ret; /* register with serial core */ - if ((ret = uart_register_driver(&ioc4_uart)) < 0) { + if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) { + printk(KERN_WARNING + "%s: Couldn't register rs232 IOC4 serial driver\n", + __FUNCTION__); + return ret; + } + if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) { printk(KERN_WARNING - "%s: Couldn't register IOC4 serial driver\n", + "%s: Couldn't register rs422 IOC4 serial driver\n", __FUNCTION__); return ret; } @@ -2810,7 +2920,8 @@ int ioc4_serial_init(void) static void __devexit ioc4_serial_exit(void) { ioc4_unregister_submodule(&ioc4_serial_submodule); - uart_unregister_driver(&ioc4_uart); + uart_unregister_driver(&ioc4_uart_rs232); + uart_unregister_driver(&ioc4_uart_rs422); } module_init(ioc4_serial_init); diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 928e6cf12dc..6459edc7f5c 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -40,7 +40,7 @@ * and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and * so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly * fpr the console code : without this 1:1 mapping, at early boot time, when we - * are parsing the kernel args console=ttyPSC?, we wouldn't know wich PSC it + * are parsing the kernel args console=ttyPSC?, we wouldn't know which PSC it * will be mapped to. */ diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 0ca83ac31d0..94681922ea0 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1,6 +1,4 @@ /* - * drivers/serial/mpsc.c - * * Generic driver for the MPSC (UART mode) on Marvell parts (e.g., GT64240, * GT64260, MV64340, MV64360, GT96100, ... ). * @@ -52,9 +50,263 @@ * 4) AFAICT, hardware flow control isn't supported by the controller --MAG. */ +#include <linux/config.h> + +#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 "mpsc.h" +#include <asm/io.h> +#include <asm/irq.h> + +#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#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 */ + + /* 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 @@ -1165,7 +1417,7 @@ mpsc_startup(struct uart_port *port) flag = SA_SHIRQ; if (request_irq(pi->port.irq, mpsc_sdma_intr, flag, - "mpsc/sdma", pi)) + "mpsc-sdma", pi)) printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d\n", pi->port.irq); diff --git a/drivers/serial/mpsc.h b/drivers/serial/mpsc.h deleted file mode 100644 index 678dbcf06c8..00000000000 --- a/drivers/serial/mpsc.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * drivers/serial/mpsc.h - * - * Author: Mark A. Greer <mgreer@mvista.com> - * - * 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. - */ - -#ifndef __MPSC_H__ -#define __MPSC_H__ - -#include <linux/config.h> -#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 <asm/io.h> -#include <asm/irq.h> - -#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#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 */ - - /* 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); - -/* - ***************************************************************************** - * - * Multi-Protocol Serial Controller Interface Registers - * - ***************************************************************************** - */ - -/* Main Configuratino 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 - -#endif /* __MPSC_H__ */ diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index b848b7d9441..3bdee64d1a9 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -483,7 +483,7 @@ static int serial_txx9_startup(struct uart_port *port) /* * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) + * (they will be reenabled in set_termios()) */ sio_set(up, TXX9_SIFCR, TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 9fe2283d91e..1c4396c2962 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -641,7 +641,7 @@ static int sunsu_startup(struct uart_port *port) /* * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) + * (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); |