diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2009-04-07 11:52:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:44:05 -0400 |
commit | d307d36adeaa70074773b3e5eab8d7e1beb008a4 (patch) | |
tree | 2a51257927be7c1a99ffb38b4752e0a4b56edc2a /drivers/serial | |
parent | 6f95570e407d03c5140a220e054f9b18abdc7041 (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')
-rw-r--r-- | drivers/serial/Kconfig | 26 | ||||
-rw-r--r-- | drivers/serial/bfin_5xx.c | 169 |
2 files changed, 137 insertions, 58 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index d89972beb12c..f2e5736ad0c8 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -734,7 +734,7 @@ config BFIN_UART0_CTSRTS | |||
734 | 734 | ||
735 | config UART0_CTS_PIN | 735 | config UART0_CTS_PIN |
736 | int "UART0 CTS pin" | 736 | int "UART0 CTS pin" |
737 | depends on BFIN_UART0_CTSRTS | 737 | depends on BFIN_UART0_CTSRTS && !BF548 |
738 | default 23 | 738 | default 23 |
739 | help | 739 | help |
740 | The default pin is GPIO_GP7. | 740 | The default pin is GPIO_GP7. |
@@ -742,7 +742,7 @@ config UART0_CTS_PIN | |||
742 | 742 | ||
743 | config UART0_RTS_PIN | 743 | config UART0_RTS_PIN |
744 | int "UART0 RTS pin" | 744 | int "UART0 RTS pin" |
745 | depends on BFIN_UART0_CTSRTS | 745 | depends on BFIN_UART0_CTSRTS && !BF548 |
746 | default 22 | 746 | default 22 |
747 | help | 747 | help |
748 | The default pin is GPIO_GP6. | 748 | The default pin is GPIO_GP6. |
@@ -763,14 +763,14 @@ config BFIN_UART1_CTSRTS | |||
763 | 763 | ||
764 | config UART1_CTS_PIN | 764 | config UART1_CTS_PIN |
765 | int "UART1 CTS pin" | 765 | int "UART1 CTS pin" |
766 | depends on BFIN_UART1_CTSRTS && !BF54x | 766 | depends on BFIN_UART1_CTSRTS && !BF548 |
767 | default -1 | 767 | default -1 |
768 | help | 768 | help |
769 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | 769 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. |
770 | 770 | ||
771 | config UART1_RTS_PIN | 771 | config UART1_RTS_PIN |
772 | int "UART1 RTS pin" | 772 | int "UART1 RTS pin" |
773 | depends on BFIN_UART1_CTSRTS && !BF54x | 773 | depends on BFIN_UART1_CTSRTS && !BF548 |
774 | default -1 | 774 | default -1 |
775 | help | 775 | help |
776 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | 776 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. |
@@ -790,14 +790,14 @@ config BFIN_UART2_CTSRTS | |||
790 | 790 | ||
791 | config UART2_CTS_PIN | 791 | config UART2_CTS_PIN |
792 | int "UART2 CTS pin" | 792 | int "UART2 CTS pin" |
793 | depends on BFIN_UART2_CTSRTS | 793 | depends on BFIN_UART2_CTSRTS && !BF548 |
794 | default -1 | 794 | default -1 |
795 | help | 795 | help |
796 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | 796 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. |
797 | 797 | ||
798 | config UART2_RTS_PIN | 798 | config UART2_RTS_PIN |
799 | int "UART2 RTS pin" | 799 | int "UART2 RTS pin" |
800 | depends on BFIN_UART2_CTSRTS | 800 | depends on BFIN_UART2_CTSRTS && !BF548 |
801 | default -1 | 801 | default -1 |
802 | help | 802 | help |
803 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | 803 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. |
@@ -815,6 +815,20 @@ config BFIN_UART3_CTSRTS | |||
815 | Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS | 815 | Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS |
816 | signal. | 816 | signal. |
817 | 817 | ||
818 | config UART3_CTS_PIN | ||
819 | int "UART3 CTS pin" | ||
820 | depends on BFIN_UART3_CTSRTS && !BF548 | ||
821 | default -1 | ||
822 | help | ||
823 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | ||
824 | |||
825 | config UART3_RTS_PIN | ||
826 | int "UART3 RTS pin" | ||
827 | depends on BFIN_UART3_CTSRTS && !BF548 | ||
828 | default -1 | ||
829 | help | ||
830 | Refer to ./include/asm-blackfin/gpio.h to see the GPIO map. | ||
831 | |||
818 | config SERIAL_IMX | 832 | config SERIAL_IMX |
819 | bool "IMX serial port support" | 833 | bool "IMX serial port support" |
820 | depends on ARM && (ARCH_IMX || ARCH_MXC) | 834 | depends on ARM && (ARCH_IMX || ARCH_MXC) |
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 | ||
73 | static void bfin_serial_reset_irda(struct uart_port *port); | 73 | static 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) | ||
77 | static 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 | |||
90 | static 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 | */ | ||
106 | static 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 | ||
122 | static unsigned int bfin_serial_get_mctrl(struct uart_port *port) | ||
123 | { | ||
124 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | ||
125 | } | ||
126 | |||
127 | static 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 | ||
484 | static 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 | |||
498 | static 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 | */ | ||
516 | static 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 | */ | ||
531 | static void bfin_serial_break_ctl(struct uart_port *port, int break_state) | 561 | static 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 | ||
705 | static void | 765 | static 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 |