From 04dd17822334871b23ea2862f7798fb0e0007777 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 11 May 2024 08:53:19 +0000
Subject: [PATCH] change otg to host mode

---
 kernel/drivers/tty/serial/8250/8250_dma.c |   86 ++++++++++++++++++++++++++----------------
 1 files changed, 53 insertions(+), 33 deletions(-)

diff --git a/kernel/drivers/tty/serial/8250/8250_dma.c b/kernel/drivers/tty/serial/8250/8250_dma.c
index 141a5b0..8cde714 100644
--- a/kernel/drivers/tty/serial/8250/8250_dma.c
+++ b/kernel/drivers/tty/serial/8250/8250_dma.c
@@ -11,10 +11,11 @@
 
 #include "8250.h"
 
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 #define MAX_TX_BYTES		64
 #define MAX_FIFO_SIZE		64
 #define UART_RFL_16550A		0x21
+#define DW_UART_DMASA		0x2a
 #endif
 
 static void __dma_tx_complete(void *param)
@@ -40,18 +41,13 @@
 		uart_write_wakeup(&p->port);
 
 	ret = serial8250_tx_dma(p);
-	if (ret) {
-		p->ier |= UART_IER_THRI;
-#ifdef CONFIG_ARCH_ROCKCHIP
-		p->ier |= UART_IER_PTIME;
-#endif
-		serial_port_out(&p->port, UART_IER, p->ier);
-	}
+	if (ret)
+		serial8250_set_THRI(p);
 
 	spin_unlock_irqrestore(&p->port.lock, flags);
 }
 
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 
 static void __dma_rx_complete(void *param)
 {
@@ -90,19 +86,38 @@
 	struct uart_8250_dma	*dma = p->dma;
 	struct tty_port		*tty_port = &p->port.state->port;
 	struct dma_tx_state	state;
+	enum dma_status		dma_status;
 	int			count;
 
-	dma->rx_running = 0;
-	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+	/*
+	 * New DMA Rx can be started during the completion handler before it
+	 * could acquire port's lock and it might still be ongoing. Don't to
+	 * anything in such case.
+	 */
+	dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+	if (dma_status == DMA_IN_PROGRESS)
+		return;
 
 	count = dma->rx_size - state.residue;
 
 	tty_insert_flip_string(tty_port, dma->rx_buf, count);
 	p->port.icount.rx += count;
+	dma->rx_running = 0;
 
 	tty_flip_buffer_push(tty_port);
 }
 
+static void dma_rx_complete(void *param)
+{
+	struct uart_8250_port *p = param;
+	struct uart_8250_dma *dma = p->dma;
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->port.lock, flags);
+	if (dma->rx_running)
+		__dma_rx_complete(p);
+	spin_unlock_irqrestore(&p->port.lock, flags);
+}
 #endif
 
 int serial8250_tx_dma(struct uart_8250_port *p)
@@ -110,10 +125,19 @@
 	struct uart_8250_dma		*dma = p->dma;
 	struct circ_buf			*xmit = &p->port.state->xmit;
 	struct dma_async_tx_descriptor	*desc;
+	struct uart_port		*up = &p->port;
 	int ret;
 
-	if (dma->tx_running)
+	if (dma->tx_running) {
+		if (up->x_char) {
+			dmaengine_pause(dma->txchan);
+			uart_xchar_out(up, UART_TX);
+			dmaengine_resume(dma->txchan);
+		}
 		return 0;
+	} else if (up->x_char) {
+		uart_xchar_out(up, UART_TX);
+	}
 
 	if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
 		/* We have been called from __dma_tx_complete() */
@@ -122,7 +146,7 @@
 	}
 
 	dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 	if (dma->tx_size < MAX_TX_BYTES) {
 		ret = -EBUSY;
 		goto err;
@@ -146,16 +170,14 @@
 	dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
 				   UART_XMIT_SIZE, DMA_TO_DEVICE);
 
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
+	/* Clear uart dma request before start dma */
+	serial_port_out(&p->port, DW_UART_DMASA, 0x1);
+#endif
 	dma_async_issue_pending(dma->txchan);
 	if (dma->tx_err) {
 		dma->tx_err = 0;
-		if (p->ier & UART_IER_THRI) {
-			p->ier &= ~UART_IER_THRI;
-#ifdef CONFIG_ARCH_ROCKCHIP
-			p->ier &= ~UART_IER_PTIME;
-#endif
-			serial_out(p, UART_IER, p->ier);
-		}
+		serial8250_clear_THRI(p);
 	}
 	return 0;
 err:
@@ -163,7 +185,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 
 int serial8250_rx_dma(struct uart_8250_port *p)
 {
@@ -236,7 +258,7 @@
 		return -EBUSY;
 
 	dma->rx_running = 1;
-	desc->callback = __dma_rx_complete;
+	desc->callback = dma_rx_complete;
 	desc->callback_param = p;
 
 	dma->rx_cookie = dmaengine_submit(desc);
@@ -275,7 +297,7 @@
 	dma->rxconf.direction		= DMA_DEV_TO_MEM;
 	dma->rxconf.src_addr_width	= DMA_SLAVE_BUSWIDTH_1_BYTE;
 	dma->rxconf.src_addr		= rx_dma_addr + UART_RX;
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 	if ((p->port.fifosize / 4) < 16)
 		dma->rxconf.src_maxburst = p->port.fifosize / 4;
 	else
@@ -285,7 +307,7 @@
 	dma->txconf.direction		= DMA_MEM_TO_DEV;
 	dma->txconf.dst_addr_width	= DMA_SLAVE_BUSWIDTH_1_BYTE;
 	dma->txconf.dst_addr		= tx_dma_addr + UART_TX;
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 	dma->txconf.dst_maxburst	= 16;
 #endif
 	dma_cap_zero(mask);
@@ -301,17 +323,17 @@
 	/* 8250 rx dma requires dmaengine driver to support pause/terminate */
 	ret = dma_get_slave_caps(dma->rxchan, &caps);
 	if (ret)
-		goto err_rx;
+		goto release_rx;
 	if (!caps.cmd_pause || !caps.cmd_terminate ||
 	    caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) {
 		ret = -EINVAL;
-		goto err_rx;
+		goto release_rx;
 	}
 
 	dmaengine_slave_config(dma->rxchan, &dma->rxconf);
 
 	/* RX buffer */
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 	if (!dma->rx_size)
 		dma->rx_size = PAGE_SIZE * 2;
 #else
@@ -321,10 +343,9 @@
 
 	dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size,
 					&dma->rx_addr, GFP_KERNEL);
-
 	if (!dma->rx_buf) {
 		ret = -ENOMEM;
-		goto err_rx;
+		goto release_rx;
 	}
 
 	/* Get a channel for TX */
@@ -352,13 +373,12 @@
 		dev_info_ratelimited(p->port.dev, "got rx dma channels only\n");
 	}
 
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 	/* start dma for rx*/
 	serial8250_start_rx_dma(p);
 #endif
 	return 0;
-
-err_rx:
+release_rx:
 	dma_release_channel(dma->rxchan);
 	return ret;
 }
@@ -377,7 +397,7 @@
 			  dma->rx_addr);
 	dma_release_channel(dma->rxchan);
 	dma->rxchan = NULL;
-#ifdef CONFIG_ARCH_ROCKCHIP
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
 	dma->rx_running = 0;
 #endif
 	/* Release TX resources */

--
Gitblit v1.6.2