diff options
-rw-r--r-- | drivers/serial/sh-sci.c | 114 |
1 files changed, 81 insertions, 33 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index cd52dd64edf0..304a877d083d 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -106,6 +106,7 @@ struct sci_port { | |||
106 | struct work_struct work_tx; | 106 | struct work_struct work_tx; |
107 | struct work_struct work_rx; | 107 | struct work_struct work_rx; |
108 | struct timer_list rx_timer; | 108 | struct timer_list rx_timer; |
109 | unsigned int rx_timeout; | ||
109 | #endif | 110 | #endif |
110 | }; | 111 | }; |
111 | 112 | ||
@@ -673,22 +674,22 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) | |||
673 | struct sci_port *s = to_sci_port(port); | 674 | struct sci_port *s = to_sci_port(port); |
674 | 675 | ||
675 | if (s->chan_rx) { | 676 | if (s->chan_rx) { |
676 | unsigned long tout; | ||
677 | u16 scr = sci_in(port, SCSCR); | 677 | u16 scr = sci_in(port, SCSCR); |
678 | u16 ssr = sci_in(port, SCxSR); | 678 | u16 ssr = sci_in(port, SCxSR); |
679 | 679 | ||
680 | /* Disable future Rx interrupts */ | 680 | /* Disable future Rx interrupts */ |
681 | sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE); | 681 | if (port->type == PORT_SCIFA) { |
682 | disable_irq_nosync(irq); | ||
683 | scr |= 0x4000; | ||
684 | } else { | ||
685 | scr &= ~SCI_CTRL_FLAGS_RIE; | ||
686 | } | ||
687 | sci_out(port, SCSCR, scr); | ||
682 | /* Clear current interrupt */ | 688 | /* Clear current interrupt */ |
683 | sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); | 689 | sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); |
684 | /* Calculate delay for 1.5 DMA buffers */ | 690 | dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n", |
685 | tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / | 691 | jiffies, s->rx_timeout); |
686 | port->fifosize / 2; | 692 | mod_timer(&s->rx_timer, jiffies + s->rx_timeout); |
687 | dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n", | ||
688 | tout * 1000 / HZ); | ||
689 | if (tout < 2) | ||
690 | tout = 2; | ||
691 | mod_timer(&s->rx_timer, jiffies + tout); | ||
692 | 693 | ||
693 | return IRQ_HANDLED; | 694 | return IRQ_HANDLED; |
694 | } | 695 | } |
@@ -925,13 +926,17 @@ static void sci_dma_tx_complete(void *arg) | |||
925 | s->cookie_tx = -EINVAL; | 926 | s->cookie_tx = -EINVAL; |
926 | s->desc_tx = NULL; | 927 | s->desc_tx = NULL; |
927 | 928 | ||
928 | spin_unlock_irqrestore(&port->lock, flags); | ||
929 | |||
930 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 929 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
931 | uart_write_wakeup(port); | 930 | uart_write_wakeup(port); |
932 | 931 | ||
933 | if (uart_circ_chars_pending(xmit)) | 932 | if (!uart_circ_empty(xmit)) { |
934 | schedule_work(&s->work_tx); | 933 | schedule_work(&s->work_tx); |
934 | } else if (port->type == PORT_SCIFA) { | ||
935 | u16 ctrl = sci_in(port, SCSCR); | ||
936 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); | ||
937 | } | ||
938 | |||
939 | spin_unlock_irqrestore(&port->lock, flags); | ||
935 | } | 940 | } |
936 | 941 | ||
937 | /* Locking: called with port lock held */ | 942 | /* Locking: called with port lock held */ |
@@ -975,13 +980,13 @@ static void sci_dma_rx_complete(void *arg) | |||
975 | unsigned long flags; | 980 | unsigned long flags; |
976 | int count; | 981 | int count; |
977 | 982 | ||
978 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | 983 | dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx); |
979 | 984 | ||
980 | spin_lock_irqsave(&port->lock, flags); | 985 | spin_lock_irqsave(&port->lock, flags); |
981 | 986 | ||
982 | count = sci_dma_rx_push(s, tty, s->buf_len_rx); | 987 | count = sci_dma_rx_push(s, tty, s->buf_len_rx); |
983 | 988 | ||
984 | mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5)); | 989 | mod_timer(&s->rx_timer, jiffies + s->rx_timeout); |
985 | 990 | ||
986 | spin_unlock_irqrestore(&port->lock, flags); | 991 | spin_unlock_irqrestore(&port->lock, flags); |
987 | 992 | ||
@@ -1053,6 +1058,8 @@ static void sci_submit_rx(struct sci_port *s) | |||
1053 | sci_rx_dma_release(s, true); | 1058 | sci_rx_dma_release(s, true); |
1054 | return; | 1059 | return; |
1055 | } | 1060 | } |
1061 | dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__, | ||
1062 | s->cookie_rx[i], i); | ||
1056 | } | 1063 | } |
1057 | 1064 | ||
1058 | s->active_rx = s->cookie_rx[0]; | 1065 | s->active_rx = s->cookie_rx[0]; |
@@ -1110,10 +1117,10 @@ static void work_fn_rx(struct work_struct *work) | |||
1110 | return; | 1117 | return; |
1111 | } | 1118 | } |
1112 | 1119 | ||
1113 | dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__, | ||
1114 | s->cookie_rx[new], new); | ||
1115 | |||
1116 | s->active_rx = s->cookie_rx[!new]; | 1120 | s->active_rx = s->cookie_rx[!new]; |
1121 | |||
1122 | dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__, | ||
1123 | s->cookie_rx[new], new, s->active_rx); | ||
1117 | } | 1124 | } |
1118 | 1125 | ||
1119 | static void work_fn_tx(struct work_struct *work) | 1126 | static void work_fn_tx(struct work_struct *work) |
@@ -1175,23 +1182,28 @@ static void work_fn_tx(struct work_struct *work) | |||
1175 | 1182 | ||
1176 | static void sci_start_tx(struct uart_port *port) | 1183 | static void sci_start_tx(struct uart_port *port) |
1177 | { | 1184 | { |
1185 | struct sci_port *s = to_sci_port(port); | ||
1178 | unsigned short ctrl; | 1186 | unsigned short ctrl; |
1179 | 1187 | ||
1180 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1188 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
1181 | struct sci_port *s = to_sci_port(port); | 1189 | if (port->type == PORT_SCIFA) { |
1182 | 1190 | u16 new, scr = sci_in(port, SCSCR); | |
1183 | if (s->chan_tx) { | 1191 | if (s->chan_tx) |
1184 | if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0) | 1192 | new = scr | 0x8000; |
1185 | schedule_work(&s->work_tx); | 1193 | else |
1186 | 1194 | new = scr & ~0x8000; | |
1187 | return; | 1195 | if (new != scr) |
1196 | sci_out(port, SCSCR, new); | ||
1188 | } | 1197 | } |
1198 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && | ||
1199 | s->cookie_tx < 0) | ||
1200 | schedule_work(&s->work_tx); | ||
1189 | #endif | 1201 | #endif |
1190 | 1202 | if (!s->chan_tx || port->type == PORT_SCIFA) { | |
1191 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1203 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1192 | ctrl = sci_in(port, SCSCR); | 1204 | ctrl = sci_in(port, SCSCR); |
1193 | ctrl |= SCI_CTRL_FLAGS_TIE; | 1205 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); |
1194 | sci_out(port, SCSCR, ctrl); | 1206 | } |
1195 | } | 1207 | } |
1196 | 1208 | ||
1197 | static void sci_stop_tx(struct uart_port *port) | 1209 | static void sci_stop_tx(struct uart_port *port) |
@@ -1200,6 +1212,8 @@ static void sci_stop_tx(struct uart_port *port) | |||
1200 | 1212 | ||
1201 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1213 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1202 | ctrl = sci_in(port, SCSCR); | 1214 | ctrl = sci_in(port, SCSCR); |
1215 | if (port->type == PORT_SCIFA) | ||
1216 | ctrl &= ~0x8000; | ||
1203 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 1217 | ctrl &= ~SCI_CTRL_FLAGS_TIE; |
1204 | sci_out(port, SCSCR, ctrl); | 1218 | sci_out(port, SCSCR, ctrl); |
1205 | } | 1219 | } |
@@ -1210,6 +1224,8 @@ static void sci_start_rx(struct uart_port *port) | |||
1210 | 1224 | ||
1211 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | 1225 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ |
1212 | ctrl |= sci_in(port, SCSCR); | 1226 | ctrl |= sci_in(port, SCSCR); |
1227 | if (port->type == PORT_SCIFA) | ||
1228 | ctrl &= ~0x4000; | ||
1213 | sci_out(port, SCSCR, ctrl); | 1229 | sci_out(port, SCSCR, ctrl); |
1214 | } | 1230 | } |
1215 | 1231 | ||
@@ -1219,6 +1235,8 @@ static void sci_stop_rx(struct uart_port *port) | |||
1219 | 1235 | ||
1220 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ | 1236 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ |
1221 | ctrl = sci_in(port, SCSCR); | 1237 | ctrl = sci_in(port, SCSCR); |
1238 | if (port->type == PORT_SCIFA) | ||
1239 | ctrl &= ~0x4000; | ||
1222 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); | 1240 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); |
1223 | sci_out(port, SCSCR, ctrl); | 1241 | sci_out(port, SCSCR, ctrl); |
1224 | } | 1242 | } |
@@ -1253,8 +1271,12 @@ static void rx_timer_fn(unsigned long arg) | |||
1253 | { | 1271 | { |
1254 | struct sci_port *s = (struct sci_port *)arg; | 1272 | struct sci_port *s = (struct sci_port *)arg; |
1255 | struct uart_port *port = &s->port; | 1273 | struct uart_port *port = &s->port; |
1256 | |||
1257 | u16 scr = sci_in(port, SCSCR); | 1274 | u16 scr = sci_in(port, SCSCR); |
1275 | |||
1276 | if (port->type == PORT_SCIFA) { | ||
1277 | scr &= ~0x4000; | ||
1278 | enable_irq(s->irqs[1]); | ||
1279 | } | ||
1258 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); | 1280 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); |
1259 | dev_dbg(port->dev, "DMA Rx timed out\n"); | 1281 | dev_dbg(port->dev, "DMA Rx timed out\n"); |
1260 | schedule_work(&s->work_rx); | 1282 | schedule_work(&s->work_rx); |
@@ -1404,8 +1426,12 @@ static void sci_shutdown(struct uart_port *port) | |||
1404 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 1426 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
1405 | struct ktermios *old) | 1427 | struct ktermios *old) |
1406 | { | 1428 | { |
1429 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1430 | struct sci_port *s = to_sci_port(port); | ||
1431 | #endif | ||
1407 | unsigned int status, baud, smr_val, max_baud; | 1432 | unsigned int status, baud, smr_val, max_baud; |
1408 | int t = -1; | 1433 | int t = -1; |
1434 | u16 scfcr = 0; | ||
1409 | 1435 | ||
1410 | /* | 1436 | /* |
1411 | * earlyprintk comes here early on with port->uartclk set to zero. | 1437 | * earlyprintk comes here early on with port->uartclk set to zero. |
@@ -1428,7 +1454,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1428 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ | 1454 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ |
1429 | 1455 | ||
1430 | if (port->type != PORT_SCI) | 1456 | if (port->type != PORT_SCI) |
1431 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | 1457 | sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); |
1432 | 1458 | ||
1433 | smr_val = sci_in(port, SCSMR) & 3; | 1459 | smr_val = sci_in(port, SCSMR) & 3; |
1434 | if ((termios->c_cflag & CSIZE) == CS7) | 1460 | if ((termios->c_cflag & CSIZE) == CS7) |
@@ -1459,10 +1485,32 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1459 | } | 1485 | } |
1460 | 1486 | ||
1461 | sci_init_pins(port, termios->c_cflag); | 1487 | sci_init_pins(port, termios->c_cflag); |
1462 | sci_out(port, SCFCR, (termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0); | 1488 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); |
1463 | 1489 | ||
1464 | sci_out(port, SCSCR, SCSCR_INIT(port)); | 1490 | sci_out(port, SCSCR, SCSCR_INIT(port)); |
1465 | 1491 | ||
1492 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1493 | /* | ||
1494 | * Calculate delay for 1.5 DMA buffers: see | ||
1495 | * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits | ||
1496 | * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function | ||
1497 | * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)." | ||
1498 | * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO | ||
1499 | * sizes), but it has been found out experimentally, that this is not | ||
1500 | * enough: the driver too often needlessly runs on a DMA timeout. 20ms | ||
1501 | * as a minimum seem to work perfectly. | ||
1502 | */ | ||
1503 | if (s->chan_rx) { | ||
1504 | s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / | ||
1505 | port->fifosize / 2; | ||
1506 | dev_dbg(port->dev, | ||
1507 | "DMA Rx t-out %ums, tty t-out %u jiffies\n", | ||
1508 | s->rx_timeout * 1000 / HZ, port->timeout); | ||
1509 | if (s->rx_timeout < msecs_to_jiffies(20)) | ||
1510 | s->rx_timeout = msecs_to_jiffies(20); | ||
1511 | } | ||
1512 | #endif | ||
1513 | |||
1466 | if ((termios->c_cflag & CREAD) != 0) | 1514 | if ((termios->c_cflag & CREAD) != 0) |
1467 | sci_start_rx(port); | 1515 | sci_start_rx(port); |
1468 | } | 1516 | } |