linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial.
@ 2014-02-07 14:59 Richard Genoud
  2014-02-07 14:59 ` [PATCH 1/8] tty/serial: at91: use dev_err instead of printk Richard Genoud
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

The USART controller on sam9x5 chips (and also all AT91/SAMA5 chips
but at91rm9200) are not capable of handling DTR/DSR/DCD/RI signal.
Moreover, even if the controller can handle CTS/RTS, the dedicated
CTS/RTS pins are already muxed for other peripherals (LCDC/EMAC/MMC).

So this patchset adds the possibility to control those lines via GPIO,
as it is done for RTS in the patch "switch atmel serial to use gpiolib"

With all those signals, you'll finally get the best out of your brand
new 33600 baud modem \o/.

And with the Ring Indicator, Atmel boards can now answer the phone !


This is based on 3.14-rc1 + Linus Walleij/Nicolas Ferre's patch:
 354e57f3a0a2 ARM/serial: at91: switch atmel serial to use gpiolib
(in Uwe's tree git://git.pengutronix.de/git/ukl/linux.git dropmachtimexh )

Tested on at91sam9g35, with a null modem cable between 2 serial ports,
one with CTS/RTS controlled by the USART controller, the other via GPIO,
full duplex transfers.
Did some tests also with null modem cables on a PC.

Richard Genoud (8):
  tty/serial: at91: use dev_err instead of printk
  tty/serial: at91: remove unused open/close hooks
  tty/serial: at91: prepare for more gpio lines to come
  tty/serial: at91: add cts control via gpio
  tty/serial: at91: add dtr control via gpio
  tty/serial: at91: add dsr control via gpio
  tty/serial: at91: add ring control via gpio
  tty/serial: at91: add dcd control via gpio

 .../devicetree/bindings/serial/atmel-usart.txt     |  15 +
 arch/arm/mach-at91/at91rm9200_devices.c            |  25 ++
 arch/arm/mach-at91/at91sam9260_devices.c           |  35 +++
 arch/arm/mach-at91/at91sam9261_devices.c           |  20 ++
 arch/arm/mach-at91/at91sam9263_devices.c           |  20 ++
 arch/arm/mach-at91/at91sam9g45_devices.c           |  25 ++
 arch/arm/mach-at91/at91sam9rl_devices.c            |  25 ++
 drivers/tty/serial/atmel_serial.c                  | 324 +++++++++++++++++----
 include/linux/platform_data/atmel.h                |   5 +
 9 files changed, 441 insertions(+), 53 deletions(-)

-- 
1.8.5

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/8] tty/serial: at91: use dev_err instead of printk
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  2014-02-07 14:59 ` [PATCH 2/8] tty/serial: at91: remove unused open/close hooks Richard Genoud
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

For better consistency.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 drivers/tty/serial/atmel_serial.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 91c0d8839570..ed9621a21d67 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1549,7 +1549,7 @@ static int atmel_startup(struct uart_port *port)
 	retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
 			tty ? tty->name : "atmel_serial", port);
 	if (retval) {
-		printk("atmel_serial: atmel_startup - Can't get irq\n");
+		dev_err(port->dev, "atmel_startup - Can't get irq\n");
 		return retval;
 	}
 
@@ -1732,7 +1732,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
 		clk_disable_unprepare(atmel_port->clk);
 		break;
 	default:
-		printk(KERN_ERR "atmel_serial: unknown pm %d\n", state);
+		dev_err(port->dev, "atmel_serial: unknown pm %d\n", state);
 	}
 }
 
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/8] tty/serial: at91: remove unused open/close hooks
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
  2014-02-07 14:59 ` [PATCH 1/8] tty/serial: at91: use dev_err instead of printk Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  2014-02-07 14:59 ` [PATCH 3/8] tty/serial: at91: prepare for more gpio lines to come Richard Genoud
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

commit 95e629b761ce36996d1befe2824d5346b5a220b9 removed the use of board
specific hooks in serial_at91.h, so now, the open/close hook are just
dead code.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 drivers/tty/serial/atmel_serial.c | 21 ---------------------
 1 file changed, 21 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index ed9621a21d67..a51b3a762948 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -112,9 +112,6 @@ static void atmel_stop_rx(struct uart_port *port);
 #define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
 #define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
 
-static int (*atmel_open_hook)(struct uart_port *);
-static void (*atmel_close_hook)(struct uart_port *);
-
 struct atmel_dma_buffer {
 	unsigned char	*buf;
 	dma_addr_t	dma_addr;
@@ -1569,17 +1566,6 @@ static int atmel_startup(struct uart_port *port)
 		if (retval < 0)
 			atmel_set_ops(port);
 	}
-	/*
-	 * If there is a specific "open" function (to register
-	 * control line interrupts)
-	 */
-	if (atmel_open_hook) {
-		retval = atmel_open_hook(port);
-		if (retval) {
-			free_irq(port->irq, port);
-			return retval;
-		}
-	}
 
 	/* Save current CSR for comparison in atmel_tasklet_func() */
 	atmel_port->irq_status_prev = UART_GET_CSR(port);
@@ -1678,13 +1664,6 @@ static void atmel_shutdown(struct uart_port *port)
 	 * Free the interrupt
 	 */
 	free_irq(port->irq, port);
-
-	/*
-	 * If there is a specific "close" function (to unregister
-	 * control line interrupts)
-	 */
-	if (atmel_close_hook)
-		atmel_close_hook(port);
 }
 
 /*
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/8] tty/serial: at91: prepare for more gpio lines to come
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
  2014-02-07 14:59 ` [PATCH 1/8] tty/serial: at91: use dev_err instead of printk Richard Genoud
  2014-02-07 14:59 ` [PATCH 2/8] tty/serial: at91: remove unused open/close hooks Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  2014-02-07 14:59 ` [PATCH 4/8] tty/serial: at91: add cts control via gpio Richard Genoud
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

There's no functionnal change, it will just be easier to review the
next patches.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 drivers/tty/serial/atmel_serial.c | 73 ++++++++++++++++++++++++++++-----------
 1 file changed, 53 insertions(+), 20 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index a51b3a762948..7ef99d7e070b 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -126,6 +126,10 @@ struct atmel_uart_char {
 
 #define ATMEL_SERIAL_RINGSIZE 1024
 
+struct gpio_lines {
+	int rts;	/* optional RTS GPIO */
+};
+
 /*
  * We wrap our port structure around the generic uart_port.
  */
