Commit 3b216c9e authored by Jason Wessel's avatar Jason Wessel

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: default avatarJason Wessel <jason.wessel@windriver.com>
parent 8e21d04c
......@@ -921,6 +921,10 @@ static int mpsc_make_ready(struct mpsc_port_info *pi)
return 0;
}
#ifdef CONFIG_CONSOLE_POLL
static int serial_polled;
#endif
/*
******************************************************************************
*
......@@ -956,7 +960,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
& SDMA_DESC_CMDSTAT_O)) {
bytes_in = be16_to_cpu(rxre->bytecnt);
#ifdef CONFIG_CONSOLE_POLL
if (unlikely(serial_polled)) {
serial_polled = 0;
return 0;
}
#endif
/* Following use of tty struct directly is deprecated */
if (unlikely(tty_buffer_request_room(tty, bytes_in)
< bytes_in)) {
......@@ -1017,6 +1026,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
if (uart_handle_sysrq_char(&pi->port, *bp)) {
bp++;
bytes_in--;
#ifdef CONFIG_CONSOLE_POLL
if (unlikely(serial_polled)) {
serial_polled = 0;
return 0;
}
#endif
goto next_frame;
}
......@@ -1519,6 +1534,133 @@ static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser)
return rc;
}
#ifdef CONFIG_CONSOLE_POLL
/* Serial polling routines for writing and reading from the uart while
* in an interrupt or debug context.
*/
static char poll_buf[2048];
static int poll_ptr;
static int poll_cnt;
static void mpsc_put_poll_char(struct uart_port *port,
unsigned char c);
static int mpsc_get_poll_char(struct uart_port *port)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
struct mpsc_rx_desc *rxre;
u32 cmdstat, bytes_in, i;
u8 *bp;
if (!serial_polled)
serial_polled = 1;
pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
if (poll_cnt) {
poll_cnt--;
return poll_buf[poll_ptr++];
}
poll_ptr = 0;
poll_cnt = 0;
while (poll_cnt == 0) {
rxre = (struct mpsc_rx_desc *)(pi->rxr +
(pi->rxr_posn*MPSC_RXRE_SIZE));
dma_cache_sync(pi->port.dev, (void *)rxre,
MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
invalidate_dcache_range((ulong)rxre,
(ulong)rxre + MPSC_RXRE_SIZE);
#endif
/*
* Loop through Rx descriptors handling ones that have
* been completed.
*/
while (poll_cnt == 0 &&
!((cmdstat = be32_to_cpu(rxre->cmdstat)) &
SDMA_DESC_CMDSTAT_O)){
bytes_in = be16_to_cpu(rxre->bytecnt);
bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
dma_cache_sync(pi->port.dev, (void *) bp,
MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
invalidate_dcache_range((ulong)bp,
(ulong)bp + MPSC_RXBE_SIZE);
#endif
if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR |
SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) &&
!(cmdstat & pi->port.ignore_status_mask)) {
poll_buf[poll_cnt] = *bp;
poll_cnt++;
} else {
for (i = 0; i < bytes_in; i++) {
poll_buf[poll_cnt] = *bp++;
poll_cnt++;
}
pi->port.icount.rx += bytes_in;
}
rxre->bytecnt = cpu_to_be16(0);
wmb();
rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O |
SDMA_DESC_CMDSTAT_EI |
SDMA_DESC_CMDSTAT_F |
SDMA_DESC_CMDSTAT_L);
wmb();
dma_cache_sync(pi->port.dev, (void *)rxre,
MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
flush_dcache_range((ulong)rxre,
(ulong)rxre + MPSC_RXRE_SIZE);
#endif
/* Advance to next descriptor */
pi->rxr_posn = (pi->rxr_posn + 1) &
(MPSC_RXR_ENTRIES - 1);
rxre = (struct mpsc_rx_desc *)(pi->rxr +
(pi->rxr_posn * MPSC_RXRE_SIZE));
dma_cache_sync(pi->port.dev, (void *)rxre,
MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
invalidate_dcache_range((ulong)rxre,
(ulong)rxre + MPSC_RXRE_SIZE);
#endif
}
/* Restart rx engine, if its stopped */
if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
mpsc_start_rx(pi);
}
if (poll_cnt) {
poll_cnt--;
return poll_buf[poll_ptr++];
}
return 0;
}
static void mpsc_put_poll_char(struct uart_port *port,
unsigned char c)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
u32 data;
data = readl(pi->mpsc_base + MPSC_MPCR);
writeb(c, pi->mpsc_base + MPSC_CHR_1);
mb();
data = readl(pi->mpsc_base + MPSC_CHR_2);
data |= MPSC_CHR_2_TTCS;
writel(data, pi->mpsc_base + MPSC_CHR_2);
mb();
while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS);
}
#endif
static struct uart_ops mpsc_pops = {
.tx_empty = mpsc_tx_empty,
......@@ -1537,6 +1679,10 @@ static struct uart_ops mpsc_pops = {
.request_port = mpsc_request_port,
.config_port = mpsc_config_port,
.verify_port = mpsc_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = mpsc_get_poll_char,
.poll_put_char = mpsc_put_poll_char,
#endif
};
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment