diff options
author | Magnus Damm <damm@opensource.se> | 2012-05-02 08:46:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-02 17:04:40 -0400 |
commit | cc419fa0d38c425e4ea7bffeed931b07b0a3e461 (patch) | |
tree | 75a6c82980c7aa761e265b9ab7c3788fd77fa24d /drivers/tty/serial | |
parent | f9a9111b540fd67db5dab332f4b83d86c90e27b1 (diff) |
serial8250: Add dl_read()/dl_write() callbacks
Convert serial_dl_read() and serial_dl_write() from macro
to 8250 specific callbacks. This change makes it easier to
support 8250 hardware with non-standard DLL and DLM register
configurations such as Alchemy, RM9K and upcoming Emma Mobile
UART hardware.
Signed-off-by: Magnus Damm <damm@opensource.se>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r-- | drivers/tty/serial/8250/8250.c | 117 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250.h | 14 |
2 files changed, 78 insertions, 53 deletions
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index c9ac4eabe35a..590ee85150bf 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c | |||
@@ -284,6 +284,66 @@ static const struct serial8250_config uart_config[] = { | |||
284 | }, | 284 | }, |
285 | }; | 285 | }; |
286 | 286 | ||
287 | /* Uart divisor latch read */ | ||
288 | static int default_dl_read(struct uart_8250_port *up) | ||
289 | { | ||
290 | return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; | ||
291 | } | ||
292 | |||
293 | /* Uart divisor latch write */ | ||
294 | static void default_dl_write(struct uart_8250_port *up, int value) | ||
295 | { | ||
296 | serial_out(up, UART_DLL, value & 0xff); | ||
297 | serial_out(up, UART_DLM, value >> 8 & 0xff); | ||
298 | } | ||
299 | |||
300 | #if defined(CONFIG_MIPS_ALCHEMY) | ||
301 | /* Au1x00 haven't got a standard divisor latch */ | ||
302 | static int _serial_dl_read(struct uart_8250_port *up) | ||
303 | { | ||
304 | if (up->port.iotype == UPIO_AU) | ||
305 | return __raw_readl(up->port.membase + 0x28); | ||
306 | else | ||
307 | return default_dl_read(up); | ||
308 | } | ||
309 | |||
310 | static void _serial_dl_write(struct uart_8250_port *up, int value) | ||
311 | { | ||
312 | if (up->port.iotype == UPIO_AU) | ||
313 | __raw_writel(value, up->port.membase + 0x28); | ||
314 | else | ||
315 | default_dl_write(up, value); | ||
316 | } | ||
317 | #elif defined(CONFIG_SERIAL_8250_RM9K) | ||
318 | static int _serial_dl_read(struct uart_8250_port *up) | ||
319 | { | ||
320 | return (up->port.iotype == UPIO_RM9000) ? | ||
321 | (((__raw_readl(up->port.membase + 0x10) << 8) | | ||
322 | (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) : | ||
323 | default_dl_read(up); | ||
324 | } | ||
325 | |||
326 | static void _serial_dl_write(struct uart_8250_port *up, int value) | ||
327 | { | ||
328 | if (up->port.iotype == UPIO_RM9000) { | ||
329 | __raw_writel(value, up->port.membase + 0x08); | ||
330 | __raw_writel(value >> 8, up->port.membase + 0x10); | ||
331 | } else { | ||
332 | default_dl_write(up, value); | ||
333 | } | ||
334 | } | ||
335 | #else | ||
336 | static int _serial_dl_read(struct uart_8250_port *up) | ||
337 | { | ||
338 | return default_dl_read(up); | ||
339 | } | ||
340 | |||
341 | static void _serial_dl_write(struct uart_8250_port *up, int value) | ||
342 | { | ||
343 | default_dl_write(up, value); | ||
344 | } | ||
345 | #endif | ||
346 | |||
287 | #if defined(CONFIG_MIPS_ALCHEMY) | 347 | #if defined(CONFIG_MIPS_ALCHEMY) |
288 | 348 | ||
289 | /* Au1x00 UART hardware has a weird register layout */ | 349 | /* Au1x00 UART hardware has a weird register layout */ |
@@ -434,6 +494,10 @@ static void set_io_from_upio(struct uart_port *p) | |||
434 | { | 494 | { |
435 | struct uart_8250_port *up = | 495 | struct uart_8250_port *up = |
436 | container_of(p, struct uart_8250_port, port); | 496 | container_of(p, struct uart_8250_port, port); |
497 | |||
498 | up->dl_read = _serial_dl_read; | ||
499 | up->dl_write = _serial_dl_write; | ||
500 | |||
437 | switch (p->iotype) { | 501 | switch (p->iotype) { |
438 | case UPIO_HUB6: | 502 | case UPIO_HUB6: |
439 | p->serial_in = hub6_serial_in; | 503 | p->serial_in = hub6_serial_in; |
@@ -481,59 +545,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) | |||
481 | } | 545 | } |
482 | } | 546 | } |
483 | 547 | ||
484 | /* Uart divisor latch read */ | ||
485 | static inline int _serial_dl_read(struct uart_8250_port *up) | ||
486 | { | ||
487 | return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; | ||
488 | } | ||
489 | |||
490 | /* Uart divisor latch write */ | ||
491 | static inline void _serial_dl_write(struct uart_8250_port *up, int value) | ||
492 | { | ||
493 | serial_out(up, UART_DLL, value & 0xff); | ||
494 | serial_out(up, UART_DLM, value >> 8 & 0xff); | ||
495 | } | ||
496 | |||
497 | #if defined(CONFIG_MIPS_ALCHEMY) | ||
498 | /* Au1x00 haven't got a standard divisor latch */ | ||
499 | static int serial_dl_read(struct uart_8250_port *up) | ||
500 | { | ||
501 | if (up->port.iotype == UPIO_AU) | ||
502 | return __raw_readl(up->port.membase + 0x28); | ||
503 | else | ||
504 | return _serial_dl_read(up); | ||
505 | } | ||
506 | |||
507 | static void serial_dl_write(struct uart_8250_port *up, int value) | ||
508 | { | ||
509 | if (up->port.iotype == UPIO_AU) | ||
510 | __raw_writel(value, up->port.membase + 0x28); | ||
511 | else | ||
512 | _serial_dl_write(up, value); | ||
513 | } | ||
514 | #elif defined(CONFIG_SERIAL_8250_RM9K) | ||
515 | static int serial_dl_read(struct uart_8250_port *up) | ||
516 | { | ||
517 | return (up->port.iotype == UPIO_RM9000) ? | ||
518 | (((__raw_readl(up->port.membase + 0x10) << 8) | | ||
519 | (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) : | ||
520 | _serial_dl_read(up); | ||
521 | } | ||
522 | |||
523 | static void serial_dl_write(struct uart_8250_port *up, int value) | ||
524 | { | ||
525 | if (up->port.iotype == UPIO_RM9000) { | ||
526 | __raw_writel(value, up->port.membase + 0x08); | ||
527 | __raw_writel(value >> 8, up->port.membase + 0x10); | ||
528 | } else { | ||
529 | _serial_dl_write(up, value); | ||
530 | } | ||
531 | } | ||
532 | #else | ||
533 | #define serial_dl_read(up) _serial_dl_read(up) | ||
534 | #define serial_dl_write(up, value) _serial_dl_write(up, value) | ||
535 | #endif | ||
536 | |||
537 | /* | 548 | /* |
538 | * For the 16C950 | 549 | * For the 16C950 |
539 | */ | 550 | */ |
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index c9d0ebe952fc..f9719d167c8d 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h | |||
@@ -37,6 +37,10 @@ struct uart_8250_port { | |||
37 | unsigned char lsr_saved_flags; | 37 | unsigned char lsr_saved_flags; |
38 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | 38 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA |
39 | unsigned char msr_saved_flags; | 39 | unsigned char msr_saved_flags; |
40 | |||
41 | /* 8250 specific callbacks */ | ||
42 | int (*dl_read)(struct uart_8250_port *); | ||
43 | void (*dl_write)(struct uart_8250_port *, int); | ||
40 | }; | 44 | }; |
41 | 45 | ||
42 | struct old_serial_port { | 46 | struct old_serial_port { |
@@ -98,6 +102,16 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) | |||
98 | 102 | ||
99 | void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); | 103 | void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); |
100 | 104 | ||
105 | static inline int serial_dl_read(struct uart_8250_port *up) | ||
106 | { | ||
107 | return up->dl_read(up); | ||
108 | } | ||
109 | |||
110 | static inline void serial_dl_write(struct uart_8250_port *up, int value) | ||
111 | { | ||
112 | up->dl_write(up, value); | ||
113 | } | ||
114 | |||
101 | #if defined(__alpha__) && !defined(CONFIG_PCI) | 115 | #if defined(__alpha__) && !defined(CONFIG_PCI) |
102 | /* | 116 | /* |
103 | * Digital did something really horribly wrong with the OUT1 and OUT2 | 117 | * Digital did something really horribly wrong with the OUT1 and OUT2 |