@@ -162,7 +166,7 @@ struct atmel_uart_port {
 	struct circ_buf		rx_ring;
 
 	struct serial_rs485	rs485;		/* rs485 settings */
-	int			rts_gpio;	/* optional RTS GPIO */
+	struct gpio_lines	gpio;
 	unsigned int		tx_done_mask;
 	bool			is_usart;	/* usart or uart */
 	struct timer_list	uart_timer;	/* uart timer */
@@ -300,11 +304,11 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	 * AT91RM9200 Errata #39: RTS0 is not internally connected
 	 * to PA21. We need to drive the pin as a GPIO.
 	 */
-	if (gpio_is_valid(atmel_port->rts_gpio)) {
+	if (gpio_is_valid(atmel_port->gpio.rts)) {
 		if (mctrl & TIOCM_RTS)
-			gpio_set_value(atmel_port->rts_gpio, 0);
+			gpio_set_value(atmel_port->gpio.rts, 0);
 		else
-			gpio_set_value(atmel_port->rts_gpio, 1);
+			gpio_set_value(atmel_port->gpio.rts, 1);
 	}
 
 	if (mctrl & TIOCM_RTS)
@@ -2327,6 +2331,45 @@ static int atmel_serial_resume(struct platform_device *pdev)
 #define atmel_serial_resume NULL
 #endif
 
+static int atmel_request_gpio(struct device *dev, int gpio,
+			      const char *label, int *irq)
+{
+	int ret = 0;
+
+	if (gpio_is_valid(gpio)) {
+		ret = devm_gpio_request(dev, gpio, label);
+		if (ret) {
+			dev_err(dev, "error requesting %s GPIO\n", label);
+			goto err;
+		}
+
+		if (irq == NULL) {
+			/* Default to 1 as all signals are active low */
+			ret = gpio_direction_output(gpio, 1);
+		} else {
+			ret = gpio_direction_input(gpio);
+			*irq = gpio_to_irq(gpio);
+		}
+		if (ret) {
+			dev_err(dev, "error setting up %s GPIO\n", label);
+			goto err;
+		}
+	}
+
+err:
+	return ret;
+}
+
+static int atmel_init_gpios(struct atmel_uart_port *atmel_port,
+			    struct platform_device *pdev)
+{
+	int ret;
+
+	ret = atmel_request_gpio(&pdev->dev, atmel_port->gpio.rts,
+				 "RTS", NULL);
+	return ret;
+}
+
 static int atmel_serial_probe(struct platform_device *pdev)
 {
 	struct atmel_uart_port *port;
@@ -2362,25 +2405,15 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port = &atmel_ports[ret];
 	port->backup_imr = 0;
 	port->uart.line = ret;
-	port->rts_gpio = -EINVAL; /* Invalid, zero could be valid */
+	port->gpio.rts = -EINVAL; /* Invalid, zero could be valid */
 	if (pdata)
-		port->rts_gpio = pdata->rts_gpio;
+		port->gpio.rts = pdata->rts_gpio;
 	else if (np)
-		port->rts_gpio = of_get_named_gpio(np, "rts-gpios", 0);
+		port->gpio.rts = of_get_named_gpio(np, "rts-gpios", 0);
 
-	if (gpio_is_valid(port->rts_gpio)) {
-		ret = devm_gpio_request(&pdev->dev, port->rts_gpio, "RTS");
-		if (ret) {
-			dev_err(&pdev->dev, "error requesting RTS GPIO\n");
-			goto err;
-		}
-		/* Default to 1 as RTS is active low */
-		ret = gpio_direction_output(port->rts_gpio, 1);
-		if (ret) {
-			dev_err(&pdev->dev, "error setting up RTS GPIO\n");
-			goto err;
-		}
-	}
+	ret = atmel_init_gpios(port, pdev);
+	if (ret)
+		goto err;
 
 	ret = atmel_init_port(port, pdev);
 	if (ret)
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/8] tty/serial: at91: add cts control via gpio
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
                   ` (2 preceding siblings ...)
  2014-02-07 14:59 ` [PATCH 3/8] tty/serial: at91: prepare for more gpio lines to come Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  2014-02-07 14:59 ` [PATCH 5/8] tty/serial: at91: add dtr " Richard Genoud
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On sam9x5, dedicated CTS (and RTS) pins are unusable together with the
LCDC, the EMAC, or the MMC because they share the same line.

This patch permits to use a GPIO to control the CTS line.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 .../devicetree/bindings/serial/atmel-usart.txt     |   3 +
 arch/arm/mach-at91/at91rm9200_devices.c            |   5 +
 arch/arm/mach-at91/at91sam9260_devices.c           |   7 ++
 arch/arm/mach-at91/at91sam9261_devices.c           |   4 +
 arch/arm/mach-at91/at91sam9263_devices.c           |   4 +
 arch/arm/mach-at91/at91sam9g45_devices.c           |   5 +
 arch/arm/mach-at91/at91sam9rl_devices.c            |   5 +
 drivers/tty/serial/atmel_serial.c                  | 112 +++++++++++++++++++--
 include/linux/platform_data/atmel.h                |   1 +
 9 files changed, 136 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 17c1042b2df8..6c0898e4b58e 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -15,6 +15,8 @@ Optional properties:
 - atmel,use-dma-tx: use of PDC or DMA for transmitting data
 - rts-gpios: specify a GPIO for RTS line. It will use specified PIO instead of the peripheral
   function pin for the USART RTS feature. If unsure, don't specify this property.
+- cts-gpios: specify a GPIO for CTS line. It will use specified PIO instead of the peripheral
+  function pin for the USART CTS feature. If unsure, don't specify this property.
 - add dma bindings for dma transfer:
 	- dmas: DMA specifier, consisting of a phandle to DMA controller node,
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
@@ -36,6 +38,7 @@ Example:
 		atmel,use-dma-rx;
 		atmel,use-dma-tx;
 		rts-gpios = <&pioD 15 0>;
+		cts-gpios = <&pioD 16 0>;
 	};
 
 - use DMA:
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 605add05af7e..4688a85cabc4 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -923,6 +923,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -962,6 +963,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1013,6 +1015,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1065,6 +1068,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1109,6 +1113,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index b52527c78b12..5e8f0d1add1d 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -820,6 +820,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -859,6 +860,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -911,6 +913,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -955,6 +958,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -999,6 +1003,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
@@ -1043,6 +1048,7 @@ static struct atmel_uart_data uart4_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart4_dmamask = DMA_BIT_MASK(32);
@@ -1082,6 +1088,7 @@ static struct atmel_uart_data uart5_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart5_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 6c1a2ecc306f..f0ccc835e331 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -881,6 +881,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -920,6 +921,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -964,6 +966,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1008,6 +1011,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 97cc2a0d6f90..1e696ceacfaf 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1325,6 +1325,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1364,6 +1365,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1408,6 +1410,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1452,6 +1455,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index c10149588e21..b75eb826b803 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1588,6 +1588,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1627,6 +1628,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1671,6 +1673,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1715,6 +1718,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1759,6 +1763,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 4120af972b61..67bf5811b38f 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -957,6 +957,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -996,6 +997,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1048,6 +1050,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1092,6 +1095,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1136,6 +1140,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
+	.cts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 7ef99d7e070b..7a6b0506c050 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -43,6 +43,7 @@
 #include <linux/platform_data/atmel.h>
 #include <linux/timer.h>
 #include <linux/gpio.h>
+#include <linux/irq.h>
 
 #include <asm/io.h>
 #include <asm/ioctls.h>
@@ -55,6 +56,8 @@
 #define SUPPORT_SYSRQ
 #endif
 
+#define INVALID_IRQ  ((unsigned)-1)
+
 #include <linux/serial_core.h>
 
 static void atmel_start_rx(struct uart_port *port);
@@ -128,6 +131,8 @@ struct atmel_uart_char {
 
 struct gpio_lines {
 	int rts;	/* optional RTS GPIO */
+	int cts;	/* optional CTS GPIO */
+	int cts_irq;
 };
 
 /*
@@ -168,6 +173,7 @@ struct atmel_uart_port {
 	struct serial_rs485	rs485;		/* rs485 settings */
 	struct gpio_lines	gpio;
 	unsigned int		tx_done_mask;
+	bool			ms_irq_enabled;
 	bool			is_usart;	/* usart or uart */
 	struct timer_list	uart_timer;	/* uart timer */
 	int (*prepare_rx)(struct uart_port *port);
@@ -241,6 +247,23 @@ static bool atmel_use_dma_rx(struct uart_port *port)
 	return atmel_port->use_dma_rx;
 }
 
+static unsigned int atmel_get_lines_status(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	unsigned int status = 0;
+
+	status = UART_GET_CSR(port);
+
+	if (gpio_is_valid(atmel_port->gpio.cts)) {
+		if (gpio_get_value(atmel_port->gpio.cts))
+			status |= ATMEL_US_CTS;
+		else
+			status &= ~ATMEL_US_CTS;
+	}
+
+	return status;
+}
+
 /* Enable or disable the rs485 support */
 void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
 {
@@ -352,7 +375,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
 {
 	unsigned int status, ret = 0;
 
-	status = UART_GET_CSR(port);
+	status = atmel_get_lines_status(port);
 
 	/*
 	 * The control signals are active low.
@@ -453,8 +476,25 @@ static void atmel_stop_rx(struct uart_port *port)
  */
 static void atmel_enable_ms(struct uart_port *port)
 {
-	UART_PUT_IER(port, ATMEL_US_RIIC | ATMEL_US_DSRIC
-			| ATMEL_US_DCDIC | ATMEL_US_CTSIC);
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	uint32_t ier;
+
+	/*
+	 * Interrupt should not be enabled twice
+	 */
+	if (atmel_port->ms_irq_enabled)
+		return;
+
+	atmel_port->ms_irq_enabled = true;
+
+	ier = ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC;
+
+	if (atmel_port->gpio.cts_irq != INVALID_IRQ)
+		enable_irq(atmel_port->gpio.cts_irq);
+	else
+		ier |= ATMEL_US_CTSIC;
+
+	UART_PUT_IER(port, ier);
 }
 
 /*
@@ -522,7 +562,7 @@ static void atmel_rx_chars(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, ch;
 
-	status = UART_GET_CSR(port);
+	status = atmel_get_lines_status(port);
 	while (status & ATMEL_US_RXRDY) {
 		ch = UART_GET_CHAR(port);
 
@@ -556,7 +596,7 @@ static void atmel_rx_chars(struct uart_port *port)
 		}
 
 		atmel_buffer_rx_char(port, status, ch);
-		status = UART_GET_CSR(port);
+		status = atmel_get_lines_status(port);
 	}
 
 	tasklet_schedule(&atmel_port->tasklet);
@@ -1043,11 +1083,22 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
 static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, pending, pass_counter = 0;
+	bool gpio_handled = false;
 
 	do {
-		status = UART_GET_CSR(port);
+		status = atmel_get_lines_status(port);
 		pending = status & UART_GET_IMR(port);
+		if (!gpio_handled) {
+			/*
+			 * Dealing with GPIO interrupt
+			 */
+			if ((irq !=  INVALID_IRQ) &&
+			    (irq == atmel_port->gpio.cts_irq))
+				pending |= ATMEL_US_CTSIC;
+			gpio_handled = true;
+		}
 		if (!pending)
 			break;
 
@@ -1527,6 +1578,22 @@ static void atmel_get_ip_name(struct uart_port *port)
 	}
 }
 
+static int atmel_request_gpio_irq(struct uart_port *port, int irq,
+				  const char *name)
+{
+	int err = 0;
+
+	if (irq == INVALID_IRQ)
+		goto out;
+
+	irq_set_status_flags(irq, IRQ_NOAUTOEN);
+	err = request_irq(irq, atmel_interrupt, IRQ_TYPE_EDGE_BOTH, name, port);
+	if (err)
+		dev_err(port->dev, "atmel_startup - Can't get %s\n", name);
+out:
+	return err;
+}
+
 /*
  * Perform initialization and enable port for reception
  */
@@ -1543,6 +1610,7 @@ static int atmel_startup(struct uart_port *port)
 	 * handle an unexpected interrupt
 	 */
 	UART_PUT_IDR(port, -1);
+	atmel_port->ms_irq_enabled = false;
 
 	/*
 	 * Allocate the IRQ
@@ -1555,6 +1623,14 @@ static int atmel_startup(struct uart_port *port)
 	}
 
 	/*
+	 * Get the GPIO lines IRQ
+	 */
+	retval = atmel_request_gpio_irq(port, atmel_port->gpio.cts_irq,
+					"atmel_cts_irq");
+	if (retval)
+		goto free_ctrl_irq;
+
+	/*
 	 * Initialize DMA (if necessary)
 	 */
 	atmel_init_property(atmel_port, pdev);
@@ -1572,7 +1648,7 @@ static int atmel_startup(struct uart_port *port)
 	}
 
 	/* Save current CSR for comparison in atmel_tasklet_func() */
-	atmel_port->irq_status_prev = UART_GET_CSR(port);
+	atmel_port->irq_status_prev = atmel_get_lines_status(port);
 	atmel_port->irq_status = atmel_port->irq_status_prev;
 
 	/*
@@ -1618,6 +1694,11 @@ static int atmel_startup(struct uart_port *port)
 	}
 
 	return 0;
+
+free_ctrl_irq:
+	free_irq(port->irq, port);
+
+	return retval;
 }
 
 /*
@@ -1665,9 +1746,13 @@ static void atmel_shutdown(struct uart_port *port)
 	atmel_port->rx_ring.tail = 0;
 
 	/*
-	 * Free the interrupt
+	 * Free the interrupts
 	 */
 	free_irq(port->irq, port);
+	if (atmel_port->gpio.cts_irq != INVALID_IRQ)
+		free_irq(atmel_port->gpio.cts_irq, port);
+
+	atmel_port->ms_irq_enabled = false;
 }
 
 /*
@@ -2367,6 +2452,8 @@ static int atmel_init_gpios(struct atmel_uart_port *atmel_port,
 
 	ret = atmel_request_gpio(&pdev->dev, atmel_port->gpio.rts,
 				 "RTS", NULL);
+	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.cts,
+				  "CTS", &atmel_port->gpio.cts_irq);
 	return ret;
 }
 
@@ -2406,10 +2493,15 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port->backup_imr = 0;
 	port->uart.line = ret;
 	port->gpio.rts = -EINVAL; /* Invalid, zero could be valid */
-	if (pdata)
+	port->gpio.cts = -EINVAL;
+	port->gpio.cts_irq = INVALID_IRQ;
+	if (pdata) {
 		port->gpio.rts = pdata->rts_gpio;
-	else if (np)
+		port->gpio.cts = pdata->cts_gpio;
+	} else if (np) {
 		port->gpio.rts = of_get_named_gpio(np, "rts-gpios", 0);
+		port->gpio.cts = of_get_named_gpio(np, "cts-gpios", 0);
+	}
 
 	ret = atmel_init_gpios(port, pdev);
 	if (ret)
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index e26b0c14edea..166a99ca911f 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -85,6 +85,7 @@ struct atmel_uart_data {
 	void __iomem		*regs;		/* virt. base address, if any */
 	struct serial_rs485	rs485;		/* rs485 settings */
 	int			rts_gpio;	/* optional RTS GPIO */
+	int			cts_gpio;	/* optional CTS GPIO */
 };
 
  /* Touchscreen Controller */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/8] tty/serial: at91: add dtr control via gpio
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
                   ` (3 preceding siblings ...)
  2014-02-07 14:59 ` [PATCH 4/8] tty/serial: at91: add cts control via gpio Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  2014-02-07 15:21   ` Alexander Shiyan
  2014-02-07 14:59 ` [PATCH 6/8] tty/serial: at91: add dsr " Richard Genoud
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
so we have to control them via GPIO.

This patch permits to use a GPIO to control the DTR signal.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 Documentation/devicetree/bindings/serial/atmel-usart.txt |  3 +++
 arch/arm/mach-at91/at91rm9200_devices.c                  |  5 +++++
 arch/arm/mach-at91/at91sam9260_devices.c                 |  7 +++++++
 arch/arm/mach-at91/at91sam9261_devices.c                 |  4 ++++
 arch/arm/mach-at91/at91sam9263_devices.c                 |  4 ++++
 arch/arm/mach-at91/at91sam9g45_devices.c                 |  5 +++++
 arch/arm/mach-at91/at91sam9rl_devices.c                  |  5 +++++
 drivers/tty/serial/atmel_serial.c                        | 13 +++++++++++++
 include/linux/platform_data/atmel.h                      |  1 +
 9 files changed, 47 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 6c0898e4b58e..77d45c88b494 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -17,6 +17,8 @@ Optional properties:
   function pin for the USART RTS feature. If unsure, don't specify this property.
 - cts-gpios: specify a GPIO for CTS line. It will use specified PIO instead of the peripheral
   function pin for the USART CTS feature. If unsure, don't specify this property.
+- dtr-gpios: specify a GPIO for DTR line. It will use specified PIO instead of the peripheral
+  function pin for the USART DTR feature. If unsure, don't specify this property.
 - add dma bindings for dma transfer:
 	- dmas: DMA specifier, consisting of a phandle to DMA controller node,
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
@@ -39,6 +41,7 @@ Example:
 		atmel,use-dma-tx;
 		rts-gpios = <&pioD 15 0>;
 		cts-gpios = <&pioD 16 0>;
+		dtr-gpios = <&pioD 17 0>;
 	};
 
 - use DMA:
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 4688a85cabc4..d8523cc05157 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -924,6 +924,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -964,6 +965,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1016,6 +1018,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1069,6 +1072,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1114,6 +1118,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 5e8f0d1add1d..b8e325b00e1a 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -821,6 +821,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -861,6 +862,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -914,6 +916,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -959,6 +962,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1004,6 +1008,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
@@ -1049,6 +1054,7 @@ static struct atmel_uart_data uart4_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart4_dmamask = DMA_BIT_MASK(32);
@@ -1089,6 +1095,7 @@ static struct atmel_uart_data uart5_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart5_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index f0ccc835e331..3a05d9f09b0d 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -882,6 +882,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -922,6 +923,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -967,6 +969,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1012,6 +1015,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 1e696ceacfaf..d26255ba3907 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1326,6 +1326,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1366,6 +1367,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1411,6 +1413,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1456,6 +1459,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index b75eb826b803..67e9f7f259e1 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1589,6 +1589,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_rx	= 0,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1629,6 +1630,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1674,6 +1676,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1719,6 +1722,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1764,6 +1768,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 67bf5811b38f..94fecc40dbba 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -958,6 +958,7 @@ static struct atmel_uart_data dbgu_data = {
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -998,6 +999,7 @@ static struct atmel_uart_data uart0_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1051,6 +1053,7 @@ static struct atmel_uart_data uart1_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1096,6 +1099,7 @@ static struct atmel_uart_data uart2_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1141,6 +1145,7 @@ static struct atmel_uart_data uart3_data = {
 	.use_dma_rx	= 1,
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
+	.dtr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 7a6b0506c050..f5bdb84aed53 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -133,6 +133,7 @@ struct gpio_lines {
 	int rts;	/* optional RTS GPIO */
 	int cts;	/* optional CTS GPIO */
 	int cts_irq;
+	int dtr;	/* optional DTR GPIO */
 };
 
 /*
@@ -339,6 +340,13 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	else
 		control |= ATMEL_US_RTSDIS;
 
+	if (gpio_is_valid(atmel_port->gpio.dtr)) {
+		if (mctrl & TIOCM_DTR)
+			gpio_set_value(atmel_port->gpio.dtr, 0);
+		else
+			gpio_set_value(atmel_port->gpio.dtr, 1);
+	}
+
 	if (mctrl & TIOCM_DTR)
 		control |= ATMEL_US_DTREN;
 	else
@@ -2454,6 +2462,8 @@ static int atmel_init_gpios(struct atmel_uart_port *atmel_port,
 				 "RTS", NULL);
 	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.cts,
 				  "CTS", &atmel_port->gpio.cts_irq);
+	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.dtr,
+				  "DTR", NULL);
 	return ret;
 }
 
@@ -2494,13 +2504,16 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port->uart.line = ret;
 	port->gpio.rts = -EINVAL; /* Invalid, zero could be valid */
 	port->gpio.cts = -EINVAL;
+	port->gpio.dtr = -EINVAL;
 	port->gpio.cts_irq = INVALID_IRQ;
 	if (pdata) {
 		port->gpio.rts = pdata->rts_gpio;
 		port->gpio.cts = pdata->cts_gpio;
+		port->gpio.dtr = pdata->dtr_gpio;
 	} else if (np) {
 		port->gpio.rts = of_get_named_gpio(np, "rts-gpios", 0);
 		port->gpio.cts = of_get_named_gpio(np, "cts-gpios", 0);
+		port->gpio.dtr = of_get_named_gpio(np, "dtr-gpios", 0);
 	}
 
 	ret = atmel_init_gpios(port, pdev);
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 166a99ca911f..8472b6f3c618 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -86,6 +86,7 @@ struct atmel_uart_data {
 	struct serial_rs485	rs485;		/* rs485 settings */
 	int			rts_gpio;	/* optional RTS GPIO */
 	int			cts_gpio;	/* optional CTS GPIO */
+	int			dtr_gpio;	/* optional DTR GPIO */
 };
 
  /* Touchscreen Controller */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/8] tty/serial: at91: add dsr control via gpio
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
                   ` (4 preceding siblings ...)
  2014-02-07 14:59 ` [PATCH 5/8] tty/serial: at91: add dtr " Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  2014-02-07 14:59 ` [PATCH 7/8] tty/serial: at91: add ring " Richard Genoud
  2014-02-07 14:59 ` [PATCH 8/8] tty/serial: at91: add dcd " Richard Genoud
  7 siblings, 0 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
so we have to control them via GPIO.

This patch permits to use a GPIO to control the DSR signal.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 .../devicetree/bindings/serial/atmel-usart.txt     |  3 ++
 arch/arm/mach-at91/at91rm9200_devices.c            |  5 +++
 arch/arm/mach-at91/at91sam9260_devices.c           |  7 ++++
 arch/arm/mach-at91/at91sam9261_devices.c           |  4 +++
 arch/arm/mach-at91/at91sam9263_devices.c           |  4 +++
 arch/arm/mach-at91/at91sam9g45_devices.c           |  5 +++
 arch/arm/mach-at91/at91sam9rl_devices.c            |  5 +++
 drivers/tty/serial/atmel_serial.c                  | 37 +++++++++++++++++++++-
 include/linux/platform_data/atmel.h                |  1 +
 9 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 77d45c88b494..3b90795ee641 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -19,6 +19,8 @@ Optional properties:
   function pin for the USART CTS feature. If unsure, don't specify this property.
 - dtr-gpios: specify a GPIO for DTR line. It will use specified PIO instead of the peripheral
   function pin for the USART DTR feature. If unsure, don't specify this property.
+- dsr-gpios: specify a GPIO for DSR line. It will use specified PIO instead of the peripheral
+  function pin for the USART DSR feature. If unsure, don't specify this property.
 - add dma bindings for dma transfer:
 	- dmas: DMA specifier, consisting of a phandle to DMA controller node,
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
@@ -42,6 +44,7 @@ Example:
 		rts-gpios = <&pioD 15 0>;
 		cts-gpios = <&pioD 16 0>;
 		dtr-gpios = <&pioD 17 0>;
+		dsr-gpios = <&pioD 18 0>;
 	};
 
 - use DMA:
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index d8523cc05157..980ea65142b4 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -925,6 +925,7 @@ static struct atmel_uart_data dbgu_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -966,6 +967,7 @@ static struct atmel_uart_data uart0_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1019,6 +1021,7 @@ static struct atmel_uart_data uart1_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1073,6 +1076,7 @@ static struct atmel_uart_data uart2_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1119,6 +1123,7 @@ static struct atmel_uart_data uart3_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index b8e325b00e1a..c11d1225a75c 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -822,6 +822,7 @@ static struct atmel_uart_data dbgu_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -863,6 +864,7 @@ static struct atmel_uart_data uart0_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -917,6 +919,7 @@ static struct atmel_uart_data uart1_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -963,6 +966,7 @@ static struct atmel_uart_data uart2_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1009,6 +1013,7 @@ static struct atmel_uart_data uart3_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
@@ -1055,6 +1060,7 @@ static struct atmel_uart_data uart4_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart4_dmamask = DMA_BIT_MASK(32);
@@ -1096,6 +1102,7 @@ static struct atmel_uart_data uart5_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart5_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 3a05d9f09b0d..ea35af48a2e2 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -883,6 +883,7 @@ static struct atmel_uart_data dbgu_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -924,6 +925,7 @@ static struct atmel_uart_data uart0_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -970,6 +972,7 @@ static struct atmel_uart_data uart1_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1016,6 +1019,7 @@ static struct atmel_uart_data uart2_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index d26255ba3907..c8833ebd4fcb 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1327,6 +1327,7 @@ static struct atmel_uart_data dbgu_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1368,6 +1369,7 @@ static struct atmel_uart_data uart0_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1414,6 +1416,7 @@ static struct atmel_uart_data uart1_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1460,6 +1463,7 @@ static struct atmel_uart_data uart2_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 67e9f7f259e1..76772d12acfd 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1590,6 +1590,7 @@ static struct atmel_uart_data dbgu_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1631,6 +1632,7 @@ static struct atmel_uart_data uart0_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1677,6 +1679,7 @@ static struct atmel_uart_data uart1_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1723,6 +1726,7 @@ static struct atmel_uart_data uart2_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1769,6 +1773,7 @@ static struct atmel_uart_data uart3_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 94fecc40dbba..2aa6f8ddcd53 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -959,6 +959,7 @@ static struct atmel_uart_data dbgu_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1000,6 +1001,7 @@ static struct atmel_uart_data uart0_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1054,6 +1056,7 @@ static struct atmel_uart_data uart1_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1100,6 +1103,7 @@ static struct atmel_uart_data uart2_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1146,6 +1150,7 @@ static struct atmel_uart_data uart3_data = {
 	.rts_gpio	= -EINVAL,
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
+	.dsr_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index f5bdb84aed53..28b3636135cd 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -134,6 +134,8 @@ struct gpio_lines {
 	int cts;	/* optional CTS GPIO */
 	int cts_irq;
 	int dtr;	/* optional DTR GPIO */
+	int dsr;	/* optional DSR GPIO */
+	int dsr_irq;
 };
 
 /*
@@ -262,6 +264,13 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
 			status &= ~ATMEL_US_CTS;
 	}
 
+	if (gpio_is_valid(atmel_port->gpio.dsr)) {
+		if (gpio_get_value(atmel_port->gpio.dsr))
+			status |= ATMEL_US_DSR;
+		else
+			status &= ~ATMEL_US_DSR;
+	}
+
 	return status;
 }
 
@@ -495,13 +504,18 @@ static void atmel_enable_ms(struct uart_port *port)
 
 	atmel_port->ms_irq_enabled = true;
 
-	ier = ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC;
+	ier = ATMEL_US_RIIC | ATMEL_US_DCDIC;
 
 	if (atmel_port->gpio.cts_irq != INVALID_IRQ)
 		enable_irq(atmel_port->gpio.cts_irq);
 	else
 		ier |= ATMEL_US_CTSIC;
 
+	if (atmel_port->gpio.dsr_irq != INVALID_IRQ)
+		enable_irq(atmel_port->gpio.dsr_irq);
+	else
+		ier |= ATMEL_US_DSRIC;
+
 	UART_PUT_IER(port, ier);
 }
 
@@ -1105,6 +1119,11 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 			if ((irq !=  INVALID_IRQ) &&
 			    (irq == atmel_port->gpio.cts_irq))
 				pending |= ATMEL_US_CTSIC;
+
+			if ((irq !=  INVALID_IRQ) &&
+			    (irq == atmel_port->gpio.dsr_irq))
+				pending |= ATMEL_US_DSRIC;
+
 			gpio_handled = true;
 		}
 		if (!pending)
@@ -1638,6 +1657,11 @@ static int atmel_startup(struct uart_port *port)
 	if (retval)
 		goto free_ctrl_irq;
 
+	retval = atmel_request_gpio_irq(port, atmel_port->gpio.dsr_irq,
+					"atmel_dsr_irq");
+	if (retval)
+		goto free_cts_irq;
+
 	/*
 	 * Initialize DMA (if necessary)
 	 */
@@ -1703,6 +1727,9 @@ static int atmel_startup(struct uart_port *port)
 
 	return 0;
 
+free_cts_irq:
+	free_irq(atmel_port->gpio.cts_irq, port);
+
 free_ctrl_irq:
 	free_irq(port->irq, port);
 
@@ -1759,6 +1786,8 @@ static void atmel_shutdown(struct uart_port *port)
 	free_irq(port->irq, port);
 	if (atmel_port->gpio.cts_irq != INVALID_IRQ)
 		free_irq(atmel_port->gpio.cts_irq, port);
+	if (atmel_port->gpio.dsr_irq != INVALID_IRQ)
+		free_irq(atmel_port->gpio.dsr_irq, port);
 
 	atmel_port->ms_irq_enabled = false;
 }
@@ -2464,6 +2493,8 @@ static int atmel_init_gpios(struct atmel_uart_port *atmel_port,
 				  "CTS", &atmel_port->gpio.cts_irq);
 	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.dtr,
 				  "DTR", NULL);
+	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.dsr,
+				  "DSR", &atmel_port->gpio.dsr_irq);
 	return ret;
 }
 
@@ -2505,15 +2536,19 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port->gpio.rts = -EINVAL; /* Invalid, zero could be valid */
 	port->gpio.cts = -EINVAL;
 	port->gpio.dtr = -EINVAL;
+	port->gpio.dsr = -EINVAL;
 	port->gpio.cts_irq = INVALID_IRQ;
+	port->gpio.dsr_irq = INVALID_IRQ;
 	if (pdata) {
 		port->gpio.rts = pdata->rts_gpio;
 		port->gpio.cts = pdata->cts_gpio;
 		port->gpio.dtr = pdata->dtr_gpio;
+		port->gpio.dsr = pdata->dsr_gpio;
 	} else if (np) {
 		port->gpio.rts = of_get_named_gpio(np, "rts-gpios", 0);
 		port->gpio.cts = of_get_named_gpio(np, "cts-gpios", 0);
 		port->gpio.dtr = of_get_named_gpio(np, "dtr-gpios", 0);
+		port->gpio.dsr = of_get_named_gpio(np, "dsr-gpios", 0);
 	}
 
 	ret = atmel_init_gpios(port, pdev);
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 8472b6f3c618..81f2c658c996 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -87,6 +87,7 @@ struct atmel_uart_data {
 	int			rts_gpio;	/* optional RTS GPIO */
 	int			cts_gpio;	/* optional CTS GPIO */
 	int			dtr_gpio;	/* optional DTR GPIO */
+	int			dsr_gpio;	/* optional DSR GPIO */
 };
 
  /* Touchscreen Controller */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/8] tty/serial: at91: add ring control via gpio
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
                   ` (5 preceding siblings ...)
  2014-02-07 14:59 ` [PATCH 6/8] tty/serial: at91: add dsr " Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  2014-02-07 14:59 ` [PATCH 8/8] tty/serial: at91: add dcd " Richard Genoud
  7 siblings, 0 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
so we have to control them via GPIO.

This patch permits to use a GPIO to control the RI signal.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 .../devicetree/bindings/serial/atmel-usart.txt     |  3 ++
 arch/arm/mach-at91/at91rm9200_devices.c            |  5 +++
 arch/arm/mach-at91/at91sam9260_devices.c           |  7 +++++
 arch/arm/mach-at91/at91sam9261_devices.c           |  4 +++
 arch/arm/mach-at91/at91sam9263_devices.c           |  4 +++
 arch/arm/mach-at91/at91sam9g45_devices.c           |  5 +++
 arch/arm/mach-at91/at91sam9rl_devices.c            |  5 +++
 drivers/tty/serial/atmel_serial.c                  | 36 +++++++++++++++++++++-
 include/linux/platform_data/atmel.h                |  1 +
 9 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 3b90795ee641..11d033649b19 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -21,6 +21,8 @@ Optional properties:
   function pin for the USART DTR feature. If unsure, don't specify this property.
 - dsr-gpios: specify a GPIO for DSR line. It will use specified PIO instead of the peripheral
   function pin for the USART DSR feature. If unsure, don't specify this property.
+- ri-gpios: specify a GPIO for Ring line. It will use specified PIO instead of the peripheral
+  function pin for the USART Ring feature. If unsure, don't specify this property.
 - add dma bindings for dma transfer:
 	- dmas: DMA specifier, consisting of a phandle to DMA controller node,
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
@@ -45,6 +47,7 @@ Example:
 		cts-gpios = <&pioD 16 0>;
 		dtr-gpios = <&pioD 17 0>;
 		dsr-gpios = <&pioD 18 0>;
+		ri-gpios = <&pioD 19 0>;
 	};
 
 - use DMA:
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 980ea65142b4..11c5c7f5b067 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -926,6 +926,7 @@ static struct atmel_uart_data dbgu_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -968,6 +969,7 @@ static struct atmel_uart_data uart0_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1022,6 +1024,7 @@ static struct atmel_uart_data uart1_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1077,6 +1080,7 @@ static struct atmel_uart_data uart2_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1124,6 +1128,7 @@ static struct atmel_uart_data uart3_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index c11d1225a75c..f8ccdbe2bcbc 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -823,6 +823,7 @@ static struct atmel_uart_data dbgu_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -865,6 +866,7 @@ static struct atmel_uart_data uart0_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -920,6 +922,7 @@ static struct atmel_uart_data uart1_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -967,6 +970,7 @@ static struct atmel_uart_data uart2_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1014,6 +1018,7 @@ static struct atmel_uart_data uart3_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
@@ -1061,6 +1066,7 @@ static struct atmel_uart_data uart4_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart4_dmamask = DMA_BIT_MASK(32);
@@ -1103,6 +1109,7 @@ static struct atmel_uart_data uart5_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart5_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index ea35af48a2e2..c40aa819cfac 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -884,6 +884,7 @@ static struct atmel_uart_data dbgu_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -926,6 +927,7 @@ static struct atmel_uart_data uart0_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -973,6 +975,7 @@ static struct atmel_uart_data uart1_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1020,6 +1023,7 @@ static struct atmel_uart_data uart2_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index c8833ebd4fcb..1da08465d952 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1328,6 +1328,7 @@ static struct atmel_uart_data dbgu_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1370,6 +1371,7 @@ static struct atmel_uart_data uart0_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1417,6 +1419,7 @@ static struct atmel_uart_data uart1_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1464,6 +1467,7 @@ static struct atmel_uart_data uart2_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 76772d12acfd..4520d8f70cff 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1591,6 +1591,7 @@ static struct atmel_uart_data dbgu_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1633,6 +1634,7 @@ static struct atmel_uart_data uart0_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1680,6 +1682,7 @@ static struct atmel_uart_data uart1_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1727,6 +1730,7 @@ static struct atmel_uart_data uart2_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1774,6 +1778,7 @@ static struct atmel_uart_data uart3_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 2aa6f8ddcd53..5916d65b6362 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -960,6 +960,7 @@ static struct atmel_uart_data dbgu_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1002,6 +1003,7 @@ static struct atmel_uart_data uart0_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1057,6 +1059,7 @@ static struct atmel_uart_data uart1_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1104,6 +1107,7 @@ static struct atmel_uart_data uart2_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1151,6 +1155,7 @@ static struct atmel_uart_data uart3_data = {
 	.cts_gpio	= -EINVAL,
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
+	.ri_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 28b3636135cd..9d47497713ab 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -136,6 +136,8 @@ struct gpio_lines {
 	int dtr;	/* optional DTR GPIO */
 	int dsr;	/* optional DSR GPIO */
 	int dsr_irq;
+	int ri;		/* optional Ring GPIO */
+	int ri_irq;
 };
 
 /*
@@ -271,6 +273,13 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
 			status &= ~ATMEL_US_DSR;
 	}
 
+	if (gpio_is_valid(atmel_port->gpio.ri)) {
+		if (gpio_get_value(atmel_port->gpio.ri))
+			status |= ATMEL_US_RI;
+		else
+			status &= ~ATMEL_US_RI;
+	}
+
 	return status;
 }
 
@@ -504,7 +513,7 @@ static void atmel_enable_ms(struct uart_port *port)
 
 	atmel_port->ms_irq_enabled = true;
 
-	ier = ATMEL_US_RIIC | ATMEL_US_DCDIC;
+	ier = ATMEL_US_DCDIC;
 
 	if (atmel_port->gpio.cts_irq != INVALID_IRQ)
 		enable_irq(atmel_port->gpio.cts_irq);
@@ -516,6 +525,11 @@ static void atmel_enable_ms(struct uart_port *port)
 	else
 		ier |= ATMEL_US_DSRIC;
 
+	if (atmel_port->gpio.ri_irq != INVALID_IRQ)
+		enable_irq(atmel_port->gpio.ri_irq);
+	else
+		ier |= ATMEL_US_RIIC;
+
 	UART_PUT_IER(port, ier);
 }
 
@@ -1124,6 +1138,10 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 			    (irq == atmel_port->gpio.dsr_irq))
 				pending |= ATMEL_US_DSRIC;
 
+			if ((irq !=  INVALID_IRQ) &&
+			    (irq == atmel_port->gpio.ri_irq))
+				pending |= ATMEL_US_RIIC;
+
 			gpio_handled = true;
 		}
 		if (!pending)
@@ -1662,6 +1680,11 @@ static int atmel_startup(struct uart_port *port)
 	if (retval)
 		goto free_cts_irq;
 
+	retval = atmel_request_gpio_irq(port, atmel_port->gpio.ri_irq,
+					"atmel_ri_irq");
+	if (retval)
+		goto free_dsr_irq;
+
 	/*
 	 * Initialize DMA (if necessary)
 	 */
@@ -1727,6 +1750,9 @@ static int atmel_startup(struct uart_port *port)
 
 	return 0;
 
+free_dsr_irq:
+	free_irq(atmel_port->gpio.dsr_irq, port);
+
 free_cts_irq:
 	free_irq(atmel_port->gpio.cts_irq, port);
 
@@ -1788,6 +1814,8 @@ static void atmel_shutdown(struct uart_port *port)
 		free_irq(atmel_port->gpio.cts_irq, port);
 	if (atmel_port->gpio.dsr_irq != INVALID_IRQ)
 		free_irq(atmel_port->gpio.dsr_irq, port);
+	if (atmel_port->gpio.ri_irq != INVALID_IRQ)
+		free_irq(atmel_port->gpio.ri_irq, port);
 
 	atmel_port->ms_irq_enabled = false;
 }
@@ -2495,6 +2523,8 @@ static int atmel_init_gpios(struct atmel_uart_port *atmel_port,
 				  "DTR", NULL);
 	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.dsr,
 				  "DSR", &atmel_port->gpio.dsr_irq);
