summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/atmel_serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/atmel_serial.c')
-rw-r--r--drivers/tty/serial/atmel_serial.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index a49f10d269b2..91c0d8839570 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -35,21 +35,18 @@
#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)