aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBryan Wu <bryan.wu@analog.com>2007-05-06 17:50:30 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:58 -0400
commit194de5612777a9ff4f96dae1932f77a5a89e5f0a (patch)
tree2def94b88b7ce3348ecd216032490754cc7a31a0 /drivers
parent1394f03221790a988afc3e4b3cb79f2e477246a9 (diff)
blackfin: serial driver
This patch implements the driver necessary use the Analog Devices Blackfin processor's Serial Port. Signed-off-by: Bryan Wu <bryan.wu@analog.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Russell King <rmk+lkml@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/Kconfig94
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/bfin_5xx.c1012
3 files changed, 1107 insertions, 0 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index e9d927e3b8e6..924e9bd757f0 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -508,6 +508,100 @@ config SERIAL_SA1100_CONSOLE
508 your boot loader (lilo or loadlin) about how to pass options to the 508 your boot loader (lilo or loadlin) about how to pass options to the
509 kernel at boot time.) 509 kernel at boot time.)
510 510
511config SERIAL_BFIN
512 tristate "Blackfin serial port support"
513 depends on BFIN
514 select SERIAL_CORE
515 select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561)
516 help
517 Add support for the built-in UARTs on the Blackfin.
518
519 To compile this driver as a module, choose M here: the
520 module will be called bfin_5xx.
521
522config SERIAL_BFIN_CONSOLE
523 bool "Console on Blackfin serial port"
524 depends on SERIAL_BFIN
525 select SERIAL_CORE_CONSOLE
526
527choice
528 prompt "UART Mode"
529 depends on SERIAL_BFIN
530 default SERIAL_BFIN_DMA
531 help
532 This driver supports the built-in serial ports of the Blackfin family
533 of CPUs
534
535config SERIAL_BFIN_DMA
536 bool "DMA mode"
537 depends on DMA_UNCACHED_1M
538 help
539 This driver works under DMA mode. If this option is selected, the
540 blackfin simple dma driver is also enabled.
541
542config SERIAL_BFIN_PIO
543 bool "PIO mode"
544 help
545 This driver works under PIO mode.
546
547endchoice
548
549config SERIAL_BFIN_UART0
550 bool "Enable UART0"
551 depends on SERIAL_BFIN
552 help
553 Enable UART0
554
555config BFIN_UART0_CTSRTS
556 bool "Enable UART0 hardware flow control"
557 depends on SERIAL_BFIN_UART0
558 help
559 Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
560 signal.
561
562config UART0_CTS_PIN
563 int "UART0 CTS pin"
564 depends on BFIN_UART0_CTSRTS
565 default 23
566 help
567 The default pin is GPIO_GP7.
568 Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
569
570config UART0_RTS_PIN
571 int "UART0 RTS pin"
572 depends on BFIN_UART0_CTSRTS
573 default 22
574 help
575 The default pin is GPIO_GP6.
576 Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
577
578config SERIAL_BFIN_UART1
579 bool "Enable UART1"
580 depends on SERIAL_BFIN && (BF534 || BF536 || BF537)
581 help
582 Enable UART1
583
584config BFIN_UART1_CTSRTS
585 bool "Enable UART1 hardware flow control"
586 depends on SERIAL_BFIN_UART1
587 help
588 Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
589 signal.
590
591config UART1_CTS_PIN
592 int "UART1 CTS pin"
593 depends on BFIN_UART1_CTSRTS
594 default -1
595 help
596 Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
597
598config UART1_RTS_PIN
599 int "UART1 RTS pin"
600 depends on BFIN_UART1_CTSRTS
601 default -1
602 help
603 Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
604
511config SERIAL_IMX 605config SERIAL_IMX
512 bool "IMX serial port support" 606 bool "IMX serial port support"
513 depends on ARM && ARCH_IMX 607 depends on ARM && ARCH_IMX
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 6b3560c5749a..4959bcb8d1ef 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
27obj-$(CONFIG_SERIAL_PXA) += pxa.o 27obj-$(CONFIG_SERIAL_PXA) += pxa.o
28obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o 28obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
29obj-$(CONFIG_SERIAL_SA1100) += sa1100.o 29obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
30obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
30obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o 31obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
31obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o 32obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
32obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o 33obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
new file mode 100644
index 000000000000..408390f93db9
--- /dev/null
+++ b/drivers/serial/bfin_5xx.c
@@ -0,0 +1,1012 @@
1/*
2 * File: drivers/serial/bfin_5xx.c
3 * Based on: Based on drivers/serial/sa1100.c
4 * Author: Aubrey Li <aubrey.li@analog.com>
5 *
6 * Created:
7 * Description: Driver for blackfin 5xx serial ports
8 *
9 * Rev: $Id: bfin_5xx.c,v 1.19 2006/09/24 02:33:53 aubrey Exp $
10 *
11 * Modified:
12 * Copyright 2006 Analog Devices Inc.
13 *
14 * Bugs: Enter bugs at http://blackfin.uclinux.org/
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see the file COPYING, or write
28 * to the Free Software Foundation, Inc.,
29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32#if defined(CONFIG_SERIAL_BFIN_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
33#define SUPPORT_SYSRQ
34#endif
35
36#include <linux/module.h>
37#include <linux/ioport.h>
38#include <linux/init.h>
39#include <linux/console.h>
40#include <linux/sysrq.h>
41#include <linux/platform_device.h>
42#include <linux/tty.h>
43#include <linux/tty_flip.h>
44#include <linux/serial_core.h>
45
46#include <asm/gpio.h>
47#include <asm/mach/bfin_serial_5xx.h>
48
49#ifdef CONFIG_SERIAL_BFIN_DMA
50#include <linux/dma-mapping.h>
51#include <asm/io.h>
52#include <asm/irq.h>
53#include <asm/cacheflush.h>
54#endif
55
56/* UART name and device definitions */
57#define BFIN_SERIAL_NAME "ttyBF"
58#define BFIN_SERIAL_MAJOR 204
59#define BFIN_SERIAL_MINOR 64
60
61/*
62 * Setup for console. Argument comes from the menuconfig
63 */
64#define DMA_RX_XCOUNT 512
65#define DMA_RX_YCOUNT (PAGE_SIZE / DMA_RX_XCOUNT)
66
67#define DMA_RX_FLUSH_JIFFIES 5
68
69#ifdef CONFIG_SERIAL_BFIN_DMA
70static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart);
71#else
72static void bfin_serial_do_work(struct work_struct *work);
73static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
74static void local_put_char(struct bfin_serial_port *uart, char ch);
75#endif
76
77static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
78
79/*
80 * interrupts are disabled on entry
81 */
82static void bfin_serial_stop_tx(struct uart_port *port)
83{
84 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
85
86#ifdef CONFIG_SERIAL_BFIN_DMA
87 disable_dma(uart->tx_dma_channel);
88#else
89 unsigned short ier;
90
91 ier = UART_GET_IER(uart);
92 ier &= ~ETBEI;
93 UART_PUT_IER(uart, ier);
94#endif
95}
96
97/*
98 * port is locked and interrupts are disabled
99 */
100static void bfin_serial_start_tx(struct uart_port *port)
101{
102 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
103
104#ifdef CONFIG_SERIAL_BFIN_DMA
105 bfin_serial_dma_tx_chars(uart);
106#else
107 unsigned short ier;
108 ier = UART_GET_IER(uart);
109 ier |= ETBEI;
110 UART_PUT_IER(uart, ier);
111 bfin_serial_tx_chars(uart);
112#endif
113}
114
115/*
116 * Interrupts are enabled
117 */
118static void bfin_serial_stop_rx(struct uart_port *port)
119{
120 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
121 unsigned short ier;
122
123 ier = UART_GET_IER(uart);
124 ier &= ~ERBFI;
125 UART_PUT_IER(uart, ier);
126}
127
128/*
129 * Set the modem control timer to fire immediately.
130 */
131static void bfin_serial_enable_ms(struct uart_port *port)
132{
133}
134
135#ifdef CONFIG_SERIAL_BFIN_PIO
136static void local_put_char(struct bfin_serial_port *uart, char ch)
137{
138 unsigned short status;
139 int flags = 0;
140
141 spin_lock_irqsave(&uart->port.lock, flags);
142
143 do {
144 status = UART_GET_LSR(uart);
145 } while (!(status & THRE));
146
147 UART_PUT_CHAR(uart, ch);
148 SSYNC();
149
150 spin_unlock_irqrestore(&uart->port.lock, flags);
151}
152
153static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
154{
155 struct tty_struct *tty = uart->port.info?uart->port.info->tty:0;
156 unsigned int status, ch, flg;
157#ifdef BF533_FAMILY
158 static int in_break = 0;
159#endif
160
161 status = UART_GET_LSR(uart);
162 ch = UART_GET_CHAR(uart);
163 uart->port.icount.rx++;
164
165#ifdef BF533_FAMILY
166 /* The BF533 family of processors have a nice misbehavior where
167 * they continuously generate characters for a "single" break.
168 * We have to basically ignore this flood until the "next" valid
169 * character comes across. All other Blackfin families operate
170 * properly though.
171 */
172 if (in_break) {
173 if (ch != 0) {
174 in_break = 0;
175 ch = UART_GET_CHAR(uart);
176 }
177 return;
178 }
179#endif
180
181 if (status & BI) {
182#ifdef BF533_FAMILY
183 in_break = 1;
184#endif
185 uart->port.icount.brk++;
186 if (uart_handle_break(&uart->port))
187 goto ignore_char;
188 flg = TTY_BREAK;
189 } else if (status & PE) {
190 flg = TTY_PARITY;
191 uart->port.icount.parity++;
192 } else if (status & OE) {
193 flg = TTY_OVERRUN;
194 uart->port.icount.overrun++;
195 } else if (status & FE) {
196 flg = TTY_FRAME;
197 uart->port.icount.frame++;
198 } else
199 flg = TTY_NORMAL;
200
201 if (uart_handle_sysrq_char(&uart->port, ch))
202 goto ignore_char;
203 if (tty)
204 uart_insert_char(&uart->port, status, 2, ch, flg);
205
206ignore_char:
207 if (tty)
208 tty_flip_buffer_push(tty);
209}
210
211static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
212{
213 struct circ_buf *xmit = &uart->port.info->xmit;
214
215 if (uart->port.x_char) {
216 UART_PUT_CHAR(uart, uart->port.x_char);
217 uart->port.icount.tx++;
218 uart->port.x_char = 0;
219 return;
220 }
221 /*
222 * Check the modem control lines before
223 * transmitting anything.
224 */
225 bfin_serial_mctrl_check(uart);
226
227 if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
228 bfin_serial_stop_tx(&uart->port);
229 return;
230 }
231
232 local_put_char(uart, xmit->buf[xmit->tail]);
233 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
234 uart->port.icount.tx++;
235
236 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
237 uart_write_wakeup(&uart->port);
238
239 if (uart_circ_empty(xmit))
240 bfin_serial_stop_tx(&uart->port);
241}
242
243static irqreturn_t bfin_serial_int(int irq, void *dev_id)
244{
245 struct bfin_serial_port *uart = dev_id;
246 unsigned short status;
247
248 spin_lock(&uart->port.lock);
249 status = UART_GET_IIR(uart);
250 do {
251 if ((status & IIR_STATUS) == IIR_TX_READY)
252 bfin_serial_tx_chars(uart);
253 if ((status & IIR_STATUS) == IIR_RX_READY)
254 bfin_serial_rx_chars(uart);
255 status = UART_GET_IIR(uart);
256 } while (status & (IIR_TX_READY | IIR_RX_READY));
257 spin_unlock(&uart->port.lock);
258 return IRQ_HANDLED;
259}
260
261static void bfin_serial_do_work(struct work_struct *work)
262{
263 struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue);
264
265 bfin_serial_mctrl_check(uart);
266}
267
268#endif
269
270#ifdef CONFIG_SERIAL_BFIN_DMA
271static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
272{
273 struct circ_buf *xmit = &uart->port.info->xmit;
274 unsigned short ier;
275 int flags = 0;
276
277 if (!uart->tx_done)
278 return;
279
280 uart->tx_done = 0;
281
282 if (uart->port.x_char) {
283 UART_PUT_CHAR(uart, uart->port.x_char);
284 uart->port.icount.tx++;
285 uart->port.x_char = 0;
286 uart->tx_done = 1;
287 return;
288 }
289 /*
290 * Check the modem control lines before
291 * transmitting anything.
292 */
293 bfin_serial_mctrl_check(uart);
294
295 if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
296 bfin_serial_stop_tx(&uart->port);
297 uart->tx_done = 1;
298 return;
299 }
300
301 spin_lock_irqsave(&uart->port.lock, flags);
302 uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
303 if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail))
304 uart->tx_count = UART_XMIT_SIZE - xmit->tail;
305 blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail),
306 (unsigned long)(xmit->buf+xmit->tail+uart->tx_count));
307 set_dma_config(uart->tx_dma_channel,
308 set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP,
309 INTR_ON_BUF,
310 DIMENSION_LINEAR,
311 DATA_SIZE_8));
312 set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
313 set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
314 set_dma_x_modify(uart->tx_dma_channel, 1);
315 enable_dma(uart->tx_dma_channel);
316 ier = UART_GET_IER(uart);
317 ier |= ETBEI;
318 UART_PUT_IER(uart, ier);
319 spin_unlock_irqrestore(&uart->port.lock, flags);
320}
321
322static void bfin_serial_dma_rx_chars(struct bfin_serial_port * uart)
323{
324 struct tty_struct *tty = uart->port.info->tty;
325 int i, flg, status;
326
327 status = UART_GET_LSR(uart);
328 uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE);;
329
330 if (status & BI) {
331 uart->port.icount.brk++;
332 if (uart_handle_break(&uart->port))
333 goto dma_ignore_char;
334 flg = TTY_BREAK;
335 } else if (status & PE) {
336 flg = TTY_PARITY;
337 uart->port.icount.parity++;
338 } else if (status & OE) {
339 flg = TTY_OVERRUN;
340 uart->port.icount.overrun++;
341 } else if (status & FE) {
342 flg = TTY_FRAME;
343 uart->port.icount.frame++;
344 } else
345 flg = TTY_NORMAL;
346
347 for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) {
348 if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
349 goto dma_ignore_char;
350 uart_insert_char(&uart->port, status, 2, uart->rx_dma_buf.buf[i], flg);
351 }
352dma_ignore_char:
353 tty_flip_buffer_push(tty);
354}
355
356void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
357{
358 int x_pos, pos;
359 int flags = 0;
360
361 bfin_serial_dma_tx_chars(uart);
362
363 spin_lock_irqsave(&uart->port.lock, flags);
364 x_pos = DMA_RX_XCOUNT - get_dma_curr_xcount(uart->rx_dma_channel);
365 if (x_pos == DMA_RX_XCOUNT)
366 x_pos = 0;
367
368 pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
369
370 if (pos>uart->rx_dma_buf.tail) {
371 uart->rx_dma_buf.tail = pos;
372 bfin_serial_dma_rx_chars(uart);
373 uart->rx_dma_buf.head = uart->rx_dma_buf.tail;
374 }
375 spin_unlock_irqrestore(&uart->port.lock, flags);
376 uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
377 add_timer(&(uart->rx_dma_timer));
378}
379
380static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
381{
382 struct bfin_serial_port *uart = dev_id;
383 struct circ_buf *xmit = &uart->port.info->xmit;
384 unsigned short ier;
385
386 spin_lock(&uart->port.lock);
387 if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
388 clear_dma_irqstat(uart->tx_dma_channel);
389 disable_dma(uart->tx_dma_channel);
390 ier = UART_GET_IER(uart);
391 ier &= ~ETBEI;
392 UART_PUT_IER(uart, ier);
393 xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);
394 uart->port.icount.tx+=uart->tx_count;
395
396 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
397 uart_write_wakeup(&uart->port);
398
399 if (uart_circ_empty(xmit))
400 bfin_serial_stop_tx(&uart->port);
401 uart->tx_done = 1;
402 }
403
404 spin_unlock(&uart->port.lock);
405 return IRQ_HANDLED;
406}
407
408static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
409{
410 struct bfin_serial_port *uart = dev_id;
411 unsigned short irqstat;
412
413 uart->rx_dma_nrows++;
414 if (uart->rx_dma_nrows == DMA_RX_YCOUNT) {
415 uart->rx_dma_nrows = 0;
416 uart->rx_dma_buf.tail = DMA_RX_XCOUNT*DMA_RX_YCOUNT;
417 bfin_serial_dma_rx_chars(uart);
418 uart->rx_dma_buf.head = uart->rx_dma_buf.tail = 0;
419 }
420 spin_lock(&uart->port.lock);
421 irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
422 clear_dma_irqstat(uart->rx_dma_channel);
423
424 spin_unlock(&uart->port.lock);
425 return IRQ_HANDLED;
426}
427#endif
428
429/*
430 * Return TIOCSER_TEMT when transmitter is not busy.
431 */
432static unsigned int bfin_serial_tx_empty(struct uart_port *port)
433{
434 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
435 unsigned short lsr;
436
437 lsr = UART_GET_LSR(uart);
438 if (lsr & TEMT)
439 return TIOCSER_TEMT;
440 else
441 return 0;
442}
443
444static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
445{
446#ifdef CONFIG_SERIAL_BFIN_CTSRTS
447 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
448 if (uart->cts_pin < 0)
449 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
450
451 if (gpio_get_value(uart->cts_pin))
452 return TIOCM_DSR | TIOCM_CAR;
453 else
454#endif
455 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
456}
457
458static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
459{
460#ifdef CONFIG_SERIAL_BFIN_CTSRTS
461 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
462 if (uart->rts_pin < 0)
463 return;
464
465 if (mctrl & TIOCM_RTS)
466 gpio_set_value(uart->rts_pin, 0);
467 else
468 gpio_set_value(uart->rts_pin, 1);
469#endif
470}
471
472/*
473 * Handle any change of modem status signal since we were last called.
474 */
475static void bfin_serial_mctrl_check(struct bfin_serial_port *uart)
476{
477#ifdef CONFIG_SERIAL_BFIN_CTSRTS
478 unsigned int status;
479# ifdef CONFIG_SERIAL_BFIN_DMA
480 struct uart_info *info = uart->port.info;
481 struct tty_struct *tty = info->tty;
482
483 status = bfin_serial_get_mctrl(&uart->port);
484 if (!(status & TIOCM_CTS)) {
485 tty->hw_stopped = 1;
486 } else {
487 tty->hw_stopped = 0;
488 }
489# else
490 status = bfin_serial_get_mctrl(&uart->port);
491 uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
492 if (!(status & TIOCM_CTS))
493 schedule_work(&uart->cts_workqueue);
494# endif
495#endif
496}
497
498/*
499 * Interrupts are always disabled.
500 */
501static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
502{
503}
504
505static int bfin_serial_startup(struct uart_port *port)
506{
507 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
508
509#ifdef CONFIG_SERIAL_BFIN_DMA
510 dma_addr_t dma_handle;
511
512 if (request_dma(uart->rx_dma_channel, "BFIN_UART_RX") < 0) {
513 printk(KERN_NOTICE "Unable to attach Blackfin UART RX DMA channel\n");
514 return -EBUSY;
515 }
516
517 if (request_dma(uart->tx_dma_channel, "BFIN_UART_TX") < 0) {
518 printk(KERN_NOTICE "Unable to attach Blackfin UART TX DMA channel\n");
519 free_dma(uart->rx_dma_channel);
520 return -EBUSY;
521 }
522
523 set_dma_callback(uart->rx_dma_channel, bfin_serial_dma_rx_int, uart);
524 set_dma_callback(uart->tx_dma_channel, bfin_serial_dma_tx_int, uart);
525
526 uart->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA);
527 uart->rx_dma_buf.head = 0;
528 uart->rx_dma_buf.tail = 0;
529 uart->rx_dma_nrows = 0;
530
531 set_dma_config(uart->rx_dma_channel,
532 set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO,
533 INTR_ON_ROW, DIMENSION_2D,
534 DATA_SIZE_8));
535 set_dma_x_count(uart->rx_dma_channel, DMA_RX_XCOUNT);
536 set_dma_x_modify(uart->rx_dma_channel, 1);
537 set_dma_y_count(uart->rx_dma_channel, DMA_RX_YCOUNT);
538 set_dma_y_modify(uart->rx_dma_channel, 1);
539 set_dma_start_addr(uart->rx_dma_channel, (unsigned long)uart->rx_dma_buf.buf);
540 enable_dma(uart->rx_dma_channel);
541
542 uart->rx_dma_timer.data = (unsigned long)(uart);
543 uart->rx_dma_timer.function = (void *)bfin_serial_rx_dma_timeout;
544 uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
545 add_timer(&(uart->rx_dma_timer));
546#else
547 if (request_irq
548 (uart->port.irq, bfin_serial_int, IRQF_DISABLED,
549 "BFIN_UART_RX", uart)) {
550 printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
551 return -EBUSY;
552 }
553
554 if (request_irq
555 (uart->port.irq+1, bfin_serial_int, IRQF_DISABLED,
556 "BFIN_UART_TX", uart)) {
557 printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n");
558 free_irq(uart->port.irq, uart);
559 return -EBUSY;
560 }
561#endif
562 UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
563 return 0;
564}
565
566static void bfin_serial_shutdown(struct uart_port *port)
567{
568 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
569
570#ifdef CONFIG_SERIAL_BFIN_DMA
571 disable_dma(uart->tx_dma_channel);
572 free_dma(uart->tx_dma_channel);
573 disable_dma(uart->rx_dma_channel);
574 free_dma(uart->rx_dma_channel);
575 del_timer(&(uart->rx_dma_timer));
576#else
577 free_irq(uart->port.irq, uart);
578 free_irq(uart->port.irq+1, uart);
579#endif
580}
581
582static void
583bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
584 struct ktermios *old)
585{
586 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
587 unsigned long flags;
588 unsigned int baud, quot;
589 unsigned short val, ier, lsr, lcr = 0;
590
591 switch (termios->c_cflag & CSIZE) {
592 case CS8:
593 lcr = WLS(8);
594 break;
595 case CS7:
596 lcr = WLS(7);
597 break;
598 case CS6:
599 lcr = WLS(6);
600 break;
601 case CS5:
602 lcr = WLS(5);
603 break;
604 default:
605 printk(KERN_ERR "%s: word lengh not supported\n",
606 __FUNCTION__);
607 }
608
609 if (termios->c_cflag & CSTOPB)
610 lcr |= STB;
611 if (termios->c_cflag & PARENB) {
612 lcr |= PEN;
613 if (!(termios->c_cflag & PARODD))
614 lcr |= EPS;
615 }
616
617 /* These controls are not implemented for this port */
618 termios->c_iflag |= INPCK | BRKINT | PARMRK;
619 termios->c_iflag &= ~(IGNPAR | IGNBRK);
620
621 /* These controls are not implemented for this port */
622 termios->c_iflag |= INPCK | BRKINT | PARMRK;
623 termios->c_iflag &= ~(IGNPAR | IGNBRK);
624
625 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
626 quot = uart_get_divisor(port, baud);
627 spin_lock_irqsave(&uart->port.lock, flags);
628
629 do {
630 lsr = UART_GET_LSR(uart);
631 } while (!(lsr & TEMT));
632
633 /* Disable UART */
634 ier = UART_GET_IER(uart);
635 UART_PUT_IER(uart, 0);
636
637 /* Set DLAB in LCR to Access DLL and DLH */
638 val = UART_GET_LCR(uart);
639 val |= DLAB;
640 UART_PUT_LCR(uart, val);
641 SSYNC();
642
643 UART_PUT_DLL(uart, quot & 0xFF);
644 SSYNC();
645 UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
646 SSYNC();
647
648 /* Clear DLAB in LCR to Access THR RBR IER */
649 val = UART_GET_LCR(uart);
650 val &= ~DLAB;
651 UART_PUT_LCR(uart, val);
652 SSYNC();
653
654 UART_PUT_LCR(uart, lcr);
655
656 /* Enable UART */
657 UART_PUT_IER(uart, ier);
658
659 val = UART_GET_GCTL(uart);
660 val |= UCEN;
661 UART_PUT_GCTL(uart, val);
662
663 spin_unlock_irqrestore(&uart->port.lock, flags);
664}
665
666static const char *bfin_serial_type(struct uart_port *port)
667{
668 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
669
670 return uart->port.type == PORT_BFIN ? "BFIN-UART" : NULL;
671}
672
673/*
674 * Release the memory region(s) being used by 'port'.
675 */
676static void bfin_serial_release_port(struct uart_port *port)
677{
678}
679
680/*
681 * Request the memory region(s) being used by 'port'.
682 */
683static int bfin_serial_request_port(struct uart_port *port)
684{
685 return 0;
686}
687
688/*
689 * Configure/autoconfigure the port.
690 */
691static void bfin_serial_config_port(struct uart_port *port, int flags)
692{
693 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
694
695 if (flags & UART_CONFIG_TYPE &&
696 bfin_serial_request_port(&uart->port) == 0)
697 uart->port.type = PORT_BFIN;
698}
699
700/*
701 * Verify the new serial_struct (for TIOCSSERIAL).
702 * The only change we allow are to the flags and type, and
703 * even then only between PORT_BFIN and PORT_UNKNOWN
704 */
705static int
706bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
707{
708 return 0;
709}
710
711static struct uart_ops bfin_serial_pops = {
712 .tx_empty = bfin_serial_tx_empty,
713 .set_mctrl = bfin_serial_set_mctrl,
714 .get_mctrl = bfin_serial_get_mctrl,
715 .stop_tx = bfin_serial_stop_tx,
716 .start_tx = bfin_serial_start_tx,
717 .stop_rx = bfin_serial_stop_rx,
718 .enable_ms = bfin_serial_enable_ms,
719 .break_ctl = bfin_serial_break_ctl,
720 .startup = bfin_serial_startup,
721 .shutdown = bfin_serial_shutdown,
722 .set_termios = bfin_serial_set_termios,
723 .type = bfin_serial_type,
724 .release_port = bfin_serial_release_port,
725 .request_port = bfin_serial_request_port,
726 .config_port = bfin_serial_config_port,
727 .verify_port = bfin_serial_verify_port,
728};
729
730static void __init bfin_serial_init_ports(void)
731{
732 static int first = 1;
733 int i;
734
735 if (!first)
736 return;
737 first = 0;
738
739 for (i = 0; i < nr_ports; i++) {
740 bfin_serial_ports[i].port.uartclk = get_sclk();
741 bfin_serial_ports[i].port.ops = &bfin_serial_pops;
742 bfin_serial_ports[i].port.line = i;
743 bfin_serial_ports[i].port.iotype = UPIO_MEM;
744 bfin_serial_ports[i].port.membase =
745 (void __iomem *)bfin_serial_resource[i].uart_base_addr;
746 bfin_serial_ports[i].port.mapbase =
747 bfin_serial_resource[i].uart_base_addr;
748 bfin_serial_ports[i].port.irq =
749 bfin_serial_resource[i].uart_irq;
750 bfin_serial_ports[i].port.flags = UPF_BOOT_AUTOCONF;
751#ifdef CONFIG_SERIAL_BFIN_DMA
752 bfin_serial_ports[i].tx_done = 1;
753 bfin_serial_ports[i].tx_count = 0;
754 bfin_serial_ports[i].tx_dma_channel =
755 bfin_serial_resource[i].uart_tx_dma_channel;
756 bfin_serial_ports[i].rx_dma_channel =
757 bfin_serial_resource[i].uart_rx_dma_channel;
758 init_timer(&(bfin_serial_ports[i].rx_dma_timer));
759#else
760 INIT_WORK(&bfin_serial_ports[i].cts_workqueue, bfin_serial_do_work);
761#endif
762#ifdef CONFIG_SERIAL_BFIN_CTSRTS
763 bfin_serial_ports[i].cts_pin =
764 bfin_serial_resource[i].uart_cts_pin;
765 bfin_serial_ports[i].rts_pin =
766 bfin_serial_resource[i].uart_rts_pin;
767#endif
768 bfin_serial_hw_init(&bfin_serial_ports[i]);
769
770 }
771}
772
773#ifdef CONFIG_SERIAL_BFIN_CONSOLE
774static void bfin_serial_console_putchar(struct uart_port *port, int ch)
775{
776 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
777 while (!(UART_GET_LSR(uart)))
778 barrier();
779 UART_PUT_CHAR(uart, ch);
780 SSYNC();
781}
782
783/*
784 * Interrupts are disabled on entering
785 */
786static void
787bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
788{
789 struct bfin_serial_port *uart = &bfin_serial_ports[co->index];
790 int flags = 0;
791
792 spin_lock_irqsave(&uart->port.lock, flags);
793 uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);
794 spin_unlock_irqrestore(&uart->port.lock, flags);
795
796}
797
798/*
799 * If the port was already initialised (eg, by a boot loader),
800 * try to determine the current setup.
801 */
802static void __init
803bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
804 int *parity, int *bits)
805{
806 unsigned short status;
807
808 status = UART_GET_IER(uart) & (ERBFI | ETBEI);
809 if (status == (ERBFI | ETBEI)) {
810 /* ok, the port was enabled */
811 unsigned short lcr, val;
812 unsigned short dlh, dll;
813
814 lcr = UART_GET_LCR(uart);
815
816 *parity = 'n';
817 if (lcr & PEN) {
818 if (lcr & EPS)
819 *parity = 'e';
820 else
821 *parity = 'o';
822 }
823 switch (lcr & 0x03) {
824 case 0: *bits = 5; break;
825 case 1: *bits = 6; break;
826 case 2: *bits = 7; break;
827 case 3: *bits = 8; break;
828 }
829 /* Set DLAB in LCR to Access DLL and DLH */
830 val = UART_GET_LCR(uart);
831 val |= DLAB;
832 UART_PUT_LCR(uart, val);
833
834 dll = UART_GET_DLL(uart);
835 dlh = UART_GET_DLH(uart);
836
837 /* Clear DLAB in LCR to Access THR RBR IER */
838 val = UART_GET_LCR(uart);
839 val &= ~DLAB;
840 UART_PUT_LCR(uart, val);
841
842 *baud = get_sclk() / (16*(dll | dlh << 8));
843 }
844 pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
845}
846
847static int __init
848bfin_serial_console_setup(struct console *co, char *options)
849{
850 struct bfin_serial_port *uart;
851 int baud = 57600;
852 int bits = 8;
853 int parity = 'n';
854#ifdef CONFIG_SERIAL_BFIN_CTSRTS
855 int flow = 'r';
856#else
857 int flow = 'n';
858#endif
859
860 /*
861 * Check whether an invalid uart number has been specified, and
862 * if so, search for the first available port that does have
863 * console support.
864 */
865 if (co->index == -1 || co->index >= nr_ports)
866 co->index = 0;
867 uart = &bfin_serial_ports[co->index];
868
869 if (options)
870 uart_parse_options(options, &baud, &parity, &bits, &flow);
871 else
872 bfin_serial_console_get_options(uart, &baud, &parity, &bits);
873
874 return uart_set_options(&uart->port, co, baud, parity, bits, flow);
875}
876
877static struct uart_driver bfin_serial_reg;
878static struct console bfin_serial_console = {
879 .name = BFIN_SERIAL_NAME,
880 .write = bfin_serial_console_write,
881 .device = uart_console_device,
882 .setup = bfin_serial_console_setup,
883 .flags = CON_PRINTBUFFER,
884 .index = -1,
885 .data = &bfin_serial_reg,
886};
887
888static int __init bfin_serial_rs_console_init(void)
889{
890 bfin_serial_init_ports();
891 register_console(&bfin_serial_console);
892 return 0;
893}
894console_initcall(bfin_serial_rs_console_init);
895
896#define BFIN_SERIAL_CONSOLE &bfin_serial_console
897#else
898#define BFIN_SERIAL_CONSOLE NULL
899#endif
900
901static struct uart_driver bfin_serial_reg = {
902 .owner = THIS_MODULE,
903 .driver_name = "bfin-uart",
904 .dev_name = BFIN_SERIAL_NAME,
905 .major = BFIN_SERIAL_MAJOR,
906 .minor = BFIN_SERIAL_MINOR,
907 .nr = NR_PORTS,
908 .cons = BFIN_SERIAL_CONSOLE,
909};
910
911static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state)
912{
913 struct bfin_serial_port *uart = platform_get_drvdata(dev);
914
915 if (uart)
916 uart_suspend_port(&bfin_serial_reg, &uart->port);
917
918 return 0;
919}
920
921static int bfin_serial_resume(struct platform_device *dev)
922{
923 struct bfin_serial_port *uart = platform_get_drvdata(dev);
924
925 if (uart)
926 uart_resume_port(&bfin_serial_reg, &uart->port);
927
928 return 0;
929}
930
931static int bfin_serial_probe(struct platform_device *dev)
932{
933 struct resource *res = dev->resource;
934 int i;
935
936 for (i = 0; i < dev->num_resources; i++, res++)
937 if (res->flags & IORESOURCE_MEM)
938 break;
939
940 if (i < dev->num_resources) {
941 for (i = 0; i < nr_ports; i++, res++) {
942 if (bfin_serial_ports[i].port.mapbase != res->start)
943 continue;
944 bfin_serial_ports[i].port.dev = &dev->dev;
945 uart_add_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
946 platform_set_drvdata(dev, &bfin_serial_ports[i]);
947 }
948 }
949
950 return 0;
951}
952
953static int bfin_serial_remove(struct platform_device *pdev)
954{
955 struct bfin_serial_port *uart = platform_get_drvdata(pdev);
956
957
958#ifdef CONFIG_SERIAL_BFIN_CTSRTS
959 gpio_free(uart->cts_pin);
960 gpio_free(uart->rts_pin);
961#endif
962
963 platform_set_drvdata(pdev, NULL);
964
965 if (uart)
966 uart_remove_one_port(&bfin_serial_reg, &uart->port);
967
968 return 0;
969}
970
971static struct platform_driver bfin_serial_driver = {
972 .probe = bfin_serial_probe,
973 .remove = bfin_serial_remove,
974 .suspend = bfin_serial_suspend,
975 .resume = bfin_serial_resume,
976 .driver = {
977 .name = "bfin-uart",
978 },
979};
980
981static int __init bfin_serial_init(void)
982{
983 int ret;
984
985 pr_info("Serial: Blackfin serial driver\n");
986
987 bfin_serial_init_ports();
988
989 ret = uart_register_driver(&bfin_serial_reg);
990 if (ret == 0) {
991 ret = platform_driver_register(&bfin_serial_driver);
992 if (ret) {
993 pr_debug("uart register failed\n");
994 uart_unregister_driver(&bfin_serial_reg);
995 }
996 }
997 return ret;
998}
999
1000static void __exit bfin_serial_exit(void)
1001{
1002 platform_driver_unregister(&bfin_serial_driver);
1003 uart_unregister_driver(&bfin_serial_reg);
1004}
1005
1006module_init(bfin_serial_init);
1007module_exit(bfin_serial_exit);
1008
1009MODULE_AUTHOR("Aubrey.Li <aubrey.li@analog.com>");
1010MODULE_DESCRIPTION("Blackfin generic serial port driver");
1011MODULE_LICENSE("GPL");
1012MODULE_ALIAS_CHARDEV_MAJOR(BFIN_SERIAL_MAJOR);