aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2010-02-18 03:59:06 -0500
committerTony Lindgren <tony@atomide.com>2010-02-23 13:57:40 -0500
commite03d37d85909fd9b09e78087c57b45972a7664ad (patch)
tree9c026405e45ee7597eb45c1d596d39952c3888c3 /arch
parentae46ec77311b550be992339c1e01fc20bc65296e (diff)
omap3/4: uart: fix full-fifo write abort
This patch is addition to the already merged commit on non-empty uart fifo read abort. "ce13d4716a276f4331d78ba28a5093a63822ab95" OMAP3630 and OMAP4430 UART IP blocks have a restriction on TX FIFO too. If you try to write to the tx fifo when it is full, the system aborts. More details on this thread are here: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg19447.html This can be easily reproducible by not suppressing interconnect errors or long duration testing where continuous prints over console from multiple threads. This patch is addressing the issue by ensuring that write is not issued while fifo is full. A timeout is added to avoid any hang on fifo-full for 10 mS which is unlikely case. Patch is validated on OMAP3630 and OMAP4 SDP. V2 version removed the additional 1 uS on every TX as per Tony's suggestion Signed-off-by: Woodruff Richard <r-woodruff2@ti.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> CC: Ghorai Sukumar <s-ghorai@ti.com> Reviewed-by: Paul Walmsley <paul@pwsan.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/serial.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 5f3035ec0d6f..b79bc8926cc9 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -23,6 +23,7 @@
23#include <linux/serial_reg.h> 23#include <linux/serial_reg.h>
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/delay.h>
26 27
27#include <plat/common.h> 28#include <plat/common.h>
28#include <plat/board.h> 29#include <plat/board.h>
@@ -160,6 +161,13 @@ static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
160 return (unsigned int)__raw_readb(up->membase + offset); 161 return (unsigned int)__raw_readb(up->membase + offset);
161} 162}
162 163
164static inline void __serial_write_reg(struct uart_port *up, int offset,
165 int value)
166{
167 offset <<= up->regshift;
168 __raw_writeb(value, up->membase + offset);
169}
170
163static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, 171static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
164 int value) 172 int value)
165{ 173{
@@ -620,6 +628,20 @@ static unsigned int serial_in_override(struct uart_port *up, int offset)
620 return __serial_read_reg(up, offset); 628 return __serial_read_reg(up, offset);
621} 629}
622 630
631static void serial_out_override(struct uart_port *up, int offset, int value)
632{
633 unsigned int status, tmout = 10000;
634
635 status = __serial_read_reg(up, UART_LSR);
636 while (!(status & UART_LSR_THRE)) {
637 /* Wait up to 10ms for the character(s) to be sent. */
638 if (--tmout == 0)
639 break;
640 udelay(1);
641 status = __serial_read_reg(up, UART_LSR);
642 }
643 __serial_write_reg(up, offset, value);
644}
623void __init omap_serial_early_init(void) 645void __init omap_serial_early_init(void)
624{ 646{
625 int i; 647 int i;
@@ -721,11 +743,14 @@ void __init omap_serial_init_port(int port)
721 * omap3xxx: Never read empty UART fifo on UARTs 743 * omap3xxx: Never read empty UART fifo on UARTs
722 * with IP rev >=0x52 744 * with IP rev >=0x52
723 */ 745 */
724 if (cpu_is_omap44xx()) 746 if (cpu_is_omap44xx()) {
725 uart->p->serial_in = serial_in_override; 747 uart->p->serial_in = serial_in_override;
726 else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) 748 uart->p->serial_out = serial_out_override;
727 >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) 749 } else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF)
750 >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) {
728 uart->p->serial_in = serial_in_override; 751 uart->p->serial_in = serial_in_override;
752 uart->p->serial_out = serial_out_override;
753 }
729} 754}
730 755
731/** 756/**