diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/68360serial.c | 7 | ||||
-rw-r--r-- | drivers/serial/8250.c | 28 | ||||
-rw-r--r-- | drivers/serial/8250_early.c | 117 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 62 | ||||
-rw-r--r-- | drivers/serial/atmel_serial.c | 32 | ||||
-rw-r--r-- | drivers/serial/bfin_5xx.c | 201 | ||||
-rw-r--r-- | drivers/serial/ip22zilog.c | 3 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_driver.c | 2 | ||||
-rw-r--r-- | drivers/serial/mpsc.c | 3 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 6 | ||||
-rw-r--r-- | drivers/serial/serial_cs.c | 4 | ||||
-rw-r--r-- | drivers/serial/sn_console.c | 4 | ||||
-rw-r--r-- | drivers/serial/vr41xx_siu.c | 143 |
13 files changed, 396 insertions, 216 deletions
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 68817a7d8c0..2aa6bfe8fdb 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -934,8 +934,6 @@ static void change_speed(ser_info_t *info) /* * Set up parity check flag */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); if (I_INPCK(info->tty)) info->read_status_mask |= BD_SC_FR | BD_SC_PR; @@ -1527,11 +1525,6 @@ static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_term { ser_info_t *info = (ser_info_t *)tty->driver_data; - if ( (tty->termios->c_cflag == old_termios->c_cflag) - && ( RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - change_speed(info); #ifdef modem_control diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index c84dab083a8..0b3ec38ae61 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2514,12 +2514,18 @@ static int __init serial8250_console_setup(struct console *co, char *options) return uart_set_options(port, co, baud, parity, bits, flow); } +static int __init serial8250_console_early_setup(void) +{ + return serial8250_find_port_for_earlycon(); +} + static struct uart_driver serial8250_reg; static struct console serial8250_console = { .name = "ttyS", .write = serial8250_console_write, .device = uart_console_device, .setup = serial8250_console_setup, + .early_setup = serial8250_console_early_setup, .flags = CON_PRINTBUFFER, .index = -1, .data = &serial8250_reg, @@ -2533,7 +2539,7 @@ static int __init serial8250_console_init(void) } console_initcall(serial8250_console_init); -static int __init find_port(struct uart_port *p) +int serial8250_find_port(struct uart_port *p) { int line; struct uart_port *port; @@ -2546,26 +2552,6 @@ static int __init find_port(struct uart_port *p) return -ENODEV; } -int __init serial8250_start_console(struct uart_port *port, char *options) -{ - int line; - - line = find_port(port); - if (line < 0) - return -ENODEV; - - add_preferred_console("ttyS", line, options); - printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n", - line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port", - port->iotype == UPIO_MEM ? (unsigned long) port->mapbase : - (unsigned long) port->iobase, options); - if (!(serial8250_console.flags & CON_ENABLED)) { - serial8250_console.flags &= ~CON_PRINTBUFFER; - register_console(&serial8250_console); - } - return line; -} - #define SERIAL8250_CONSOLE &serial8250_console #else #define SERIAL8250_CONSOLE NULL diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index 7e511199b4c..947c20507e1 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -17,13 +17,11 @@ * we locate the device directly by its MMIO or I/O port address. * * The user can specify the device directly, e.g., - * console=uart,io,0x3f8,9600n8 - * console=uart,mmio,0xff5e0000,115200n8 - * or platform code can call early_uart_console_init() to set - * the early UART device. - * - * After the normal serial driver starts, we try to locate the - * matching ttyS device and start a console there. + * earlycon=uart8250,io,0x3f8,9600n8 + * earlycon=uart8250,mmio,0xff5e0000,115200n8 + * or + * console=uart8250,io,0x3f8,9600n8 + * console=uart8250,mmio,0xff5e0000,115200n8 */ #include <linux/tty.h> @@ -32,17 +30,21 @@ #include <linux/serial_core.h> #include <linux/serial_reg.h> #include <linux/serial.h> +#include <linux/serial_8250.h> #include <asm/io.h> #include <asm/serial.h> +#ifdef CONFIG_FIX_EARLYCON_MEM +#include <asm/pgtable.h> +#include <asm/fixmap.h> +#endif -struct early_uart_device { +struct early_serial8250_device { struct uart_port port; char options[16]; /* e.g., 115200n8 */ unsigned int baud; }; -static struct early_uart_device early_device __initdata; -static int early_uart_registered __initdata; +static struct early_serial8250_device early_device; static unsigned int __init serial_in(struct uart_port *port, int offset) { @@ -80,7 +82,7 @@ static void __init putc(struct uart_port *port, int c) serial_out(port, UART_TX, c); } -static void __init early_uart_write(struct console *console, const char *s, unsigned int count) +static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count) { struct uart_port *port = &early_device.port; unsigned int ier; @@ -111,7 +113,7 @@ static unsigned int __init probe_baud(struct uart_port *port) return (port->uartclk / 16) / quot; } -static void __init init_port(struct early_uart_device *device) +static void __init init_port(struct early_serial8250_device *device) { struct uart_port *port = &device->port; unsigned int divisor; @@ -130,10 +132,9 @@ static void __init init_port(struct early_uart_device *device) serial_out(port, UART_LCR, c & ~UART_LCR_DLAB); } -static int __init parse_options(struct early_uart_device *device, char *options) +static int __init parse_options(struct early_serial8250_device *device, char *options) { struct uart_port *port = &device->port; - int mapsize = 64; int mmio, length; if (!options) @@ -143,12 +144,18 @@ static int __init parse_options(struct early_uart_device *device, char *options) if (!strncmp(options, "mmio,", 5)) { port->iotype = UPIO_MEM; port->mapbase = simple_strtoul(options + 5, &options, 0); - port->membase = ioremap(port->mapbase, mapsize); +#ifdef CONFIG_FIX_EARLYCON_MEM + set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK); + port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); + port->membase += port->mapbase & ~PAGE_MASK; +#else + port->membase = ioremap(port->mapbase, 64); if (!port->membase) { printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n", __FUNCTION__, port->mapbase); return -ENOMEM; } +#endif mmio = 1; } else if (!strncmp(options, "io,", 3)) { port->iotype = UPIO_PORT; @@ -175,9 +182,16 @@ static int __init parse_options(struct early_uart_device *device, char *options) return 0; } -static int __init early_uart_setup(struct console *console, char *options) +static struct console early_serial8250_console __initdata = { + .name = "uart", + .write = early_serial8250_write, + .flags = CON_PRINTBUFFER | CON_BOOT, + .index = -1, +}; + +static int __init early_serial8250_setup(char *options) { - struct early_uart_device *device = &early_device; + struct early_serial8250_device *device = &early_device; int err; if (device->port.membase || device->port.iobase) @@ -190,61 +204,48 @@ static int __init early_uart_setup(struct console *console, char *options) return 0; } -static struct console early_uart_console __initdata = { - .name = "uart", - .write = early_uart_write, - .setup = early_uart_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static int __init early_uart_console_init(void) -{ - if (!early_uart_registered) { - register_console(&early_uart_console); - early_uart_registered = 1; - } - return 0; -} -console_initcall(early_uart_console_init); - -int __init early_serial_console_init(char *cmdline) +int __init setup_early_serial8250_console(char *cmdline) { char *options; int err; - options = strstr(cmdline, "console=uart,"); - if (!options) - return -ENODEV; + options = strstr(cmdline, "uart8250,"); + if (!options) { + options = strstr(cmdline, "uart,"); + if (!options) + return 0; + } options = strchr(cmdline, ',') + 1; - if ((err = early_uart_setup(NULL, options)) < 0) + if ((err = early_serial8250_setup(options)) < 0) return err; - return early_uart_console_init(); + + register_console(&early_serial8250_console); + + return 0; } -static int __init early_uart_console_switch(void) +int __init serial8250_find_port_for_earlycon(void) { - struct early_uart_device *device = &early_device; + struct early_serial8250_device *device = &early_device; struct uart_port *port = &device->port; - int mmio, line; + int line; + int ret; - if (!(early_uart_console.flags & CON_ENABLED)) - return 0; + if (!device->port.membase && !device->port.iobase) + return -ENODEV; - /* Try to start the normal driver on a matching line. */ - mmio = (port->iotype == UPIO_MEM); - line = serial8250_start_console(port, device->options); + line = serial8250_find_port(port); if (line < 0) - printk("No ttyS device at %s 0x%lx for console\n", - mmio ? "MMIO" : "I/O port", - mmio ? port->mapbase : - (unsigned long) port->iobase); + return -ENODEV; - unregister_console(&early_uart_console); - if (mmio) - iounmap(port->membase); + ret = update_console_cmdline("uart", 8250, + "ttyS", line, device->options); + if (ret < 0) + ret = update_console_cmdline("uart", 0, + "ttyS", line, device->options); - return 0; + return ret; } -late_initcall(early_uart_console_switch); + +early_param("earlycon", setup_early_serial8250_console); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 315ea991645..cab42cbd920 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -62,8 +62,22 @@ config SERIAL_8250_CONSOLE kernel will automatically use the first serial line, /dev/ttyS0, as system console. + you can set that using a kernel command line option such as + "console=uart8250,io,0x3f8,9600n8" + "console=uart8250,mmio,0xff5e0000,115200n8". + and it will switch to normal serial console when correponding port is + ready. + "earlycon=uart8250,io,0x3f8,9600n8" + "earlycon=uart8250,mmio,0xff5e0000,115200n8". + it will not only setup early console. + If unsure, say N. +config FIX_EARLYCON_MEM + bool + depends on X86 + default y + config SERIAL_8250_GSC tristate depends on SERIAL_8250 && GSC @@ -556,7 +570,7 @@ choice config SERIAL_BFIN_DMA bool "DMA mode" - depends on DMA_UNCACHED_1M + depends on DMA_UNCACHED_1M && !KGDB_UART help This driver works under DMA mode. If this option is selected, the blackfin simple dma driver is also enabled. @@ -599,7 +613,7 @@ config UART0_RTS_PIN config SERIAL_BFIN_UART1 bool "Enable UART1" - depends on SERIAL_BFIN && (BF534 || BF536 || BF537) + depends on SERIAL_BFIN && (BF534 || BF536 || BF537 || BF54x) help Enable UART1 @@ -612,18 +626,58 @@ config BFIN_UART1_CTSRTS config UART1_CTS_PIN int "UART1 CTS pin" - depends on BFIN_UART1_CTSRTS + depends on BFIN_UART1_CTSRTS && (BF53x || BF561) default -1 help Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. config UART1_RTS_PIN int "UART1 RTS pin" - depends on BFIN_UART1_CTSRTS + depends on BFIN_UART1_CTSRTS && (BF53x || BF561) + default -1 + help + Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. + +config SERIAL_BFIN_UART2 + bool "Enable UART2" + depends on SERIAL_BFIN && (BF54x) + help + Enable UART2 + +config BFIN_UART2_CTSRTS + bool "Enable UART2 hardware flow control" + depends on SERIAL_BFIN_UART2 + help + Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS + signal. + +config UART2_CTS_PIN + int "UART2 CTS pin" + depends on BFIN_UART2_CTSRTS + default -1 + help + Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. + +config UART2_RTS_PIN + int "UART2 RTS pin" + depends on BFIN_UART2_CTSRTS default -1 help Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. +config SERIAL_BFIN_UART3 + bool "Enable UART3" + depends on SERIAL_BFIN && (BF54x) + help + Enable UART3 + +config BFIN_UART3_CTSRTS + bool "Enable UART3 hardware flow control" + depends on SERIAL_BFIN_UART3 + help + Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS + signal. + config SERIAL_IMX bool "IMX serial port support" depends on ARM && ARCH_IMX diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 3320bcd92c0..4d6b3c56d20 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -114,6 +114,7 @@ struct atmel_uart_port { struct uart_port uart; /* uart */ struct clk *clk; /* uart clock */ unsigned short suspended; /* is port suspended? */ + int break_active; /* break being received */ }; static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; @@ -252,6 +253,7 @@ static void atmel_break_ctl(struct uart_port *port, int break_state) */ static void atmel_rx_chars(struct uart_port *port) { + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; struct tty_struct *tty = port->info->tty; unsigned int status, ch, flg; @@ -267,13 +269,29 @@ static void atmel_rx_chars(struct uart_port *port) * note that the error handling code is * out of the main execution path */ - if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) { + if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME + | ATMEL_US_OVRE | ATMEL_US_RXBRK) + || atmel_port->break_active)) { UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */ - if (status & ATMEL_US_RXBRK) { + if (status & ATMEL_US_RXBRK + && !atmel_port->break_active) { status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */ port->icount.brk++; + atmel_port->break_active = 1; + UART_PUT_IER(port, ATMEL_US_RXBRK); if (uart_handle_break(port)) goto ignore_char; + } else { + /* + * This is either the end-of-break + * condition or we've received at + * least one character without RXBRK + * being set. In both cases, the next + * RXBRK will indicate start-of-break. + */ + UART_PUT_IDR(port, ATMEL_US_RXBRK); + status &= ~ATMEL_US_RXBRK; + atmel_port->break_active = 0; } if (status & ATMEL_US_PARE) port->icount.parity++; @@ -352,6 +370,16 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) /* Interrupt receive */ if (pending & ATMEL_US_RXRDY) atmel_rx_chars(port); + else if (pending & ATMEL_US_RXBRK) { + /* + * End of break detected. If it came along + * with a character, atmel_rx_chars will + * handle it. + */ + UART_PUT_CR(port, ATMEL_US_RSTSTA); + UART_PUT_IDR(port, ATMEL_US_RXBRK); + atmel_port->break_active = 0; + } // TODO: All reads to CSR will clear these interrupts! if (pending & ATMEL_US_RIIC) port->icount.rng++; diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 787dc7168f3..66c92bc36f3 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -41,6 +41,11 @@ #include <linux/tty_flip.h> #include <linux/serial_core.h> +#ifdef CONFIG_KGDB_UART +#include <linux/kgdb.h> +#include <asm/irq_regs.h> +#endif + #include <asm/gpio.h> #include <asm/mach/bfin_serial_5xx.h> @@ -81,15 +86,29 @@ static void bfin_serial_stop_tx(struct uart_port *port) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; +#ifdef CONFIG_BF54x + while (!(UART_GET_LSR(uart) & TEMT)) + continue; +#endif + #ifdef CONFIG_SERIAL_BFIN_DMA disable_dma(uart->tx_dma_channel); #else +#ifdef CONFIG_BF54x + /* Waiting for Transmission Finished */ + while (!(UART_GET_LSR(uart) & TFI)) + continue; + /* Clear TFI bit */ + UART_PUT_LSR(uart, TFI); + UART_CLEAR_IER(uart, ETBEI); +#else unsigned short ier; ier = UART_GET_IER(uart); ier &= ~ETBEI; UART_PUT_IER(uart, ier); #endif +#endif } /* @@ -102,12 +121,16 @@ static void bfin_serial_start_tx(struct uart_port *port) #ifdef CONFIG_SERIAL_BFIN_DMA bfin_serial_dma_tx_chars(uart); #else +#ifdef CONFIG_BF54x + UART_SET_IER(uart, ETBEI); +#else unsigned short ier; ier = UART_GET_IER(uart); ier |= ETBEI; UART_PUT_IER(uart, ier); bfin_serial_tx_chars(uart); #endif +#endif } /* @@ -116,11 +139,18 @@ static void bfin_serial_start_tx(struct uart_port *port) static void bfin_serial_stop_rx(struct uart_port *port) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; +#ifdef CONFIG_BF54x + UART_CLEAR_IER(uart, ERBFI); +#else unsigned short ier; ier = UART_GET_IER(uart); +#ifdef CONFIG_KGDB_UART + if (uart->port.line != CONFIG_KGDB_UART_PORT) +#endif ier &= ~ERBFI; UART_PUT_IER(uart, ier); +#endif } /* @@ -130,6 +160,49 @@ static void bfin_serial_enable_ms(struct uart_port *port) { } +#ifdef CONFIG_KGDB_UART +static int kgdb_entry_state; + +void kgdb_put_debug_char(int chr) +{ + struct bfin_serial_port *uart; + + if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS) + uart = &bfin_serial_ports[0]; + else + uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; + + while (!(UART_GET_LSR(uart) & THRE)) { + __builtin_bfin_ssync(); + } + UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); + __builtin_bfin_ssync(); + UART_PUT_CHAR(uart, (unsigned char)chr); + __builtin_bfin_ssync(); +} + +int kgdb_get_debug_char(void) +{ + struct bfin_serial_port *uart; + unsigned char chr; + + if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS) + uart = &bfin_serial_ports[0]; + else + uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; + + while(!(UART_GET_LSR(uart) & DR)) { + __builtin_bfin_ssync(); + } + UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); + __builtin_bfin_ssync(); + chr = UART_GET_CHAR(uart); + __builtin_bfin_ssync(); + + return chr; +} +#endif + #ifdef CONFIG_SERIAL_BFIN_PIO static void local_put_char(struct bfin_serial_port *uart, char ch) { @@ -152,6 +225,9 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = uart->port.info->tty; unsigned int status, ch, flg; +#ifdef CONFIG_KGDB_UART + struct pt_regs *regs = get_irq_regs(); +#endif #ifdef BF533_FAMILY static int in_break = 0; #endif @@ -160,6 +236,27 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) ch = UART_GET_CHAR(uart); uart->port.icount.rx++; +#ifdef CONFIG_KGDB_UART + if (uart->port.line == CONFIG_KGDB_UART_PORT) { + if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */ + kgdb_breakkey_pressed(regs); + return; + } else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */ + kgdb_entry_state = 1; + } else if (kgdb_entry_state == 1 && ch == 'q') { + kgdb_entry_state = 0; + kgdb_breakkey_pressed(regs); + return; + } else if (ch == 0x3) {/* Ctrl + C */ + kgdb_entry_state = 0; + kgdb_breakkey_pressed(regs); + return; + } else { + kgdb_entry_state = 0; + } + } +#endif + #ifdef BF533_FAMILY /* The BF533 family of processors have a nice misbehavior where * they continuously generate characters for a "single" break. @@ -185,6 +282,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto ignore_char; + status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; @@ -249,10 +347,21 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; +#ifdef CONFIG_BF54x + unsigned short status; + spin_lock(&uart->port.lock); + status = UART_GET_LSR(uart); + while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) { + bfin_serial_rx_chars(uart); + status = UART_GET_LSR(uart); + } + spin_unlock(&uart->port.lock); +#else spin_lock(&uart->port.lock); while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY) bfin_serial_rx_chars(uart); spin_unlock(&uart->port.lock); +#endif return IRQ_HANDLED; } @@ -260,10 +369,21 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; +#ifdef CONFIG_BF54x + unsigned short status; + spin_lock(&uart->port.lock); + status = UART_GET_LSR(uart); + while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) { + bfin_serial_tx_chars(uart); + status = UART_GET_LSR(uart); + } + spin_unlock(&uart->port.lock); +#else spin_lock(&uart->port.lock); while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY) bfin_serial_tx_chars(uart); spin_unlock(&uart->port.lock); +#endif return IRQ_HANDLED; } @@ -274,7 +394,6 @@ static void bfin_serial_do_work(struct work_struct *work) bfin_serial_mctrl_check(uart); } - #endif #ifdef CONFIG_SERIAL_BFIN_DMA @@ -323,9 +442,13 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) set_dma_x_count(uart->tx_dma_channel, uart->tx_count); set_dma_x_modify(uart->tx_dma_channel, 1); enable_dma(uart->tx_dma_channel); +#ifdef CONFIG_BF54x + UART_SET_IER(uart, ETBEI); +#else ier = UART_GET_IER(uart); ier |= ETBEI; UART_PUT_IER(uart, ier); +#endif spin_unlock_irqrestore(&uart->port.lock, flags); } @@ -341,6 +464,7 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto dma_ignore_char; + status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; @@ -404,9 +528,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { clear_dma_irqstat(uart->tx_dma_channel); disable_dma(uart->tx_dma_channel); +#ifdef CONFIG_BF54x + UART_CLEAR_IER(uart, ETBEI); +#else ier = UART_GET_IER(uart); ier &= ~ETBEI; UART_PUT_IER(uart, ier); +#endif xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1); uart->port.icount.tx+=uart->tx_count; @@ -517,6 +645,14 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart) */ static void bfin_serial_break_ctl(struct uart_port *port, int break_state) { + struct bfin_serial_port *uart = (struct bfin_serial_port *)port; + u16 lcr = UART_GET_LCR(uart); + if (break_state) + lcr |= SB; + else + lcr &= ~SB; + UART_PUT_LCR(uart, lcr); + SSYNC(); } static int bfin_serial_startup(struct uart_port *port) @@ -561,7 +697,11 @@ static int bfin_serial_startup(struct uart_port *port) uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; add_timer(&(uart->rx_dma_timer)); #else +# ifdef CONFIG_KGDB_UART + if (uart->port.line != CONFIG_KGDB_UART_PORT && request_irq +# else if (request_irq +# endif (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, "BFIN_UART_RX", uart)) { printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); @@ -576,7 +716,11 @@ static int bfin_serial_startup(struct uart_port *port) return -EBUSY; } #endif +#ifdef CONFIG_BF54x + UART_SET_IER(uart, ERBFI); +#else UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI); +#endif return 0; } @@ -591,6 +735,9 @@ static void bfin_serial_shutdown(struct uart_port *port) free_dma(uart->rx_dma_channel); del_timer(&(uart->rx_dma_timer)); #else +#ifdef CONFIG_KGDB_UART + if (uart->port.line != CONFIG_KGDB_UART_PORT) +#endif free_irq(uart->port.irq, uart); free_irq(uart->port.irq+1, uart); #endif @@ -625,11 +772,12 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & CSTOPB) lcr |= STB; - if (termios->c_cflag & PARENB) { + if (termios->c_cflag & PARENB) lcr |= PEN; - if (!(termios->c_cflag & PARODD)) - lcr |= EPS; - } + if (!(termios->c_cflag & PARODD)) + lcr |= EPS; + if (termios->c_cflag & CMSPAR) + lcr |= STP; port->read_status_mask = OE; if (termios->c_iflag & INPCK) @@ -663,29 +811,41 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, /* Disable UART */ ier = UART_GET_IER(uart); +#ifdef CONFIG_BF54x + UART_CLEAR_IER(uart, 0xF); +#else UART_PUT_IER(uart, 0); +#endif +#ifndef CONFIG_BF54x /* Set DLAB in LCR to Access DLL and DLH */ val = UART_GET_LCR(uart); val |= DLAB; UART_PUT_LCR(uart, val); SSYNC(); +#endif UART_PUT_DLL(uart, quot & 0xFF); SSYNC(); UART_PUT_DLH(uart, (quot >> 8) & 0xFF); SSYNC(); +#ifndef CONFIG_BF54x /* Clear DLAB in LCR to Access THR RBR IER */ val = UART_GET_LCR(uart); val &= ~DLAB; UART_PUT_LCR(uart, val); SSYNC(); +#endif UART_PUT_LCR(uart, lcr); /* Enable UART */ +#ifdef CONFIG_BF54x + UART_SET_IER(uart, ier); +#else UART_PUT_IER(uart, ier); +#endif val = UART_GET_GCTL(uart); val |= UCEN; @@ -797,15 +957,15 @@ static void __init bfin_serial_init_ports(void) bfin_serial_resource[i].uart_rts_pin; #endif bfin_serial_hw_init(&bfin_serial_ports[i]); - } + } #ifdef CONFIG_SERIAL_BFIN_CONSOLE static void bfin_serial_console_putchar(struct uart_port *port, int ch) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - while (!(UART_GET_LSR(uart))) + while (!(UART_GET_LSR(uart) & THRE)) barrier(); UART_PUT_CHAR(uart, ch); SSYNC(); @@ -857,18 +1017,22 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud, case 2: *bits = 7; break; case 3: *bits = 8; break; } +#ifndef CONFIG_BF54x /* Set DLAB in LCR to Access DLL and DLH */ val = UART_GET_LCR(uart); val |= DLAB; UART_PUT_LCR(uart, val); +#endif dll = UART_GET_DLL(uart); dlh = UART_GET_DLH(uart); +#ifndef CONFIG_BF54x /* Clear DLAB in LCR to Access THR RBR IER */ val = UART_GET_LCR(uart); val &= ~DLAB; UART_PUT_LCR(uart, val); +#endif *baud = get_sclk() / (16*(dll | dlh << 8)); } @@ -920,6 +1084,10 @@ static int __init bfin_serial_rs_console_init(void) { bfin_serial_init_ports(); register_console(&bfin_serial_console); +#ifdef CONFIG_KGDB_UART + kgdb_entry_state = 0; + init_kgdb_uart(); +#endif return 0; } console_initcall(bfin_serial_rs_console_init); @@ -1012,6 +1180,10 @@ static struct platform_driver bfin_serial_driver = { static int __init bfin_serial_init(void) { int ret; +#ifdef CONFIG_KGDB_UART + struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; + struct termios t; +#endif pr_info("Serial: Blackfin serial driver\n"); @@ -1025,6 +1197,21 @@ static int __init bfin_serial_init(void) uart_unregister_driver(&bfin_serial_reg); } } +#ifdef CONFIG_KGDB_UART + if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) { + request_irq(uart->port.irq, bfin_serial_int, + IRQF_DISABLED, "BFIN_UART_RX", uart); + pr_info("Request irq for kgdb uart port\n"); + UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI); + __builtin_bfin_ssync(); + t.c_cflag = CS8|B57600; + t.c_iflag = 0; + t.c_oflag = 0; + t.c_lflag = ICANON; + t.c_line = CONFIG_KGDB_UART_PORT; + bfin_serial_set_termios(&uart->port, &t, &t); + } +#endif return ret; } diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index c3abfb39f31..f3257f708ef 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -862,6 +862,7 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, up->cflag = termios->c_cflag; ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); + uart_update_timeout(port, termios->c_cflag, baud); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -1017,6 +1018,8 @@ ip22serial_console_termios(struct console *con, char *options) } con->cflag = cflag | CS8; /* 8N1 */ + + uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud); } static int __init ip22zilog_console_setup(struct console *con, char *options) diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index 81792e6eeb2..6767ee381cd 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -88,7 +88,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) spin_lock_init(&brd->bd_intr_lock); /* store which revision we have */ - pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev); + brd->rev = pdev->revision; brd->irq = pdev->irq; diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index d09f2097d5b..00924feaf62 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -503,7 +503,8 @@ mpsc_sdma_intr_ack(struct mpsc_port_info *pi) if (pi->mirror_regs) pi->shared_regs->SDMA_INTR_CAUSE_m = 0; - writel(0, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE); + writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE + + pi->port.line); return; } diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 326020f86f7..9c57486c2e7 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1910,6 +1910,12 @@ uart_set_options(struct uart_port *port, struct console *co, if (flow == 'r') termios.c_cflag |= CRTSCTS; + /* + * some uarts on other side don't support no flow control. + * So we set * DTR in host uart to make them happy + */ + port->mctrl |= TIOCM_DTR; + port->ops->set_termios(port, &termios, NULL); co->cflag = termios.c_cflag; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 6b76babc7fb..a0ea4359851 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -842,12 +842,16 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), + PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555), + PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed), PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), + PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05), + PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101), PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070), PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562), PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070), diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index a27e9e92cb5..41fc6126444 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -759,7 +759,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) */ static void sn_sal_console_write(struct console *, const char *, unsigned); -static int __init sn_sal_console_setup(struct console *, char *); +static int sn_sal_console_setup(struct console *, char *); static struct uart_driver sal_console_uart; extern struct tty_driver *uart_console_device(struct console *, int *); @@ -1006,7 +1006,7 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) * here so providing it is easier. * */ -static int __init sn_sal_console_setup(struct console *co, char *options) +static int sn_sal_console_setup(struct console *co, char *options) { return 0; } diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index cf0e663b42e..85309acb75f 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -1,7 +1,7 @@ /* * Driver for NEC VR4100 series Serial Interface Unit. * - * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2004-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * Based on drivers/serial/8250.c, by Russell King. * @@ -25,12 +25,12 @@ #endif #include <linux/console.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/ioport.h> +#include <linux/errno.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/ioport.h> #include <linux/module.h> +#include <linux/platform_device.h> #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/serial_reg.h> @@ -38,11 +38,9 @@ #include <linux/tty_flip.h> #include <asm/io.h> -#include <asm/vr41xx/irq.h> #include <asm/vr41xx/siu.h> #include <asm/vr41xx/vr41xx.h> -#define SIU_PORTS_MAX 2 #define SIU_BAUD_BASE 1152000 #define SIU_MAJOR 204 #define SIU_MINOR_BASE 82 @@ -60,32 +58,13 @@ #define IRUSESEL 0x02 #define SIRSEL 0x01 -struct siu_port { - unsigned int type; - unsigned int irq; - unsigned long start; -}; - -static const struct siu_port siu_type1_ports[] = { - { .type = PORT_VR41XX_SIU, - .irq = SIU_IRQ, - .start = 0x0c000000UL, }, -}; - -#define SIU_TYPE1_NR_PORTS (sizeof(siu_type1_ports) / sizeof(struct siu_port)) - -static const struct siu_port siu_type2_ports[] = { - { .type = PORT_VR41XX_SIU, - .irq = SIU_IRQ, - .start = 0x0f000800UL, }, - { .type = PORT_VR41XX_DSIU, - .irq = DSIU_IRQ, - .start = 0x0f000820UL, }, +static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { + [0 ... SIU_PORTS_MAX-1] = { + .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock), + .irq = -1, + }, }; -#define SIU_TYPE2_NR_PORTS (sizeof(siu_type2_ports) / sizeof(struct siu_port)) - -static struct uart_port siu_uart_ports[SIU_PORTS_MAX]; static uint8_t lsr_break_flag[SIU_PORTS_MAX]; #define siu_read(port, offset) readb((port)->membase + (offset)) @@ -110,7 +89,6 @@ void vr41xx_select_siu_interface(siu_interface_t interface) spin_unlock_irqrestore(&port->lock, flags); } - EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface); void vr41xx_use_irda(irda_use_t use) @@ -132,7 +110,6 @@ void vr41xx_use_irda(irda_use_t use) spin_unlock_irqrestore(&port->lock, flags); } - EXPORT_SYMBOL_GPL(vr41xx_use_irda); void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed) @@ -166,7 +143,6 @@ void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed) spin_unlock_irqrestore(&port->lock, flags); } - EXPORT_SYMBOL_GPL(vr41xx_select_irda_module); static inline void siu_clear_fifo(struct uart_port *port) @@ -177,21 +153,6 @@ static inline void siu_clear_fifo(struct uart_port *port) siu_write(port, UART_FCR, 0); } -static inline int siu_probe_ports(void) -{ - switch (current_cpu_data.cputype) { - case CPU_VR4111: - case CPU_VR4121: - return SIU_TYPE1_NR_PORTS; - case CPU_VR4122: - case CPU_VR4131: - case CPU_VR4133: - return SIU_TYPE2_NR_PORTS; - } - - return 0; -} - static inline unsigned long siu_port_size(struct uart_port *port) { switch (port->type) { @@ -206,21 +167,10 @@ static inline unsigned long siu_port_size(struct uart_port *port) static inline unsigned int siu_check_type(struct uart_port *port) { - switch (current_cpu_data.cputype) { - case CPU_VR4111: - case CPU_VR4121: - if (port->line == 0) - return PORT_VR41XX_SIU; - break; - case CPU_VR4122: - case CPU_VR4131: - case CPU_VR4133: - if (port->line == 0) - return PORT_VR41XX_SIU; - else if (port->line == 1) - return PORT_VR41XX_DSIU; - break; - } + if (port->line == 0) + return PORT_VR41XX_SIU; + if (port->line == 1 && port->irq != -1) + return PORT_VR41XX_DSIU; return PORT_UNKNOWN; } @@ -751,44 +701,34 @@ static struct uart_ops siu_uart_ops = { .verify_port = siu_verify_port, }; -static int siu_init_ports(void) +static int siu_init_ports(struct platform_device *pdev) { - const struct siu_port *siu; struct uart_port *port; - int i, num; + struct resource *res; + int *type = pdev->dev.platform_data; + int i; - switch (current_cpu_data.cputype) { - case CPU_VR4111: - case CPU_VR4121: - siu = siu_type1_ports; - break; - case CPU_VR4122: - case CPU_VR4131: - case CPU_VR4133: - siu = siu_type2_ports; - break; - default: + if (!type) return 0; - } port = siu_uart_ports; - num = siu_probe_ports(); - for (i = 0; i < num; i++) { - spin_lock_init(&port->lock); - port->irq = siu->irq; + for (i = 0; i < SIU_PORTS_MAX; i++) { + port->type = type[i]; + if (port->type == PORT_UNKNOWN) + continue; + port->irq = platform_get_irq(pdev, i); port->uartclk = SIU_BAUD_BASE * 16; port->fifosize = 16; port->regshift = 0; port->iotype = UPIO_MEM; port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - port->type = siu->type; port->line = i; - port->mapbase = siu->start; - siu++; + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + port->mapbase = res->start; port++; } - return num; + return i; } #ifdef CONFIG_SERIAL_VR41XX_CONSOLE @@ -883,13 +823,9 @@ static struct console siu_console = { static int __devinit siu_console_init(void) { struct uart_port *port; - int num, i; - - num = siu_init_ports(); - if (num <= 0) - return -ENODEV; + int i; - for (i = 0; i < num; i++) { + for (i = 0; i < SIU_PORTS_MAX; i++) { port = &siu_uart_ports[i]; port->ops = &siu_uart_ops; } @@ -920,7 +856,7 @@ static int __devinit siu_probe(struct platform_device *dev) struct uart_port *port; int num, i, retval; - num = siu_init_ports(); + num = siu_init_ports(dev); if (num <= 0) return -ENODEV; @@ -998,8 +934,6 @@ static int siu_resume(struct platform_device *dev) return 0; } -static struct platform_device *siu_platform_device; - static struct platform_driver siu_device_driver = { .probe = siu_probe, .remove = __devexit_p(siu_remove), @@ -1013,29 +947,12 @@ static struct platform_driver siu_device_driver = { static int __init vr41xx_siu_init(void) { - int retval; - - siu_platform_device = platform_device_alloc("SIU", -1); - if (!siu_platform_device) - return -ENOMEM; - - retval = platform_device_add(siu_platform_device); - if (retval < 0) { - platform_device_put(siu_platform_device); - return retval; - } - - retval = platform_driver_register(&siu_device_driver); - if (retval < 0) - platform_device_unregister(siu_platform_device); - - return retval; + return platform_driver_register(&siu_device_driver); } static void __exit vr41xx_siu_exit(void) { platform_driver_unregister(&siu_device_driver); - platform_device_unregister(siu_platform_device); } module_init(vr41xx_siu_init); |