diff options
| -rw-r--r-- | drivers/serial/mpsc.c | 148 |
1 files changed, 147 insertions, 1 deletions
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index c9f53e71f252..61d3ade5286c 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c | |||
| @@ -921,6 +921,10 @@ static int mpsc_make_ready(struct mpsc_port_info *pi) | |||
| 921 | return 0; | 921 | return 0; |
| 922 | } | 922 | } |
| 923 | 923 | ||
| 924 | #ifdef CONFIG_CONSOLE_POLL | ||
| 925 | static int serial_polled; | ||
| 926 | #endif | ||
| 927 | |||
| 924 | /* | 928 | /* |
| 925 | ****************************************************************************** | 929 | ****************************************************************************** |
| 926 | * | 930 | * |
| @@ -956,7 +960,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi) | |||
| 956 | while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) | 960 | while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) |
| 957 | & SDMA_DESC_CMDSTAT_O)) { | 961 | & SDMA_DESC_CMDSTAT_O)) { |
| 958 | bytes_in = be16_to_cpu(rxre->bytecnt); | 962 | bytes_in = be16_to_cpu(rxre->bytecnt); |
| 959 | 963 | #ifdef CONFIG_CONSOLE_POLL | |
| 964 | if (unlikely(serial_polled)) { | ||
| 965 | serial_polled = 0; | ||
| 966 | return 0; | ||
| 967 | } | ||
| 968 | #endif | ||
| 960 | /* Following use of tty struct directly is deprecated */ | 969 | /* Following use of tty struct directly is deprecated */ |
| 961 | if (unlikely(tty_buffer_request_room(tty, bytes_in) | 970 | if (unlikely(tty_buffer_request_room(tty, bytes_in) |
| 962 | < bytes_in)) { | 971 | < bytes_in)) { |
| @@ -1017,6 +1026,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi) | |||
| 1017 | if (uart_handle_sysrq_char(&pi->port, *bp)) { | 1026 | if (uart_handle_sysrq_char(&pi->port, *bp)) { |
| 1018 | bp++; | 1027 | bp++; |
| 1019 | bytes_in--; | 1028 | bytes_in--; |
| 1029 | #ifdef CONFIG_CONSOLE_POLL | ||
| 1030 | if (unlikely(serial_polled)) { | ||
| 1031 | serial_polled = 0; | ||
| 1032 | return 0; | ||
| 1033 | } | ||
| 1034 | #endif | ||
| 1020 | goto next_frame; | 1035 | goto next_frame; |
| 1021 | } | 1036 | } |
| 1022 | 1037 | ||
| @@ -1519,6 +1534,133 @@ static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
| 1519 | 1534 | ||
| 1520 | return rc; | 1535 | return rc; |
| 1521 | } | 1536 | } |
| 1537 | #ifdef CONFIG_CONSOLE_POLL | ||
| 1538 | /* Serial polling routines for writing and reading from the uart while | ||
| 1539 | * in an interrupt or debug context. | ||
| 1540 | */ | ||
| 1541 | |||
| 1542 | static char poll_buf[2048]; | ||
| 1543 | static int poll_ptr; | ||
| 1544 | static int poll_cnt; | ||
| 1545 | static void mpsc_put_poll_char(struct uart_port *port, | ||
| 1546 | unsigned char c); | ||
| 1547 | |||
| 1548 | static int mpsc_get_poll_char(struct uart_port *port) | ||
| 1549 | { | ||
| 1550 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; | ||
| 1551 | struct mpsc_rx_desc *rxre; | ||
| 1552 | u32 cmdstat, bytes_in, i; | ||
| 1553 | u8 *bp; | ||
| 1554 | |||
| 1555 | if (!serial_polled) | ||
| 1556 | serial_polled = 1; | ||
| 1557 | |||
| 1558 | pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line); | ||
| 1559 | |||
| 1560 | if (poll_cnt) { | ||
| 1561 | poll_cnt--; | ||
| 1562 | return poll_buf[poll_ptr++]; | ||
| 1563 | } | ||
| 1564 | poll_ptr = 0; | ||
| 1565 | poll_cnt = 0; | ||
| 1566 | |||
| 1567 | while (poll_cnt == 0) { | ||
| 1568 | rxre = (struct mpsc_rx_desc *)(pi->rxr + | ||
| 1569 | (pi->rxr_posn*MPSC_RXRE_SIZE)); | ||
| 1570 | dma_cache_sync(pi->port.dev, (void *)rxre, | ||
| 1571 | MPSC_RXRE_SIZE, DMA_FROM_DEVICE); | ||
| 1572 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
| 1573 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
| 1574 | invalidate_dcache_range((ulong)rxre, | ||
| 1575 | (ulong)rxre + MPSC_RXRE_SIZE); | ||
| 1576 | #endif | ||
| 1577 | /* | ||
| 1578 | * Loop through Rx descriptors handling ones that have | ||
| 1579 | * been completed. | ||
| 1580 | */ | ||
| 1581 | while (poll_cnt == 0 && | ||
| 1582 | !((cmdstat = be32_to_cpu(rxre->cmdstat)) & | ||
| 1583 | SDMA_DESC_CMDSTAT_O)){ | ||
| 1584 | bytes_in = be16_to_cpu(rxre->bytecnt); | ||
| 1585 | bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); | ||
| 1586 | dma_cache_sync(pi->port.dev, (void *) bp, | ||
| 1587 | MPSC_RXBE_SIZE, DMA_FROM_DEVICE); | ||
| 1588 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
| 1589 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
| 1590 | invalidate_dcache_range((ulong)bp, | ||
| 1591 | (ulong)bp + MPSC_RXBE_SIZE); | ||
| 1592 | #endif | ||
| 1593 | if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR | | ||
| 1594 | SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) && | ||
| 1595 | !(cmdstat & pi->port.ignore_status_mask)) { | ||
| 1596 | poll_buf[poll_cnt] = *bp; | ||
| 1597 | poll_cnt++; | ||
| 1598 | } else { | ||
| 1599 | for (i = 0; i < bytes_in; i++) { | ||
| 1600 | poll_buf[poll_cnt] = *bp++; | ||
| 1601 | poll_cnt++; | ||
| 1602 | } | ||
| 1603 | pi->port.icount.rx += bytes_in; | ||
| 1604 | } | ||
| 1605 | rxre->bytecnt = cpu_to_be16(0); | ||
| 1606 | wmb(); | ||
| 1607 | rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | | ||
| 1608 | SDMA_DESC_CMDSTAT_EI | | ||
| 1609 | SDMA_DESC_CMDSTAT_F | | ||
| 1610 | SDMA_DESC_CMDSTAT_L); | ||
| 1611 | wmb(); | ||
| 1612 | dma_cache_sync(pi->port.dev, (void *)rxre, | ||
| 1613 | MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); | ||
| 1614 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
| 1615 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
| 1616 | flush_dcache_range((ulong)rxre, | ||
| 1617 | (ulong)rxre + MPSC_RXRE_SIZE); | ||
| 1618 | #endif | ||
| 1619 | |||
| 1620 | /* Advance to next descriptor */ | ||
| 1621 | pi->rxr_posn = (pi->rxr_posn + 1) & | ||
| 1622 | (MPSC_RXR_ENTRIES - 1); | ||
| 1623 | rxre = (struct mpsc_rx_desc *)(pi->rxr + | ||
| 1624 | (pi->rxr_posn * MPSC_RXRE_SIZE)); | ||
| 1625 | dma_cache_sync(pi->port.dev, (void *)rxre, | ||
| 1626 | MPSC_RXRE_SIZE, DMA_FROM_DEVICE); | ||
| 1627 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
| 1628 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
| 1629 | invalidate_dcache_range((ulong)rxre, | ||
| 1630 | (ulong)rxre + MPSC_RXRE_SIZE); | ||
| 1631 | #endif | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | /* Restart rx engine, if its stopped */ | ||
| 1635 | if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0) | ||
| 1636 | mpsc_start_rx(pi); | ||
| 1637 | } | ||
| 1638 | if (poll_cnt) { | ||
| 1639 | poll_cnt--; | ||
| 1640 | return poll_buf[poll_ptr++]; | ||
| 1641 | } | ||
| 1642 | |||
| 1643 | return 0; | ||
| 1644 | } | ||
| 1645 | |||
| 1646 | |||
| 1647 | static void mpsc_put_poll_char(struct uart_port *port, | ||
| 1648 | unsigned char c) | ||
| 1649 | { | ||
| 1650 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; | ||
| 1651 | u32 data; | ||
| 1652 | |||
| 1653 | data = readl(pi->mpsc_base + MPSC_MPCR); | ||
| 1654 | writeb(c, pi->mpsc_base + MPSC_CHR_1); | ||
| 1655 | mb(); | ||
| 1656 | data = readl(pi->mpsc_base + MPSC_CHR_2); | ||
| 1657 | data |= MPSC_CHR_2_TTCS; | ||
| 1658 | writel(data, pi->mpsc_base + MPSC_CHR_2); | ||
| 1659 | mb(); | ||
| 1660 | |||
| 1661 | while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS); | ||
| 1662 | } | ||
| 1663 | #endif | ||
| 1522 | 1664 | ||
| 1523 | static struct uart_ops mpsc_pops = { | 1665 | static struct uart_ops mpsc_pops = { |
| 1524 | .tx_empty = mpsc_tx_empty, | 1666 | .tx_empty = mpsc_tx_empty, |
| @@ -1537,6 +1679,10 @@ static struct uart_ops mpsc_pops = { | |||
| 1537 | .request_port = mpsc_request_port, | 1679 | .request_port = mpsc_request_port, |
| 1538 | .config_port = mpsc_config_port, | 1680 | .config_port = mpsc_config_port, |
| 1539 | .verify_port = mpsc_verify_port, | 1681 | .verify_port = mpsc_verify_port, |
| 1682 | #ifdef CONFIG_CONSOLE_POLL | ||
| 1683 | .poll_get_char = mpsc_get_poll_char, | ||
| 1684 | .poll_put_char = mpsc_put_poll_char, | ||
| 1685 | #endif | ||
| 1540 | }; | 1686 | }; |
| 1541 | 1687 | ||
| 1542 | /* | 1688 | /* |
