aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-07-29 20:30:26 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-08-16 15:10:43 -0400
commit9574f36fb801035f6ab0fbb1b53ce2c12c17d100 (patch)
treefeb4794a8c1a54b5fb0e3024b836e93f2a39f36e
parenta92098a1cb7ec08c86d1b97d1831d8edaf26b1a2 (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>
-rw-r--r--arch/arm/mach-omap2/serial.c3
-rw-r--r--arch/arm/plat-omap/include/plat/omap-serial.h7
-rw-r--r--drivers/tty/serial/omap-serial.c35
3 files changed, 44 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index c1b93c752d70..25d53b2800c1 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -304,6 +304,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
304 omap_up.dma_rx_timeout = info->dma_rx_timeout; 304 omap_up.dma_rx_timeout = info->dma_rx_timeout;
305 omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate; 305 omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
306 omap_up.autosuspend_timeout = info->autosuspend_timeout; 306 omap_up.autosuspend_timeout = info->autosuspend_timeout;
307 omap_up.DTR_gpio = info->DTR_gpio;
308 omap_up.DTR_inverted = info->DTR_inverted;
309 omap_up.DTR_present = info->DTR_present;
307 310
308 pdata = &omap_up; 311 pdata = &omap_up;
309 pdata_size = sizeof(struct omap_uart_port_info); 312 pdata_size = sizeof(struct omap_uart_port_info);
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 1a52725ffcf2..52d3de45745f 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -69,6 +69,9 @@ struct omap_uart_port_info {
69 unsigned int dma_rx_timeout; 69 unsigned int dma_rx_timeout;
70 unsigned int autosuspend_timeout; 70 unsigned int autosuspend_timeout;
71 unsigned int dma_rx_poll_rate; 71 unsigned int dma_rx_poll_rate;
72 int DTR_gpio;
73 int DTR_inverted;
74 int DTR_present;
72 75
73 int (*get_context_loss_count)(struct device *); 76 int (*get_context_loss_count)(struct device *);
74 void (*set_forceidle)(struct platform_device *); 77 void (*set_forceidle)(struct platform_device *);
@@ -131,6 +134,10 @@ struct uart_omap_port {
131 u32 errata; 134 u32 errata;
132 u8 wakeups_enabled; 135 u8 wakeups_enabled;
133 136
137 int DTR_gpio;
138 int DTR_inverted;
139 int DTR_active;
140
134 struct pm_qos_request pm_qos_request; 141 struct pm_qos_request pm_qos_request;
135 u32 latency; 142 u32 latency;
136 u32 calc_latency; 143 u32 calc_latency;
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
512static void serial_omap_break_ctl(struct uart_port *port, int break_state) 523static 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
720static void 734static 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;