diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/bfin_sport_uart.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index b9938acb0309..0b459cf1b2eb 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c | |||
@@ -54,7 +54,7 @@ struct sport_uart_port { | |||
54 | #endif | 54 | #endif |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static void sport_uart_tx_chars(struct sport_uart_port *up); | 57 | static int sport_uart_tx_chars(struct sport_uart_port *up); |
58 | static void sport_stop_tx(struct uart_port *port); | 58 | static void sport_stop_tx(struct uart_port *port); |
59 | 59 | ||
60 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) | 60 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) |
@@ -307,18 +307,24 @@ static int sport_startup(struct uart_port *port) | |||
307 | return ret; | 307 | return ret; |
308 | } | 308 | } |
309 | 309 | ||
310 | static void sport_uart_tx_chars(struct sport_uart_port *up) | 310 | /* |
311 | * sport_uart_tx_chars | ||
312 | * | ||
313 | * ret 1 means need to enable sport. | ||
314 | * ret 0 means do nothing. | ||
315 | */ | ||
316 | static int sport_uart_tx_chars(struct sport_uart_port *up) | ||
311 | { | 317 | { |
312 | struct circ_buf *xmit = &up->port.state->xmit; | 318 | struct circ_buf *xmit = &up->port.state->xmit; |
313 | 319 | ||
314 | if (SPORT_GET_STAT(up) & TXF) | 320 | if (SPORT_GET_STAT(up) & TXF) |
315 | return; | 321 | return 0; |
316 | 322 | ||
317 | if (up->port.x_char) { | 323 | if (up->port.x_char) { |
318 | tx_one_byte(up, up->port.x_char); | 324 | tx_one_byte(up, up->port.x_char); |
319 | up->port.icount.tx++; | 325 | up->port.icount.tx++; |
320 | up->port.x_char = 0; | 326 | up->port.x_char = 0; |
321 | return; | 327 | return 1; |
322 | } | 328 | } |
323 | 329 | ||
324 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 330 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { |
@@ -329,7 +335,7 @@ static void sport_uart_tx_chars(struct sport_uart_port *up) | |||
329 | */ | 335 | */ |
330 | if (SPORT_GET_STAT(up) & TXHRE) | 336 | if (SPORT_GET_STAT(up) & TXHRE) |
331 | sport_stop_tx(&up->port); | 337 | sport_stop_tx(&up->port); |
332 | return; | 338 | return 0; |
333 | } | 339 | } |
334 | 340 | ||
335 | while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) { | 341 | while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) { |
@@ -340,6 +346,8 @@ static void sport_uart_tx_chars(struct sport_uart_port *up) | |||
340 | 346 | ||
341 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 347 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
342 | uart_write_wakeup(&up->port); | 348 | uart_write_wakeup(&up->port); |
349 | |||
350 | return 1; | ||
343 | } | 351 | } |
344 | 352 | ||
345 | static unsigned int sport_tx_empty(struct uart_port *port) | 353 | static unsigned int sport_tx_empty(struct uart_port *port) |
@@ -361,6 +369,9 @@ static void sport_stop_tx(struct uart_port *port) | |||
361 | 369 | ||
362 | pr_debug("%s enter\n", __func__); | 370 | pr_debug("%s enter\n", __func__); |
363 | 371 | ||
372 | if (!(SPORT_GET_TCR1(up) & TSPEN)) | ||
373 | return; | ||
374 | |||
364 | /* Although the hold register is empty, last byte is still in shift | 375 | /* Although the hold register is empty, last byte is still in shift |
365 | * register and not sent out yet. So, put a dummy data into TX FIFO. | 376 | * register and not sent out yet. So, put a dummy data into TX FIFO. |
366 | * Then, sport tx stops when last byte is shift out and the dummy | 377 | * Then, sport tx stops when last byte is shift out and the dummy |
@@ -383,11 +394,12 @@ static void sport_start_tx(struct uart_port *port) | |||
383 | pr_debug("%s enter\n", __func__); | 394 | pr_debug("%s enter\n", __func__); |
384 | 395 | ||
385 | /* Write data into SPORT FIFO before enable SPROT to transmit */ | 396 | /* Write data into SPORT FIFO before enable SPROT to transmit */ |
386 | sport_uart_tx_chars(up); | 397 | if (sport_uart_tx_chars(up)) { |
398 | /* Enable transmit, then an interrupt will generated */ | ||
399 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); | ||
400 | SSYNC(); | ||
401 | } | ||
387 | 402 | ||
388 | /* Enable transmit, then an interrupt will generated */ | ||
389 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); | ||
390 | SSYNC(); | ||
391 | pr_debug("%s exit\n", __func__); | 403 | pr_debug("%s exit\n", __func__); |
392 | } | 404 | } |
393 | 405 | ||