diff options
| author | Stephen Boyd <sboyd@codeaurora.org> | 2013-07-24 14:37:31 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-26 19:13:30 -0400 |
| commit | 17fae28efe8f460918e13aedd7163690206c682d (patch) | |
| tree | e18a47918d559d3c15d8a4da1ec6015e24929622 | |
| parent | 6909dadd914259f459828b11c378ddea08d40ab6 (diff) | |
msm_serial: Send more than 1 character at a time on UARTDM
UARTDM cores have a TX fifo that can accept more than one
character per register write, but the msm_serial driver currently
only supports 1 character mode. Add support for this mode of operation
to speed up the transmit path on DM devices.
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.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index ca2ae6581149..252d514b47fb 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c | |||
| @@ -195,10 +195,10 @@ static void handle_rx(struct uart_port *port) | |||
| 195 | tty_flip_buffer_push(tport); | 195 | tty_flip_buffer_push(tport); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static void reset_dm_count(struct uart_port *port) | 198 | static void reset_dm_count(struct uart_port *port, int count) |
| 199 | { | 199 | { |
| 200 | wait_for_xmitr(port); | 200 | wait_for_xmitr(port); |
| 201 | msm_write(port, 1, UARTDM_NCF_TX); | 201 | msm_write(port, count, UARTDM_NCF_TX); |
| 202 | msm_read(port, UARTDM_NCF_TX); | 202 | msm_read(port, UARTDM_NCF_TX); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| @@ -206,39 +206,52 @@ static void handle_tx(struct uart_port *port) | |||
| 206 | { | 206 | { |
| 207 | struct circ_buf *xmit = &port->state->xmit; | 207 | struct circ_buf *xmit = &port->state->xmit; |
| 208 | struct msm_port *msm_port = UART_TO_MSM(port); | 208 | struct msm_port *msm_port = UART_TO_MSM(port); |
| 209 | int sent_tx; | 209 | unsigned int tx_count, num_chars; |
| 210 | unsigned int tf_pointer = 0; | ||
| 211 | |||
| 212 | tx_count = uart_circ_chars_pending(xmit); | ||
| 213 | tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail, | ||
| 214 | port->fifosize); | ||
| 210 | 215 | ||
| 211 | if (port->x_char) { | 216 | if (port->x_char) { |
| 212 | if (msm_port->is_uartdm) | 217 | if (msm_port->is_uartdm) |
| 213 | reset_dm_count(port); | 218 | reset_dm_count(port, tx_count + 1); |
| 214 | 219 | ||
| 215 | msm_write(port, port->x_char, | 220 | msm_write(port, port->x_char, |
| 216 | msm_port->is_uartdm ? UARTDM_TF : UART_TF); | 221 | msm_port->is_uartdm ? UARTDM_TF : UART_TF); |
| 217 | port->icount.tx++; | 222 | port->icount.tx++; |
| 218 | port->x_char = 0; | 223 | port->x_char = 0; |
| 224 | } else if (tx_count && msm_port->is_uartdm) { | ||
| 225 | reset_dm_count(port, tx_count); | ||
| 219 | } | 226 | } |
| 220 | 227 | ||
| 221 | if (msm_port->is_uartdm) | 228 | while (tf_pointer < tx_count) { |
| 222 | reset_dm_count(port); | 229 | int i; |
| 230 | char buf[4] = { 0 }; | ||
| 231 | unsigned int *bf = (unsigned int *)&buf; | ||
| 223 | 232 | ||
| 224 | while (msm_read(port, UART_SR) & UART_SR_TX_READY) { | 233 | if (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) |
| 225 | if (uart_circ_empty(xmit)) { | ||
| 226 | /* disable tx interrupts */ | ||
| 227 | msm_port->imr &= ~UART_IMR_TXLEV; | ||
| 228 | msm_write(port, msm_port->imr, UART_IMR); | ||
| 229 | break; | 234 | break; |
| 230 | } | ||
| 231 | msm_write(port, xmit->buf[xmit->tail], | ||
| 232 | msm_port->is_uartdm ? UARTDM_TF : UART_TF); | ||
| 233 | 235 | ||
| 234 | if (msm_port->is_uartdm) | 236 | if (msm_port->is_uartdm) |
| 235 | reset_dm_count(port); | 237 | num_chars = min(tx_count - tf_pointer, sizeof(buf)); |
| 238 | else | ||
| 239 | num_chars = 1; | ||
| 236 | 240 | ||
| 237 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 241 | for (i = 0; i < num_chars; i++) { |
| 238 | port->icount.tx++; | 242 | buf[i] = xmit->buf[xmit->tail + i]; |
| 239 | sent_tx = 1; | 243 | port->icount.tx++; |
| 244 | } | ||
| 245 | |||
| 246 | msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF); | ||
| 247 | xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1); | ||
| 248 | tf_pointer += num_chars; | ||
| 240 | } | 249 | } |
| 241 | 250 | ||
| 251 | /* disable tx interrupts if nothing more to send */ | ||
| 252 | if (uart_circ_empty(xmit)) | ||
| 253 | msm_stop_tx(port); | ||
| 254 | |||
| 242 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 255 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| 243 | uart_write_wakeup(port); | 256 | uart_write_wakeup(port); |
| 244 | } | 257 | } |
| @@ -759,7 +772,7 @@ static void msm_console_putchar(struct uart_port *port, int c) | |||
| 759 | struct msm_port *msm_port = UART_TO_MSM(port); | 772 | struct msm_port *msm_port = UART_TO_MSM(port); |
| 760 | 773 | ||
| 761 | if (msm_port->is_uartdm) | 774 | if (msm_port->is_uartdm) |
| 762 | reset_dm_count(port); | 775 | reset_dm_count(port, 1); |
| 763 | 776 | ||
| 764 | while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) | 777 | while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) |
| 765 | ; | 778 | ; |