+	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.ri,
+				  "RI", &atmel_port->gpio.ri_irq);
 	return ret;
 }
 
@@ -2537,18 +2567,22 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port->gpio.cts = -EINVAL;
 	port->gpio.dtr = -EINVAL;
 	port->gpio.dsr = -EINVAL;
+	port->gpio.ri = -EINVAL;
 	port->gpio.cts_irq = INVALID_IRQ;
 	port->gpio.dsr_irq = INVALID_IRQ;
+	port->gpio.ri_irq = INVALID_IRQ;
 	if (pdata) {
 		port->gpio.rts = pdata->rts_gpio;
 		port->gpio.cts = pdata->cts_gpio;
 		port->gpio.dtr = pdata->dtr_gpio;
 		port->gpio.dsr = pdata->dsr_gpio;
+		port->gpio.ri = pdata->ri_gpio;
 	} else if (np) {
 		port->gpio.rts = of_get_named_gpio(np, "rts-gpios", 0);
 		port->gpio.cts = of_get_named_gpio(np, "cts-gpios", 0);
 		port->gpio.dtr = of_get_named_gpio(np, "dtr-gpios", 0);
 		port->gpio.dsr = of_get_named_gpio(np, "dsr-gpios", 0);
+		port->gpio.ri = of_get_named_gpio(np, "ri-gpios", 0);
 	}
 
 	ret = atmel_init_gpios(port, pdev);
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 81f2c658c996..ce6ca1b8aef3 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -88,6 +88,7 @@ struct atmel_uart_data {
 	int			cts_gpio;	/* optional CTS GPIO */
 	int			dtr_gpio;	/* optional DTR GPIO */
 	int			dsr_gpio;	/* optional DSR GPIO */
+	int			ri_gpio;	/* optional Ring GPIO */
 };
 
  /* Touchscreen Controller */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 8/8] tty/serial: at91: add dcd control via gpio
  2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
                   ` (6 preceding siblings ...)
  2014-02-07 14:59 ` [PATCH 7/8] tty/serial: at91: add ring " Richard Genoud
