aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/mcf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/mcf.c')
-rw-r--r--drivers/tty/serial/mcf.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index fcd56ab6053f..e956377a38fe 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -23,6 +23,7 @@
23#include <linux/serial.h> 23#include <linux/serial.h>
24#include <linux/serial_core.h> 24#include <linux/serial_core.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/uaccess.h>
26#include <asm/coldfire.h> 27#include <asm/coldfire.h>
27#include <asm/mcfsim.h> 28#include <asm/mcfsim.h>
28#include <asm/mcfuart.h> 29#include <asm/mcfuart.h>
@@ -55,6 +56,7 @@ struct mcf_uart {
55 struct uart_port port; 56 struct uart_port port;
56 unsigned int sigs; /* Local copy of line sigs */ 57 unsigned int sigs; /* Local copy of line sigs */
57 unsigned char imr; /* Local IMR mirror */ 58 unsigned char imr; /* Local IMR mirror */
59 struct serial_rs485 rs485; /* RS485 settings */
58}; 60};
59 61
60/****************************************************************************/ 62/****************************************************************************/
@@ -101,6 +103,12 @@ static void mcf_start_tx(struct uart_port *port)
101{ 103{
102 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 104 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
103 105
106 if (pp->rs485.flags & SER_RS485_ENABLED) {
107 /* Enable Transmitter */
108 writeb(MCFUART_UCR_TXENABLE, port->membase + MCFUART_UCR);
109 /* Manually assert RTS */
110 writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
111 }
104 pp->imr |= MCFUART_UIR_TXREADY; 112 pp->imr |= MCFUART_UIR_TXREADY;
105 writeb(pp->imr, port->membase + MCFUART_UIMR); 113 writeb(pp->imr, port->membase + MCFUART_UIMR);
106} 114}
@@ -196,6 +204,7 @@ static void mcf_shutdown(struct uart_port *port)
196static void mcf_set_termios(struct uart_port *port, struct ktermios *termios, 204static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
197 struct ktermios *old) 205 struct ktermios *old)
198{ 206{
207 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
199 unsigned long flags; 208 unsigned long flags;
200 unsigned int baud, baudclk; 209 unsigned int baud, baudclk;
201#if defined(CONFIG_M5272) 210#if defined(CONFIG_M5272)
@@ -248,6 +257,11 @@ static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
248 mr2 |= MCFUART_MR2_TXCTS; 257 mr2 |= MCFUART_MR2_TXCTS;
249 } 258 }
250 259
260 if (pp->rs485.flags & SER_RS485_ENABLED) {
261 dev_dbg(port->dev, "Setting UART to RS485\n");
262 mr2 |= MCFUART_MR2_TXRTS;
263 }
264
251 spin_lock_irqsave(&port->lock, flags); 265 spin_lock_irqsave(&port->lock, flags);
252 uart_update_timeout(port, termios->c_cflag, baud); 266 uart_update_timeout(port, termios->c_cflag, baud);
253 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 267 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
@@ -310,7 +324,7 @@ static void mcf_rx_chars(struct mcf_uart *pp)
310 uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag); 324 uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
311 } 325 }
312 326
313 tty_flip_buffer_push(port->state->port.tty); 327 tty_flip_buffer_push(&port->state->port);
314} 328}
315 329
316/****************************************************************************/ 330/****************************************************************************/
@@ -342,6 +356,10 @@ static void mcf_tx_chars(struct mcf_uart *pp)
342 if (xmit->head == xmit->tail) { 356 if (xmit->head == xmit->tail) {
343 pp->imr &= ~MCFUART_UIR_TXREADY; 357 pp->imr &= ~MCFUART_UIR_TXREADY;
344 writeb(pp->imr, port->membase + MCFUART_UIMR); 358 writeb(pp->imr, port->membase + MCFUART_UIMR);
359 /* Disable TX to negate RTS automatically */
360 if (pp->rs485.flags & SER_RS485_ENABLED)
361 writeb(MCFUART_UCR_TXDISABLE,
362 port->membase + MCFUART_UCR);
345 } 363 }
346} 364}
347 365
@@ -418,6 +436,58 @@ static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser)
418 436
419/****************************************************************************/ 437/****************************************************************************/
420 438
439/* Enable or disable the RS485 support */
440static void mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
441{
442 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
443 unsigned long flags;
444 unsigned char mr1, mr2;
445
446 spin_lock_irqsave(&port->lock, flags);
447 /* Get mode registers */
448 mr1 = readb(port->membase + MCFUART_UMR);
449 mr2 = readb(port->membase + MCFUART_UMR);
450 if (rs485->flags & SER_RS485_ENABLED) {
451 dev_dbg(port->dev, "Setting UART to RS485\n");
452 /* Automatically negate RTS after TX completes */
453 mr2 |= MCFUART_MR2_TXRTS;
454 } else {
455 dev_dbg(port->dev, "Setting UART to RS232\n");
456 mr2 &= ~MCFUART_MR2_TXRTS;
457 }
458 writeb(mr1, port->membase + MCFUART_UMR);
459 writeb(mr2, port->membase + MCFUART_UMR);
460 pp->rs485 = *rs485;
461 spin_unlock_irqrestore(&port->lock, flags);
462}
463
464static int mcf_ioctl(struct uart_port *port, unsigned int cmd,
465 unsigned long arg)
466{
467 switch (cmd) {
468 case TIOCSRS485: {
469 struct serial_rs485 rs485;
470 if (copy_from_user(&rs485, (struct serial_rs485 *)arg,
471 sizeof(struct serial_rs485)))
472 return -EFAULT;
473 mcf_config_rs485(port, &rs485);
474 break;
475 }
476 case TIOCGRS485: {
477 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
478 if (copy_to_user((struct serial_rs485 *)arg, &pp->rs485,
479 sizeof(struct serial_rs485)))
480 return -EFAULT;
481 break;
482 }
483 default:
484 return -ENOIOCTLCMD;
485 }
486 return 0;
487}
488
489/****************************************************************************/
490
421/* 491/*
422 * Define the basic serial functions we support. 492 * Define the basic serial functions we support.
423 */ 493 */
@@ -438,6 +508,7 @@ static const struct uart_ops mcf_uart_ops = {
438 .release_port = mcf_release_port, 508 .release_port = mcf_release_port,
439 .config_port = mcf_config_port, 509 .config_port = mcf_config_port,
440 .verify_port = mcf_verify_port, 510 .verify_port = mcf_verify_port,
511 .ioctl = mcf_ioctl,
441}; 512};
442 513
443static struct mcf_uart mcf_ports[4]; 514static struct mcf_uart mcf_ports[4];