aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorRichard Genoud <richard.genoud@gmail.com>2014-05-13 14:20:44 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-28 15:49:44 -0400
commite0b0baadb7a4509bdcd5ba37d0be61e2c4bb0d48 (patch)
treeea9d6937dddf11ed65c8b9c2f8847213f73e2d2e /drivers/tty
parent84130aace83989c1dba073ed98dad721d2060258 (diff)
tty/serial: at91: use mctrl_gpio helpers
On sam9x5, dedicated CTS (and RTS) pins are unusable together with the LCDC, the EMAC, or the MMC because they share the same line. Moreover, the USART controller doesn't handle DTR/DSR/DCD/RI signals, so we have to control them via GPIO. This patch permits to use GPIOs to control the CTS/RTS/DTR/DSR/DCD/RI signals. Signed-off-by: Richard Genoud <richard.genoud@gmail.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/Kconfig1
-rw-r--r--drivers/tty/serial/atmel_serial.c105
2 files changed, 71 insertions, 35 deletions
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 4bf6d220357b..fb57159bad3a 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -117,6 +117,7 @@ config SERIAL_ATMEL
117 bool "AT91 / AT32 on-chip serial port support" 117 bool "AT91 / AT32 on-chip serial port support"
118 depends on ARCH_AT91 || AVR32 118 depends on ARCH_AT91 || AVR32
119 select SERIAL_CORE 119 select SERIAL_CORE
120 select SERIAL_MCTRL_GPIO
120 help 121 help
121 This enables the driver for the on-chip UARTs of the Atmel 122 This enables the driver for the on-chip UARTs of the Atmel
122 AT91 and AT32 processors. 123 AT91 and AT32 processors.
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 53eeea13ff16..43ca659c1d4b 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -43,6 +43,8 @@
43#include <linux/platform_data/atmel.h> 43#include <linux/platform_data/atmel.h>
44#include <linux/timer.h> 44#include <linux/timer.h>
45#include <linux/gpio.h> 45#include <linux/gpio.h>
46#include <linux/gpio/consumer.h>
47#include <linux/err.h>
46 48
47#include <asm/io.h> 49#include <asm/io.h>
48#include <asm/ioctls.h> 50#include <asm/ioctls.h>
@@ -57,6 +59,8 @@
57 59
58#include <linux/serial_core.h> 60#include <linux/serial_core.h>
59 61
62#include "serial_mctrl_gpio.h"
63
60static void atmel_start_rx(struct uart_port *port); 64static void atmel_start_rx(struct uart_port *port);
61static void atmel_stop_rx(struct uart_port *port); 65static void atmel_stop_rx(struct uart_port *port);
62 66
@@ -162,7 +166,7 @@ struct atmel_uart_port {
162 struct circ_buf rx_ring; 166 struct circ_buf rx_ring;
163 167
164 struct serial_rs485 rs485; /* rs485 settings */ 168 struct serial_rs485 rs485; /* rs485 settings */
165 int rts_gpio; /* optional RTS GPIO */ 169 struct mctrl_gpios *gpios;
166 unsigned int tx_done_mask; 170 unsigned int tx_done_mask;
167 bool is_usart; /* usart or uart */ 171 bool is_usart; /* usart or uart */
168 struct timer_list uart_timer; /* uart timer */ 172 struct timer_list uart_timer; /* uart timer */
@@ -237,6 +241,50 @@ static bool atmel_use_dma_rx(struct uart_port *port)
237 return atmel_port->use_dma_rx; 241 return atmel_port->use_dma_rx;
238} 242}
239 243
244static unsigned int atmel_get_lines_status(struct uart_port *port)
245{
246 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
247 unsigned int status, ret = 0;
248
249 status = UART_GET_CSR(port);
250
251 mctrl_gpio_get(atmel_port->gpios, &ret);
252
253 if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
254 UART_GPIO_CTS))) {
255 if (ret & TIOCM_CTS)
256 status &= ~ATMEL_US_CTS;
257 else
258 status |= ATMEL_US_CTS;
259 }
260
261 if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
262 UART_GPIO_DSR))) {
263 if (ret & TIOCM_DSR)
264 status &= ~ATMEL_US_DSR;
265 else
266 status |= ATMEL_US_DSR;
267 }
268
269 if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
270 UART_GPIO_RI))) {
271 if (ret & TIOCM_RI)
272 status &= ~ATMEL_US_RI;
273 else
274 status |= ATMEL_US_RI;
275 }
276
277 if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios,
278 UART_GPIO_DCD))) {
279 if (ret & TIOCM_CD)
280 status &= ~ATMEL_US_DCD;
281 else
282 status |= ATMEL_US_DCD;
283 }
284
285 return status;
286}
287
240/* Enable or disable the rs485 support */ 288/* Enable or disable the rs485 support */
241void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) 289void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
242{ 290{
@@ -296,17 +344,6 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
296 unsigned int mode; 344 unsigned int mode;
297 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); 345 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
298 346
299 /*
300 * AT91RM9200 Errata #39: RTS0 is not internally connected
301 * to PA21. We need to drive the pin as a GPIO.
302 */
303 if (gpio_is_valid(atmel_port->rts_gpio)) {
304 if (mctrl & TIOCM_RTS)
305 gpio_set_value(atmel_port->rts_gpio, 0);
306 else
307 gpio_set_value(atmel_port->rts_gpio, 1);
308 }
309
310 if (mctrl & TIOCM_RTS) 347 if (mctrl & TIOCM_RTS)
311 control |= ATMEL_US_RTSEN; 348 control |= ATMEL_US_RTSEN;
312 else 349 else
@@ -319,6 +356,8 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
319 356
320 UART_PUT_CR(port, control); 357 UART_PUT_CR(port, control);
321 358
359 mctrl_gpio_set(atmel_port->gpios, mctrl);
360
322 /* Local loopback mode? */ 361 /* Local loopback mode? */
323 mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE; 362 mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE;
324 if (mctrl & TIOCM_LOOP) 363 if (mctrl & TIOCM_LOOP)
@@ -346,7 +385,8 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
346 */ 385 */
347static u_int atmel_get_mctrl(struct uart_port *port) 386static u_int atmel_get_mctrl(struct uart_port *port)
348{ 387{
349 unsigned int status, ret = 0; 388 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
389 unsigned int ret = 0, status;
350 390
351 status = UART_GET_CSR(port); 391 status = UART_GET_CSR(port);
352 392
@@ -362,7 +402,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
362 if (!(status & ATMEL_US_RI)) 402 if (!(status & ATMEL_US_RI))
363 ret |= TIOCM_RI; 403 ret |= TIOCM_RI;
364 404
365 return ret; 405 return mctrl_gpio_get(atmel_port->gpios, &ret);
366} 406}
367 407
368/* 408/*
@@ -1042,7 +1082,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
1042 unsigned int status, pending, pass_counter = 0; 1082 unsigned int status, pending, pass_counter = 0;
1043 1083
1044 do { 1084 do {
1045 status = UART_GET_CSR(port); 1085 status = atmel_get_lines_status(port);
1046 pending = status & UART_GET_IMR(port); 1086 pending = status & UART_GET_IMR(port);
1047 if (!pending) 1087 if (!pending)
1048 break; 1088 break;
@@ -1568,7 +1608,7 @@ static int atmel_startup(struct uart_port *port)
1568 } 1608 }
1569 1609
1570 /* Save current CSR for comparison in atmel_tasklet_func() */ 1610 /* Save current CSR for comparison in atmel_tasklet_func() */
1571 atmel_port->irq_status_prev = UART_GET_CSR(port); 1611 atmel_port->irq_status_prev = atmel_get_lines_status(port);
1572 atmel_port->irq_status = atmel_port->irq_status_prev; 1612 atmel_port->irq_status = atmel_port->irq_status_prev;
1573 1613
1574 /* 1614 /*
@@ -2324,6 +2364,15 @@ static int atmel_serial_resume(struct platform_device *pdev)
2324#define atmel_serial_resume NULL 2364#define atmel_serial_resume NULL
2325#endif 2365#endif
2326 2366
2367static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
2368{
2369 p->gpios = mctrl_gpio_init(dev, 0);
2370 if (IS_ERR_OR_NULL(p->gpios))
2371 return -1;
2372
2373 return 0;
2374}
2375
2327static int atmel_serial_probe(struct platform_device *pdev) 2376static int atmel_serial_probe(struct platform_device *pdev)
2328{ 2377{
2329 struct atmel_uart_port *port; 2378 struct atmel_uart_port *port;
@@ -2359,25 +2408,11 @@ static int atmel_serial_probe(struct platform_device *pdev)
2359 port = &atmel_ports[ret]; 2408 port = &atmel_ports[ret];
2360 port->backup_imr = 0; 2409 port->backup_imr = 0;
2361 port->uart.line = ret; 2410 port->uart.line = ret;
2362 port->rts_gpio = -EINVAL; /* Invalid, zero could be valid */ 2411
2363 if (pdata) 2412 ret = atmel_init_gpios(port, &pdev->dev);
2364 port->rts_gpio = pdata->rts_gpio; 2413 if (ret < 0)
2365 else if (np) 2414 dev_err(&pdev->dev, "%s",
2366 port->rts_gpio = of_get_named_gpio(np, "rts-gpios", 0); 2415 "Failed to initialize GPIOs. The serial port may not work as expected");
2367
2368 if (gpio_is_valid(port->rts_gpio)) {
2369 ret = devm_gpio_request(&pdev->dev, port->rts_gpio, "RTS");
2370 if (ret) {
2371 dev_err(&pdev->dev, "error requesting RTS GPIO\n");
2372 goto err;
2373 }
2374 /* Default to 1 as RTS is active low */
2375 ret = gpio_direction_output(port->rts_gpio, 1);
2376 if (ret) {
2377 dev_err(&pdev->dev, "error setting up RTS GPIO\n");
2378 goto err;
2379 }
2380 }
2381 2416
2382 ret = atmel_init_port(port, pdev); 2417 ret = atmel_init_port(port, pdev);
2383 if (ret) 2418 if (ret)