aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/serial.c
diff options
context:
space:
mode:
authorvikram pandita <vikram.pandita@ti.com>2009-12-11 19:16:37 -0500
committerTony Lindgren <tony@atomide.com>2009-12-11 19:16:37 -0500
commitce13d4716a276f4331d78ba28a5093a63822ab95 (patch)
tree0537f1349cae8f963eea5c0da7d5cfa4e738149d /arch/arm/mach-omap2/serial.c
parented32350dc5ccc2b00685d857c3270688d465cd41 (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.c36
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 */
582static 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
575void __init omap_serial_early_init(void) 593void __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/**