Commit 4a5662d6 authored by Stephen Boyd's avatar Stephen Boyd Committed by Greg Kroah-Hartman

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: default avatarStephen Boyd <sboyd@codeaurora.org>
Acked-by: default avatarDavid Brown <davidb@codeaurora.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fee8bf4b
...@@ -50,11 +50,14 @@ struct msm_port { ...@@ -50,11 +50,14 @@ struct msm_port {
unsigned int old_snap_state; unsigned int old_snap_state;
}; };
static inline void wait_for_xmitr(struct uart_port *port, int bits) static inline void wait_for_xmitr(struct uart_port *port)
{ {
if (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
while ((msm_read(port, UART_ISR) & bits) != bits) if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
cpu_relax(); break;
udelay(1);
}
msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR);
} }
static void msm_stop_tx(struct uart_port *port) static void msm_stop_tx(struct uart_port *port)
...@@ -194,8 +197,9 @@ static void handle_rx(struct uart_port *port) ...@@ -194,8 +197,9 @@ static void handle_rx(struct uart_port *port)
static void reset_dm_count(struct uart_port *port) static void reset_dm_count(struct uart_port *port)
{ {
wait_for_xmitr(port, UART_ISR_TX_READY); wait_for_xmitr(port);
msm_write(port, 1, UARTDM_NCF_TX); msm_write(port, 1, UARTDM_NCF_TX);
msm_read(port, UARTDM_NCF_TX);
} }
static void handle_tx(struct uart_port *port) static void handle_tx(struct uart_port *port)
......
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
#define UART_CR_CMD_RESET_RFR (14 << 4) #define UART_CR_CMD_RESET_RFR (14 << 4)
#define UART_CR_CMD_PROTECTION_EN (16 << 4) #define UART_CR_CMD_PROTECTION_EN (16 << 4)
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
#define UART_CR_TX_DISABLE (1 << 3) #define UART_CR_TX_DISABLE (1 << 3)
#define UART_CR_TX_ENABLE (1 << 2) #define UART_CR_TX_ENABLE (1 << 2)
#define UART_CR_RX_DISABLE (1 << 1) #define UART_CR_RX_DISABLE (1 << 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment