aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPantelis Antoniou <pantelis.antoniou@gmail.com>2005-11-06 04:07:03 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-11-06 04:07:03 -0500
commit21c614a7899046ab108b3d327d76c33443a8ebf2 (patch)
tree99cf486877f2a4133b5bfb262bc7aa0641cefd14 /drivers
parentf912696ab330bf539231d1f8032320f2a08b850f (diff)
[SERIAL] Support Au1x00 8250 UARTs using the generic 8250 driver.
The offsets of the registers are in a different place, and some parts cannot handle a full set of modem control signals. Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.ocm> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/8250.c73
-rw-r--r--drivers/serial/8250.h1
-rw-r--r--drivers/serial/8250_au1x00.c102
-rw-r--r--drivers/serial/Kconfig8
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_core.c1
6 files changed, 183 insertions, 3 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index f47d2c454e33..186e96c47b3d 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -251,9 +251,53 @@ static const struct serial8250_config uart_config[] = {
251 }, 251 },
252}; 252};
253 253
254#ifdef CONFIG_SERIAL_8250_AU1X00
255
256/* Au1x00 UART hardware has a weird register layout */
257static const u8 au_io_in_map[] = {
258 [UART_RX] = 0,
259 [UART_IER] = 2,
260 [UART_IIR] = 3,
261 [UART_LCR] = 5,
262 [UART_MCR] = 6,
263 [UART_LSR] = 7,
264 [UART_MSR] = 8,
265};
266
267static const u8 au_io_out_map[] = {
268 [UART_TX] = 1,
269 [UART_IER] = 2,
270 [UART_FCR] = 4,
271 [UART_LCR] = 5,
272 [UART_MCR] = 6,
273};
274
275/* sane hardware needs no mapping */
276static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
277{
278 if (up->port.iotype != UPIO_AU)
279 return offset;
280 return au_io_in_map[offset];
281}
282
283static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
284{
285 if (up->port.iotype != UPIO_AU)
286 return offset;
287 return au_io_out_map[offset];
288}
289
290#else
291
292/* sane hardware needs no mapping */
293#define map_8250_in_reg(up, offset) (offset)
294#define map_8250_out_reg(up, offset) (offset)
295
296#endif
297
254static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) 298static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
255{ 299{
256 offset <<= up->port.regshift; 300 offset = map_8250_in_reg(up, offset) << up->port.regshift;
257 301
258 switch (up->port.iotype) { 302 switch (up->port.iotype) {
259 case UPIO_HUB6: 303 case UPIO_HUB6:
@@ -266,6 +310,11 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
266 case UPIO_MEM32: 310 case UPIO_MEM32:
267 return readl(up->port.membase + offset); 311 return readl(up->port.membase + offset);
268 312
313#ifdef CONFIG_SERIAL_8250_AU1X00
314 case UPIO_AU:
315 return __raw_readl(up->port.membase + offset);
316#endif
317
269 default: 318 default:
270 return inb(up->port.iobase + offset); 319 return inb(up->port.iobase + offset);
271 } 320 }
@@ -274,7 +323,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
274static _INLINE_ void 323static _INLINE_ void
275serial_out(struct uart_8250_port *up, int offset, int value) 324serial_out(struct uart_8250_port *up, int offset, int value)
276{ 325{
277 offset <<= up->port.regshift; 326 offset = map_8250_out_reg(up, offset) << up->port.regshift;
278 327
279 switch (up->port.iotype) { 328 switch (up->port.iotype) {
280 case UPIO_HUB6: 329 case UPIO_HUB6:
@@ -290,6 +339,12 @@ serial_out(struct uart_8250_port *up, int offset, int value)
290 writel(value, up->port.membase + offset); 339 writel(value, up->port.membase + offset);
291 break; 340 break;
292 341
342#ifdef CONFIG_SERIAL_8250_AU1X00
343 case UPIO_AU:
344 __raw_writel(value, up->port.membase + offset);
345 break;
346#endif
347
293 default: 348 default:
294 outb(value, up->port.iobase + offset); 349 outb(value, up->port.iobase + offset);
295 } 350 }
@@ -910,6 +965,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
910 } 965 }
911 } 966 }
912#endif 967#endif
968
969#ifdef CONFIG_SERIAL_8250_AU1X00
970 /* if access method is AU, it is a 16550 with a quirk */
971 if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
972 up->bugs |= UART_BUG_NOMSR;
973#endif
974
913 serial_outp(up, UART_LCR, save_lcr); 975 serial_outp(up, UART_LCR, save_lcr);
914 976
915 if (up->capabilities != uart_config[up->port.type].flags) { 977 if (up->capabilities != uart_config[up->port.type].flags) {
@@ -1057,6 +1119,10 @@ static void serial8250_enable_ms(struct uart_port *port)
1057{ 1119{
1058 struct uart_8250_port *up = (struct uart_8250_port *)port; 1120 struct uart_8250_port *up = (struct uart_8250_port *)port;
1059 1121
1122 /* no MSR capabilities */
1123 if (up->bugs & UART_BUG_NOMSR)
1124 return;
1125
1060 up->ier |= UART_IER_MSI; 1126 up->ier |= UART_IER_MSI;
1061 serial_out(up, UART_IER, up->ier); 1127 serial_out(up, UART_IER, up->ier);
1062} 1128}
@@ -1774,7 +1840,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
1774 * CTS flow control flag and modem status interrupts 1840 * CTS flow control flag and modem status interrupts
1775 */ 1841 */
1776 up->ier &= ~UART_IER_MSI; 1842 up->ier &= ~UART_IER_MSI;
1777 if (UART_ENABLE_MS(&up->port, termios->c_cflag)) 1843 if (!(up->bugs & UART_BUG_NOMSR) &&
1844 UART_ENABLE_MS(&up->port, termios->c_cflag))
1778 up->ier |= UART_IER_MSI; 1845 up->ier |= UART_IER_MSI;
1779 if (up->capabilities & UART_CAP_UUE) 1846 if (up->capabilities & UART_CAP_UUE)
1780 up->ier |= UART_IER_UUE | UART_IER_RTOIE; 1847 up->ier |= UART_IER_UUE | UART_IER_RTOIE;
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index b1b459efda52..a607b98016db 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -49,6 +49,7 @@ struct serial8250_config {
49 49
50#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ 50#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
51#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ 51#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
52#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
52 53
53#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) 54#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
54#define _INLINE_ inline 55#define _INLINE_ inline
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
new file mode 100644
index 000000000000..06ae8fbcc947
--- /dev/null
+++ b/drivers/serial/8250_au1x00.c
@@ -0,0 +1,102 @@
1/*
2 * Serial Device Initialisation for Au1x00
3 *
4 * (C) Copyright Embedded Alley Solutions, Inc 2005
5 * Author: Pantelis Antoniou <pantelis@embeddedalley.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/errno.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/ioport.h>
17#include <linux/module.h>
18#include <linux/serial_core.h>
19#include <linux/signal.h>
20#include <linux/slab.h>
21#include <linux/types.h>
22
23#include <linux/serial_8250.h>
24
25#include <asm/mach-au1x00/au1000.h>
26
27#include "8250.h"
28
29#define PORT(_base, _irq) \
30 { \
31 .iobase = _base, \
32 .membase = (void __iomem *)_base,\
33 .mapbase = _base, \
34 .irq = _irq, \
35 .uartclk = 0, /* filled */ \
36 .regshift = 2, \
37 .iotype = UPIO_AU, \
38 .flags = UPF_SKIP_TEST | \
39 UPF_IOREMAP, \
40 }
41
42static struct plat_serial8250_port au1x00_data[] = {
43#if defined(CONFIG_SOC_AU1000)
44 PORT(UART0_ADDR, AU1000_UART0_INT),
45 PORT(UART1_ADDR, AU1000_UART1_INT),
46 PORT(UART2_ADDR, AU1000_UART2_INT),
47 PORT(UART3_ADDR, AU1000_UART3_INT),
48#elif defined(CONFIG_SOC_AU1500)
49 PORT(UART0_ADDR, AU1500_UART0_INT),
50 PORT(UART3_ADDR, AU1500_UART3_INT),
51#elif defined(CONFIG_SOC_AU1100)
52 PORT(UART0_ADDR, AU1100_UART0_INT),
53 PORT(UART1_ADDR, AU1100_UART1_INT),
54 PORT(UART2_ADDR, AU1100_UART2_INT),
55 PORT(UART3_ADDR, AU1100_UART3_INT),
56#elif defined(CONFIG_SOC_AU1550)
57 PORT(UART0_ADDR, AU1550_UART0_INT),
58 PORT(UART1_ADDR, AU1550_UART1_INT),
59 PORT(UART2_ADDR, AU1550_UART2_INT),
60 PORT(UART3_ADDR, AU1550_UART3_INT),
61#elif defined(CONFIG_SOC_AU1200)
62 PORT(UART0_ADDR, AU1200_UART0_INT),
63 PORT(UART1_ADDR, AU1200_UART1_INT),
64#endif
65 { },
66};
67
68static struct platform_device au1x00_device = {
69 .name = "serial8250",
70 .id = PLAT8250_DEV_AU1X00,
71 .dev = {
72 .platform_data = au1x00_data,
73 },
74};
75
76static int __init au1x00_init(void)
77{
78 int i;
79 unsigned int uartclk;
80
81 /* get uart clock */
82 uartclk = get_au1x00_uart_baud_base() * 16;
83
84 /* fill up uartclk */
85 for (i = 0; au1x00_data[i].flags ; i++)
86 au1x00_data[i].uartclk = uartclk;
87
88 return platform_device_register(&au1x00_device);
89}
90
91/* XXX: Yes, I know this doesn't yet work. */
92static void __exit au1x00_exit(void)
93{
94 platform_device_unregister(&au1x00_device);
95}
96
97module_init(au1x00_init);
98module_exit(au1x00_exit);
99
100MODULE_AUTHOR("Pantelis Antoniou <pantelis@embeddedalley.com>");
101MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards");
102MODULE_LICENSE("GPL");
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b745a1b9e835..ff36f0c9fdad 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -207,6 +207,14 @@ config SERIAL_8250_ACORN
207 system, say Y to this option. The driver can handle 1, 2, or 3 port 207 system, say Y to this option. The driver can handle 1, 2, or 3 port
208 cards. If unsure, say N. 208 cards. If unsure, say N.
209 209
210config SERIAL_8250_AU1X00
211 bool "AU1X00 serial port support"
212 depends on SERIAL_8250 != n && SOC_AU1X00
213 help
214 If you have an Au1x00 board and want to use the serial port, say Y
215 to this option. The driver can handle 1 or 2 serial ports.
216 If unsure, say N.
217
210comment "Non-8250 serial port support" 218comment "Non-8250 serial port support"
211 219
212config SERIAL_AMBA_PL010 220config SERIAL_AMBA_PL010
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 11c7dc483f93..d7c7c7180e33 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
22obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o 22obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
23obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o 23obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
24obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o 24obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
25obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o
25obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o 26obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
26obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o 27obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
27obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o 28obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 0745ce782974..427a23858076 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)
1959 break; 1959 break;
1960 case UPIO_MEM: 1960 case UPIO_MEM:
1961 case UPIO_MEM32: 1961 case UPIO_MEM32:
1962 case UPIO_AU:
1962 snprintf(address, sizeof(address), 1963 snprintf(address, sizeof(address),
1963 "MMIO 0x%lx", port->mapbase); 1964 "MMIO 0x%lx", port->mapbase);
1964 break; 1965 break;