diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/8250.c | 10 | ||||
-rw-r--r-- | drivers/serial/8250_pnp.c | 3 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 3 | ||||
-rw-r--r-- | drivers/serial/atmel_serial.c | 3 | ||||
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_cpm2.c | 2 | ||||
-rw-r--r-- | drivers/serial/dz.c | 7 | ||||
-rw-r--r-- | drivers/serial/icom.c | 9 | ||||
-rw-r--r-- | drivers/serial/icom.h | 1 | ||||
-rw-r--r-- | drivers/serial/imx.c | 14 | ||||
-rw-r--r-- | drivers/serial/mcfserial.c | 44 | ||||
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 4 | ||||
-rw-r--r-- | drivers/serial/mux.c | 167 | ||||
-rw-r--r-- | drivers/serial/pmac_zilog.c | 4 | ||||
-rw-r--r-- | drivers/serial/serial_cs.c | 5 | ||||
-rw-r--r-- | drivers/serial/serial_txx9.c | 276 | ||||
-rw-r--r-- | drivers/serial/sh-sci.c | 11 | ||||
-rw-r--r-- | drivers/serial/sn_console.c | 52 | ||||
-rw-r--r-- | drivers/serial/sunsu.c | 4 |
18 files changed, 403 insertions, 216 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 98ec8618532..90621c3312b 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1196,7 +1196,7 @@ static void serial8250_enable_ms(struct uart_port *port) } static void -receive_chars(struct uart_8250_port *up, int *status) +receive_chars(struct uart_8250_port *up, unsigned int *status) { struct tty_struct *tty = up->port.info->tty; unsigned char ch, lsr = *status; @@ -1310,7 +1310,8 @@ static unsigned int check_modem_status(struct uart_8250_port *up) { unsigned int status = serial_in(up, UART_MSR); - if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI) { + if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && + up->port.info != NULL) { if (status & UART_MSR_TERI) up->port.icount.rng++; if (status & UART_MSR_DDSR) @@ -1333,8 +1334,9 @@ static inline void serial8250_handle_port(struct uart_8250_port *up) { unsigned int status; + unsigned long flags; - spin_lock(&up->port.lock); + spin_lock_irqsave(&up->port.lock, flags); status = serial_inp(up, UART_LSR); @@ -1346,7 +1348,7 @@ serial8250_handle_port(struct uart_8250_port *up) if (status & UART_LSR_THRE) transmit_chars(up); - spin_unlock(&up->port.lock); + spin_unlock_irqrestore(&up->port.lock, flags); } /* diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index cde5db44abf..301c8c0be9d 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -340,6 +340,9 @@ static const struct pnp_device_id pnp_dev_table[] = { { "FUJ02B8", 0 }, { "FUJ02B9", 0 }, { "FUJ02BC", 0 }, + /* Fujitsu Wacom Tablet PC devices */ + { "FUJ02E5", 0 }, + { "FUJ02E6", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ { "WCI0003", 0 }, /* Unkown PnP modems */ diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index e8dd71df916..ad9f321968e 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -262,7 +262,8 @@ config SERIAL_AMBA_PL010 select SERIAL_CORE help This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have - an Integrator/AP or Integrator/PP2 platform, say Y or M here. + an Integrator/AP or Integrator/PP2 platform, or if you have a + Cirrus Logic EP93xx CPU, say Y or M here. If unsure, say N. diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index df45a7ac773..935f48fa501 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -33,12 +33,13 @@ #include <linux/sysrq.h> #include <linux/tty_flip.h> #include <linux/platform_device.h> +#include <linux/atmel_pdc.h> #include <asm/io.h> #include <asm/mach/serial_at91.h> #include <asm/arch/board.h> -#include <asm/arch/at91_pdc.h> + #ifdef CONFIG_ARM #include <asm/arch/cpu.h> #include <asm/arch/gpio.h> diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index 787a8f13467..fa455996ad8 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -285,7 +285,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo) int __init cpm_uart_init_portdesc(void) { #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2) - u32 addr; + u16 *addr; #endif pr_debug("CPM uart[-]:init portdesc\n"); diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 587d87b9eb3..d31721f2744 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -170,8 +170,7 @@ static void dz_enable_ms(struct uart_port *port) * This routine deals with inputs from any lines. * ------------------------------------------------------------ */ -static inline void dz_receive_chars(struct dz_port *dport_in, - struct pt_regs *regs) +static inline void dz_receive_chars(struct dz_port *dport_in) { struct dz_port *dport; struct tty_struct *tty = NULL; @@ -226,7 +225,7 @@ static inline void dz_receive_chars(struct dz_port *dport_in, break; } - if (uart_handle_sysrq_char(&dport->port, ch, regs)) + if (uart_handle_sysrq_char(&dport->port, ch)) continue; if ((status & dport->port.ignore_status_mask) == 0) { @@ -332,7 +331,7 @@ static irqreturn_t dz_interrupt(int irq, void *dev) status = dz_in(dport, DZ_CSR); if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) - dz_receive_chars(dport, regs); + dz_receive_chars(dport); if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) dz_transmit_chars(dport); diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 41431d0d551..246c5572667 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -164,7 +164,7 @@ static void free_port_memory(struct icom_port *icom_port) } } -static int __init get_port_memory(struct icom_port *icom_port) +static int __devinit get_port_memory(struct icom_port *icom_port) { int index; unsigned long stgAddr; @@ -1380,7 +1380,7 @@ static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *i 0x8024 + 2 - 2 * (icom_port->port - 2); } } -static int __init icom_load_ports(struct icom_adapter *icom_adapter) +static int __devinit icom_load_ports(struct icom_adapter *icom_adapter) { struct icom_port *icom_port; int port_num; @@ -1473,7 +1473,7 @@ static void icom_remove_adapter(struct icom_adapter *icom_adapter) } } - free_irq(icom_adapter->irq_number, (void *) icom_adapter); + free_irq(icom_adapter->pci_dev->irq, (void *) icom_adapter); iounmap(icom_adapter->base_addr); icom_free_adapter(icom_adapter); pci_release_regions(icom_adapter->pci_dev); @@ -1539,7 +1539,6 @@ static int __devinit icom_probe(struct pci_dev *dev, } icom_adapter->base_addr_pci = pci_resource_start(dev, 0); - icom_adapter->irq_number = dev->irq; icom_adapter->pci_dev = dev; icom_adapter->version = ent->driver_data; icom_adapter->subsystem_id = ent->subdevice; @@ -1570,7 +1569,7 @@ static int __devinit icom_probe(struct pci_dev *dev, icom_port = &icom_adapter->port_info[index]; if (icom_port->status == ICOM_PORT_ACTIVE) { - icom_port->uart_port.irq = icom_port->adapter->irq_number; + icom_port->uart_port.irq = icom_port->adapter->pci_dev->irq; icom_port->uart_port.type = PORT_ICOM; icom_port->uart_port.iotype = UPIO_MEM; icom_port->uart_port.membase = diff --git a/drivers/serial/icom.h b/drivers/serial/icom.h index 798f1ef2371..e8578d8cd35 100644 --- a/drivers/serial/icom.h +++ b/drivers/serial/icom.h @@ -258,7 +258,6 @@ struct icom_port { struct icom_adapter { void __iomem * base_addr; unsigned long base_addr_pci; - unsigned char irq_number; struct pci_dev *pci_dev; struct icom_port port_info[4]; int index; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index e216dcf2937..04cc88cc528 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -154,7 +154,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport) { struct circ_buf *xmit = &sport->port.info->xmit; - do { + while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) { /* send xmit->buf[xmit->tail] * out the port here */ URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail]; @@ -163,7 +163,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport) sport->port.icount.tx++; if (uart_circ_empty(xmit)) break; - } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)); + } if (uart_circ_empty(xmit)) imx_stop_tx(&sport->port); @@ -178,8 +178,7 @@ static void imx_start_tx(struct uart_port *port) UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN; - if(UTS((u32)sport->port.membase) & UTS_TXEMPTY) - imx_transmit_buffer(sport); + imx_transmit_buffer(sport); } static irqreturn_t imx_rtsint(int irq, void *dev_id) @@ -404,7 +403,8 @@ static int imx_startup(struct uart_port *port) if (retval) goto error_out2; retval = request_irq(sport->rtsirq, imx_rtsint, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + (sport->rtsirq < IMX_IRQS) ? 0 : + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, DRIVER_NAME, sport); if (retval) goto error_out3; @@ -678,7 +678,7 @@ static struct imx_port imx_ports[] = { .mapbase = IMX_UART1_BASE, /* FIXME */ .irq = UART1_MINT_RX, .uartclk = 16000000, - .fifosize = 8, + .fifosize = 32, .flags = UPF_BOOT_AUTOCONF, .ops = &imx_pops, .line = 0, @@ -694,7 +694,7 @@ static struct imx_port imx_ports[] = { .mapbase = IMX_UART2_BASE, /* FIXME */ .irq = UART2_MINT_RX, .uartclk = 16000000, - .fifosize = 8, + .fifosize = 32, .flags = UPF_BOOT_AUTOCONF, .ops = &imx_pops, .line = 1, diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 08430961a89..99af084c7ce 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -425,15 +425,13 @@ irqreturn_t mcfrs_interrupt(int irq, void *dev_id) * ------------------------------------------------------------------- */ -static void mcfrs_offintr(void *private) +static void mcfrs_offintr(struct work_struct *work) { - struct mcf_serial *info = (struct mcf_serial *) private; - struct tty_struct *tty; + struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue); + struct tty_struct *tty = info->tty; - tty = info->tty; - if (!tty) - return; - tty_wakeup(tty); + if (tty) + tty_wakeup(tty); } @@ -497,16 +495,13 @@ static void mcfrs_timer(void) * do_serial_hangup() -> tty->hangup() -> mcfrs_hangup() * */ -static void do_serial_hangup(void *private) +static void do_serial_hangup(struct work_struct *work) { - struct mcf_serial *info = (struct mcf_serial *) private; - struct tty_struct *tty; + struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue_hangup); + struct tty_struct *tty = info->tty; - tty = info->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); } static int startup(struct mcf_serial * info) @@ -857,7 +852,7 @@ static void mcfrs_throttle(struct tty_struct * tty) #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("throttle %s: %d....\n", _tty_name(tty, buf), + printk("throttle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif @@ -876,7 +871,7 @@ static void mcfrs_unthrottle(struct tty_struct * tty) #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("unthrottle %s: %d....\n", _tty_name(tty, buf), + printk("unthrottle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif @@ -1541,8 +1536,8 @@ static void mcfrs_irqinit(struct mcf_serial *info) * External Pin Mask Setting & Enable External Pin for Interface * mrcbis@aliceposta.it */ - unsigned short *serpin_enable_mask; - serpin_enable_mask = (MCF_IPSBAR + MCF_GPIO_PAR_UART); + u16 *serpin_enable_mask; + serpin_enable_mask = (u16 *) (MCF_IPSBAR + MCF_GPIO_PAR_UART); if (info->line == 0) *serpin_enable_mask |= UART0_ENABLE_MASK; else if (info->line == 1) @@ -1551,6 +1546,13 @@ static void mcfrs_irqinit(struct mcf_serial *info) *serpin_enable_mask |= UART2_ENABLE_MASK; } #endif +#if defined(CONFIG_M528x) + /* make sure PUAPAR is set for UART0 and UART1 */ + if (info->line < 2) { + volatile unsigned char *portp = (volatile unsigned char *) (MCF_MBAR + MCF5282_GPIO_PUAPAR); + *portp |= (0x03 << (info->line * 2)); + } +#endif #elif defined(CONFIG_M520x) volatile unsigned char *icrp, *uartp; volatile unsigned long *imrp; @@ -1783,8 +1785,8 @@ mcfrs_init(void) info->event = 0; info->count = 0; info->blocked_open = 0; - INIT_WORK(&info->tqueue, mcfrs_offintr, info); - INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + INIT_WORK(&info->tqueue, mcfrs_offintr); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 955bbd653e2..8d24cd52105 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -995,8 +995,10 @@ mpc52xx_uart_of_remove(struct of_device *op) struct uart_port *port = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); - if (port) + if (port) { uart_remove_one_port(&mpc52xx_uart_driver, port); + irq_dispose_mapping(port->irq); + } return 0; } diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index ccb8fa1800a..83211013deb 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -51,7 +51,11 @@ #define MUX_NR 256 static unsigned int port_cnt __read_mostly; -static struct uart_port mux_ports[MUX_NR]; +struct mux_port { + struct uart_port port; + int enabled; +}; +static struct mux_port mux_ports[MUX_NR]; static struct uart_driver mux_driver = { .owner = THIS_MODULE, @@ -66,7 +70,36 @@ static struct timer_list mux_timer; #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) #define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET) -#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8 + +/** + * get_mux_port_count - Get the number of available ports on the Mux. + * @dev: The parisc device. + * + * This function is used to determine the number of ports the Mux + * supports. The IODC data reports the number of ports the Mux + * can support, but there are cases where not all the Mux ports + * are connected. This function can override the IODC and + * return the true port count. + */ +static int __init get_mux_port_count(struct parisc_device *dev) +{ + int status; + u8 iodc_data[32]; + unsigned long bytecnt; + + /* If this is the built-in Mux for the K-Class (Eole CAP/MUX), + * we only need to allocate resources for 1 port since the + * other 7 ports are not connected. + */ + if(dev->id.hversion == 0x15) + return 1; + + status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); + BUG_ON(status != PDC_OK); + + /* Return the number of ports specified in the iodc data. */ + return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8; +} /** * mux_tx_empty - Check if the transmitter fifo is empty. @@ -250,7 +283,7 @@ static void mux_read(struct uart_port *port) */ static int mux_startup(struct uart_port *port) { - mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + mux_ports[port->line].enabled = 1; return 0; } @@ -262,6 +295,7 @@ static int mux_startup(struct uart_port *port) */ static void mux_shutdown(struct uart_port *port) { + mux_ports[port->line].enabled = 0; } /** @@ -319,7 +353,7 @@ static int mux_request_port(struct uart_port *port) * @port: Ptr to the uart_port. * @type: Bitmask of required configurations. * - * Perform any autoconfiguration steps for the port. This functino is + * Perform any autoconfiguration steps for the port. This function is * called if the UPF_BOOT_AUTOCONF flag is specified for the port. * [Note: This is required for now because of a bug in the Serial core. * rmk has already submitted a patch to linus, should be available for @@ -357,11 +391,11 @@ static void mux_poll(unsigned long unused) int i; for(i = 0; i < port_cnt; ++i) { - if(!mux_ports[i].info) + if(!mux_ports[i].enabled) continue; - mux_read(&mux_ports[i]); - mux_write(&mux_ports[i]); + mux_read(&mux_ports[i].port); + mux_write(&mux_ports[i].port); } mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); @@ -371,8 +405,17 @@ static void mux_poll(unsigned long unused) #ifdef CONFIG_SERIAL_MUX_CONSOLE static void mux_console_write(struct console *co, const char *s, unsigned count) { - while(count--) - pdc_iodc_putc(*s++); + /* Wait until the FIFO drains. */ + while(UART_GET_FIFO_CNT(&mux_ports[0].port)) + udelay(1); + + while(count--) { + if(*s == '\n') { + UART_PUT_CHAR(&mux_ports[0].port, '\r'); + } + UART_PUT_CHAR(&mux_ports[0].port, *s++); + } + } static int mux_console_setup(struct console *co, char *options) @@ -428,19 +471,14 @@ static struct uart_ops mux_pops = { */ static int __init mux_probe(struct parisc_device *dev) { - int i, status, ports; - u8 iodc_data[32]; - unsigned long bytecnt; - struct uart_port *port; + int i, status; - status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); - if(status != PDC_OK) { - printk(KERN_ERR "Serial mux: Unable to read IODC.\n"); - return 1; - } + int port_count = get_mux_port_count(dev); + printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count); - ports = GET_MUX_PORTS(iodc_data); - printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports); + dev_set_drvdata(&dev->dev, (void *)(long)port_count); + request_mem_region(dev->hpa.start + MUX_OFFSET, + port_count * MUX_LINE_OFFSET, "Mux"); if(!port_cnt) { mux_driver.cons = MUX_CONSOLE; @@ -450,13 +488,10 @@ static int __init mux_probe(struct parisc_device *dev) printk(KERN_ERR "Serial mux: Unable to register driver.\n"); return 1; } - - init_timer(&mux_timer); - mux_timer.function = mux_poll; } - for(i = 0; i < ports; ++i, ++port_cnt) { - port = &mux_ports[port_cnt]; + for(i = 0; i < port_count; ++i, ++port_cnt) { + struct uart_port *port = &mux_ports[port_cnt].port; port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); @@ -477,27 +512,73 @@ static int __init mux_probe(struct parisc_device *dev) */ port->timeout = HZ / 50; spin_lock_init(&port->lock); + status = uart_add_one_port(&mux_driver, port); BUG_ON(status); } -#ifdef CONFIG_SERIAL_MUX_CONSOLE - register_console(&mux_console); -#endif return 0; } +static int __devexit mux_remove(struct parisc_device *dev) +{ + int i, j; + int port_count = (long)dev_get_drvdata(&dev->dev); + + /* Find Port 0 for this card in the mux_ports list. */ + for(i = 0; i < port_cnt; ++i) { + if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) + break; + } + BUG_ON(i + port_count > port_cnt); + + /* Release the resources associated with each port on the device. */ + for(j = 0; j < port_count; ++j, ++i) { + struct uart_port *port = &mux_ports[i].port; + + uart_remove_one_port(&mux_driver, port); + if(port->membase) + iounmap(port->membase); + } + + release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET); + return 0; +} + +/* Hack. This idea was taken from the 8250_gsc.c on how to properly order + * the serial port detection in the proper order. The idea is we always + * want the builtin mux to be detected before addin mux cards, so we + * specifically probe for the builtin mux cards first. + * + * This table only contains the parisc_device_id of known builtin mux + * devices. All other mux cards will be detected by the generic mux_tbl. + */ +static struct parisc_device_id builtin_mux_tbl[] = { + { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */ + { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */ + { 0, } +}; + static struct parisc_device_id mux_tbl[] = { { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D }, { 0, } }; +MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl); MODULE_DEVICE_TABLE(parisc, mux_tbl); +static struct parisc_driver builtin_serial_mux_driver = { + .name = "builtin_serial_mux", + .id_table = builtin_mux_tbl, + .probe = mux_probe, + .remove = __devexit_p(mux_remove), +}; + static struct parisc_driver serial_mux_driver = { .name = "serial_mux", .id_table = mux_tbl, .probe = mux_probe, + .remove = __devexit_p(mux_remove), }; /** @@ -507,7 +588,21 @@ static struct parisc_driver serial_mux_driver = { */ static int __init mux_init(void) { - return register_parisc_driver(&serial_mux_driver); + register_parisc_driver(&builtin_serial_mux_driver); + register_parisc_driver(&serial_mux_driver); + + if(port_cnt > 0) { + /* Start the Mux timer */ + init_timer(&mux_timer); + mux_timer.function = mux_poll; + mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + +#ifdef CONFIG_SERIAL_MUX_CONSOLE + register_console(&mux_console); +#endif + } + + return 0; } /** @@ -517,14 +612,16 @@ static int __init mux_init(void) */ static void __exit mux_exit(void) { - int i; - - for (i = 0; i < port_cnt; i++) { - uart_remove_one_port(&mux_driver, &mux_ports[i]); - if (mux_ports[i].membase) - iounmap(mux_ports[i].membase); + /* Delete the Mux timer. */ + if(port_cnt > 0) { + del_timer(&mux_timer); +#ifdef CONFIG_SERIAL_MUX_CONSOLE + unregister_console(&mux_console); +#endif } + unregister_parisc_driver(&builtin_serial_mux_driver); + unregister_parisc_driver(&serial_mux_driver); uart_unregister_driver(&mux_driver); } diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 752ef07516b..be8d75721a8 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1467,7 +1467,8 @@ no_dma: if (ZS_IS_IRDA(uap)) uap->port_type = PMAC_SCC_IRDA; if (ZS_IS_INTMODEM(uap)) { - struct device_node* i2c_modem = find_devices("i2c-modem"); + struct device_node* i2c_modem = + of_find_node_by_name(NULL, "i2c-modem"); if (i2c_modem) { const char* mid = get_property(i2c_modem, "modem-id", NULL); @@ -1482,6 +1483,7 @@ no_dma: } printk(KERN_INFO "pmac_zilog: i2c-modem detected, id: %d\n", mid ? (*mid) : 0); + of_node_put(i2c_modem); } else { printk(KERN_INFO "pmac_zilog: serial modem detected\n"); } diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index c2f1012449d..6b76babc7fb 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -248,6 +248,10 @@ static const struct serial_quirk quirks[] = { .multi = 2, }, { .manfid = MANFID_QUATECH, + .prodid = PRODID_QUATECH_DUAL_RS232_G, + .multi = 2, + }, { + .manfid = MANFID_QUATECH, .prodid = PRODID_QUATECH_QUAD_RS232, .multi = 4, }, { @@ -891,6 +895,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a), PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab), PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f), + PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index f4440d32931..509ace7e688 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -38,6 +38,8 @@ * Fix some spin_locks. * Do not call uart_add_one_port for absent ports. * 1.07 Use CONFIG_SERIAL_TXX9_NR_UARTS. Cleanup. + * 1.08 Use platform_device. + * Fix and cleanup suspend/resume/initialization codes. */ #if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) @@ -50,7 +52,7 @@ #include <linux/console.h> #include <linux/sysrq.h> #include <linux/delay.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/pci.h> #include <linux/tty.h> #include <linux/tty_flip.h> @@ -60,7 +62,7 @@ #include <asm/io.h> -static char *serial_version = "1.07"; +static char *serial_version = "1.08"; static char *serial_name = "TX39/49 Serial driver"; #define PASS_LIMIT 256 @@ -94,12 +96,7 @@ static char *serial_name = "TX39/49 Serial driver"; struct uart_txx9_port { struct uart_port port; - - /* - * We provide a per-port pm hook. - */ - void (*pm)(struct uart_port *port, - unsigned int state, unsigned int old); + /* No additional info for now */ }; #define TXX9_REGION_SIZE 0x24 @@ -277,6 +274,31 @@ static void serial_txx9_enable_ms(struct uart_port *port) /* TXX9-SIO can not control DTR... */ } +static void serial_txx9_initialize(struct uart_port *port) +{ + struct uart_txx9_port *up = (struct uart_txx9_port *)port; + unsigned int tmout = 10000; + + sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST); + /* TX4925 BUG WORKAROUND. Accessing SIOC register + * immediately after soft reset causes bus error. */ + mmiowb(); + udelay(1); + while ((sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) && --tmout) + udelay(1); + /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */ + sio_set(up, TXX9_SIFCR, + TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1); + /* initial settings */ + sio_out(up, TXX9_SILCR, + TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT | + ((up->port.flags & UPF_TXX9_USE_SCLK) ? + TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG)); + sio_quot_set(up, uart_get_divisor(port, 9600)); + sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */); + sio_out(up, TXX9_SIDICR, 0); +} + static inline void receive_chars(struct uart_txx9_port *up, unsigned int *status) { @@ -657,9 +679,8 @@ static void serial_txx9_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - struct uart_txx9_port *up = (struct uart_txx9_port *)port; - if (up->pm) - up->pm(port, state, oldstate); + if (state == 0) + serial_txx9_initialize(port); } static int serial_txx9_request_resource(struct uart_txx9_port *up) @@ -732,7 +753,6 @@ static int serial_txx9_request_port(struct uart_port *port) static void serial_txx9_config_port(struct uart_port *port, int uflags) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; - unsigned long flags; int ret; /* @@ -749,30 +769,7 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags) if (up->port.line == up->port.cons->index) return; #endif - spin_lock_irqsave(&up->port.lock, flags); - /* - * Reset the UART. - */ - sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST); -#ifdef CONFIG_CPU_TX49XX - /* TX4925 BUG WORKAROUND. Accessing SIOC register - * immediately after soft reset causes bus error. */ - iob(); - udelay(1); -#endif - while (sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) - ; - /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */ - sio_set(up, TXX9_SIFCR, - TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1); - /* initial settings */ - sio_out(up, TXX9_SILCR, - TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT | - ((up->port.flags & UPF_TXX9_USE_SCLK) ? - TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG)); - sio_quot_set(up, uart_get_divisor(port, 9600)); - sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */); - spin_unlock_irqrestore(&up->port.lock, flags); + serial_txx9_initialize(port); } static int @@ -818,7 +815,8 @@ static struct uart_ops serial_txx9_pops = { static struct uart_txx9_port serial_txx9_ports[UART_NR]; -static void __init serial_txx9_register_ports(struct uart_driver *drv) +static void __init serial_txx9_register_ports(struct uart_driver *drv, + struct device *dev) { int i; @@ -827,6 +825,7 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv) up->port.line = i; up->port.ops = &serial_txx9_pops; + up->port.dev = dev; if (up->port.iobase || up->port.mapbase) uart_add_one_port(drv, &up->port); } @@ -898,7 +897,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) sio_out(up, TXX9_SIDICR, ier); } -static int serial_txx9_console_setup(struct console *co, char *options) +static int __init serial_txx9_console_setup(struct console *co, char *options) { struct uart_port *port; struct uart_txx9_port *up; @@ -919,17 +918,7 @@ static int serial_txx9_console_setup(struct console *co, char *options) if (!port->ops) return -ENODEV; - /* - * Disable UART interrupts, set DTR and RTS high - * and set speed. - */ - sio_out(up, TXX9_SIDICR, 0); - /* initial settings */ - sio_out(up, TXX9_SILCR, - TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT | - ((port->flags & UPF_TXX9_USE_SCLK) ? - TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG)); - sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */); + serial_txx9_initialize(&up->port); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -981,31 +970,6 @@ int __init early_serial_txx9_setup(struct uart_port *port) return 0; } -#ifdef ENABLE_SERIAL_TXX9_PCI -#ifdef CONFIG_PM -/** - * serial_txx9_suspend_port - suspend one serial port - * @line: serial line number - * - * Suspend one serial port. - */ -static void serial_txx9_suspend_port(int line) -{ - uart_suspend_port(&serial_txx9_reg, &serial_txx9_ports[line].port); -} - -/** - * serial_txx9_resume_port - resume one serial port - * @line: serial line number - * - * Resume one serial port. - */ -static void serial_txx9_resume_port(int line) -{ - uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port); -} -#endif - static DEFINE_MUTEX(serial_txx9_mutex); /** @@ -1028,8 +992,18 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) mutex_lock(&serial_txx9_mutex); for (i = 0; i < UART_NR; i++) { uart = &serial_txx9_ports[i]; - if (!(uart->port.iobase || uart->port.mapbase)) + if (uart_match_port(&uart->port, port)) { + uart_remove_one_port(&serial_txx9_reg, &uart->port); break; + } + } + if (i == UART_NR) { + /* Find unused port */ + for (i = 0; i < UART_NR; i++) { + uart = &serial_txx9_ports[i]; + if (!(uart->port.iobase || uart->port.mapbase)) + break; + } } if (i < UART_NR) { uart->port.iobase = port->iobase; @@ -1072,6 +1046,95 @@ static void __devexit serial_txx9_unregister_port(int line) } /* + * Register a set of serial devices attached to a platform device. + */ +static int __devinit serial_txx9_probe(struct platform_device *dev) +{ + struct uart_port *p = dev->dev.platform_data; + struct uart_port port; + int ret, i; + + memset(&port, 0, sizeof(struct uart_port)); + for (i = 0; p && p->uartclk != 0; p++, i++) { + port.iobase = p->iobase; + port.membase = p->membase; + port.irq = p->irq; + port.uartclk = p->uartclk; + port.iotype = p->iotype; + port.flags = p->flags; + port.mapbase = p->mapbase; + port.dev = &dev->dev; + ret = serial_txx9_register_port(&port); + if (ret < 0) { + dev_err(&dev->dev, "unable to register port at index %d " + "(IO%x MEM%lx IRQ%d): %d\n", i, + p->iobase, p->mapbase, p->irq, ret); + } + } + return 0; +} + +/* + * Remove serial ports registered against a platform device. + */ +static int __devexit serial_txx9_remove(struct platform_device *dev) +{ + int i; + + for (i = 0; i < UART_NR; i++) { + struct uart_txx9_port *up = &serial_txx9_ports[i]; + + if (up->port.dev == &dev->dev) + serial_txx9_unregister_port(i); + } + return 0; +} + +#ifdef CONFIG_PM +static int serial_txx9_suspend(struct platform_device *dev, pm_message_t state) +{ + int i; + + for (i = 0; i < UART_NR; i++) { + struct uart_txx9_port *up = &serial_txx9_ports[i]; + + if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) + uart_suspend_port(&serial_txx9_reg, &up->port); + } + + return 0; +} + +static int serial_txx9_resume(struct platform_device *dev) +{ + int i; + + for (i = 0; i < UART_NR; i++) { + struct uart_txx9_port *up = &serial_txx9_ports[i]; + + if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) + uart_resume_port(&serial_txx9_reg, &up->port); + } + + return 0; +} +#endif + +static struct platform_driver serial_txx9_plat_driver = { + .probe = serial_txx9_probe, + .remove = __devexit_p(serial_txx9_remove), +#ifdef CONFIG_PM + .suspend = serial_txx9_suspend, + .resume = serial_txx9_resume, +#endif + .driver = { + .name = "serial_txx9", + .owner = THIS_MODULE, + }, +}; + +#ifdef ENABLE_SERIAL_TXX9_PCI +/* * Probe one serial board. Unfortunately, there is no rhyme nor reason * to the arrangement of serial ports on a PCI card. */ @@ -1097,20 +1160,22 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent) line = serial_txx9_register_port(&port); if (line < 0) { printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line); + pci_disable_device(dev); + return line; } - pci_set_drvdata(dev, (void *)(long)line); + pci_set_drvdata(dev, &serial_txx9_ports[line]); return 0; } static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev) { - int line = (int)(long)pci_get_drvdata(dev); + struct uart_txx9_port *up = pci_get_drvdata(dev); pci_set_drvdata(dev, NULL); - if (line) { - serial_txx9_unregister_port(line); + if (up) { + serial_txx9_unregister_port(up->port.line); pci_disable_device(dev); } } @@ -1118,10 +1183,10 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev) #ifdef CONFIG_PM static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state) { - int line = (int)(long)pci_get_drvdata(dev); + struct uart_txx9_port *up = pci_get_drvdata(dev); - if (line) - serial_txx9_suspend_port(line); + if (up) + uart_suspend_port(&serial_txx9_reg, &up->port); pci_save_state(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); return 0; @@ -1129,15 +1194,12 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state) static int pciserial_txx9_resume_one(struct pci_dev *dev) { - int line = (int)(long)pci_get_drvdata(dev); + struct uart_txx9_port *up = pci_get_drvdata(dev); pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); - - if (line) { - pci_enable_device(dev); - serial_txx9_resume_port(line); - } + if (up) + uart_resume_port(&serial_txx9_reg, &up->port); return 0; } #endif @@ -1161,6 +1223,8 @@ static struct pci_driver serial_txx9_pci_driver = { MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl); #endif /* ENABLE_SERIAL_TXX9_PCI */ +static struct platform_device *serial_txx9_plat_devs; + static int __init serial_txx9_init(void) { int ret; @@ -1168,13 +1232,39 @@ static int __init serial_txx9_init(void) printk(KERN_INFO "%s version %s\n", serial_name, serial_version); ret = uart_register_driver(&serial_txx9_reg); - if (ret >= 0) { - serial_txx9_register_ports(&serial_txx9_reg); + if (ret) + goto out; + + serial_txx9_plat_devs = platform_device_alloc("serial_txx9", -1); + if (!serial_txx9_plat_devs) { + ret = -ENOMEM; + goto unreg_uart_drv; + } + + ret = platform_device_add(serial_txx9_plat_devs); + if (ret) + goto put_dev; + + serial_txx9_register_ports(&serial_txx9_reg, + &serial_txx9_plat_devs->dev); + + ret = platform_driver_register(&serial_txx9_plat_driver); + if (ret) + goto del_dev; #ifdef ENABLE_SERIAL_TXX9_PCI - ret = pci_register_driver(&serial_txx9_pci_driver); + ret = pci_register_driver(&serial_txx9_pci_driver); #endif - } + if (ret == 0) + goto out; + + del_dev: + platform_device_del(serial_txx9_plat_devs); + put_dev: + platform_device_put(serial_txx9_plat_devs); + unreg_uart_drv: + uart_unregister_driver(&serial_txx9_reg); + out: return ret; } @@ -1185,6 +1275,8 @@ static void __exit serial_txx9_exit(void) #ifdef ENABLE_SERIAL_TXX9_PCI pci_unregister_driver(&serial_txx9_pci_driver); #endif + platform_driver_unregister(&serial_txx9_plat_driver); + platform_device_unregister(serial_txx9_plat_devs); for (i = 0; i < UART_NR; i++) { struct uart_txx9_port *up = &serial_txx9_ports[i]; if (up->port.iobase || up->port.mapbase) diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index c53b69610a5..46c40bbc4bc 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -17,6 +17,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif #undef DEBUG @@ -49,11 +52,6 @@ #endif #include <asm/sci.h> - -#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include "sh-sci.h" struct sci_port { @@ -645,6 +643,9 @@ static inline int sci_handle_breaks(struct uart_port *port) struct tty_struct *tty = port->info->tty; struct sci_port *s = &sci_ports[port->line]; + if (uart_handle_break(port)) + return 0; + if (!s->break_flag && status & SCxSR_BRK(port)) { #if defined(CONFIG_CPU_SH3) /* Debounce break */ diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 253ceb895ca..a27e9e92cb5 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -636,25 +636,6 @@ static irqreturn_t sn_sal_interrupt(int irq, void *dev_id) } /** - * sn_sal_connect_interrupt - Request interrupt, handled by sn_sal_interrupt - * @port: Our sn_cons_port (which contains the uart port) - * - * returns the console irq if interrupt is successfully registered, else 0 - * - */ -static int sn_sal_connect_interrupt(struct sn_cons_port *port) -{ - if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, - IRQF_DISABLED | IRQF_SHARED, - "SAL console driver", port) >= 0) { - return SGI_UART_VECTOR; - } - - printk(KERN_INFO "sn_console: console proceeding in polled mode\n"); - return 0; -} - -/** * sn_sal_timer_poll - this function handles polled console mode * @data: A pointer to our sn_cons_port (which contains the uart port) * @@ -746,30 +727,31 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port) * mode. We were previously in asynch/polling mode (using init_timer). * * We attempt to switch to interrupt mode here by calling - * sn_sal_connect_interrupt. If that works out, we enable receive interrupts. + * request_irq. If that works out, we enable receive interrupts. */ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) { - int irq; unsigned long flags; - if (!port) - return; - - DPRINTF("sn_console: switching to interrupt driven console\n"); - - spin_lock_irqsave(&port->sc_port.lock, flags); + if (port) { + DPRINTF("sn_console: switching to interrupt driven console\n"); - irq = sn_sal_connect_interrupt(port); + if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, + IRQF_DISABLED | IRQF_SHARED, + "SAL console driver", port) >= 0) { + spin_lock_irqsave(&port->sc_port.lock, flags); + port->sc_port.irq = SGI_UART_VECTOR; + port->sc_ops = &intr_ops; - if (irq) { - port->sc_port.irq = irq; - port->sc_ops = &intr_ops; - - /* turn on receive interrupts */ - ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); + /* turn on receive interrupts */ + ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); + spin_unlock_irqrestore(&port->sc_port.lock, flags); + } + else { + printk(KERN_INFO + "sn_console: console proceeding in polled mode\n"); + } } - spin_unlock_irqrestore(&port->sc_port.lock, flags); } /* diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 96a852aa190..bfd44177a21 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1387,8 +1387,8 @@ static enum su_type __devinit su_get_type(struct device_node *dp) struct device_node *ap = of_find_node_by_path("/aliases"); if (ap) { - char *keyb = of_get_property(ap, "keyboard", NULL); - char *ms = of_get_property(ap, "mouse", NULL); + const char *keyb = of_get_property(ap, "keyboard", NULL); + const char *ms = of_get_property(ap, "mouse", NULL); if (keyb) { if (dp == of_find_node_by_path(keyb)) |