imxrt:Serial Use smart invalidate

This commit is contained in:
David Sidrane 2023-11-20 08:16:03 -08:00 committed by Xiang Xiao
parent 0ff18e31f5
commit 05e620d12b

View File

@ -770,6 +770,10 @@ struct imxrt_uart_s
DMACH_HANDLE rxdma; /* currently-open receive DMA stream */
bool rxenable; /* DMA-based reception en/disable */
uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
#ifdef CONFIG_ARMV7M_DCACHE
uint32_t rxdmaavail; /* Number of bytes available without need to
* to invalidate the data cache */
#endif
char *const rxfifo; /* Receive DMA buffer */
#endif
};
@ -2086,6 +2090,9 @@ static int imxrt_dma_setup(struct uart_dev_s *dev)
*/
priv->rxdmanext = 0;
#ifdef CONFIG_ARMV7M_DCACHE
priv->rxdmaavail = 0;
#endif
/* Enable receive Rx DMA for the UART */
@ -2907,7 +2914,6 @@ static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
static int imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status)
{
struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
static uint32_t last_nextrx = -1;
uint32_t nextrx = imxrt_dma_nextrx(priv);
int c = 0;
@ -2915,17 +2921,49 @@ static int imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status)
if (nextrx != priv->rxdmanext)
{
/* Now we must ensure the cache is updated if the DMA has
* updated again.
#ifdef CONFIG_ARMV7M_DCACHE
/* If the data cache is enabled, then we will also need to manage
* cache coherency. Are any bytes available in the currently coherent
* region of the data cache?
*/
if (last_nextrx != nextrx)
if (priv->rxdmaavail == 0)
{
up_invalidate_dcache((uintptr_t)priv->rxfifo,
(uintptr_t)priv->rxfifo + RXDMA_BUFFER_SIZE);
last_nextrx = nextrx;
uint32_t rxdmaavail;
uintptr_t addr;
/* No.. then we will have to invalidate additional space in the Rx
* DMA buffer.
*/
if (nextrx > priv->rxdmanext)
{
/* Number of available bytes */
rxdmaavail = nextrx - priv->rxdmanext;
}
else
{
/* Number of available bytes up to the end of RXDMA buffer */
rxdmaavail = RXDMA_BUFFER_SIZE - priv->rxdmanext;
}
/* Invalidate the DMA buffer range */
addr = (uintptr_t)&priv->rxfifo[priv->rxdmanext];
up_invalidate_dcache(addr, addr + rxdmaavail);
/* We don't need to invalidate the data cache for the next
* rxdmaavail number of next bytes.
*/
priv->rxdmaavail = rxdmaavail;
}
priv->rxdmaavail--;
#endif
/* Now read from the DMA buffer */
c = priv->rxfifo[priv->rxdmanext];
@ -2990,6 +3028,9 @@ static void imxrt_dma_reenable(struct imxrt_uart_s *priv)
*/
priv->rxdmanext = 0;
#ifdef CONFIG_ARMV7M_DCACHE
priv->rxdmaavail = 0;
#endif
/* Start the DMA channel, and arrange for callbacks at the half and
* full points in the FIFO. This ensures that we have half a FIFO