Commit 9574f36f authored by NeilBrown's avatar NeilBrown Committed by Greg Kroah-Hartman

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: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a92098a1
...@@ -304,6 +304,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, ...@@ -304,6 +304,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
omap_up.dma_rx_timeout = info->dma_rx_timeout; omap_up.dma_rx_timeout = info->dma_rx_timeout;
omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate; omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
omap_up.autosuspend_timeout = info->autosuspend_timeout; omap_up.autosuspend_timeout = info->autosuspend_timeout;
omap_up.DTR_gpio = info->DTR_gpio;
omap_up.DTR_inverted = info->DTR_inverted;
omap_up.DTR_present = info->DTR_present;
pdata = &omap_up; pdata = &omap_up;
pdata_size = sizeof(struct omap_uart_port_info); pdata_size = sizeof(struct omap_uart_port_info);
......
...@@ -69,6 +69,9 @@ struct omap_uart_port_info { ...@@ -69,6 +69,9 @@ struct omap_uart_port_info {
unsigned int dma_rx_timeout; unsigned int dma_rx_timeout;
unsigned int autosuspend_timeout; unsigned int autosuspend_timeout;
unsigned int dma_rx_poll_rate; unsigned int dma_rx_poll_rate;
int DTR_gpio;
int DTR_inverted;
int DTR_present;
int (*get_context_loss_count)(struct device *); int (*get_context_loss_count)(struct device *);
void (*set_forceidle)(struct platform_device *); void (*set_forceidle)(struct platform_device *);
...@@ -131,6 +134,10 @@ struct uart_omap_port { ...@@ -131,6 +134,10 @@ struct uart_omap_port {
u32 errata; u32 errata;
u8 wakeups_enabled; u8 wakeups_enabled;
int DTR_gpio;
int DTR_inverted;
int DTR_active;
struct pm_qos_request pm_qos_request; struct pm_qos_request pm_qos_request;
u32 latency; u32 latency;
u32 calc_latency; u32 calc_latency;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/gpio.h>
#include <plat/dma.h> #include <plat/dma.h>
#include <plat/dmtimer.h> #include <plat/dmtimer.h>
...@@ -507,6 +508,16 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) ...@@ -507,6 +508,16 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
up->mcr |= mcr; up->mcr |= mcr;
serial_out(up, UART_MCR, up->mcr); serial_out(up, UART_MCR, up->mcr);
pm_runtime_put(&up->pdev->dev); pm_runtime_put(&up->pdev->dev);
if (gpio_is_valid(up->DTR_gpio) &&
!!(mctrl & TIOCM_DTR) != up->DTR_active) {
up->DTR_active = !up->DTR_active;
if (gpio_cansleep(up->DTR_gpio))
schedule_work(&up->qos_work);
else
gpio_set_value(up->DTR_gpio,
up->DTR_active != up->DTR_inverted);
}
} }
static void serial_omap_break_ctl(struct uart_port *port, int break_state) 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,6 +726,9 @@ static void serial_omap_uart_qos_work(struct work_struct *work)
qos_work); qos_work);
pm_qos_update_request(&up->pm_qos_request, up->latency); pm_qos_update_request(&up->pm_qos_request, up->latency);
if (gpio_is_valid(up->DTR_gpio))
gpio_set_value_cansleep(up->DTR_gpio,
up->DTR_active != up->DTR_inverted);
} }
static void static void
...@@ -1435,7 +1449,7 @@ static int serial_omap_probe(struct platform_device *pdev) ...@@ -1435,7 +1449,7 @@ static int serial_omap_probe(struct platform_device *pdev)
struct uart_omap_port *up; struct uart_omap_port *up;
struct resource *mem, *irq, *dma_tx, *dma_rx; struct resource *mem, *irq, *dma_tx, *dma_rx;
struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
int ret = -ENOSPC; int ret;
if (pdev->dev.of_node) if (pdev->dev.of_node)
omap_up_info = of_get_uart_port_info(&pdev->dev); omap_up_info = of_get_uart_port_info(&pdev->dev);
...@@ -1466,10 +1480,29 @@ static int serial_omap_probe(struct platform_device *pdev) ...@@ -1466,10 +1480,29 @@ static int serial_omap_probe(struct platform_device *pdev)
if (!dma_tx) if (!dma_tx)
return -ENXIO; return -ENXIO;
if (gpio_is_valid(omap_up_info->DTR_gpio) &&
omap_up_info->DTR_present) {
ret = gpio_request(omap_up_info->DTR_gpio, "omap-serial");
if (ret < 0)
return ret;
ret = gpio_direction_output(omap_up_info->DTR_gpio,
omap_up_info->DTR_inverted);
if (ret < 0)
return ret;
}
up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL); up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);
if (!up) if (!up)
return -ENOMEM; return -ENOMEM;
if (gpio_is_valid(omap_up_info->DTR_gpio) &&
omap_up_info->DTR_present) {
up->DTR_gpio = omap_up_info->DTR_gpio;
up->DTR_inverted = omap_up_info->DTR_inverted;
} else
up->DTR_gpio = -EINVAL;
up->DTR_active = 0;
up->pdev = pdev; up->pdev = pdev;
up->port.dev = &pdev->dev; up->port.dev = &pdev->dev;
up->port.type = PORT_OMAP; up->port.type = PORT_OMAP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment