diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2010-03-09 12:25:33 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-21 12:34:27 -0400 |
commit | 1f7d1c85df5b63359e7f7e3fbd1509c1cdd6414f (patch) | |
tree | a25db974be00d82156479e705a6ced9f8f84b0e3 /drivers/serial | |
parent | b59588aae8356caf52b653a7c448c3fffdd27628 (diff) |
serial: bfin_sport_uart: add support for CTS/RTS via GPIOs
Some people need flow control on their ports, so now boards can support
that via any GPIOs.
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 24 | ||||
-rw-r--r-- | drivers/serial/bfin_sport_uart.c | 111 | ||||
-rw-r--r-- | drivers/serial/bfin_sport_uart.h | 11 |
3 files changed, 135 insertions, 11 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 302836a80693..63258305c057 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -1443,24 +1443,48 @@ config SERIAL_BFIN_SPORT0_UART | |||
1443 | help | 1443 | help |
1444 | Enable UART over SPORT0 | 1444 | Enable UART over SPORT0 |
1445 | 1445 | ||
1446 | config SERIAL_BFIN_SPORT0_UART_CTSRTS | ||
1447 | bool "Enable UART over SPORT0 hardware flow control" | ||
1448 | depends on SERIAL_BFIN_SPORT0_UART | ||
1449 | help | ||
1450 | Enable hardware flow control in the driver. | ||
1451 | |||
1446 | config SERIAL_BFIN_SPORT1_UART | 1452 | config SERIAL_BFIN_SPORT1_UART |
1447 | bool "Enable UART over SPORT1" | 1453 | bool "Enable UART over SPORT1" |
1448 | depends on SERIAL_BFIN_SPORT | 1454 | depends on SERIAL_BFIN_SPORT |
1449 | help | 1455 | help |
1450 | Enable UART over SPORT1 | 1456 | Enable UART over SPORT1 |
1451 | 1457 | ||
1458 | config SERIAL_BFIN_SPORT1_UART_CTSRTS | ||
1459 | bool "Enable UART over SPORT1 hardware flow control" | ||
1460 | depends on SERIAL_BFIN_SPORT1_UART | ||
1461 | help | ||
1462 | Enable hardware flow control in the driver. | ||
1463 | |||
1452 | config SERIAL_BFIN_SPORT2_UART | 1464 | config SERIAL_BFIN_SPORT2_UART |
1453 | bool "Enable UART over SPORT2" | 1465 | bool "Enable UART over SPORT2" |
1454 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) | 1466 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) |
1455 | help | 1467 | help |
1456 | Enable UART over SPORT2 | 1468 | Enable UART over SPORT2 |
1457 | 1469 | ||
1470 | config SERIAL_BFIN_SPORT2_UART_CTSRTS | ||
1471 | bool "Enable UART over SPORT2 hardware flow control" | ||
1472 | depends on SERIAL_BFIN_SPORT2_UART | ||
1473 | help | ||
1474 | Enable hardware flow control in the driver. | ||
1475 | |||
1458 | config SERIAL_BFIN_SPORT3_UART | 1476 | config SERIAL_BFIN_SPORT3_UART |
1459 | bool "Enable UART over SPORT3" | 1477 | bool "Enable UART over SPORT3" |
1460 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) | 1478 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) |
1461 | help | 1479 | help |
1462 | Enable UART over SPORT3 | 1480 | Enable UART over SPORT3 |
1463 | 1481 | ||
1482 | config SERIAL_BFIN_SPORT3_UART_CTSRTS | ||
1483 | bool "Enable UART over SPORT3 hardware flow control" | ||
1484 | depends on SERIAL_BFIN_SPORT3_UART | ||
1485 | help | ||
1486 | Enable hardware flow control in the driver. | ||
1487 | |||
1464 | config SERIAL_TIMBERDALE | 1488 | config SERIAL_TIMBERDALE |
1465 | tristate "Support for timberdale UART" | 1489 | tristate "Support for timberdale UART" |
1466 | select SERIAL_CORE | 1490 | select SERIAL_CORE |
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index 79252664f706..8cb0a40c2baa 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c | |||
@@ -48,6 +48,10 @@ struct sport_uart_port { | |||
48 | unsigned short txmask2; | 48 | unsigned short txmask2; |
49 | unsigned char stopb; | 49 | unsigned char stopb; |
50 | /* unsigned char parib; */ | 50 | /* unsigned char parib; */ |
51 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS | ||
52 | int cts_pin; | ||
53 | int rts_pin; | ||
54 | #endif | ||
51 | }; | 55 | }; |
52 | 56 | ||
53 | static void sport_uart_tx_chars(struct sport_uart_port *up); | 57 | static void sport_uart_tx_chars(struct sport_uart_port *up); |
@@ -198,6 +202,59 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) | |||
198 | return IRQ_HANDLED; | 202 | return IRQ_HANDLED; |
199 | } | 203 | } |
200 | 204 | ||
205 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS | ||
206 | static unsigned int sport_get_mctrl(struct uart_port *port) | ||
207 | { | ||
208 | struct sport_uart_port *up = (struct sport_uart_port *)port; | ||
209 | if (up->cts_pin < 0) | ||
210 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | ||
211 | |||
212 | /* CTS PIN is negative assertive. */ | ||
213 | if (SPORT_UART_GET_CTS(up)) | ||
214 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | ||
215 | else | ||
216 | return TIOCM_DSR | TIOCM_CAR; | ||
217 | } | ||
218 | |||
219 | static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
220 | { | ||
221 | struct sport_uart_port *up = (struct sport_uart_port *)port; | ||
222 | if (up->rts_pin < 0) | ||
223 | return; | ||
224 | |||
225 | /* RTS PIN is negative assertive. */ | ||
226 | if (mctrl & TIOCM_RTS) | ||
227 | SPORT_UART_ENABLE_RTS(up); | ||
228 | else | ||
229 | SPORT_UART_DISABLE_RTS(up); | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Handle any change of modem status signal. | ||
234 | */ | ||
235 | static irqreturn_t sport_mctrl_cts_int(int irq, void *dev_id) | ||
236 | { | ||
237 | struct sport_uart_port *up = (struct sport_uart_port *)dev_id; | ||
238 | unsigned int status; | ||
239 | |||
240 | status = sport_get_mctrl(&up->port); | ||
241 | uart_handle_cts_change(&up->port, status & TIOCM_CTS); | ||
242 | |||
243 | return IRQ_HANDLED; | ||
244 | } | ||
245 | #else | ||
246 | static unsigned int sport_get_mctrl(struct uart_port *port) | ||
247 | { | ||
248 | pr_debug("%s enter\n", __func__); | ||
249 | return TIOCM_CTS | TIOCM_CD | TIOCM_DSR; | ||
250 | } | ||
251 | |||
252 | static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
253 | { | ||
254 | pr_debug("%s enter\n", __func__); | ||
255 | } | ||
256 | #endif | ||
257 | |||
201 | /* Reqeust IRQ, Setup clock */ | 258 | /* Reqeust IRQ, Setup clock */ |
202 | static int sport_startup(struct uart_port *port) | 259 | static int sport_startup(struct uart_port *port) |
203 | { | 260 | { |
@@ -226,6 +283,21 @@ static int sport_startup(struct uart_port *port) | |||
226 | goto fail2; | 283 | goto fail2; |
227 | } | 284 | } |
228 | 285 | ||
286 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS | ||
287 | if (up->cts_pin >= 0) { | ||
288 | if (request_irq(gpio_to_irq(up->cts_pin), | ||
289 | sport_mctrl_cts_int, | ||
290 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | | ||
291 | IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) { | ||
292 | up->cts_pin = -1; | ||
293 | dev_info(port->dev, "Unable to attach BlackFin UART \ | ||
294 | over SPORT CTS interrupt. So, disable it.\n"); | ||
295 | } | ||
296 | } | ||
297 | if (up->rts_pin >= 0) | ||
298 | gpio_direction_output(up->rts_pin, 0); | ||
299 | #endif | ||
300 | |||
229 | return 0; | 301 | return 0; |
230 | fail2: | 302 | fail2: |
231 | free_irq(up->port.irq+1, up); | 303 | free_irq(up->port.irq+1, up); |
@@ -283,17 +355,6 @@ static unsigned int sport_tx_empty(struct uart_port *port) | |||
283 | return 0; | 355 | return 0; |
284 | } | 356 | } |
285 | 357 | ||
286 | static unsigned int sport_get_mctrl(struct uart_port *port) | ||
287 | { | ||
288 | pr_debug("%s enter\n", __func__); | ||
289 | return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR); | ||
290 | } | ||
291 | |||
292 | static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
293 | { | ||
294 | pr_debug("%s enter\n", __func__); | ||
295 | } | ||
296 | |||
297 | static void sport_stop_tx(struct uart_port *port) | 358 | static void sport_stop_tx(struct uart_port *port) |
298 | { | 359 | { |
299 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 360 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
@@ -364,6 +425,10 @@ static void sport_shutdown(struct uart_port *port) | |||
364 | free_irq(up->port.irq, up); | 425 | free_irq(up->port.irq, up); |
365 | free_irq(up->port.irq+1, up); | 426 | free_irq(up->port.irq+1, up); |
366 | free_irq(up->err_irq, up); | 427 | free_irq(up->err_irq, up); |
428 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS | ||
429 | if (up->cts_pin >= 0) | ||
430 | free_irq(gpio_to_irq(up->cts_pin), up); | ||
431 | #endif | ||
367 | } | 432 | } |
368 | 433 | ||
369 | static const char *sport_type(struct uart_port *port) | 434 | static const char *sport_type(struct uart_port *port) |
@@ -536,7 +601,11 @@ sport_uart_console_setup(struct console *co, char *options) | |||
536 | int baud = 57600; | 601 | int baud = 57600; |
537 | int bits = 8; | 602 | int bits = 8; |
538 | int parity = 'n'; | 603 | int parity = 'n'; |
604 | # ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS | ||
605 | int flow = 'r'; | ||
606 | # else | ||
539 | int flow = 'n'; | 607 | int flow = 'n'; |
608 | # endif | ||
540 | 609 | ||
541 | /* Check whether an invalid uart number has been specified */ | 610 | /* Check whether an invalid uart number has been specified */ |
542 | if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS) | 611 | if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS) |
@@ -729,6 +798,22 @@ static int __devinit sport_uart_probe(struct platform_device *pdev) | |||
729 | ret = -ENOENT; | 798 | ret = -ENOENT; |
730 | goto out_error_unmap; | 799 | goto out_error_unmap; |
731 | } | 800 | } |
801 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS | ||
802 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
803 | if (res == NULL) | ||
804 | sport->cts_pin = -1; | ||
805 | else | ||
806 | sport->cts_pin = res->start; | ||
807 | |||
808 | res = platform_get_resource(pdev, IORESOURCE_IO, 1); | ||
809 | if (res == NULL) | ||
810 | sport->rts_pin = -1; | ||
811 | else | ||
812 | sport->rts_pin = res->start; | ||
813 | |||
814 | if (sport->rts_pin >= 0) | ||
815 | gpio_request(sport->rts_pin, DRV_NAME); | ||
816 | #endif | ||
732 | } | 817 | } |
733 | 818 | ||
734 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE | 819 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE |
@@ -767,6 +852,10 @@ static int __devexit sport_uart_remove(struct platform_device *pdev) | |||
767 | 852 | ||
768 | if (sport) { | 853 | if (sport) { |
769 | uart_remove_one_port(&sport_uart_reg, &sport->port); | 854 | uart_remove_one_port(&sport_uart_reg, &sport->port); |
855 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | ||
856 | if (sport->rts_pin >= 0) | ||
857 | gpio_free(sport->rts_pin); | ||
858 | #endif | ||
770 | iounmap(sport->port.membase); | 859 | iounmap(sport->port.membase); |
771 | peripheral_free_list( | 860 | peripheral_free_list( |
772 | (unsigned short *)pdev->dev.platform_data); | 861 | (unsigned short *)pdev->dev.platform_data); |
diff --git a/drivers/serial/bfin_sport_uart.h b/drivers/serial/bfin_sport_uart.h index 9791fcc80a74..9ce253e381d2 100644 --- a/drivers/serial/bfin_sport_uart.h +++ b/drivers/serial/bfin_sport_uart.h | |||
@@ -72,4 +72,15 @@ | |||
72 | 72 | ||
73 | #define SPORT_TX_FIFO_SIZE 8 | 73 | #define SPORT_TX_FIFO_SIZE 8 |
74 | 74 | ||
75 | #define SPORT_UART_GET_CTS(x) gpio_get_value(x->cts_pin) | ||
76 | #define SPORT_UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1) | ||
77 | #define SPORT_UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0) | ||
78 | |||
79 | #if defined(CONFIG_SERIAL_BFIN_SPORT0_UART_CTSRTS) \ | ||
80 | || defined(CONFIG_SERIAL_BFIN_SPORT1_UART_CTSRTS) \ | ||
81 | || defined(CONFIG_SERIAL_BFIN_SPORT2_UART_CTSRTS) \ | ||
82 | || defined(CONFIG_SERIAL_BFIN_SPORT3_UART_CTSRTS) | ||
83 | # define CONFIG_SERIAL_BFIN_SPORT_CTSRTS | ||
84 | #endif | ||
85 | |||
75 | #endif /* _BFIN_SPORT_UART_H */ | 86 | #endif /* _BFIN_SPORT_UART_H */ |