@ 2014-02-07 14:59 ` Richard Genoud
  7 siblings, 0 replies; 12+ messages in thread
From: Richard Genoud @ 2014-02-07 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
so we have to control them via GPIO.

This patch permits to use a GPIO to control the DCD signal.

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
 .../devicetree/bindings/serial/atmel-usart.txt     |  3 ++
 arch/arm/mach-at91/at91rm9200_devices.c            |  5 +++
 arch/arm/mach-at91/at91sam9260_devices.c           |  7 ++++
 arch/arm/mach-at91/at91sam9261_devices.c           |  4 +++
 arch/arm/mach-at91/at91sam9263_devices.c           |  4 +++
 arch/arm/mach-at91/at91sam9g45_devices.c           |  5 +++
 arch/arm/mach-at91/at91sam9rl_devices.c            |  5 +++
 drivers/tty/serial/atmel_serial.c                  | 38 ++++++++++++++++++++--
 include/linux/platform_data/atmel.h                |  1 +
 9 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 11d033649b19..4ff660e1487f 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -23,6 +23,8 @@ Optional properties:
   function pin for the USART DSR feature. If unsure, don't specify this property.
 - ri-gpios: specify a GPIO for Ring line. It will use specified PIO instead of the peripheral
   function pin for the USART Ring feature. If unsure, don't specify this property.
+- dcd-gpios: specify a GPIO for DCD line. It will use specified PIO instead of the peripheral
+  function pin for the USART DCD feature. If unsure, don't specify this property.
 - add dma bindings for dma transfer:
 	- dmas: DMA specifier, consisting of a phandle to DMA controller node,
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
@@ -48,6 +50,7 @@ Example:
 		dtr-gpios = <&pioD 17 0>;
 		dsr-gpios = <&pioD 18 0>;
 		ri-gpios = <&pioD 19 0>;
+		dcd-gpios = <&pioD 20 0>;
 	};
 
 - use DMA:
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 11c5c7f5b067..288421f38b42 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -927,6 +927,7 @@ static struct atmel_uart_data dbgu_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -970,6 +971,7 @@ static struct atmel_uart_data uart0_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1025,6 +1027,7 @@ static struct atmel_uart_data uart1_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1081,6 +1084,7 @@ static struct atmel_uart_data uart2_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1129,6 +1133,7 @@ static struct atmel_uart_data uart3_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index f8ccdbe2bcbc..0e20ba04d43f 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -824,6 +824,7 @@ static struct atmel_uart_data dbgu_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -867,6 +868,7 @@ static struct atmel_uart_data uart0_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -923,6 +925,7 @@ static struct atmel_uart_data uart1_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -971,6 +974,7 @@ static struct atmel_uart_data uart2_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1019,6 +1023,7 @@ static struct atmel_uart_data uart3_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
@@ -1067,6 +1072,7 @@ static struct atmel_uart_data uart4_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart4_dmamask = DMA_BIT_MASK(32);
@@ -1110,6 +1116,7 @@ static struct atmel_uart_data uart5_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart5_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index c40aa819cfac..d3d7a546db9b 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -885,6 +885,7 @@ static struct atmel_uart_data dbgu_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -928,6 +929,7 @@ static struct atmel_uart_data uart0_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -976,6 +978,7 @@ static struct atmel_uart_data uart1_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1024,6 +1027,7 @@ static struct atmel_uart_data uart2_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 1da08465d952..5fcb2a0383d1 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1329,6 +1329,7 @@ static struct atmel_uart_data dbgu_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1372,6 +1373,7 @@ static struct atmel_uart_data uart0_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1420,6 +1422,7 @@ static struct atmel_uart_data uart1_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1468,6 +1471,7 @@ static struct atmel_uart_data uart2_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 4520d8f70cff..bd44970403e5 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1592,6 +1592,7 @@ static struct atmel_uart_data dbgu_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1635,6 +1636,7 @@ static struct atmel_uart_data uart0_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1683,6 +1685,7 @@ static struct atmel_uart_data uart1_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1731,6 +1734,7 @@ static struct atmel_uart_data uart2_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1779,6 +1783,7 @@ static struct atmel_uart_data uart3_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 5916d65b6362..e43623dc1c9e 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -961,6 +961,7 @@ static struct atmel_uart_data dbgu_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1004,6 +1005,7 @@ static struct atmel_uart_data uart0_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1060,6 +1062,7 @@ static struct atmel_uart_data uart1_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1108,6 +1111,7 @@ static struct atmel_uart_data uart2_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1156,6 +1160,7 @@ static struct atmel_uart_data uart3_data = {
 	.dtr_gpio	= -EINVAL,
 	.dsr_gpio	= -EINVAL,
 	.ri_gpio	= -EINVAL,
+	.dcd_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 9d47497713ab..926f77e6bde5 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -138,6 +138,8 @@ struct gpio_lines {
 	int dsr_irq;
 	int ri;		/* optional Ring GPIO */
 	int ri_irq;
+	int dcd;	/* optional DCD GPIO */
+	int dcd_irq;
 };
 
 /*
@@ -280,6 +282,13 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
 			status &= ~ATMEL_US_RI;
 	}
 
+	if (gpio_is_valid(atmel_port->gpio.dcd)) {
+		if (gpio_get_value(atmel_port->gpio.dcd))
+			status |= ATMEL_US_DCD;
+		else
+			status &= ~ATMEL_US_DCD;
+	}
+
 	return status;
 }
 
@@ -503,7 +512,7 @@ static void atmel_stop_rx(struct uart_port *port)
 static void atmel_enable_ms(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-	uint32_t ier;
+	uint32_t ier = 0;
 
 	/*
 	 * Interrupt should not be enabled twice
@@ -513,8 +522,6 @@ static void atmel_enable_ms(struct uart_port *port)
 
 	atmel_port->ms_irq_enabled = true;
 
-	ier = ATMEL_US_DCDIC;
-
 	if (atmel_port->gpio.cts_irq != INVALID_IRQ)
 		enable_irq(atmel_port->gpio.cts_irq);
 	else
@@ -530,6 +537,11 @@ static void atmel_enable_ms(struct uart_port *port)
 	else
 		ier |= ATMEL_US_RIIC;
 
+	if (atmel_port->gpio.dcd_irq != INVALID_IRQ)
+		enable_irq(atmel_port->gpio.dcd_irq);
+	else
+		ier |= ATMEL_US_DCDIC;
+
 	UART_PUT_IER(port, ier);
 }
 
@@ -1142,6 +1154,10 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 			    (irq == atmel_port->gpio.ri_irq))
 				pending |= ATMEL_US_RIIC;
 
+			if ((irq !=  INVALID_IRQ) &&
+			    (irq == atmel_port->gpio.dcd_irq))
+				pending |= ATMEL_US_DCDIC;
+
 			gpio_handled = true;
 		}
 		if (!pending)
@@ -1685,6 +1701,11 @@ static int atmel_startup(struct uart_port *port)
 	if (retval)
 		goto free_dsr_irq;
 
+	retval = atmel_request_gpio_irq(port, atmel_port->gpio.dcd_irq,
+					"atmel_dcd_irq");
+	if (retval)
+		goto free_ri_irq;
+
 	/*
 	 * Initialize DMA (if necessary)
 	 */
@@ -1750,6 +1771,9 @@ static int atmel_startup(struct uart_port *port)
 
 	return 0;
 
+free_ri_irq:
+	free_irq(atmel_port->gpio.ri_irq, port);
+
 free_dsr_irq:
 	free_irq(atmel_port->gpio.dsr_irq, port);
 
@@ -1816,6 +1840,8 @@ static void atmel_shutdown(struct uart_port *port)
 		free_irq(atmel_port->gpio.dsr_irq, port);
 	if (atmel_port->gpio.ri_irq != INVALID_IRQ)
 		free_irq(atmel_port->gpio.ri_irq, port);
+	if (atmel_port->gpio.dcd_irq != INVALID_IRQ)
+		free_irq(atmel_port->gpio.dcd_irq, port);
 
 	atmel_port->ms_irq_enabled = false;
 }
@@ -2525,6 +2551,8 @@ static int atmel_init_gpios(struct atmel_uart_port *atmel_port,
 				  "DSR", &atmel_port->gpio.dsr_irq);
 	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.ri,
 				  "RI", &atmel_port->gpio.ri_irq);
+	ret += atmel_request_gpio(&pdev->dev, atmel_port->gpio.dcd,
+				  "DCD", &atmel_port->gpio.dcd_irq);
 	return ret;
 }
 
@@ -2568,21 +2596,25 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port->gpio.dtr = -EINVAL;
 	port->gpio.dsr = -EINVAL;
 	port->gpio.ri = -EINVAL;
+	port->gpio.dcd = -EINVAL;
 	port->gpio.cts_irq = INVALID_IRQ;
 	port->gpio.dsr_irq = INVALID_IRQ;
 	port->gpio.ri_irq = INVALID_IRQ;
+	port->gpio.dcd_irq = INVALID_IRQ;
 	if (pdata) {
 		port->gpio.rts = pdata->rts_gpio;
 		port->gpio.cts = pdata->cts_gpio;
 		port->gpio.dtr = pdata->dtr_gpio;
 		port->gpio.dsr = pdata->dsr_gpio;
 		port->gpio.ri = pdata->ri_gpio;
+		port->gpio.dcd = pdata->dcd_gpio;
 	} else if (np) {
 		port->gpio.rts = of_get_named_gpio(np, "rts-gpios", 0);
 		port->gpio.cts = of_get_named_gpio(np, "cts-gpios", 0);
 		port->gpio.dtr = of_get_named_gpio(np, "dtr-gpios", 0);
 		port->gpio.dsr = of_get_named_gpio(np, "dsr-gpios", 0);
 		port->gpio.ri = of_get_named_gpio(np, "ri-gpios", 0);
+		port->gpio.dcd = of_get_named_gpio(np, "dcd-gpios", 0);
 	}
 
 	ret = atmel_init_gpios(port, pdev);
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index ce6ca1b8aef3..565c5c693c7f 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -88,6 +88,7 @@ struct atmel_uart_data {
 	int			cts_gpio;	/* optional CTS GPIO */
 	int			dtr_gpio;	/* optional DTR GPIO */
 	int			dsr_gpio;	/* optional DSR GPIO */
+	int			dcd_gpio;	/* optional DCD GPIO */
 	int			ri_gpio;	/* optional Ring GPIO */
 };
 
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 5/8] tty/serial: at91: add dtr control via gpio
  2014-02-07 14:59 ` [PATCH 5/8] tty/serial: at91: add dtr " Richard Genoud
