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 /drivers/tty/serial/msm_serial.c | |
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>
Diffstat (limited to 'drivers/tty/serial/msm_serial.c')
-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 | ; |