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