diff options
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 102 |
1 files changed, 77 insertions, 25 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c291b3add1d2..92c91c83edde 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) | 4 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) |
5 | * | 5 | * |
6 | * Copyright (C) 2002 - 2008 Paul Mundt | 6 | * Copyright (C) 2002 - 2011 Paul Mundt |
7 | * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). | 7 | * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). |
8 | * | 8 | * |
9 | * based off of the old drivers/char/sh-sci.c by: | 9 | * based off of the old drivers/char/sh-sci.c by: |
@@ -81,14 +81,22 @@ struct sci_port { | |||
81 | struct timer_list break_timer; | 81 | struct timer_list break_timer; |
82 | int break_flag; | 82 | int break_flag; |
83 | 83 | ||
84 | /* SCSCR initialization */ | ||
85 | unsigned int scscr; | ||
86 | |||
87 | /* SCBRR calculation algo */ | ||
88 | unsigned int scbrr_algo_id; | ||
89 | |||
84 | /* Interface clock */ | 90 | /* Interface clock */ |
85 | struct clk *iclk; | 91 | struct clk *iclk; |
86 | /* Function clock */ | 92 | /* Function clock */ |
87 | struct clk *fclk; | 93 | struct clk *fclk; |
88 | 94 | ||
89 | struct list_head node; | 95 | struct list_head node; |
96 | |||
90 | struct dma_chan *chan_tx; | 97 | struct dma_chan *chan_tx; |
91 | struct dma_chan *chan_rx; | 98 | struct dma_chan *chan_rx; |
99 | |||
92 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 100 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
93 | struct device *dma_dev; | 101 | struct device *dma_dev; |
94 | unsigned int slave_tx; | 102 | unsigned int slave_tx; |
@@ -415,9 +423,9 @@ static void sci_transmit_chars(struct uart_port *port) | |||
415 | if (!(status & SCxSR_TDxE(port))) { | 423 | if (!(status & SCxSR_TDxE(port))) { |
416 | ctrl = sci_in(port, SCSCR); | 424 | ctrl = sci_in(port, SCSCR); |
417 | if (uart_circ_empty(xmit)) | 425 | if (uart_circ_empty(xmit)) |
418 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 426 | ctrl &= ~SCSCR_TIE; |
419 | else | 427 | else |
420 | ctrl |= SCI_CTRL_FLAGS_TIE; | 428 | ctrl |= SCSCR_TIE; |
421 | sci_out(port, SCSCR, ctrl); | 429 | sci_out(port, SCSCR, ctrl); |
422 | return; | 430 | return; |
423 | } | 431 | } |
@@ -459,7 +467,7 @@ static void sci_transmit_chars(struct uart_port *port) | |||
459 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); | 467 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); |
460 | } | 468 | } |
461 | 469 | ||
462 | ctrl |= SCI_CTRL_FLAGS_TIE; | 470 | ctrl |= SCSCR_TIE; |
463 | sci_out(port, SCSCR, ctrl); | 471 | sci_out(port, SCSCR, ctrl); |
464 | } | 472 | } |
465 | } | 473 | } |
@@ -708,7 +716,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) | |||
708 | disable_irq_nosync(irq); | 716 | disable_irq_nosync(irq); |
709 | scr |= 0x4000; | 717 | scr |= 0x4000; |
710 | } else { | 718 | } else { |
711 | scr &= ~SCI_CTRL_FLAGS_RIE; | 719 | scr &= ~SCSCR_RIE; |
712 | } | 720 | } |
713 | sci_out(port, SCSCR, scr); | 721 | sci_out(port, SCSCR, scr); |
714 | /* Clear current interrupt */ | 722 | /* Clear current interrupt */ |
@@ -777,6 +785,18 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) | |||
777 | return IRQ_HANDLED; | 785 | return IRQ_HANDLED; |
778 | } | 786 | } |
779 | 787 | ||
788 | static inline unsigned long port_rx_irq_mask(struct uart_port *port) | ||
789 | { | ||
790 | /* | ||
791 | * Not all ports (such as SCIFA) will support REIE. Rather than | ||
792 | * special-casing the port type, we check the port initialization | ||
793 | * IRQ enable mask to see whether the IRQ is desired at all. If | ||
794 | * it's unset, it's logically inferred that there's no point in | ||
795 | * testing for it. | ||
796 | */ | ||
797 | return SCSCR_RIE | (to_sci_port(port)->scscr & SCSCR_REIE); | ||
798 | } | ||
799 | |||
780 | static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | 800 | static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) |
781 | { | 801 | { |
782 | unsigned short ssr_status, scr_status, err_enabled; | 802 | unsigned short ssr_status, scr_status, err_enabled; |
@@ -786,22 +806,25 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | |||
786 | 806 | ||
787 | ssr_status = sci_in(port, SCxSR); | 807 | ssr_status = sci_in(port, SCxSR); |
788 | scr_status = sci_in(port, SCSCR); | 808 | scr_status = sci_in(port, SCSCR); |
789 | err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); | 809 | err_enabled = scr_status & port_rx_irq_mask(port); |
790 | 810 | ||
791 | /* Tx Interrupt */ | 811 | /* Tx Interrupt */ |
792 | if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE) && | 812 | if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCSCR_TIE) && |
793 | !s->chan_tx) | 813 | !s->chan_tx) |
794 | ret = sci_tx_interrupt(irq, ptr); | 814 | ret = sci_tx_interrupt(irq, ptr); |
815 | |||
795 | /* | 816 | /* |
796 | * Rx Interrupt: if we're using DMA, the DMA controller clears RDF / | 817 | * Rx Interrupt: if we're using DMA, the DMA controller clears RDF / |
797 | * DR flags | 818 | * DR flags |
798 | */ | 819 | */ |
799 | if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) && | 820 | if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) && |
800 | (scr_status & SCI_CTRL_FLAGS_RIE)) | 821 | (scr_status & SCSCR_RIE)) |
801 | ret = sci_rx_interrupt(irq, ptr); | 822 | ret = sci_rx_interrupt(irq, ptr); |
823 | |||
802 | /* Error Interrupt */ | 824 | /* Error Interrupt */ |
803 | if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) | 825 | if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) |
804 | ret = sci_er_interrupt(irq, ptr); | 826 | ret = sci_er_interrupt(irq, ptr); |
827 | |||
805 | /* Break Interrupt */ | 828 | /* Break Interrupt */ |
806 | if ((ssr_status & SCxSR_BRK(port)) && err_enabled) | 829 | if ((ssr_status & SCxSR_BRK(port)) && err_enabled) |
807 | ret = sci_br_interrupt(irq, ptr); | 830 | ret = sci_br_interrupt(irq, ptr); |
@@ -951,7 +974,7 @@ static void sci_dma_tx_complete(void *arg) | |||
951 | schedule_work(&s->work_tx); | 974 | schedule_work(&s->work_tx); |
952 | } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 975 | } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
953 | u16 ctrl = sci_in(port, SCSCR); | 976 | u16 ctrl = sci_in(port, SCSCR); |
954 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); | 977 | sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); |
955 | } | 978 | } |
956 | 979 | ||
957 | spin_unlock_irqrestore(&port->lock, flags); | 980 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -1214,14 +1237,16 @@ static void sci_start_tx(struct uart_port *port) | |||
1214 | if (new != scr) | 1237 | if (new != scr) |
1215 | sci_out(port, SCSCR, new); | 1238 | sci_out(port, SCSCR, new); |
1216 | } | 1239 | } |
1240 | |||
1217 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && | 1241 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && |
1218 | s->cookie_tx < 0) | 1242 | s->cookie_tx < 0) |
1219 | schedule_work(&s->work_tx); | 1243 | schedule_work(&s->work_tx); |
1220 | #endif | 1244 | #endif |
1245 | |||
1221 | if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 1246 | if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1222 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1247 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1223 | ctrl = sci_in(port, SCSCR); | 1248 | ctrl = sci_in(port, SCSCR); |
1224 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); | 1249 | sci_out(port, SCSCR, ctrl | SCSCR_TIE); |
1225 | } | 1250 | } |
1226 | } | 1251 | } |
1227 | 1252 | ||
@@ -1231,20 +1256,24 @@ static void sci_stop_tx(struct uart_port *port) | |||
1231 | 1256 | ||
1232 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1257 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1233 | ctrl = sci_in(port, SCSCR); | 1258 | ctrl = sci_in(port, SCSCR); |
1259 | |||
1234 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 1260 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1235 | ctrl &= ~0x8000; | 1261 | ctrl &= ~0x8000; |
1236 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 1262 | |
1263 | ctrl &= ~SCSCR_TIE; | ||
1264 | |||
1237 | sci_out(port, SCSCR, ctrl); | 1265 | sci_out(port, SCSCR, ctrl); |
1238 | } | 1266 | } |
1239 | 1267 | ||
1240 | static void sci_start_rx(struct uart_port *port) | 1268 | static void sci_start_rx(struct uart_port *port) |
1241 | { | 1269 | { |
1242 | unsigned short ctrl = SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE; | 1270 | unsigned short ctrl; |
1271 | |||
1272 | ctrl = sci_in(port, SCSCR) | port_rx_irq_mask(port); | ||
1243 | 1273 | ||
1244 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | ||
1245 | ctrl |= sci_in(port, SCSCR); | ||
1246 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 1274 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1247 | ctrl &= ~0x4000; | 1275 | ctrl &= ~0x4000; |
1276 | |||
1248 | sci_out(port, SCSCR, ctrl); | 1277 | sci_out(port, SCSCR, ctrl); |
1249 | } | 1278 | } |
1250 | 1279 | ||
@@ -1252,11 +1281,13 @@ static void sci_stop_rx(struct uart_port *port) | |||
1252 | { | 1281 | { |
1253 | unsigned short ctrl; | 1282 | unsigned short ctrl; |
1254 | 1283 | ||
1255 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ | ||
1256 | ctrl = sci_in(port, SCSCR); | 1284 | ctrl = sci_in(port, SCSCR); |
1285 | |||
1257 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 1286 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1258 | ctrl &= ~0x4000; | 1287 | ctrl &= ~0x4000; |
1259 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); | 1288 | |
1289 | ctrl &= ~port_rx_irq_mask(port); | ||
1290 | |||
1260 | sci_out(port, SCSCR, ctrl); | 1291 | sci_out(port, SCSCR, ctrl); |
1261 | } | 1292 | } |
1262 | 1293 | ||
@@ -1296,7 +1327,7 @@ static void rx_timer_fn(unsigned long arg) | |||
1296 | scr &= ~0x4000; | 1327 | scr &= ~0x4000; |
1297 | enable_irq(s->irqs[1]); | 1328 | enable_irq(s->irqs[1]); |
1298 | } | 1329 | } |
1299 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); | 1330 | sci_out(port, SCSCR, scr | SCSCR_RIE); |
1300 | dev_dbg(port->dev, "DMA Rx timed out\n"); | 1331 | dev_dbg(port->dev, "DMA Rx timed out\n"); |
1301 | schedule_work(&s->work_rx); | 1332 | schedule_work(&s->work_rx); |
1302 | } | 1333 | } |
@@ -1442,12 +1473,31 @@ static void sci_shutdown(struct uart_port *port) | |||
1442 | s->disable(port); | 1473 | s->disable(port); |
1443 | } | 1474 | } |
1444 | 1475 | ||
1476 | static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, | ||
1477 | unsigned long freq) | ||
1478 | { | ||
1479 | switch (algo_id) { | ||
1480 | case SCBRR_ALGO_1: | ||
1481 | return ((freq + 16 * bps) / (16 * bps) - 1); | ||
1482 | case SCBRR_ALGO_2: | ||
1483 | return ((freq + 16 * bps) / (32 * bps) - 1); | ||
1484 | case SCBRR_ALGO_3: | ||
1485 | return (((freq * 2) + 16 * bps) / (16 * bps) - 1); | ||
1486 | case SCBRR_ALGO_4: | ||
1487 | return (((freq * 2) + 16 * bps) / (32 * bps) - 1); | ||
1488 | case SCBRR_ALGO_5: | ||
1489 | return (((freq * 1000 / 32) / bps) - 1); | ||
1490 | } | ||
1491 | |||
1492 | /* Warn, but use a safe default */ | ||
1493 | WARN_ON(1); | ||
1494 | return ((freq + 16 * bps) / (32 * bps) - 1); | ||
1495 | } | ||
1496 | |||
1445 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 1497 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
1446 | struct ktermios *old) | 1498 | struct ktermios *old) |
1447 | { | 1499 | { |
1448 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1449 | struct sci_port *s = to_sci_port(port); | 1500 | struct sci_port *s = to_sci_port(port); |
1450 | #endif | ||
1451 | unsigned int status, baud, smr_val, max_baud; | 1501 | unsigned int status, baud, smr_val, max_baud; |
1452 | int t = -1; | 1502 | int t = -1; |
1453 | u16 scfcr = 0; | 1503 | u16 scfcr = 0; |
@@ -1464,7 +1514,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1464 | 1514 | ||
1465 | baud = uart_get_baud_rate(port, termios, old, 0, max_baud); | 1515 | baud = uart_get_baud_rate(port, termios, old, 0, max_baud); |
1466 | if (likely(baud && port->uartclk)) | 1516 | if (likely(baud && port->uartclk)) |
1467 | t = SCBRR_VALUE(baud, port->uartclk); | 1517 | t = sci_scbrr_calc(s->scbrr_algo_id, baud, port->uartclk); |
1468 | 1518 | ||
1469 | do { | 1519 | do { |
1470 | status = sci_in(port, SCxSR); | 1520 | status = sci_in(port, SCxSR); |
@@ -1490,7 +1540,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1490 | sci_out(port, SCSMR, smr_val); | 1540 | sci_out(port, SCSMR, smr_val); |
1491 | 1541 | ||
1492 | dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, | 1542 | dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, |
1493 | SCSCR_INIT(port)); | 1543 | s->scscr); |
1494 | 1544 | ||
1495 | if (t > 0) { | 1545 | if (t > 0) { |
1496 | if (t >= 256) { | 1546 | if (t >= 256) { |
@@ -1506,7 +1556,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1506 | sci_init_pins(port, termios->c_cflag); | 1556 | sci_init_pins(port, termios->c_cflag); |
1507 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); | 1557 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); |
1508 | 1558 | ||
1509 | sci_out(port, SCSCR, SCSCR_INIT(port)); | 1559 | sci_out(port, SCSCR, s->scscr); |
1510 | 1560 | ||
1511 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1561 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
1512 | /* | 1562 | /* |
@@ -1679,9 +1729,11 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1679 | port->mapbase = p->mapbase; | 1729 | port->mapbase = p->mapbase; |
1680 | port->membase = p->membase; | 1730 | port->membase = p->membase; |
1681 | 1731 | ||
1682 | port->irq = p->irqs[SCIx_TXI_IRQ]; | 1732 | port->irq = p->irqs[SCIx_TXI_IRQ]; |
1683 | port->flags = p->flags; | 1733 | port->flags = p->flags; |
1684 | sci_port->type = port->type = p->type; | 1734 | sci_port->type = port->type = p->type; |
1735 | sci_port->scscr = p->scscr; | ||
1736 | sci_port->scbrr_algo_id = p->scbrr_algo_id; | ||
1685 | 1737 | ||
1686 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1738 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
1687 | sci_port->dma_dev = p->dma_dev; | 1739 | sci_port->dma_dev = p->dma_dev; |