Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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_poll_rate = info->dma_rx_poll_rate;
	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_size = sizeof(struct omap_uart_port_info);
+7 −0
Original line number Diff line number Diff line
@@ -69,6 +69,9 @@ struct omap_uart_port_info {
	unsigned int		dma_rx_timeout;
	unsigned int		autosuspend_timeout;
	unsigned int		dma_rx_poll_rate;
	int			DTR_gpio;
	int			DTR_inverted;
	int			DTR_present;

	int (*get_context_loss_count)(struct device *);
	void (*set_forceidle)(struct platform_device *);
@@ -131,6 +134,10 @@ struct uart_omap_port {
	u32			errata;
	u8			wakeups_enabled;

	int			DTR_gpio;
	int			DTR_inverted;
	int			DTR_active;

	struct pm_qos_request	pm_qos_request;
	u32			latency;
	u32			calc_latency;
+34 −1
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <linux/irq.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/gpio.h>

#include <plat/dma.h>
#include <plat/dmtimer.h>
@@ -507,6 +508,16 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
	up->mcr |= mcr;
	serial_out(up, UART_MCR, up->mcr);
	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)
@@ -715,6 +726,9 @@ static void serial_omap_uart_qos_work(struct work_struct *work)
						qos_work);

	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
@@ -1435,7 +1449,7 @@ static int serial_omap_probe(struct platform_device *pdev)
	struct uart_omap_port	*up;
	struct resource		*mem, *irq, *dma_tx, *dma_rx;
	struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
	int ret = -ENOSPC;
	int ret;

	if (pdev->dev.of_node)
		omap_up_info = of_get_uart_port_info(&pdev->dev);
@@ -1466,10 +1480,29 @@ static int serial_omap_probe(struct platform_device *pdev)
	if (!dma_tx)
		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);
	if (!up)
		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->port.dev = &pdev->dev;
	up->port.type = PORT_OMAP;