Skip to content

Commit 3b69e32

Browse files
linosanfilippo-kunbusgregkh
authored andcommitted
serial: amba-pl011: Fix DMA transmission in RS485 mode
When DMA is used in RS485 mode make sure that the UARTs tx section is enabled before the DMA buffers are queued for transmission. Cc: [email protected] Fixes: 8d47923 ("serial: amba-pl011: add RS485 support") Signed-off-by: Lino Sanfilippo <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f418ae7 commit 3b69e32

File tree

1 file changed

+30
-30
lines changed

1 file changed

+30
-30
lines changed

drivers/tty/serial/amba-pl011.c

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,11 +1339,41 @@ static void pl011_start_tx_pio(struct uart_amba_port *uap)
13391339
}
13401340
}
13411341

1342+
static void pl011_rs485_tx_start(struct uart_amba_port *uap)
1343+
{
1344+
struct uart_port *port = &uap->port;
1345+
u32 cr;
1346+
1347+
/* Enable transmitter */
1348+
cr = pl011_read(uap, REG_CR);
1349+
cr |= UART011_CR_TXE;
1350+
1351+
/* Disable receiver if half-duplex */
1352+
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
1353+
cr &= ~UART011_CR_RXE;
1354+
1355+
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
1356+
cr &= ~UART011_CR_RTS;
1357+
else
1358+
cr |= UART011_CR_RTS;
1359+
1360+
pl011_write(cr, uap, REG_CR);
1361+
1362+
if (port->rs485.delay_rts_before_send)
1363+
mdelay(port->rs485.delay_rts_before_send);
1364+
1365+
uap->rs485_tx_started = true;
1366+
}
1367+
13421368
static void pl011_start_tx(struct uart_port *port)
13431369
{
13441370
struct uart_amba_port *uap =
13451371
container_of(port, struct uart_amba_port, port);
13461372

1373+
if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
1374+
!uap->rs485_tx_started)
1375+
pl011_rs485_tx_start(uap);
1376+
13471377
if (!pl011_dma_tx_start(uap))
13481378
pl011_start_tx_pio(uap);
13491379
}
@@ -1424,42 +1454,12 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
14241454
return true;
14251455
}
14261456

1427-
static void pl011_rs485_tx_start(struct uart_amba_port *uap)
1428-
{
1429-
struct uart_port *port = &uap->port;
1430-
u32 cr;
1431-
1432-
/* Enable transmitter */
1433-
cr = pl011_read(uap, REG_CR);
1434-
cr |= UART011_CR_TXE;
1435-
1436-
/* Disable receiver if half-duplex */
1437-
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
1438-
cr &= ~UART011_CR_RXE;
1439-
1440-
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
1441-
cr &= ~UART011_CR_RTS;
1442-
else
1443-
cr |= UART011_CR_RTS;
1444-
1445-
pl011_write(cr, uap, REG_CR);
1446-
1447-
if (port->rs485.delay_rts_before_send)
1448-
mdelay(port->rs485.delay_rts_before_send);
1449-
1450-
uap->rs485_tx_started = true;
1451-
}
1452-
14531457
/* Returns true if tx interrupts have to be (kept) enabled */
14541458
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
14551459
{
14561460
struct circ_buf *xmit = &uap->port.state->xmit;
14571461
int count = uap->fifosize >> 1;
14581462

1459-
if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
1460-
!uap->rs485_tx_started)
1461-
pl011_rs485_tx_start(uap);
1462-
14631463
if (uap->port.x_char) {
14641464
if (!pl011_tx_char(uap, uap->port.x_char, from_irq))
14651465
return true;

0 commit comments

Comments
 (0)