aboutsummaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/8250.c76
-rw-r--r--drivers/serial/8250.h1
-rw-r--r--drivers/serial/8250_au1x00.c102
-rw-r--r--drivers/serial/8250_early.c2
-rw-r--r--drivers/serial/Kconfig8
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/clps711x.c9
-rw-r--r--drivers/serial/crisv10.c9
-rw-r--r--drivers/serial/mcfserial.c37
-rw-r--r--drivers/serial/serial_core.c1
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;