[PATCH v5 1/2] serial: fsl_lpuart: Add DMA quirk

Andrew Lunn andrew at lunn.ch
Mon Apr 4 14:53:11 PDT 2016


Using DMA with the vf610 and other Vybrid devices results in a corrupt
serial stream. Add a quirk to disable the use of DMA.

Refactor the existing code to add a 32 bit access quirk for the
fsl,ls1021a-lpuart.

Signed-off-by: Andrew Lunn <andrew at lunn.ch>
---
 drivers/tty/serial/fsl_lpuart.c | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 3d790033744e..8d2f67b93e1f 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -257,12 +257,17 @@ struct lpuart_port {
 	struct timer_list	lpuart_timer;
 };
 
+#define QUIRK_LPUART32		BIT(0)
+#define QUIRK_NO_DMA		BIT(1)
+
 static const struct of_device_id lpuart_dt_ids[] = {
 	{
 		.compatible = "fsl,vf610-lpuart",
+		.data = (void *)QUIRK_NO_DMA,
 	},
 	{
 		.compatible = "fsl,ls1021a-lpuart",
+		.data = (void *)QUIRK_LPUART32,
 	},
 	{ /* sentinel */ }
 };
@@ -1803,7 +1808,9 @@ static struct uart_driver lpuart_reg = {
 static int lpuart_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match;
 	struct lpuart_port *sport;
+	kernel_ulong_t quirks;
 	struct resource *res;
 	int ret;
 
@@ -1819,7 +1826,10 @@ static int lpuart_probe(struct platform_device *pdev)
 		return ret;
 	}
 	sport->port.line = ret;
-	sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
+
+	match = of_match_node(lpuart_dt_ids, np);
+	quirks = (kernel_ulong_t)match->data;
+	sport->lpuart32 = quirks & QUIRK_LPUART32;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
@@ -1867,15 +1877,21 @@ static int lpuart_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
-	if (!sport->dma_tx_chan)
-		dev_info(sport->port.dev, "DMA tx channel request failed, "
-				"operating without tx DMA\n");
-
-	sport->dma_rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
-	if (!sport->dma_rx_chan)
-		dev_info(sport->port.dev, "DMA rx channel request failed, "
-				"operating without rx DMA\n");
+	if (quirks & QUIRK_NO_DMA) {
+		dev_info(sport->port.dev, "Not using DMA\n");
+	} else {
+		sport->dma_tx_chan = dma_request_slave_channel(
+			sport->port.dev, "tx");
+		if (!sport->dma_tx_chan)
+			dev_info(sport->port.dev,
+				 "DMA tx channel request failed, operating without tx DMA\n");
+
+		sport->dma_rx_chan = dma_request_slave_channel(
+			sport->port.dev, "rx");
+		if (!sport->dma_rx_chan)
+			dev_info(sport->port.dev,
+				 "DMA rx channel request failed, operating without rx DMA\n");
+	}
 
 	return 0;
 }
-- 
2.7.0




More information about the linux-arm-kernel mailing list