Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+147 −1
Original line number Diff line number Diff line
@@ -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
};

/*