diff options
author | Thomas Koeller <thomas.koeller@baslerweb.com> | 2007-05-06 17:48:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-07 15:12:50 -0400 |
commit | bd71c182d5a02337305fc381831c11029dd17d64 (patch) | |
tree | 0b21234a7d1c38bfcafc12b6dcbfb3455d73b587 | |
parent | beab697ab4b2962e3d741b476abe443baad0933d (diff) |
RM9000 serial driver
Add support for the integrated serial ports of the MIPS RM9122 processor
and its relatives.
The patch also does some whitespace cleanup.
[akpm@linux-foundation.org: cleanups]
Signed-off-by: Thomas Koeller <thomas.koeller@baslerweb.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/mips/Kconfig | 3 | ||||
-rw-r--r-- | drivers/serial/8250.c | 92 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 9 | ||||
-rw-r--r-- | include/linux/serial_core.h | 4 |
4 files changed, 95 insertions, 13 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 130d825e5438..7441a2cf523e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -1042,6 +1042,9 @@ config SOC_AU1X00 | |||
1042 | select SYS_SUPPORTS_APM_EMULATION | 1042 | select SYS_SUPPORTS_APM_EMULATION |
1043 | select SYS_SUPPORTS_KGDB | 1043 | select SYS_SUPPORTS_KGDB |
1044 | 1044 | ||
1045 | config SERIAL_RM9000 | ||
1046 | bool | ||
1047 | |||
1045 | config PNX8550 | 1048 | config PNX8550 |
1046 | bool | 1049 | bool |
1047 | select SOC_PNX8550 | 1050 | select SOC_PNX8550 |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 194362d9f5a3..c9832d963f1e 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -251,9 +251,16 @@ static const struct serial8250_config uart_config[] = { | |||
251 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 251 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
252 | .flags = UART_CAP_FIFO | UART_CAP_UUE, | 252 | .flags = UART_CAP_FIFO | UART_CAP_UUE, |
253 | }, | 253 | }, |
254 | [PORT_RM9000] = { | ||
255 | .name = "RM9000", | ||
256 | .fifo_size = 16, | ||
257 | .tx_loadsz = 16, | ||
258 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
259 | .flags = UART_CAP_FIFO, | ||
260 | }, | ||
254 | }; | 261 | }; |
255 | 262 | ||
256 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 263 | #if defined (CONFIG_SERIAL_8250_AU1X00) |
257 | 264 | ||
258 | /* Au1x00 UART hardware has a weird register layout */ | 265 | /* Au1x00 UART hardware has a weird register layout */ |
259 | static const u8 au_io_in_map[] = { | 266 | static const u8 au_io_in_map[] = { |
@@ -289,6 +296,44 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | |||
289 | return au_io_out_map[offset]; | 296 | return au_io_out_map[offset]; |
290 | } | 297 | } |
291 | 298 | ||
299 | #elif defined (CONFIG_SERIAL_8250_RM9K) | ||
300 | |||
301 | static const u8 | ||
302 | regmap_in[8] = { | ||
303 | [UART_RX] = 0x00, | ||
304 | [UART_IER] = 0x0c, | ||
305 | [UART_IIR] = 0x14, | ||
306 | [UART_LCR] = 0x1c, | ||
307 | [UART_MCR] = 0x20, | ||
308 | [UART_LSR] = 0x24, | ||
309 | [UART_MSR] = 0x28, | ||
310 | [UART_SCR] = 0x2c | ||
311 | }, | ||
312 | regmap_out[8] = { | ||
313 | [UART_TX] = 0x04, | ||
314 | [UART_IER] = 0x0c, | ||
315 | [UART_FCR] = 0x18, | ||
316 | [UART_LCR] = 0x1c, | ||
317 | [UART_MCR] = 0x20, | ||
318 | [UART_LSR] = 0x24, | ||
319 | [UART_MSR] = 0x28, | ||
320 | [UART_SCR] = 0x2c | ||
321 | }; | ||
322 | |||
323 | static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) | ||
324 | { | ||
325 | if (up->port.iotype != UPIO_RM9000) | ||
326 | return offset; | ||
327 | return regmap_in[offset]; | ||
328 | } | ||
329 | |||
330 | static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | ||
331 | { | ||
332 | if (up->port.iotype != UPIO_RM9000) | ||
333 | return offset; | ||
334 | return regmap_out[offset]; | ||
335 | } | ||
336 | |||
292 | #else | 337 | #else |
293 | 338 | ||
294 | /* sane hardware needs no mapping */ | 339 | /* sane hardware needs no mapping */ |
@@ -311,6 +356,7 @@ static unsigned int serial_in(struct uart_8250_port *up, int offset) | |||
311 | case UPIO_DWAPB: | 356 | case UPIO_DWAPB: |
312 | return readb(up->port.membase + offset); | 357 | return readb(up->port.membase + offset); |
313 | 358 | ||
359 | case UPIO_RM9000: | ||
314 | case UPIO_MEM32: | 360 | case UPIO_MEM32: |
315 | return readl(up->port.membase + offset); | 361 | return readl(up->port.membase + offset); |
316 | 362 | ||
@@ -348,6 +394,7 @@ serial_out(struct uart_8250_port *up, int offset, int value) | |||
348 | writeb(value, up->port.membase + offset); | 394 | writeb(value, up->port.membase + offset); |
349 | break; | 395 | break; |
350 | 396 | ||
397 | case UPIO_RM9000: | ||
351 | case UPIO_MEM32: | 398 | case UPIO_MEM32: |
352 | writel(value, up->port.membase + offset); | 399 | writel(value, up->port.membase + offset); |
353 | break; | 400 | break; |
@@ -419,7 +466,7 @@ static inline void _serial_dl_write(struct uart_8250_port *up, int value) | |||
419 | serial_outp(up, UART_DLM, value >> 8 & 0xff); | 466 | serial_outp(up, UART_DLM, value >> 8 & 0xff); |
420 | } | 467 | } |
421 | 468 | ||
422 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 469 | #if defined (CONFIG_SERIAL_8250_AU1X00) |
423 | /* Au1x00 haven't got a standard divisor latch */ | 470 | /* Au1x00 haven't got a standard divisor latch */ |
424 | static int serial_dl_read(struct uart_8250_port *up) | 471 | static int serial_dl_read(struct uart_8250_port *up) |
425 | { | 472 | { |
@@ -436,6 +483,24 @@ static void serial_dl_write(struct uart_8250_port *up, int value) | |||
436 | else | 483 | else |
437 | _serial_dl_write(up, value); | 484 | _serial_dl_write(up, value); |
438 | } | 485 | } |
486 | #elif defined (CONFIG_SERIAL_8250_RM9K) | ||
487 | static int serial_dl_read(struct uart_8250_port *up) | ||
488 | { | ||
489 | return (up->port.iotype == UPIO_RM9000) ? | ||
490 | (((__raw_readl(up->port.membase + 0x10) << 8) | | ||
491 | (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) : | ||
492 | _serial_dl_read(up); | ||
493 | } | ||
494 | |||
495 | static void serial_dl_write(struct uart_8250_port *up, int value) | ||
496 | { | ||
497 | if (up->port.iotype == UPIO_RM9000) { | ||
498 | __raw_writel(value, up->port.membase + 0x08); | ||
499 | __raw_writel(value >> 8, up->port.membase + 0x10); | ||
500 | } else { | ||
501 | _serial_dl_write(up, value); | ||
502 | } | ||
503 | } | ||
439 | #else | 504 | #else |
440 | #define serial_dl_read(up) _serial_dl_read(up) | 505 | #define serial_dl_read(up) _serial_dl_read(up) |
441 | #define serial_dl_write(up, value) _serial_dl_write(up, value) | 506 | #define serial_dl_write(up, value) _serial_dl_write(up, value) |
@@ -637,7 +702,7 @@ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) | |||
637 | * its clones. (We treat the broken original StarTech 16650 V1 as a | 702 | * its clones. (We treat the broken original StarTech 16650 V1 as a |
638 | * 16550, and why not? Startech doesn't seem to even acknowledge its | 703 | * 16550, and why not? Startech doesn't seem to even acknowledge its |
639 | * existence.) | 704 | * existence.) |
640 | * | 705 | * |
641 | * What evil have men's minds wrought... | 706 | * What evil have men's minds wrought... |
642 | */ | 707 | */ |
643 | static void autoconfig_has_efr(struct uart_8250_port *up) | 708 | static void autoconfig_has_efr(struct uart_8250_port *up) |
@@ -690,7 +755,7 @@ static void autoconfig_has_efr(struct uart_8250_port *up) | |||
690 | up->bugs |= UART_BUG_QUOT; | 755 | up->bugs |= UART_BUG_QUOT; |
691 | return; | 756 | return; |
692 | } | 757 | } |
693 | 758 | ||
694 | /* | 759 | /* |
695 | * We check for a XR16C850 by setting DLL and DLM to 0, and then | 760 | * We check for a XR16C850 by setting DLL and DLM to 0, and then |
696 | * reading back DLL and DLM. The chip type depends on the DLM | 761 | * reading back DLL and DLM. The chip type depends on the DLM |
@@ -833,7 +898,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
833 | status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | 898 | status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ |
834 | status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ | 899 | status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ |
835 | serial_outp(up, 0x04, status1); | 900 | serial_outp(up, 0x04, status1); |
836 | 901 | ||
837 | serial_dl_write(up, quot); | 902 | serial_dl_write(up, quot); |
838 | 903 | ||
839 | serial_outp(up, UART_LCR, 0); | 904 | serial_outp(up, UART_LCR, 0); |
@@ -938,7 +1003,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
938 | /* | 1003 | /* |
939 | * Do a simple existence test first; if we fail this, | 1004 | * Do a simple existence test first; if we fail this, |
940 | * there's no point trying anything else. | 1005 | * there's no point trying anything else. |
941 | * | 1006 | * |
942 | * 0x80 is used as a nonsense port to prevent against | 1007 | * 0x80 is used as a nonsense port to prevent against |
943 | * false positives due to ISA bus float. The | 1008 | * false positives due to ISA bus float. The |
944 | * assumption is that 0x80 is a non-existent port; | 1009 | * assumption is that 0x80 is a non-existent port; |
@@ -977,7 +1042,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
977 | save_mcr = serial_in(up, UART_MCR); | 1042 | save_mcr = serial_in(up, UART_MCR); |
978 | save_lcr = serial_in(up, UART_LCR); | 1043 | save_lcr = serial_in(up, UART_LCR); |
979 | 1044 | ||
980 | /* | 1045 | /* |
981 | * Check to see if a UART is really there. Certain broken | 1046 | * Check to see if a UART is really there. Certain broken |
982 | * internal modems based on the Rockwell chipset fail this | 1047 | * internal modems based on the Rockwell chipset fail this |
983 | * test, because they apparently don't implement the loopback | 1048 | * test, because they apparently don't implement the loopback |
@@ -1084,7 +1149,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
1084 | else | 1149 | else |
1085 | serial_outp(up, UART_IER, 0); | 1150 | serial_outp(up, UART_IER, 0); |
1086 | 1151 | ||
1087 | out: | 1152 | out: |
1088 | spin_unlock_irqrestore(&up->port.lock, flags); | 1153 | spin_unlock_irqrestore(&up->port.lock, flags); |
1089 | // restore_flags(flags); | 1154 | // restore_flags(flags); |
1090 | DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); | 1155 | DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); |
@@ -1110,7 +1175,7 @@ static void autoconfig_irq(struct uart_8250_port *up) | |||
1110 | save_mcr = serial_inp(up, UART_MCR); | 1175 | save_mcr = serial_inp(up, UART_MCR); |
1111 | save_ier = serial_inp(up, UART_IER); | 1176 | save_ier = serial_inp(up, UART_IER); |
1112 | serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); | 1177 | serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); |
1113 | 1178 | ||
1114 | irqs = probe_irq_on(); | 1179 | irqs = probe_irq_on(); |
1115 | serial_outp(up, UART_MCR, 0); | 1180 | serial_outp(up, UART_MCR, 0); |
1116 | udelay (10); | 1181 | udelay (10); |
@@ -1175,8 +1240,11 @@ static void serial8250_start_tx(struct uart_port *port) | |||
1175 | if (up->bugs & UART_BUG_TXEN) { | 1240 | if (up->bugs & UART_BUG_TXEN) { |
1176 | unsigned char lsr, iir; | 1241 | unsigned char lsr, iir; |
1177 | lsr = serial_in(up, UART_LSR); | 1242 | lsr = serial_in(up, UART_LSR); |
1178 | iir = serial_in(up, UART_IIR); | 1243 | iir = serial_in(up, UART_IIR) & 0x0f; |
1179 | if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) | 1244 | if ((up->port.type == PORT_RM9000) ? |
1245 | (lsr & UART_LSR_THRE && | ||
1246 | (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : | ||
1247 | (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) | ||
1180 | transmit_chars(up); | 1248 | transmit_chars(up); |
1181 | } | 1249 | } |
1182 | } | 1250 | } |
@@ -1957,7 +2025,7 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1957 | /* | 2025 | /* |
1958 | * Ask the core to calculate the divisor for us. | 2026 | * Ask the core to calculate the divisor for us. |
1959 | */ | 2027 | */ |
1960 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | 2028 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
1961 | quot = serial8250_get_divisor(port, baud); | 2029 | quot = serial8250_get_divisor(port, baud); |
1962 | 2030 | ||
1963 | /* | 2031 | /* |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ad9f321968e1..e9d927e3b8e6 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -254,6 +254,15 @@ config SERIAL_8250_AU1X00 | |||
254 | to this option. The driver can handle 1 or 2 serial ports. | 254 | to this option. The driver can handle 1 or 2 serial ports. |
255 | If unsure, say N. | 255 | If unsure, say N. |
256 | 256 | ||
257 | config SERIAL_8250_RM9K | ||
258 | bool "Support for MIPS RM9xxx integrated serial port" | ||
259 | depends on SERIAL_8250 != n && SERIAL_RM9000 | ||
260 | select SERIAL_8250_SHARE_IRQ | ||
261 | help | ||
262 | Selecting this option will add support for the integrated serial | ||
263 | port hardware found on MIPS RM9122 and similar processors. | ||
264 | If unsure, say N. | ||
265 | |||
257 | comment "Non-8250 serial port support" | 266 | comment "Non-8250 serial port support" |
258 | 267 | ||
259 | config SERIAL_AMBA_PL010 | 268 | config SERIAL_AMBA_PL010 |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 8b5592e6aca4..d242c731491f 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -39,7 +39,8 @@ | |||
39 | #define PORT_RSA 13 | 39 | #define PORT_RSA 13 |
40 | #define PORT_NS16550A 14 | 40 | #define PORT_NS16550A 14 |
41 | #define PORT_XSCALE 15 | 41 | #define PORT_XSCALE 15 |
42 | #define PORT_MAX_8250 15 /* max port ID */ | 42 | #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ |
43 | #define PORT_MAX_8250 16 /* max port ID */ | ||
43 | 44 | ||
44 | /* | 45 | /* |
45 | * ARM specific type numbers. These are not currently guaranteed | 46 | * ARM specific type numbers. These are not currently guaranteed |
@@ -231,6 +232,7 @@ struct uart_port { | |||
231 | #define UPIO_AU (4) /* Au1x00 type IO */ | 232 | #define UPIO_AU (4) /* Au1x00 type IO */ |
232 | #define UPIO_TSI (5) /* Tsi108/109 type IO */ | 233 | #define UPIO_TSI (5) /* Tsi108/109 type IO */ |
233 | #define UPIO_DWAPB (6) /* DesignWare APB UART */ | 234 | #define UPIO_DWAPB (6) /* DesignWare APB UART */ |
235 | #define UPIO_RM9000 (7) /* RM9000 type IO */ | ||
234 | 236 | ||
235 | unsigned int read_status_mask; /* driver specific */ | 237 | unsigned int read_status_mask; /* driver specific */ |
236 | unsigned int ignore_status_mask; /* driver specific */ | 238 | unsigned int ignore_status_mask; /* driver specific */ |