aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGraf Yang <graf.yang@analog.com>2009-01-02 08:40:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 13:19:34 -0500
commit80d5c474b87da88eca8e1ab034e26daa9f688130 (patch)
treeadb114b756b95541cefaba89cff38180a074003b
parent52e15f0eae193a8e4ca31c1520179b8d65c79811 (diff)
Blackfin Serial Driver: fix bug - SIR driver stop receiving randomly
Bug description: The IRDA receiver may can't receiving any more after processed some signals. To duplicate this issue is put three IRDA devices together, one blackfin, two none blackfin, they will detect each other. Let one none blackfin devices irdaping the blackfin devices, when it stopped print out ping information, it is the time that blackfin stoped receiving, the time is random. The related register bit is OK, the other devices is sending data continuously. But no interrupt come. Fixing: I tried Michael's suggestion that request the UARTx error interrupt, and reset the IRDA when found FE error. This method helps much, but it can't completely avoid stop. Reset the IRDA before every time sending the data is more safe. Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/serial/bfin_5xx.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index d63fad7363b7..59a221f9ee9c 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -73,6 +73,8 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
73 73
74static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); 74static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
75 75
76static void bfin_serial_reset_irda(struct uart_port *port);
77
76/* 78/*
77 * interrupts are disabled on entry 79 * interrupts are disabled on entry
78 */ 80 */
@@ -105,6 +107,14 @@ static void bfin_serial_stop_tx(struct uart_port *port)
105static void bfin_serial_start_tx(struct uart_port *port) 107static void bfin_serial_start_tx(struct uart_port *port)
106{ 108{
107 struct bfin_serial_port *uart = (struct bfin_serial_port *)port; 109 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
110 struct tty_struct *tty = uart->port.info->port.tty;
111
112 /*
113 * To avoid losting RX interrupt, we reset IR function
114 * before sending data.
115 */
116 if (tty->termios->c_line == N_IRDA)
117 bfin_serial_reset_irda(port);
108 118
109#ifdef CONFIG_SERIAL_BFIN_DMA 119#ifdef CONFIG_SERIAL_BFIN_DMA
110 if (uart->tx_done) 120 if (uart->tx_done)
@@ -890,6 +900,20 @@ static int bfin_kgdboc_port_startup(struct uart_port *port)
890} 900}
891#endif 901#endif
892 902
903static void bfin_serial_reset_irda(struct uart_port *port)
904{
905 int line = port->line;
906 unsigned short val;
907
908 val = UART_GET_GCTL(&bfin_serial_ports[line]);
909 val &= ~(IREN | RPOLC);
910 UART_PUT_GCTL(&bfin_serial_ports[line], val);
911 SSYNC();
912 val |= (IREN | RPOLC);
913 UART_PUT_GCTL(&bfin_serial_ports[line], val);
914 SSYNC();
915}
916
893static struct uart_ops bfin_serial_pops = { 917static struct uart_ops bfin_serial_pops = {
894 .tx_empty = bfin_serial_tx_empty, 918 .tx_empty = bfin_serial_tx_empty,
895 .set_mctrl = bfin_serial_set_mctrl, 919 .set_mctrl = bfin_serial_set_mctrl,