@ 2014-02-07 15:21   ` Alexander Shiyan
  2014-02-10 10:24     ` Richard Genoud
  0 siblings, 1 reply; 12+ messages in thread
From: Alexander Shiyan @ 2014-02-07 15:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

???????,  7 ??????? 2014, 15:59 +01:00 ?? Richard Genoud <richard.genoud@gmail.com>:
> On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
> so we have to control them via GPIO.
> 
> This patch permits to use a GPIO to control the DTR signal.
> 
> Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
> ---
...
> +	if (gpio_is_valid(atmel_port->gpio.dtr)) {
> +		if (mctrl & TIOCM_DTR)
> +			gpio_set_value(atmel_port->gpio.dtr, 0);
> +		else
> +			gpio_set_value(atmel_port->gpio.dtr, 1);
> +	}

So, if you use GPIO for such purpose (here and in the other patches),
you should take and use GPIO active level from bindings.
It will make use of GPIO more flexible and deliver us from further special
possible bindings to declare the active level.
Actually, it would be good to have a separate unit for mctrl GPIOs,
which could be used for other drivers.

---

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 5/8] tty/serial: at91: add dtr control via gpio
  2014-02-07 15:21   ` Alexander Shiyan
@ 2014-02-10 10:24     ` Richard Genoud
  2014-02-10 10:37       ` Nicolas Ferre
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Genoud @ 2014-02-10 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

2014-02-07 16:21 GMT+01:00 Alexander Shiyan <shc_work@mail.ru>:
> Hello.
>
> ???????,  7 ??????? 2014, 15:59 +01:00 ?? Richard Genoud <richard.genoud@gmail.com>:
>> On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
>> so we have to control them via GPIO.
>>
>> This patch permits to use a GPIO to control the DTR signal.
>>
>> Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
>> ---
> ...
>> +     if (gpio_is_valid(atmel_port->gpio.dtr)) {
>> +             if (mctrl & TIOCM_DTR)
>> +                     gpio_set_value(atmel_port->gpio.dtr, 0);
>> +             else
>> +                     gpio_set_value(atmel_port->gpio.dtr, 1);
>> +     }
>
> So, if you use GPIO for such purpose (here and in the other patches),
> you should take and use GPIO active level from bindings.
> It will make use of GPIO more flexible and deliver us from further special
> possible bindings to declare the active level.
Yes, I could do that. I'll have to change the alreday merged RTS
binding so that it gets it's active level from DTS, but I don't think
it's a problem, since it's not already in mainline.
Linus, Nicolas, what do you think ?

> Actually, it would be good to have a separate unit for mctrl GPIOs,
> which could be used for other drivers.
good idea, I can add them in serial_core.c

Thanks!

Richard.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 5/8] tty/serial: at91: add dtr control via gpio
  2014-02-10 10:24     ` Richard Genoud
