]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/tty/serial/atmel_serial.c
Merge tag 'dropmachtimexh-v2' of git://git.pengutronix.de/git/ukl/linux
[mirror_ubuntu-artful-kernel.git] / drivers / tty / serial / atmel_serial.c
index a49f10d269b20afb2e8d2a1579af8f8987ed2a16..91c0d8839570ce996d7acdb05368932ab6d797b7 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/dma-mapping.h>
 #include <linux/atmel_pdc.h>
 #include <linux/atmel_serial.h>
 #include <linux/uaccess.h>
 #include <linux/platform_data/atmel.h>
 #include <linux/timer.h>
+#include <linux/gpio.h>
 
 #include <asm/io.h>
 #include <asm/ioctls.h>
 
-#ifdef CONFIG_ARM
-#include <mach/cpu.h>
-#include <asm/gpio.h>
-#endif
-
 #define PDC_BUFFER_SIZE                512
 /* Revisit: We should calculate this based on the actual port settings */
 #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
@@ -168,6 +165,7 @@ struct atmel_uart_port {
        struct circ_buf         rx_ring;
 
        struct serial_rs485     rs485;          /* rs485 settings */
+       int                     rts_gpio;       /* optional RTS GPIO */
        unsigned int            tx_done_mask;
        bool                    is_usart;       /* usart or uart */
        struct timer_list       uart_timer;     /* uart timer */
@@ -301,20 +299,16 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
        unsigned int mode;
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-#ifdef CONFIG_ARCH_AT91RM9200
-       if (cpu_is_at91rm9200()) {
-               /*
-                * AT91RM9200 Errata #39: RTS0 is not internally connected
-                * to PA21. We need to drive the pin manually.
-                */
-               if (port->mapbase == AT91RM9200_BASE_US0) {
-                       if (mctrl & TIOCM_RTS)
-                               at91_set_gpio_value(AT91_PIN_PA21, 0);
-                       else
-                               at91_set_gpio_value(AT91_PIN_PA21, 1);
-               }
+       /*
+        * 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 (mctrl & TIOCM_RTS)
+                       gpio_set_value(atmel_port->rts_gpio, 0);
+               else
+                       gpio_set_value(atmel_port->rts_gpio, 1);
        }
-#endif
 
        if (mctrl & TIOCM_RTS)
                control |= ATMEL_US_RTSEN;
@@ -2389,6 +2383,25 @@ 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 */
+       if (pdata)
+               port->rts_gpio = pdata->rts_gpio;
+       else if (np)
+               port->rts_gpio = 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_port(port, pdev);
        if (ret)