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 | |
| 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>
| -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 | /** |
