diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 19:59:04 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 19:59:04 -0700 |
commit | 73ecf3a6e3f0206bf56a0fefe3b3eda042fb7034 (patch) | |
tree | 866f0ebb2b148479e93b5ac955097b1cc94ceb4e /drivers/serial | |
parent | b9da0571050c09863e59f94d0b8594a290d61b88 (diff) | |
parent | cd3ecad19aea8debae9a48b53de2ec7a571f24e9 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (49 commits)
serial8250: ratelimit "too much work" error
serial: bfin_sport_uart: speed up sport RX sample rate to be 3% faster
serial: abstraction for 8250 legacy ports
serial/imx: check that the buffer is non-empty before sending it out
serial: mfd: add more baud rates support
jsm: Remove the uart port on errors
Alchemy: Add UART PM methods.
8250: allow platforms to override PM hook.
altera_uart: Don't use plain integer as NULL pointer
altera_uart: Fix missing prototype for registering an early console
altera_uart: Fixup type usage of port flags
altera_uart: Make it possible to use Altera UART and 8250 ports together
altera_uart: Add support for different address strides
altera_uart: Add support for getting mapbase and IRQ from resources
altera_uart: Add support for polling mode (IRQ-less)
serial: Factor out uart_poll_timeout() from 8250 driver
serial: mark the 8250 driver as maintained
serial: 8250: Don't delay after transmitter is ready.
tty: MAINTAINERS: add drivers/serial/jsm/ as maintained driver
vcs: invoke the vt update callback when /dev/vcs* is written to
...
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/68360serial.c | 51 | ||||
-rw-r--r-- | drivers/serial/8250.c | 69 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 7 | ||||
-rw-r--r-- | drivers/serial/altera_uart.c | 156 | ||||
-rw-r--r-- | drivers/serial/bfin_sport_uart.c | 7 | ||||
-rw-r--r-- | drivers/serial/imx.c | 5 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_driver.c | 4 | ||||
-rw-r--r-- | drivers/serial/max3107.c | 34 | ||||
-rw-r--r-- | drivers/serial/mfd.c | 47 | ||||
-rw-r--r-- | drivers/serial/mrst_max3110.c | 358 | ||||
-rw-r--r-- | drivers/serial/mrst_max3110.h | 1 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 49 | ||||
-rw-r--r-- | drivers/serial/uartlite.c | 26 |
13 files changed, 515 insertions, 299 deletions
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 0dff3bbddc8..88b13356ec1 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1381,6 +1381,30 @@ static void send_break(ser_info_t *info, unsigned int duration) } +/* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +static int rs_360_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + struct async_icount cnow; + + local_irq_disable(); + cnow = info->state->icount; + local_irq_enable(); + + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + + return 0; +} + static int rs_360_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { @@ -1394,7 +1418,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, if (serial_paranoia_check(info, tty->name, "rs_ioctl")) return -ENODEV; - if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (cmd != TIOCMIWAIT) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } @@ -1477,31 +1501,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, return 0; #endif - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - local_irq_disable(); - cnow = info->state->icount; - local_irq_enable(); - p_cuser = (struct serial_icounter_struct *) arg; -/* error = put_user(cnow.cts, &p_cuser->cts); */ -/* if (error) return error; */ -/* error = put_user(cnow.dsr, &p_cuser->dsr); */ -/* if (error) return error; */ -/* error = put_user(cnow.rng, &p_cuser->rng); */ -/* if (error) return error; */ -/* error = put_user(cnow.dcd, &p_cuser->dcd); */ -/* if (error) return error; */ - - put_user(cnow.cts, &p_cuser->cts); - put_user(cnow.dsr, &p_cuser->dsr); - put_user(cnow.rng, &p_cuser->rng); - put_user(cnow.dcd, &p_cuser->dcd); - return 0; default: return -ENOIOCTLCMD; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 24110f6f61e..167c4a6ccbc 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -31,6 +31,7 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/tty.h> +#include <linux/ratelimit.h> #include <linux/tty_flip.h> #include <linux/serial_reg.h> #include <linux/serial_core.h> @@ -154,12 +155,6 @@ struct uart_8250_port { unsigned char lsr_saved_flags; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; - - /* - * We provide a per-port pm hook. - */ - void (*pm)(struct uart_port *port, - unsigned int state, unsigned int old); }; struct irq_info { @@ -1606,8 +1601,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) if (l == i->head && pass_counter++ > PASS_LIMIT) { /* If we hit this, we're dead. */ - printk(KERN_ERR "serial8250: too much work for " - "irq%d\n", irq); + printk_ratelimited(KERN_ERR + "serial8250: too much work for irq%d\n", irq); break; } } while (l != end); @@ -1722,12 +1717,6 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up) mutex_unlock(&hash_mutex); } -/* Base timer interval for polling */ -static inline int poll_timeout(int timeout) -{ - return timeout > 6 ? (timeout / 2 - 2) : 1; -} - /* * This function is used to handle ports that do not have an * interrupt. This doesn't work very well for 16450's, but gives @@ -1742,7 +1731,7 @@ static void serial8250_timeout(unsigned long data) iir = serial_in(up, UART_IIR); if (!(iir & UART_IIR_NO_INT)) serial8250_handle_port(up); - mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout)); + mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port)); } static void serial8250_backup_timeout(unsigned long data) @@ -1787,7 +1776,7 @@ static void serial8250_backup_timeout(unsigned long data) /* Standard timer interval plus 0.2s to keep the port running */ mod_timer(&up->timer, - jiffies + poll_timeout(up->port.timeout) + HZ / 5); + jiffies + uart_poll_timeout(&up->port) + HZ / 5); } static unsigned int serial8250_tx_empty(struct uart_port *port) @@ -1867,15 +1856,17 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) unsigned int status, tmout = 10000; /* Wait up to 10ms for the character(s) to be sent. */ - do { + for (;;) { status = serial_in(up, UART_LSR); up->lsr_saved_flags |= status & LSR_SAVE_FLAGS; + if ((status & bits) == bits) + break; if (--tmout == 0) break; udelay(1); - } while ((status & bits) != bits); + } /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { @@ -2069,7 +2060,7 @@ static int serial8250_startup(struct uart_port *port) up->timer.function = serial8250_backup_timeout; up->timer.data = (unsigned long)up; mod_timer(&up->timer, jiffies + - poll_timeout(up->port.timeout) + HZ / 5); + uart_poll_timeout(port) + HZ / 5); } /* @@ -2079,7 +2070,7 @@ static int serial8250_startup(struct uart_port *port) */ if (!is_real_interrupt(up->port.irq)) { up->timer.data = (unsigned long)up; - mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout)); + mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); } else { retval = serial_link_irq_chain(up); if (retval) @@ -2440,16 +2431,24 @@ serial8250_set_ldisc(struct uart_port *port, int new) port->flags &= ~UPF_HARDPPS_CD; } -static void -serial8250_pm(struct uart_port *port, unsigned int state, - unsigned int oldstate) + +void serial8250_do_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) { struct uart_8250_port *p = (struct uart_8250_port *)port; serial8250_set_sleep(p, state != 0); +} +EXPORT_SYMBOL(serial8250_do_pm); - if (p->pm) - p->pm(port, state, oldstate); +static void +serial8250_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + if (port->pm) + port->pm(port, state, oldstate); + else + serial8250_do_pm(port, state, oldstate); } static unsigned int serial8250_port_size(struct uart_8250_port *pt) @@ -2674,6 +2673,16 @@ static struct uart_ops serial8250_pops = { static struct uart_8250_port serial8250_ports[UART_NR]; +static void (*serial8250_isa_config)(int port, struct uart_port *up, + unsigned short *capabilities); + +void serial8250_set_isa_configurator( + void (*v)(int port, struct uart_port *up, unsigned short *capabilities)) +{ + serial8250_isa_config = v; +} +EXPORT_SYMBOL(serial8250_set_isa_configurator); + static void __init serial8250_isa_init_ports(void) { struct uart_8250_port *up; @@ -2719,6 +2728,9 @@ static void __init serial8250_isa_init_ports(void) up->port.regshift = old_serial_port[i].iomem_reg_shift; set_io_from_upio(&up->port); up->port.irqflags |= irqflag; + if (serial8250_isa_config != NULL) + serial8250_isa_config(i, &up->port, &up->capabilities); + } } @@ -3010,6 +3022,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) port.serial_in = p->serial_in; port.serial_out = p->serial_out; port.set_termios = p->set_termios; + port.pm = p->pm; port.dev = &dev->dev; port.irqflags |= irqflag; ret = serial8250_register_port(&port); @@ -3176,6 +3189,12 @@ int serial8250_register_port(struct uart_port *port) /* Possibly override set_termios call */ if (port->set_termios) uart->port.set_termios = port->set_termios; + if (port->pm) + uart->port.pm = port->pm; + + if (serial8250_isa_config != NULL) + serial8250_isa_config(0, &uart->port, + &uart->capabilities); ret = uart_add_one_port(&serial8250_reg, &uart->port); if (ret == 0) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 3198c5335f0..92781648439 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -718,13 +718,6 @@ config SERIAL_MRST_MAX3110 the Intel Moorestown platform. On other systems use the max3100 driver. -config MRST_MAX3110_IRQ - boolean "Enable GPIO IRQ for Max3110 over Moorestown" - default n - depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL - help - This has to be enabled after Moorestown GPIO driver is loaded - config SERIAL_MFD_HSU tristate "Medfield High Speed UART support" depends on PCI diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index f8d8a00554d..721216292a5 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/timer.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/console.h> @@ -27,6 +28,8 @@ #include <linux/altera_uart.h> #define DRV_NAME "altera_uart" +#define SERIAL_ALTERA_MAJOR 204 +#define SERIAL_ALTERA_MINOR 213 /* * Altera UART register definitions according to the Nios UART datasheet: @@ -76,13 +79,28 @@ */ struct altera_uart { struct uart_port port; + struct timer_list tmr; unsigned int sigs; /* Local copy of line sigs */ unsigned short imr; /* Local IMR mirror */ }; +static u32 altera_uart_readl(struct uart_port *port, int reg) +{ + struct altera_uart_platform_uart *platp = port->private_data; + + return readl(port->membase + (reg << platp->bus_shift)); +} + +static void altera_uart_writel(struct uart_port *port, u32 dat, int reg) +{ + struct altera_uart_platform_uart *platp = port->private_data; + + writel(dat, port->membase + (reg << platp->bus_shift)); +} + static unsigned int altera_uart_tx_empty(struct uart_port *port) { - return (readl(port->membase + ALTERA_UART_STATUS_REG) & + return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0; } @@ -91,8 +109,7 @@ static unsigned int altera_uart_get_mctrl(struct uart_port *port) struct altera_uart *pp = container_of(port, struct altera_uart, port); unsigned int sigs; - sigs = - (readl(port->membase + ALTERA_UART_STATUS_REG) & + sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0; sigs |= (pp->sigs & TIOCM_RTS); @@ -108,7 +125,7 @@ static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; else pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); } static void altera_uart_start_tx(struct uart_port *port) @@ -116,7 +133,7 @@ static void altera_uart_start_tx(struct uart_port *port) struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); } static void altera_uart_stop_tx(struct uart_port *port) @@ -124,7 +141,7 @@ static void altera_uart_stop_tx(struct uart_port *port) struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); } static void altera_uart_stop_rx(struct uart_port *port) @@ -132,7 +149,7 @@ static void altera_uart_stop_rx(struct uart_port *port) struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); } static void altera_uart_break_ctl(struct uart_port *port, int break_state) @@ -145,7 +162,7 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state) pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; else pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); spin_unlock_irqrestore(&port->lock, flags); } @@ -168,7 +185,8 @@ static void altera_uart_set_termios(struct uart_port *port, tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&port->lock, flags); - writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG); + uart_update_timeout(port, termios->c_cflag, baud); + altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG); spin_unlock_irqrestore(&port->lock, flags); } @@ -178,14 +196,15 @@ static void altera_uart_rx_chars(struct altera_uart *pp) unsigned char ch, flag; unsigned short status; - while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) & + while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) & ALTERA_UART_STATUS_RRDY_MSK) { - ch = readl(port->membase + ALTERA_UART_RXDATA_REG); + ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG); flag = TTY_NORMAL; port->icount.rx++; if (status & ALTERA_UART_STATUS_E_MSK) { - writel(status, port->membase + ALTERA_UART_STATUS_REG); + altera_uart_writel(port, status, + ALTERA_UART_STATUS_REG); if (status & ALTERA_UART_STATUS_BRK_MSK) { port->icount.brk++; @@ -225,18 +244,18 @@ static void altera_uart_tx_chars(struct altera_uart *pp) if (port->x_char) { /* Send special char - probably flow control */ - writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG); + altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG); port->x_char = 0; port->icount.tx++; return; } - while (readl(port->membase + ALTERA_UART_STATUS_REG) & + while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & ALTERA_UART_STATUS_TRDY_MSK) { if (xmit->head == xmit->tail) break; - writel(xmit->buf[xmit->tail], - port->membase + ALTERA_UART_TXDATA_REG); + altera_uart_writel(port, xmit->buf[xmit->tail], + ALTERA_UART_TXDATA_REG); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } @@ -246,7 +265,7 @@ static void altera_uart_tx_chars(struct altera_uart *pp) if (xmit->head == xmit->tail) { pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; - writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); } } @@ -256,7 +275,7 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) struct altera_uart *pp = container_of(port, struct altera_uart, port); unsigned int isr; - isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr; + isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr; spin_lock(&port->lock); if (isr & ALTERA_UART_STATUS_RRDY_MSK) @@ -268,14 +287,23 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) return IRQ_RETVAL(isr); } +static void altera_uart_timer(unsigned long data) +{ + struct uart_port *port = (void *)data; + struct altera_uart *pp = container_of(port, struct altera_uart, port); + + altera_uart_interrupt(0, port); + mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port)); +} + static void altera_uart_config_port(struct uart_port *port, int flags) { port->type = PORT_ALTERA_UART; /* Clear mask, so no surprise interrupts. */ - writel(0, port->membase + ALTERA_UART_CONTROL_REG); + altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG); /* Clear status register */ - writel(0, port->membase + ALTERA_UART_STATUS_REG); + altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG); } static int altera_uart_startup(struct uart_port *port) @@ -284,6 +312,12 @@ static int altera_uart_startup(struct uart_port *port) unsigned long flags; int ret; + if (!port->irq) { + setup_timer(&pp->tmr, altera_uart_timer, (unsigned long)port); + mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port)); + return 0; + } + ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED, DRV_NAME, port); if (ret) { @@ -316,7 +350,10 @@ static void altera_uart_shutdown(struct uart_port *port) spin_unlock_irqrestore(&port->lock, flags); - free_irq(port->irq, port); + if (port->irq) + free_irq(port->irq, port); + else + del_timer_sync(&pp->tmr); } static const char *altera_uart_type(struct uart_port *port) @@ -384,8 +421,9 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) port->iotype = SERIAL_IO_MEM; port->irq = platp[i].irq; port->uartclk = platp[i].uartclk; - port->flags = ASYNC_BOOT_AUTOCONF; + port->flags = UPF_BOOT_AUTOCONF; port->ops = &altera_uart_ops; + port->private_data = platp; } return 0; @@ -393,7 +431,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) static void altera_uart_console_putc(struct uart_port *port, const char c) { - while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & + while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & ALTERA_UART_STATUS_TRDY_MSK)) cpu_relax(); @@ -423,7 +461,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options) if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) return -EINVAL; port = &altera_uart_ports[co->index].port; - if (port->membase == 0) + if (!port->membase) return -ENODEV; if (options) @@ -435,7 +473,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options) static struct uart_driver altera_uart_driver; static struct console altera_uart_console = { - .name = "ttyS", + .name = "ttyAL", .write = altera_uart_console_write, .device = uart_console_device, .setup = altera_uart_console_setup, @@ -466,9 +504,9 @@ console_initcall(altera_uart_console_init); static struct uart_driver altera_uart_driver = { .owner = THIS_MODULE, .driver_name = DRV_NAME, - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = 64, + .dev_name = "ttyAL", + .major = SERIAL_ALTERA_MAJOR, + .minor = SERIAL_ALTERA_MINOR, .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS, .cons = ALTERA_UART_CONSOLE, }; @@ -477,38 +515,55 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) { struct altera_uart_platform_uart *platp = pdev->dev.platform_data; struct uart_port *port; - int i; + struct resource *res_mem; + struct resource *res_irq; + int i = pdev->id; - for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { - port = &altera_uart_ports[i].port; + /* -1 emphasizes that the platform must have one port, no .N suffix */ + if (i == -1) + i = 0; - port->line = i; - port->type = PORT_ALTERA_UART; - port->mapbase = platp[i].mapbase; - port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); - port->iotype = SERIAL_IO_MEM; - port->irq = platp[i].irq; - port->uartclk = platp[i].uartclk; - port->ops = &altera_uart_ops; - port->flags = ASYNC_BOOT_AUTOCONF; + if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) + return -EINVAL; - uart_add_one_port(&altera_uart_driver, port); - } + port = &altera_uart_ports[i].port; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res_mem) + port->mapbase = res_mem->start; + else if (platp->mapbase) + port->mapbase = platp->mapbase; + else + return -EINVAL; + + res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res_irq) + port->irq = res_irq->start; + else if (platp->irq) + port->irq = platp->irq; + + port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); + if (!port->membase) + return -ENOMEM; + + port->line = i; + port->type = PORT_ALTERA_UART; + port->iotype = SERIAL_IO_MEM; + port->uartclk = platp->uartclk; + port->ops = &altera_uart_ops; + port->flags = UPF_BOOT_AUTOCONF; + port->private_data = platp; + + uart_add_one_port(&altera_uart_driver, port); return 0; } static int __devexit altera_uart_remove(struct platform_device *pdev) { - struct uart_port *port; - int i; - - for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) { - port = &altera_uart_ports[i].port; - if (port) - uart_remove_one_port(&altera_uart_driver, port); - } + struct uart_port *port = &altera_uart_ports[pdev->id].port; + uart_remove_one_port(&altera_uart_driver, port); return 0; } @@ -550,3 +605,4 @@ MODULE_DESCRIPTION("Altera UART driver"); MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); +MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR); diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index 5318dd3774a..6f1b51e231e 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c @@ -131,7 +131,12 @@ static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate) pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); tclkdiv = sclk / (2 * baud_rate) - 1; - rclkdiv = sclk / (2 * baud_rate * 2) - 1; + /* The actual uart baud rate of devices vary between +/-2%. The sport + * RX sample rate should be faster than the double of the worst case, + * otherwise, wrong data are received. So, set sport RX clock to be + * 3% faster. + */ + rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1; SPORT_PUT_TCLKDIV(up, tclkdiv); SPORT_PUT_RCLKDIV(up, rclkdiv); SSYNC(); diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 66ecc7ab6da..dfcf4b1878a 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -327,14 +327,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport) { struct circ_buf *xmit = &sport->port.state->xmit; - while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) { + while (!uart_circ_empty(xmit) && + !(readl(sport->port.membase + UTS) & UTS_TXFULL)) { /* send xmit->buf[xmit->tail] * out the port here */ writel(xmit->buf[xmit->tail], sport->port.membase + URTX0); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); sport->port.icount.tx++; - if (uart_circ_empty(xmit)) - break; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index eaf54501411..18f548449c6 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -172,13 +172,15 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device jsm_uart_port_init here! */ dev_err(&pdev->dev, "memory allocation for flipbuf failed\n"); rc = -ENOMEM; - goto out_free_irq; + goto out_free_uart; } pci_set_drvdata(pdev, brd); pci_save_state(pdev); return 0; + out_free_uart: + jsm_remove_uart_port(brd); out_free_irq: jsm_remove_uart_port(brd); free_irq(brd->irq, brd); diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c index 67283c1a57f..910870edf70 100644 --- a/drivers/serial/max3107.c +++ b/drivers/serial/max3107.c @@ -986,12 +986,14 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL); if (!s->rxbuf) { pr_err("Allocating RX buffer failed\n"); - return -ENOMEM; + retval = -ENOMEM; + goto err_free4; } s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL); if (!s->rxstr) { pr_err("Allocating RX buffer failed\n"); - return -ENOMEM; + retval = -ENOMEM; + goto err_free3; } /* SPI Tx buffer * SPI transfer buffer @@ -1002,7 +1004,8 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL); if (!s->txbuf) { pr_err("Allocating TX buffer failed\n"); - return -ENOMEM; + retval = -ENOMEM; + goto err_free2; } /* Initialize shared data lock */ spin_lock_init(&s->data_lock); @@ -1021,13 +1024,15 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) buf[0] = MAX3107_REVID_REG; if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n"); - return -EIO; + retval = -EIO; + goto err_free1; } if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 && (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) { dev_err(&s->spi->dev, "REVID %x does not match\n", (buf[0] & MAX3107_SPI_RX_DATA_MASK)); - return -ENODEV; + retval = -ENODEV; + goto err_free1; } /* Disable all interrupts */ @@ -1047,7 +1052,8 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) /* Perform SPI transfer */ if (max3107_rw(s, (u8 *)buf, NULL, 4)) { dev_err(&s->spi->dev, "SPI transfer for init failed\n"); - return -EIO; + retval = -EIO; + goto err_free1; } /* Register UART driver */ @@ -1055,7 +1061,7 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) retval = uart_register_driver(&max3107_uart_driver); if (retval) { dev_err(&s->spi->dev, "Registering UART driver failed\n"); - return retval; + goto err_free1; } driver_registered = 1; } @@ -1074,13 +1080,13 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) retval = uart_add_one_port(&max3107_uart_driver, &s->port); if (retval < 0) { dev_err(&s->spi->dev, "Adding UART port failed\n"); - return retval; + goto err_free1; } if (pdata->configure) { retval = pdata->configure(s); if (retval < 0) - return retval; + goto err_free1; } /* Go to suspend mode */ @@ -1088,6 +1094,16 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) pdata->hw_suspend(s, 1); return 0; + +err_free1: + kfree(s->txbuf); +err_free2: + kfree(s->rxstr); +err_free3: + kfree(s->rxbuf); +err_free4: + kfree(s); + return retval; } EXPORT_SYMBOL_GPL(max3107_probe); diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index dc0967fb9ea..5fc699e929d 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c @@ -172,6 +172,9 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf, len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV)); + if (len > HSU_REGS_BUFSIZE) + len = HSU_REGS_BUFSIZE; + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret; @@ -219,6 +222,9 @@ static ssize_t dma_show_regs(struct file *file, char __user *user_buf, len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR)); + if (len > HSU_REGS_BUFSIZE) + len = HSU_REGS_BUFSIZE; + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret; @@ -925,39 +931,52 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, cval |= UART_LCR_EPAR; /* + * The base clk is 50Mhz, and the baud rate come from: + * baud = 50M * MUL / (DIV * PS * DLAB) + * * For those basic low baud rate we can get the direct - * scalar from 2746800, like 115200 = 2746800/24, for those - * higher baud rate, we have to handle them case by case, - * but DIV reg is never touched as its default value 0x3d09 + * scalar from 2746800, like 115200 = 2746800/24. For those + * higher baud rate, we handle them case by case, mainly by + * adjusting the MUL/PS registers, and DIV register is kept + * as default value 0x3d09 to make things simple */ baud = uart_get_baud_rate(port, termios, old, 0, 4000000); - quot = uart_get_divisor(port, baud); + quot = 1; switch (baud) { case 3500000: mul = 0x3345; ps = 0xC; - quot = 1; + break; + case 3000000: + mul = 0x2EE0; break; case 2500000: mul = 0x2710; - ps = 0x10; - quot = 1; break; - case 18432000: + case 2000000: + mul = 0x1F40; + break; + case 1843200: mul = 0x2400; - ps = 0x10; - quot = 1; break; case 1500000: - mul = 0x1D4C; - ps = 0xc; - quot = 1; + mul = 0x1770; + break; + case 1000000: + mul = 0xFA0; + break; + case 500000: + mul = 0x7D0; break; default: - ; + /* Use uart_get_divisor to get quot for other baud rates */ + quot = 0; } + if (!quot) + quot = uart_get_divisor(port, baud); + if ((up->port.uartclk / quot) < (2400 * 16)) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B; else if ((up->port.uartclk / quot) < (230400 * 16)) diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c index 51c15f58e01..b62857bf2fd 100644 --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c @@ -1,7 +1,7 @@ /* - * max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown + * mrst_max3110.c - spi uart protocol driver for Maxim 3110 * - * Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com> + * Copyright (c) 2008-2010, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -32,18 +32,13 @@ #include <linux/irq.h> #include <linux/init.h> #include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/platform_device.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/seri |