diff options
author | vikram pandita <vikram.pandita@ti.com> | 2009-12-11 19:16:37 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2009-12-11 19:16:37 -0500 |
commit | ce13d4716a276f4331d78ba28a5093a63822ab95 (patch) | |
tree | 0537f1349cae8f963eea5c0da7d5cfa4e738149d /arch/arm/mach-omap2/serial.c | |
parent | ed32350dc5ccc2b00685d857c3270688d465cd41 (diff) |
omap: serial: fix non-empty uart fifo read abort
OMAP3xxx and OMAP4430 UART IP blocks have a restriction wrt RX FIFO.
Empty RX fifo read causes an abort.
OMAP3xxx:
UART IP revision >= 0x52 have this issue
MVR register format is:
Bits Field Name Description Type Reset
31:8 RESERVED RO 0x0
7:4 MAJOR Major revision number of the module. RO 0x--
3:0 MINOR Minor revision number of the module. RO 0x--
OMAP4xxx:
All revisions have this issue
Revision id check is not used as the format of MVR resigster has changed
For omap4 MVR register reads as: 0x50410602 => Revision id = 0x0602
Format of MVR register on omap4 is: (Courtesy: Cousson, Benoit)
Bits Field Name Description Type Reset
31:30 SCHEME Scheme revision number of module RO 0x1
29:28 RESERVED RO 0x1
27:16 FUNC Function revision number of module RO 0x041
15:11 RTL Rtl revision number of module RO 0x00
10:8 MAJOR Major revision number of the module. RO 0x6
7:6 CUSTOM Custom revision number of the module. RO 0x0
5:0 MINOR Minor revision number of the module. RO 0x02
Override the default 8250 read handler: mem_serial_in()
by a custom handler: serial_in_8250()
which makes sure that RX fifo is not read when empty
tested on zoom3(3630) board
Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 6278fe585c05..39b797bc14d6 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "pm.h" | 33 | #include "pm.h" |
34 | #include "prm-regbits-34xx.h" | 34 | #include "prm-regbits-34xx.h" |
35 | 35 | ||
36 | #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 | ||
36 | #define UART_OMAP_WER 0x17 /* Wake-up enable register */ | 37 | #define UART_OMAP_WER 0x17 /* Wake-up enable register */ |
37 | 38 | ||
38 | #define DEFAULT_TIMEOUT (5 * HZ) | 39 | #define DEFAULT_TIMEOUT (5 * HZ) |
@@ -572,6 +573,23 @@ static struct omap_uart_state omap_uart[] = { | |||
572 | #endif | 573 | #endif |
573 | }; | 574 | }; |
574 | 575 | ||
576 | /* | ||
577 | * Override the default 8250 read handler: mem_serial_in() | ||
578 | * Empty RX fifo read causes an abort on omap3630 and omap4 | ||
579 | * This function makes sure that an empty rx fifo is not read on these silicons | ||
580 | * (OMAP1/2/3430 are not affected) | ||
581 | */ | ||
582 | static unsigned int serial_in_override(struct uart_port *up, int offset) | ||
583 | { | ||
584 | if (UART_RX == offset) { | ||
585 | unsigned int lsr; | ||
586 | lsr = serial_read_reg(omap_uart[up->line].p, UART_LSR); | ||
587 | if (!(lsr & UART_LSR_DR)) | ||
588 | return -EPERM; | ||
589 | } | ||
590 | return serial_read_reg(omap_uart[up->line].p, offset); | ||
591 | } | ||
592 | |||
575 | void __init omap_serial_early_init(void) | 593 | void __init omap_serial_early_init(void) |
576 | { | 594 | { |
577 | int i; | 595 | int i; |
@@ -667,15 +685,15 @@ void __init omap_serial_init_port(int port) | |||
667 | DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); | 685 | DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); |
668 | } | 686 | } |
669 | 687 | ||
670 | /* omap44xx: Never read empty UART fifo | 688 | /* omap44xx: Never read empty UART fifo |
671 | * omap3xxx: Never read empty UART fifo on UARTs | 689 | * omap3xxx: Never read empty UART fifo on UARTs |
672 | * with IP rev >=0x52 | 690 | * with IP rev >=0x52 |
673 | */ | 691 | */ |
674 | if (cpu_is_omap44xx()) | 692 | if (cpu_is_omap44xx()) |
675 | uart->p->serial_in = serial_in_override; | 693 | uart->p->serial_in = serial_in_override; |
676 | else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) | 694 | else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) |
677 | >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) | 695 | >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) |
678 | uart->p->serial_in = serial_in_override; | 696 | uart->p->serial_in = serial_in_override; |
679 | } | 697 | } |
680 | 698 | ||
681 | /** | 699 | /** |