cpm_uart: Modem control lines support
authorLaurent Pinchart <laurentp@cse-semaphore.com>
Thu, 24 Jul 2008 16:36:37 +0000 (18:36 +0200)
committerKumar Gala <galak@kernel.crashing.org>
Mon, 28 Jul 2008 12:48:04 +0000 (07:48 -0500)
This patch replaces the get_mctrl/set_mctrl stubs with modem control line
read/write access through the GPIO lib.

Available modem control lines are described in the device tree using GPIO
bindings. The driver expect a GPIO pin for each of the CTS, RTS, DCD, DSR,
DTR and RI signals. Unused control lines can be left out.

Signed-off-by: Laurent Pinchart <laurentp@cse-semaphore.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Documentation/powerpc/dts-bindings/fsl/cpm_qe/serial.txt
drivers/serial/cpm_uart/cpm_uart.h
drivers/serial/cpm_uart/cpm_uart_core.c

index b35f3482e3e4dc73574ae0dd7f3ec9474aec8f9a..2ea76d9d137c56fc41a160b534612a3542ba94b9 100644 (file)
@@ -7,6 +7,15 @@ Currently defined compatibles:
 - fsl,cpm2-scc-uart
 - fsl,qe-uart
 
+Modem control lines connected to GPIO controllers are listed in the gpios
+property as described in booting-without-of.txt, section IX.1 in the following
+order:
+
+CTS, RTS, DCD, DSR, DTR, and RI.
+
+The gpios property is optional and can be left out when control lines are
+not used.
+
 Example:
 
        serial@11a00 {
@@ -18,4 +27,6 @@ Example:
                interrupt-parent = <&PIC>;
                fsl,cpm-brg = <1>;
                fsl,cpm-command = <00800000>;
+               gpios = <&gpio_c 15 0
+                        &gpio_d 29 0>;
        };
index 5c76e0ae0582f63b2659cbc72384da822744d2b3..5999ef5ac78e2ff00f32ad76e8db6b5ec3c60d2c 100644 (file)
 
 #define SCC_WAIT_CLOSING 100
 
+#define GPIO_CTS       0
+#define GPIO_RTS       1
+#define GPIO_DCD       2
+#define GPIO_DSR       3
+#define GPIO_DTR       4
+#define GPIO_RI                5
+
+#define NUM_GPIOS      (GPIO_RI+1)
+
 struct uart_cpm_port {
        struct uart_port        port;
        u16                     rx_nrfifos;
@@ -82,6 +91,7 @@ struct uart_cpm_port {
        int                     wait_closing;
        /* value to combine with opcode to form cpm command */
        u32                     command;
+       int                     gpios[NUM_GPIOS];
 };
 
 extern int cpm_uart_nr;
index a4f86927a74bfd830e51a9fdd4ae008ebd1ac65e..5e0c17f71653529587b58c0d9c5567c104fde53a 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/fs_uart_pd.h>
 #include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -96,13 +98,41 @@ static unsigned int cpm_uart_tx_empty(struct uart_port *port)
 
 static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-       /* Whee. Do nothing. */
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+       if (pinfo->gpios[GPIO_RTS] >= 0)
+               gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS));
+
+       if (pinfo->gpios[GPIO_DTR] >= 0)
+               gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));
 }
 
 static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
 {
-       /* Whee. Do nothing. */
-       return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+
+       if (pinfo->gpios[GPIO_CTS] >= 0) {
+               if (gpio_get_value(pinfo->gpios[GPIO_CTS]))
+                       mctrl &= ~TIOCM_CTS;
+       }
+
+       if (pinfo->gpios[GPIO_DSR] >= 0) {
+               if (gpio_get_value(pinfo->gpios[GPIO_DSR]))
+                       mctrl &= ~TIOCM_DSR;
+       }
+
+       if (pinfo->gpios[GPIO_DCD] >= 0) {
+               if (gpio_get_value(pinfo->gpios[GPIO_DCD]))
+                       mctrl &= ~TIOCM_CAR;
+       }
+
+       if (pinfo->gpios[GPIO_RI] >= 0) {
+               if (!gpio_get_value(pinfo->gpios[GPIO_RI]))
+                       mctrl |= TIOCM_RNG;
+       }
+
+       return mctrl;
 }
 
 /*
@@ -991,6 +1021,7 @@ static int cpm_uart_init_port(struct device_node *np,
        void __iomem *mem, *pram;
        int len;
        int ret;
+       int i;
 
        data = of_get_property(np, "fsl,cpm-brg", &len);
        if (!data || len != 4) {
@@ -1050,6 +1081,9 @@ static int cpm_uart_init_port(struct device_node *np,
                goto out_pram;
        }
 
+       for (i = 0; i < NUM_GPIOS; i++)
+               pinfo->gpios[i] = of_get_gpio(np, i);
+
        return cpm_uart_request_port(&pinfo->port);
 
 out_pram: