summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabien Lahoudere <fabien.lahoudere@collabora.com>2021-04-30 19:50:37 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-06-04 15:11:16 +0200
commitdb0a196bd8ad1d6bb4b1a9e54f54c09f8dc2cc25 (patch)
treef5bcfce7bcaa5837de636f0e7ba7f45f9e707990
parent910cc9537302caddc9777cf3ae2f5582730380c9 (diff)
downloadlinux-db0a196bd8ad1d6bb4b1a9e54f54c09f8dc2cc25.tar.bz2
serial: imx: Add DMA buffer configuration via DT
In order to optimize serial communication (performance/throughput VS latency), we may need to tweak DMA period number and size. This adds DT properties to configure those values before initialising DMA. The defaults will stay the same as before. [update documentation and commit message, rebase to current master, switch back to DT instead of sysfs] Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Link: https://lore.kernel.org/r/20210430175038.103226-2-sebastian.reichel@collabora.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml12
-rw-r--r--drivers/tty/serial/imx.c25
2 files changed, 30 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml b/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
index 2b06c6ce4a75..9d949296a142 100644
--- a/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
@@ -71,6 +71,18 @@ properties:
received, and that the peripheral should invert its input using the
INVR registers.
+ fsl,dma-info:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 2
+ maxItems: 2
+ description: |
+ First cell contains the size of DMA buffer chunks, second cell contains
+ the amount of chunks used for the device. Multiplying both numbers is
+ the total size of memory used for receiving data.
+ When not being configured the system will use default settings, which
+ are sensible for most use cases. If you need low latency processing on
+ slow connections this needs to be configured appropriately.
+
uart-has-rtscts: true
rs485-rts-delay: true
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 4b838601cdce..8b121cd869e9 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -225,6 +225,8 @@ struct imx_port {
struct scatterlist rx_sgl, tx_sgl[2];
void *rx_buf;
struct circ_buf rx_ring;
+ unsigned int rx_buf_size;
+ unsigned int rx_period_length;
unsigned int rx_periods;
dma_cookie_t rx_cookie;
unsigned int tx_bytes;
@@ -1183,10 +1185,6 @@ static void imx_uart_dma_rx_callback(void *data)
}
}
-/* RX DMA buffer periods */
-#define RX_DMA_PERIODS 16
-#define RX_BUF_SIZE (RX_DMA_PERIODS * PAGE_SIZE / 4)
-
static int imx_uart_start_rx_dma(struct imx_port *sport)
{
struct scatterlist *sgl = &sport->rx_sgl;
@@ -1197,9 +1195,8 @@ static int imx_uart_start_rx_dma(struct imx_port *sport)
sport->rx_ring.head = 0;
sport->rx_ring.tail = 0;
- sport->rx_periods = RX_DMA_PERIODS;
- sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+ sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size);
ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
if (ret == 0) {
dev_err(dev, "DMA mapping error for RX.\n");
@@ -1316,7 +1313,8 @@ static int imx_uart_dma_init(struct imx_port *sport)
goto err;
}
- sport->rx_buf = kzalloc(RX_BUF_SIZE, GFP_KERNEL);
+ sport->rx_buf_size = sport->rx_period_length * sport->rx_periods;
+ sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL);
if (!sport->rx_buf) {
ret = -ENOMEM;
goto err;
@@ -2179,11 +2177,16 @@ static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t)
return HRTIMER_NORESTART;
}
+/* Default RX DMA buffer configuration */
+#define RX_DMA_PERIODS 16
+#define RX_DMA_PERIOD_LEN (PAGE_SIZE / 4)
+
static int imx_uart_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct imx_port *sport;
void __iomem *base;
+ u32 dma_buf_conf[2];
int ret = 0;
u32 ucr1;
struct resource *res;
@@ -2218,6 +2221,14 @@ static int imx_uart_probe(struct platform_device *pdev)
if (of_get_property(np, "fsl,inverted-rx", NULL))
sport->inverted_rx = 1;
+ if (!of_property_read_u32_array(np, "fsl,dma-info", dma_buf_conf, 2)) {
+ sport->rx_period_length = dma_buf_conf[0];
+ sport->rx_periods = dma_buf_conf[1];
+ } else {
+ sport->rx_period_length = RX_DMA_PERIOD_LEN;
+ sport->rx_periods = RX_DMA_PERIODS;
+ }
+
if (sport->port.line >= ARRAY_SIZE(imx_uart_ports)) {
dev_err(&pdev->dev, "serial%d out of range\n",
sport->port.line);