aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/8250.c
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/serial/8250.c
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/serial/8250.c')
-rw-r--r--drivers/serial/8250.c73
1 files changed, 70 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;