diff options
Diffstat (limited to 'drivers/serial')
62 files changed, 827 insertions, 944 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 0276471cb25..f31c6698419 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -4,8 +4,6 @@ * Driver for the serial port on the 21285 StrongArm-110 core logic chip. * * Based on drivers/char/serial.c - * - * $Id: 21285.c,v 1.37 2002/07/28 10:03:27 rmk Exp $ */ #include <linux/module.h> #include <linux/tty.h> @@ -21,7 +19,7 @@ #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/hardware/dec21285.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #define BAUD_BASE (mem_fclk_21285/64) @@ -88,7 +86,7 @@ static void serial21285_enable_ms(struct uart_port *port) static irqreturn_t serial21285_rx_chars(int irq, void *dev_id) { struct uart_port *port = dev_id; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; unsigned int status, ch, flag, rxs, max_count = 256; status = *CSR_UARTFLG; @@ -237,8 +235,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); - if (port->info && port->info->tty) { - struct tty_struct *tty = port->info->tty; + if (port->info && port->info->port.tty) { + struct tty_struct *tty = port->info->port.tty; unsigned int b = port->uartclk / (16 * quot); tty_encode_baud_rate(tty, b, b); } @@ -494,7 +492,7 @@ static int __init serial21285_init(void) { int ret; - printk(KERN_INFO "Serial: 21285 driver $Revision: 1.37 $\n"); + printk(KERN_INFO "Serial: 21285 driver\n"); serial21285_setup_ports(); @@ -515,5 +513,5 @@ module_init(serial21285_init); module_exit(serial21285_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.37 $"); +MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver"); MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR); diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index bbf5bc5892c..381b12ac20e 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -249,7 +249,7 @@ static void status_handle(struct m68k_serial *info, unsigned short status) { #if 0 if(status & DCD) { - if((info->tty->termios->c_cflag & CRTSCTS) && + if((info->port.tty->termios->c_cflag & CRTSCTS) && ((info->curregs[3] & AUTO_ENAB)==0)) { info->curregs[3] |= AUTO_ENAB; info->pendregs[3] |= AUTO_ENAB; @@ -274,7 +274,7 @@ static void status_handle(struct m68k_serial *info, unsigned short status) static void receive_chars(struct m68k_serial *info, unsigned short rx) { - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; m68328_uart *uart = &uart_addr[info->line]; unsigned char ch, flag; @@ -345,7 +345,7 @@ static void transmit_chars(struct m68k_serial *info) goto clear_and_return; } - if((info->xmit_cnt <= 0) || info->tty->stopped) { + if((info->xmit_cnt <= 0) || info->port.tty->stopped) { /* That's peculiar... TX ints off */ uart->ustcnt &= ~USTCNT_TX_INTR_MASK; goto clear_and_return; @@ -403,7 +403,7 @@ static void do_softint(struct work_struct *work) struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue); struct tty_struct *tty; - tty = info->tty; + tty = info->port.tty; if (!tty) return; #if 0 @@ -427,7 +427,7 @@ static void do_serial_hangup(struct work_struct *work) struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue_hangup); struct tty_struct *tty; - tty = info->tty; + tty = info->port.tty; if (!tty) return; @@ -471,8 +471,8 @@ static int startup(struct m68k_serial * info) uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK; #endif - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; /* @@ -506,8 +506,8 @@ static void shutdown(struct m68k_serial * info) info->xmit_buf = 0; } - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); info->flags &= ~S_INITIALIZED; local_irq_restore(flags); @@ -573,9 +573,9 @@ static void change_speed(struct m68k_serial *info) unsigned cflag; int i; - if (!info->tty || !info->tty->termios) + if (!info->port.tty || !info->port.tty->termios) return; - cflag = info->tty->termios->c_cflag; + cflag = info->port.tty->termios->c_cflag; if (!(port = info->port)) return; @@ -1131,7 +1131,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; - info->tty = 0; + info->port.tty = NULL; #warning "This is not and has never been valid so fix it" #if 0 if (tty->ldisc.num != ldiscs[N_TTY].num) { @@ -1169,7 +1169,7 @@ void rs_hangup(struct tty_struct *tty) info->event = 0; info->count = 0; info->flags &= ~S_NORMAL_ACTIVE; - info->tty = 0; + info->port.tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -1286,7 +1286,7 @@ int rs_open(struct tty_struct *tty, struct file * filp) info->count++; tty->driver_data = info; - info->tty = tty; + info->port.tty = tty; /* * Start up serial port @@ -1363,7 +1363,7 @@ rs68328_init(void) info = &m68k_soft[i]; info->magic = SERIAL_MAGIC; info->port = (int) &uart_addr[i]; - info->tty = 0; + info->port.tty = NULL; info->irq = uart_irqs[i]; info->custom_divisor = 16; info->close_delay = 50; diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index d9d4e9552a4..24661cd5e4f 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -393,7 +393,7 @@ static void rs_360_start(struct tty_struct *tty) static _INLINE_ void receive_chars(ser_info_t *info) { - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; unsigned char ch, flag, *cp; /*int ignored = 0;*/ int i; @@ -514,7 +514,7 @@ static _INLINE_ void receive_chars(ser_info_t *info) static _INLINE_ void receive_break(ser_info_t *info) { - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; info->state->icount.brk++; /* Check to see if there is room in the tty buffer for @@ -528,7 +528,7 @@ static _INLINE_ void transmit_chars(ser_info_t *info) { if ((info->flags & TX_WAKEUP) || - (info->tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) { + (info->port.tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) { schedule_work(&info->tqueue); } @@ -584,12 +584,12 @@ static _INLINE_ void check_modem_status(struct async_struct *info) } } if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty->hw_stopped) { + if (info->port.tty->hw_stopped) { if (status & UART_MSR_CTS) { #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) printk("CTS tx start..."); #endif - info->tty->hw_stopped = 0; + info->port.tty->hw_stopped = 0; info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); @@ -600,7 +600,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info) #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) printk("CTS tx stop..."); #endif - info->tty->hw_stopped = 1; + info->port.tty->hw_stopped = 1; info->IER &= ~UART_IER_THRI; serial_out(info, UART_IER, info->IER); } @@ -670,7 +670,7 @@ static void do_softint(void *private_) ser_info_t *info = (ser_info_t *) private_; struct tty_struct *tty; - tty = info->tty; + tty = info->port.tty; if (!tty) return; @@ -693,7 +693,7 @@ static void do_serial_hangup(void *private_) struct async_struct *info = (struct async_struct *) private_; struct tty_struct *tty; - tty = info->tty; + tty = info->port.tty; if (!tty) return; @@ -721,8 +721,8 @@ static int startup(ser_info_t *info) #ifdef maybe if (!state->port || !state->type) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); goto errout; } #endif @@ -734,12 +734,12 @@ static int startup(ser_info_t *info) #ifdef modem_control info->MCR = 0; - if (info->tty->termios->c_cflag & CBAUD) + if (info->port.tty->termios->c_cflag & CBAUD) info->MCR = UART_MCR_DTR | UART_MCR_RTS; #endif - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); /* * and set the speed of the serial port @@ -842,8 +842,8 @@ static void shutdown(ser_info_t *info) smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); } - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); info->flags &= ~ASYNC_INITIALIZED; local_irq_restore(flags); @@ -863,9 +863,9 @@ static void change_speed(ser_info_t *info) volatile struct smc_regs *smcp; volatile struct scc_regs *sccp; - if (!info->tty || !info->tty->termios) + if (!info->port.tty || !info->port.tty->termios) return; - cflag = info->tty->termios->c_cflag; + cflag = info->port.tty->termios->c_cflag; state = info->state; @@ -936,24 +936,24 @@ static void change_speed(ser_info_t *info) * Set up parity check flag */ info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); - if (I_INPCK(info->tty)) + if (I_INPCK(info->port.tty)) info->read_status_mask |= BD_SC_FR | BD_SC_PR; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) info->read_status_mask |= BD_SC_BR; /* * Characters to ignore */ info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) + if (I_IGNPAR(info->port.tty)) info->ignore_status_mask |= BD_SC_PR | BD_SC_FR; - if (I_IGNBRK(info->tty)) { + if (I_IGNBRK(info->port.tty)) { info->ignore_status_mask |= BD_SC_BR; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ - if (I_IGNPAR(info->tty)) + if (I_IGNPAR(info->port.tty)) info->ignore_status_mask |= BD_SC_OV; } /* @@ -1658,7 +1658,7 @@ static void rs_360_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; - info->tty = 0; + info->port.tty = NULL; if (info->blocked_open) { if (info->close_delay) { msleep_interruptible(jiffies_to_msecs(info->close_delay)); @@ -1758,7 +1758,7 @@ static void rs_360_hangup(struct tty_struct *tty) info->event = 0; state->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; + info->port.tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -1919,7 +1919,7 @@ static int rs_360_open(struct tty_struct *tty, struct file * filp) printk("rs_open %s, count = %d\n", tty->name, info->state->count); #endif tty->driver_data = info; - info->tty = tty; + info->port.tty = tty; /* * Start up serial port @@ -1976,7 +1976,7 @@ static inline int line_info(char *buf, struct serial_state *state) info->port = state->port; info->flags = state->flags; info->quot = 0; - info->tty = 0; + info->port.tty = NULL; } local_irq_disable(); status = serial_in(info, UART_MSR); diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index be95e55b228..9ccc563d873 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -12,8 +12,6 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * $Id: 8250.c,v 1.90 2002/07/28 10:03:27 rmk Exp $ - * * A note about mapbase / membase * * mapbase is the physical address of the IO port. @@ -1289,13 +1287,24 @@ static void serial8250_enable_ms(struct uart_port *port) static void receive_chars(struct uart_8250_port *up, unsigned int *status) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->port.tty; unsigned char ch, lsr = *status; int max_count = 256; char flag; do { - ch = serial_inp(up, UART_RX); + if (likely(lsr & UART_LSR_DR)) + ch = serial_inp(up, UART_RX); + else + /* + * Intel 82571 has a Serial Over Lan device that will + * set UART_LSR_BI without setting UART_LSR_DR when + * it receives a break. To avoid reading from the + * receive buffer without UART_LSR_DR bit set, we + * just force the read character to be 0 + */ + ch = 0; + flag = TTY_NORMAL; up->port.icount.rx++; @@ -1344,7 +1353,7 @@ receive_chars(struct uart_8250_port *up, unsigned int *status) ignore_char: lsr = serial_inp(up, UART_LSR); - } while ((lsr & UART_LSR_DR) && (max_count-- > 0)); + } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); spin_unlock(&up->port.lock); tty_flip_buffer_push(tty); spin_lock(&up->port.lock); @@ -1427,7 +1436,7 @@ serial8250_handle_port(struct uart_8250_port *up) DEBUG_INTR("status = %x...", status); - if (status & UART_LSR_DR) + if (status & (UART_LSR_DR | UART_LSR_BI)) receive_chars(up, &status); check_modem_status(up); if (status & UART_LSR_THRE) @@ -1877,6 +1886,8 @@ static int serial8250_startup(struct uart_port *port) * allow register changes to become visible. */ spin_lock_irqsave(&up->port.lock, flags); + if (up->port.flags & UPF_SHARE_IRQ) + disable_irq_nosync(up->port.irq); wait_for_xmitr(up, UART_LSR_THRE); serial_out_sync(up, UART_IER, UART_IER_THRI); @@ -1888,6 +1899,8 @@ static int serial8250_startup(struct uart_port *port) iir = serial_in(up, UART_IIR); serial_out(up, UART_IER, 0); + if (up->port.flags & UPF_SHARE_IRQ) + enable_irq(up->port.irq); spin_unlock_irqrestore(&up->port.lock, flags); /* @@ -1895,15 +1908,23 @@ static int serial8250_startup(struct uart_port *port) * kick the UART on a regular basis. */ if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) { + up->bugs |= UART_BUG_THRE; pr_debug("ttyS%d - using backup timer\n", port->line); - up->timer.function = serial8250_backup_timeout; - up->timer.data = (unsigned long)up; - mod_timer(&up->timer, jiffies + - poll_timeout(up->port.timeout) + HZ / 5); } } /* + * The above check will only give an accurate result the first time + * the port is opened so this value needs to be preserved. + */ + if (up->bugs & UART_BUG_THRE) { + up->timer.function = serial8250_backup_timeout; + up->timer.data = (unsigned long)up; + mod_timer(&up->timer, jiffies + + poll_timeout(up->port.timeout) + HZ / 5); + } + + /* * If the "interrupt" for this port doesn't correspond with any * hardware interrupt, we use a timer-based system. The original * driver used to do this with IRQ0. @@ -2934,7 +2955,7 @@ static int __init serial8250_init(void) if (nr_uarts > UART_NR) nr_uarts = UART_NR; - printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ " + printk(KERN_INFO "Serial: 8250/16550 driver" "%d ports, IRQ sharing %sabled\n", nr_uarts, share_irqs ? "en" : "dis"); @@ -2995,7 +3016,7 @@ EXPORT_SYMBOL(serial8250_suspend_port); EXPORT_SYMBOL(serial8250_resume_port); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $"); +MODULE_DESCRIPTION("Generic 8250/16x50 serial driver"); module_param(share_irqs, uint, 0644); MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index 91bd28f2bb4..520260326f3 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -11,8 +11,6 @@ * 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. - * - * $Id: 8250.h,v 1.8 2002/07/21 21:32:30 rmk Exp $ */ #include <linux/serial_8250.h> @@ -49,6 +47,7 @@ struct serial8250_config { #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ #define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ +#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */ #define PROBE_RSA (1 << 0) #define PROBE_ANY (~0) diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c index 4eb7437a404..0416ad3bc12 100644 --- a/drivers/serial/8250_gsc.c +++ b/drivers/serial/8250_gsc.c @@ -119,3 +119,5 @@ int __init probe_serial_gsc(void) } module_init(probe_serial_gsc); + +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 788c3559522..c2f23933155 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -10,8 +10,6 @@ * 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. - * - * $Id: 8250_pci.c,v 1.28 2002/11/02 11:14:18 rmk Exp $ */ #include <linux/module.h> #include <linux/init.h> @@ -769,6 +767,9 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board, #define PCI_SUBDEVICE_ID_POCTAL232 0x0308 #define PCI_SUBDEVICE_ID_POCTAL422 0x0408 +/* Unknown vendors/cards - this should not be in linux/pci_ids.h */ +#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 + /* * Master list of serial port init/setup/exit quirks. * This does not describe the general nature of the port. @@ -884,6 +885,15 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { }, { .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9050, + .subvendor = PCI_VENDOR_ID_PLX, + .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + { + .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_ROMULUS, .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_ROMULUS, @@ -2199,6 +2209,11 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_4_921600 }, + /* Unknown card - subdevice 0x1584 */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_VENDOR_ID_PLX, + PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0, + pbn_b0_4_115200 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_SUBVENDOR_ID_KEYSPAN, PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 638b68649e7..fde7f9ccf57 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -12,8 +12,6 @@ * 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. - * - * $Id: 8250_pnp.c,v 1.10 2002/07/21 21:32:30 rmk Exp $ */ #include <linux/module.h> #include <linux/init.h> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 18ca9075e13..77cb34270fc 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -1,8 +1,6 @@ # # Serial device configuration # -# $Id: Kconfig,v 1.11 2004/03/11 18:08:04 lethal Exp $ -# menu "Serial drivers" depends on HAS_IOMEM @@ -451,6 +449,7 @@ config SERIAL_CLPS711X_CONSOLE config SERIAL_SAMSUNG tristate "Samsung SoC serial support" depends on ARM && PLAT_S3C24XX + select SERIAL_CORE help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, providing /dev/ttySAC0, 1 and 2 (note, some machines may not @@ -944,22 +943,6 @@ config SERIAL_IP22_ZILOG_CONSOLE depends on SERIAL_IP22_ZILOG=y select SERIAL_CORE_CONSOLE -config V850E_UART - bool "NEC V850E on-chip UART support" - depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1 - select SERIAL_CORE - default y - -config V850E_UARTB - bool - depends on V850E_UART && V850E_ME2 - default y - -config V850E_UART_CONSOLE - bool "Use NEC V850E on-chip UART for console" - depends on V850E_UART - select SERIAL_CORE_CONSOLE - config SERIAL_SH_SCI tristate "SuperH SCI(F) serial port support" depends on SUPERH || H8300 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 7d85c1fbe7e..7e7383e890d 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -1,8 +1,6 @@ # # Makefile for the kernel serial device drivers. # -# $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $ -# obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o @@ -44,7 +42,6 @@ obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_SERIAL_MCF) += mcf.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_DZ) += dz.o diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index e88da72f830..90b56c2c31e 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -22,8 +22,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $ - * * This is a generic driver for ARM AMBA-type serial ports. They * have a lot of 16550-like features, but are not register compatible. * Note that although they do have CTS, DCD and DSR inputs, they do @@ -119,7 +117,7 @@ static void pl010_enable_ms(struct uart_port *port) static void pl010_rx_chars(struct uart_amba_port *uap) { - struct tty_struct *tty = uap->port.info->tty; + struct tty_struct *tty = uap->port.info->port.tty; unsigned int status, ch, flag, rsr, max_count = 256; status = readb(uap->port.membase + UART01x_FR); @@ -791,7 +789,7 @@ static int __init pl010_init(void) { int ret; - printk(KERN_INFO "Serial: AMBA driver $Revision: 1.41 $\n"); + printk(KERN_INFO "Serial: AMBA driver\n"); ret = uart_register_driver(&amba_reg); if (ret == 0) { @@ -812,5 +810,5 @@ module_init(pl010_init); module_exit(pl010_exit); MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); -MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $"); +MODULE_DESCRIPTION("ARM AMBA serial port driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 08adc1de4a7..9d08f27208a 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -22,8 +22,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $ - * * This is a generic driver for ARM AMBA-type serial ports. They * have a lot of 16550-like features, but are not register compatible. * Note that although they do have CTS, DCD and DSR inputs, they do @@ -109,7 +107,7 @@ static void pl011_enable_ms(struct uart_port *port) static void pl011_rx_chars(struct uart_amba_port *uap) { - struct tty_struct *tty = uap->port.info->tty; + struct tty_struct *tty = uap->port.info->port.tty; unsigned int status, ch, flag, max_count = 256; status = readw(uap->port.membase + UART01x_FR); diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 6aeef22bd20..61fb8b6d19a 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -42,11 +42,11 @@ #include <asm/io.h> #include <asm/mach/serial_at91.h> -#include <asm/arch/board.h> +#include <mach/board.h> #ifdef CONFIG_ARM -#include <asm/arch/cpu.h> -#include <asm/arch/gpio.h> +#include <mach/cpu.h> +#include <mach/gpio.h> #endif #define PDC_BUFFER_SIZE 512 @@ -131,7 +131,8 @@ struct atmel_uart_char { struct atmel_uart_port { struct uart_port uart; /* uart */ struct clk *clk; /* uart clock */ - unsigned short suspended; /* is port suspended? */ + int may_wakeup; /* cached value of device_may_wakeup for times we need to disable it */ + u32 backup_imr; /* IMR saved during suspend */ int break_active; /* break being received */ short use_dma_rx; /* enable PDC receiver */ @@ -662,14 +663,14 @@ static void atmel_rx_from_ring(struct uart_port *port) * uart_start(), which takes the lock. */ spin_unlock(&port->lock); - tty_flip_buffer_push(port->info->tty); + tty_flip_buffer_push(port->info->port.tty); spin_lock(&port->lock); } static void atmel_rx_from_dma(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; struct atmel_dma_buffer *pdc; int rx_idx = atmel_port->pdc_rx_idx; unsigned int head; @@ -794,7 +795,7 @@ static void atmel_tasklet_func(unsigned long data) static int atmel_startup(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; int retval; /* @@ -956,6 +957,20 @@ static void atmel_shutdown(struct uart_port *port) } /* + * Flush any TX data submitted for DMA. Called when the TX circular + * buffer is reset. + */ +static void atmel_flush_buffer(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + if (atmel_use_dma_tx(port)) { + UART_PUT_TCR(port, 0); + atmel_port->pdc_tx.ofs = 0; + } +} + +/* * Power / Clock management. */ static void atmel_serial_pm(struct uart_port *port, unsigned int state, @@ -970,8 +985,15 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, * This is called on uart_open() or a resume event. */ clk_enable(atmel_port->clk); + + /* re-enable interrupts if we disabled some on suspend */ + UART_PUT_IER(port, atmel_port->backup_imr); break; case 3: + /* Back up the interrupt mask and disable all interrupts */ + atmel_port->backup_imr = UART_GET_IMR(port); + UART_PUT_IDR(port, -1); + /* * Disable the peripheral clock for this serial port. * This is called on uart_close() or a suspend event. @@ -1189,6 +1211,7 @@ static struct uart_ops atmel_pops = { .break_ctl = atmel_break_ctl, .startup = atmel_startup, .shutdown = atmel_shutdown, + .flush_buffer = atmel_flush_buffer, .set_termios = atmel_set_termios, .type = atmel_type, .release_port = atmel_release_port, @@ -1460,13 +1483,12 @@ static int atmel_serial_suspend(struct platform_device *pdev, cpu_relax(); } - if (device_may_wakeup(&pdev->dev) - && !atmel_serial_clk_will_stop()) - enable_irq_wake(port->irq); - else { - uart_suspend_port(&atmel_uart, port); - atmel_port->suspended = 1; - } + /* we can not wake up if we're running on slow clock */ + atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); + if (atmel_serial_clk_will_stop()) + device_set_wakeup_enable(&pdev->dev, 0); + + uart_suspend_port(&atmel_uart, port); return 0; } @@ -1476,11 +1498,8 @@ static int atmel_serial_resume(struct platform_device *pdev) struct uart_port *port = platform_get_drvdata(pdev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_port->suspended) { - uart_resume_port(&atmel_uart, port); - atmel_port->suspended = 0; - } else - disable_irq_wake(port->irq); + uart_resume_port(&atmel_uart, port); + device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup); return 0; } @@ -1498,6 +1517,8 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE)); port = &atmel_ports[pdev->id]; + port->backup_imr = 0; + atmel_init_port(port, pdev); if (!atmel_use_dma_rx(&port->uart)) { diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index fd9bb777df2..4a0d30bed9f 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -28,7 +28,7 @@ #endif #include <asm/gpio.h> -#include <asm/mach/bfin_serial_5xx.h> +#include <mach/bfin_serial_5xx.h> #ifdef CONFIG_SERIAL_BFIN_DMA #include <linux/dma-mapping.h> @@ -175,7 +175,7 @@ int kgdb_get_debug_char(void) #ifdef CONFIG_SERIAL_BFIN_PIO static void bfin_serial_rx_chars(struct bfin_serial_port *uart) { - struct tty_struct *tty = uart->port.info->tty; + struct tty_struct *tty = uart->port.info->port.tty; unsigned int status, ch, flg; static struct timeval anomaly_start = { .tv_sec = 0 }; @@ -393,7 +393,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) { - struct tty_struct *tty = uart->port.info->tty; + struct tty_struct *tty = uart->port.info->port.tty; int i, flg, status; status = UART_GET_LSR(uart); @@ -552,7 +552,7 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart) #ifdef CONFIG_SERIAL_BFIN_CTSRTS unsigned int status; struct uart_info *info = uart->port.info; - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; status = bfin_serial_get_mctrl(&uart->port); uart_handle_cts_change(&uart->port, status & TIOCM_CTS); @@ -814,10 +814,10 @@ static void bfin_serial_set_ldisc(struct uart_port *port) int line = port->line; unsigned short val; - if (line >= port->info->tty->driver->num) + if (line >= port->info->port.tty->driver->num) return; - switch (port->info->tty->ldisc.num) { + switch (port->info->port.tty->termios->c_line) { case N_IRDA: val = UART_GET_GCTL(&bfin_serial_ports[line]); val |= (IREN | RPOLC); diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index aca1240ad80..dd8564d2505 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c @@ -174,7 +174,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate) static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id) { struct sport_uart_port *up = dev_id; - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->port.tty; unsigned int ch; do { @@ -201,7 +201,7 @@ static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id) static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) { struct sport_uart_port *up = dev_id; - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->port.tty; unsigned int stat = SPORT_GET_STAT(up); /* Overflow in RX FIFO */ diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 23827189ec0..459f3420a42 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -21,9 +21,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: clps711x.c,v 1.42 2002/07/28 10:03:28 rmk Exp $ - * */ #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) @@ -42,7 +39,7 @@ #include <linux/serial_core.h> #include <linux/serial.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/hardware/clps7111.h> @@ -96,7 +93,7 @@ static void clps711xuart_enable_ms(struct uart_port *port) static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id) { struct uart_port *port = dev_id; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; unsigned int status, ch, flg; status = clps_readl(SYSFLG(port)); @@ -551,7 +548,7 @@ static int __init clps711xuart_init(void) { int ret, i; - printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.42 $\n"); + printk(KERN_INFO "Serial: CLPS711x driver\n"); ret = uart_register_driver(&clps711x_reg); if (ret) @@ -577,6 +574,6 @@ module_init(clps711xuart_init); module_exit(clps711xuart_exit); MODULE_AUTHOR("Deep Blue Solutions Ltd"); -MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.42 $"); +MODULE_DESCRIPTION("CLPS-711x generic serial driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR); diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 5c76e0ae058..7274b527a3c 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -50,6 +50,15 @@ #define SCC_WAIT_CLOSING 100 +#define GPIO_CTS 0 +#define GPIO_RTS 1 +#define GPIO_DCD 2 +#define GPIO_DSR 3 +#define GPIO_DTR 4 +#define GPIO_RI 5 + +#define NUM_GPIOS (GPIO_RI+1) + struct uart_cpm_port { struct uart_port port; u16 rx_nrfifos; @@ -68,6 +77,7 @@ struct uart_cpm_port { unsigned char *rx_buf; u32 flags; void (*set_lineif)(struct uart_cpm_port *); + struct clk *clk; u8 brg; uint dp_addr; void *mem_addr; @@ -82,6 +92,7 @@ struct uart_cpm_port { int wait_closing; /* value to combine with opcode to form cpm command */ u32 command; + int gpios[NUM_GPIOS]; }; extern int cpm_uart_nr; diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index abe129cc927..25efca5a7a1 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -43,6 +43,9 @@ #include <linux/dma-mapping.h> #include <linux/fs_uart_pd.h> #include <linux/of_platform.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> +#include <linux/clk.h> #include <asm/io.h> #include <asm/irq.h> @@ -96,13 +99,41 @@ static unsigned int cpm_uart_tx_empty(struct uart_port *port) static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) { - /* Whee. Do nothing. */ + struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + + if (pinfo->gpios[GPIO_RTS] >= 0) + gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS)); + + if (pinfo->gpios[GPIO_DTR] >= 0) + gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR)); } static unsigned int cpm_uart_get_mctrl(struct uart_port *port) { - /* Whee. Do nothing. */ - return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; + struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + + if (pinfo->gpios[GPIO_CTS] >= 0) { + if (gpio_get_value(pinfo->gpios[GPIO_CTS])) + mctrl &= ~TIOCM_CTS; + } + + if (pinfo->gpios[GPIO_DSR] >= 0) { + if (gpio_get_value(pinfo->gpios[GPIO_DSR])) + mctrl &= ~TIOCM_DSR; + } + + if (pinfo->gpios[GPIO_DCD] >= 0) { + if (gpio_get_value(pinfo->gpios[GPIO_DCD])) + mctrl &= ~TIOCM_CAR; + } + + if (pinfo->gpios[GPIO_RI] >= 0) { + if (!gpio_get_value(pinfo->gpios[GPIO_RI])) + mctrl |= TIOCM_RNG; + } + + return mctrl; } /* @@ -201,6 +232,10 @@ static void cpm_uart_int_tx(struct uart_port *port) cpm_uart_tx_pump(port); } +#ifdef CONFIG_CONSOLE_POLL +static int serial_polled; +#endif + /* * Receive characters */ @@ -209,7 +244,7 @@ static void cpm_uart_int_rx(struct uart_port *port) int i; unsigned char ch; u8 *cp; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; cbd_t __iomem *bdp; u16 status; @@ -222,6 +257,12 @@ static void cpm_uart_int_rx(struct uart_port *port) */ bdp = pinfo->rx_cur; for (;;) { +#ifdef CONFIG_CONSOLE_POLL + if (unlikely(serial_polled)) { + serial_polled = 0; + return; + } +#endif /* get status */ status = in_be16(&bdp->cbd_sc); /* If this one is empty, return happy */ @@ -253,7 +294,12 @@ static void cpm_uart_int_rx(struct uart_port *port) goto handle_error; if (uart_handle_sysrq_char(port, ch)) continue; - +#ifdef CONFIG_CONSOLE_POLL + if (unlikely(serial_polled)) { + serial_polled = 0; + return; + } +#endif error_return: tty_insert_flip_char(tty, ch, flg); @@ -420,10 +466,13 @@ static void cpm_uart_shutdown(struct uart_port *port) } /* Shut them really down and reinit buffer descriptors */ - if (IS_SMC(pinfo)) + if (IS_SMC(pinfo)) { + out_be16(&pinfo->smcup->smc_brkcr, 0); cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX); - else + } else { + out_be16(&pinfo->sccup->scc_brkcr, 0); cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX); + } cpm_uart_initbd(pinfo); } @@ -539,14 +588,19 @@ static void cpm_uart_set_termios(struct uart_port *port, * enables, because we want to put them back if they were * present. */ - prev_mode = in_be16(&smcp->smc_smcmr); - out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | SMCMR_SM_UART); - setbits16(&smcp->smc_smcmr, (prev_mode & (SMCMR_REN | SMCMR_TEN))); + prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN); + /* Output in *one* operation, so we don't interrupt RX/TX if they + * were already enabled. */ + out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | + SMCMR_SM_UART | prev_mode); } else { out_be16(&sccp->scc_psmr, (sbits << 12) | scval); } - cpm_set_brg(pinfo->brg - 1, baud); + if (pinfo->clk) + clk_set_rate(pinfo->clk, baud); + else + cpm_set_brg(pinfo->brg - 1, baud); spin_unlock_irqrestore(&port->lock, flags); } @@ -865,6 +919,80 @@ static void cpm_uart_config_port(struct uart_port *port, int flags) cpm_uart_request_port(port); } } + +#ifdef CONFIG_CONSOLE_POLL +/* Serial polling routines for writing and reading from the uart while + * in an interrupt or debug context. + */ + +#define GDB_BUF_SIZE 512 /* power of 2, please */ + +static char poll_buf[GDB_BUF_SIZE]; +static char *pollp; +static int poll_chars; + +static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo) +{ + u_char c, *cp; + volatile cbd_t *bdp; + int i; + + /* Get the address of the host memory buffer. + */ + bdp = pinfo->rx_cur; + while (bdp->cbd_sc & BD_SC_EMPTY) + ; + + /* If the buffer address is in the CPM DPRAM, don't + * convert it. + */ + cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); + + if (obuf) { + i = c = bdp->cbd_datlen; + while (i-- > 0) + *obuf++ = *cp++; + } else + c = *cp; + bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); + bdp->cbd_sc |= BD_SC_EMPTY; + + if (bdp->cbd_sc & BD_SC_WRAP) + bdp = pinfo->rx_bd_base; + else + bdp++; + pinfo->rx_cur = (cbd_t *)bdp; + + return (int)c; +} + +static int cpm_get_poll_char(struct uart_port *port) +{ + struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + + if (!serial_polled) { + serial_polled = 1; + poll_chars = 0; + } + if (poll_chars <= 0) { + poll_chars = poll_wait_key(poll_buf, pinfo); + pollp = poll_buf; + } + poll_chars--; + return *pollp++; +} + +static void cpm_put_poll_char(struct uart_port *port, + unsigned char c) +{ + struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + static char ch[2]; + + ch[0] = (char)c; + cpm_uart_early_write(pinfo->port.line, ch, 1); +} +#endif /* CONFIG_CONSOLE_POLL */ + static struct uart_ops cpm_uart_pops = { .tx_empty = cpm_uart_tx_empty, .set_mctrl = cpm_uart_set_mctrl, @@ -882,6 +1010,10 @@ static struct uart_ops cpm_uart_pops = { .request_port = cpm_uart_request_port, .config_port = cpm_uart_config_port, .verify_port = cpm_uart_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = cpm_get_poll_char, + .poll_put_char = cpm_put_poll_char, +#endif }; struct uart_cpm_port cpm_uart_ports[UART_NR]; @@ -893,14 +1025,23 @@ static int cpm_uart_init_port(struct device_node *np, void __iomem *mem, *pram; int len; int ret; + int i; - data = of_get_property(np, "fsl,cpm-brg", &len); - if (!data || len != 4) { - printk(KERN_ERR "CPM UART %s has no/invalid " - "fsl,cpm-brg property.\n", np->name); - return -EINVAL; + data = of_get_property(np, "clock", NULL); + if (data) { + struct clk *clk = clk_get(NULL, (const char*)data); + if (!IS_ERR(clk)) + pinfo->clk = clk; + } + if (!pinfo->clk) { + data = of_get_property(np, "fsl,cpm-brg", &len); + if (!data || len != 4) { + printk(KERN_ERR "CPM UART %s has no/invalid " + "fsl,cpm-brg property.\n", np->name); + return -EINVAL; + } + pinfo->brg = *data; } - pinfo->brg = *data; data = of_get_property(np, "fsl,cpm-command", &len); if (!data || len != 4) { @@ -952,6 +1093,9 @@ static int cpm_uart_init_port(struct device_node *np, goto out_pram; } + for (i = 0; i < NUM_GPIOS; i++) + pinfo->gpios[i] = of_get_gpio(np, i); + return cpm_uart_request_port(&pinfo->port); out_pram: @@ -1105,12 +1249,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) udbg_putc = NULL; #endif - cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX); - if (IS_SMC(pinfo)) { + out_be16(&pinfo->smcup->smc_brkcr, 0); + cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX); clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX); clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN); } else { + out_be16(&pinfo->sccup->scc_brkcr, 0); + cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX); clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX); clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); } diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 3e0366eab41..bf94a770bb4 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -234,7 +234,7 @@ unsigned long r_alt_ser_baudrate_shadow = 0; static struct e100_serial rs_table[] = { { .baud = DEF_BAUD, - .port = (unsigned char *)R_SERIAL0_CTRL, + .ioport = (unsigned char *)R_SERIAL0_CTRL, .irq = 1U << 12, /* uses DMA 6 and 7 */ .oclrintradr = R_DMA_CH6_CLR_INTR, .ofirstadr = R_DMA_CH6_FIRST, @@ -288,7 +288,7 @@ static struct e100_serial rs_table[] = { }, /* ttyS0 */ #ifndef CONFIG_SVINTO_SIM { .baud = DEF_BAUD, - .port = (unsigned char *)R_SERIAL1_CTRL, + .ioport = (unsigned char *)R_SERIAL1_CTRL, .irq = 1U << 16, /* uses DMA 8 and 9 */ .oclrintradr = R_DMA_CH8_CLR_INTR, .ofirstadr = R_DMA_CH8_FIRST, @@ -344,7 +344,7 @@ static struct e100_serial rs_table[] = { }, /* ttyS1 */ { .baud = DEF_BAUD, - .port = (unsigned char *)R_SERIAL2_CTRL, + .ioport = (unsigned char *)R_SERIAL2_CTRL, .irq = 1U << 4, /* uses DMA 2 and 3 */ .oclrintradr = R_DMA_CH2_CLR_INTR, .ofirstadr = R_DMA_CH2_FIRST, @@ -398,7 +398,7 @@ static struct e100_serial rs_table[] = { }, /* ttyS2 */ { .baud = DEF_BAUD, - .port = (unsigned char *)R_SERIAL3_CTRL, + .ioport = (unsigned char *)R_SERIAL3_CTRL, .irq = 1U << 8, /* uses DMA 4 and 5 */ .oclrintradr = R_DMA_CH4_CLR_INTR, .ofirstadr = R_DMA_CH4_FIRST, @@ -939,7 +939,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] = /* Output */ #define E100_RTS_GET(info) ((info)->rx_ctrl & E100_RTS_MASK) /* Input */ -#define E100_CTS_GET(info) ((info)->port[REG_STATUS] & E100_CTS_MASK) +#define E100_CTS_GET(info) ((info)->ioport[REG_STATUS] & E100_CTS_MASK) /* These are typically PA or PB and 0 means 0V, 1 means 3.3V */ /* Is an output */ @@ -968,7 +968,7 @@ static DEFINE_MUTEX(tmp_buf_mutex); /* Calculate the chartime depending on baudrate, numbor of bits etc. */ static void update_char_time(struct e100_serial * info) { - tcflag_t cflags = info->tty->termios->c_cflag; + tcflag_t cflags = info->port.tty->termios->c_cflag; int bits; /* calc. number of bits / data byte */ @@ -1092,7 +1092,7 @@ e100_rts(struct e100_serial *info, int set) local_irq_save(flags); info->rx_ctrl &= ~E100_RTS_MASK; info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ - info->port[REG_REC_CTRL] = info->rx_ctrl; + info->ioport[REG_REC_CTRL] = info->rx_ctrl; local_irq_restore(flags); #ifdef SERIAL_DEBUG_IO printk("ser%i rts %i\n", info->line, set); @@ -1142,7 +1142,7 @@ e100_disable_rx(struct e100_serial *info) { #ifndef CONFIG_SVINTO_SIM /* disable the receiver */ - info->port[REG_REC_CTRL] = + info->ioport[REG_REC_CTRL] = (info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); #endif } @@ -1152,7 +1152,7 @@ e100_enable_rx(struct e100_serial *info) { #ifndef CONFIG_SVINTO_SIM /* enable the receiver */ - info->port[REG_REC_CTRL] = + info->ioport[REG_REC_CTRL] = (info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); #endif } @@ -1483,13 +1483,14 @@ rs_stop(struct tty_struct *tty) CIRC_CNT(info->xmit.head, info->xmit.tail,SERIAL_XMIT_SIZE))); - xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->tty)); + xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, + STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); if (tty->termios->c_iflag & IXON ) { xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } - *((unsigned long *)&info->port[REG_XOFF]) = xoff; + *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; local_irq_restore(flags); } } @@ -1512,7 +1513,7 @@ rs_start(struct tty_struct *tty) xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } - *((unsigned long *)&info->port[REG_XOFF]) = xoff; + *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; if (!info->uses_dma_out && info->xmit.head != info->xmit.tail && info->xmit.buf) e100_enable_serial_tx_ready_irq(info); @@ -1772,7 +1773,7 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl info->icount.rx++; } else { - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; tty_insert_flip_char(tty, data, flag); info->icount.rx++; } @@ -1838,7 +1839,7 @@ static unsigned int handle_all_descr_data(struct e100_serial *info) descr->status = 0; DFLOW( DEBUG_LOG(info->line, "RX %lu\n", recvl); - if (info->tty->stopped) { + if (info->port.tty->stopped) { unsigned char *buf = phys_to_virt(descr->buf); DEBUG_LOG(info->line, "rx 0x%02X\n", buf[0]); DEBUG_LOG(info->line, "rx 0x%02X\n", buf[1]); @@ -1872,7 +1873,7 @@ static void receive_chars_dma(struct e100_serial *info) IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); - tty = info->tty; + tty = info->port.tty; if (!tty) /* Something wrong... */ return; @@ -1887,7 +1888,7 @@ static void receive_chars_dma(struct e100_serial *info) handle_all_descr_data(info); /* Read the status register to detect errors */ - rstat = info->port[REG_STATUS]; + rstat = info->ioport[REG_STATUS]; if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { DFLOW(DEBUG_LOG(info->line, "XOFF detect stat %x\n", rstat)); } @@ -1896,7 +1897,7 @@ static void receive_chars_dma(struct e100_serial *info) /* If we got an error, we must reset it by reading the * data_in field */ - unsigned char data = info->port[REG_DATA]; + unsigned char data = info->ioport[REG_DATA]; PROCSTAT(ser_stat[info->line].errors_cnt++); DEBUG_LOG(info->line, "#dERR: s d 0x%04X\n", @@ -2076,7 +2077,7 @@ static int force_eop_if_needed(struct e100_serial *info) /* We check data_avail bit to determine if data has * arrived since last time */ - unsigned char rstat = info->port[REG_STATUS]; + unsigned char rstat = info->ioport[REG_STATUS]; /* error or datavail? */ if (rstat & SER_ERROR_MASK) { @@ -2095,7 +2096,7 @@ static int force_eop_if_needed(struct e100_serial *info) TIMERD(DEBUG_LOG(info->line, "timeout: rstat 0x%03X\n", rstat | (info->line << 8))); /* Read data to clear status flags */ - (void)info->port[REG_DATA]; + (void)info->ioport[REG_DATA]; info->forced_eop = 0; START_FLUSH_FAST_TIMER(info, "magic"); @@ -2122,7 +2123,7 @@ static void flush_to_flip_buffer(struct e100_serial *info) unsigned long flags; local_irq_save(flags); - tty = info->tty; + tty = info->port.tty; if (!tty) { local_irq_restore(flags); @@ -2287,7 +2288,7 @@ static struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) { unsigned long data_read; - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; if (!tty) { printk("!NO TTY!\n"); @@ -2295,7 +2296,7 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) } /* Read data and status at the same time */ - data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); + data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]); more_data: if (data_read & IO_MASK(R_SERIAL0_READ, xoff_detect) ) { DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); @@ -2350,7 +2351,7 @@ more_data: data_in, data_read); char flag = TTY_NORMAL; if (info->errorcode == ERRCODE_INSERT_BREAK) { - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; tty_insert_flip_char(tty, 0, flag); info->icount.rx++; } @@ -2390,13 +2391,13 @@ more_data: info->icount.rx++; - data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); + data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]); if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { DEBUG_LOG(info->line, "ser_rx %c in loop\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read)); goto more_data; } - tty_flip_buffer_push(info->tty); + tty_flip_buffer_push(info->port.tty); return info; } @@ -2412,7 +2413,7 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) return handle_ser_rx_interrupt_no_dma(info); } /* DMA is used */ - rstat = info->port[REG_STATUS]; + rstat = info->ioport[REG_STATUS]; if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); } @@ -2425,7 +2426,7 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) /* If we got an error, we must reset it by reading the * data_in field */ - data = info->port[REG_DATA]; + data = info->ioport[REG_DATA]; DINTR1(DEBUG_LOG(info->line, "ser_rx! %c\n", data)); DINTR1(DEBUG_LOG(info->line, "ser_rx err stat %02X\n", rstat)); if (!data && (rstat & SER_FRAMING_ERR_MASK)) { @@ -2527,10 +2528,10 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) unsigned char rstat; DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); local_irq_save(flags); - rstat = info->port[REG_STATUS]; + rstat = info->ioport[REG_STATUS]; DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); - info->port[REG_TR_DATA] = info->x_char; + info->ioport[REG_TR_DATA] = info->x_char; info->icount.tx++; info->x_char = 0; /* We must enable since it is disabled in ser_interrupt */ @@ -2544,11 +2545,11 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) /* We only use normal tx interrupt when sending x_char */ DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); local_irq_save(flags); - rstat = info->port[REG_STATUS]; + rstat = info->ioport[REG_STATUS]; DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); e100_disable_serial_tx_ready_irq(info); - if (info->tty->stopped) - rs_stop(info->tty); + if (info->port.tty->stopped) + rs_stop(info->port.tty); /* Enable the DMA channel and tell it to continue */ e100_enable_txdma_channel(info); /* Wait 12 cycles before doing the DMA command */ @@ -2561,9 +2562,10 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) } /* Normal char-by-char interrupt */ if (info->xmit.head == info->xmit.tail - || info->tty->stopped - || info->tty->hw_stopped) { - DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n", info->tty->stopped)); + || info->port.tty->stopped + || info->port.tty->hw_stopped) { + DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n", + info->port.tty->stopped)); e100_disable_serial_tx_ready_irq(info); info->tr_running = 0; return; @@ -2571,7 +2573,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); /* Send a byte, rs485 timing is critical so turn of ints */ local_irq_save(flags); - info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; + info->ioport[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); info->icount.tx++; if (info->xmit.head == info->xmit.tail) { @@ -2725,7 +2727,7 @@ do_softint(struct work_struct *work) info = container_of(work, struct e100_serial, work); - tty = info->tty; + tty = info->port.tty; if (!tty) return; @@ -2767,8 +2769,8 @@ startup(struct e100_serial * info) /* Bits and pieces collected from below. Better to have them in one ifdef:ed clause than to mix in a lot of ifdefs, right? */ - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); info->xmit.head = info->xmit.tail = 0; info->first_recv_buffer = info->last_recv_buffer = NULL; @@ -2825,8 +2827,8 @@ startup(struct e100_serial * info) e100_disable_txdma_channel(info); } - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); info->xmit.head = info->xmit.tail = 0; info->first_recv_buffer = info->last_recv_buffer = NULL; @@ -2846,7 +2848,7 @@ startup(struct e100_serial * info) /* dummy read to reset any serial errors */ - (void)info->port[REG_DATA]; + (void)info->ioport[REG_DATA]; /* enable the interrupts */ if (info->uses_dma_out) @@ -2895,7 +2897,7 @@ shutdown(struct e100_serial * info) /* shut down the transmitter and receiver */ DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line)); e100_disable_rx(info); - info->port[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40); + info->ioport[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40); /* disable interrupts, reset dma channels */ if (info->uses_dma_in) { @@ -2940,14 +2942,14 @@ shutdown(struct e100_serial * info) descr[i].buf = 0; } - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { /* hang up DTR and RTS if HUPCL is enabled */ e100_dtr(info, 0); e100_rts(info, 0); /* could check CRTSCTS before doing this */ } - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); info->flags &= ~ASYNC_INITIALIZED; local_irq_restore(flags); @@ -2964,12 +2966,12 @@ change_speed(struct e100_serial *info) unsigned long flags; /* first some safety checks */ - if (!info->tty || !info->tty->termios) + if (!info->port.tty || !info->port.tty->termios) return; - if (!info->port) + if (!info->ioport) return; - cflag = info->tty->termios->c_cflag; + cflag = info->port.tty->termios->c_cflag; /* possibly, the tx/rx should be disabled first to do this safely */ @@ -3035,7 +3037,7 @@ change_speed(struct e100_serial *info) info->baud = cflag_to_baud(cflag); #ifndef CONFIG_SVINTO_SIM - info->port[REG_BAUD] = cflag_to_etrax_baud(cflag); + info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag); #endif /* CONFIG_SVINTO_SIM */ } @@ -3095,16 +3097,17 @@ change_speed(struct e100_serial *info) /* actually write the control regs to the hardware */ - info->port[REG_TR_CTRL] = info->tx_ctrl; - info->port[REG_REC_CTRL] = info->rx_ctrl; - xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->tty)); + info->ioport[REG_TR_CTRL] = info->tx_ctrl; + info->ioport[REG_REC_CTRL] = info->rx_ctrl; + xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (info->tty->termios->c_iflag & IXON ) { - DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n", STOP_CHAR(info->tty))); + if (info->port.tty->termios->c_iflag & IXON ) { + DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n", + STOP_CHAR(info->port.tty))); xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } - *((unsigned long *)&info->port[REG_XOFF]) = xoff; + *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; local_irq_restore(flags); #endif /* !CONFIG_SVINTO_SIM */ @@ -3153,7 +3156,7 @@ static int rs_raw_write(struct tty_struct *tty, #ifdef SERIAL_DEBUG_DATA if (info->line == SERIAL_DEBUG_LINE) printk("rs_raw_write (%d), status %d\n", - count, info->port[REG_STATUS]); + count, info->ioport[REG_STATUS]); #endif #ifdef CONFIG_SVINTO_SIM @@ -3424,7 +3427,7 @@ get_serial_info(struct e100_serial * info, memset(&tmp, 0, sizeof(tmp)); tmp.type = info->type; tmp.line = info->line; - tmp.port = (int)info->port; + tmp.port = (int)info->ioport; tmp.irq = info->irq; tmp.flags = info->flags; tmp.baud_base = info->baud_base; @@ -3475,7 +3478,7 @@ set_serial_info(struct e100_serial *info, info->type = new_serial.type; info->close_delay = new_serial.close_delay; info->closing_wait = new_serial.closing_wait; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: if (info->flags & ASYNC_INITIALIZED) { @@ -3554,14 +3557,14 @@ char *get_control_state_str(int MLines, char *s) } #endif -static void +static int rs_break(struct tty_struct *tty, int break_state) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; unsigned long flags; - if (!info->port) - return; + if (!info->ioport) + return -EIO; local_irq_save(flags); if (break_state == -1) { @@ -3572,8 +3575,9 @@ rs_break(struct tty_struct *tty, int break_state) /* Set bit 7 (txd) and 6 (tr_enable) */ info->tx_ctrl |= (0x80 | 0x40); } - info->port[REG_TR_CTRL] = info->tx_ctrl; + info->ioport[REG_TR_CTRL] = info->tx_ctrl; local_irq_restore(flags); + return 0; } static int @@ -3811,7 +3815,7 @@ rs_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; - info->tty = 0; + info->port.tty = NULL; if (info->blocked_open) { if (info->close_delay) schedule_timeout_interruptible(info->close_delay); @@ -3915,7 +3919,7 @@ rs_hangup(struct tty_struct *tty) info->event = 0; info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; + info->port.tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -4077,9 +4081,9 @@ rs_open(struct tty_struct *tty, struct file * filp) info->count++; tty->driver_data = info; - info->tty = tty; + info->port.tty = tty; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); @@ -4228,9 +4232,9 @@ static int line_info(char *buf, struct e100_serial *info) unsigned long tmp; ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d", - info->line, (unsigned long)info->port, info->irq); + info->line, (unsigned long)info->ioport, info->irq); - if (!info->port || (info->type == PORT_UNKNOWN)) { + if (!info->ioport || (info->type == PORT_UNKNOWN)) { ret += sprintf(buf+ret, "\n"); return ret; } @@ -4267,18 +4271,18 @@ static int line_info(char *buf, struct e100_serial *info) (unsigned long)info->max_recv_cnt); #if 1 - if (info->tty) { + if (info->port.tty) { - if (info->tty->stopped) + if (info->port.tty->stopped) ret += sprintf(buf+ret, " stopped:%i", - (int)info->tty->stopped); - if (info->tty->hw_stopped) + (int)info->port.tty->stopped); + if (info->port.tty->hw_stopped) ret += sprintf(buf+ret, " hw_stopped:%i", - (int)info->tty->hw_stopped); + (int)info->port.tty->hw_stopped); } { - unsigned char rstat = info->port[REG_STATUS]; + unsigned char rstat = info->ioport[REG_STATUS]; if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) ret += sprintf(buf+ret, " xoff_detect:1"); } @@ -4465,7 +4469,7 @@ rs_init(void) info->uses_dma_in = 0; info->uses_dma_out = 0; info->line = i; - info->tty = 0; + info->port.tty = NULL; info->type = PORT_ETRAX; info->tr_running = 0; info->forced_eop = 0; @@ -4499,7 +4503,7 @@ rs_init(void) if (info->enabled) { printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", - serial_driver->name, info->line, (unsigned int)info->port); + serial_driver->name, info->line, (unsigned int)info->ioport); } } #ifdef CONFIG_ETRAX_FAST_TIMER diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h index ccd0f32b737..e3c5c8c3c09 100644 --- a/drivers/serial/crisv10.h +++ b/drivers/serial/crisv10.h @@ -36,8 +36,9 @@ struct etrax_recv_buffer { }; struct e100_serial { + struct tty_port port; int baud; - volatile u8 *port; /* R_SERIALx_CTRL */ + volatile u8 *ioport; /* R_SERIALx_CTRL */ u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */ /* Output registers */ diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 0dddd68b20d..6042b87797a 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -197,7 +197,7 @@ static inline void dz_receive_chars(struct dz_mux *mux) while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) { dport = &mux->dport[LINE(status)]; uport = &dport->port; - tty = uport->info->tty; /* point to the proper dev */ + tty = uport->info->port.tty; /* point to the proper dev */ ch = UCHAR(status); /* grab the char */ flag = TTY_NORMAL; @@ -249,7 +249,7 @@ static inline void dz_receive_chars(struct dz_mux *mux) } for (i = 0; i < DZ_NB_PORT; i++) if (lines_rx[i]) - tty_flip_buffer_push(mux->dport[i].port.info->tty); + tty_flip_buffer_push(mux->dport[i].port.info->port.tty); } /* @@ -642,6 +642,26 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, spin_unlock_irqrestore(&dport->port.lock, flags); } +/* + * Hack alert! + * Required solely so that the initial PROM-based console + * works undisturbed in parallel with this one. + */ +static void dz_pm(struct uart_port *uport, unsigned int state, + unsigned int oldstate) +{ + struct dz_port *dport = to_dport(uport); + unsigned long flags; + + spin_lock_irqsave(&dport->port.lock, flags); + if (state < 3) + dz_start_tx(&dport->port); + else + dz_stop_tx(&dport->port); + spin_unlock_irqrestore(&dport->port.lock, flags); +} + + static const char *dz_type(struct uart_port *uport) { return "DZ"; @@ -738,6 +758,7 @@ static struct uart_ops dz_ops = { .startup = dz_startup, .shutdown = dz_shutdown, .set_termios = dz_set_termios, + .pm = dz_pm, .type = dz_type, .release_port = dz_release_port, .request_port = dz_request_port, @@ -861,7 +882,10 @@ static int __init dz_console_setup(struct console *co, char *options) if (ret) return ret; + spin_lock_init(&dport->port.lock); /* For dz_pm(). */ + dz_reset(dport); + dz_pm(uport, 0, -1); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 9c2df5c857c..2b7531d9f6a 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -730,7 +730,7 @@ static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port) static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port) { short int count, rcv_buff; - struct tty_struct *tty = icom_port->uart_port.info->tty; + struct tty_struct *tty = icom_port->uart_port.info->port.tty; unsigned short int status; struct uart_icount *icount; unsigned long offset; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 64acb39a51b..3f90f1bbbbc 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -44,8 +44,8 @@ #include <asm/io.h> #include <asm/irq.h> -#include <asm/hardware.h> -#include <asm/arch/imx-uart.h> +#include <mach/hardware.h> +#include <mach/imx-uart.h> /* Register definitions */ #define URXD0 0x0 /* Receiver Register */ @@ -127,8 +127,13 @@ #define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ #define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ #define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ -#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ -#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ +#ifdef CONFIG_ARCH_IMX +#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */ +#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */ +#endif +#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3 +#define UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */ +#endif #define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ #define UCR3_BPEN (1<<0) /* Preset registers enable */ #define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ @@ -372,7 +377,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) { struct imx_port *sport = dev_id; unsigned int rx,flg,ignored = 0; - struct tty_struct *tty = sport->port.info->tty; + struct tty_struct *tty = sport->port.info->port.tty; unsigned long flags, temp; spin_lock_irqsave(&sport->port.lock,flags); @@ -445,7 +450,7 @@ static irqreturn_t imx_int(int irq, void *dev_id) readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) imx_txint(irq, dev_id); - if (sts & USR1_RTSS) + if (sts & USR1_RTSD) imx_rtsint(irq, dev_id); return IRQ_HANDLED; @@ -598,6 +603,12 @@ static int imx_startup(struct uart_port *port) temp |= (UCR2_RXEN | UCR2_TXEN); writel(temp, sport->port.membase + UCR2); +#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3 + temp = readl(sport->port.membase + UCR3); + temp |= UCR3_RXDMUXSEL; + writel(temp, sport->port.membase + UCR3); +#endif + /* * Enable modem status interrupts */ @@ -1133,13 +1144,19 @@ static int serial_imx_probe(struct platform_device *pdev) if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS)) sport->have_rtscts = 1; - if (pdata->init) - pdata->init(pdev); + if (pdata->init) { + ret = pdata->init(pdev); + if (ret) + goto clkput; + } uart_add_one_port(&imx_reg, &sport->port); platform_set_drvdata(pdev, &sport->port); return 0; +clkput: + clk_put(sport->clk); + clk_disable(sport->clk); unmap: iounmap(sport->port.membase); free: diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 4f1af71e9a1..6dd98f9fb89 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c @@ -905,7 +905,7 @@ static void transmit_chars(struct uart_port *the_port) return; info = the_port->info; - tty = info->tty; + tty = info->port.tty; if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) { /* Nothing to do or hw stopped */ @@ -997,14 +997,14 @@ ioc3_change_speed(struct uart_port *the_port, the_port->ignore_status_mask = N_ALL_INPUT; - info->tty->low_latency = 1; + info->port.tty->low_latency = 1; - if (I_IGNPAR(info->tty)) + if (I_IGNPAR(info->port.tty)) the_port->ignore_status_mask &= ~(N_PARITY_ERROR | N_FRAMING_ERROR); - if (I_IGNBRK(info->tty)) { + if (I_IGNBRK(info->port.tty)) { the_port->ignore_status_mask &= ~N_BREAK; - if (I_IGNPAR(info->tty)) + if (I_IGNPAR(info->port.tty)) the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; } if (!(cflag & CREAD)) { @@ -1399,14 +1399,14 @@ static int receive_chars(struct uart_port *the_port) /* Make sure all the pointers are "good" ones */ if (!info) return 0; - if (!info->tty) + if (!info->port.tty) return 0; if (!(port->ip_flags & INPUT_ENABLE)) return 0; spin_lock_irqsave(&the_port->lock, pflags); - tty = info->tty; + tty = info->port.tty; read_count = do_read(the_port, ch, MAX_CHARS); if (read_count > 0) { diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 49b8a82b7b9..6bab63cd5b2 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -1635,7 +1635,7 @@ static void transmit_chars(struct uart_port *the_port) return; info = the_port->info; - tty = info->tty; + tty = info->port.tty; if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) { /* Nothing to do or hw stopped */ @@ -1738,14 +1738,14 @@ ioc4_change_speed(struct uart_port *the_port, the_port->ignore_status_mask = N_ALL_INPUT; - info->tty->low_latency = 1; + info->port.tty->low_latency = 1; - if (I_IGNPAR(info->tty)) + if (I_IGNPAR(info->port.tty)) the_port->ignore_status_mask &= ~(N_PARITY_ERROR | N_FRAMING_ERROR); - if (I_IGNBRK(info->tty)) { + if (I_IGNBRK(info->port.tty)) { the_port->ignore_status_mask &= ~N_BREAK; - if (I_IGNPAR(info->tty)) + if (I_IGNPAR(info->port.tty)) the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; } if (!(cflag & CREAD)) { @@ -1801,7 +1801,8 @@ static inline int ic4_startup_local(struct uart_port *the_port) ioc4_set_proto(port, the_port->mapbase); /* set the speed of the serial port */ - ioc4_change_speed(the_port, info->tty->termios, (struct ktermios *)0); + ioc4_change_speed(the_port, info->port.tty->termios, + (struct ktermios *)0); return 0; } @@ -2346,11 +2347,11 @@ static void receive_chars(struct uart_port *the_port) /* Make sure all the pointers are "good" ones */ if (!info) return; - if (!info->tty) + if (!info->port.tty) return; spin_lock_irqsave(&the_port->lock, pflags); - tty = info->tty; + tty = info->port.tty; request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS); @@ -2440,8 +2441,8 @@ static void ic4_shutdown(struct uart_port *the_port) wake_up_interruptible(&info->delta_msr_wait); - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); spin_lock_irqsave(&the_port->lock, port_flags); set_notification(port, N_ALL, 0); diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 9c95bc0398a..0d9acbd0bb7 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -257,8 +257,8 @@ static struct tty_struct *ip22zilog_receive_chars(struct uart_ip22zilog_port *up tty = NULL; if (up->port.info != NULL && - up->port.info->tty != NULL) - tty = up->port.info->tty; + up->port.info->port.tty != NULL) + tty = up->port.info->port.tty; for (;;) { ch = readb(&channel->control); diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index b2d6f5b1a7c..b7584ca55ad 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -998,7 +998,7 @@ static void neo_param(struct jsm_channel *ch) { 50, B50 }, }; - cflag = C_BAUD(ch->uart_port.info->tty); + cflag = C_BAUD(ch->uart_port.info->port.tty); baud = 9600; for (i = 0; i < ARRAY_SIZE(baud_rates); i++) { if (baud_rates[i].cflag == cflag) { diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 94ec6637250..a697914ae3d 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -145,7 +145,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch) struct ktermios *termios; spin_lock_irqsave(&port->lock, lock_flags); - termios = port->info->tty->termios; + termios = port->info->port.tty->termios; if (ch == termios->c_cc[VSTART]) channel->ch_bd->bd_ops->send_start_character(channel); @@ -239,7 +239,7 @@ static int jsm_tty_open(struct uart_port *port) channel->ch_cached_lsr = 0; channel->ch_stops_sent = 0; - termios = port->info->tty->termios; + termios = port->info->port.tty->termios; channel->ch_c_cflag = termios->c_cflag; channel->ch_c_iflag = termios->c_iflag; channel->ch_c_oflag = termios->c_oflag; @@ -272,7 +272,7 @@ static void jsm_tty_close(struct uart_port *port) jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); bd = channel->ch_bd; - ts = channel->uart_port.info->tty->termios; + ts = channel->uart_port.info->port.tty->termios; channel->ch_flags &= ~(CH_STOPI); @@ -515,7 +515,7 @@ void jsm_input(struct jsm_channel *ch) if (!ch) return; - tp = ch->uart_port.info->tty; + tp = ch->uart_port.info->port.tty; bd = ch->ch_bd; if(!bd) diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index c2bb11c02bd..23d03051101 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -325,7 +325,7 @@ static void m32r_sio_enable_ms(struct uart_port *port) static void receive_chars(struct uart_sio_port *up, int *status) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->port.tty; unsigned char ch; unsigned char flag; int max_count = 256; @@ -1160,7 +1160,7 @@ static int __init m32r_sio_init(void) { int ret, i; - printk(KERN_INFO "Serial: M32R SIO driver $Revision: 1.11 $ "); + printk(KERN_INFO "Serial: M32R SIO driver\n"); for (i = 0; i < NR_IRQS; i++) spin_lock_init(&irq_lists[i].lock); @@ -1189,4 +1189,4 @@ EXPORT_SYMBOL(m32r_sio_suspend_port); EXPORT_SYMBOL(m32r_sio_resume_port); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic M32R SIO serial driver $Revision: 1.11 $"); +MODULE_DESCRIPTION("Generic M32R SIO serial driver"); diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c index 7e164e0cd21..b2001c5b145 100644 --- a/drivers/serial/mcf.c +++ b/drivers/serial/mcf.c @@ -312,7 +312,7 @@ static void mcf_rx_chars(struct mcf_uart *pp) uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag); } - tty_flip_buffer_push(port->info->tty); + tty_flip_buffer_push(port->info->port.tty); } /****************************************************************************/ diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 56007cc8a9b..fbe3835f6b7 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -327,7 +327,7 @@ static void mcfrs_start(struct tty_struct *tty) static inline void receive_chars(struct mcf_serial *info) { volatile unsigned char *uartp; - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; unsigned char status, ch, flag; if (!tty) @@ -382,7 +382,7 @@ static inline void transmit_chars(struct mcf_serial *info) info->stats.tx++; } - if ((info->xmit_cnt <= 0) || info->tty->stopped) { + if ((info->xmit_cnt <= 0) || info->port.tty->stopped) { info->imr &= ~MCFUART_UIR_TXREADY; uartp[MCFUART_UIMR] = info->imr; return; @@ -428,7 +428,7 @@ irqreturn_t mcfrs_interrupt(int irq, void *dev_id) static void mcfrs_offintr(struct work_struct *work) { struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue); - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; if (tty) tty_wakeup(tty); @@ -498,7 +498,7 @@ static void mcfrs_timer(void) static void do_serial_hangup(struct work_struct *work) { struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue_hangup); - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; if (tty) tty_hangup(tty); @@ -532,8 +532,8 @@ static int startup(struct mcf_serial * info) uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ mcfrs_setsignals(info, 1, 1); - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; /* @@ -578,7 +578,7 @@ static void shutdown(struct mcf_serial * info) uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) mcfrs_setsignals(info, 0, 0); if (info->xmit_buf) { @@ -586,8 +586,8 @@ static void shutdown(struct mcf_serial * info) info->xmit_buf = 0; } - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); info->flags &= ~ASYNC_INITIALIZED; local_irq_restore(flags); @@ -609,9 +609,9 @@ static void mcfrs_change_speed(struct mcf_serial *info) unsigned int fraction; #endif - if (!info->tty || !info->tty->termios) + if (!info->port.tty || !info->port.tty->termios) return; - cflag = info->tty->termios->c_cflag; + cflag = info->port.tty->termios->c_cflag; if (info->addr == 0) return; @@ -623,7 +623,7 @@ static void mcfrs_change_speed(struct mcf_serial *info) if (i & CBAUDEX) { i &= ~CBAUDEX; if (i < 1 || i > 4) - info->tty->termios->c_cflag &= ~CBAUDEX; + info->port.tty->termios->c_cflag &= ~CBAUDEX; else i += 15; } @@ -1216,7 +1216,7 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp) tty->closing = 0; info->event = 0; - info->tty = 0; + info->port.tty = NULL; #if 0 if (tty->ldisc.num != ldiscs[N_TTY].num) { if (tty->ldisc.close) @@ -1325,7 +1325,7 @@ void mcfrs_hangup(struct tty_struct *tty) info->event = 0; info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; + info->port.tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -1452,7 +1452,7 @@ int mcfrs_open(struct tty_struct *tty, struct file * filp) #endif info->count++; tty->driver_data = info; - info->tty = tty; + info->port.tty = tty; /* * Start up serial port @@ -1767,7 +1767,7 @@ mcfrs_init(void) for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) { info->magic = SERIAL_MAGIC; info->line = i; - info->tty = 0; + info->port.tty = NULL; info->custom_divisor = 16; info->close_delay = 50; info->closing_wait = 3000; diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index efc971d9647..36126070d9a 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -732,7 +732,7 @@ static struct uart_ops mpc52xx_uart_ops = { static inline int mpc52xx_uart_int_rx_chars(struct uart_port *port) { - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; unsigned char ch, flag; unsigned short status; diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index e8819c43f57..61d3ade5286 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -921,6 +921,10 @@ static int mpsc_make_ready(struct mpsc_port_info *pi) return 0; } +#ifdef CONFIG_CONSOLE_POLL +static int serial_polled; +#endif + /* ****************************************************************************** * @@ -932,7 +936,7 @@ static int mpsc_make_ready(struct mpsc_port_info *pi) static int mpsc_rx_intr(struct mpsc_port_info *pi) { struct mpsc_rx_desc *rxre; - struct tty_struct *tty = pi->port.info->tty; + struct tty_struct *tty = pi->port.info->port.tty; u32 cmdstat, bytes_in, i; int rc = 0; u8 *bp; @@ -956,7 +960,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi) while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) & SDMA_DESC_CMDSTAT_O)) { bytes_in = be16_to_cpu(rxre->bytecnt); - +#ifdef CONFIG_CONSOLE_POLL + if (unlikely(serial_polled)) { + serial_polled = 0; + return 0; + } +#endif /* Following use of tty struct directly is deprecated */ if (unlikely(tty_buffer_request_room(tty, bytes_in) < bytes_in)) { @@ -1017,6 +1026,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi) if (uart_handle_sysrq_char(&pi->port, *bp)) { bp++; bytes_in--; +#ifdef CONFIG_CONSOLE_POLL + if (unlikely(serial_polled)) { + serial_polled = 0; + return 0; + } +#endif goto next_frame; } @@ -1519,6 +1534,133 @@ static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser) return rc; } +#ifdef CONFIG_CONSOLE_POLL +/* Serial polling routines for writing and reading from the uart while + * in an interrupt or debug context. + */ + +static char poll_buf[2048]; +static int poll_ptr; +static int poll_cnt; +static void mpsc_put_poll_char(struct uart_port *port, + unsigned char c); + +static int mpsc_get_poll_char(struct uart_port *port) +{ + struct mpsc_port_info *pi = (struct mpsc_port_info *)port; + struct mpsc_rx_desc *rxre; + u32 cmdstat, bytes_in, i; + u8 *bp; + + if (!serial_polled) + serial_polled = 1; + + pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line); + + if (poll_cnt) { + poll_cnt--; + return poll_buf[poll_ptr++]; + } + poll_ptr = 0; + poll_cnt = 0; + + while (poll_cnt == 0) { + rxre = (struct mpsc_rx_desc *)(pi->rxr + + (pi->rxr_posn*MPSC_RXRE_SIZE)); + dma_cache_sync(pi->port.dev, (void *)rxre, + MPSC_RXRE_SIZE, DMA_FROM_DEVICE); +#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) + if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ + invalidate_dcache_range((ulong)rxre, + (ulong)rxre + MPSC_RXRE_SIZE); +#endif + /* + * Loop through Rx descriptors handling ones that have + * been completed. + */ + while (poll_cnt == 0 && + !((cmdstat = be32_to_cpu(rxre->cmdstat)) & + SDMA_DESC_CMDSTAT_O)){ + bytes_in = be16_to_cpu(rxre->bytecnt); + bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); + dma_cache_sync(pi->port.dev, (void *) bp, + MPSC_RXBE_SIZE, DMA_FROM_DEVICE); +#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) + if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ + invalidate_dcache_range((ulong)bp, + (ulong)bp + MPSC_RXBE_SIZE); +#endif + if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR | + SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) && + !(cmdstat & pi->port.ignore_status_mask)) { + poll_buf[poll_cnt] = *bp; + poll_cnt++; + } else { + for (i = 0; i < bytes_in; i++) { + poll_buf[poll_cnt] = *bp++; + poll_cnt++; + } + pi->port.icount.rx += bytes_in; + } + rxre->bytecnt = cpu_to_be16(0); + wmb(); + rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | + SDMA_DESC_CMDSTAT_EI | + SDMA_DESC_CMDSTAT_F | + SDMA_DESC_CMDSTAT_L); + wmb(); + dma_cache_sync(pi->port.dev, (void *)rxre, + MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); +#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) + if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ + flush_dcache_range((ulong)rxre, + (ulong)rxre + MPSC_RXRE_SIZE); +#endif + + /* Advance to next descriptor */ + pi->rxr_posn = (pi->rxr_posn + 1) & + (MPSC_RXR_ENTRIES - 1); + rxre = (struct mpsc_rx_desc *)(pi->rxr + + (pi->rxr_posn * MPSC_RXRE_SIZE)); + dma_cache_sync(pi->port.dev, (void *)rxre, + MPSC_RXRE_SIZE, DMA_FROM_DEVICE); +#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) + if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ + invalidate_dcache_range((ulong)rxre, + (ulong)rxre + MPSC_RXRE_SIZE); +#endif + } + + /* Restart rx engine, if its stopped */ + if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0) + mpsc_start_rx(pi); + } + if (poll_cnt) { + poll_cnt--; + return poll_buf[poll_ptr++]; + } + + return 0; +} + + +static void mpsc_put_poll_char(struct uart_port *port, + unsigned char c) +{ + struct mpsc_port_info *pi = (struct mpsc_port_info *)port; + u32 data; + + data = readl(pi->mpsc_base + MPSC_MPCR); + writeb(c, pi->mpsc_base + MPSC_CHR_1); + mb(); + data = readl(pi->mpsc_base + MPSC_CHR_2); + data |= MPSC_CHR_2_TTCS; + writel(data, pi->mpsc_base + MPSC_CHR_2); + mb(); + + while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS); +} +#endif static struct uart_ops mpsc_pops = { .tx_empty = mpsc_tx_empty, @@ -1537,6 +1679,10 @@ static struct uart_ops mpsc_pops = { .request_port = mpsc_request_port, .config_port = mpsc_config_port, .verify_port = mpsc_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = mpsc_get_poll_char, + .poll_put_char = mpsc_put_poll_char, +#endif }; /* @@ -1972,7 +2118,7 @@ static int __init mpsc_drv_init(void) { int rc; - printk(KERN_INFO "Serial: MPSC driver $Revision: 1.00 $\n"); + printk(KERN_INFO "Serial: MPSC driver\n"); memset(mpsc_ports, 0, sizeof(mpsc_ports)); memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs)); @@ -2004,7 +2150,7 @@ module_init(mpsc_drv_init); module_exit(mpsc_drv_exit); MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>"); -MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver $Revision: 1.00 $"); +MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver"); MODULE_VERSION(MPSC_VERSION); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(MPSC_MAJOR); diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index e94031731a4..953a5ffa9b4 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -243,7 +243,7 @@ static void mux_write(struct uart_port *port) static void mux_read(struct uart_port *port) { int data; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; __u32 start_count = port->icount.rx; while(1) { diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c index 81ac9bb4f39..3f489329e8d 100644 --- a/drivers/serial/netx-serial.c +++ b/drivers/serial/netx-serial.c @@ -35,8 +35,8 @@ #include <asm/io.h> #include <asm/irq.h> -#include <asm/hardware.h> -#include <asm/arch/netx-regs.h> +#include <mach/hardware.h> +#include <mach/netx-regs.h> /* We've been assigned a range on the "Low-density serial ports" major */ #define SERIAL_NX_MAJOR 204 @@ -203,7 +203,7 @@ static void netx_txint(struct uart_port *port) static void netx_rxint(struct uart_port *port) { unsigned char rx, flg, status; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; while (!(readl(port->membase + UART_FR) & FR_RXFE)) { rx = readl(port->membase + UART_DR); diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 794bd0f50d7..317b061f764 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -242,12 +242,12 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) } /* Sanity check, make sure the old bug is no longer happening */ - if (uap->port.info == NULL || uap->port.info->tty == NULL) { + if (uap->port.info == NULL || uap->port.info->port.tty == NULL) { WARN_ON(1); (void)read_zsdata(uap); return NULL; } - tty = uap->port.info->tty; + tty = uap->port.info->port.tty; while (1) { error = 0; diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c index d0e5a79ea63..22e30d21225 100644 --- a/drivers/serial/pnx8xxx_uart.c +++ b/drivers/serial/pnx8xxx_uart.c @@ -181,7 +181,7 @@ static void pnx8xxx_enable_ms(struct uart_port *port) static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport) { - struct tty_struct *tty = sport->port.info->tty; + struct tty_struct *tty = sport->port.info->port.tty; unsigned int status, ch, flg; status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) | @@ -824,7 +824,7 @@ static int __init pnx8xxx_serial_init(void) { int ret; - printk(KERN_INFO "Serial: PNX8XXX driver $Revision: 1.2 $\n"); + printk(KERN_INFO "Serial: PNX8XXX driver\n"); pnx8xxx_init_ports(); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index b4f7ffb7688..f7a0d37c422 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -45,9 +45,9 @@ #include <linux/clk.h> #include <asm/io.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/irq.h> -#include <asm/arch/pxa-regs.h> +#include <mach/pxa-regs.h> struct uart_pxa_port { @@ -101,7 +101,7 @@ static void serial_pxa_stop_rx(struct uart_port *port) static inline void receive_chars(struct uart_pxa_port *up, int *status) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->port.tty; unsigned int ch, flag; int max_count = 256; diff --git a/drivers/serial/s3c2400.c b/drivers/serial/s3c2400.c index a1102053e55..c8b4266ac35 100644 --- a/drivers/serial/s3c2400.c +++ b/drivers/serial/s3c2400.c @@ -17,10 +17,10 @@ #include <asm/irq.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/plat-s3c/regs-serial.h> -#include <asm/arch/regs-gpio.h> +#include <mach/regs-gpio.h> #include "samsung.h" diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index c5f03f41686..40a2531b554 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -19,10 +19,10 @@ #include <linux/serial.h> #include <asm/irq.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/plat-s3c/regs-serial.h> -#include <asm/arch/regs-gpio.h> +#include <mach/regs-gpio.h> #include "samsung.h" diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c index ce0c220e3e9..d0170319c72 100644 --- a/drivers/serial/s3c2412.c +++ b/drivers/serial/s3c2412.c @@ -19,10 +19,10 @@ #include <linux/serial.h> #include <asm/irq.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/plat-s3c/regs-serial.h> -#include <asm/arch/regs-gpio.h> +#include <mach/regs-gpio.h> #include "samsung.h" diff --git a/drivers/serial/s3c2440.c b/drivers/serial/s3c2440.c index 38f954bd39c..d4a2b17b249 100644 --- a/drivers/serial/s3c2440.c +++ b/drivers/serial/s3c2440.c @@ -19,10 +19,10 @@ #include <linux/serial.h> #include <asm/irq.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/plat-s3c/regs-serial.h> -#include <asm/arch/regs-gpio.h> +#include <mach/regs-gpio.h> #include "samsung.h" diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 62b38582f5e..b24a25ea6bc 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -20,9 +20,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: sa1100.c,v 1.50 2002/07/29 14:41:04 rmk Exp $ - * */ #if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) @@ -42,7 +39,7 @@ #include <asm/io.h> #include <asm/irq.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/mach/serial_sa1100.h> /* We've been assigned a range on the "Low-density serial ports" major */ @@ -192,7 +189,7 @@ static void sa1100_enable_ms(struct uart_port *port) static void sa1100_rx_chars(struct sa1100_port *sport) { - struct tty_struct *tty = sport->port.info->tty; + struct tty_struct *tty = sport->port.info->port.tty; unsigned int status, ch, flg; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | @@ -892,7 +889,7 @@ static int __init sa1100_serial_init(void) { int ret; - printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.50 $\n"); + printk(KERN_INFO "Serial: SA11x0 driver\n"); sa1100_init_ports(); @@ -915,7 +912,7 @@ module_init(sa1100_serial_init); module_exit(sa1100_serial_exit); MODULE_AUTHOR("Deep Blue Solutions Ltd"); -MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.50 $"); +MODULE_DESCRIPTION("SA1100 generic serial port driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_SA1100_MAJOR); MODULE_ALIAS("platform:sa11x0-uart"); diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index 4a3ecaa629e..5a88b3f9fe9 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -45,10 +45,10 @@ #include <asm/irq.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/plat-s3c/regs-serial.h> -#include <asm/arch/regs-gpio.h> +#include <mach/regs-gpio.h> #include "samsung.h" @@ -202,7 +202,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id) { struct s3c24xx_uart_port *ourport = dev_id; struct uart_port *port = &ourport->port; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; unsigned int ufcon, ch, flag, ufstat, uerstat; int max_count = 64; diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c index f8e1447a022..a4fb343a08d 100644 --- a/drivers/serial/sb1250-duart.c +++ b/drivers/serial/sb1250-duart.c @@ -384,7 +384,7 @@ static void sbd_receive_chars(struct sbd_port *sport) uart_insert_char(uport, status, M_DUART_OVRUN_ERR, ch, flag); } - tty_flip_buffer_push(uport->info->tty); + tty_flip_buffer_push(uport->info->port.tty); } static void sbd_transmit_chars(struct sbd_port *sport) diff --git a/drivers/serial/sc26xx.c b/drivers/serial/sc26xx.c index ae2a9e2df77..e0be11ceaa2 100644 --- a/drivers/serial/sc26xx.c +++ b/drivers/serial/sc26xx.c @@ -141,7 +141,7 @@ static struct tty_struct *receive_chars(struct uart_port *port) u8 status; if (port->info != NULL) /* Unopened serial console */ - tty = port->info->tty; + tty = port->info->port.tty; while (limit-- > 0) { status = READ_SC_PORT(port, SR); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 42d2e108b67..f977c98cfa9 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -50,7 +50,7 @@ static struct lock_class_key port_lock_key; #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) -#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0)) +#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->port.blocked_open : 0)) #ifdef CONFIG_SERIAL_CORE_CONSOLE #define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) @@ -113,7 +113,7 @@ static void uart_start(struct tty_struct *tty) static void uart_tasklet_action(unsigned long data) { struct uart_state *state = (struct uart_state *)data; - tty_wakeup(state->info->tty); + tty_wakeup(state->info->port.tty); } static inline void @@ -135,7 +135,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) /* * Startup the port. This will be called once per open. All calls - * will be serialised by the per-port semaphore. + * will be serialised by the per-port mutex. */ static int uart_startup(struct uart_state *state, int init_hw) { @@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw) * once we have successfully opened the port. Also set * up the tty->alt_speed kludge */ - set_bit(TTY_IO_ERROR, &info->tty->flags); + set_bit(TTY_IO_ERROR, &info->port.tty->flags); if (port->type == PORT_UNKNOWN) return 0; @@ -162,6 +162,7 @@ static int uart_startup(struct uart_state *state, int init_hw) * buffer. */ if (!info->xmit.buf) { + /* This is protected by the per port mutex */ page = get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; @@ -182,20 +183,20 @@ static int uart_startup(struct uart_state *state, int init_hw) * Setup the RTS and DTR signals once the * port is open and ready to respond. */ - if (info->tty->termios->c_cflag & CBAUD) + if (info->port.tty->termios->c_cflag & CBAUD) uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); } if (info->flags & UIF_CTS_FLOW) { spin_lock_irq(&port->lock); if (!(port->ops->get_mctrl(port) & TIOCM_CTS)) - info->tty->hw_stopped = 1; + info->port.tty->hw_stopped = 1; spin_unlock_irq(&port->lock); } info->flags |= UIF_INITIALIZED; - clear_bit(TTY_IO_ERROR, &info->tty->flags); + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); } if (retval && capable(CAP_SYS_ADMIN)) @@ -217,8 +218,8 @@ static void uart_shutdown(struct uart_state *state) /* * Set the TTY IO error marker */ - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); if (info->flags & UIF_INITIALIZED) { info->flags &= ~UIF_INITIALIZED; @@ -226,7 +227,7 @@ static void uart_shutdown(struct uart_state *state) /* * Turn off DTR and RTS early. */ - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); /* @@ -426,7 +427,7 @@ EXPORT_SYMBOL(uart_get_divisor); static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios) { - struct tty_struct *tty = state->info->tty; + struct tty_struct *tty = state->info->port.tty; struct uart_port *port = state->port; struct ktermios *termios; @@ -573,6 +574,8 @@ static void uart_flush_buffer(struct tty_struct *tty) spin_lock_irqsave(&port->lock, flags); uart_circ_clear(&state->info->xmit); + if (port->ops->flush_buffer) + port->ops->flush_buffer(port); spin_unlock_irqrestore(&port->lock, flags); tty_wakeup(tty); } @@ -834,8 +837,8 @@ static int uart_set_info(struct uart_state *state, state->closing_wait = closing_wait; if (new_serial.xmit_fifo_size) port->fifosize = new_serial.xmit_fifo_size; - if (state->info->tty) - state->info->tty->low_latency = + if (state->info->port.tty) + state->info->port.tty->low_latency = (port->flags & UPF_LOW_LATENCY) ? 1 : 0; check_and_exit: @@ -855,7 +858,7 @@ static int uart_set_info(struct uart_state *state, printk(KERN_NOTICE "%s sets custom speed on %s. This " "is deprecated.\n", current->comm, - tty_name(state->info->tty, buf)); + tty_name(state->info->port.tty, buf)); } uart_change_speed(state, NULL); } @@ -887,7 +890,7 @@ static int uart_get_lsr_info(struct uart_state *state, */ if (port->x_char || ((uart_circ_chars_pending(&state->info->xmit) > 0) && - !state->info->tty->stopped && !state->info->tty->hw_stopped)) + !state->info->port.tty->stopped && !state->info->port.tty->hw_stopped)) result &= ~TIOCSER_TEMT; return put_user(result, value); @@ -931,7 +934,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file, return ret; } -static void uart_break_ctl(struct tty_struct *tty, int break_state) +static int uart_break_ctl(struct tty_struct *tty, int break_state) { struct uart_state *state = tty->driver_data; struct uart_port *port = state->port; @@ -942,6 +945,7 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state) port->ops->break_ctl(port, break_state); mutex_unlock(&state->mutex); + return 0; } static int uart_do_autoconfig(struct uart_state *state) @@ -1237,7 +1241,7 @@ static void uart_set_termios(struct tty_struct *tty, */ if (!(old_termios->c_cflag & CLOCAL) && (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&state->info->open_wait); + wake_up_interruptible(&state->info->port.open_wait); #endif } @@ -1318,9 +1322,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty_ldisc_flush(tty); tty->closing = 0; - state->info->tty = NULL; + state->info->port.tty = NULL; - if (state->info->blocked_open) { + if (state->info->port.blocked_open) { if (state->close_delay) msleep_interruptible(state->close_delay); } else if (!uart_console(port)) { @@ -1331,7 +1335,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * Wake up anyone trying to open this port. */ state->info->flags &= ~UIF_NORMAL_ACTIVE; - wake_up_interruptible(&state->info->open_wait); + wake_up_interruptible(&state->info->port.open_wait); done: mutex_unlock(&state->mutex); @@ -1415,8 +1419,8 @@ static void uart_hangup(struct tty_struct *tty) uart_shutdown(state); state->count = 0; state->info->flags &= ~UIF_NORMAL_ACTIVE; - state->info->tty = NULL; - wake_up_interruptible(&state->info->open_wait); + state->info->port.tty = NULL; + wake_up_interruptible(&state->info->port.open_wait); wake_up_interruptible(&state->info->delta_msr_wait); } mutex_unlock(&state->mutex); @@ -1430,7 +1434,7 @@ static void uart_hangup(struct tty_struct *tty) */ static void uart_update_termios(struct uart_state *state) { - struct tty_struct *tty = state->info->tty; + struct tty_struct *tty = state->info->port.tty; struct uart_port *port = state->port; if (uart_console(port) && port->cons->cflag) { @@ -1469,17 +1473,17 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) struct uart_port *port = state->port; unsigned int mctrl; - info->blocked_open++; + info->port.blocked_open++; state->count--; - add_wait_queue(&info->open_wait, &wait); + add_wait_queue(&info->port.open_wait, &wait); while (1) { set_current_state(TASK_INTERRUPTIBLE); /* * If we have been hung up, tell userspace/restart open. */ - if (tty_hung_up_p(filp) || info->tty == NULL) + if (tty_hung_up_p(filp) || info->port.tty == NULL) break; /* @@ -1498,8 +1502,8 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) * have set TTY_IO_ERROR for a non-existant port. */ if ((filp->f_flags & O_NONBLOCK) || - (info->tty->termios->c_cflag & CLOCAL) || - (info->tty->flags & (1 << TTY_IO_ERROR))) + (info->port.tty->termios->c_cflag & CLOCAL) || + (info->port.tty->flags & (1 << TTY_IO_ERROR))) break; /* @@ -1507,7 +1511,7 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) * not set RTS here - we want to make sure we catch * the data from the modem. */ - if (info->tty->termios->c_cflag & CBAUD) + if (info->port.tty->termios->c_cflag & CBAUD) uart_set_mctrl(port, TIOCM_DTR); /* @@ -1529,15 +1533,15 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) break; } set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); + remove_wait_queue(&info->port.open_wait, &wait); state->count++; - info->blocked_open--; + info->port.blocked_open--; if (signal_pending(current)) return -ERESTARTSYS; - if (!info->tty || tty_hung_up_p(filp)) + if (!info->port.tty || tty_hung_up_p(filp)) return -EAGAIN; return 0; @@ -1560,10 +1564,13 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) goto err_unlock; } + /* BKL: RACE HERE - LEAK */ + /* We should move this into the uart_state structure and kill off + this whole complexity */ if (!state->info) { state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL); if (state->info) { - init_waitqueue_head(&state->info->open_wait); + init_waitqueue_head(&state->info->port.open_wait); init_waitqueue_head(&state->info->delta_msr_wait); /* @@ -1620,7 +1627,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) * be re-entered while allocating the info structure, or while we * request any IRQs that the driver may need. This also has the nice * side-effect that it delays the action of uart_hangup, so we can - * guarantee that info->tty will always contain something reasonable. + * guarantee that info->port.tty will always contain something reasonable. */ state = uart_get(drv, line); if (IS_ERR(state)) { @@ -1636,7 +1643,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) tty->driver_data = state; tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; tty->alt_speed = 0; - state->info->tty = tty; + state->info->port.tty = tty; /* * If the port is in the middle of closing, bail out now. @@ -2099,8 +2106,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) /* * If that's unset, use the tty termios setting. */ - if (state->info && state->info->tty && termios.c_cflag == 0) - termios = *state->info->tty->termios; + if (state->info && state->info->port.tty && termios.c_cflag == 0) + termios = *state->info->port.tty->termios; uart_change_pm(state, 0); port->ops->set_termios(port, &termios, NULL); @@ -2519,8 +2526,8 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) tty_unregister_device(drv->tty_driver, port->line); info = state->info; - if (info && info->tty) - tty_vhangup(info->tty); + if (info && info->port.tty) + tty_vhangup(info->port.tty); /* * All users of this port should now be disconnected from diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c index 8721afe1ae4..b9cbfc87f61 100644 --- a/drivers/serial/serial_ks8695.c +++ b/drivers/serial/serial_ks8695.c @@ -26,8 +26,8 @@ #include <asm/irq.h> #include <asm/mach/irq.h> -#include <asm/arch/regs-uart.h> -#include <asm/arch/regs-irq.h> +#include <mach/regs-uart.h> +#include <mach/regs-irq.h> #if defined(CONFIG_SERIAL_KS8695_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -108,7 +108,7 @@ static void ks8695uart_disable_ms(struct uart_port *port) static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id) { struct uart_port *port = dev_id; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; unsigned int status, ch, lsr, flg, max_count = 256; status = UART_GET_LSR(port); /* clears pending LSR interrupts */ diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index eb18d429752..cb49a5ac022 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -137,7 +137,7 @@ static void lh7a40xuart_enable_ms (struct uart_port* port) static void lh7a40xuart_rx_chars (struct uart_port* port) { - struct tty_struct* tty = port->info->tty; + struct tty_struct* tty = port->info->port.tty; int cbRxMax = 256; /* (Gross) limit on receive */ unsigned int data; /* Received data and status */ unsigned int flag; diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 7ad21925869..8fcb4c5b9a2 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -272,7 +272,7 @@ static void serial_txx9_initialize(struct uart_port *port) static inline void receive_chars(struct uart_txx9_port *up, unsigned int *status) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->port.tty; unsigned char ch; unsigned int disr = *status; int max_count = 256; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index ce6ee92b3a1..3df2aaec829 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -410,7 +410,6 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) #endif #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \ - defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) static inline int scif_txroom(struct uart_port *port) @@ -422,6 +421,22 @@ static inline int scif_rxroom(struct uart_port *port) { return sci_in(port, SCRFDR) & 0xff; } +#elif defined(CONFIG_CPU_SUBTYPE_SH7763) +static inline int scif_txroom(struct uart_port *port) +{ + if((port->mapbase == 0xffe00000) || (port->mapbase == 0xffe08000)) /* SCIF0/1*/ + return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff); + else /* SCIF2 */ + return SCIF2_TXROOM_MAX - (sci_in(port, SCFDR) >> 8); +} + +static inline int scif_rxroom(struct uart_port *port) +{ + if((port->mapbase == 0xffe00000) || (port->mapbase == 0xffe08000)) /* SCIF0/1*/ + return sci_in(port, SCRFDR) & 0xff; + else /* SCIF2 */ + return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; +} #else static inline int scif_txroom(struct uart_port *port) { @@ -521,7 +536,7 @@ static void sci_transmit_chars(struct uart_port *port) static inline void sci_receive_chars(struct uart_port *port) { struct sci_port *sci_port = (struct sci_port *)port; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; int i, count, copied = 0; unsigned short status; unsigned char flag; @@ -642,7 +657,7 @@ static inline int sci_handle_errors(struct uart_port *port) { int copied = 0; unsigned short status = sci_in(port, SCxSR); - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; if (status & SCxSR_ORER(port)) { /* overrun error */ @@ -692,7 +707,7 @@ static inline int sci_handle_breaks(struct uart_port *port) { int copied = 0; unsigned short status = sci_in(port, SCxSR); - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; struct sci_port *s = &sci_ports[port->line]; if (uart_handle_break(port)) @@ -762,7 +777,7 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr) } else { #if defined(SCIF_ORER) if((sci_in(port, SCLSR) & SCIF_ORER) != 0) { - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; sci_out(port, SCLSR, 0); tty_insert_flip_char(tty, 0, TTY_OVERRUN); diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index eb84833233f..8a0749e34ca 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -123,8 +123,9 @@ #elif defined(CONFIG_CPU_SUBTYPE_SH7763) # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ # define SCSPTR1 0xffe08024 /* 16 bit SCIF */ +# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */ # define SCIF_ORER 0x0001 /* overrun error bit */ -# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7770) # define SCSPTR0 0xff923020 /* 16 bit SCIF */ @@ -188,6 +189,7 @@ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ defined(CONFIG_CPU_SUBTYPE_SH7751) || \ defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ + defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) || \ defined(CONFIG_CPU_SUBTYPE_SHX3) @@ -225,14 +227,21 @@ #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) -#define SCIF_ORER 0x0200 -#define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) -#define SCIF_RFDC_MASK 0x007f -#define SCIF_TXROOM_MAX 64 +# define SCIF_ORER 0x0200 +# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) +# define SCIF_RFDC_MASK 0x007f +# define SCIF_TXROOM_MAX 64 +#elif defined(CONFIG_CPU_SUBTYPE_SH7763) +# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK ) +# define SCIF_RFDC_MASK 0x007f +# define SCIF_TXROOM_MAX 64 +/* SH7763 SCIF2 support */ +# define SCIF2_RFDC_MASK 0x001f +# define SCIF2_TXROOM_MAX 16 #else -#define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) -#define SCIF_RFDC_MASK 0x001f -#define SCIF_TXROOM_MAX 16 +# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) +# define SCIF_RFDC_MASK 0x001f +# define SCIF_TXROOM_MAX 16 #endif #if defined(SCI_ONLY) @@ -442,7 +451,6 @@ SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8) SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8) SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \ - defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) @@ -450,6 +458,14 @@ SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) SCIF_FNS(SCLSR, 0, 0, 0x28, 16) +#elif defined(CONFIG_CPU_SUBTYPE_SH7763) +SCIF_FNS(SCFDR, 0, 0, 0x1C, 16) +SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16) +SCIF_FNS(SCLSR2, 0, 0, 0x24, 16) +SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) +SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) +SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) +SCIF_FNS(SCLSR, 0, 0, 0x28, 16) #else SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) #if defined(CONFIG_CPU_SUBTYPE_SH7722) @@ -652,6 +668,9 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe08000) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xffe10000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */ + return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7770) @@ -764,8 +783,7 @@ static inline int sci_rxd_in(struct uart_port *port) * -- Mitch Davis - 15 Jul 2000 */ -#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) || \ +#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 019da2e05f0..b73e3c0056c 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -471,7 +471,7 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags) if (port->sc_port.info) { /* The serial_core stuffs are initilized, use them */ - tty = port->sc_port.info->tty; + tty = port->sc_port.info->port.tty; } else { /* Not registered yet - can't pass to tty layer. */ diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 2847336742d..e41766d0803 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -17,11 +17,11 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/of_device.h> #include <asm/hypervisor.h> #include <asm/spitfire.h> #include <asm/prom.h> -#include <asm/of_device.h> #include <asm/irq.h> #if defined(CONFIG_MAGIC_SYSRQ) @@ -185,7 +185,7 @@ static struct tty_struct *receive_chars(struct uart_port *port) struct tty_struct *tty = NULL; if (port->info != NULL) /* Unopened serial console */ - tty = port->info->tty; + tty = port->info->port.tty; if (sunhv_ops->receive_chars(port, tty)) sun_do_break(); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 9ff5b38f3be..29b4458abf7 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -32,11 +32,11 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/of_device.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/prom.h> -#include <asm/of_device.h> #if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -118,7 +118,7 @@ receive_chars(struct uart_sunsab_port *up, int i; if (up->port.info != NULL) /* Unopened serial console */ - tty = up->port.info->tty; + tty = up->port.info->port.tty; /* Read number of BYTES (Character + Status) available. */ if (stat->sreg.isr0 & SAB82532_ISR0_RPF) { diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 03806a93520..a378464f929 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1,4 +1,4 @@ -/* $Id: su.c,v 1.55 2002/01/08 16:00:16 davem Exp $ +/* * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -35,11 +35,11 @@ #include <linux/serial_reg.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/of_device.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/prom.h> -#include <asm/of_device.h> #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -311,7 +311,7 @@ static void sunsu_enable_ms(struct uart_port *port) static struct tty_struct * receive_chars(struct uart_sunsu_port *up, unsigned char *status) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->port.tty; unsigned char ch, flag; int max_count = 256; int saw_console_brk = 0; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 7e9fa5ef0eb..3cb4c8aee13 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -32,11 +32,11 @@ #include <linux/serio.h> #endif #include <linux/init.h> +#include <linux/of_device.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/prom.h> -#include <asm/of_device.h> #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -329,8 +329,8 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, tty = NULL; if (up->port.info != NULL && /* Unopened serial console */ - up->port.info->tty != NULL) /* Keyboard || mouse */ - tty = up->port.info->tty; + up->port.info->port.tty != NULL) /* Keyboard || mouse */ + tty = up->port.info->port.tty; for (;;) { diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index b51c24245be..6a3f8fb0c9d 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -75,7 +75,7 @@ static struct uart_port ulite_ports[ULITE_NR_UARTS]; static int ulite_receive(struct uart_port *port, int stat) { - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; unsigned char ch = 0; char flag = TTY_NORMAL; @@ -162,7 +162,7 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) busy |= ulite_transmit(port, stat); } while (busy); - tty_flip_buffer_push(port->info->tty); + tty_flip_buffer_push(port->info->port.tty); return IRQ_HANDLED; } diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 566a8b42e05..5c5d18dcb6a 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c @@ -466,7 +466,7 @@ static void qe_uart_int_rx(struct uart_qe_port *qe_port) int i; unsigned char ch, *cp; struct uart_port *port = &qe_port->port; - struct tty_struct *tty = port->info->tty; + struct tty_struct *tty = port->info->port.tty; struct qe_bd *bdp; u16 status; unsigned int flg; diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c deleted file mode 100644 index dd98aca6ed0..00000000000 --- a/drivers/serial/v850e_uart.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * drivers/serial/v850e_uart.c -- Serial I/O using V850E on-chip UART or UARTB - * - * Copyright (C) 2001,02,03 NEC Electronics Corporation - * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. - * - * Written by Miles Bader <miles@gnu.org> - */ - -/* This driver supports both the original V850E UART interface (called - merely `UART' in the docs) and the newer `UARTB' interface, which is - roughly a superset of the first one. The selection is made at - configure time -- if CONFIG_V850E_UARTB is defined, then UARTB is - presumed, otherwise the old UART -- as these are on-CPU UARTS, a system - can never have both. - - The UARTB interface also has a 16-entry FIFO mode, which is not - yet supported by this driver. */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/console.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial.h> -#include <linux/serial_core.h> - -#include <asm/v850e_uart.h> - -/* Initial UART state. This may be overridden by machine-dependent headers. */ -#ifndef V850E_UART_INIT_BAUD -#define V850E_UART_INIT_BAUD 115200 -#endif -#ifndef V850E_UART_INIT_CFLAGS -#define V850E_UART_INIT_CFLAGS (B115200 | CS8 | CREAD) -#endif - -/* A string used for prefixing printed descriptions; since the same UART - macro is actually used on other chips than the V850E. This must be a - constant string. */ -#ifndef V850E_UART_CHIP_NAME -#define V850E_UART_CHIP_NAME "V850E" -#endif - -#define V850E_UART_MINOR_BASE 64 /* First tty minor number */ - - -/* Low-level UART functions. */ - -/* Configure and turn on uart channel CHAN, using the termios `control - modes' bits in CFLAGS, and a baud-rate of BAUD. */ -void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud) -{ - int flags; - v850e_uart_speed_t old_speed; - v850e_uart_config_t old_config; - v850e_uart_speed_t new_speed = v850e_uart_calc_speed (baud); - v850e_uart_config_t new_config = v850e_uart_calc_config (cflags); - - /* Disable interrupts while we're twiddling the hardware. */ - local_irq_save (flags); - -#ifdef V850E_UART_PRE_CONFIGURE - V850E_UART_PRE_CONFIGURE (chan, cflags, baud); -#endif - - old_config = V850E_UART_CONFIG (chan); - old_speed = v850e_uart_speed (chan); - - if (! v850e_uart_speed_eq (old_speed, new_speed)) { - /* The baud rate has changed. First, disable the UART. */ - V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_FINI; - old_config = 0; /* Force the uart to be re-initialized. */ - - /* Reprogram the baud-rate generator. */ - v850e_uart_set_speed (chan, new_speed); - } - - if (! (old_config & V850E_UART_CONFIG_ENABLED)) { - /* If we are using the uart for the first time, start by - enabling it, which must be done before turning on any - other bits. */ - V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_INIT; - /* See the initial state. */ - old_config = V850E_UART_CONFIG (chan); - } - - if (new_config != old_config) { - /* Which of the TXE/RXE bits we'll temporarily turn off - before changing other control bits. */ - unsigned temp_disable = 0; - /* Which of the TXE/RXE bits will be enabled. */ - unsigned enable = 0; - unsigned changed_bits = new_config ^ old_config; - - /* Which of RX/TX will be enabled in the new configuration. */ - if (new_config & V850E_UART_CONFIG_RX_BITS) - enable |= (new_config & V850E_UART_CONFIG_RX_ENABLE); - if (new_config & V850E_UART_CONFIG_TX_BITS) - enable |= (new_config & V850E_UART_CONFIG_TX_ENABLE); - - /* Figure out which of RX/TX needs to be disabled; note - that this will only happen if they're not already - disabled. */ - if (changed_bits & V850E_UART_CONFIG_RX_BITS) - temp_disable - |= (old_config & V850E_UART_CONFIG_RX_ENABLE); - if (changed_bits & V850E_UART_CONFIG_TX_BITS) - temp_disable - |= (old_config & V850E_UART_CONFIG_TX_ENABLE); - - /* We have to turn off RX and/or TX mode before changing - any associated control bits. */ - if (temp_disable) - V850E_UART_CONFIG (chan) = old_config & ~temp_disable; - - /* Write the new control bits, while RX/TX are disabled. */ - if (changed_bits & ~enable) - V850E_UART_CONFIG (chan) = new_config & ~enable; - - v850e_uart_config_delay (new_config, new_speed); - - /* Write the final version, with enable bits turned on. */ - V850E_UART_CONFIG (chan) = new_config; - } - - local_irq_restore (flags); -} - - -/* Low-level console. */ - -#ifdef CONFIG_V850E_UART_CONSOLE - -static void v850e_uart_cons_write (struct console *co, - const char *s, unsigned count) -{ - if (count > 0) { - unsigned chan = co->index; - unsigned irq = V850E_UART_TX_IRQ (chan); - int irq_was_enabled, irq_was_pending, flags; - - /* We don't want to get `transmission completed' - interrupts, since we're busy-waiting, so we disable them - while sending (we don't disable interrupts entirely - because sending over a serial line is really slow). We - save the status of the tx interrupt and restore it when - we're done so that using printk doesn't interfere with - normal serial transmission (other than interleaving the - output, of course!). This should work correctly even if - this function is interrupted and the interrupt printks - something. */ - - /* Disable interrupts while fiddling with tx interrupt. */ - local_irq_save (flags); - /* Get current tx interrupt status. */ - irq_was_enabled = v850e_intc_irq_enabled (irq); - irq_was_pending = v850e_intc_irq_pending (irq); - /* Disable tx interrupt if necessary. */ - if (irq_was_enabled) - v850e_intc_disable_irq (irq); - /* Turn interrupts back on. */ - local_irq_restore (flags); - - /* Send characters. */ - while (count > 0) { - int ch = *s++; - - if (ch == '\n') { - /* We don't have the benefit of a tty - driver, so translate NL into CR LF. */ - v850e_uart_wait_for_xmit_ok (chan); - v850e_uart_putc (chan, '\r'); - } - - v850e_uart_wait_for_xmit_ok (chan); - v850e_uart_putc (chan, ch); - - count--; - } - - /* Restore saved tx interrupt status. */ - if (irq_was_enabled) { - /* Wait for the last character we sent to be - completely transmitted (as we'll get an - interrupt interrupt at that point). */ - v850e_uart_wait_for_xmit_done (chan); - /* Clear pending interrupts received due - to our transmission, unless there was already - one pending, in which case we want the - handler to be called. */ - if (! irq_was_pending) - v850e_intc_clear_pending_irq (irq); - /* ... and then turn back on handling. */ - v850e_intc_enable_irq (irq); - } - } -} - -extern struct uart_driver v850e_uart_driver; -static struct console v850e_uart_cons = -{ - .name = "ttyS", - .write = v850e_uart_cons_write, - .device = uart_console_device, - .flags = CON_PRINTBUFFER, - .cflag = V850E_UART_INIT_CFLAGS, - .index = -1, - .data = &v850e_uart_driver, -}; - -void v850e_uart_cons_init (unsigned chan) -{ - v850e_uart_configure (chan, V850E_UART_INIT_CFLAGS, - V850E_UART_INIT_BAUD); - v850e_uart_cons.index = chan; - register_console (&v850e_uart_cons); - printk ("Console: %s on-chip UART channel %d\n", - V850E_UART_CHIP_NAME, chan); -} - -/* This is what the init code actually calls. */ -static int v850e_uart_console_init (void) -{ - v850e_uart_cons_init (V850E_UART_CONSOLE_CHANNEL); - return 0; -} -console_initcall(v850e_uart_console_init); - -#define V850E_UART_CONSOLE &v850e_uart_cons - -#else /* !CONFIG_V850E_UART_CONSOLE */ -#define V850E_UART_CONSOLE 0 -#endif /* CONFIG_V850E_UART_CONSOLE */ - -/* TX/RX interrupt handlers. */ - -static void v850e_uart_stop_tx (struct uart_port *port); - -void v850e_uart_tx (struct uart_port *port) -{ - struct circ_buf *xmit = &port->info->xmit; - int stopped = uart_tx_stopped (port); - - if (v850e_uart_xmit_ok (port->line)) { - int tx_ch; - - if (port->x_char) { - tx_ch = port->x_char; - port->x_char = 0; - } else if (!uart_circ_empty (xmit) && !stopped) { - tx_ch = xmit->buf[xmit->tail]; - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - } else - goto no_xmit; - - v850e_uart_putc (port->line, tx_ch); - port->icount.tx++; - - if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) - uart_write_wakeup (port); - } - - no_xmit: - if (uart_circ_empty (xmit) || stopped) - v850e_uart_stop_tx (port, stopped); -} - -static irqreturn_t v850e_uart_tx_irq(int irq, void *data) -{ - struct uart_port *port = data; - v850e_uart_tx (port); - return IRQ_HANDLED; -} - -static irqreturn_t v850e_uart_rx_irq(int irq, void *data) -{ - struct uart_port *port = data; - unsigned ch_stat = TTY_NORMAL; - unsigned ch = v850e_uart_getc (port->line); - unsigned err = v850e_uart_err (port->line); - - if (err) { - if (err & V850E_UART_ERR_OVERRUN) { - ch_stat = TTY_OVERRUN; - port->icount.overrun++; - } else if (err & V850E_UART_ERR_FRAME) { - ch_stat = TTY_FRAME; - port->icount.frame++; - } else if (err & V850E_UART_ERR_PARITY) { - ch_stat = TTY_PARITY; - port->icount.parity++; - } - } - - port->icount.rx++; - - tty_insert_flip_char (port->info->tty, ch, ch_stat); - tty_schedule_flip (port->info->tty); - - return IRQ_HANDLED; -} - - -/* Control functions for the serial framework. */ - -static void v850e_uart_nop (struct uart_port *port) { } -static int v850e_uart_success (struct uart_port *port) { return 0; } - -static unsigned v850e_uart_tx_empty (struct uart_port *port) -{ - return TIOCSER_TEMT; /* Can't detect. */ -} - -static void v850e_uart_set_mctrl (struct uart_port *port, unsigned mctrl) -{ -#ifdef V850E_UART_SET_RTS - V850E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS)); -#endif -} - -static unsigned v850e_uart_get_mctrl (struct uart_port *port) -{ - /* We don't support DCD or DSR, so consider them permanently active. */ - int mctrl = TIOCM_CAR | TIOCM_DSR; - - /* We may support CTS. */ -#ifdef V850E_UART_CTS - mctrl |= V850E_UART_CTS(port->line) ? TIOCM_CTS : 0; -#else - mctrl |= TIOCM_CTS; -#endif - - return mctrl; -} - -static void v850e_uart_start_tx (struct uart_port *port) -{ - v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); - v850e_uart_tx (port); - v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line)); -} - -static void v850e_uart_stop_tx (struct uart_port *port) -{ - v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); -} - -static void v850e_uart_start_rx (struct uart_port *port) -{ - v850e_intc_enable_irq (V850E_UART_RX_IRQ (port->line)); -} - -static void v850e_uart_stop_rx (struct uart_port *port) -{ - v850e_intc_disable_irq (V850E_UART_RX_IRQ (port->line)); -} - -static void v850e_uart_break_ctl (struct uart_port *port, int break_ctl) -{ - /* Umm, do this later. */ -} - -static int v850e_uart_startup (struct uart_port *port) -{ - int err; - - /* Alloc RX irq. */ - err = request_irq (V850E_UART_RX_IRQ (port->line), v850e_uart_rx_irq, - IRQF_DISABLED, "v850e_uart", port); - if (err) - return err; - - /* Alloc TX irq. */ - err = request_irq (V850E_UART_TX_IRQ (port->line), v850e_uart_tx_irq, - IRQF_DISABLED, "v850e_uart", port); - if (err) { - free_irq (V850E_UART_RX_IRQ (port->line), port); - return err; - } - - v850e_uart_start_rx (port); - - return 0; -} - -static void v850e_uart_shutdown (struct uart_port *port) -{ - /* Disable port interrupts. */ - free_irq (V850E_UART_TX_IRQ (port->line), port); - free_irq (V850E_UART_RX_IRQ (port->line), port); - - /* Turn off xmit/recv enable bits. */ - V850E_UART_CONFIG (port->line) - &= ~(V850E_UART_CONFIG_TX_ENABLE - | V850E_UART_CONFIG_RX_ENABLE); - /* Then reset the channel. */ - V850E_UART_CONFIG (port->line) = 0; -} - -static void -v850e_uart_set_termios (struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ - unsigned cflags = termios->c_cflag; - - /* Restrict flags to legal values. */ - if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8) - /* The new value of CSIZE is invalid, use the old value. */ - cflags = (cflags & ~CSIZE) - | (old ? (old->c_cflag & CSIZE) : CS8); - - termios->c_cflag = cflags; - - v850e_uart_configure (port->line, cflags, - uart_get_baud_rate (port, termios, old, - v850e_uart_min_baud(), - v850e_uart_max_baud())); -} - -static const char *v850e_uart_type (struct uart_port *port) -{ - return port->type == PORT_V850E_UART ? "v850e_uart" : 0; -} - -static void v850e_uart_config_port (struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) - port->type = PORT_V850E_UART; -} - -static int -v850e_uart_verify_port (struct uart_port *port, struct serial_struct *ser) -{ - if (ser->type != PORT_UNKNOWN && ser->type != PORT_V850E_UART) - return -EINVAL; - if (ser->irq != V850E_UART_TX_IRQ (port->line)) - return -EINVAL; - return 0; -} - -static struct uart_ops v850e_uart_ops = { - .tx_empty = v850e_uart_tx_empty, - .get_mctrl = v850e_uart_get_mctrl, - .set_mctrl = v850e_uart_set_mctrl, - .start_tx = v850e_uart_start_tx, - .stop_tx = v850e_uart_stop_tx, - .stop_rx = v850e_uart_stop_rx, - .enable_ms = v850e_uart_nop, - .break_ctl = v850e_uart_break_ctl, - .startup = v850e_uart_startup, - .shutdown = v850e_uart_shutdown, - .set_termios = v850e_uart_set_termios, - .type = v850e_uart_type, - .release_port = v850e_uart_nop, - .request_port = v850e_uart_success, - .config_port = v850e_uart_config_port, - .verify_port = v850e_uart_verify_port, -}; - -/* Initialization and cleanup. */ - -static struct uart_driver v850e_uart_driver = { - .owner = THIS_MODULE, - .driver_name = "v850e_uart", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = V850E_UART_MINOR_BASE, - .nr = V850E_UART_NUM_CHANNELS, - .cons = V850E_UART_CONSOLE, -}; - - -static struct uart_port v850e_uart_ports[V850E_UART_NUM_CHANNELS]; - -static int __init v850e_uart_init (void) -{ - int rval; - - printk (KERN_INFO "%s on-chip UART\n", V850E_UART_CHIP_NAME); - - rval = uart_register_driver (&v850e_uart_driver); - if (rval == 0) { - unsigned chan; - - for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) { - struct uart_port *port = &v850e_uart_ports[chan]; - - memset (port, 0, sizeof *port); - - port->ops = &v850e_uart_ops; - port->line = chan; - port->iotype = UPIO_MEM; - port->flags = UPF_BOOT_AUTOCONF; - - /* We actually use multiple IRQs, but the serial - framework seems to mainly use this for - informational purposes anyway. Here we use the TX - irq. */ - port->irq = V850E_UART_TX_IRQ (chan); - - /* The serial framework doesn't really use these - membase/mapbase fields for anything useful, but - it requires that they be something non-zero to - consider the port `valid', and also uses them - for informational purposes. */ - port->membase = (void *)V850E_UART_BASE_ADDR (chan); - port->mapbase = V850E_UART_BASE_ADDR (chan); - - /* The framework insists on knowing the uart's master - clock freq, though it doesn't seem to do anything - useful for us with it. We must make it at least - higher than (the maximum baud rate * 16), otherwise - the framework will puke during its internal - calculations, and force the baud rate to be 9600. - To be accurate though, just repeat the calculation - we use when actually setting the speed. */ - port->uartclk = v850e_uart_max_clock() * 16; - - uart_add_one_port (&v850e_uart_driver, port); - } - } - - return rval; -} - -static void __exit v850e_uart_exit (void) -{ - unsigned chan; - - for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) - uart_remove_one_port (&v850e_uart_driver, - &v850e_uart_ports[chan]); - - uart_unregister_driver (&v850e_uart_driver); -} - -module_init (v850e_uart_init); -module_exit (v850e_uart_exit); - -MODULE_AUTHOR ("Miles Bader"); -MODULE_DESCRIPTION ("NEC " V850E_UART_CHIP_NAME " on-chip UART"); -MODULE_LICENSE ("GPL"); diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index bb6ce6bba32..0573f3b5175 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -318,7 +318,7 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status) char flag; int max_count = RX_MAX_COUNT; - tty = port->info->tty; + tty = port->info->port.tty; lsr = *status; do { diff --git a/drivers/serial/zs.c b/drivers/serial/zs.c index 65f1294fd27..9e6a873f820 100644 --- a/drivers/serial/zs.c +++ b/drivers/serial/zs.c @@ -602,7 +602,7 @@ static void zs_receive_chars(struct zs_port *zport) uart_insert_char(uport, status, Rx_OVR, ch, flag); } - tty_flip_buffer_push(uport->info->tty); + tty_flip_buffer_push(uport->info->port.tty); } static void zs_raw_transmit_chars(struct zs_port *zport) @@ -787,7 +787,6 @@ static int zs_startup(struct uart_port *uport) zport->regs[1] &= ~RxINT_MASK; zport->regs[1] |= RxINT_ALL | TxINT_ENAB | EXT_INT_ENAB; zport->regs[3] |= RxENABLE; - zport->regs[5] |= TxENAB; zport->regs[15] |= BRKIE; write_zsreg(zport, R1, zport->regs[1]); write_zsreg(zport, R3, zport->regs[3]); @@ -814,7 +813,6 @@ static void zs_shutdown(struct uart_port *uport) spin_lock_irqsave(&scc->zlock, flags); - zport->regs[5] &= ~TxENAB; zport->regs[3] &= ~RxENABLE; write_zsreg(zport, R5, zport->regs[5]); write_zsreg(zport, R3, zport->regs[3]); @@ -959,6 +957,23 @@ static void zs_set_termios(struct uart_port *uport, struct ktermios *termios, spin_unlock_irqrestore(&scc->zlock, flags); } +/* + * Hack alert! + * Required solely so that the initial PROM-based console + * works undisturbed in parallel with this one. + */ +static void zs_pm(struct uart_port *uport, unsigned int state, + unsigned int oldstate) +{ + struct zs_port *zport = to_zport(uport); + + if (state < 3) + zport->regs[5] |= TxENAB; + else + zport->regs[5] &= ~TxENAB; + write_zsreg(zport, R5, zport->regs[5]); +} + static const char *zs_type(struct uart_port *uport) { @@ -1041,6 +1056,7 @@ static struct uart_ops zs_ops = { .startup = zs_startup, .shutdown = zs_shutdown, .set_termios = zs_set_termios, + .pm = zs_pm, .type = zs_type, .release_port = zs_release_port, .request_port = zs_request_port, @@ -1190,6 +1206,7 @@ static int __init zs_console_setup(struct console *co, char *options) return ret; zs_reset(zport); + zs_pm(uport, 0, -1); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); |