@@ -248,6 +248,13 @@ struct pl011_dmatx_data {
248
248
bool queued ;
249
249
};
250
250
251
+ enum pl011_rs485_tx_state {
252
+ OFF ,
253
+ WAIT_AFTER_RTS ,
254
+ SEND ,
255
+ WAIT_AFTER_SEND ,
256
+ };
257
+
251
258
/*
252
259
* We wrap our port structure around the generic uart_port.
253
260
*/
@@ -261,8 +268,10 @@ struct uart_amba_port {
261
268
unsigned int fifosize ; /* vendor-specific */
262
269
unsigned int fixed_baud ; /* vendor-set fixed baud rate */
263
270
char type [12 ];
264
- bool rs485_tx_started ;
265
- unsigned int rs485_tx_drain_interval ; /* usecs */
271
+ ktime_t rs485_tx_drain_interval ; /* nano */
272
+ enum pl011_rs485_tx_state rs485_tx_state ;
273
+ struct hrtimer trigger_start_tx ;
274
+ struct hrtimer trigger_stop_tx ;
266
275
#ifdef CONFIG_DMA_ENGINE
267
276
/* DMA stuff */
268
277
unsigned int dmacr ; /* dma control reg */
@@ -1260,30 +1269,31 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
1260
1269
1261
1270
static void pl011_rs485_tx_stop (struct uart_amba_port * uap )
1262
1271
{
1263
- /*
1264
- * To be on the safe side only time out after twice as many iterations
1265
- * as fifo size.
1266
- */
1267
- const int MAX_TX_DRAIN_ITERS = uap -> port .fifosize * 2 ;
1268
1272
struct uart_port * port = & uap -> port ;
1269
- int i = 0 ;
1270
1273
u32 cr ;
1271
1274
1272
- /* Wait until hardware tx queue is empty */
1273
- while (!pl011_tx_empty (port )) {
1274
- if (i > MAX_TX_DRAIN_ITERS ) {
1275
- dev_warn (port -> dev ,
1276
- "timeout while draining hardware tx queue\n" );
1277
- break ;
1278
- }
1275
+ if (uap -> rs485_tx_state == SEND )
1276
+ uap -> rs485_tx_state = WAIT_AFTER_SEND ;
1279
1277
1280
- udelay (uap -> rs485_tx_drain_interval );
1281
- i ++ ;
1278
+ if (uap -> rs485_tx_state == WAIT_AFTER_SEND ) {
1279
+ /* Schedule hrtimer if tx queue not empty */
1280
+ if (!pl011_tx_empty (port )) {
1281
+ hrtimer_start (& uap -> trigger_stop_tx ,
1282
+ uap -> rs485_tx_drain_interval ,
1283
+ HRTIMER_MODE_REL );
1284
+ return ;
1285
+ }
1286
+ if (port -> rs485 .delay_rts_after_send > 0 ) {
1287
+ hrtimer_start (& uap -> trigger_stop_tx ,
1288
+ ms_to_ktime (port -> rs485 .delay_rts_after_send ),
1289
+ HRTIMER_MODE_REL );
1290
+ return ;
1291
+ }
1292
+ /* Continue without any delay */
1293
+ } else if (uap -> rs485_tx_state == WAIT_AFTER_RTS ) {
1294
+ hrtimer_try_to_cancel (& uap -> trigger_start_tx );
1282
1295
}
1283
1296
1284
- if (port -> rs485 .delay_rts_after_send )
1285
- mdelay (port -> rs485 .delay_rts_after_send );
1286
-
1287
1297
cr = pl011_read (uap , REG_CR );
1288
1298
1289
1299
if (port -> rs485 .flags & SER_RS485_RTS_AFTER_SEND )
@@ -1296,19 +1306,26 @@ static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
1296
1306
cr |= UART011_CR_RXE ;
1297
1307
pl011_write (cr , uap , REG_CR );
1298
1308
1299
- uap -> rs485_tx_started = false ;
1309
+ uap -> rs485_tx_state = OFF ;
1300
1310
}
1301
1311
1302
1312
static void pl011_stop_tx (struct uart_port * port )
1303
1313
{
1304
1314
struct uart_amba_port * uap =
1305
1315
container_of (port , struct uart_amba_port , port );
1306
1316
1317
+ if (port -> rs485 .flags & SER_RS485_ENABLED &&
1318
+ uap -> rs485_tx_state == WAIT_AFTER_RTS ) {
1319
+ pl011_rs485_tx_stop (uap );
1320
+ return ;
1321
+ }
1322
+
1307
1323
uap -> im &= ~UART011_TXIM ;
1308
1324
pl011_write (uap -> im , uap , REG_IMSC );
1309
1325
pl011_dma_tx_stop (uap );
1310
1326
1311
- if ((port -> rs485 .flags & SER_RS485_ENABLED ) && uap -> rs485_tx_started )
1327
+ if (port -> rs485 .flags & SER_RS485_ENABLED &&
1328
+ uap -> rs485_tx_state != OFF )
1312
1329
pl011_rs485_tx_stop (uap );
1313
1330
}
1314
1331
@@ -1328,10 +1345,19 @@ static void pl011_rs485_tx_start(struct uart_amba_port *uap)
1328
1345
struct uart_port * port = & uap -> port ;
1329
1346
u32 cr ;
1330
1347
1348
+ if (uap -> rs485_tx_state == WAIT_AFTER_RTS ) {
1349
+ uap -> rs485_tx_state = SEND ;
1350
+ return ;
1351
+ }
1352
+ if (uap -> rs485_tx_state == WAIT_AFTER_SEND ) {
1353
+ hrtimer_try_to_cancel (& uap -> trigger_stop_tx );
1354
+ uap -> rs485_tx_state = SEND ;
1355
+ return ;
1356
+ }
1357
+ /* uap->rs485_tx_state == OFF */
1331
1358
/* Enable transmitter */
1332
1359
cr = pl011_read (uap , REG_CR );
1333
1360
cr |= UART011_CR_TXE ;
1334
-
1335
1361
/* Disable receiver if half-duplex */
1336
1362
if (!(port -> rs485 .flags & SER_RS485_RX_DURING_TX ))
1337
1363
cr &= ~UART011_CR_RXE ;
@@ -1343,10 +1369,14 @@ static void pl011_rs485_tx_start(struct uart_amba_port *uap)
1343
1369
1344
1370
pl011_write (cr , uap , REG_CR );
1345
1371
1346
- if (port -> rs485 .delay_rts_before_send )
1347
- mdelay (port -> rs485 .delay_rts_before_send );
1348
-
1349
- uap -> rs485_tx_started = true;
1372
+ if (port -> rs485 .delay_rts_before_send > 0 ) {
1373
+ uap -> rs485_tx_state = WAIT_AFTER_RTS ;
1374
+ hrtimer_start (& uap -> trigger_start_tx ,
1375
+ ms_to_ktime (port -> rs485 .delay_rts_before_send ),
1376
+ HRTIMER_MODE_REL );
1377
+ } else {
1378
+ uap -> rs485_tx_state = SEND ;
1379
+ }
1350
1380
}
1351
1381
1352
1382
static void pl011_start_tx (struct uart_port * port )
@@ -1355,13 +1385,44 @@ static void pl011_start_tx(struct uart_port *port)
1355
1385
container_of (port , struct uart_amba_port , port );
1356
1386
1357
1387
if ((uap -> port .rs485 .flags & SER_RS485_ENABLED ) &&
1358
- ! uap -> rs485_tx_started )
1388
+ uap -> rs485_tx_state != SEND ) {
1359
1389
pl011_rs485_tx_start (uap );
1390
+ if (uap -> rs485_tx_state == WAIT_AFTER_RTS )
1391
+ return ;
1392
+ }
1360
1393
1361
1394
if (!pl011_dma_tx_start (uap ))
1362
1395
pl011_start_tx_pio (uap );
1363
1396
}
1364
1397
1398
+ static enum hrtimer_restart pl011_trigger_start_tx (struct hrtimer * t )
1399
+ {
1400
+ struct uart_amba_port * uap =
1401
+ container_of (t , struct uart_amba_port , trigger_start_tx );
1402
+ unsigned long flags ;
1403
+
1404
+ uart_port_lock_irqsave (& uap -> port , & flags );
1405
+ if (uap -> rs485_tx_state == WAIT_AFTER_RTS )
1406
+ pl011_start_tx (& uap -> port );
1407
+ uart_port_unlock_irqrestore (& uap -> port , flags );
1408
+
1409
+ return HRTIMER_NORESTART ;
1410
+ }
1411
+
1412
+ static enum hrtimer_restart pl011_trigger_stop_tx (struct hrtimer * t )
1413
+ {
1414
+ struct uart_amba_port * uap =
1415
+ container_of (t , struct uart_amba_port , trigger_stop_tx );
1416
+ unsigned long flags ;
1417
+
1418
+ uart_port_lock_irqsave (& uap -> port , & flags );
1419
+ if (uap -> rs485_tx_state == WAIT_AFTER_SEND )
1420
+ pl011_rs485_tx_stop (uap );
1421
+ uart_port_unlock_irqrestore (& uap -> port , flags );
1422
+
1423
+ return HRTIMER_NORESTART ;
1424
+ }
1425
+
1365
1426
static void pl011_stop_rx (struct uart_port * port )
1366
1427
{
1367
1428
struct uart_amba_port * uap =
@@ -1953,7 +2014,7 @@ static void pl011_shutdown(struct uart_port *port)
1953
2014
1954
2015
pl011_dma_shutdown (uap );
1955
2016
1956
- if ((port -> rs485 .flags & SER_RS485_ENABLED ) && uap -> rs485_tx_started )
2017
+ if ((port -> rs485 .flags & SER_RS485_ENABLED && uap -> rs485_tx_state != OFF ) )
1957
2018
pl011_rs485_tx_stop (uap );
1958
2019
1959
2020
free_irq (uap -> port .irq , uap );
@@ -2098,7 +2159,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
2098
2159
* with the given baud rate. We use this as the poll interval when we
2099
2160
* wait for the tx queue to empty.
2100
2161
*/
2101
- uap -> rs485_tx_drain_interval = DIV_ROUND_UP (bits * 1000 * 1000 , baud );
2162
+ uap -> rs485_tx_drain_interval = ns_to_ktime ( DIV_ROUND_UP (bits * NSEC_PER_SEC , baud ) );
2102
2163
2103
2164
pl011_setup_status_masks (port , termios );
2104
2165
@@ -2807,6 +2868,11 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
2807
2868
}
2808
2869
}
2809
2870
2871
+ hrtimer_init (& uap -> trigger_start_tx , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
2872
+ hrtimer_init (& uap -> trigger_stop_tx , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
2873
+ uap -> trigger_start_tx .function = pl011_trigger_start_tx ;
2874
+ uap -> trigger_stop_tx .function = pl011_trigger_stop_tx ;
2875
+
2810
2876
ret = pl011_setup_port (& dev -> dev , uap , & dev -> res , portnr );
2811
2877
if (ret )
2812
2878
return ret ;
0 commit comments