diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/8250.c | 76 | ||||
-rw-r--r-- | drivers/serial/8250.h | 1 | ||||
-rw-r--r-- | drivers/serial/8250_au1x00.c | 102 | ||||
-rw-r--r-- | drivers/serial/8250_early.c | 2 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 8 | ||||
-rw-r--r-- | drivers/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/serial/clps711x.c | 9 | ||||
-rw-r--r-- | drivers/serial/crisv10.c | 9 | ||||
-rw-r--r-- | drivers/serial/mcfserial.c | 37 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 1 |
10 files changed, 224 insertions, 22 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index f47d2c454e3..98820603e75 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -40,6 +40,7 @@ #include <linux/serial_core.h> #include <linux/serial.h> #include <linux/serial_8250.h> +#include <linux/nmi.h> #include <asm/io.h> #include <asm/irq.h> @@ -251,9 +252,53 @@ static const struct serial8250_config uart_config[] = { }, }; +#ifdef CONFIG_SERIAL_8250_AU1X00 + +/* Au1x00 UART hardware has a weird register layout */ +static const u8 au_io_in_map[] = { + [UART_RX] = 0, + [UART_IER] = 2, + [UART_IIR] = 3, + [UART_LCR] = 5, + [UART_MCR] = 6, + [UART_LSR] = 7, + [UART_MSR] = 8, +}; + +static const u8 au_io_out_map[] = { + [UART_TX] = 1, + [UART_IER] = 2, + [UART_FCR] = 4, + [UART_LCR] = 5, + [UART_MCR] = 6, +}; + +/* sane hardware needs no mapping */ +static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_in_map[offset]; +} + +static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_out_map[offset]; +} + +#else + +/* sane hardware needs no mapping */ +#define map_8250_in_reg(up, offset) (offset) +#define map_8250_out_reg(up, offset) (offset) + +#endif + static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) { - offset <<= up->port.regshift; + offset = map_8250_in_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -266,6 +311,11 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) case UPIO_MEM32: return readl(up->port.membase + offset); +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + return __raw_readl(up->port.membase + offset); +#endif + default: return inb(up->port.iobase + offset); } @@ -274,7 +324,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) static _INLINE_ void serial_out(struct uart_8250_port *up, int offset, int value) { - offset <<= up->port.regshift; + offset = map_8250_out_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -290,6 +340,12 @@ serial_out(struct uart_8250_port *up, int offset, int value) writel(value, up->port.membase + offset); break; +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + __raw_writel(value, up->port.membase + offset); + break; +#endif + default: outb(value, up->port.iobase + offset); } @@ -910,6 +966,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) } } #endif + +#ifdef CONFIG_SERIAL_8250_AU1X00 + /* if access method is AU, it is a 16550 with a quirk */ + if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) + up->bugs |= UART_BUG_NOMSR; +#endif + serial_outp(up, UART_LCR, save_lcr); if (up->capabilities != uart_config[up->port.type].flags) { @@ -1057,6 +1120,10 @@ static void serial8250_enable_ms(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; + /* no MSR capabilities */ + if (up->bugs & UART_BUG_NOMSR) + return; + up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); } @@ -1774,7 +1841,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, * CTS flow control flag and modem status interrupts */ up->ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (!(up->bugs & UART_BUG_NOMSR) && + UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; if (up->capabilities & UART_CAP_UUE) up->ier |= UART_IER_UUE | UART_IER_RTOIE; @@ -2141,6 +2209,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) unsigned int ier; int i; + touch_nmi_watchdog(); + /* * First save the UER then disable the interrupts */ diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index b1b459efda5..a607b98016d 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -49,6 +49,7 @@ struct serial8250_config { #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ +#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) #define _INLINE_ inline diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c new file mode 100644 index 00000000000..06ae8fbcc94 --- /dev/null +++ b/drivers/serial/8250_au1x00.c @@ -0,0 +1,102 @@ +/* + * Serial Device Initialisation for Au1x00 + * + * (C) Copyright Embedded Alley Solutions, Inc 2005 + * Author: Pantelis Antoniou <pantelis@embeddedalley.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/module.h> +#include <linux/serial_core.h> +#include <linux/signal.h> +#include <linux/slab.h> +#include <linux/types.h> + +#include <linux/serial_8250.h> + +#include <asm/mach-au1x00/au1000.h> + +#include "8250.h" + +#define PORT(_base, _irq) \ + { \ + .iobase = _base, \ + .membase = (void __iomem *)_base,\ + .mapbase = _base, \ + .irq = _irq, \ + .uartclk = 0, /* filled */ \ + .regshift = 2, \ + .iotype = UPIO_AU, \ + .flags = UPF_SKIP_TEST | \ + UPF_IOREMAP, \ + } + +static struct plat_serial8250_port au1x00_data[] = { +#if defined(CONFIG_SOC_AU1000) + PORT(UART0_ADDR, AU1000_UART0_INT), + PORT(UART1_ADDR, AU1000_UART1_INT), + PORT(UART2_ADDR, AU1000_UART2_INT), + PORT(UART3_ADDR, AU1000_UART3_INT), +#elif defined(CONFIG_SOC_AU1500) + PORT(UART0_ADDR, AU1500_UART0_INT), + PORT(UART3_ADDR, AU1500_UART3_INT), +#elif defined(CONFIG_SOC_AU1100) + PORT(UART0_ADDR, AU1100_UART0_INT), + PORT(UART1_ADDR, AU1100_UART1_INT), + PORT(UART2_ADDR, AU1100_UART2_INT), + PORT(UART3_ADDR, AU1100_UART3_INT), +#elif defined(CONFIG_SOC_AU1550) + PORT(UART0_ADDR, AU1550_UART0_INT), + PORT(UART1_ADDR, AU1550_UART1_INT), + PORT(UART2_ADDR, AU1550_UART2_INT), + PORT(UART3_ADDR, AU1550_UART3_INT), +#elif defined(CONFIG_SOC_AU1200) + PORT(UART0_ADDR, AU1200_UART0_INT), + PORT(UART1_ADDR, AU1200_UART1_INT), +#endif + { }, +}; + +static struct platform_device au1x00_device = { + .name = "serial8250", + .id = PLAT8250_DEV_AU1X00, + .dev = { + .platform_data = au1x00_data, + }, +}; + +static int __init au1x00_init(void) +{ + int i; + unsigned int uartclk; + + /* get uart clock */ + uartclk = get_au1x00_uart_baud_base() * 16; + + /* fill up uartclk */ + for (i = 0; au1x00_data[i].flags ; i++) + au1x00_data[i].uartclk = uartclk; + + return platform_device_register(&au1x00_device); +} + +/* XXX: Yes, I know this doesn't yet work. */ +static void __exit au1x00_exit(void) +{ + platform_device_unregister(&au1x00_device); +} + +module_init(au1x00_init); +module_exit(au1x00_exit); + +MODULE_AUTHOR("Pantelis Antoniou <pantelis@embeddedalley.com>"); +MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index b7a5dd71022..59ba5d993b4 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -164,7 +164,7 @@ static int __init parse_options(struct early_uart_device *device, char *options) if ((options = strchr(options, ','))) { options++; - device->baud = simple_strtoul(options, 0, 0); + device->baud = simple_strtoul(options, NULL, 0); length = min(strcspn(options, " "), sizeof(device->options)); strncpy(device->options, options, length); } else { diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b745a1b9e83..ff36f0c9fda 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -207,6 +207,14 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AU1X00 + bool "AU1X00 serial port support" + depends on SERIAL_8250 != n && SOC_AU1X00 + help + If you have an Au1x00 board and want to use the serial port, say Y + to this option. The driver can handle 1 or 2 serial ports. + If unsure, say N. + comment "Non-8250 serial port support" config SERIAL_AMBA_PL010 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 11c7dc483f9..d7c7c7180e3 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o +obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 6a67e8f585b..87ef368384f 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -408,11 +408,7 @@ static struct uart_port clps711x_ports[UART_NR] = { { .iobase = SYSCON1, .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */ -#ifdef CONFIG_MP1000_90MHZ - .uartclk = 4515840, -#else .uartclk = 3686400, -#endif .fifosize = 16, .ops = &clps711x_pops, .line = 0, @@ -421,11 +417,7 @@ static struct uart_port clps711x_ports[UART_NR] = { { .iobase = SYSCON2, .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */ -#ifdef CONFIG_MP1000_90MHZ - .uartclk = 4515840, -#else .uartclk = 3686400, -#endif .fifosize = 16, .ops = &clps711x_pops, .line = 1, @@ -559,7 +551,6 @@ console_initcall(clps711xuart_console_init); static struct uart_driver clps711x_reg = { .driver_name = "ttyCL", .dev_name = "ttyCL", - .devfs_name = "ttyCL", .major = SERIAL_CLPS711X_MAJOR, .minor = SERIAL_CLPS711X_MINOR, .nr = UART_NR, diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 40d3e7139cf..08c42c00018 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -4416,10 +4416,8 @@ rs_close(struct tty_struct *tty, struct file * filp) info->event = 0; info->tty = 0; if (info->blocked_open) { - if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); - } + if (info->close_delay) + schedule_timeout_interruptible(info->close_delay); wake_up_interruptible(&info->open_wait); } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); @@ -4469,8 +4467,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) while (info->xmit.head != info->xmit.tail || /* More in send queue */ (*info->ostatusadr & 0x007f) || /* more in FIFO */ (elapsed_usec < 2*info->char_time_usec)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index e2ebdcad553..47f7404cb04 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -57,7 +57,8 @@ struct timer_list mcfrs_timer_struct; * keep going. Perhaps one day the cflag settings for the * console can be used instead. */ -#if defined(CONFIG_ARNEWSH) || defined(CONFIG_MOTOROLA) || defined(CONFIG_senTec) || defined(CONFIG_SNEHA) +#if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ + defined(CONFIG_senTec) || defined(CONFIG_SNEHA) #define CONSOLE_BAUD_RATE 19200 #define DEFAULT_CBAUD B19200 #endif @@ -67,7 +68,7 @@ struct timer_list mcfrs_timer_struct; #define DEFAULT_CBAUD B38400 #endif -#if defined(CONFIG_MOD5272) +#if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) #define CONSOLE_BAUD_RATE 115200 #define DEFAULT_CBAUD B115200 #endif @@ -95,7 +96,8 @@ static struct tty_driver *mcfrs_serial_driver; #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_FLOW -#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) +#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ + defined(CONFIG_M520x) #define IRQBASE (MCFINT_VECBASE+MCFINT_UART0) #else #define IRQBASE 73 @@ -1528,6 +1530,35 @@ static void mcfrs_irqinit(struct mcf_serial *info) imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + MCFINTC_IMRL); *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); +#elif defined(CONFIG_M520x) + volatile unsigned char *icrp, *uartp; + volatile unsigned long *imrp; + + uartp = info->addr; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 + + MCFINTC_ICR0 + MCFINT_UART0 + info->line); + *icrp = 0x03; + + imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + + MCFINTC_IMRL); + *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); + if (info->line < 2) { + unsigned short *uart_par; + uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART); + if (info->line == 0) + *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD0 + | MCF_GPIO_PAR_UART_PAR_URXD0; + else if (info->line == 1) + *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD1 + | MCF_GPIO_PAR_UART_PAR_URXD1; + } else if (info->line == 2) { + unsigned char *feci2c_par; + feci2c_par = (unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); + *feci2c_par &= ~0x0F; + *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 + | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2; + } #else volatile unsigned char *icrp, *uartp; diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0745ce78297..427a2385807 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1959,6 +1959,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) break; case UPIO_MEM: case UPIO_MEM32: + case UPIO_AU: snprintf(address, sizeof(address), "MMIO 0x%lx", port->mapbase); break; |