Commit 3b216c9ed347924efb5e7a66b3257c40a5596d30
1 parent
8e21d04c07
Exists in
master
and in
39 other branches
kgdb: kgdboc console poll hooks for mpsc uart
Add in console polling hooks for the mpsc uart for use with kgdb and kgdboc. Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Showing 1 changed file with 147 additions and 1 deletions Side-by-side Diff
drivers/serial/mpsc.c
... | ... | @@ -921,6 +921,10 @@ |
921 | 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 @@ |
956 | 960 | while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) |
957 | 961 | & SDMA_DESC_CMDSTAT_O)) { |
958 | 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 | 969 | /* Following use of tty struct directly is deprecated */ |
961 | 970 | if (unlikely(tty_buffer_request_room(tty, bytes_in) |
962 | 971 | < bytes_in)) { |
... | ... | @@ -1017,6 +1026,12 @@ |
1017 | 1026 | if (uart_handle_sysrq_char(&pi->port, *bp)) { |
1018 | 1027 | bp++; |
1019 | 1028 | bytes_in--; |
1029 | +#ifdef CONFIG_CONSOLE_POLL | |
1030 | + if (unlikely(serial_polled)) { | |
1031 | + serial_polled = 0; | |
1032 | + return 0; | |
1033 | + } | |
1034 | +#endif | |
1020 | 1035 | goto next_frame; |
1021 | 1036 | } |
1022 | 1037 | |
1023 | 1038 | |
... | ... | @@ -1519,7 +1534,134 @@ |
1519 | 1534 | |
1520 | 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 | + */ | |
1522 | 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 | |
1664 | + | |
1523 | 1665 | static struct uart_ops mpsc_pops = { |
1524 | 1666 | .tx_empty = mpsc_tx_empty, |
1525 | 1667 | .set_mctrl = mpsc_set_mctrl, |
... | ... | @@ -1537,6 +1679,10 @@ |
1537 | 1679 | .request_port = mpsc_request_port, |
1538 | 1680 | .config_port = mpsc_config_port, |
1539 | 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 | /* |