@ 2014-02-10 10:37       ` Nicolas Ferre
  0 siblings, 0 replies; 12+ messages in thread
From: Nicolas Ferre @ 2014-02-10 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/02/2014 11:24, Richard Genoud :
> 2014-02-07 16:21 GMT+01:00 Alexander Shiyan <shc_work@mail.ru>:
>> Hello.
>>
>> ???????,  7 ??????? 2014, 15:59 +01:00 ?? Richard Genoud <richard.genoud@gmail.com>:
>>> On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
>>> so we have to control them via GPIO.
>>>
>>> This patch permits to use a GPIO to control the DTR signal.
>>>
>>> Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
>>> ---
>> ...
>>> +     if (gpio_is_valid(atmel_port->gpio.dtr)) {
>>> +             if (mctrl & TIOCM_DTR)
>>> +                     gpio_set_value(atmel_port->gpio.dtr, 0);
>>> +             else
>>> +                     gpio_set_value(atmel_port->gpio.dtr, 1);
>>> +     }
>>
>> So, if you use GPIO for such purpose (here and in the other patches),
>> you should take and use GPIO active level from bindings.
>> It will make use of GPIO more flexible and deliver us from further special
>> possible bindings to declare the active level.
> Yes, I could do that. I'll have to change the alreday merged RTS
> binding so that it gets it's active level from DTS, but I don't think
> it's a problem, since it's not already in mainline.
> Linus, Nicolas, what do you think ?

Yes I agree. It is not used yet, so the sooner we move to this
specification, the better.

>> Actually, it would be good to have a separate unit for mctrl GPIOs,
>> which could be used for other drivers.
> good idea, I can add them in serial_core.c

That would be great. Thanks Richard!

Bye,
-- 
Nicolas Ferre

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-02-10 10:37 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-07 14:59 [PATCH 0/8] tty/serial: at91: Add missing modem signals to atmel_serial Richard Genoud
2014-02-07 14:59 ` [PATCH 1/8] tty/serial: at91: use dev_err instead of printk Richard Genoud
2014-02-07 14:59 ` [PATCH 2/8] tty/serial: at91: remove unused open/close hooks Richard Genoud
2014-02-07 14:59 ` [PATCH 3/8] tty/serial: at91: prepare for more gpio lines to come Richard Genoud
2014-02-07 14:59 ` [PATCH 4/8] tty/serial: at91: add cts control via gpio Richard Genoud
2014-02-07 14:59 ` [PATCH 5/8] tty/serial: at91: add dtr " Richard Genoud
2014-02-07 15:21   ` Alexander Shiyan
2014-02-10 10:24     ` Richard Genoud
2014-02-10 10:37       ` Nicolas Ferre
2014-02-07 14:59 ` [PATCH 6/8] tty/serial: at91: add dsr " Richard Genoud
2014-02-07 14:59 ` [PATCH 7/8] tty/serial: at91: add ring " Richard Genoud
2014-02-07 14:59 ` [PATCH 8/8] tty/serial: at91: add dcd " Richard Genoud

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).