diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-29 11:41:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-29 11:41:13 -0500 |
commit | 84b9a774008b132a8b5bd5460f639028a9c7f971 (patch) | |
tree | 4d6bd0f095c5653672cd227053da1579a8859b23 /drivers/serial | |
parent | 3cf9460a999480f444d1b96f09b0640f52b1537e (diff) | |
parent | 0aef45645174525ee6aa7baed247a130e052740d (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6: (35 commits)
Blackfin Serial Driver: Fix bug - Only insert UART rx char in timer task.
Blackfin Serial Driver: Fix bug - update tx dma buffer tail before wake up processes.
Blackfin Serial Driver: Fix bug - Increase buffer tail immediately before starting tx dma.
[Blackfin] serial driver: Add flow control support to bf54x
[Blackfin] serial driver: Fix bug Poll RTS/CTS status in DMA mode as well
[Blackfin] serial driver: ADSP-BF52x arch/mach support
[Blackfin] serial driver: use simpler comment headers and strip out information that is maintained in the scm's log
[Blackfin] serial driver: rework break flood anomaly handling to be more robust/realistic about what we can actually work around
[Blackfin] serial driver: fix bug - cache the bits of the LSR on systems where the LSR is read-to-clear
[Blackfin] serial driver: fix bug - should not wait for the TFI bit, just clear it when tx stop.
[Blackfin] serial driver: Fix bug serial driver in DMA mode spams history to console on shell restart
[Blackfin] serial driver: Fix bug Free rx dma buffer in shutdown.
[Blackfin] serial driver: Clean up UART DMA code.
Blackfin Serial driver: Fix bug - serial driver in PIO mode cant handle input very quickly
[Blackfin] arch: kill section mismatch warnings
[Blackfin] arch: handle the most common L1 shrinkage case (L1 does not exist for a part) so that any parts labeled for L1 instead get placed into external memory sections
[Blackfin] arch: add bfin_clear_PPIx_STATUS() helper funcs like we have for other parts
[Blackfin] arch: make sure we have proper description/copyright/license lines
[Blackfin] arch: Fix CONFIG_PM support for BF561
[Blackfin] arch: Remove DPMC char driver option
...
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 6 | ||||
-rw-r--r-- | drivers/serial/bfin_5xx.c | 281 |
2 files changed, 139 insertions, 148 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b82595cf13e8..cf627cd1b4c8 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -686,7 +686,7 @@ config UART0_RTS_PIN | |||
686 | 686 | ||
687 | config SERIAL_BFIN_UART1 | 687 | config SERIAL_BFIN_UART1 |
688 | bool "Enable UART1" | 688 | bool "Enable UART1" |
689 | depends on SERIAL_BFIN && (BF534 || BF536 || BF537 || BF54x) | 689 | depends on SERIAL_BFIN && (!BF531 && !BF532 && !BF533 && !BF561) |
690 | help | 690 | help |
691 | Enable UART1 | 691 | Enable UART1 |
692 | 692 | ||
@@ -699,14 +699,14 @@ config BFIN_UART1_CTSRTS | |||
699 | 699 | ||
700 | config UART1_CTS_PIN | 700 | config UART1_CTS_PIN |
701 | int "UART1 CTS pin" | 701 | int "UART1 CTS pin" |
702 | depends on BFIN_UART1_CTSRTS && (BF53x || BF561) | 702 | depends on BFIN_UART1_CTSRTS && !BF54x |
703 | default -1 | 703 | default -1 |
704 | help | 704 | help |
705 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | 705 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. |
706 | 706 | ||
707 | config UART1_RTS_PIN | 707 | config UART1_RTS_PIN |
708 | int "UART1 RTS pin" | 708 | int "UART1 RTS pin" |
709 | depends on BFIN_UART1_CTSRTS && (BF53x || BF561) | 709 | depends on BFIN_UART1_CTSRTS && !BF54x |
710 | default -1 | 710 | default -1 |
711 | help | 711 | help |
712 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | 712 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index ac2a3ef28d55..0aa345b9a38b 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -1,30 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * File: drivers/serial/bfin_5xx.c | 2 | * Blackfin On-Chip Serial Driver |
3 | * Based on: Based on drivers/serial/sa1100.c | ||
4 | * Author: Aubrey Li <aubrey.li@analog.com> | ||
5 | * | 3 | * |
6 | * Created: | 4 | * Copyright 2006-2007 Analog Devices Inc. |
7 | * Description: Driver for blackfin 5xx serial ports | ||
8 | * | 5 | * |
9 | * Modified: | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
10 | * Copyright 2006 Analog Devices Inc. | ||
11 | * | 7 | * |
12 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 8 | * Licensed under the GPL-2 or later. |
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, see the file COPYING, or write | ||
26 | * to the Free Software Foundation, Inc., | ||
27 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
28 | */ | 9 | */ |
29 | 10 | ||
30 | #if defined(CONFIG_SERIAL_BFIN_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 11 | #if defined(CONFIG_SERIAL_BFIN_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
@@ -67,14 +48,12 @@ | |||
67 | #define DMA_RX_XCOUNT 512 | 48 | #define DMA_RX_XCOUNT 512 |
68 | #define DMA_RX_YCOUNT (PAGE_SIZE / DMA_RX_XCOUNT) | 49 | #define DMA_RX_YCOUNT (PAGE_SIZE / DMA_RX_XCOUNT) |
69 | 50 | ||
70 | #define DMA_RX_FLUSH_JIFFIES 5 | 51 | #define DMA_RX_FLUSH_JIFFIES (HZ / 50) |
71 | 52 | ||
72 | #ifdef CONFIG_SERIAL_BFIN_DMA | 53 | #ifdef CONFIG_SERIAL_BFIN_DMA |
73 | static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart); | 54 | static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart); |
74 | #else | 55 | #else |
75 | static void bfin_serial_do_work(struct work_struct *work); | ||
76 | static void bfin_serial_tx_chars(struct bfin_serial_port *uart); | 56 | static void bfin_serial_tx_chars(struct bfin_serial_port *uart); |
77 | static void local_put_char(struct bfin_serial_port *uart, char ch); | ||
78 | #endif | 57 | #endif |
79 | 58 | ||
80 | static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); | 59 | static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); |
@@ -85,23 +64,26 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); | |||
85 | static void bfin_serial_stop_tx(struct uart_port *port) | 64 | static void bfin_serial_stop_tx(struct uart_port *port) |
86 | { | 65 | { |
87 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 66 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
67 | struct circ_buf *xmit = &uart->port.info->xmit; | ||
68 | #if !defined(CONFIG_BF54x) && !defined(CONFIG_SERIAL_BFIN_DMA) | ||
69 | unsigned short ier; | ||
70 | #endif | ||
88 | 71 | ||
89 | while (!(UART_GET_LSR(uart) & TEMT)) | 72 | while (!(UART_GET_LSR(uart) & TEMT)) |
90 | continue; | 73 | cpu_relax(); |
91 | 74 | ||
92 | #ifdef CONFIG_SERIAL_BFIN_DMA | 75 | #ifdef CONFIG_SERIAL_BFIN_DMA |
93 | disable_dma(uart->tx_dma_channel); | 76 | disable_dma(uart->tx_dma_channel); |
77 | xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); | ||
78 | uart->port.icount.tx += uart->tx_count; | ||
79 | uart->tx_count = 0; | ||
80 | uart->tx_done = 1; | ||
94 | #else | 81 | #else |
95 | #ifdef CONFIG_BF54x | 82 | #ifdef CONFIG_BF54x |
96 | /* Waiting for Transmission Finished */ | ||
97 | while (!(UART_GET_LSR(uart) & TFI)) | ||
98 | continue; | ||
99 | /* Clear TFI bit */ | 83 | /* Clear TFI bit */ |
100 | UART_PUT_LSR(uart, TFI); | 84 | UART_PUT_LSR(uart, TFI); |
101 | UART_CLEAR_IER(uart, ETBEI); | 85 | UART_CLEAR_IER(uart, ETBEI); |
102 | #else | 86 | #else |
103 | unsigned short ier; | ||
104 | |||
105 | ier = UART_GET_IER(uart); | 87 | ier = UART_GET_IER(uart); |
106 | ier &= ~ETBEI; | 88 | ier &= ~ETBEI; |
107 | UART_PUT_IER(uart, ier); | 89 | UART_PUT_IER(uart, ier); |
@@ -117,7 +99,8 @@ static void bfin_serial_start_tx(struct uart_port *port) | |||
117 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 99 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
118 | 100 | ||
119 | #ifdef CONFIG_SERIAL_BFIN_DMA | 101 | #ifdef CONFIG_SERIAL_BFIN_DMA |
120 | bfin_serial_dma_tx_chars(uart); | 102 | if (uart->tx_done) |
103 | bfin_serial_dma_tx_chars(uart); | ||
121 | #else | 104 | #else |
122 | #ifdef CONFIG_BF54x | 105 | #ifdef CONFIG_BF54x |
123 | UART_SET_IER(uart, ETBEI); | 106 | UART_SET_IER(uart, ETBEI); |
@@ -209,34 +192,27 @@ int kgdb_get_debug_char(void) | |||
209 | } | 192 | } |
210 | #endif | 193 | #endif |
211 | 194 | ||
212 | #ifdef CONFIG_SERIAL_BFIN_PIO | 195 | #if ANOMALY_05000230 && defined(CONFIG_SERIAL_BFIN_PIO) |
213 | static void local_put_char(struct bfin_serial_port *uart, char ch) | 196 | # define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold) |
214 | { | 197 | # define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v)) |
215 | unsigned short status; | 198 | #else |
216 | int flags = 0; | 199 | # define UART_GET_ANOMALY_THRESHOLD(uart) 0 |
217 | 200 | # define UART_SET_ANOMALY_THRESHOLD(uart, v) | |
218 | spin_lock_irqsave(&uart->port.lock, flags); | 201 | #endif |
219 | |||
220 | do { | ||
221 | status = UART_GET_LSR(uart); | ||
222 | } while (!(status & THRE)); | ||
223 | |||
224 | UART_PUT_CHAR(uart, ch); | ||
225 | SSYNC(); | ||
226 | |||
227 | spin_unlock_irqrestore(&uart->port.lock, flags); | ||
228 | } | ||
229 | 202 | ||
203 | #ifdef CONFIG_SERIAL_BFIN_PIO | ||
230 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | 204 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) |
231 | { | 205 | { |
232 | struct tty_struct *tty = uart->port.info->tty; | 206 | struct tty_struct *tty = uart->port.info->tty; |
233 | unsigned int status, ch, flg; | 207 | unsigned int status, ch, flg; |
234 | static int in_break = 0; | 208 | static struct timeval anomaly_start = { .tv_sec = 0 }; |
235 | #ifdef CONFIG_KGDB_UART | 209 | #ifdef CONFIG_KGDB_UART |
236 | struct pt_regs *regs = get_irq_regs(); | 210 | struct pt_regs *regs = get_irq_regs(); |
237 | #endif | 211 | #endif |
238 | 212 | ||
239 | status = UART_GET_LSR(uart); | 213 | status = UART_GET_LSR(uart); |
214 | UART_CLEAR_LSR(uart); | ||
215 | |||
240 | ch = UART_GET_CHAR(uart); | 216 | ch = UART_GET_CHAR(uart); |
241 | uart->port.icount.rx++; | 217 | uart->port.icount.rx++; |
242 | 218 | ||
@@ -262,28 +238,56 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
262 | #endif | 238 | #endif |
263 | 239 | ||
264 | if (ANOMALY_05000230) { | 240 | if (ANOMALY_05000230) { |
265 | /* The BF533 family of processors have a nice misbehavior where | 241 | /* The BF533 (and BF561) family of processors have a nice anomaly |
266 | * they continuously generate characters for a "single" break. | 242 | * where they continuously generate characters for a "single" break. |
267 | * We have to basically ignore this flood until the "next" valid | 243 | * We have to basically ignore this flood until the "next" valid |
268 | * character comes across. All other Blackfin families operate | 244 | * character comes across. Due to the nature of the flood, it is |
269 | * properly though. | 245 | * not possible to reliably catch bytes that are sent too quickly |
246 | * after this break. So application code talking to the Blackfin | ||
247 | * which sends a break signal must allow at least 1.5 character | ||
248 | * times after the end of the break for things to stabilize. This | ||
249 | * timeout was picked as it must absolutely be larger than 1 | ||
250 | * character time +/- some percent. So 1.5 sounds good. All other | ||
251 | * Blackfin families operate properly. Woo. | ||
270 | * Note: While Anomaly 05000230 does not directly address this, | 252 | * Note: While Anomaly 05000230 does not directly address this, |
271 | * the changes that went in for it also fixed this issue. | 253 | * the changes that went in for it also fixed this issue. |
254 | * That anomaly was fixed in 0.5+ silicon. I like bunnies. | ||
272 | */ | 255 | */ |
273 | if (in_break) { | 256 | if (anomaly_start.tv_sec) { |
274 | if (ch != 0) { | 257 | struct timeval curr; |
275 | in_break = 0; | 258 | suseconds_t usecs; |
276 | ch = UART_GET_CHAR(uart); | 259 | |
277 | if (bfin_revid() < 5) | 260 | if ((~ch & (~ch + 1)) & 0xff) |
278 | return; | 261 | goto known_good_char; |
279 | } else | 262 | |
280 | return; | 263 | do_gettimeofday(&curr); |
264 | if (curr.tv_sec - anomaly_start.tv_sec > 1) | ||
265 | goto known_good_char; | ||
266 | |||
267 | usecs = 0; | ||
268 | if (curr.tv_sec != anomaly_start.tv_sec) | ||
269 | usecs += USEC_PER_SEC; | ||
270 | usecs += curr.tv_usec - anomaly_start.tv_usec; | ||
271 | |||
272 | if (usecs > UART_GET_ANOMALY_THRESHOLD(uart)) | ||
273 | goto known_good_char; | ||
274 | |||
275 | if (ch) | ||
276 | anomaly_start.tv_sec = 0; | ||
277 | else | ||
278 | anomaly_start = curr; | ||
279 | |||
280 | return; | ||
281 | |||
282 | known_good_char: | ||
283 | anomaly_start.tv_sec = 0; | ||
281 | } | 284 | } |
282 | } | 285 | } |
283 | 286 | ||
284 | if (status & BI) { | 287 | if (status & BI) { |
285 | if (ANOMALY_05000230) | 288 | if (ANOMALY_05000230) |
286 | in_break = 1; | 289 | if (bfin_revid() < 5) |
290 | do_gettimeofday(&anomaly_start); | ||
287 | uart->port.icount.brk++; | 291 | uart->port.icount.brk++; |
288 | if (uart_handle_break(&uart->port)) | 292 | if (uart_handle_break(&uart->port)) |
289 | goto ignore_char; | 293 | goto ignore_char; |
@@ -324,7 +328,6 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart) | |||
324 | UART_PUT_CHAR(uart, uart->port.x_char); | 328 | UART_PUT_CHAR(uart, uart->port.x_char); |
325 | uart->port.icount.tx++; | 329 | uart->port.icount.tx++; |
326 | uart->port.x_char = 0; | 330 | uart->port.x_char = 0; |
327 | return; | ||
328 | } | 331 | } |
329 | /* | 332 | /* |
330 | * Check the modem control lines before | 333 | * Check the modem control lines before |
@@ -337,9 +340,12 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart) | |||
337 | return; | 340 | return; |
338 | } | 341 | } |
339 | 342 | ||
340 | local_put_char(uart, xmit->buf[xmit->tail]); | 343 | while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) { |
341 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 344 | UART_PUT_CHAR(uart, xmit->buf[xmit->tail]); |
342 | uart->port.icount.tx++; | 345 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
346 | uart->port.icount.tx++; | ||
347 | SSYNC(); | ||
348 | } | ||
343 | 349 | ||
344 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 350 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
345 | uart_write_wakeup(&uart->port); | 351 | uart_write_wakeup(&uart->port); |
@@ -352,21 +358,11 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) | |||
352 | { | 358 | { |
353 | struct bfin_serial_port *uart = dev_id; | 359 | struct bfin_serial_port *uart = dev_id; |
354 | 360 | ||
355 | #ifdef CONFIG_BF54x | ||
356 | unsigned short status; | ||
357 | spin_lock(&uart->port.lock); | ||
358 | status = UART_GET_LSR(uart); | ||
359 | while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) { | ||
360 | bfin_serial_rx_chars(uart); | ||
361 | status = UART_GET_LSR(uart); | ||
362 | } | ||
363 | spin_unlock(&uart->port.lock); | ||
364 | #else | ||
365 | spin_lock(&uart->port.lock); | 361 | spin_lock(&uart->port.lock); |
366 | while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY) | 362 | while (UART_GET_LSR(uart) & DR) |
367 | bfin_serial_rx_chars(uart); | 363 | bfin_serial_rx_chars(uart); |
368 | spin_unlock(&uart->port.lock); | 364 | spin_unlock(&uart->port.lock); |
369 | #endif | 365 | |
370 | return IRQ_HANDLED; | 366 | return IRQ_HANDLED; |
371 | } | 367 | } |
372 | 368 | ||
@@ -374,25 +370,16 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) | |||
374 | { | 370 | { |
375 | struct bfin_serial_port *uart = dev_id; | 371 | struct bfin_serial_port *uart = dev_id; |
376 | 372 | ||
377 | #ifdef CONFIG_BF54x | ||
378 | unsigned short status; | ||
379 | spin_lock(&uart->port.lock); | 373 | spin_lock(&uart->port.lock); |
380 | status = UART_GET_LSR(uart); | 374 | if (UART_GET_LSR(uart) & THRE) |
381 | while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) { | ||
382 | bfin_serial_tx_chars(uart); | 375 | bfin_serial_tx_chars(uart); |
383 | status = UART_GET_LSR(uart); | ||
384 | } | ||
385 | spin_unlock(&uart->port.lock); | 376 | spin_unlock(&uart->port.lock); |
386 | #else | 377 | |
387 | spin_lock(&uart->port.lock); | ||
388 | while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY) | ||
389 | bfin_serial_tx_chars(uart); | ||
390 | spin_unlock(&uart->port.lock); | ||
391 | #endif | ||
392 | return IRQ_HANDLED; | 378 | return IRQ_HANDLED; |
393 | } | 379 | } |
380 | #endif | ||
394 | 381 | ||
395 | 382 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | |
396 | static void bfin_serial_do_work(struct work_struct *work) | 383 | static void bfin_serial_do_work(struct work_struct *work) |
397 | { | 384 | { |
398 | struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue); | 385 | struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue); |
@@ -406,33 +393,27 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) | |||
406 | { | 393 | { |
407 | struct circ_buf *xmit = &uart->port.info->xmit; | 394 | struct circ_buf *xmit = &uart->port.info->xmit; |
408 | unsigned short ier; | 395 | unsigned short ier; |
409 | int flags = 0; | ||
410 | |||
411 | if (!uart->tx_done) | ||
412 | return; | ||
413 | 396 | ||
414 | uart->tx_done = 0; | 397 | uart->tx_done = 0; |
415 | 398 | ||
399 | if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { | ||
400 | uart->tx_count = 0; | ||
401 | uart->tx_done = 1; | ||
402 | return; | ||
403 | } | ||
404 | |||
416 | if (uart->port.x_char) { | 405 | if (uart->port.x_char) { |
417 | UART_PUT_CHAR(uart, uart->port.x_char); | 406 | UART_PUT_CHAR(uart, uart->port.x_char); |
418 | uart->port.icount.tx++; | 407 | uart->port.icount.tx++; |
419 | uart->port.x_char = 0; | 408 | uart->port.x_char = 0; |
420 | uart->tx_done = 1; | ||
421 | return; | ||
422 | } | 409 | } |
410 | |||
423 | /* | 411 | /* |
424 | * Check the modem control lines before | 412 | * Check the modem control lines before |
425 | * transmitting anything. | 413 | * transmitting anything. |
426 | */ | 414 | */ |
427 | bfin_serial_mctrl_check(uart); | 415 | bfin_serial_mctrl_check(uart); |
428 | 416 | ||
429 | if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { | ||
430 | bfin_serial_stop_tx(&uart->port); | ||
431 | uart->tx_done = 1; | ||
432 | return; | ||
433 | } | ||
434 | |||
435 | spin_lock_irqsave(&uart->port.lock, flags); | ||
436 | uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); | 417 | uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); |
437 | if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) | 418 | if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) |
438 | uart->tx_count = UART_XMIT_SIZE - xmit->tail; | 419 | uart->tx_count = UART_XMIT_SIZE - xmit->tail; |
@@ -448,6 +429,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) | |||
448 | set_dma_x_count(uart->tx_dma_channel, uart->tx_count); | 429 | set_dma_x_count(uart->tx_dma_channel, uart->tx_count); |
449 | set_dma_x_modify(uart->tx_dma_channel, 1); | 430 | set_dma_x_modify(uart->tx_dma_channel, 1); |
450 | enable_dma(uart->tx_dma_channel); | 431 | enable_dma(uart->tx_dma_channel); |
432 | |||
451 | #ifdef CONFIG_BF54x | 433 | #ifdef CONFIG_BF54x |
452 | UART_SET_IER(uart, ETBEI); | 434 | UART_SET_IER(uart, ETBEI); |
453 | #else | 435 | #else |
@@ -455,7 +437,6 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) | |||
455 | ier |= ETBEI; | 437 | ier |= ETBEI; |
456 | UART_PUT_IER(uart, ier); | 438 | UART_PUT_IER(uart, ier); |
457 | #endif | 439 | #endif |
458 | spin_unlock_irqrestore(&uart->port.lock, flags); | ||
459 | } | 440 | } |
460 | 441 | ||
461 | static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | 442 | static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) |
@@ -464,7 +445,11 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | |||
464 | int i, flg, status; | 445 | int i, flg, status; |
465 | 446 | ||
466 | status = UART_GET_LSR(uart); | 447 | status = UART_GET_LSR(uart); |
467 | uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE);; | 448 | UART_CLEAR_LSR(uart); |
449 | |||
450 | uart->port.icount.rx += | ||
451 | CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, | ||
452 | UART_XMIT_SIZE); | ||
468 | 453 | ||
469 | if (status & BI) { | 454 | if (status & BI) { |
470 | uart->port.icount.brk++; | 455 | uart->port.icount.brk++; |
@@ -490,10 +475,12 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | |||
490 | else | 475 | else |
491 | flg = TTY_NORMAL; | 476 | flg = TTY_NORMAL; |
492 | 477 | ||
493 | for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) { | 478 | for (i = uart->rx_dma_buf.tail; i != uart->rx_dma_buf.head; i++) { |
494 | if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) | 479 | if (i >= UART_XMIT_SIZE) |
495 | goto dma_ignore_char; | 480 | i = 0; |
496 | uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg); | 481 | if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) |
482 | uart_insert_char(&uart->port, status, OE, | ||
483 | uart->rx_dma_buf.buf[i], flg); | ||
497 | } | 484 | } |
498 | 485 | ||
499 | dma_ignore_char: | 486 | dma_ignore_char: |
@@ -503,23 +490,23 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | |||
503 | void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | 490 | void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) |
504 | { | 491 | { |
505 | int x_pos, pos; | 492 | int x_pos, pos; |
506 | int flags = 0; | ||
507 | |||
508 | bfin_serial_dma_tx_chars(uart); | ||
509 | 493 | ||
510 | spin_lock_irqsave(&uart->port.lock, flags); | 494 | uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); |
511 | x_pos = DMA_RX_XCOUNT - get_dma_curr_xcount(uart->rx_dma_channel); | 495 | x_pos = get_dma_curr_xcount(uart->rx_dma_channel); |
496 | uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; | ||
497 | if (uart->rx_dma_nrows == DMA_RX_YCOUNT) | ||
498 | uart->rx_dma_nrows = 0; | ||
499 | x_pos = DMA_RX_XCOUNT - x_pos; | ||
512 | if (x_pos == DMA_RX_XCOUNT) | 500 | if (x_pos == DMA_RX_XCOUNT) |
513 | x_pos = 0; | 501 | x_pos = 0; |
514 | 502 | ||
515 | pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; | 503 | pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; |
516 | 504 | if (pos != uart->rx_dma_buf.tail) { | |
517 | if (pos>uart->rx_dma_buf.tail) { | 505 | uart->rx_dma_buf.head = pos; |
518 | uart->rx_dma_buf.tail = pos; | ||
519 | bfin_serial_dma_rx_chars(uart); | 506 | bfin_serial_dma_rx_chars(uart); |
520 | uart->rx_dma_buf.head = uart->rx_dma_buf.tail; | 507 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; |
521 | } | 508 | } |
522 | spin_unlock_irqrestore(&uart->port.lock, flags); | 509 | |
523 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; | 510 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; |
524 | add_timer(&(uart->rx_dma_timer)); | 511 | add_timer(&(uart->rx_dma_timer)); |
525 | } | 512 | } |
@@ -532,8 +519,8 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) | |||
532 | 519 | ||
533 | spin_lock(&uart->port.lock); | 520 | spin_lock(&uart->port.lock); |
534 | if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { | 521 | if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { |
535 | clear_dma_irqstat(uart->tx_dma_channel); | ||
536 | disable_dma(uart->tx_dma_channel); | 522 | disable_dma(uart->tx_dma_channel); |
523 | clear_dma_irqstat(uart->tx_dma_channel); | ||
537 | #ifdef CONFIG_BF54x | 524 | #ifdef CONFIG_BF54x |
538 | UART_CLEAR_IER(uart, ETBEI); | 525 | UART_CLEAR_IER(uart, ETBEI); |
539 | #else | 526 | #else |
@@ -541,15 +528,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) | |||
541 | ier &= ~ETBEI; | 528 | ier &= ~ETBEI; |
542 | UART_PUT_IER(uart, ier); | 529 | UART_PUT_IER(uart, ier); |
543 | #endif | 530 | #endif |
544 | xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1); | 531 | xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); |
545 | uart->port.icount.tx+=uart->tx_count; | 532 | uart->port.icount.tx += uart->tx_count; |
546 | 533 | ||
547 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 534 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
548 | uart_write_wakeup(&uart->port); | 535 | uart_write_wakeup(&uart->port); |
549 | 536 | ||
550 | if (uart_circ_empty(xmit)) | 537 | bfin_serial_dma_tx_chars(uart); |
551 | bfin_serial_stop_tx(&uart->port); | ||
552 | uart->tx_done = 1; | ||
553 | } | 538 | } |
554 | 539 | ||
555 | spin_unlock(&uart->port.lock); | 540 | spin_unlock(&uart->port.lock); |
@@ -561,18 +546,15 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id) | |||
561 | struct bfin_serial_port *uart = dev_id; | 546 | struct bfin_serial_port *uart = dev_id; |
562 | unsigned short irqstat; | 547 | unsigned short irqstat; |
563 | 548 | ||
564 | uart->rx_dma_nrows++; | ||
565 | if (uart->rx_dma_nrows == DMA_RX_YCOUNT) { | ||
566 | uart->rx_dma_nrows = 0; | ||
567 | uart->rx_dma_buf.tail = DMA_RX_XCOUNT*DMA_RX_YCOUNT; | ||
568 | bfin_serial_dma_rx_chars(uart); | ||
569 | uart->rx_dma_buf.head = uart->rx_dma_buf.tail = 0; | ||
570 | } | ||
571 | spin_lock(&uart->port.lock); | 549 | spin_lock(&uart->port.lock); |
572 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); | 550 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); |
573 | clear_dma_irqstat(uart->rx_dma_channel); | 551 | clear_dma_irqstat(uart->rx_dma_channel); |
574 | |||
575 | spin_unlock(&uart->port.lock); | 552 | spin_unlock(&uart->port.lock); |
553 | |||
554 | del_timer(&(uart->rx_dma_timer)); | ||
555 | uart->rx_dma_timer.expires = jiffies; | ||
556 | add_timer(&(uart->rx_dma_timer)); | ||
557 | |||
576 | return IRQ_HANDLED; | 558 | return IRQ_HANDLED; |
577 | } | 559 | } |
578 | #endif | 560 | #endif |
@@ -599,7 +581,11 @@ static unsigned int bfin_serial_get_mctrl(struct uart_port *port) | |||
599 | if (uart->cts_pin < 0) | 581 | if (uart->cts_pin < 0) |
600 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | 582 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; |
601 | 583 | ||
584 | # ifdef BF54x | ||
585 | if (UART_GET_MSR(uart) & CTS) | ||
586 | # else | ||
602 | if (gpio_get_value(uart->cts_pin)) | 587 | if (gpio_get_value(uart->cts_pin)) |
588 | # endif | ||
603 | return TIOCM_DSR | TIOCM_CAR; | 589 | return TIOCM_DSR | TIOCM_CAR; |
604 | else | 590 | else |
605 | #endif | 591 | #endif |
@@ -614,9 +600,17 @@ static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
614 | return; | 600 | return; |
615 | 601 | ||
616 | if (mctrl & TIOCM_RTS) | 602 | if (mctrl & TIOCM_RTS) |
603 | # ifdef BF54x | ||
604 | UART_PUT_MCR(uart, UART_GET_MCR(uart) & ~MRTS); | ||
605 | # else | ||
617 | gpio_set_value(uart->rts_pin, 0); | 606 | gpio_set_value(uart->rts_pin, 0); |
607 | # endif | ||
618 | else | 608 | else |
609 | # ifdef BF54x | ||
610 | UART_PUT_MCR(uart, UART_GET_MCR(uart) | MRTS); | ||
611 | # else | ||
619 | gpio_set_value(uart->rts_pin, 1); | 612 | gpio_set_value(uart->rts_pin, 1); |
613 | # endif | ||
620 | #endif | 614 | #endif |
621 | } | 615 | } |
622 | 616 | ||
@@ -627,22 +621,17 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart) | |||
627 | { | 621 | { |
628 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 622 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
629 | unsigned int status; | 623 | unsigned int status; |
630 | # ifdef CONFIG_SERIAL_BFIN_DMA | ||
631 | struct uart_info *info = uart->port.info; | 624 | struct uart_info *info = uart->port.info; |
632 | struct tty_struct *tty = info->tty; | 625 | struct tty_struct *tty = info->tty; |
633 | 626 | ||
634 | status = bfin_serial_get_mctrl(&uart->port); | 627 | status = bfin_serial_get_mctrl(&uart->port); |
628 | uart_handle_cts_change(&uart->port, status & TIOCM_CTS); | ||
635 | if (!(status & TIOCM_CTS)) { | 629 | if (!(status & TIOCM_CTS)) { |
636 | tty->hw_stopped = 1; | 630 | tty->hw_stopped = 1; |
631 | schedule_work(&uart->cts_workqueue); | ||
637 | } else { | 632 | } else { |
638 | tty->hw_stopped = 0; | 633 | tty->hw_stopped = 0; |
639 | } | 634 | } |
640 | # else | ||
641 | status = bfin_serial_get_mctrl(&uart->port); | ||
642 | uart_handle_cts_change(&uart->port, status & TIOCM_CTS); | ||
643 | if (!(status & TIOCM_CTS)) | ||
644 | schedule_work(&uart->cts_workqueue); | ||
645 | # endif | ||
646 | #endif | 635 | #endif |
647 | } | 636 | } |
648 | 637 | ||
@@ -743,6 +732,7 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
743 | disable_dma(uart->rx_dma_channel); | 732 | disable_dma(uart->rx_dma_channel); |
744 | free_dma(uart->rx_dma_channel); | 733 | free_dma(uart->rx_dma_channel); |
745 | del_timer(&(uart->rx_dma_timer)); | 734 | del_timer(&(uart->rx_dma_timer)); |
735 | dma_free_coherent(NULL, PAGE_SIZE, uart->rx_dma_buf.buf, 0); | ||
746 | #else | 736 | #else |
747 | #ifdef CONFIG_KGDB_UART | 737 | #ifdef CONFIG_KGDB_UART |
748 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | 738 | if (uart->port.line != CONFIG_KGDB_UART_PORT) |
@@ -814,6 +804,8 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, | |||
814 | quot = uart_get_divisor(port, baud); | 804 | quot = uart_get_divisor(port, baud); |
815 | spin_lock_irqsave(&uart->port.lock, flags); | 805 | spin_lock_irqsave(&uart->port.lock, flags); |
816 | 806 | ||
807 | UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15); | ||
808 | |||
817 | do { | 809 | do { |
818 | lsr = UART_GET_LSR(uart); | 810 | lsr = UART_GET_LSR(uart); |
819 | } while (!(lsr & TEMT)); | 811 | } while (!(lsr & TEMT)); |
@@ -956,10 +948,9 @@ static void __init bfin_serial_init_ports(void) | |||
956 | bfin_serial_ports[i].rx_dma_channel = | 948 | bfin_serial_ports[i].rx_dma_channel = |
957 | bfin_serial_resource[i].uart_rx_dma_channel; | 949 | bfin_serial_resource[i].uart_rx_dma_channel; |
958 | init_timer(&(bfin_serial_ports[i].rx_dma_timer)); | 950 | init_timer(&(bfin_serial_ports[i].rx_dma_timer)); |
959 | #else | ||
960 | INIT_WORK(&bfin_serial_ports[i].cts_workqueue, bfin_serial_do_work); | ||
961 | #endif | 951 | #endif |
962 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 952 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
953 | INIT_WORK(&bfin_serial_ports[i].cts_workqueue, bfin_serial_do_work); | ||
963 | bfin_serial_ports[i].cts_pin = | 954 | bfin_serial_ports[i].cts_pin = |
964 | bfin_serial_resource[i].uart_cts_pin; | 955 | bfin_serial_resource[i].uart_cts_pin; |
965 | bfin_serial_ports[i].rts_pin = | 956 | bfin_serial_ports[i].rts_pin = |