diff options
author | NeilBrown <neilb@suse.de> | 2012-07-29 20:30:26 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-16 15:10:43 -0400 |
commit | 9574f36fb801035f6ab0fbb1b53ce2c12c17d100 (patch) | |
tree | feb4794a8c1a54b5fb0e3024b836e93f2a39f36e /drivers | |
parent | a92098a1cb7ec08c86d1b97d1831d8edaf26b1a2 (diff) |
OMAP/serial: Add support for driving a GPIO as DTR.
OMAP hardware doesn't provide a phyisical DTR line, but
some configurations may need a DTR line which tracks whether
the device is open or not.
So allow a gpio to be configured as the DTR line.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d3cda0cb2df0..aa603f221c6a 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
40 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
41 | #include <linux/of.h> | 41 | #include <linux/of.h> |
42 | #include <linux/gpio.h> | ||
42 | 43 | ||
43 | #include <plat/dma.h> | 44 | #include <plat/dma.h> |
44 | #include <plat/dmtimer.h> | 45 | #include <plat/dmtimer.h> |
@@ -507,6 +508,16 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
507 | up->mcr |= mcr; | 508 | up->mcr |= mcr; |
508 | serial_out(up, UART_MCR, up->mcr); | 509 | serial_out(up, UART_MCR, up->mcr); |
509 | pm_runtime_put(&up->pdev->dev); | 510 | pm_runtime_put(&up->pdev->dev); |
511 | |||
512 | if (gpio_is_valid(up->DTR_gpio) && | ||
513 | !!(mctrl & TIOCM_DTR) != up->DTR_active) { | ||
514 | up->DTR_active = !up->DTR_active; | ||
515 | if (gpio_cansleep(up->DTR_gpio)) | ||
516 | schedule_work(&up->qos_work); | ||
517 | else | ||
518 | gpio_set_value(up->DTR_gpio, | ||
519 | up->DTR_active != up->DTR_inverted); | ||
520 | } | ||
510 | } | 521 | } |
511 | 522 | ||
512 | static void serial_omap_break_ctl(struct uart_port *port, int break_state) | 523 | static void serial_omap_break_ctl(struct uart_port *port, int break_state) |
@@ -715,6 +726,9 @@ static void serial_omap_uart_qos_work(struct work_struct *work) | |||
715 | qos_work); | 726 | qos_work); |
716 | 727 | ||
717 | pm_qos_update_request(&up->pm_qos_request, up->latency); | 728 | pm_qos_update_request(&up->pm_qos_request, up->latency); |
729 | if (gpio_is_valid(up->DTR_gpio)) | ||
730 | gpio_set_value_cansleep(up->DTR_gpio, | ||
731 | up->DTR_active != up->DTR_inverted); | ||
718 | } | 732 | } |
719 | 733 | ||
720 | static void | 734 | static void |
@@ -1435,7 +1449,7 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1435 | struct uart_omap_port *up; | 1449 | struct uart_omap_port *up; |
1436 | struct resource *mem, *irq, *dma_tx, *dma_rx; | 1450 | struct resource *mem, *irq, *dma_tx, *dma_rx; |
1437 | struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; | 1451 | struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; |
1438 | int ret = -ENOSPC; | 1452 | int ret; |
1439 | 1453 | ||
1440 | if (pdev->dev.of_node) | 1454 | if (pdev->dev.of_node) |
1441 | omap_up_info = of_get_uart_port_info(&pdev->dev); | 1455 | omap_up_info = of_get_uart_port_info(&pdev->dev); |
@@ -1466,10 +1480,29 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1466 | if (!dma_tx) | 1480 | if (!dma_tx) |
1467 | return -ENXIO; | 1481 | return -ENXIO; |
1468 | 1482 | ||
1483 | if (gpio_is_valid(omap_up_info->DTR_gpio) && | ||
1484 | omap_up_info->DTR_present) { | ||
1485 | ret = gpio_request(omap_up_info->DTR_gpio, "omap-serial"); | ||
1486 | if (ret < 0) | ||
1487 | return ret; | ||
1488 | ret = gpio_direction_output(omap_up_info->DTR_gpio, | ||
1489 | omap_up_info->DTR_inverted); | ||
1490 | if (ret < 0) | ||
1491 | return ret; | ||
1492 | } | ||
1493 | |||
1469 | up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL); | 1494 | up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL); |
1470 | if (!up) | 1495 | if (!up) |
1471 | return -ENOMEM; | 1496 | return -ENOMEM; |
1472 | 1497 | ||
1498 | if (gpio_is_valid(omap_up_info->DTR_gpio) && | ||
1499 | omap_up_info->DTR_present) { | ||
1500 | up->DTR_gpio = omap_up_info->DTR_gpio; | ||
1501 | up->DTR_inverted = omap_up_info->DTR_inverted; | ||
1502 | } else | ||
1503 | up->DTR_gpio = -EINVAL; | ||
1504 | up->DTR_active = 0; | ||
1505 | |||
1473 | up->pdev = pdev; | 1506 | up->pdev = pdev; |
1474 | up->port.dev = &pdev->dev; | 1507 | up->port.dev = &pdev->dev; |
1475 | up->port.type = PORT_OMAP; | 1508 | up->port.type = PORT_OMAP; |