aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2013-07-24 14:37:28 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-26 19:13:29 -0400
commit4a5662d6a6412dabe0b5518bec111e17babbba05 (patch)
treebd8c8bb7a169052f3fed6af81790e8efedd48c19
parentfee8bf4b74e37bfeb8998a349cb788680eb3f634 (diff)
msm_serial: Fix NUL byte output on UARTDM
UARTDM serial devices require us to wait for the entire TX fifo to drain before we can change the contents of the NCF_TX register. Furthermore, if we write any characters to the TX fifo within the same clock cycle of changing the NCF_TX register the NCF_TX register won't latch properly. To fix these issues we should read back the NCF_TX register to delay any TX fifo accesses by a clock cycle and we should wait for the TX fifo to drain (instead of just waiting for the fifo to be ready to receive more characters). Failure to do so leads to random NUL bytes interspersed in the output. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Acked-by: David Brown <davidb@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/msm_serial.c14
-rw-r--r--drivers/tty/serial/msm_serial.h1
2 files changed, 10 insertions, 5 deletions
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 0b38b288ed5b..5a88d88b25da 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -50,11 +50,14 @@ struct msm_port {
50 unsigned int old_snap_state; 50 unsigned int old_snap_state;
51}; 51};
52 52
53static inline void wait_for_xmitr(struct uart_port *port, int bits) 53static inline void wait_for_xmitr(struct uart_port *port)
54{ 54{
55 if (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) 55 while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
56 while ((msm_read(port, UART_ISR) & bits) != bits) 56 if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
57 cpu_relax(); 57 break;
58 udelay(1);
59 }
60 msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR);
58} 61}
59 62
60static void msm_stop_tx(struct uart_port *port) 63static void msm_stop_tx(struct uart_port *port)
@@ -194,8 +197,9 @@ static void handle_rx(struct uart_port *port)
194 197
195static void reset_dm_count(struct uart_port *port) 198static void reset_dm_count(struct uart_port *port)
196{ 199{
197 wait_for_xmitr(port, UART_ISR_TX_READY); 200 wait_for_xmitr(port);
198 msm_write(port, 1, UARTDM_NCF_TX); 201 msm_write(port, 1, UARTDM_NCF_TX);
202 msm_read(port, UARTDM_NCF_TX);
199} 203}
200 204
201static void handle_tx(struct uart_port *port) 205static void handle_tx(struct uart_port *port)
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index e4acef5de77e..15c186ecbd9e 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -71,6 +71,7 @@
71#define UART_CR_CMD_RESET_RFR (14 << 4) 71#define UART_CR_CMD_RESET_RFR (14 << 4)
72#define UART_CR_CMD_PROTECTION_EN (16 << 4) 72#define UART_CR_CMD_PROTECTION_EN (16 << 4)
73#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) 73#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
74#define UART_CR_CMD_RESET_TX_READY (3 << 8)
74#define UART_CR_TX_DISABLE (1 << 3) 75#define UART_CR_TX_DISABLE (1 << 3)
75#define UART_CR_TX_ENABLE (1 << 2) 76#define UART_CR_TX_ENABLE (1 << 2)
76#define UART_CR_RX_DISABLE (1 << 1) 77#define UART_CR_RX_DISABLE (1 << 1)