History

serial: 8250: Generalize rs485 software emulation

Commit e490c9144cfa ("tty: Add software emulated RS485 support for 8250") introduced support to use RTS as an rs485 Transmit Enable signal. So far the only drivers taking advantage of it are 8250_omap.c and 8250_of.c. We're about to make use of the feature in 8250_bcm2835aux.c as well. The bcm2835aux differs from omap chips by inverting the meaning of RTS in the MCR register. Moreover, omap achieves half-duplex mode by disabling the RX interrupt and clearing the RX FIFO when TX stops. The bcm2835aux requires disabling the receiver instead. Support these behavioral differences by generalizing the rs485 emulation: Introduce ->rs485_start_tx() and ->rs485_stop_tx() callbacks in struct uart_8250_port, provide generic implementations containing the existing code and use them as callbacks in 8250_omap.c and 8250_of.c. start_tx_rs485() is idempotent in that it recognizes whether RTS is already asserted. Achieve the same by introducing a tx_stopped flag in struct uart_8250_em485. This may even perform a little better on arches where memory access is faster than mmio access.

Lukas Wunner committed 6 years ago

Commit 058bc101 parent 41a70b76 files · +67 −31Browse files

Unified · Split

6 files
  1. drivers/tty/serial/8250/8250.h +2 −0
  2. drivers/tty/serial/8250/8250_core.c +2 −0
  3. drivers/tty/serial/8250/8250_of.c +5 −2
  4. drivers/tty/serial/8250/8250_omap.c +2 −0
  5. drivers/tty/serial/8250/8250_port.c +53 −29
  6. include/linux/serial_8250.h +3 −0
