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
157157 void serial8250_rpm_put_tx(struct uart_8250_port *p);
158158
159159 int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485);
160+void serial8250_em485_start_tx(struct uart_8250_port *p);
161+void serial8250_em485_stop_tx(struct uart_8250_port *p);
160162 void serial8250_em485_destroy(struct uart_8250_port *p);
161163
162164 /* 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
10071007 uart->port.unthrottle = up->port.unthrottle;
10081008 uart->port.rs485_config = up->port.rs485_config;
10091009 uart->port.rs485 = up->port.rs485;
1010+ uart->rs485_start_tx = up->rs485_start_tx;
1011+ uart->rs485_stop_tx = up->rs485_stop_tx;
10101012 uart->dma = up->dma;
10111013
10121014 /* 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
2929 * Fill a struct uart_port for a given device node
3030 */
3131 static int of_platform_serial_setup(struct platform_device *ofdev,
32− int type, struct uart_port *port,
32+ int type, struct uart_8250_port *up,
3333 struct of_serial_info *info)
3434 {
3535 struct resource resource;
3636 struct device_node *np = ofdev->dev.of_node;
37+ struct uart_port *port = &up->port;
3738 u32 clk, spd, prop;
3839 int ret, irq;
3940
@@ -155,6 +156,8 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 115 unmodified lines
155156
156157 port->dev = &ofdev->dev;
157158 port->rs485_config = serial8250_em485_config;
159+ up->rs485_start_tx = serial8250_em485_start_tx;
160+ up->rs485_stop_tx = serial8250_em485_stop_tx;
158161
159162 switch (type) {
160163 case PORT_RT2880:
@@ -201,7 +204,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev) · 40 unmodified lines
201204 return -ENOMEM;
202205
203206 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);
205208 if (ret)
206209 goto err_free;
207210
drivers/tty/serial/8250/8250_omap.c+2−0
@@ -1158,6 +1158,8 @@ static int omap8250_probe(struct platform_device *pdev) · 1157 unmodified lines
11581158 up.port.throttle = omap_8250_throttle;
11591159 up.port.unthrottle = omap_8250_unthrottle;
11601160 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;
11611163 up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
11621164
11631165 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
557557 }
558558 }
559559
560−static 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−
571560 static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
572561 static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
573562
@@ -632,7 +621,9 @@ static int serial8250_em485_init(struct uart_8250_port *p) · 58 unmodified lines
632621 p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
633622 p->em485->port = p;
634623 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);
636627
637628 return 0;
638629 }
@@ -1439,9 +1430,21 @@ static void serial8250_stop_rx(struct uart_port *port) · 800 unmodified lines
14391430 serial8250_rpm_put(up);
14401431 }
14411432
1442−static 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+ */
1439+void serial8250_em485_stop_tx(struct uart_8250_port *p)
14431440 {
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);
14451448
14461449 /*
14471450 * 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
14551458 serial_port_out(&p->port, UART_IER, p->ier);
14561459 }
14571460 }
1461+EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
1462+
14581463 static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
14591464 {
14601465 struct uart_8250_em485 *em485;
@@ -1467,8 +1472,9 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) · 6 unmodified lines
14671472 serial8250_rpm_get(p);
14681473 spin_lock_irqsave(&p->port.lock, flags);
14691474 if (em485->active_timer == &em485->stop_tx_timer) {
1470− __do_stop_tx_rs485(p);
1475+ p->rs485_stop_tx(p);
14711476 em485->active_timer = NULL;
1477+ em485->tx_stopped = true;
14721478 }
14731479 spin_unlock_irqrestore(&p->port.lock, flags);
14741480 serial8250_rpm_put(p);
@@ -1489,7 +1495,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p) · 14 unmodified lines
14891495 struct uart_8250_em485 *em485 = p->em485;
14901496
14911497 /*
1492− * __do_stop_tx_rs485 is going to set RTS according to config
1498+ * rs485_stop_tx() is going to set RTS according to config
14931499 * AND flush RX FIFO if required.
14941500 */
14951501 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
14971503 start_hrtimer_ms(&em485->stop_tx_timer,
14981504 p->port.rs485.delay_rts_after_send);
14991505 } else {
1500− __do_stop_tx_rs485(p);
1506+ p->rs485_stop_tx(p);
15011507 em485->active_timer = NULL;
1508+ em485->tx_stopped = true;
15021509 }
15031510 }
15041511
@@ -1572,25 +1579,42 @@ static inline void __start_tx(struct uart_port *port) · 67 unmodified lines
15721579 }
15731580 }
15741581
1575−static 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+ */
1592+void serial8250_em485_start_tx(struct uart_8250_port *up)
15761593 {
1577− struct uart_8250_port *up = up_to_u8250p(port);
1578− struct uart_8250_em485 *em485 = up->em485;
1579− unsigned char mcr;
1594+ unsigned char mcr = serial8250_in_MCR(up);
15801595
15811596 if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
15821597 serial8250_stop_rx(&up->port);
15831598
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+}
1605+EXPORT_SYMBOL_GPL(serial8250_em485_start_tx);
1606+
1607+static 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+
15841612 em485->active_timer = NULL;
15851613
1586− mcr = serial8250_in_MCR(up);
1587− if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) !=
1588− !!(mcr & UART_MCR_RTS)) {
1589− if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
1590− mcr |= UART_MCR_RTS;
1591− else
1592− mcr &= ~UART_MCR_RTS;
1593− serial8250_out_MCR(up, mcr);
1614+ if (em485->tx_stopped) {
1615+ em485->tx_stopped = false;
1616+
1617+ up->rs485_start_tx(up);
15941618
15951619 if (up->port.rs485.delay_rts_before_send > 0) {
15961620 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
8181 struct hrtimer stop_tx_timer; /* "rs485 stop tx" timer */
8282 struct hrtimer *active_timer; /* pointer to active timer */
8383 struct uart_8250_port *port; /* for hrtimer callbacks */
84+ unsigned int tx_stopped:1; /* tx is currently stopped */
8485 };
8586
8687 /*
@@ -132,6 +133,8 @@ struct uart_8250_port { · 45 unmodified lines
132133 void (*dl_write)(struct uart_8250_port *, int);
133134
134135 struct uart_8250_em485 *em485;
136+ void (*rs485_start_tx)(struct uart_8250_port *);
137+ void (*rs485_stop_tx)(struct uart_8250_port *);
135138
136139 /* Serial port overrun backoff */
137140 struct delayed_work overrun_backoff;