aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/bfin_5xx.c
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2009-04-07 11:52:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:44:05 -0400
commitd307d36adeaa70074773b3e5eab8d7e1beb008a4 (patch)
tree2a51257927be7c1a99ffb38b4752e0a4b56edc2a /drivers/serial/bfin_5xx.c
parent6f95570e407d03c5140a220e054f9b18abdc7041 (diff)
tty: Blackin CTS/RTS
Both software emulated and hardware based CTS and RTS are enabled in serial driver. The CTS RTS PIN connection on BF548 UART port is defined as a modem device not as a host device. In order to test it under Linux, please nake a cross UART cable to exchange CTS and RTS signal. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/serial/bfin_5xx.c')
-rw-r--r--drivers/serial/bfin_5xx.c169
1 files changed, 117 insertions, 52 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index fbbddb9e73f6..18ba812a4f84 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -72,6 +72,63 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
72 72
73static void bfin_serial_reset_irda(struct uart_port *port); 73static void bfin_serial_reset_irda(struct uart_port *port);
74 74
75#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
76 defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
77static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
78{
79 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
80 if (uart->cts_pin < 0)
81 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
82
83 /* CTS PIN is negative assertive. */
84 if (UART_GET_CTS(uart))
85 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
86 else
87 return TIOCM_DSR | TIOCM_CAR;
88}
89
90static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
91{
92 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
93 if (uart->rts_pin < 0)
94 return;
95
96 /* RTS PIN is negative assertive. */
97 if (mctrl & TIOCM_RTS)
98 UART_ENABLE_RTS(uart);
99 else
100 UART_DISABLE_RTS(uart);
101}
102
103/*
104 * Handle any change of modem status signal.
105 */
106static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)
107{
108 struct bfin_serial_port *uart = dev_id;
109 unsigned int status;
110
111 status = bfin_serial_get_mctrl(&uart->port);
112 uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
113#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
114 uart->scts = 1;
115 UART_CLEAR_SCTS(uart);
116 UART_CLEAR_IER(uart, EDSSI);
117#endif
118
119 return IRQ_HANDLED;
120}
121#else
122static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
123{
124 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
125}
126
127static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
128{
129}
130#endif
131
75/* 132/*
76 * interrupts are disabled on entry 133 * interrupts are disabled on entry
77 */ 134 */
@@ -108,6 +165,13 @@ static void bfin_serial_start_tx(struct uart_port *port)
108 struct bfin_serial_port *uart = (struct bfin_serial_port *)port; 165 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
109 struct tty_struct *tty = uart->port.info->port.tty; 166 struct tty_struct *tty = uart->port.info->port.tty;
110 167
168#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
169 if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
170 uart->scts = 0;
171 uart_handle_cts_change(&uart->port, uart->scts);
172 }
173#endif
174
111 /* 175 /*
112 * To avoid losting RX interrupt, we reset IR function 176 * To avoid losting RX interrupt, we reset IR function
113 * before sending data. 177 * before sending data.
@@ -303,6 +367,12 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
303{ 367{
304 struct bfin_serial_port *uart = dev_id; 368 struct bfin_serial_port *uart = dev_id;
305 369
370#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
371 if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
372 uart->scts = 0;
373 uart_handle_cts_change(&uart->port, uart->scts);
374 }
375#endif
306 spin_lock(&uart->port.lock); 376 spin_lock(&uart->port.lock);
307 if (UART_GET_LSR(uart) & THRE) 377 if (UART_GET_LSR(uart) & THRE)
308 bfin_serial_tx_chars(uart); 378 bfin_serial_tx_chars(uart);
@@ -433,6 +503,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
433 struct bfin_serial_port *uart = dev_id; 503 struct bfin_serial_port *uart = dev_id;
434 struct circ_buf *xmit = &uart->port.info->xmit; 504 struct circ_buf *xmit = &uart->port.info->xmit;
435 505
506#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
507 if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
508 uart->scts = 0;
509 uart_handle_cts_change(&uart->port, uart->scts);
510 }
511#endif
512
436 spin_lock(&uart->port.lock); 513 spin_lock(&uart->port.lock);
437 if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { 514 if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
438 disable_dma(uart->tx_dma_channel); 515 disable_dma(uart->tx_dma_channel);
@@ -481,53 +558,6 @@ static unsigned int bfin_serial_tx_empty(struct uart_port *port)
481 return 0; 558 return 0;
482} 559}
483 560
484static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
485{
486#ifdef CONFIG_SERIAL_BFIN_CTSRTS
487 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
488 if (uart->cts_pin < 0)
489 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
490
491 if (UART_GET_CTS(uart))
492 return TIOCM_DSR | TIOCM_CAR;
493 else
494#endif
495 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
496}
497
498static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
499{
500#ifdef CONFIG_SERIAL_BFIN_CTSRTS
501 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
502 if (uart->rts_pin < 0)
503 return;
504
505 if (mctrl & TIOCM_RTS)
506 UART_CLEAR_RTS(uart);
507 else
508 UART_SET_RTS(uart);
509#endif
510}
511
512#ifdef CONFIG_SERIAL_BFIN_CTSRTS
513/*
514 * Handle any change of modem status signal.
515 */
516static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)
517{
518 struct bfin_serial_port *uart = dev_id;
519 unsigned int status;
520
521 status = bfin_serial_get_mctrl(&uart->port);
522 uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
523
524 return IRQ_HANDLED;
525}
526#endif
527
528/*
529 * Interrupts are always disabled.
530 */
531static void bfin_serial_break_ctl(struct uart_port *port, int break_state) 561static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
532{ 562{
533 struct bfin_serial_port *uart = (struct bfin_serial_port *)port; 563 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
@@ -660,6 +690,28 @@ static int bfin_serial_startup(struct uart_port *port)
660 gpio_direction_output(uart->rts_pin, 0); 690 gpio_direction_output(uart->rts_pin, 0);
661 } 691 }
662#endif 692#endif
693#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
694 if (request_irq(uart->status_irq,
695 bfin_serial_mctrl_cts_int,
696 IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
697 pr_info("Unable to attach BlackFin UART Modem \
698 Status interrupt.\n");
699 }
700
701 if (uart->cts_pin >= 0) {
702 gpio_request(uart->cts_pin, DRIVER_NAME);
703 gpio_direction_output(uart->cts_pin, 1);
704 }
705 if (uart->rts_pin >= 0) {
706 gpio_request(uart->rts_pin, DRIVER_NAME);
707 gpio_direction_output(uart->rts_pin, 0);
708 }
709
710 /* CTS RTS PINs are negative assertive. */
711 UART_PUT_MCR(uart, ACTS);
712 UART_SET_IER(uart, EDSSI);
713#endif
714
663 UART_SET_IER(uart, ERBFI); 715 UART_SET_IER(uart, ERBFI);
664 return 0; 716 return 0;
665} 717}
@@ -694,12 +746,20 @@ static void bfin_serial_shutdown(struct uart_port *port)
694 free_irq(uart->port.irq+1, uart); 746 free_irq(uart->port.irq+1, uart);
695#endif 747#endif
696 748
697# ifdef CONFIG_SERIAL_BFIN_CTSRTS 749#ifdef CONFIG_SERIAL_BFIN_CTSRTS
698 if (uart->cts_pin >= 0) 750 if (uart->cts_pin >= 0)
699 free_irq(gpio_to_irq(uart->cts_pin), uart); 751 free_irq(gpio_to_irq(uart->cts_pin), uart);
700 if (uart->rts_pin >= 0) 752 if (uart->rts_pin >= 0)
701 gpio_free(uart->rts_pin); 753 gpio_free(uart->rts_pin);
702# endif 754#endif
755#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
756 if (uart->cts_pin >= 0)
757 gpio_free(uart->cts_pin);
758 if (uart->rts_pin >= 0)
759 gpio_free(uart->rts_pin);
760 if (UART_GET_IER(uart) && EDSSI)
761 free_irq(uart->status_irq, uart);
762#endif
703} 763}
704 764
705static void 765static void
@@ -1009,6 +1069,8 @@ static void __init bfin_serial_init_ports(void)
1009 bfin_serial_resource[i].uart_base_addr; 1069 bfin_serial_resource[i].uart_base_addr;
1010 bfin_serial_ports[i].port.irq = 1070 bfin_serial_ports[i].port.irq =
1011 bfin_serial_resource[i].uart_irq; 1071 bfin_serial_resource[i].uart_irq;
1072 bfin_serial_ports[i].status_irq =
1073 bfin_serial_resource[i].uart_status_irq;
1012 bfin_serial_ports[i].port.flags = UPF_BOOT_AUTOCONF; 1074 bfin_serial_ports[i].port.flags = UPF_BOOT_AUTOCONF;
1013#ifdef CONFIG_SERIAL_BFIN_DMA 1075#ifdef CONFIG_SERIAL_BFIN_DMA
1014 bfin_serial_ports[i].tx_done = 1; 1076 bfin_serial_ports[i].tx_done = 1;
@@ -1019,7 +1081,8 @@ static void __init bfin_serial_init_ports(void)
1019 bfin_serial_resource[i].uart_rx_dma_channel; 1081 bfin_serial_resource[i].uart_rx_dma_channel;
1020 init_timer(&(bfin_serial_ports[i].rx_dma_timer)); 1082 init_timer(&(bfin_serial_ports[i].rx_dma_timer));
1021#endif 1083#endif
1022#ifdef CONFIG_SERIAL_BFIN_CTSRTS 1084#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
1085 defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
1023 bfin_serial_ports[i].cts_pin = 1086 bfin_serial_ports[i].cts_pin =
1024 bfin_serial_resource[i].uart_cts_pin; 1087 bfin_serial_resource[i].uart_cts_pin;
1025 bfin_serial_ports[i].rts_pin = 1088 bfin_serial_ports[i].rts_pin =
@@ -1082,7 +1145,8 @@ bfin_serial_console_setup(struct console *co, char *options)
1082 int baud = 57600; 1145 int baud = 57600;
1083 int bits = 8; 1146 int bits = 8;
1084 int parity = 'n'; 1147 int parity = 'n';
1085# ifdef CONFIG_SERIAL_BFIN_CTSRTS 1148# if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
1149 defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
1086 int flow = 'r'; 1150 int flow = 'r';
1087# else 1151# else
1088 int flow = 'n'; 1152 int flow = 'n';
@@ -1279,7 +1343,8 @@ static int bfin_serial_remove(struct platform_device *dev)
1279 continue; 1343 continue;
1280 uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); 1344 uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
1281 bfin_serial_ports[i].port.dev = NULL; 1345 bfin_serial_ports[i].port.dev = NULL;
1282#ifdef CONFIG_SERIAL_BFIN_CTSRTS 1346#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
1347 defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
1283 gpio_free(bfin_serial_ports[i].cts_pin); 1348 gpio_free(bfin_serial_ports[i].cts_pin);
1284 gpio_free(bfin_serial_ports[i].rts_pin); 1349 gpio_free(bfin_serial_ports[i].rts_pin);
1285#endif 1350#endif