drivers/tty/serial/8250/8250.h+2−0
@@ -157,6 +157,8 @@ void serial8250_rpm_get_tx(struct uart_8250_port *p); · 156 unmodified lines
157void serial8250_rpm_put_tx(struct uart_8250_port *p);157void serial8250_rpm_put_tx(struct uart_8250_port *p);
158 158
159int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485);159int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485);
160void serial8250_em485_start_tx(struct uart_8250_port *p);
161void serial8250_em485_stop_tx(struct uart_8250_port *p);
160void serial8250_em485_destroy(struct uart_8250_port *p);162void serial8250_em485_destroy(struct uart_8250_port *p);
161 163
162/* MCR <-> TIOCM conversion */164/* MCR <-> TIOCM conversion */
drivers/tty/serial/8250/8250_core.c+2−0
@@ -1007,6 +1007,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) · 1006 unmodified lines
1007 uart->port.unthrottle = up->port.unthrottle;1007 uart->port.unthrottle = up->port.unthrottle;
1008 uart->port.rs485_config = up->port.rs485_config;1008 uart->port.rs485_config = up->port.rs485_config;
1009 uart->port.rs485 = up->port.rs485;1009 uart->port.rs485 = up->port.rs485;
1010 uart->rs485_start_tx = up->rs485_start_tx;
1011 uart->rs485_stop_tx = up->rs485_stop_tx;
1010 uart->dma = up->dma;1012 uart->dma = up->dma;
1011 1013
1012 /* Take tx_loadsz from fifosize if it wasn't set separately */1014 /* Take tx_loadsz from fifosize if it wasn't set separately */
drivers/tty/serial/8250/8250_of.c+5−2
@@ -29,11 +29,12 @@ struct of_serial_info { · 28 unmodified lines
29 * Fill a struct uart_port for a given device node29 * Fill a struct uart_port for a given device node
30 */30 */
31static int of_platform_serial_setup(struct platform_device *ofdev,31static int of_platform_serial_setup(struct platform_device *ofdev,
32 int type, struct uart_port *port,32 int type, struct uart_8250_port *up,
33 struct of_serial_info *info)33 struct of_serial_info *info)
34{34{
35 struct resource resource;35 struct resource resource;
36 struct device_node *np = ofdev->dev.of_node;36 struct device_node *np = ofdev->dev.of_node;
37 struct uart_port *port = &up->port;
37 u32 clk, spd, prop;38 u32 clk, spd, prop;
38 int ret, irq;39 int ret, irq;
39 40
@@ -155,6 +156,8 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 115 unmodified lines
155 156
156 port->dev = &ofdev->dev;157 port->dev = &ofdev->dev;
157 port->rs485_config = serial8250_em485_config;158 port->rs485_config = serial8250_em485_config;
159 up->rs485_start_tx = serial8250_em485_start_tx;
160 up->rs485_stop_tx = serial8250_em485_stop_tx;
158 161
159 switch (type) {162 switch (type) {
160 case PORT_RT2880:163 case PORT_RT2880:
@@ -201,7 +204,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev) · 40 unmodified lines
201 return -ENOMEM;204 return -ENOMEM;
202 205
203 memset(&port8250, 0, sizeof(port8250));206 memset(&port8250, 0, sizeof(port8250));
204 ret = of_platform_serial_setup(ofdev, port_type, &port8250.port, info);207 ret = of_platform_serial_setup(ofdev, port_type, &port8250, info);
205 if (ret)208 if (ret)
206 goto err_free;209 goto err_free;
207 210
drivers/tty/serial/8250/8250_omap.c+2−0
@@ -1158,6 +1158,8 @@ static int omap8250_probe(struct platform_device *pdev) · 1157 unmodified lines
1158 up.port.throttle = omap_8250_throttle;1158 up.port.throttle = omap_8250_throttle;
1159 up.port.unthrottle = omap_8250_unthrottle;1159 up.port.unthrottle = omap_8250_unthrottle;
1160 up.port.rs485_config = serial8250_em485_config;1160 up.port.rs485_config = serial8250_em485_config;
1161 up.rs485_start_tx = serial8250_em485_start_tx;
1162 up.rs485_stop_tx = serial8250_em485_stop_tx;
1161 up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);1163 up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
1162 1164
1163 ret = of_alias_get_id(np, "serial");1165 ret = of_alias_get_id(np, "serial");
drivers/tty/serial/8250/8250_port.c+53−29
@@ -557,17 +557,6 @@ static void serial8250_clear_fifos(struct uart_8250_port *p) · 556 unmodified lines
557 }557 }
558}558}
559 559
560static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p)
561{
562 unsigned char mcr = serial8250_in_MCR(p);
563
564 if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
565 mcr |= UART_MCR_RTS;
566 else
567 mcr &= ~UART_MCR_RTS;
568 serial8250_out_MCR(p, mcr);
569}
570
571static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);560static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
572static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);561static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
573 562
@@ -632,7 +621,9 @@ static int serial8250_em485_init(struct uart_8250_port *p) · 58 unmodified lines
632 p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;621 p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
633 p->em485->port = p;622 p->em485->port = p;
634 p->em485->active_timer = NULL;623 p->em485->active_timer = NULL;
635 serial8250_em485_rts_after_send(p);624 p->em485->tx_stopped = true;
625
626 p->rs485_stop_tx(p);
636 627
637 return 0;628 return 0;
638}629}
@@ -1439,9 +1430,21 @@ static void serial8250_stop_rx(struct uart_port *port) · 800 unmodified lines
1439 serial8250_rpm_put(up);1430 serial8250_rpm_put(up);
1440}1431}
1441 1432
1442static void __do_stop_tx_rs485(struct uart_8250_port *p)1433/**
1434 * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback
1435 * @up: uart 8250 port
1436 *
1437 * Generic callback usable by 8250 uart drivers to stop rs485 transmission.
1438 */
1439void serial8250_em485_stop_tx(struct uart_8250_port *p)
1443{1440{
1444 serial8250_em485_rts_after_send(p);1441 unsigned char mcr = serial8250_in_MCR(p);
1442
1443 if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
1444 mcr |= UART_MCR_RTS;
1445 else
1446 mcr &= ~UART_MCR_RTS;
1447 serial8250_out_MCR(p, mcr);
1445 1448
1446 /*1449 /*
1447 * Empty the RX FIFO, we are not interested in anything1450 * Empty the RX FIFO, we are not interested in anything
@@ -1455,6 +1458,8 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p) · 7 unmodified lines
1455 serial_port_out(&p->port, UART_IER, p->ier);1458 serial_port_out(&p->port, UART_IER, p->ier);
1456 }1459 }
1457}1460}
1461EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
1462
1458static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)1463static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
1459{1464{
1460 struct uart_8250_em485 *em485;1465 struct uart_8250_em485 *em485;
@@ -1467,8 +1472,9 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) · 6 unmodified lines
1467 serial8250_rpm_get(p);1472 serial8250_rpm_get(p);
1468 spin_lock_irqsave(&p->port.lock, flags);1473 spin_lock_irqsave(&p->port.lock, flags);
1469 if (em485->active_timer == &em485->stop_tx_timer) {1474 if (em485->active_timer == &em485->stop_tx_timer) {
1470 __do_stop_tx_rs485(p);1475 p->rs485_stop_tx(p);
1471 em485->active_timer = NULL;1476 em485->active_timer = NULL;
1477 em485->tx_stopped = true;
1472 }1478 }
1473 spin_unlock_irqrestore(&p->port.lock, flags);1479 spin_unlock_irqrestore(&p->port.lock, flags);
1474 serial8250_rpm_put(p);1480 serial8250_rpm_put(p);
@@ -1489,7 +1495,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p) · 14 unmodified lines
1489 struct uart_8250_em485 *em485 = p->em485;1495 struct uart_8250_em485 *em485 = p->em485;
1490 1496
1491 /*1497 /*
1492 * __do_stop_tx_rs485 is going to set RTS according to config1498 * rs485_stop_tx() is going to set RTS according to config
1493 * AND flush RX FIFO if required.1499 * AND flush RX FIFO if required.
1494 */1500 */
1495 if (p->port.rs485.delay_rts_after_send > 0) {1501 if (p->port.rs485.delay_rts_after_send > 0) {
@@ -1497,8 +1503,9 @@ static void __stop_tx_rs485(struct uart_8250_port *p) · 1 unmodified line
1497 start_hrtimer_ms(&em485->stop_tx_timer,1503 start_hrtimer_ms(&em485->stop_tx_timer,
1498 p->port.rs485.delay_rts_after_send);1504 p->port.rs485.delay_rts_after_send);
1499 } else {1505 } else {
1500 __do_stop_tx_rs485(p);1506 p->rs485_stop_tx(p);
1501 em485->active_timer = NULL;1507 em485->active_timer = NULL;
1508 em485->tx_stopped = true;
1502 }1509 }
1503}1510}
1504 1511
@@ -1572,25 +1579,42 @@ static inline void __start_tx(struct uart_port *port) · 67 unmodified lines
1572 }1579 }
1573}1580}
1574 1581
1575static inline void start_tx_rs485(struct uart_port *port)1582/**
1583 * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback
1584 * @up: uart 8250 port
1585 *
1586 * Generic callback usable by 8250 uart drivers to start rs485 transmission.
1587 * Assumes that setting the RTS bit in the MCR register means RTS is high.
1588 * (Some chips use inverse semantics.) Further assumes that reception is
1589 * stoppable by disabling the UART_IER_RDI interrupt. (Some chips set the
1590 * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.)
1591 */
1592void serial8250_em485_start_tx(struct uart_8250_port *up)
1576{1593{
1577 struct uart_8250_port *up = up_to_u8250p(port);1594 unsigned char mcr = serial8250_in_MCR(up);
1578 struct uart_8250_em485 *em485 = up->em485;
1579 unsigned char mcr;
1580 1595
1581 if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))1596 if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
1582 serial8250_stop_rx(&up->port);1597 serial8250_stop_rx(&up->port);
1583 1598
1599 if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
1600 mcr |= UART_MCR_RTS;
1601 else
1602 mcr &= ~UART_MCR_RTS;
1603 serial8250_out_MCR(up, mcr);
1604}
1605EXPORT_SYMBOL_GPL(serial8250_em485_start_tx);
1606
1607static inline void start_tx_rs485(struct uart_port *port)
1608{
1609 struct uart_8250_port *up = up_to_u8250p(port);
1610 struct uart_8250_em485 *em485 = up->em485;
1611
1584 em485->active_timer = NULL;1612 em485->active_timer = NULL;
1585 1613
1586 mcr = serial8250_in_MCR(up);1614 if (em485->tx_stopped) {
1587 if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) !=1615 em485->tx_stopped = false;
1588 !!(mcr & UART_MCR_RTS)) {1616
1589 if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)1617 up->rs485_start_tx(up);
1590 mcr |= UART_MCR_RTS;
1591 else
1592 mcr &= ~UART_MCR_RTS;
1593 serial8250_out_MCR(up, mcr);
1594 1618
1595 if (up->port.rs485.delay_rts_before_send > 0) {1619 if (up->port.rs485.delay_rts_before_send > 0) {
1596 em485->active_timer = &em485->start_tx_timer;1620 em485->active_timer = &em485->start_tx_timer;
include/linux/serial_8250.h+3−0
@@ -81,6 +81,7 @@ struct uart_8250_em485 { · 80 unmodified lines
81 struct hrtimer stop_tx_timer; /* "rs485 stop tx" timer */81 struct hrtimer stop_tx_timer; /* "rs485 stop tx" timer */
82 struct hrtimer *active_timer; /* pointer to active timer */82 struct hrtimer *active_timer; /* pointer to active timer */
83 struct uart_8250_port *port; /* for hrtimer callbacks */83 struct uart_8250_port *port; /* for hrtimer callbacks */
84 unsigned int tx_stopped:1; /* tx is currently stopped */
84};85};
85 86
86/*87/*
@@ -132,6 +133,8 @@ struct uart_8250_port { · 45 unmodified lines
132 void (*dl_write)(struct uart_8250_port *, int);133 void (*dl_write)(struct uart_8250_port *, int);
133 134
134 struct uart_8250_em485 *em485;135 struct uart_8250_em485 *em485;
136 void (*rs485_start_tx)(struct uart_8250_port *);
137 void (*rs485_stop_tx)(struct uart_8250_port *);
135 138
136 /* Serial port overrun backoff */139 /* Serial port overrun backoff */
137 struct delayed_work overrun_backoff;140 struct delayed_work overrun_backoff;